]> mj.ucw.cz Git - libucw.git/commitdiff
Random: fastrand_mem() is now deterministic.
authorPavel Charvat <pchar@ucw.cz>
Tue, 9 Jun 2020 16:51:46 +0000 (18:51 +0200)
committerPavel Charvat <pchar@ucw.cz>
Tue, 22 Mar 2022 18:06:59 +0000 (18:06 +0000)
ucw/random-fast.c
ucw/random.h

index 5c8bfaab5a0c87a50c51a78662b4937e95f841de..672ccd883f4a260aaca26d31593c8fc1ff4c0ef0 100644 (file)
@@ -12,6 +12,7 @@
 #include <ucw/lib.h>
 #include <ucw/random.h>
 #include <ucw/threads.h>
+#include <ucw/unaligned.h>
 
 #include <limits.h>
 #include <stdlib.h>
@@ -581,41 +582,24 @@ u64 fastrand_max_u64(struct fastrand *c, u64 bound)
 
 void fastrand_mem(struct fastrand *c, void *ptr, size_t size)
 {
+  // XXX: Could be optimized to aligned assignments instead of put_u32/64, but it
+  // would be quite complex to make it deterministic (for same seed and any @ptr)
+  // and large sizes are not used often anyway.
   FASTRAND_CHECK_SEED(c);
   byte *p = ptr;
-  if (size > 3)
+#if FASTRAND_ONE_BITS < 64
+  for (size_t n = size >> 2; n--; p += 4)
+    put_u32(p, fastrand_u32_helper(c));
+  if (size &= 3)
     {
-      if ((intptr_t)p & 3)
-       {
-         u32 x = fastrand_u32_helper(c);
-         while ((intptr_t)p & 3)
-           {
-             *p++ = x;
-             x >>= 8;
-             size--;
-           }
-       }
-#if FASTRAND_ONE_BITS == 64
-      for (size_t n = size >> 3; n--; )
-       {
-         u64 x = fastrand_one(c);
-         ((u32 *)p)[0] = x;
-         ((u32 *)p)[1] = x >> 32;
-         p += 8;
-       }
-      if (size & 4)
+      u32 x = fastrand_u32_helper(c);
 #else
-      for (size_t n = size >> 2; n--; )
-#endif
-       {
-         *(u32 *)p = fastrand_u32_helper(c);
-         p += 4;
-       }
-      size &= 3;
-    }
-  if (size)
+  for (size_t n = size >> 3; n--; p += 8)
+    put_u64(p, fastrand_one(c));
+  if (size &= 7)
     {
-      u32 x = fastrand_u32_helper(c);
+      u64 x = fastrand_one(c);
+#endif
       while (size--)
        {
          *p++ = x;
index 93c6b28fe6ba25fdc236262d59c8c78b138524c9..703b1b09a7660bc5002359122123a7ac9d048ca1 100644 (file)
@@ -76,7 +76,7 @@ u32 fastrand_u32(struct fastrand *c);
 /** Uniformly generate 64 random bits. **/
 u64 fastrand_u64(struct fastrand *c);
 
-/** Uniformly generate [0..64] random bits. **/
+/** Uniformly generate [064] random bits. **/
 u64 fastrand_bits_u64(struct fastrand *c, uint bits);
 
 /** Uniformly generate [0, 8*sizeof(uint)] random bits. **/