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