Addons updated to new doc format
[io.git] / addons / Random / source / IoRandom.c
blob99d6b2fb1afc221c675ee81ccdc30ef75e6bad52
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.
8 <p>
9 Reference:
10 <p>
11 <i>
12 M. Matsumoto and T. Nishimura, <br>
13 "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-RandomGen Number
14 Generator", <br>
15 ACM Transactions on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3--30.
16 </i>
18 //metadoc Random category Math")
20 #include "IoRandom.h"
21 #include "IoNumber.h"
22 #include "RandomGen.h"
23 #include "BStream.h"
25 #define DATA(self) ((RandomGen *)(IoObject_dataPointer(self)))
27 void IoRandom_writeToStream_(IoRandom *self, BStream *stream)
29 RandomGen *r = DATA(self);
30 int i;
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);
43 int i;
45 for (i = 0; i < RANDOMGEN_N; i ++)
47 r->mt[i] = BStream_readTaggedUint32(stream);
50 r->mti = BStream_readTaggedUint32(stream);
51 return self;
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);
62 return tag;
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},
73 {NULL, NULL},
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);
86 return self;
89 IoNumber *IoRandom_rawClone(IoRandom *proto)
91 IoObject *self = IoObject_rawClonePrimitive(proto);
92 IoObject_setDataPointer_(self, RandomGen_new());
93 //RandomGen_chooseRandomSeed(DATA(self));
94 return 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)
111 If called with:
112 <ul>
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.
119 </ul>
122 double f = RandomGen_randomDouble(DATA(self));
123 double result = 0;
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);
133 if (a == b )
135 result = a;
137 else
139 result = a + (b - a) * f;
142 else
144 if (a == 0)
146 result = 0;
148 else
150 result = a * f;
154 else
156 result = 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);
170 return self;
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.
179 double mean = 0;
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);
202 UArray *a;
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);