Commit c8091045 authored by Rusty Russell's avatar Rusty Russell

Tim's ISAAC module.

parent c1bdf46a
/**
* isaac - A fast, high-quality pseudo-random number generator.
*
* ISAAC (Indirect, Shift, Accumulate, Add, and Count) is the most advanced of
* a series of pseudo-random number generators designed by Robert J. Jenkins
* Jr. in 1996: http://www.burtleburtle.net/bob/rand/isaac.html
* To quote:
* No efficient method is known for deducing their internal states.
* ISAAC requires an amortized 18.75 instructions to produce a 32-bit value.
* There are no cycles in ISAAC shorter than 2**40 values.
* The expected cycle length is 2**8295 values.
* ...
* ISAAC-64 generates a different sequence than ISAAC, but it uses the same
* principles.
* It uses 64-bit arithmetic.
* It generates a 64-bit result every 19 instructions.
* All cycles are at least 2**72 values, and the average cycle length is
* 2**16583.
* An additional, important comment from Bob Jenkins in 2006:
* Seeding a random number generator is essentially the same problem as
* encrypting the seed with a block cipher.
* ISAAC should be initialized with the encryption of the seed by some
* secure cipher.
* I've provided a seeding routine in my implementations, which nobody has
* broken so far, but I have less faith in that initialization routine than
* I have in ISAAC.
*
* A number of attacks on ISAAC have been published.
* [Pudo01] can recover the entire internal state and has expected running time
* less than the square root of the number of states, or 2**4121 (4.67E+1240).
* [Auma06] reveals a large set of weak states, consisting of those for which
* the first value is repeated one or more times elsewhere in the state
* vector.
* These induce a bias in the output relative to the repeated value.
* The seed values used as input below are scrambled before being used, so any
* duplicates in them do not imply duplicates in the resulting internal state,
* however the chances of some duplicate existing elsewhere in a random state
* are just over 255/2**32, or merely 1 in 16 million.
* Such states are, of course, much rarer in ISAAC-64.
* It is not clear if an attacker can tell from just the output if ISAAC is in
* a weak state, or deduce the full internal state in any case except that
* where all or almost all of the entries in the state vector are identical.
* @MISC{Pudo01,
* author="Marina Pudovkina",
* title="A Known Plaintext Attack on the {ISAAC} Keystream Generator",
* howpublished="Cryptology ePrint Archive, Report 2001/049",
* year=2001,
* note="\url{http://eprint.iacr.org/2001/049}",
* }
* @MISC{Auma06,
* author="Jean-Philippe Aumasson",
* title="On the Pseudo-Random Generator {ISAAC}",
* howpublished="Cryptology ePrint Archive, Report 2006/438",
* year=2006,
* note="\url{http://eprint.iacr.org/2006/438}",
* }
*
* Even if one does not trust the security of this PRNG (and, without a good
* source of entropy to seed it, one should not), ISAAC is an excellent source
* of high-quality random numbers for Monte Carlo simulations, etc.
* It is the fastest 32-bit generator among all of those that pass the
* statistical tests in the recent survey
* http://www.iro.umontreal.ca/~simardr/testu01/tu01.html, with the exception
* of Marsa-LFIB4, and it is quite competitive on 64-bit archtectures.
* Unlike Marsa-LFIB4 (and all other LFib generators), there are no linear
* dependencies between successive values, and unlike many generators found in
* libc implementations, there are no small periods in the least significant
* bits, or seeds which lead to very small periods in general.
*
* Example:
* #include <stdio.h>
* #include <time.h>
* #include <ccan/isaac/isaac.h>
*
* int main(void){
* static const char *CHEESE[3]={"Cheddar","Provolone","Camembert"};
* isaac_ctx isaac;
* unsigned char seed[8];
* time_t now;
* int i;
* //N.B.: time() is not a good source of entropy.
* //Do not use it for cryptogrpahic purposes.
* time(&now);
* //Print it out so we can reproduce problems if needed.
* printf("Seed: 0x%016llX\n",(long long)now);
* //And convert the time to a byte array so that we can reproduce the same
* // seed on platforms with different endianesses.
* for(i=0;i<8;i++){
* seed[i]=(unsigned char)(now&0xFF);
* now>>=8;
* }
* isaac_init(&isaac,seed,8);
* printf("0x%08lX\n",(long)isaac_next_uint32(&isaac));
* printf("%s\n",CHEESE[isaac_next_uint(&isaac,3)]);
* printf("%0.8G\n",isaac_next_float(&isaac));
* printf("%0.8G\n",isaac_next_signed_float(&isaac));
* printf("%0.18G\n",isaac_next_double(&isaac));
* printf("%0.18G\n",isaac_next_signed_double(&isaac));
* return 0;
* }
*
* License: Public Domain
*/
#include <string.h>
#include "config.h"
int main(int _argc,const char *_argv[]){
/*Expect exactly one argument.*/
if(_argc!=2)return 1;
if(strcmp(_argv[1],"depends")==0){
/*PRINTF-CCAN-PACKAGES-YOU-NEED-ONE-PER-LINE-IF-ANY*/
printf("ccan/ilog\n");
return 0;
}
return 1;
}
/*Written by Timothy B. Terriberry (tterribe@xiph.org) 1999-2009 public domain.
Based on the public domain implementation by Robert J. Jenkins Jr.*/
#include <float.h>
#include <math.h>
#include <string.h>
#include <ccan/ilog/ilog.h>
#include "isaac.h"
#if defined(__GNUC_PREREQ)
# if __GNUC_PREREQ(4,2)
# pragma GCC diagnostic ignored "-Wparentheses"
# endif
#endif
#define ISAAC_MASK (0xFFFFFFFFU)
static void isaac_update(isaac_ctx *_ctx){
uint32_t *m;
uint32_t *r;
uint32_t a;
uint32_t b;
uint32_t x;
uint32_t y;
int i;
m=_ctx->m;
r=_ctx->r;
a=_ctx->a;
b=_ctx->b+(++_ctx->c)&ISAAC_MASK;
for(i=0;i<ISAAC_SZ/2;i++){
x=m[i];
a=(a^a<<13)+m[i+ISAAC_SZ/2]&ISAAC_MASK;
m[i]=y=m[(x&ISAAC_SZ-1<<2)>>2]+a+b&ISAAC_MASK;
r[i]=b=m[y>>ISAAC_SZ_LOG+2&ISAAC_SZ-1]+x&ISAAC_MASK;
x=m[++i];
a=(a^a>>6)+m[i+ISAAC_SZ/2]&ISAAC_MASK;
m[i]=y=m[(x&ISAAC_SZ-1<<2)>>2]+a+b&ISAAC_MASK;
r[i]=b=m[y>>ISAAC_SZ_LOG+2&ISAAC_SZ-1]+x&ISAAC_MASK;
x=m[++i];
a=(a^a<<2)+m[i+ISAAC_SZ/2]&ISAAC_MASK;
m[i]=y=m[(x&ISAAC_SZ-1<<2)>>2]+a+b&ISAAC_MASK;
r[i]=b=m[y>>ISAAC_SZ_LOG+2&ISAAC_SZ-1]+x&ISAAC_MASK;
x=m[++i];
a=(a^a>>16)+m[i+ISAAC_SZ/2]&ISAAC_MASK;
m[i]=y=m[(x&ISAAC_SZ-1<<2)>>2]+a+b&ISAAC_MASK;
r[i]=b=m[y>>ISAAC_SZ_LOG+2&ISAAC_SZ-1]+x&ISAAC_MASK;
}
for(i=ISAAC_SZ/2;i<ISAAC_SZ;i++){
x=m[i];
a=(a^a<<13)+m[i-ISAAC_SZ/2]&ISAAC_MASK;
m[i]=y=m[(x&ISAAC_SZ-1<<2)>>2]+a+b&ISAAC_MASK;
r[i]=b=m[y>>ISAAC_SZ_LOG+2&ISAAC_SZ-1]+x&ISAAC_MASK;
x=m[++i];
a=(a^a>>6)+m[i-ISAAC_SZ/2]&ISAAC_MASK;
m[i]=y=m[(x&ISAAC_SZ-1<<2)>>2]+a+b&ISAAC_MASK;
r[i]=b=m[y>>ISAAC_SZ_LOG+2&ISAAC_SZ-1]+x&ISAAC_MASK;
x=m[++i];
a=(a^a<<2)+m[i-ISAAC_SZ/2]&ISAAC_MASK;
m[i]=y=m[(x&ISAAC_SZ-1<<2)>>2]+a+b&ISAAC_MASK;
r[i]=b=m[y>>ISAAC_SZ_LOG+2&ISAAC_SZ-1]+x&ISAAC_MASK;
x=m[++i];
a=(a^a>>16)+m[i-ISAAC_SZ/2]&ISAAC_MASK;
m[i]=y=m[(x&ISAAC_SZ-1<<2)>>2]+a+b&ISAAC_MASK;
r[i]=b=m[y>>ISAAC_SZ_LOG+2&ISAAC_SZ-1]+x&ISAAC_MASK;
}
_ctx->b=b;
_ctx->a=a;
_ctx->n=ISAAC_SZ;
}
static void isaac_mix(uint32_t _x[8]){
static const unsigned char SHIFT[8]={11,2,8,16,10,4,8,9};
int i;
for(i=0;i<8;i++){
_x[i]^=_x[i+1&7]<<SHIFT[i];
_x[i+3&7]+=_x[i];
_x[i+1&7]+=_x[i+2&7];
i++;
_x[i]^=_x[i+1&7]>>SHIFT[i];
_x[i+3&7]+=_x[i];
_x[i+1&7]+=_x[i+2&7];
}
}
void isaac_init(isaac_ctx *_ctx,const unsigned char *_seed,int _nseed){
_ctx->a=_ctx->b=_ctx->c=0;
memset(_ctx->r,0,sizeof(_ctx->r));
isaac_reseed(_ctx,_seed,_nseed);
}
void isaac_reseed(isaac_ctx *_ctx,const unsigned char *_seed,int _nseed){
uint32_t *m;
uint32_t *r;
uint32_t x[8];
int i;
int j;
m=_ctx->m;
r=_ctx->r;
if(_nseed>ISAAC_SEED_SZ_MAX)_nseed=ISAAC_SEED_SZ_MAX;
for(i=0;i<_nseed>>2;i++){
r[i]^=(uint32_t)_seed[i<<2|3]<<24|(uint32_t)_seed[i<<2|2]<<16|
(uint32_t)_seed[i<<2|1]<<8|_seed[i<<2];
}
_nseed-=i<<2;
if(_nseed>0){
uint32_t ri;
ri=_seed[i<<2];
for(j=1;j<_nseed;j++)ri|=(uint32_t)_seed[i<<2|j]<<(j<<3);
r[i++]^=ri;
}
x[0]=x[1]=x[2]=x[3]=x[4]=x[5]=x[6]=x[7]=0x9E3779B9U;
for(i=0;i<4;i++)isaac_mix(x);
for(i=0;i<ISAAC_SZ;i+=8){
for(j=0;j<8;j++)x[j]+=r[i+j];
isaac_mix(x);
memcpy(m+i,x,sizeof(x));
}
for(i=0;i<ISAAC_SZ;i+=8){
for(j=0;j<8;j++)x[j]+=m[i+j];
isaac_mix(x);
memcpy(m+i,x,sizeof(x));
}
isaac_update(_ctx);
}
uint32_t isaac_next_uint32(isaac_ctx *_ctx){
if(!_ctx->n)isaac_update(_ctx);
return _ctx->r[--_ctx->n];
}
uint32_t isaac_next_uint(isaac_ctx *_ctx,uint32_t _n){
uint32_t r;
uint32_t v;
uint32_t d;
do{
r=isaac_next_uint32(_ctx);
v=r%_n;
d=r-v;
}
while((d+_n-1&ISAAC_MASK)<d);
return v;
}
/*Returns a uniform random float.
The expected value is within FLT_MIN (e.g., 1E-37) of 0.5.
_bits: An initial set of random bits.
_base: This should be -(the number of bits in _bits), up to -32.
Return: A float uniformly distributed between 0 (inclusive) and 1
(exclusive).
The average value was measured over 2**32 samples to be
0.50000037448772916.*/
static float isaac_float_bits(isaac_ctx *_ctx,uint32_t _bits,int _base){
float ret;
int nbits_needed;
while(!_bits){
if(_base+FLT_MANT_DIG<FLT_MIN_EXP)return 0;
_base-=32;
_bits=isaac_next_uint32(_ctx);
}
/*Note: This could also be determined with frexp(), for a slightly more
portable solution, but that takes twice as long, and one has to worry
about rounding effects, which can over-estimate the exponent when given
FLT_MANT_DIG+1 consecutive one bits.
Even the fallback C implementation of ILOGNZ_32() yields an implementation
25% faster than the frexp() method.*/
nbits_needed=FLT_MANT_DIG-ILOGNZ_32(_bits);
#if FLT_MANT_DIG>32
ret=ldexpf((float)_bits,_base);
# if FLT_MANT_DIG>65
while(32-nbits_needed<0){
# else
if(32-nbits_needed<0){
# endif
_base-=32;
nbits_needed-=32;
ret+=ldexpf((float)isaac_next_uint32(_ctx),_base);
}
_bits=isaac_next_uint32(_ctx)>>32-nbits_needed;
ret+=ldexpf((float)_bits,_base-nbits_needed);
#else
if(nbits_needed>0){
_bits=_bits<<nbits_needed|isaac_next_uint32(_ctx)>>32-nbits_needed;
}
# if FLT_MANT_DIG<32
else _bits>>=-nbits_needed;
# endif
ret=ldexpf((float)_bits,_base-nbits_needed);
#endif
return ret;
}
float isaac_next_float(isaac_ctx *_ctx){
return isaac_float_bits(_ctx,0,0);
}
float isaac_next_signed_float(isaac_ctx *_ctx){
uint32_t bits;
bits=isaac_next_uint32(_ctx);
return (1|-((int)bits&1))*isaac_float_bits(_ctx,bits>>1,-31);
}
/*Returns a uniform random double.
_bits: An initial set of random bits.
_base: This should be -(the number of bits in _bits), up to -32.
Return: A double uniformly distributed between 0 (inclusive) and 1
(exclusive).
The average value was measured over 2**32 samples to be
0.500006289408060911*/
static double isaac_double_bits(isaac_ctx *_ctx,uint32_t _bits,int _base){
double ret;
int nbits_needed;
while(!_bits){
if(_base+DBL_MANT_DIG<DBL_MIN_EXP)return 0;
_base-=32;
_bits=isaac_next_uint32(_ctx);
}
nbits_needed=DBL_MANT_DIG-ILOGNZ_32(_bits);
#if DBL_MANT_DIG>32
ret=ldexp((double)_bits,_base);
# if DBL_MANT_DIG>65
while(32-nbits_needed<0){
# else
if(32-nbits_needed<0){
# endif
_base-=32;
nbits_needed-=32;
ret+=ldexp((double)isaac_next_uint32(_ctx),_base);
}
_bits=isaac_next_uint32(_ctx)>>32-nbits_needed;
ret+=ldexp((double)_bits,_base-nbits_needed);
#else
if(nbits_needed>0){
_bits=_bits<<nbits_needed|isaac_next_uint32(_ctx)>>32-nbits_needed;
}
# if DBL_MANT_DIG<32
else _bits>>=-nbits_needed;
# endif
ret=ldexp((double)_bits,exp-DBL_MANT_DIG);
#endif
return ret;
}
double isaac_next_double(isaac_ctx *_ctx){
return isaac_double_bits(_ctx,0,0);
}
double isaac_next_signed_double(isaac_ctx *_ctx){
uint32_t bits;
bits=isaac_next_uint32(_ctx);
return (1|-((int)bits&1))*isaac_double_bits(_ctx,bits>>1,-31);
}
#if !defined(_isaac_H)
# define _isaac_H (1)
# include <stdint.h>
typedef struct isaac_ctx isaac_ctx;
/*This value may be lowered to reduce memory usage on embedded platforms, at
the cost of reducing security and increasing bias.
Quoting Bob Jenkins: "The current best guess is that bias is detectable after
2**37 values for [ISAAC_SZ_LOG]=3, 2**45 for 4, 2**53 for 5, 2**61 for 6,
2**69 for 7, and 2**77 values for [ISAAC_SZ_LOG]=8."*/
#define ISAAC_SZ_LOG (8)
#define ISAAC_SZ (1<<ISAAC_SZ_LOG)
#define ISAAC_SEED_SZ_MAX (ISAAC_SZ<<2)
/*ISAAC is the most advanced of a series of pseudo-random number generators
designed by Robert J. Jenkins Jr. in 1996.
http://www.burtleburtle.net/bob/rand/isaac.html
To quote:
No efficient method is known for deducing their internal states.
ISAAC requires an amortized 18.75 instructions to produce a 32-bit value.
There are no cycles in ISAAC shorter than 2**40 values.
The expected cycle length is 2**8295 values.*/
struct isaac_ctx{
unsigned n;
uint32_t r[ISAAC_SZ];
uint32_t m[ISAAC_SZ];
uint32_t a;
uint32_t b;
uint32_t c;
};
/**
* isaac_init - Initialize an instance of the ISAAC random number generator.
* @_ctx: The instance to initialize.
* @_seed: The specified seed bytes.
* This may be NULL if _nseed is less than or equal to zero.
* @_nseed: The number of bytes to use for the seed.
* If this is greater than ISAAC_SEED_SZ_MAX, the extra bytes are
* ignored.
*/
void isaac_init(isaac_ctx *_ctx,const unsigned char *_seed,int _nseed);
/**
* isaac_reseed - Mix a new batch of entropy into the current state.
* To reset ISAAC to a known state, call isaac_init() again instead.
* @_ctx: The instance to reseed.
* @_seed: The specified seed bytes.
* This may be NULL if _nseed is zero.
* @_nseed: The number of bytes to use for the seed.
* If this is greater than ISAAC_SEED_SZ_MAX, the extra bytes are
* ignored.
*/
void isaac_reseed(isaac_ctx *_ctx,const unsigned char *_seed,int _nseed);
/**
* isaac_next_uint32 - Return the next random 32-bit value.
* @_ctx: The ISAAC instance to generate the value with.
*/
uint32_t isaac_next_uint32(isaac_ctx *_ctx);
/**
* isaac_next_uint - Uniform random integer less than the given value.
* @_ctx: The ISAAC instance to generate the value with.
* @_n: The upper bound on the range of numbers returned (not inclusive).
* This must be greater than zero and less than 2**32.
* To return integers in the full range 0...2**32-1, use
* isaac_next_uint32() instead.
* Return: An integer uniformly distributed between 0 and _n-1 (inclusive).
*/
uint32_t isaac_next_uint(isaac_ctx *_ctx,uint32_t _n);
/**
* isaac_next_float - Uniform random float in the range [0,1).
* @_ctx: The ISAAC instance to generate the value with.
* Returns a high-quality float uniformly distributed between 0 (inclusive)
* and 1 (exclusive).
* All of the float's mantissa bits are random, e.g., the least significant bit
* may still be non-zero even if the value is less than 0.5, and any
* representable float in the range [0,1) has a chance to be returned, though
* values very close to zero become increasingly unlikely.
* To generate cheaper float values that do not have these properties, use
* ldexpf((float)isaac_next_uint32(_ctx),-32);
*/
float isaac_next_float(isaac_ctx *_ctx);
/**
* isaac_next_signed_float - Uniform random float in the range (-1,1).
* @_ctx: The ISAAC instance to generate the value with.
* Returns a high-quality float uniformly distributed between -1 and 1
* (exclusive).
* All of the float's mantissa bits are random, e.g., the least significant bit
* may still be non-zero even if the magnitude is less than 0.5, and any
* representable float in the range (-1,1) has a chance to be returned, though
* values very close to zero become increasingly unlikely.
* To generate cheaper float values that do not have these properties, use
* ldexpf((float)isaac_next_uint32(_ctx),-31)-1;
* though this returns values in the range [-1,1).
*/
float isaac_next_signed_float(isaac_ctx *_ctx);
/**
* isaac_next_double - Uniform random double in the range [0,1).
* @_ctx: The ISAAC instance to generate the value with.
* Returns a high-quality double uniformly distributed between 0 (inclusive)
* and 1 (exclusive).
* All of the double's mantissa bits are random, e.g., the least significant
* bit may still be non-zero even if the value is less than 0.5, and any
* representable double in the range [0,1) has a chance to be returned, though
* values very close to zero become increasingly unlikely.
* To generate cheaper double values that do not have these properties, use
* ldexp((double)isaac_next_uint32(_ctx),-32);
*/
double isaac_next_double(isaac_ctx *_ctx);
/**
* isaac_next_signed_double - Uniform random double in the range (-1,1).
* @_ctx: The ISAAC instance to generate the value with.
* Returns a high-quality double uniformly distributed between -1 and 1
* (exclusive).
* All of the double's mantissa bits are random, e.g., the least significant
* bit may still be non-zero even if the value is less than 0.5, and any
* representable double in the range (-1,1) has a chance to be returned,
* though values very close to zero become increasingly unlikely.
* To generate cheaper double values that do not have these properties, use
* ldexp((double)isaac_next_uint32(_ctx),-31)-1;
* though this returns values in the range [-1,1).
*/
double isaac_next_signed_double(isaac_ctx *_ctx);
#endif
/*Written by Timothy B. Terriberry (tterribe@xiph.org) 1999-2009 public domain.
Based on the public domain ISAAC implementation by Robert J. Jenkins Jr.*/
#include <float.h>
#include <math.h>
#include <string.h>
#include <ccan/ilog/ilog.h>
#include "isaac64.h"
#if defined(__GNUC_PREREQ)
# if __GNUC_PREREQ(4,2)
# pragma GCC diagnostic ignored "-Wparentheses"
# endif
#endif
#define ISAAC64_MASK ((uint64_t)0xFFFFFFFFFFFFFFFFULL)
static void isaac64_update(isaac64_ctx *_ctx){
uint64_t *m;
uint64_t *r;
uint64_t a;
uint64_t b;
uint64_t x;
uint64_t y;
int i;
m=_ctx->m;
r=_ctx->r;
a=_ctx->a;
b=_ctx->b+(++_ctx->c)&ISAAC64_MASK;
for(i=0;i<ISAAC64_SZ/2;i++){
x=m[i];
a=~(a^a<<21)+m[i+ISAAC64_SZ/2]&ISAAC64_MASK;
m[i]=y=m[(x&ISAAC64_SZ-1<<3)>>3]+a+b&ISAAC64_MASK;
r[i]=b=m[y>>ISAAC64_SZ_LOG+3&ISAAC64_SZ-1]+x&ISAAC64_MASK;
x=m[++i];
a=(a^a>>5)+m[i+ISAAC64_SZ/2]&ISAAC64_MASK;
m[i]=y=m[(x&ISAAC64_SZ-1<<3)>>3]+a+b&ISAAC64_MASK;
r[i]=b=m[y>>ISAAC64_SZ_LOG+3&ISAAC64_SZ-1]+x&ISAAC64_MASK;
x=m[++i];
a=(a^a<<12)+m[i+ISAAC64_SZ/2]&ISAAC64_MASK;
m[i]=y=m[(x&ISAAC64_SZ-1<<3)>>3]+a+b&ISAAC64_MASK;
r[i]=b=m[y>>ISAAC64_SZ_LOG+3&ISAAC64_SZ-1]+x&ISAAC64_MASK;
x=m[++i];
a=(a^a>>33)+m[i+ISAAC64_SZ/2]&ISAAC64_MASK;
m[i]=y=m[(x&ISAAC64_SZ-1<<3)>>3]+a+b&ISAAC64_MASK;
r[i]=b=m[y>>ISAAC64_SZ_LOG+3&ISAAC64_SZ-1]+x&ISAAC64_MASK;
}
for(i=ISAAC64_SZ/2;i<ISAAC64_SZ;i++){
x=m[i];
a=~(a^a<<21)+m[i-ISAAC64_SZ/2]&ISAAC64_MASK;
m[i]=y=m[(x&ISAAC64_SZ-1<<3)>>3]+a+b&ISAAC64_MASK;
r[i]=b=m[y>>ISAAC64_SZ_LOG+3&ISAAC64_SZ-1]+x&ISAAC64_MASK;
x=m[++i];
a=(a^a>>5)+m[i-ISAAC64_SZ/2]&ISAAC64_MASK;
m[i]=y=m[(x&ISAAC64_SZ-1<<3)>>3]+a+b&ISAAC64_MASK;
r[i]=b=m[y>>ISAAC64_SZ_LOG+3&ISAAC64_SZ-1]+x&ISAAC64_MASK;
x=m[++i];
a=(a^a<<12)+m[i-ISAAC64_SZ/2]&ISAAC64_MASK;
m[i]=y=m[(x&ISAAC64_SZ-1<<3)>>3]+a+b&ISAAC64_MASK;
r[i]=b=m[y>>ISAAC64_SZ_LOG+3&ISAAC64_SZ-1]+x&ISAAC64_MASK;
x=m[++i];
a=(a^a>>33)+m[i-ISAAC64_SZ/2]&ISAAC64_MASK;
m[i]=y=m[(x&ISAAC64_SZ-1<<3)>>3]+a+b&ISAAC64_MASK;
r[i]=b=m[y>>ISAAC64_SZ_LOG+3&ISAAC64_SZ-1]+x&ISAAC64_MASK;
}
_ctx->b=b;
_ctx->a=a;
_ctx->n=ISAAC64_SZ;
}
static void isaac64_mix(uint64_t _x[8]){
static const unsigned char SHIFT[8]={9,9,23,15,14,20,17,14};
int i;
for(i=0;i<8;i++){
_x[i]-=_x[i+4&7];
_x[i+5&7]^=_x[i+7&7]>>SHIFT[i];
_x[i+7&7]+=_x[i];
i++;
_x[i]-=_x[i+4&7];
_x[i+5&7]^=_x[i+7&7]<<SHIFT[i];
_x[i+7&7]+=_x[i];
}
}
void isaac64_init(isaac64_ctx *_ctx,const unsigned char *_seed,int _nseed){
_ctx->a=_ctx->b=_ctx->c=0;
memset(_ctx->r,0,sizeof(_ctx->r));
isaac64_reseed(_ctx,_seed,_nseed);
}
void isaac64_reseed(isaac64_ctx *_ctx,const unsigned char *_seed,int _nseed){
uint64_t *m;
uint64_t *r;
uint64_t x[8];
int i;
int j;
m=_ctx->m;
r=_ctx->r;
if(_nseed>ISAAC64_SEED_SZ_MAX)_nseed=ISAAC64_SEED_SZ_MAX;
for(i=0;i<_nseed>>3;i++){
r[i]^=(uint64_t)_seed[i<<3|7]<<56|(uint64_t)_seed[i<<3|6]<<48|
(uint64_t)_seed[i<<3|5]<<40|(uint64_t)_seed[i<<3|4]<<32|
(uint64_t)_seed[i<<3|3]<<24|(uint64_t)_seed[i<<3|2]<<16|
(uint64_t)_seed[i<<3|1]<<8|_seed[i<<3];
}
_nseed-=i<<3;
if(_nseed>0){
uint64_t ri;
ri=_seed[i<<3];
for(j=1;j<_nseed;j++)ri|=(uint64_t)_seed[i<<3|j]<<(j<<3);
r[i++]^=ri;
}
x[0]=x[1]=x[2]=x[3]=x[4]=x[5]=x[6]=x[7]=(uint64_t)0x9E3779B97F4A7C13ULL;
for(i=0;i<4;i++)isaac64_mix(x);
for(i=0;i<ISAAC64_SZ;i+=8){
for(j=0;j<8;j++)x[j]+=r[i+j];
isaac64_mix(x);
memcpy(m+i,x,sizeof(x));
}
for(i=0;i<ISAAC64_SZ;i+=8){
for(j=0;j<8;j++)x[j]+=m[i+j];
isaac64_mix(x);
memcpy(m+i,x,sizeof(x));
}
isaac64_update(_ctx);
}
uint64_t isaac64_next_uint64(isaac64_ctx *_ctx){
if(!_ctx->n)isaac64_update(_ctx);
return _ctx->r[--_ctx->n];
}
uint64_t isaac64_next_uint(isaac64_ctx *_ctx,uint64_t _n){
uint64_t r;
uint64_t v;
uint64_t d;
do{
r=isaac64_next_uint64(_ctx);
v=r%_n;
d=r-v;
}
while((d+_n-1&ISAAC64_MASK)<d);
return v;
}
/*Returns a uniform random float.
The expected value is within FLT_MIN (e.g., 1E-37) of 0.5.
_bits: An initial set of random bits.
_base: This should be -(the number of bits in _bits), up to -64.
Return: A float uniformly distributed between 0 (inclusive) and 1
(exclusive).
The average value was measured over 2**32 samples to be
0.499991407275206357.*/
static float isaac64_float_bits(isaac64_ctx *_ctx,uint64_t _bits,int _base){
float ret;
int nbits_needed;
while(!_bits){
if(_base+FLT_MANT_DIG<FLT_MIN_EXP)return 0;
_base-=64;
_bits=isaac64_next_uint64(_ctx);
}
nbits_needed=FLT_MANT_DIG-ILOGNZ_64(_bits);
#if FLT_MANT_DIG>64
ret=ldexpf((float)_bits,_base);
# if FLT_MANT_DIG>129
while(64-nbits_needed<0){
# else
if(64-nbits_needed<0){
# endif
_base-=64;
nbits_needed-=64;
ret+=ldexpf((float)isaac64_next_uint64(_ctx),_base);
}
_bits=isaac64_next_uint64(_ctx)>>64-nbits_needed;
ret+=ldexpf((float)_bits,_base-nbits_needed);
#else
if(nbits_needed>0){
_bits=_bits<<nbits_needed|isaac64_next_uint64(_ctx)>>64-nbits_needed;
}
# if FLT_MANT_DIG<64
else _bits>>=-nbits_needed;
# endif
ret=ldexpf((float)_bits,_base-nbits_needed);
#endif
return ret;
}
float isaac64_next_float(isaac64_ctx *_ctx){
return isaac64_float_bits(_ctx,0,0);
}
float isaac64_next_signed_float(isaac64_ctx *_ctx){
uint64_t bits;
bits=isaac64_next_uint64(_ctx);
return (1|-((int)bits&1))*isaac64_float_bits(_ctx,bits>>1,-63);
}
/*Returns a uniform random double.
_bits: An initial set of random bits.
_base: This should be -(the number of bits in _bits), up to -64.
Return: A double uniformly distributed between 0 (inclusive) and 1
(exclusive).
The average value was measured over 2**32 samples to be
0.499990992392019273.*/
static double isaac64_double_bits(isaac64_ctx *_ctx,uint64_t _bits,int _base){
double ret;
int nbits_needed;
while(!_bits){
if(_base+DBL_MANT_DIG<DBL_MIN_EXP)return 0;
_base-=64;
_bits=isaac64_next_uint64(_ctx);
}
nbits_needed=DBL_MANT_DIG-ILOGNZ_64(_bits);
#if DBL_MANT_DIG>64
ret=ldexp((double)_bits,_base);
# if DBL_MANT_DIG>129
while(64-nbits_needed<0){
# else
if(64-nbits_needed<0){
# endif
_base-=64;
nbits_needed-=64;
ret+=ldexp((double)isaac64_next_uint64(_ctx),_base);
}
_bits=isaac64_next_uint64(_ctx)>>64-nbits_needed;
ret+=ldexp((double)_bits,_base-nbits_needed);
#else
if(nbits_needed>0){
_bits=_bits<<nbits_needed|isaac64_next_uint64(_ctx)>>64-nbits_needed;
}
# if DBL_MANT_DIG<64
else _bits>>=-nbits_needed;
# endif
ret=ldexp((double)_bits,_base-nbits_needed);
#endif
return ret;
}
double isaac64_next_double(isaac64_ctx *_ctx){
return isaac64_double_bits(_ctx,0,0);
}
double isaac64_next_signed_double(isaac64_ctx *_ctx){
uint64_t bits;
bits=isaac64_next_uint64(_ctx);
return (1|-((int)bits&1))*isaac64_double_bits(_ctx,bits>>1,-63);
}
#if !defined(_isaac64_H)
# define _isaac64_H (1)
# include <stdint.h>
typedef struct isaac64_ctx isaac64_ctx;
#define ISAAC64_SZ_LOG (8)
#define ISAAC64_SZ (1<<ISAAC64_SZ_LOG)
#define ISAAC64_SEED_SZ_MAX (ISAAC64_SZ<<3)
/*ISAAC is the most advanced of a series of pseudo-random number generators
designed by Robert J. Jenkins Jr. in 1996.
http://www.burtleburtle.net/bob/rand/isaac.html
This is the 64-bit version.
To quote:
ISAAC-64 generates a different sequence than ISAAC, but it uses the same
principles.
It uses 64-bit arithmetic.
It generates a 64-bit result every 19 instructions.
All cycles are at least 2**72 values, and the average cycle length is
2**16583.*/
struct isaac64_ctx{
unsigned n;
uint64_t r[ISAAC64_SZ];
uint64_t m[ISAAC64_SZ];
uint64_t a;
uint64_t b;
uint64_t c;
};
/**
* isaac64_init - Initialize an instance of the ISAAC64 random number generator.
* @_ctx: The ISAAC64 instance to initialize.
* @_seed: The specified seed bytes.
* This may be NULL if _nseed is less than or equal to zero.
* @_nseed: The number of bytes to use for the seed.
* If this is greater than ISAAC64_SEED_SZ_MAX, the extra bytes are
* ignored.
*/
void isaac64_init(isaac64_ctx *_ctx,const unsigned char *_seed,int _nseed);
/**
* isaac64_reseed - Mix a new batch of entropy into the current state.
* To reset ISAAC64 to a known state, call isaac64_init() again instead.
* @_ctx: The instance to reseed.
* @_seed: The specified seed bytes.
* This may be NULL if _nseed is zero.
* @_nseed: The number of bytes to use for the seed.
* If this is greater than ISAAC64_SEED_SZ_MAX, the extra bytes are
* ignored.
*/
void isaac64_reseed(isaac64_ctx *_ctx,const unsigned char *_seed,int _nseed);
/**
* isaac64_next_uint64 - Return the next random 64-bit value.
* @_ctx: The ISAAC64 instance to generate the value with.
*/
uint64_t isaac64_next_uint64(isaac64_ctx *_ctx);
/**
* isaac64_next_uint - Uniform random integer less than the given value.
* @_ctx: The ISAAC64 instance to generate the value with.
* @_n: The upper bound on the range of numbers returned (not inclusive).
* This must be greater than zero and less than 2**64.
* To return integers in the full range 0...2**64-1, use
* isaac64_next_uint64() instead.
* Return: An integer uniformly distributed between 0 and _n-1 (inclusive).
*/
uint64_t isaac64_next_uint(isaac64_ctx *_ctx,uint64_t _n);
/**
* isaac64_next_float - Uniform random float in the range [0,1).
* @_ctx: The ISAAC64 instance to generate the value with.
* Returns a high-quality float uniformly distributed between 0 (inclusive)
* and 1 (exclusive).
* All of the float's mantissa bits are random, e.g., the least significant bit
* may still be non-zero even if the value is less than 0.5, and any
* representable float in the range [0,1) has a chance to be returned, though
* values very close to zero become increasingly unlikely.
* To generate cheaper float values that do not have these properties, use
* ldexpf((float)isaac64_next_uint64(_ctx),-64);
*/
float isaac64_next_float(isaac64_ctx *_ctx);
/**
* isaac64_next_signed_float - Uniform random float in the range (-1,1).
* @_ctx: The ISAAC64 instance to generate the value with.
* Returns a high-quality float uniformly distributed between -1 and 1
* (exclusive).
* All of the float's mantissa bits are random, e.g., the least significant bit
* may still be non-zero even if the magnitude is less than 0.5, and any
* representable float in the range (-1,1) has a chance to be returned, though
* values very close to zero become increasingly unlikely.
* To generate cheaper float values that do not have these properties, use
* ldexpf((float)isaac64_next_uint64(_ctx),-63)-1;
* though this returns values in the range [-1,1).
*/
float isaac64_next_signed_float(isaac64_ctx *_ctx);
/**
* isaac64_next_double - Uniform random double in the range [0,1).
* @_ctx: The ISAAC64 instance to generate the value with.
* Returns a high-quality double uniformly distributed between 0 (inclusive)
* and 1 (exclusive).
* All of the double's mantissa bits are random, e.g., the least significant
* bit may still be non-zero even if the value is less than 0.5, and any
* representable double in the range [0,1) has a chance to be returned, though
* values very close to zero become increasingly unlikely.
* To generate cheaper double values that do not have these properties, use
* ldexp((double)isaac64_next_uint64(_ctx),-64);
*/
double isaac64_next_double(isaac64_ctx *_ctx);
/**
* isaac64_next_signed_double - Uniform random double in the range (-1,1).
* @_ctx: The ISAAC64 instance to generate the value with.
* Returns a high-quality double uniformly distributed between -1 and 1
* (exclusive).
* All of the double's mantissa bits are random, e.g., the least significant
* bit may still be non-zero even if the value is less than 0.5, and any
* representable double in the range (-1,1) has a chance to be returned,
* though values very close to zero become increasingly unlikely.
* To generate cheaper double values that do not have these properties, use
* ldexp((double)isaac64_next_uint64(_ctx),-63)-1;
* though this returns values in the range [-1,1).
*/
double isaac64_next_signed_double(isaac64_ctx *_ctx);
#endif
#include "isaac/isaac.h"
#include "isaac/isaac64.h"
#include "tap/tap.h"
#include <stddef.h>
static const uint32_t STATEVEC[ISAAC_SZ<<1]={
0xF650E4C8, 0xE448E96D, 0x98DB2FB4, 0xF5FAD54F,
0x433F1AFB, 0xEDEC154A, 0xD8370487, 0x46CA4F9A,
0x5DE3743E, 0x88381097, 0xF1D444EB, 0x823CEDB6,
0x6A83E1E0, 0x4A5F6355, 0xC7442433, 0x25890E2E,
0x7452E319, 0x57161DF6, 0x38A824F3, 0x002ED713,
0x29F55449, 0x51C08D83, 0xD78CB99E, 0xA0CC74F3,
0x8F651659, 0xCBC8B7C2, 0xF5F71C69, 0x12AD6419,
0xE5792E1B, 0x860536B8, 0x09B3CE98, 0xD45D6D81,
0xF3B26129, 0x17E38F85, 0x29CF72CE, 0x349947B0,
0xC998F9FF, 0xB5E13DAE, 0x32AE2A2B, 0xF7CF814C,
0x8EBFA303, 0xCF22E064, 0x0B923200, 0xECA4D58A,
0xEF53CEC4, 0xD0F7B37D, 0x9C411A2A, 0xFFDF8A80,
0xB40E27BC, 0xB4D2F976, 0x44B89B08, 0xF37C71D5,
0x1A70E7E9, 0x0BDB9C30, 0x60DC5207, 0xB3C3F24B,
0xD7386806, 0x229749B5, 0x4E232CD0, 0x91DABC65,
0xA70E1101, 0x8B87437E, 0x5781414F, 0xCDBC62E2,
0x8107C9FF, 0x69D2E4AE, 0x3B18E752, 0xB143B688,
0x6F4E0772, 0x95138769, 0x943C3C74, 0xAFC17A97,
0x0FD43963, 0x6A529B0B, 0xD8C58A6A, 0xA8BCC22D,
0x2DB35DFE, 0xA7A2F402, 0x6CB167DB, 0x538E1F4E,
0x7275E277, 0x1D3B8E97, 0xECC5DC91, 0x15E3A5B9,
0x03696614, 0x30AB93EC, 0xAC9FE69D, 0x7BC76811,
0x60EDA8DA, 0x28833522, 0xD5295EBC, 0x5ADB60E7,
0xF7E1CDD0, 0x97166D14, 0xB67EC13A, 0x210F3925,
0x64AF0FEF, 0x0D028684, 0x3AEA3DEC, 0xB058BAFB,
0xB8B0CCFC, 0xF2B5CC05, 0xE3A662D9, 0x814BC24C,
0x2364A1AA, 0x37C0ED05, 0x2B36505C, 0x451E7EC8,
0x5D2A542F, 0xE43D0FBB, 0x91C8D925, 0x60D4D5F8,
0x12A0594B, 0x9E8A51DA, 0xCD49EBDB, 0x1B0DCDC1,
0xCD57C7F7, 0xE6344451, 0x7DED386F, 0x2F36FA86,
0xA6D12101, 0x33BC405D, 0xB388D96C, 0xDB6DBE96,
0xFE29661C, 0x13EDC0CB, 0xCB0EEE4A, 0x70CC94AE,
0xDE11ED34, 0x0606CF9F, 0x3A6CE389, 0x23D74F4E,
0xA37F63FF, 0x917BDEC2, 0xD73F72D4, 0x0E7E0E67,
0x3D77D9A2, 0x13ADD922, 0x8891B3DB, 0x01A9BD70,
0x56A001E3, 0xD51F093D, 0xCC033CE3, 0x5AD0D3B0,
0x34105A8C, 0x6A123F57, 0xBD2E5024, 0x7364944B,
0xE89B1A3B, 0x21835C4D, 0x9F39E2D9, 0xD405DED8,
0x294D37E5, 0xBCCAAEED, 0x35A124B5, 0x6708A2BC,
0xB00960BA, 0x2A98121A, 0x4D8FAE82, 0x0BB3263F,
0x12595A19, 0x6A107589, 0x0809E494, 0x21C171EC,
0x884D6825, 0x14C8009B, 0xB0B84E7B, 0x03FB88F4,
0x28E7CB78, 0x9388B13B, 0xDD2DC1D5, 0x848F520A,
0x07C28CD1, 0x68A39358, 0x72C9137D, 0x127DD430,
0xC613F157, 0x8C2F0D55, 0xF7D3F39F, 0x309BFB78,
0x8406B137, 0x46C0A6F5, 0x3718D597, 0x08607F04,
0x76904B6D, 0x04DB4E13, 0xCD7411A7, 0xB510CE0E,
0xBFC7F7CC, 0xB83F957A, 0xFDFEF62D, 0xC35E4580,
0x3FF1E524, 0x4112D96C, 0x02C9B944, 0xD5990DFB,
0xE7E26581, 0x0D9C7E7E, 0x826DFA89, 0x66F1E0AB,
0x30BCC764, 0xEADEBEAC, 0xED35E5EE, 0x0C571A7D,
0xE4F3A26A, 0xF7F58F7B, 0xADF6BC23, 0x5D023E65,
0x1ED3FF4E, 0xEC46B0B6, 0xD2A93B51, 0xE75B41C9,
0x7E315AEB, 0x61119A5A, 0x53245B79, 0x33F6D7B1,
0xCAE8DEBA, 0x50FC8194, 0xAFA92A6D, 0xC87C8006,
0x4188BFCD, 0x8BACE62E, 0x78FFA568, 0x5597EC0F,
0xB4415F7D, 0x08294766, 0xAD567643, 0x09C36F90,
0x3DDE9F39, 0x4A0A283C, 0x18080C8E, 0x080C79EC,
0x79AE4C10, 0xCB9E1563, 0x7CDD662F, 0x62D31911,
0xA4CA0CF1, 0x5CF824CD, 0x3B708F99, 0x1E16614C,
0xB6B9D766, 0x5DE87ABB, 0x7229EA81, 0xD5B2D750,
0x56E6CD21, 0xFE1E42D5, 0x96DA2655, 0xC2B9AA36,
0xB8F6FD4A, 0x6A158D10, 0x01913FD3, 0xAF7D1FB8,
0x0B5E435F, 0x90C10757, 0x6554ABDA, 0x7A68710F,
0x82AC484F, 0xD7E1C7BE, 0x95C85EAA, 0x94A302F4,
0x4D3CFBDA, 0x786B2908, 0x1010B275, 0x82D53D12,
0x21E2A51C, 0x3D1E9150, 0xB059261D, 0xD0638E1A,
0x31860F05, 0x81F2864D, 0xFF4CFC35, 0x0451516D,
0xBD086F26, 0xBC5654C1, 0x65DFA427, 0xA82427F5,
0x582E3014, 0xB8D2486D, 0xC79A1749, 0x9A1D7745,
0x8766BB54, 0x1E04A7F7, 0x3D3DFF8A, 0xD5EC6BF4,
0xDBEF7D9F, 0x36EC0EA3, 0x1FEB2E4F, 0x15CFCC5C,
0xD8C423FB, 0xD0EF3CC9, 0xEB244925, 0xBA5590C8,
0xA5F48AC4, 0x33C5321C, 0x613B67B2, 0x479C3A22,
0xE21339CC, 0x10D210AA, 0x931DD7E2, 0xEF05EE06,
0xB82F2703, 0xA385CB2C, 0x5D67133C, 0x877EB7B4,
0x1E3437F7, 0x5AFB43AE, 0x53C078F3, 0x94D90481,
0x1D964589, 0x08063A85, 0xE1322228, 0x1956B1E5,
0x31860F13, 0x2E7B022F, 0x21182CA3, 0x96F703AC,
0x46819E2E, 0x0D28FE52, 0x3724D4DC, 0xA0EABE6B,
0xC66699FD, 0xC6112FDD, 0x19C1E69C, 0x04D3658A,
0x4B55DD99, 0x31907D62, 0xF854B522, 0x4D678F26,
0x22AE0582, 0xEAFED133, 0xE4A51D21, 0x84BD6DD6,
0xC1A51375, 0x3F28EE63, 0xFB737B1A, 0x70A1660E,
0x8A8DFAA3, 0x1BE79937, 0xF7476978, 0x513C1764,
0x531AC6BF, 0x12C06908, 0x001CDB95, 0x1A4B6A53,
0xD067FCE5, 0x12B2CFB6, 0x9DDB477F, 0x740E0066,
0x39DDF25A, 0xCC8BFA2D, 0xF1B20EAF, 0x64F2632C,
0x9783CDEE, 0x63BFD4D8, 0x0084CFE5, 0x75F4E9E2,
0x19B48FD0, 0x6C48DDD8, 0x7A36AF93, 0x71865C4C,
0x9CE0199D, 0x867027D7, 0x2CB7B77F, 0x84EF01DA,
0x72F5972F, 0x040F7074, 0xDF9AFA29, 0xC921F94E,
0x75C08A36, 0x18C1EF9A, 0xD649A428, 0xC5B71937,
0x8A30738A, 0xD97CD348, 0x858129A6, 0x239E3B0A,
0xBBB8ABC4, 0x80FAC4C2, 0xECFCF20B, 0xD9D711F9,
0xE2A4EF71, 0xB5FE87C0, 0xBE8B06B2, 0xAAFEF5A7,
0x9C15DB3B, 0x0AEB8165, 0x4389A84A, 0x253B1D7A,
0x19047C79, 0x7CDC78A2, 0xD20ADF03, 0x56F55A71,
0x3E730FA8, 0xFD8650D8, 0x959E234E, 0xB7546681,
0xDAD1B22A, 0x142A6E85, 0x8EF4BCE6, 0x68235B9D,
0x85A13F85, 0x74096AE7, 0xA949BEA2, 0x29322D0D,
0xD5683858, 0x82846526, 0x403DAE08, 0x6DD1943A,
0xE1279BFF, 0x9E7E4F04, 0x1C3A4524, 0x484525E4,
0x81D4CC5F, 0xE24124C0, 0x037464C0, 0xBF1BD691,
0x26CEB003, 0x275EAD3A, 0xC5BDE908, 0x26414FF3,
0xA30519AD, 0xD7B43ABE, 0x2CE5D3D5, 0x88412761,
0x97CA2070, 0xE5FBB9C7, 0x276DF0B4, 0x308F751F,
0x37A97DF6, 0xC9CD808C, 0xFE4CB380, 0x3D469303,
0xAEE19096, 0xC0D5D42A, 0x4E823AD3, 0xF5F9CC3B,
0x4286619C, 0x9CA45E1C, 0x66C97340, 0x891AEC49,
0x45BAE606, 0xC798F047, 0x52649D6C, 0xCE86FDFC,
0x80C6E402, 0xD6EC2F2B, 0x27C82282, 0x1FE26CE0,
0x92F57EA7, 0xDE462F4D, 0x07497CAE, 0x5A48755C,
0x721502DD, 0x6CBE7935, 0x836D8003, 0x9EAD7F70,
0x9AB3A42F, 0x4C8652D6, 0x32E39273, 0xE8FA3860,
0x1DA4F25A, 0x0CD6EF81, 0x02503F7D, 0x8854A0A1,
0x9A30C4E8, 0x88157153, 0x05EFE294, 0x57C4C925,
0x2887D96F, 0xC1A71E3C, 0xE9F84163, 0x2D0985DE,
0xD21E796C, 0x6FB5CE56, 0x02614ABF, 0xC3C7BE2C,
0xB54FED6F, 0xA617A083, 0xC3142D8F, 0x6079E4CE,
0xCEFFC147, 0x1D0CB81B, 0xDC153E5F, 0xE36EF5BB,
0xD531161A, 0x165B1015, 0x7AA114ED, 0x3F7579B3,
0xF7F395F1, 0xBC6172C7, 0xA86F875E, 0x0E6C51B3,
0xCDFEC2AF, 0x73C0E762, 0x824C2009, 0xC5A87748,
0x94D40125, 0x8ABA3FFB, 0xD32BE060, 0x8C17EFF0,
0x21E2547E, 0x07CFFAD9, 0x05340E15, 0xF3310C92,
0x9D8D1908, 0x86BA527F, 0xF943F672, 0xEF73FBF0,
0x46D95CA5, 0xC54CD95B, 0x9D855E89, 0x4BB5AF29
};
static const uint64_t STATEVEC64[ISAAC64_SZ<<1]={
0x12A8F216AF9418C2ULL, 0xD4490AD526F14431ULL,
0xB49C3B3995091A36ULL, 0x5B45E522E4B1B4EFULL,
0xA1E9300CD8520548ULL, 0x49787FEF17AF9924ULL,
0x03219A39EE587A30ULL, 0xEBE9EA2ADF4321C7ULL,
0x804456AF10F5FB53ULL, 0xD74BBE77E6116AC7ULL,
0x7C0828DD624EC390ULL, 0x14A195640116F336ULL,
0x2EAB8CA63CE802D7ULL, 0xC6E57A78FBD986E0ULL,
0x58EFC10B06A2068DULL, 0xABEEDDB2DDE06FF1ULL,
0x0B090A7560A968E3ULL, 0x2CF9C8CA052F6E9FULL,
0x116D0016CB948F09ULL, 0xA59E0BD101731A28ULL,
0x63767572AE3D6174ULL, 0xAB4F6451CC1D45ECULL,
0xC2A1E7B5B459AEB5ULL, 0x2472F6207C2D0484ULL,
0xE699ED85B0DFB40DULL, 0xD4347F66EC8941C3ULL,
0xF4D14597E660F855ULL, 0x8B889D624D44885DULL,
0x258E5A80C7204C4BULL, 0xAF0C317D32ADAA8AULL,
0x9C4CD6257C5A3603ULL, 0xEB3593803173E0CEULL,
0x36F60E2BA4FA6800ULL, 0x38B6525C21A42B0EULL,
0xF4F5D05C10CAB243ULL, 0xCF3F4688801EB9AAULL,
0x1DDC0325259B27DEULL, 0xB9571FA04DC089C8ULL,
0xD7504DFA8816EDBBULL, 0x1FE2CCA76517DB90ULL,
0x261E4E4C0A333A9DULL, 0x219B97E26FFC81BDULL,
0x66B4835D9EAFEA22ULL, 0x4CC317FB9CDDD023ULL,
0x50B704CAB602C329ULL, 0xEDB454E7BADC0805ULL,
0x9E17E49642A3E4C1ULL, 0x66C1A2A1A60CD889ULL,
0x7983EED3740847D5ULL, 0x298AF231C85BAFABULL,
0x2680B122BAA28D97ULL, 0x734DE8181F6EC39AULL,
0x53898E4C3910DA55ULL, 0x1761F93A44D5AEFEULL,
0xE4DBF0634473F5D2ULL, 0x4ED0FE7E9DC91335ULL,
0xD18D8549D140CAEAULL, 0x1CFC8BED0D681639ULL,
0xCA1E3785A9E724E5ULL, 0xB67C1FA481680AF8ULL,
0xDFEA21EA9E7557E3ULL, 0xD6B6D0ECC617C699ULL,
0xFA7E393983325753ULL, 0xA09E8C8C35AB96DEULL,
0x8FE88B57305E2AB6ULL, 0x89039D79D6FC5C5CULL,
0x9BFB227EBDF4C5CEULL, 0x7F7CC39420A3A545ULL,
0x3F6C6AF859D80055ULL, 0xC8763C5B08D1908CULL,
0x469356C504EC9F9DULL, 0x26E6DB8FFDF5ADFEULL,
0x3A938FEE32D29981ULL, 0x2C5E9DEB57EF4743ULL,
0x1E99B96E70A9BE8BULL, 0x764DBEAE7FA4F3A6ULL,
0xAAC40A2703D9BEA0ULL, 0x1A8C1E992B941148ULL,
0x73AA8A564FB7AC9EULL, 0x604D51B25FBF70E2ULL,
0xDD69A0D8AB3B546DULL, 0x65CA5B96B7552210ULL,
0x2FD7E4B9E72CD38CULL, 0x51D2B1AB2DDFB636ULL,
0x9D1D84FCCE371425ULL, 0xA44CFE79AE538BBEULL,
0xDE68A2355B93CAE6ULL, 0x9FC10D0F989993E0ULL,
0x94EBC8ABCFB56DAEULL, 0xD7A023A73260B45CULL,
0x72C8834A5957B511ULL, 0x8F8419A348F296BFULL,
0x1E152328F3318DEAULL, 0x4838D65F6EF6748FULL,
0xD6BF7BAEE43CAC40ULL, 0x13328503DF48229FULL,
0x7440FB816508C4FEULL, 0x9D266D6A1CC0542CULL,
0x4DDA48153C94938AULL, 0x74C04BF1790C0EFEULL,
0xE1925C71285279F5ULL, 0x8A8E849EB32781A5ULL,
0x073973751F12DD5EULL, 0xA319CE15B0B4DB31ULL,
0x6DD856D94D259236ULL, 0x67378D8ECCEF96CBULL,
0x9FC477DE4ED681DAULL, 0xF3B8B6675A6507FFULL,
0xC3A9DC228CAAC9E9ULL, 0xC37B45B3F8D6F2BAULL,
0xB559EB1D04E5E932ULL, 0x1B0CAB936E65C744ULL,
0xAF08DA9177DDA93DULL, 0xAC12FB171817EEE7ULL,
0x1FFF7AC80904BF45ULL, 0xA9119B60369FFEBDULL,
0xBFCED1B0048EAC50ULL, 0xB67B7896167B4C84ULL,
0x9B3CDB65F82CA382ULL, 0xDBC27AB5447822BFULL,
0x10DCD78E3851A492ULL, 0xB438C2B67F98E5E9ULL,
0x43954B3252DC25E5ULL, 0xAB9090168DD05F34ULL,
0xCE68341F79893389ULL, 0x36833336D068F707ULL,
0xDCDD7D20903D0C25ULL, 0xDA3A361B1C5157B1ULL,
0x7F9D1A2E1EBE1327ULL, 0x5D0A12F27AD310D1ULL,
0x3BC36E078F7515D7ULL, 0x4DA8979A0041E8A9ULL,
0x950113646D1D6E03ULL, 0x7B4A38E32537DF62ULL,
0x8A1B083821F40CB4ULL, 0x3D5774A11D31AB39ULL,
0x7A76956C3EAFB413ULL, 0x7F5126DBBA5E0CA7ULL,
0x12153635B2C0CF57ULL, 0x7B3F0195FC6F290FULL,
0x5544F7D774B14AEFULL, 0x56C074A581EA17FEULL,
0xE7F28ECD2D49EECDULL, 0xE479EE5B9930578CULL,
0x9FF38FED72E9052FULL, 0x9F65789A6509A440ULL,
0x0981DCD296A8736DULL, 0x5873888850659AE7ULL,
0xC678B6D860284A1CULL, 0x63E22C147B9C3403ULL,
0x92FAE24291F2B3F1ULL, 0x829626E3892D95D7ULL,
0xCFFE1939438E9B24ULL, 0x79999CDFF70902CBULL,
0x8547EDDFB81CCB94ULL, 0x7B77497B32503B12ULL,
0x97FCAACBF030BC24ULL, 0x6CED1983376FA72BULL,
0x7E75D99D94A70F4DULL, 0xD2733C4335C6A72FULL,
0xDBC0D2B6AB90A559ULL, 0x94628D38D0C20584ULL,
0x64972D68DEE33360ULL, 0xB9C11D5B1E43A07EULL,
0x2DE0966DAF2F8B1CULL, 0x2E18BC1AD9704A68ULL,
0xD4DBA84729AF48ADULL, 0xB7A0B174CFF6F36EULL,
0xE94C39A54A98307FULL, 0xAA70B5B4F89695A2ULL,
0x3BDBB92C43B17F26ULL, 0xCCCB7005C6B9C28DULL,
0x18A6A990C8B35EBDULL, 0xFC7C95D827357AFAULL,
0x1FCA8A92FD719F85ULL, 0x1DD01AAFCD53486AULL,
0x49353FEA39BA63B1ULL, 0xF85B2B4FBCDE44B7ULL,
0xBE7444E39328A0ACULL, 0x3E2B8BCBF016D66DULL,
0x964E915CD5E2B207ULL, 0x1725CABFCB045B00ULL,
0x7FBF21EC8A1F45ECULL, 0x11317BA87905E790ULL,
0x2FE4B17170E59750ULL, 0xE8D9ECBE2CF3D73FULL,
0xB57D2E985E1419C7ULL, 0x0572B974F03CE0BBULL,
0xA8D7E4DAB780A08DULL, 0x4715ED43E8A45C0AULL,
0xC330DE426430F69DULL, 0x23B70EDB1955C4BFULL,
0x098954D51FFF6580ULL, 0x8107FCCF064FCF56ULL,
0x852F54934DA55CC9ULL, 0x09C7E552BC76492FULL,
0xE9F6760E32CD8021ULL, 0xA3BC941D0A5061CBULL,
0xBA89142E007503B8ULL, 0xDC842B7E2819E230ULL,
0xBBE83F4ECC2BDECBULL, 0xCD454F8F19C5126AULL,
0xC62C58F97DD949BFULL, 0x693501D628297551ULL,
0xB9AB4CE57F2D34F3ULL, 0x9255ABB50D532280ULL,
0xEBFAFA33D7254B59ULL, 0xE9F6082B05542E4EULL,
0x35DD37D5871448AFULL, 0xB03031A8B4516E84ULL,
0xB3F256D8ACA0B0B9ULL, 0x0FD22063EDC29FCAULL,
0xD9A11FBB3D9808E4ULL, 0x3A9BF55BA91F81CAULL,
0xC8C93882F9475F5FULL, 0x947AE053EE56E63CULL,
0xC7D9F16864A76E94ULL, 0x7BD94E1D8E17DEBCULL,
0xD873DB391292ED4FULL, 0x30F5611484119414ULL,
0x565C31F7DE89EA27ULL, 0xD0E4366228B03343ULL,
0x325928EE6E6F8794ULL, 0x6F423357E7C6A9F9ULL,
0x99170A5DC3115544ULL, 0x59B97885E2F2EA28ULL,
0xBC4097B116C524D2ULL, 0x7A13F18BBEDC4FF5ULL,
0x071582401C38434DULL, 0xB422061193D6F6A7ULL,
0xB4B81B3FA97511E2ULL, 0x65D34954DAF3CEBDULL,
0xB344C470397BBA52ULL, 0xBAC7A9A18531294BULL,
0xECB53939887E8175ULL, 0x565601C0364E3228ULL,
0xEF1955914B609F93ULL, 0x16F50EDF91E513AFULL,
0x56963B0DCA418FC0ULL, 0xD60F6DCEDC314222ULL,
0x364F6FFA464EE52EULL, 0x6C3B8E3E336139D3ULL,
0xF943AEE7FEBF21B8ULL, 0x088E049589C432E0ULL,
0xD49503536ABCA345ULL, 0x3A6C27934E31188AULL,
0x957BAF61700CFF4EULL, 0x37624AE5A48FA6E9ULL,
0x501F65EDB3034D07ULL, 0x907F30421D78C5DEULL,
0x1A804AADB9CFA741ULL, 0x0CE2A38C344A6EEDULL,
0xD363EFF5F0977996ULL, 0x2CD16E2ABD791E33ULL,
0x58627E1A149BBA21ULL, 0x7F9B6AF1EBF78BAFULL,
0xD20D8C88C8FFE65FULL, 0x917F1DD5F8886C61ULL,
0x56986E2EF3ED091BULL, 0x5FA7867CAF35E149ULL,
0x81A1549FD6573DA5ULL, 0x96FBF83A12884624ULL,
0xE728E8C83C334074ULL, 0xF1BCC3D275AFE51AULL,
0x71F1CE2490D20B07ULL, 0xE6C42178C4BBB92EULL,
0x0A9C32D5EAE45305ULL, 0x0C335248857FA9E7ULL,
0x142DE49FFF7A7C3DULL, 0x64A53DC924FE7AC9ULL,
0x9F6A419D382595F4ULL, 0x150F361DAB9DEC26ULL,
0xC61BB3A141E50E8CULL, 0x2785338347F2BA08ULL,
0x7CA9723FBB2E8988ULL, 0xCE2F8642CA0712DCULL,
0x59300222B4561E00ULL, 0xC2B5A03F71471A6FULL,
0xD5F9E858292504D5ULL, 0x65FA4F227A2B6D79ULL,
0x93CBE0B699C2585DULL, 0x1D95B0A5FCF90BC6ULL,
0x17EFEE45B0DEE640ULL, 0x9E4C1269BAA4BF37ULL,
0xD79476A84EE20D06ULL, 0x0A56A5F0BFE39272ULL,
0x7EBA726D8C94094BULL, 0x5E5637885F29BC2BULL,
0xD586BD01C5C217F6ULL, 0x233003B5A6CFE6ADULL,
0x24C0E332B70019B0ULL, 0x9DA058C67844F20CULL,
0xE4D9429322CD065AULL, 0x1FAB64EA29A2DDF7ULL,
0x8AF38731C02BA980ULL, 0x7DC7785B8EFDFC80ULL,
0x486289DDCC3D6780ULL, 0x222BBFAE61725606ULL,
0x2BC60A63A6F3B3F2ULL, 0x177E00F9FC32F791ULL,
0x522E23F3925E319EULL, 0x9C2ED44081CE5FBDULL,
0x964781CE734B3C84ULL, 0xF05D129681949A4CULL,
0x046E3ECAAF453CE9ULL, 0x962ACEEFA82E1C84ULL,
0xF5B4B0B0D2DEEEB4ULL, 0x1AF3DBE25D8F45DAULL,
0xF9F4892ED96BD438ULL, 0xC4C118BFE78FEAAEULL,
0x07A69AFDCC42261AULL, 0xF8549E1A3AA5E00DULL,
0x2102AE466EBB1148ULL, 0xE87FBB46217A360EULL,
0x310CB380DB6F7503ULL, 0xB5FDFC5D3132C498ULL,
0xDAF8E9829FE96B5FULL, 0xCAC09AFBDDD2CDB4ULL,
0xB862225B055B6960ULL, 0x55B6344CF97AAFAEULL,
0xFF577222C14F0A3AULL, 0x4E4B705B92903BA4ULL,
0x730499AF921549FFULL, 0x13AE978D09FE5557ULL,
0xD9E92AA246BF719EULL, 0x7A4C10EC2158C4A6ULL,
0x49CAD48CEBF4A71EULL, 0xCF05DAF5AC8D77B0ULL,
0xABBDCDD7ED5C0860ULL, 0x9853EAB63B5E0B35ULL,
0x352787BAA0D7C22FULL, 0xC7F6AA2DE59AEA61ULL,
0x03727073C2E134B1ULL, 0x5A0F544DD2B1FB18ULL,
0x74F85198B05A2E7DULL, 0x963EF2C96B33BE31ULL,
0x4659D2B743848A2CULL, 0x19EBB029435DCB0FULL,
0x4E9D2827355FC492ULL, 0xCCEC0A73B49C9921ULL,
0x46C9FEB55D120902ULL, 0x8D2636B81555A786ULL,
0x30C05B1BA332F41CULL, 0xF6F7FD1431714200ULL,
0x1A4FF12616EEFC89ULL, 0x990A98FD5071D263ULL,
0x84547DDC3E203C94ULL, 0x07A3AEC79624C7DAULL,
0x8A328A1CEDFE552CULL, 0xD1E649DE1E7F268BULL,
0x2D8D5432157064C8ULL, 0x4AE7D6A36EB5DBCBULL,
0x57E3306D881EDB4FULL, 0x0A804D18B7097475ULL,
0xE74733427B72F0C1ULL, 0x24B33C9D7ED25117ULL,
0xE805A1E290CF2456ULL, 0x3B544EBE544C19F9ULL,
0x3E666E6F69AE2C15ULL, 0xFB152FE3FF26DA89ULL,
0xB49B52E587A1EE60ULL, 0xAC042E70F8B383F2ULL,
0x89C350C893AE7DC1ULL, 0xB592BF39B0364963ULL,
0x190E714FADA5156EULL, 0xEC8177F83F900978ULL,
0x91B534F885818A06ULL, 0x81536D601170FC20ULL,
0xD4C718BC4AE8AE5FULL, 0x9EEDECA8E272B933ULL,
0x10E8B35AF3EEAB37ULL, 0x0E09B88E1914F7AFULL,
0x3FA9DDFB67E2F199ULL, 0xB10BB459132D0A26ULL,
0x2C046F22062DC67DULL, 0x5E90277E7CB39E2DULL,
0xD6B04D3B7651DD7EULL, 0xE34A1D250E7A8D6BULL,
0x53C065C6C8E63528ULL, 0x1BDEA12E35F6A8C9ULL,
0x21874B8B4D2DBC4FULL, 0x3A88A0FBBCB05C63ULL,
0x43ED7F5A0FAE657DULL, 0x230E343DFBA08D33ULL,
0xB5B4071DBFC73A66ULL, 0x8F9887E6078735A1ULL,
0x08DE8A1C7797DA9BULL, 0xFCB6BE43A9F2FE9BULL,
0x049A7F41061A9E60ULL, 0x9F91508BFFCFC14AULL,
0xE3273522064480CAULL, 0xCD04F3FF001A4778ULL,
0x6BFA9AAE5EC05779ULL, 0x371F77E76BB8417EULL,
0x3550C2321FD6109CULL, 0xFB4A3D794A9A80D2ULL,
0xF43C732873F24C13ULL, 0xAA9119FF184CCCF4ULL,
0xB69E38A8965C6B65ULL, 0x1F2B1D1F15F6DC9CULL,
0x67FEF95D92607890ULL, 0x31865CED6120F37DULL,
0x3A6853C7E70757A7ULL, 0x32AB0EDB696703D3ULL,
0xEE97F453F06791EDULL, 0x6DC93D9526A50E68ULL,
0x78EDEFD694AF1EEDULL, 0x9C1169FA2777B874ULL,
0x50065E535A213CF6ULL, 0xDE0C89A556B9AE70ULL,
0xD1E0CCD25BB9C169ULL, 0x6B17B224BAD6BF27ULL,
0x6B02E63195AD0CF8ULL, 0x455A4B4CFE30E3F5ULL,
0x9338E69C052B8E7BULL, 0x5092EF950A16DA0BULL,
0x7C45D833AFF07862ULL, 0xA5B1CFDBA0AB4067ULL,
0x6AD047C430A12104ULL, 0x6C47BEC883A7DE39ULL,
0x944F6DE09134DFB6ULL, 0x9AEBA33AC6ECC6B0ULL,
0x52E762596BF68235ULL, 0x22AF003AB672E811ULL,
0xB5635C95FF7296E2ULL, 0xED2DF21216235097ULL,
0x4A29C6465A314CD1ULL, 0xD83CC2687A19255FULL,
0x506C11B9D90E8B1DULL, 0x57277707199B8175ULL,
0xCAF21ECD4377B28CULL, 0xC0C0F5A60EF4CDCFULL,
0x93B633ABFA3469F8ULL, 0xE846963877671A17ULL,
0x59AC2C7873F910A3ULL, 0x660D3257380841EEULL,
0xD813F2FAB7F5C5CAULL, 0x4112CF68649A260EULL,
0x443F64EC5A371195ULL, 0xB0774D261CC609DBULL,
0x720BF5F26F4D2EAAULL, 0x1C2559E30F0946BEULL,
0xE328E230E3E2B3FBULL, 0x087E79E5A57D1D13ULL,
0x08DD9BDFD96B9F63ULL, 0x64D0E29EEA8838B3ULL,
0xDDF957BC36D8B9CAULL, 0x6FFE73E81B637FB3ULL,
0x1A4E4822EB4D7A59ULL, 0x5D94337FBFAF7F5BULL,
0xD30C088BA61EA5EFULL, 0x9D765E419FB69F6DULL,
0x9E21F4F903B33FD9ULL, 0xB4D8F77BC3E56167ULL,
0x733EA705FAE4FA77ULL, 0xA4EC0132764CA04BULL,
0x7976033A39F7D952ULL, 0x106F72FE81E2C590ULL,
0x8C90FD9B083F4558ULL, 0xFD080D236DA814BAULL,
0x7B64978555326F9FULL, 0x60E8ED72C0DFF5D1ULL,
0xB063E962E045F54DULL, 0x959F587D507A8359ULL,
0x758F450C88572E0BULL, 0x1B6BACA2AE4E125BULL,
0x61CF4F94C97DF93DULL, 0x2738259634305C14ULL,
0xD39BB9C3A48DB6CFULL, 0x8215E577001332C8ULL,
0xA1082C0466DF6C0AULL, 0xEF02CDD06FFDB432ULL,
0xFC87614BAF287E07ULL, 0x240AB57A8B888B20ULL,
0xBF8D5108E27E0D48ULL, 0x61BDD1307C66E300ULL,
0xB925A6CD0421AFF3ULL, 0x3E003E616A6591E9ULL,
0x94C3251F06F90CF3ULL, 0xBF84470805E69B5FULL,
0x98F076A4F7A2322EULL, 0x70CB6AF7C2D5BCF0ULL,
0xB64BE8D8B25396C1ULL, 0xA9AA4D20DB084E9BULL,
0x2E6D02C36017F67FULL, 0xEFED53D75FD64E6BULL,
0xD9F1F30CCD97FB09ULL, 0xA2EBEE47E2FBFCE1ULL,
0xB8D91274B9E9D4FBULL, 0x1DB956E450275779ULL,
0x4FC8E9560F91B123ULL, 0x63573FF03E224774ULL,
0x0647DFEDCD894A29ULL, 0x7884D9BC6CB569D8ULL,
0x7FBA195410E5CA30ULL, 0x106C09B972D2E822ULL,
0x241260ED4AD1E87DULL, 0x64C8E531BFF53B55ULL,
0xCA672B91E9E4FA16ULL, 0x3871700761B3F743ULL,
0xF95CFFA23AF5F6F4ULL, 0x8D14DEDB30BE846EULL,
0x3B097ADAF088F94EULL, 0x21E0BD5026C619BFULL,
0x1BDA0492E7E4586EULL, 0xD23C8E176D113600ULL,
0x252F59CF0D9F04BBULL, 0xB3598080CE64A656ULL,
0x993E1DE72D36D310ULL, 0xA2853B80F17F58EEULL,
0x1877B51E57A764D5ULL, 0x001F837CC7350524ULL
};
int main(int _argc,const char *_argv[]){
isaac_ctx isaac;
isaac64_ctx isaac64;
int i;
int j;
/*This is how many tests you plan to run.*/
plan_tests(4);
isaac_init(&isaac,NULL,0);
for(j=0;j<ISAAC_SZ;j++)isaac_next_uint32(&isaac);
for(i=0;i<2;i++){
int nmatches;
nmatches=0;
for(j=0;j<ISAAC_SZ;j++){
nmatches+=isaac_next_uint32(&isaac)==STATEVEC[(i+1)*ISAAC_SZ-j-1];
}
ok1(nmatches==ISAAC_SZ);
}
isaac64_init(&isaac64,NULL,0);
for(j=0;j<ISAAC64_SZ;j++)isaac64_next_uint64(&isaac64);
for(i=0;i<2;i++){
int nmatches;
nmatches=0;
for(j=0;j<ISAAC64_SZ;j++){
nmatches+=isaac64_next_uint64(&isaac64)==STATEVEC64[(i+1)*ISAAC64_SZ-j-1];
}
ok1(nmatches==ISAAC64_SZ);
}
/*TODO: We should test the random float/double routines, but they are not
guaranteed to return the same values on all platforms, because the number
of bits in the mantissa may be different.
Perhaps some simple statistical tests would suffice.*/
return exit_status();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment