root/ext/standard/lcg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_combined_lcg
  2. lcg_seed
  3. lcg_init_globals
  4. PHP_MINIT_FUNCTION
  5. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Author: Sascha Schumann <sascha@schumann.cx>                         |
  16    +----------------------------------------------------------------------+
  17 */
  18 
  19 /* $Id$ */
  20 
  21 #include "php.h"
  22 #include "php_lcg.h"
  23 
  24 #if HAVE_UNISTD_H
  25 #include <unistd.h>
  26 #endif
  27 
  28 #ifdef PHP_WIN32
  29 #include "win32/time.h"
  30 #else
  31 #include <sys/time.h>
  32 #endif
  33 
  34 #ifdef ZTS
  35 int lcg_globals_id;
  36 #else
  37 static php_lcg_globals lcg_globals;
  38 #endif
  39 
  40 #ifdef PHP_WIN32
  41 #include <process.h>
  42 #endif
  43 
  44 /*
  45  * combinedLCG() returns a pseudo random number in the range of (0, 1).
  46  * The function combines two CGs with periods of
  47  * 2^31 - 85 and 2^31 - 249. The period of this function
  48  * is equal to the product of both primes.
  49  */
  50 
  51 #define MODMULT(a, b, c, m, s) q = s/a;s=b*(s-a*q)-c*q;if(s<0)s+=m
  52 
  53 static void lcg_seed(void);
  54 
  55 PHPAPI double php_combined_lcg(void) /* {{{ */
  56 {
  57         php_int32 q;
  58         php_int32 z;
  59 
  60         if (!LCG(seeded)) {
  61                 lcg_seed();
  62         }
  63 
  64         MODMULT(53668, 40014, 12211, 2147483563L, LCG(s1));
  65         MODMULT(52774, 40692, 3791, 2147483399L, LCG(s2));
  66 
  67         z = LCG(s1) - LCG(s2);
  68         if (z < 1) {
  69                 z += 2147483562;
  70         }
  71 
  72         return z * 4.656613e-10;
  73 }
  74 /* }}} */
  75 
  76 static void lcg_seed(void) /* {{{ */
  77 {
  78         struct timeval tv;
  79 
  80         if (gettimeofday(&tv, NULL) == 0) {
  81                 LCG(s1) = tv.tv_sec ^ (tv.tv_usec<<11);
  82         } else {
  83                 LCG(s1) = 1;
  84         }
  85 #ifdef ZTS
  86         LCG(s2) = (zend_long) tsrm_thread_id();
  87 #else
  88         LCG(s2) = (zend_long) getpid();
  89 #endif
  90 
  91         /* Add entropy to s2 by calling gettimeofday() again */
  92         if (gettimeofday(&tv, NULL) == 0) {
  93                 LCG(s2) ^= (tv.tv_usec<<11);
  94         }
  95 
  96         LCG(seeded) = 1;
  97 }
  98 /* }}} */
  99 
 100 static void lcg_init_globals(php_lcg_globals *lcg_globals_p) /* {{{ */
 101 {
 102         LCG(seeded) = 0;
 103 }
 104 /* }}} */
 105 
 106 PHP_MINIT_FUNCTION(lcg) /* {{{ */
 107 {
 108 #ifdef ZTS
 109         ts_allocate_id(&lcg_globals_id, sizeof(php_lcg_globals), (ts_allocate_ctor) lcg_init_globals, NULL);
 110 #else
 111         lcg_init_globals(&lcg_globals);
 112 #endif
 113         return SUCCESS;
 114 }
 115 /* }}} */
 116 
 117 /* {{{ proto float lcg_value()
 118    Returns a value from the combined linear congruential generator */
 119 PHP_FUNCTION(lcg_value)
 120 {
 121         RETURN_DOUBLE(php_combined_lcg());
 122 }
 123 /* }}} */
 124 
 125 /*
 126  * Local variables:
 127  * tab-width: 4
 128  * c-basic-offset: 4
 129  * End:
 130  * vim600: sw=4 ts=4 fdm=marker
 131  * vim<600: sw=4 ts=4
 132  */

/* [<][>][^][v][top][bottom][index][help] */