This commit is contained in:
Sterling Hughes 2001-09-06 00:18:13 +00:00
parent 4f10dd7985
commit a4c905ff16

View File

@ -98,96 +98,98 @@
*/
static void seedMT(php_uint32 seed TSRMLS_DC)
{
/*
We initialize state[0..(N-1)] via the generator
/*
We initialize state[0..(N-1)] via the generator
x_new = (69069 * x_old) mod 2^32
from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's
_The Art of Computer Programming_, Volume 2, 3rd ed.
Notes (SJC): I do not know what the initial state requirements
of the Mersenne Twister are, but it seems this seeding generator
could be better. It achieves the maximum period for its modulus
(2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if
x_initial can be even, you have sequences like 0, 0, 0, ...;
2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31,
2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below.
Even if x_initial is odd, if x_initial is 1 mod 4 then
x_new = (69069 * x_old) mod 2^32
the lowest bit of x is always 1,
the next-to-lowest bit of x is always 0,
the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... ,
the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... ,
the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... ,
...
and if x_initial is 3 mod 4 then
from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's
_The Art of Computer Programming_, Volume 2, 3rd ed.
the lowest bit of x is always 1,
the next-to-lowest bit of x is always 1,
the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... ,
the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... ,
the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... ,
...
The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is
16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It
also does well in the dimension 2..5 spectral tests, but it could be
better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth).
Notes (SJC): I do not know what the initial state requirements
of the Mersenne Twister are, but it seems this seeding generator
could be better. It achieves the maximum period for its modulus
(2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if
x_initial can be even, you have sequences like 0, 0, 0, ...;
2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31,
2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below.
Even if x_initial is odd, if x_initial is 1 mod 4 then
the lowest bit of x is always 1,
the next-to-lowest bit of x is always 0,
the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... ,
the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... ,
the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... ,
...
and if x_initial is 3 mod 4 then
the lowest bit of x is always 1,
the next-to-lowest bit of x is always 1,
the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... ,
the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... ,
the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... ,
...
The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is
16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It
also does well in the dimension 2..5 spectral tests, but it could be
better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth).
Note that the random number user does not see the values generated
here directly since reloadMT() will always munge them first, so maybe
none of all of this matters. In fact, the seed values made here could
even be extra-special desirable if the Mersenne Twister theory says
so-- that's why the only change I made is to restrict to odd seeds.
*/
Note that the random number user does not see the values generated
here directly since reloadMT() will always munge them first, so maybe
none of all of this matters. In fact, the seed values made here could
even be extra-special desirable if the Mersenne Twister theory says
so-- that's why the only change I made is to restrict to odd seeds.
*/
register php_uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = BG(state);
register int j;
register php_uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = BG(state);
register int j;
for(BG(left)=0, *s++=x, j=N; --j;
*s++ = (x*=69069U) & 0xFFFFFFFFU);
for (BG(left) = 0, *s++ = x, j = N; --j;
*s++ = (x *= 69069U) & 0xFFFFFFFFU);
}
/* }}} */
static php_uint32 reloadMT(TSRMLS_D)
{
register php_uint32 *p0=BG(state), *p2=BG(state)+2, *pM=BG(state)+M, s0, s1;
register int j;
register php_uint32 *p0 = BG(state), *p2 = BG(state) + 2, *pM = BG(state) + M, s0, s1;
register int j;
if(BG(left) < -1)
seedMT(4357U TSRMLS_CC);
if (BG(left) < -1)
seedMT(4357U TSRMLS_CC);
BG(left)=N-1, BG(next)=BG(state)+1;
BG(left) = N - 1, BG(next) = BG(state) + 1;
for(s0=BG(state)[0], s1=BG(state)[1], j=N-M+1; --j; s0=s1, s1=*p2++)
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
for (s0 = BG(state)[0], s1 = BG(state)[1], j = N - M + 1; --j; s0 = s1, s1 = *p2++)
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
for(pM=BG(state), j=M; --j; s0=s1, s1=*p2++)
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
for (pM = BG(state), j = M; --j; s0 = s1, s1 = *p2++)
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
s1=BG(state)[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9D2C5680U;
s1 ^= (s1 << 15) & 0xEFC60000U;
return(s1 ^ (s1 >> 18));
s1 = BG(state)[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9D2C5680U;
s1 ^= (s1 << 15) & 0xEFC60000U;
return s1 ^ (s1 >> 18);
}
static php_uint32 randomMT(TSRMLS_D)
{
php_uint32 y;
php_uint32 y;
if(--BG(left) < 0)
return(reloadMT(TSRMLS_C));
if (--BG(left) < 0)
return reloadMT(TSRMLS_C);
y = *BG(next)++;
y ^= (y >> 11);
y ^= (y << 7) & 0x9D2C5680U;
y ^= (y << 15) & 0xEFC60000U;
return(y ^ (y >> 18));
y = *BG(next)++;
y ^= (y >> 11);
y ^= (y << 7) & 0x9D2C5680U;
y ^= (y << 15) & 0xEFC60000U;
return y ^ (y >> 18);
}
/* {{{ proto void srand(int seed)