#include <ucw/threads.h>
#include <ucw/unaligned.h>
+#include <float.h>
#include <limits.h>
+#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
}
}
}
+
+double fastrand_double(struct fastrand *c)
+{
+ // Generate 52 random bits
+ FASTRAND_CHECK_SEED(c);
+ u64 r = fastrand_one(c);
+#if FASTRAND_ONE_BITS >= 52
+ r >>= FASTRAND_ONE_BITS - 52;
+#else
+ // Do we want to generate doubles with full 52 precision?
+#if 0
+ r = (r << (52 - FASTRAND_ONE_BITS)) | (fastrand_one(c) >> (2 * FASTRAND_ONE_BITS - 52));
+#else
+ r <<= 52 - FASTRAND_ONE_BITS;
+#endif
+#endif
+
+ // With standard IEC 60559 / IEEE 754 format, we can directly store @r as a double
+ // from range [1.0, 2.0) and subtract 1.0.
+ // But the alternative with multiplication is often faster anyway.
+#if 0 && defined(__STDC_IEC_559__)
+ union {
+ u64 u;
+ double d;
+ } tmp;
+ ASSERT(sizeof(double) == 8 && sizeof(tmp) == 8);
+ tmp.u = (0x3ffLLU << 52) | r;
+ return tmp.d - 1.0;
+#elif 1
+ static const double mul = 1.0 / (1LLU << 52);
+ return r * mul;
+#else
+ return ldexp(r, -52);
+#endif
+}
#include <ucw/time.h>
#include <errno.h>
+#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
TEST((y = fastrand_max(r, x)) < x);
x = fastrand_u64(r) ? : 1;
TEST((y = fastrand_max_u64(r, x)) < x);
+
+ double d;
+ d = fastrand_double(r);
+ TEST(d >= 0.0 - DBL_EPSILON && d < 1.0 + DBL_EPSILON);
}
fastrand_delete(r);
printf("OK\n");
BENCH_SLOW(4, fastrand_max_u64(r, (1LLU << 63) + 1));
BENCH_SLOW(2, fastrand_max(r, 1 + fastrand_max(r, 1000000)));
BENCH_SLOW(4, fastrand_max_u64(r, 1 + fastrand_max_u64(r, 1000000000000LL)));
+ BENCH_SLOW(4, fastrand_double(r));
byte buf[1000];
BENCH(fastrand_mem(r, buf, 1));
#define fastrand_max ucw_fastrand_max
#define fastrand_max_u64 ucw_fastrand_max_u64
#define fastrand_mem ucw_fastrand_mem
+#define fastrand_double ucw_fastrand_double
#endif
/* random-fast.c */
/** Generate @size random bytes. **/
void fastrand_mem(struct fastrand *c, void *ptr, size_t size);
+/** Uniformly generate a random number from range [0.0, 1.0) + possible inaccuracies from basic floating point operations. **/
+double fastrand_double(struct fastrand *c);
+
#endif