RSS

(root)/iphone/common : /source/MersenneTwister.m (revision 100)

To get this branch, use:
bzr branch /browse/iphone/common
Line Revision Contents
1 13
//
2
//  MersenneTwister.m
3
//
4
5
/*
6
 * Copyright (c) 2005-2008 Doemoetoer Gulyas
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 * 3. The name of the author may not be used to endorse or promote products
18
 *    derived from this software without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
 */
31
32
#import "MersenneTwister.h"
33
34
/* Period parameters */  
35
#define N 624
36
#define M 397
37
#define MATRIX_A 0x9908b0df   /* constant vector a */
38
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
39
#define LOWER_MASK 0x7fffffff /* least significant r bits */
40
41
/* Tempering parameters */   
42
#define TEMPERING_MASK_B 0x9d2c5680
43
#define TEMPERING_MASK_C 0xefc60000
44
#define TEMPERING_SHIFT_U(y)  (y >> 11)
45
#define TEMPERING_SHIFT_S(y)  (y << 7)
46
#define TEMPERING_SHIFT_T(y)  (y << 15)
47
#define TEMPERING_SHIFT_L(y)  (y >> 18)
48
49
#define MERSENNE_MAX 0xffffffff
50
51
void InitMTWisterCWithSeed(MTwisterC* mtwist, unsigned int seed)
52
{
53
54
	mtwist->mt = (unsigned int*) malloc(sizeof(unsigned int)*N);
55
	unsigned int* mt = mtwist->mt;
56
	int mti = 0;
57
58
	/* setting initial seeds to mt[N] using         */
59
	/* the generator Line 25 of Table 1 in          */
60
	/* [KNUTH 1981, The Art of Computer Programming */
61
	/*    Vol. 2 (2nd Ed.), pp102]                  */
62
	mt[0]= seed & MERSENNE_MAX;
63
	for (mti=1; mti<N; mti++)
64
		mt[mti] = (69069 * mt[mti-1]) & MERSENNE_MAX;
65
	mtwist->mti = mti;
66
}
67
68
void InitMTwisterC(MTwisterC* mtwist)
69
{
70
	InitMTWisterCWithSeed(mtwist, [NSDate timeIntervalSinceReferenceDate]);
71
}
72
void DeallocMTwisterC(MTwisterC* mtwist)
73
{
74
	free(mtwist->mt);
75
	mtwist->mt = NULL;
76
}
77
78
void MTwisterCRefill(int mti, unsigned int* mt)
79
{
80
    unsigned int y;
81
	static unsigned int mag01[2] = {0x0, MATRIX_A};
82
    
83
	/* mag01[x] = x * MATRIX_A  for x=0,1 */// generate N words at one time 
84
    int kk;
85
86
/*		if (mti == N+1)		// if sgenrand() has not been called,
87
        sgenrand(4357); // a default initial seed is used
88
*/
89
    for (kk = 0; kk < N-M; kk++)
90
    {
91
        y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
92
        mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
93
    };
94
    for (; kk < N-1; kk++)
95
    {
96
        y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
97
        mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
98
    };
99
    y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
100
    mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
101
102
    mti = 0;
103
}
104
105
@implementation MersenneTwister
106
107
- (id) init
108
{
109
	return [self initWithSeed: [NSDate timeIntervalSinceReferenceDate]];
110
}
111
112
- (id) initWithSeed: (unsigned int) seed
113
{
114
	if (!(self = [super init]))
115
		return nil;
116
117
	mt = (unsigned int*) malloc(sizeof(unsigned int)*N);
118
	NSAssert(mt, @"malloc borked out");
119
120
	/* setting initial seeds to mt[N] using         */
121
	/* the generator Line 25 of Table 1 in          */
122
	/* [KNUTH 1981, The Art of Computer Programming */
123
	/*    Vol. 2 (2nd Ed.), pp102]                  */
124
	mt[0]= seed & MERSENNE_MAX;
125
	for (mti=1; mti<N; mti++)
126
		mt[mti] = (69069 * mt[mti-1]) & MERSENNE_MAX;
127
	
128
	return self;
129
}
130
- (void) dealloc
131
{
132
	free(mt);
133
}
134
135
- (unsigned int) randomNumber
136
{
137
	unsigned int y;
138
	static unsigned int mag01[2] = {0x0, MATRIX_A};
139
	/* mag01[x] = x * MATRIX_A  for x=0,1 */
140
141
	if (mti >= N)
142
	{   // generate N words at one time 
143
		int kk;
144
145
/*		if (mti == N+1)		// if sgenrand() has not been called,
146
			sgenrand(4357); // a default initial seed is used
147
*/
148
		for (kk = 0; kk < N-M; kk++)
149
		{
150
			y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
151
			mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
152
		};
153
		for (; kk < N-1; kk++)
154
		{
155
			y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
156
			mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
157
		};
158
		y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
159
		mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
160
161
		mti = 0;
162
	}
163
  
164
	y = mt[mti++];
165
	y ^= TEMPERING_SHIFT_U(y);
166
	y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
167
	y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
168
	y ^= TEMPERING_SHIFT_L(y);
169
170
	return y;
171
}
172
173
- (double) randomDoubleWithCeiling: (double) ceiling
174
{
175
	unsigned int	rnd = [self randomNumber];
176
	return (((double)rnd)/((double)MERSENNE_MAX))*ceiling;
177
}
178 25
179
- (float) randomFloatWithCeiling: (float) ceiling
180
{
181
	unsigned int	rnd = [self randomNumber];
182
	return (((float)rnd)/((float)MERSENNE_MAX))*ceiling;
183
}
184
185 13
- (double) randomDoubleWithFloor: (double) floor ceiling: (double) ceiling
186
{
187
	double	rnd = [self randomDoubleWithCeiling: ceiling - floor];
188
	return floor + rnd;
189
}
190
191 25
- (float) randomFloatWithFloor: (float) floor ceiling: (float) ceiling
192
{
193
	float	rnd = [self randomFloatWithCeiling: ceiling - floor];
194
	return floor + rnd;
195
}
196
197 13
- (unsigned int) randomIntWithFloor: (unsigned int) floor ceiling: (unsigned int) ceiling
198
{
199
	unsigned int	rnd = [self randomNumber];
200
	return floor + (rnd % (ceiling - floor + 1));
201
}
202
203
- (unsigned int) randMax
204
{
205
	return MERSENNE_MAX;
206
}
207
208
+ (id) sharedTwister
209
{
210
	static id twister = nil;
211
	if (!twister)
212
	{
213
		twister = [[MersenneTwister alloc] init];
214
	}
215
	return twister;
216
}
217
218
@end

Loggerhead 1.17 is a web-based interface for Bazaar branches