diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-07-17 23:07:45 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-07-17 23:07:45 +0000 |
commit | 529e166888905b6ed5998c72148904d141845863 (patch) | |
tree | 8d64f12c8f1eeb273dc4a3151b54e9e1db1d7723 | |
parent | bd44e6019787a9607d3d2e9ca8900df78b8d4e10 (diff) | |
download | rockbox-529e166888905b6ed5998c72148904d141845863.tar.gz rockbox-529e166888905b6ed5998c72148904d141845863.zip |
New vastly improved random algorithm: Mersenne Twister
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1377 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/playlist.c | 18 | ||||
-rw-r--r-- | firmware/common/random.c | 153 | ||||
-rw-r--r-- | firmware/include/stdlib.h | 3 |
3 files changed, 158 insertions, 16 deletions
diff --git a/apps/playlist.c b/apps/playlist.c index 2d8bbd3a33..c74d643c52 100644 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -205,20 +205,6 @@ void add_indices_to_playlist( playlist_info_t *playlist ) | |||
205 | close(fd); | 205 | close(fd); |
206 | } | 206 | } |
207 | 207 | ||
208 | static unsigned int playlist_seed = 0xdeadcafe; | ||
209 | static void seedit(unsigned int seed) | ||
210 | { | ||
211 | playlist_seed = seed; | ||
212 | } | ||
213 | |||
214 | static int getrand(void) | ||
215 | { | ||
216 | playlist_seed += 0x12345; | ||
217 | |||
218 | /* the rand is from 0 to RAND_MAX */ | ||
219 | return playlist_seed; | ||
220 | } | ||
221 | |||
222 | /* | 208 | /* |
223 | * randomly rearrange the array of indices for the playlist | 209 | * randomly rearrange the array of indices for the playlist |
224 | */ | 210 | */ |
@@ -229,14 +215,14 @@ void randomise_playlist( playlist_info_t *playlist, unsigned int seed ) | |||
229 | int store; | 215 | int store; |
230 | 216 | ||
231 | /* seed with the given seed */ | 217 | /* seed with the given seed */ |
232 | seedit( seed ); | 218 | srand( seed ); |
233 | 219 | ||
234 | /* randomise entire indices list */ | 220 | /* randomise entire indices list */ |
235 | 221 | ||
236 | while( count < playlist->amount ) | 222 | while( count < playlist->amount ) |
237 | { | 223 | { |
238 | /* the rand is from 0 to RAND_MAX, so adjust to our value range */ | 224 | /* the rand is from 0 to RAND_MAX, so adjust to our value range */ |
239 | candidate = getrand() % ( playlist->amount ); | 225 | candidate = rand() % playlist->amount; |
240 | 226 | ||
241 | /* now swap the values at the 'count' and 'candidate' positions */ | 227 | /* now swap the values at the 'count' and 'candidate' positions */ |
242 | store = playlist->indices[candidate]; | 228 | store = playlist->indices[candidate]; |
diff --git a/firmware/common/random.c b/firmware/common/random.c new file mode 100644 index 0000000000..1e65eefaa0 --- /dev/null +++ b/firmware/common/random.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * This is the ``Mersenne Twister'' random number generator MT19937, which | ||
3 | * generates pseudorandom integers uniformly distributed in 0..(2^32 - 1) | ||
4 | * starting from any odd seed in 0..(2^32 - 1). This version is a recode | ||
5 | * by Shawn Cokus (Cokus@math.washington.edu) on March 8, 1998 of a version by | ||
6 | * Takuji Nishimura (who had suggestions from Topher Cooper and Marc Rieffel in | ||
7 | * July-August 1997). | ||
8 | * | ||
9 | * Effectiveness of the recoding (on Goedel2.math.washington.edu, a DEC Alpha | ||
10 | * running OSF/1) using GCC -O3 as a compiler: before recoding: 51.6 sec. to | ||
11 | * generate 300 million random numbers; after recoding: 24.0 sec. for the same | ||
12 | * (i.e., 46.5% of original time), so speed is now about 12.5 million random | ||
13 | * number generations per second on this machine. | ||
14 | * | ||
15 | * According to the URL <http://www.math.keio.ac.jp/~matumoto/emt.html> | ||
16 | * (and paraphrasing a bit in places), the Mersenne Twister is ``designed | ||
17 | * with consideration of the flaws of various existing generators,'' has | ||
18 | * a period of 2^19937 - 1, gives a sequence that is 623-dimensionally | ||
19 | * equidistributed, and ``has passed many stringent tests, including the | ||
20 | * die-hard test of G. Marsaglia and the load test of P. Hellekalek and | ||
21 | * S. Wegenkittl.'' It is efficient in memory usage (typically using 2506 | ||
22 | * to 5012 bytes of static data, depending on data type sizes, and the code | ||
23 | * is quite short as well). It generates random numbers in batches of 624 | ||
24 | * at a time, so the caching and pipelining of modern systems is exploited. | ||
25 | * It is also divide- and mod-free. | ||
26 | * | ||
27 | * This library is free software; you can redistribute it and/or modify it | ||
28 | * under the terms of the GNU Library General Public License as published by | ||
29 | * the Free Software Foundation (either version 2 of the License or, at your | ||
30 | * option, any later version). This library is distributed in the hope that | ||
31 | * it will be useful, but WITHOUT ANY WARRANTY, without even the implied | ||
32 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
33 | * the GNU Library General Public License for more details. You should have | ||
34 | * received a copy of the GNU Library General Public License along with this | ||
35 | * library; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
36 | * Place, Suite 330, Boston, MA 02111-1307, USA. | ||
37 | * | ||
38 | * The code as Shawn received it included the following notice: | ||
39 | * | ||
40 | * Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. When | ||
41 | * you use this, send an e-mail to <matumoto@math.keio.ac.jp> with | ||
42 | * an appropriate reference to your work. | ||
43 | * | ||
44 | * It would be nice to CC: <Cokus@math.washington.edu> when you write. | ||
45 | * | ||
46 | */ | ||
47 | |||
48 | #include <stdlib.h> | ||
49 | |||
50 | #define N (624) /* length of state vector */ | ||
51 | #define M (397) /* a period parameter */ | ||
52 | #define K (0x9908B0DFU) /* a magic constant */ | ||
53 | #define hiBit(u) ((u) & 0x80000000U) /* mask all but highest bit of u */ | ||
54 | #define loBit(u) ((u) & 0x00000001U) /* mask all but lowest bit of u */ | ||
55 | #define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ | ||
56 | #define mixBits(u, v) (hiBit(u)|loBits(v)) /* move highest bit of u to | ||
57 | highest bit of v */ | ||
58 | |||
59 | static unsigned int state[N+1]; /* state vector + 1 to not violate ANSI C */ | ||
60 | static unsigned int *next; /* next random value is computed from here */ | ||
61 | static int left = -1; /* can *next++ this many times before reloading */ | ||
62 | |||
63 | void srand(unsigned int seed) | ||
64 | { | ||
65 | /* | ||
66 | * We initialize state[0..(N-1)] via the generator | ||
67 | * | ||
68 | * x_new = (69069 * x_old) mod 2^32 | ||
69 | * | ||
70 | * from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's | ||
71 | * _The Art of Computer Programming_, Volume 2, 3rd ed. | ||
72 | * | ||
73 | * Notes (SJC): I do not know what the initial state requirements | ||
74 | * of the Mersenne Twister are, but it seems this seeding generator | ||
75 | * could be better. It achieves the maximum period for its modulus | ||
76 | * (2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if | ||
77 | * x_initial can be even, you have sequences like 0, 0, 0, ...; | ||
78 | * 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31, | ||
79 | * 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below. | ||
80 | * | ||
81 | * Even if x_initial is odd, if x_initial is 1 mod 4 then | ||
82 | * | ||
83 | * the lowest bit of x is always 1, | ||
84 | * the next-to-lowest bit of x is always 0, | ||
85 | * the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , | ||
86 | * the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... , | ||
87 | * the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... , | ||
88 | * ... | ||
89 | * | ||
90 | * and if x_initial is 3 mod 4 then | ||
91 | * | ||
92 | * the lowest bit of x is always 1, | ||
93 | * the next-to-lowest bit of x is always 1, | ||
94 | * the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , | ||
95 | * the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... , | ||
96 | * the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... , | ||
97 | * ... | ||
98 | * | ||
99 | * The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is | ||
100 | * 16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It | ||
101 | * also does well in the dimension 2..5 spectral tests, but it could be | ||
102 | * better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth). | ||
103 | * | ||
104 | * Note that the random number user does not see the values generated | ||
105 | * here directly since reloadMT() will always munge them first, so maybe | ||
106 | * none of all of this matters. In fact, the seed values made here could | ||
107 | * even be extra-special desirable if the Mersenne Twister theory says | ||
108 | * so-- that's why the only change I made is to restrict to odd seeds. | ||
109 | */ | ||
110 | |||
111 | unsigned int x = (seed | 1U) & 0xFFFFFFFFU, *s = state; | ||
112 | int j; | ||
113 | |||
114 | for(left=0, *s++=x, j=N; --j; | ||
115 | *s++ = (x*=69069U) & 0xFFFFFFFFU); | ||
116 | } | ||
117 | |||
118 | static int rand_reload(void) | ||
119 | { | ||
120 | unsigned int *p0=state, *p2=state+2, *pM=state+M, s0, s1; | ||
121 | int j; | ||
122 | |||
123 | if(left < -1) | ||
124 | srand(4357U); | ||
125 | |||
126 | left=N-1, next=state+1; | ||
127 | |||
128 | for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++) | ||
129 | *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); | ||
130 | |||
131 | for(pM=state, j=M; --j; s0=s1, s1=*p2++) | ||
132 | *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); | ||
133 | |||
134 | s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); | ||
135 | s1 ^= (s1 >> 11); | ||
136 | s1 ^= (s1 << 7) & 0x9D2C5680U; | ||
137 | s1 ^= (s1 << 15) & 0xEFC60000U; | ||
138 | return (int)s1 ^ (s1 >> 18); | ||
139 | } | ||
140 | |||
141 | int rand(void) | ||
142 | { | ||
143 | int y; | ||
144 | |||
145 | if(--left < 0) | ||
146 | return rand_reload(); | ||
147 | |||
148 | y = *next++; | ||
149 | y ^= (y >> 11); | ||
150 | y ^= (y << 7) & 0x9D2C5680U; | ||
151 | y ^= (y << 15) & 0xEFC60000U; | ||
152 | return (y ^ (y >> 18)) & ((2^31)-1); /* 31-bit limit by Björn Stenberg*/ | ||
153 | } | ||
diff --git a/firmware/include/stdlib.h b/firmware/include/stdlib.h index 40b5207223..9076bc25d2 100644 --- a/firmware/include/stdlib.h +++ b/firmware/include/stdlib.h | |||
@@ -30,6 +30,9 @@ void *calloc (size_t nmemb, size_t size); | |||
30 | void free(void *); | 30 | void free(void *); |
31 | void *realloc(void *, size_t); | 31 | void *realloc(void *, size_t); |
32 | 32 | ||
33 | void srand(unsigned int seed); | ||
34 | int rand(void); | ||
35 | |||
33 | #define abs(x) ((x)>0?(x):-(x)) | 36 | #define abs(x) ((x)>0?(x):-(x)) |
34 | 37 | ||
35 | #ifdef __cplusplus | 38 | #ifdef __cplusplus |