Commit 20743ff61f4350be0907ed51cfbe70d893795f15

Thomas de Grivel 2023-12-18T10:48:05

wip u_random

diff --git a/libc3/u.c.in b/libc3/u.c.in
index c18bc68..aa34b3d 100644
--- a/libc3/u.c.in
+++ b/libc3/u.c.in
@@ -90,17 +90,41 @@ u_bits$ * u_bits$_random (u_bits$ *u)
   return u;
 }
 
+#if _bits$ > 32
+
 u_bits$ * u_bits$_random_uniform (u_bits$ *u, u_bits$ max)
 {
-  uw size = (uw) log2(max) / 8;
-  u_bits$ rest = (max - ((1 << size) - 1)) >> size;
-  u_bits$ result = 0;
-  u_bits$ tmp;
-  arc4random_buf(&result, size);
+  u16 bits;
+  u8 i;
+  u_bits$ rest;
+  u_bits$ result;
+  u8 words;
+  assert(u);
+  assert(max);
+  bits = log2l(max) - 1;
+  words = bits / 32;
+  result = 0;
+  i = 0;
+  while (i < words) {
+    result <<= 32;
+    result += arc4random();
+    i++;
+  }
+  rest = max >> (words * 32);
   if (rest) {
-    tmp = arc4random_uniform(rest);
-    result += tmp;
+    result <<= 32;
+    result += arc4random_uniform(rest);
   }
   *u = result;
   return u;
 }
+
+#else
+
+u_bits$ * u_bits$_random_uniform (u_bits$ *u, u_bits$ max)
+{
+  *u = arc4random_uniform(max);
+  return u;
+}
+
+#endif
diff --git a/libc3/u16.c b/libc3/u16.c
index b439da4..de2eb63 100644
--- a/libc3/u16.c
+++ b/libc3/u16.c
@@ -90,17 +90,41 @@ u16 * u16_random (u16 *u)
   return u;
 }
 
+#if 16 > 32
+
 u16 * u16_random_uniform (u16 *u, u16 max)
 {
-  uw size = (uw) log2(max) / 8;
-  u16 rest = (max - ((1 << size) - 1)) >> size;
-  u16 result = 0;
-  u16 tmp;
-  arc4random_buf(&result, size);
+  u16 bits;
+  u8 i;
+  u16 rest;
+  u16 result;
+  u8 words;
+  assert(u);
+  assert(max);
+  bits = log2l(max) - 1;
+  words = bits / 32;
+  result = 0;
+  i = 0;
+  while (i < words) {
+    result <<= 32;
+    result += arc4random();
+    i++;
+  }
+  rest = max >> (words * 32);
   if (rest) {
-    tmp = arc4random_uniform(rest);
-    result += tmp;
+    result <<= 32;
+    result += arc4random_uniform(rest);
   }
   *u = result;
   return u;
 }
+
+#else
+
+u16 * u16_random_uniform (u16 *u, u16 max)
+{
+  *u = arc4random_uniform(max);
+  return u;
+}
+
+#endif
diff --git a/libc3/u32.c b/libc3/u32.c
index 8e7b6dd..9e3f11e 100644
--- a/libc3/u32.c
+++ b/libc3/u32.c
@@ -90,17 +90,41 @@ u32 * u32_random (u32 *u)
   return u;
 }
 
+#if 32 > 32
+
 u32 * u32_random_uniform (u32 *u, u32 max)
 {
-  uw size = (uw) log2(max) / 8;
-  u32 rest = (max - ((1 << size) - 1)) >> size;
-  u32 result = 0;
-  u32 tmp;
-  arc4random_buf(&result, size);
+  u16 bits;
+  u8 i;
+  u32 rest;
+  u32 result;
+  u8 words;
+  assert(u);
+  assert(max);
+  bits = log2l(max) - 1;
+  words = bits / 32;
+  result = 0;
+  i = 0;
+  while (i < words) {
+    result <<= 32;
+    result += arc4random();
+    i++;
+  }
+  rest = max >> (words * 32);
   if (rest) {
-    tmp = arc4random_uniform(rest);
-    result += tmp;
+    result <<= 32;
+    result += arc4random_uniform(rest);
   }
   *u = result;
   return u;
 }
