#include "db_config.h"
#ifndef lint
static const char revid[] = "$Id: mt19937db.c,v 1.2 2004/03/30 01:21:23 jtownsen Exp $";
#endif
#include "db_int.h"
#include "dbinc/crypto.h"
#include "dbinc/hmac.h"
#define N 624
#define M 397
#define MATRIX_A 0x9908b0df
#define UPPER_MASK 0x80000000
#define LOWER_MASK 0x7fffffff
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y) (y >> 11)
#define TEMPERING_SHIFT_S(y) (y << 7)
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_L(y) (y >> 18)
static void __db_sgenrand __P((unsigned long, unsigned long *, int *));
#ifdef NOT_USED
static void __db_lsgenrand __P((unsigned long *, unsigned long *, int *));
#endif
static unsigned long __db_genrand __P((DB_ENV *));
int
__db_generate_iv(dbenv, iv)
DB_ENV *dbenv;
u_int32_t *iv;
{
int i, n, ret;
ret = 0;
n = DB_IV_BYTES / sizeof(u_int32_t);
MUTEX_THREAD_LOCK(dbenv, dbenv->mt_mutexp);
if (dbenv->mt == NULL) {
if ((ret = __os_calloc(dbenv, 1, N*sizeof(unsigned long),
&dbenv->mt)) != 0)
return (ret);
dbenv->mti = N + 1;
}
for (i = 0; i < n; i++)
{
do {
iv[i] = (u_int32_t)__db_genrand(dbenv);
} while (iv[i] == 0);
}
MUTEX_THREAD_UNLOCK(dbenv, dbenv->mt_mutexp);
return (0);
}
static void
__db_sgenrand(seed, mt, mtip)
unsigned long seed;
unsigned long mt[];
int *mtip;
{
int i;
DB_ASSERT(seed != 0);
for (i=0;i<N;i++) {
mt[i] = seed & 0xffff0000;
seed = 69069 * seed + 1;
mt[i] |= (seed & 0xffff0000) >> 16;
seed = 69069 * seed + 1;
}
*mtip = N;
}
#ifdef NOT_USED
static void
__db_lsgenrand(seed_array, mt, mtip)
unsigned long seed_array[];
unsigned long mt[];
int *mtip;
{
int i;
for (i=0;i<N;i++)
mt[i] = seed_array[i];
*mtip=N;
}
#endif
static unsigned long
__db_genrand(dbenv)
DB_ENV *dbenv;
{
unsigned long y;
static unsigned long mag01[2]={0x0, MATRIX_A};
u_int32_t secs, seed, usecs;
if (dbenv->mti >= N) {
int kk;
if (dbenv->mti == N+1) {
do {
if (__os_clock(dbenv, &secs, &usecs) != 0)
return (0);
__db_chksum((u_int8_t *)&secs, sizeof(secs), NULL,
(u_int8_t *)&seed);
} while (seed == 0);
__db_sgenrand((long)seed, dbenv->mt, &dbenv->mti);
}
for (kk=0;kk<N-M;kk++) {
y = (dbenv->mt[kk]&UPPER_MASK)|(dbenv->mt[kk+1]&LOWER_MASK);
dbenv->mt[kk] = dbenv->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
}
for (;kk<N-1;kk++) {
y = (dbenv->mt[kk]&UPPER_MASK)|(dbenv->mt[kk+1]&LOWER_MASK);
dbenv->mt[kk] = dbenv->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
}
y = (dbenv->mt[N-1]&UPPER_MASK)|(dbenv->mt[0]&LOWER_MASK);
dbenv->mt[N-1] = dbenv->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
dbenv->mti = 0;
}
y = dbenv->mt[dbenv->mti++];
y ^= TEMPERING_SHIFT_U(y);
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
y ^= TEMPERING_SHIFT_L(y);
return y;
}