summaryrefslogtreecommitdiff
path: root/ext/standard/php_rand.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/php_rand.h')
-rw-r--r--ext/standard/php_rand.h47
1 files changed, 32 insertions, 15 deletions
diff --git a/ext/standard/php_rand.h b/ext/standard/php_rand.h
index 44a40a7c3b..506e4976a6 100644
--- a/ext/standard/php_rand.h
+++ b/ext/standard/php_rand.h
@@ -25,27 +25,46 @@
#ifndef PHP_RAND_H
#define PHP_RAND_H
-#include <stdlib.h>
-#include "basic_functions.h"
#include "php_lcg.h"
+#include "php_mt_rand.h"
/* System Rand functions */
#ifndef RAND_MAX
-#define RAND_MAX (1<<15)
+#define RAND_MAX PHP_MT_RAND_MAX
#endif
-/* In ZTS mode we rely on rand_r() so we must use RAND_MAX. */
-#if !defined(ZTS) && (defined(HAVE_LRAND48) || defined(HAVE_RANDOM))
-#define PHP_RAND_MAX 2147483647
-#else
-#define PHP_RAND_MAX RAND_MAX
-#endif
+#define PHP_RAND_MAX PHP_MT_RAND_MAX
-#define RAND_RANGE(__n, __min, __max, __tmax) \
- (__n) = (__min) + (zend_long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
+/*
+ * A bit of tricky math here. We want to avoid using a modulus because
+ * that simply tosses the high-order bits and might skew the distribution
+ * of random values over the range. Instead we map the range directly.
+ *
+ * We need to map the range from 0...M evenly to the range a...b
+ * Let n = the random number and n' = the mapped random number
+ *
+ * Then we have: n' = a + n(b-a)/M
+ *
+ * We have a problem here in that only n==M will get mapped to b which
+ # means the chances of getting b is much much less than getting any of
+ # the other values in the range. We can fix this by increasing our range
+ # artificially and using:
+ #
+ # n' = a + n(b-a+1)/M
+ *
+ # Now we only have a problem if n==M which would cause us to produce a
+ # number of b+1 which would be bad. So we bump M up by one to make sure
+ # this will never happen, and the final algorithm looks like this:
+ #
+ # n' = a + n(b-a+1)/(M+1)
+ *
+ * -RL
+ */
+#define RAND_RANGE_BADSCALING(__n, __min, __max, __tmax) \
+ (__n) = (__min) + (zend_long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
-/* MT Rand */
-#define PHP_MT_RAND_MAX ((zend_long) (0x7FFFFFFF)) /* (1<<31) - 1 */
+#define RAND_RANGE(__n, __min, __max, __tmax) \
+ (__n) = php_mt_rand_range((__min), (__max))
#ifdef PHP_WIN32
#define GENERATE_SEED() (((zend_long) (time(0) * GetCurrentProcessId())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))
@@ -55,7 +74,5 @@
PHPAPI void php_srand(zend_long seed);
PHPAPI zend_long php_rand(void);
-PHPAPI void php_mt_srand(php_uint32 seed);
-PHPAPI php_uint32 php_mt_rand(void);
#endif /* PHP_RAND_H */