summaryrefslogtreecommitdiff
path: root/ext/standard/rand.c
diff options
context:
space:
mode:
authorRasmus Lerdorf <rasmus@php.net>1999-07-24 02:30:37 +0000
committerRasmus Lerdorf <rasmus@php.net>1999-07-24 02:30:37 +0000
commit8de073782c03c361c507129733227f3c3315d214 (patch)
treeee221838c20aea89fea2d22674a54d9e1417871b /ext/standard/rand.c
parentcd8d7c7c8a73cc7b2c1302051833716b40092930 (diff)
downloadphp-git-8de073782c03c361c507129733227f3c3315d214.tar.gz
Bring rand.c up to date
Diffstat (limited to 'ext/standard/rand.c')
-rw-r--r--ext/standard/rand.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/ext/standard/rand.c b/ext/standard/rand.c
index 09d28b6d65..051eab8ce6 100644
--- a/ext/standard/rand.c
+++ b/ext/standard/rand.c
@@ -201,6 +201,8 @@ static inline uint32 randomMT(void)
#define PHP_RAND_MAX RAND_MAX
#endif
+/* {{{ proto void srand(int seed)
+ Seeds random number generator */
PHP_FUNCTION(srand)
{
pval *arg;
@@ -219,7 +221,10 @@ PHP_FUNCTION(srand)
#endif
#endif
}
+/* }}} */
+/* {{{ proto void mt_srand(int seed)
+ Seeds Mersenne Twister random number generator */
PHP_FUNCTION(mt_srand)
{
pval *arg;
@@ -229,7 +234,10 @@ PHP_FUNCTION(mt_srand)
convert_to_long(arg);
seedMT(arg->value.lval);
}
+/* }}} */
+/* {{{ proto int rand([int min, int max])
+ Returns a random number */
PHP_FUNCTION(rand)
{
pval *p_min=NULL, *p_max=NULL;
@@ -262,13 +270,40 @@ PHP_FUNCTION(rand)
return_value->value.lval = rand();
#endif
#endif
-
+ /*
+ * 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
+ # artifically 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
+ */
if (p_min && p_max) { /* implement range */
return_value->value.lval = p_min->value.lval +
- (int)((double)p_max->value.lval * return_value->value.lval/(PHP_RAND_MAX+(double)p_min->value.lval));
+ (int)((double)(p_max->value.lval - p_min->value.lval + 1) * return_value->value.lval/(PHP_RAND_MAX+1.0));
}
}
+/* }}} */
+/* {{{ proto int mt_rand([int min, int max])
+ Returns a random number from Mersenne Twister */
PHP_FUNCTION(mt_rand)
{
pval *p_min=NULL, *p_max=NULL;
@@ -304,16 +339,23 @@ PHP_FUNCTION(mt_rand)
if (p_min && p_max) { /* implement range */
return_value->value.lval = p_min->value.lval +
- (int)((double)p_max->value.lval * return_value->value.lval/(PHP_RAND_MAX+(double)p_min->value.lval));
+ (int)((double)(p_max->value.lval - p_min->value.lval + 1) * return_value->value.lval/(PHP_RAND_MAX+1.0));
}
}
+/* }}} */
+/* {{{ proto int getrandmax(void)
+ Returns the maximum value a random number can have */
PHP_FUNCTION(getrandmax)
{
return_value->type = IS_LONG;
return_value->value.lval = PHP_RAND_MAX;
}
+/* }}} */
+
+/* {{{ proto int mt_getrandmax(void)
+ Returns the maximum value a random number from Mersenne Twister can have */
PHP_FUNCTION(mt_getrandmax)
{
return_value->type = IS_LONG;
@@ -323,7 +365,7 @@ PHP_FUNCTION(mt_getrandmax)
*/
return_value->value.lval = 2147483647; /* 2^^31 */
}
-
+/* }}} */
/*
* Local variables:
* tab-width: 4