1 //metadoc Random copyright Steve Dekorte 2002
2 //metadoc Random license BSD revised
3 /*metadoc Random description
4 A high quality and reasonably fast random number generator based on
5 Makoto Matsumoto, Takuji Nishimura, and Eric Landry's implementation
6 of the Mersenne Twister algorithm. The default seed is and xor of
7 the ANSI C time() and clock() return values.
12 M. Matsumoto and T. Nishimura, <br>
13 "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-RandomGen Number
15 ACM Transactions on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3--30.
18 //metadoc Random category Math")
22 #include "RandomGen.h"
25 #define DATA(self) ((RandomGen *)(IoObject_dataPointer(self)))
27 void IoRandom_writeToStream_(IoRandom
*self
, BStream
*stream
)
29 RandomGen
*r
= DATA(self
);
32 for (i
= 0; i
< RANDOMGEN_N
; i
++)
34 BStream_writeTaggedUint32_(stream
, r
->mt
[i
]);
37 BStream_writeTaggedUint32_(stream
, r
->mti
);
40 void *IoRandom_readFromStream(IoRandom
*self
, BStream
*stream
)
42 RandomGen
*r
= DATA(self
);
45 for (i
= 0; i
< RANDOMGEN_N
; i
++)
47 r
->mt
[i
] = BStream_readTaggedUint32(stream
);
50 r
->mti
= BStream_readTaggedUint32(stream
);
54 IoTag
*IoRandom_newTag(void *state
)
56 IoTag
*tag
= IoTag_newWithName_("Random");
57 IoTag_state_(tag
, state
);
58 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoRandom_rawClone
);
59 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoRandom_free
);
60 //IoTag_writeToStreamFunc_(tag, (IoTagWriteToStreamFunc *)IoRandom_writeToStream);
61 //IoTag_readFromStreamFunc_(tag, (IoTagReadFromStreamFunc *)IoRandom_readFromStream);
65 IoRandom
*IoRandom_proto(void *state
)
67 IoMethodTable methodTable
[] = {
68 {"value", IoRandom_value
},
69 {"setSeed", IoRandom_setSeed
},
70 {"flip", IoRandom_flip
},
71 {"gaussian", IoRandom_gaussian
},
72 {"bytes", IoRandom_bytes
},
76 IoObject
*self
= IoObject_new(state
);
78 IoObject_tag_(self
, IoRandom_newTag(state
));
79 IoObject_setDataPointer_(self
, RandomGen_new());
81 RandomGen_chooseRandomSeed(DATA(self
));
83 IoState_registerProtoWithFunc_((IoState
*)state
, self
, IoRandom_proto
);
85 IoObject_addMethodTable_(self
, methodTable
);
89 IoNumber
*IoRandom_rawClone(IoRandom
*proto
)
91 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
92 IoObject_setDataPointer_(self
, RandomGen_new());
93 //RandomGen_chooseRandomSeed(DATA(self));
97 void IoRandom_free(IoMessage
*self
)
99 RandomGen_free(DATA(self
));
102 IoObject
*IoRandom_flip(IoObject
*self
, IoObject
*locals
, IoMessage
*m
)
104 int r
= RandomGen_randomInt(DATA(self
));
105 return IOBOOL(self
, r
& 0x1);
108 IoObject
*IoRandom_value(IoObject
*self
, IoObject
*locals
, IoMessage
*m
)
110 /*doc Random value(optionalArg1, optionalArg2)
113 <li> no arguments, it returns a floating point
114 random Number between 0 and 1.
115 <li> one argument, it returns a floating point random
116 Number between 0 and optionalArg1.
117 <li> two arguments, it returns a floating point random
118 Number between optionalArg1 and optionalArg2.
122 double f
= RandomGen_randomDouble(DATA(self
));
125 if (IoMessage_argCount(m
) > 0)
127 double a
= IoMessage_locals_doubleArgAt_(m
, locals
, 0);
129 if (IoMessage_argCount(m
) > 1)
131 double b
= IoMessage_locals_doubleArgAt_(m
, locals
, 1);
139 result
= a
+ (b
- a
) * f
;
159 return IONUMBER(result
);
162 IoObject
*IoRandom_setSeed(IoObject
*self
, IoObject
*locals
, IoMessage
*m
)
164 /*doc Random setSeed(aNumber)
165 Sets the random number generator seed to the unsign int version of aNumber.
168 unsigned long v
= IoMessage_locals_longArgAt_(m
, locals
, 0);
169 RandomGen_setSeed(DATA(self
), v
);
173 IoObject
*IoRandom_gaussian(IoObject
*self
, IoObject
*locals
, IoMessage
*m
)
175 /*doc Random gaussian(optionalMean, optionalStandardDeviation)
176 Returns a pseudo random number between 0 and 1 with a gaussian distribution.
180 double standardDeviation
= 1;
182 if (IoMessage_argCount(m
) > 0)
184 mean
= IoMessage_locals_doubleArgAt_(m
, locals
, 0);
187 if (IoMessage_argCount(m
) > 1)
189 standardDeviation
= IoMessage_locals_doubleArgAt_(m
, locals
, 1);
192 return IONUMBER(RandomGen_gaussian(DATA(self
), mean
, standardDeviation
));
195 IoObject
*IoRandom_bytes(IoObject
*self
, IoObject
*locals
, IoMessage
*m
)
197 /*doc Random bytes(count)
198 Returns a Sequence of size count containing random bytes.
201 size_t i
, count
= IoMessage_locals_sizetArgAt_(m
, locals
, 0);
203 uint8_t *d
= malloc(count
);
205 for(i
= 0; i
< count
; i
++)
207 d
[i
] = (uint8_t)(RandomGen_randomInt(DATA(self
)) & 255);
210 a
= UArray_newWithData_type_size_copy_(d
, CTYPE_uint8_t
, count
, 0);
211 UArray_setEncoding_(a
, CENCODING_NUMBER
);
213 return IoSeq_newWithUArray_copy_(IOSTATE
, a
, 0);