xref: /PHP-8.1/ext/standard/php_rand.h (revision 6f56c004)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
14    |          Zeev Suraski <zeev@php.net>                                 |
15    |          Pedro Melo <melo@ip.pt>                                     |
16    |          Sterling Hughes <sterling@php.net>                          |
17    |                                                                      |
18    | Based on code from: Shawn Cokus <Cokus@math.washington.edu>          |
19    +----------------------------------------------------------------------+
20  */
21 
22 #ifndef PHP_RAND_H
23 #define	PHP_RAND_H
24 
25 #include "php_lcg.h"
26 #include "php_mt_rand.h"
27 
28 /* System Rand functions */
29 #ifndef RAND_MAX
30 #define RAND_MAX PHP_MT_RAND_MAX
31 #endif
32 
33 #define PHP_RAND_MAX PHP_MT_RAND_MAX
34 
35 /*
36  * A bit of tricky math here.  We want to avoid using a modulus because
37  * that simply tosses the high-order bits and might skew the distribution
38  * of random values over the range.  Instead we map the range directly.
39  *
40  * We need to map the range from 0...M evenly to the range a...b
41  * Let n = the random number and n' = the mapped random number
42  *
43  * Then we have: n' = a + n(b-a)/M
44  *
45  * We have a problem here in that only n==M will get mapped to b which
46  # means the chances of getting b is much much less than getting any of
47  # the other values in the range.  We can fix this by increasing our range
48  # artificially and using:
49  #
50  #               n' = a + n(b-a+1)/M
51  *
52  # Now we only have a problem if n==M which would cause us to produce a
53  # number of b+1 which would be bad.  So we bump M up by one to make sure
54  # this will never happen, and the final algorithm looks like this:
55  #
56  #               n' = a + n(b-a+1)/(M+1)
57  *
58  * -RL
59  */
60 #define RAND_RANGE_BADSCALING(__n, __min, __max, __tmax) \
61 	(__n) = (__min) + (zend_long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
62 
63 #ifdef PHP_WIN32
64 #define GENERATE_SEED() (((zend_long) ((zend_ulong) time(NULL) * (zend_ulong) GetCurrentProcessId())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))
65 #else
66 #define GENERATE_SEED() (((zend_long) ((zend_ulong) time(NULL) * (zend_ulong) getpid())) ^ ((zend_long) (1000000.0 * php_combined_lcg())))
67 #endif
68 
69 PHPAPI void php_srand(zend_long seed);
70 PHPAPI zend_long php_rand(void);
71 
72 #endif	/* PHP_RAND_H */
73