+
+#else
+
+u32 * u32_random_uniform (u32 *u, u32 max)
+{
+  *u = arc4random_uniform(max);
+  return u;
+}
+
+#endif
diff --git a/libc3/u64.c b/libc3/u64.c
index a8b6c6e..9fdb100 100644
--- a/libc3/u64.c
+++ b/libc3/u64.c
@@ -90,17 +90,41 @@ u64 * u64_random (u64 *u)
   return u;
 }
 
+#if 64 > 32
+
 u64 * u64_random_uniform (u64 *u, u64 max)
 {
-  uw size = (uw) log2(max) / 8;
-  u64 rest = (max - ((1 << size) - 1)) >> size;
-  u64 result = 0;
-  u64 tmp;
-  arc4random_buf(&result, size);
+  u16 bits;
+  u8 i;
+  u64 rest;
+  u64 result;
+  u8 words;
+  assert(u);
+  assert(max);
+  bits = log2l(max) - 1;
+  words = bits / 32;
+  result = 0;
+  i = 0;
+  while (i < words) {
+    result <<= 32;
+    result += arc4random();
+    i++;
+  }
+  rest = max >> (words * 32);
   if (rest) {
-    tmp = arc4random_uniform(rest);
-    result += tmp;
+    result <<= 32;
+    result += arc4random_uniform(rest);
   }
   *u = result;
   return u;
 }
+
+#else
+
+u64 * u64_random_uniform (u64 *u, u64 max)
+{
+  *u = arc4random_uniform(max);
+  return u;
+}
+
+#endif
diff --git a/libc3/u8.c b/libc3/u8.c
index b18aeef..b4652c9 100644
--- a/libc3/u8.c
+++ b/libc3/u8.c
@@ -90,17 +90,41 @@ u8 * u8_random (u8 *u)
   return u;
 }
 
+#if 8 > 32
+
 u8 * u8_random_uniform (u8 *u, u8 max)
 {
-  uw size = (uw) log2(max) / 8;
-  u8 rest = (max - ((1 << size) - 1)) >> size;
-  u8 result = 0;
-  u8 tmp;
-  arc4random_buf(&result, size);
+  u16 bits;
+  u8 i;
+  u8 rest;
+  u8 result;
+  u8 words;
+  assert(u);
+  assert(max);
+  bits = log2l(max) - 1;
+  words = bits / 32;
+  result = 0;
+  i = 0;
+  while (i < words) {
+    result <<= 32;
+    result += arc4random();
+    i++;
+  }
+  rest = max >> (words * 32);
   if (rest) {
-    tmp = arc4random_uniform(rest);
-    result += tmp;
+    result <<= 32;
+    result += arc4random_uniform(rest);
   }
   *u = result;
   return u;
 }
+
+#else
+
+u8 * u8_random_uniform (u8 *u, u8 max)
+{
+  *u = arc4random_uniform(max);
+  return u;
+}
+
+#endif
diff --git a/libc3/uw.c b/libc3/uw.c
index 7a0e4a2..f1d7795 100644
--- a/libc3/uw.c
+++ b/libc3/uw.c
@@ -90,17 +90,41 @@ uw * uw_random (uw *u)
   return u;
 }
 
+#if w > 32
+
 uw * uw_random_uniform (uw *u, uw max)
 {
-  uw size = (uw) log2(max) / 8;
-  uw rest = (max - ((1 << size) - 1)) >> size;
-  uw result = 0;
-  uw tmp;
-  arc4random_buf(&result, size);
+  u16 bits;
+  u8 i;
+  uw rest;
+  uw result;
+  u8 words;
+  assert(u);
+  assert(max);
+  bits = log2l(max) - 1;
+  words = bits / 32;
+  result = 0;
+  i = 0;
+  while (i < words) {
+    result <<= 32;
+    result += arc4random();
+    i++;
+  }
+  rest = max >> (words * 32);
   if (rest) {
-    tmp = arc4random_uniform(rest);
-    result += tmp;
+    result <<= 32;
+    result += arc4random_uniform(rest);
   }
   *u = result;
   return u;
 }
+
+#else
+
+uw * uw_random_uniform (uw *u, uw max)
+{
+  *u = arc4random_uniform(max);
+  return u;
+}
+
+#endif