/src/openbabel/src/rand.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | rand.cpp - Pseudo random number generator. |
3 | | |
4 | | Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc. |
5 | | Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison |
6 | | |
7 | | This file is part of the Open Babel project. |
8 | | For more information, see <http://openbabel.org/> |
9 | | |
10 | | This program is free software; you can redistribute it and/or modify |
11 | | it under the terms of the GNU General Public License as published by |
12 | | the Free Software Foundation version 2 of the License. |
13 | | |
14 | | This program is distributed in the hope that it will be useful, |
15 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | GNU General Public License for more details. |
18 | | ***********************************************************************/ |
19 | | |
20 | | /* derived from sample.c |
21 | | * Pseudo-Random Number Generator Generator |
22 | | * Roger Sayle, Metaphorics LLC |
23 | | * Version 1.2, September 1998 |
24 | | */ |
25 | | #include <openbabel/babelconfig.h> |
26 | | |
27 | | #include <cstdlib> |
28 | | #include <cstdio> |
29 | | #include <cmath> |
30 | | #include <limits> |
31 | | |
32 | | #include "rand.h" |
33 | | |
34 | | #if TIME_WITH_SYS_TIME |
35 | | #include <sys/time.h> |
36 | | #include <time.h> |
37 | | #else |
38 | | #if HAVE_SYS_TIME_H |
39 | | #include <sys/time.h> |
40 | | #else |
41 | | #include <time.h> |
42 | | #endif |
43 | | #endif |
44 | | |
45 | | #ifndef True |
46 | 0 | #define True 1 |
47 | 0 | #define False 0 |
48 | | #endif |
49 | | |
50 | 0 | #define IsEven(x) (((x)&1)==0) |
51 | | #define IsOdd(x) (((x)&1)!=0) |
52 | | |
53 | 0 | #define BothEven(x,y) IsEven((x)|(y)) |
54 | | #define IsPrime(x) (!IsEven((x))&&IsOddPrime((x))) |
55 | | |
56 | 0 | #define HiPart(x) (x>>16) |
57 | 0 | #define LoPart(x) ((x)&0xffff) |
58 | | |
59 | | /* The maximum number of unique prime factors of a 32 bit number */ |
60 | | /* 2*3*5*7*11*13*17*19*23*29 = 6469693230 > 2^32 = 4294967296 */ |
61 | | #define MAXFACT 10 |
62 | | |
63 | | namespace OpenBabel |
64 | | { |
65 | 0 | #define MAXPRIMES 256 |
66 | | static int primes[MAXPRIMES] = { |
67 | | 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, |
68 | | 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, |
69 | | 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, |
70 | | 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, |
71 | | 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, |
72 | | 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, |
73 | | 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, |
74 | | 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, |
75 | | 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, |
76 | | 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, |
77 | | 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, |
78 | | 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, |
79 | | 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, |
80 | | 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, |
81 | | 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, |
82 | | 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, |
83 | | 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, |
84 | | 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, |
85 | | 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, |
86 | | 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, |
87 | | 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, |
88 | | 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, |
89 | | 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, |
90 | | 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, |
91 | | 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, |
92 | | 1583, 1597, 1601, 1607, 1609, 1613 |
93 | | }; |
94 | | |
95 | | static unsigned int isqrt( unsigned int val ) |
96 | 0 | { |
97 | 0 | unsigned int temp; |
98 | 0 | unsigned int rem; |
99 | 0 | int i,result; |
100 | |
|
101 | 0 | i = 16; |
102 | 0 | while( !(val&((unsigned int)3<<30)) && i ) |
103 | 0 | { |
104 | 0 | val <<= 2; |
105 | 0 | i--; |
106 | 0 | } |
107 | |
|
108 | 0 | if( i ) |
109 | 0 | { |
110 | 0 | rem = (val>>30)-1; |
111 | 0 | val <<= 2; |
112 | 0 | result = 1; |
113 | 0 | i--; |
114 | |
|
115 | 0 | while( i ) |
116 | 0 | { |
117 | 0 | rem = (rem<<2) | (val>>30); |
118 | 0 | result <<= 1; |
119 | 0 | val <<= 2; |
120 | |
|
121 | 0 | temp = result<<1; |
122 | 0 | if( rem > temp ) |
123 | 0 | { |
124 | 0 | rem -= temp|1; |
125 | 0 | result |= 1; |
126 | 0 | } |
127 | 0 | i--; |
128 | 0 | } |
129 | 0 | return result; |
130 | 0 | } |
131 | 0 | else |
132 | 0 | return 0; |
133 | 0 | } |
134 | | |
135 | | static int IsOddPrime( unsigned int x ) |
136 | 0 | { |
137 | 0 | unsigned int root; |
138 | 0 | unsigned int i; |
139 | |
|
140 | 0 | root = isqrt(x); |
141 | 0 | for( i=2; i<MAXPRIMES-1; i++ ) |
142 | 0 | { |
143 | 0 | if( (x%primes[i]) == 0 ) |
144 | 0 | return False; |
145 | 0 | if( (unsigned int) primes[i] >= root ) |
146 | 0 | return True; |
147 | 0 | } |
148 | | |
149 | 0 | for( i=primes[MAXPRIMES-1]; i<=root; i+=2 ) |
150 | 0 | if( (x%i) == 0 ) |
151 | 0 | return False; |
152 | 0 | return True; |
153 | 0 | } |
154 | | |
155 | | static int RelativelyPrime( unsigned int x, unsigned int y ) |
156 | 0 | { |
157 | 0 | if( BothEven(x,y) ) |
158 | 0 | return False; |
159 | | |
160 | 0 | if( IsEven(x) ) |
161 | 0 | { |
162 | 0 | do |
163 | 0 | { |
164 | 0 | x >>= 1; |
165 | 0 | } |
166 | 0 | while( IsEven(x) ); |
167 | 0 | } |
168 | 0 | else |
169 | 0 | while( IsEven(y) ) |
170 | 0 | y >>= 1; |
171 | |
|
172 | 0 | while( x != y ) |
173 | 0 | { |
174 | 0 | if( x > y ) |
175 | 0 | { |
176 | 0 | x -= y; |
177 | 0 | do |
178 | 0 | { |
179 | 0 | x >>= 1; |
180 | 0 | } |
181 | 0 | while( IsEven(x) ); |
182 | 0 | } |
183 | 0 | else if( x < y ) |
184 | 0 | { |
185 | 0 | y -= x; |
186 | 0 | do |
187 | 0 | { |
188 | 0 | y >>= 1; |
189 | 0 | } |
190 | 0 | while( IsEven(y) ); |
191 | 0 | } |
192 | 0 | } |
193 | 0 | return( x == 1 ); |
194 | 0 | } |
195 | | |
196 | | static void DoubleAdd( DoubleType *x, unsigned int y ) |
197 | 0 | { |
198 | 0 | x->lo += y; |
199 | 0 | if( x->lo < y ) |
200 | 0 | x->hi++; |
201 | 0 | } |
202 | | |
203 | | static void DoubleMultiply( unsigned int x, unsigned int y, DoubleType *z ) |
204 | 0 | { |
205 | 0 | unsigned int x0, x1, x2, x3; |
206 | 0 | unsigned int hx, lx; |
207 | 0 | unsigned int hy, ly; |
208 | |
|
209 | 0 | hx = HiPart(x); |
210 | 0 | lx = LoPart(x); |
211 | 0 | hy = HiPart(y); |
212 | 0 | ly = LoPart(y); |
213 | |
|
214 | 0 | x0 = lx*ly; |
215 | 0 | x1 = lx*hy; |
216 | 0 | x2 = hx*ly; |
217 | 0 | x3 = hx*hy; |
218 | |
|
219 | 0 | x1 += HiPart(x0); |
220 | 0 | x1 += x2; |
221 | 0 | if( x1 < x2 ) |
222 | 0 | x3 += (1<<16); |
223 | |
|
224 | 0 | z->hi = HiPart(x1) + x3; |
225 | 0 | z->lo = (LoPart(x1)<<16) + LoPart(x0); |
226 | 0 | } |
227 | | |
228 | | static int LeadingZeros( unsigned int x ) |
229 | 0 | { |
230 | 0 | static int table[256] = { |
231 | 0 | 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, |
232 | 0 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, |
233 | 0 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, |
234 | 0 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, |
235 | 0 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, |
236 | 0 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, |
237 | 0 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, |
238 | 0 | 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 |
239 | 0 | }; |
240 | |
|
241 | 0 | if( x >= (1<<16) ) |
242 | 0 | { |
243 | 0 | if( x >= (1<<24) ) |
244 | 0 | { |
245 | 0 | return 8-table[x>>24]; |
246 | 0 | } |
247 | 0 | else |
248 | 0 | return 16-table[x>>16]; |
249 | 0 | } |
250 | 0 | else if( x >= (1<<8) ) |
251 | 0 | { |
252 | 0 | return 24-table[x>>8]; |
253 | 0 | } |
254 | 0 | else |
255 | 0 | return 32-table[x]; |
256 | 0 | } |
257 | | |
258 | | static unsigned int DoubleModulus( DoubleType *n, unsigned int d ) |
259 | 0 | { |
260 | 0 | unsigned int d1, d0; |
261 | 0 | unsigned int r1, r0; |
262 | 0 | unsigned int m,s; |
263 | |
|
264 | 0 | s = LeadingZeros(d); |
265 | 0 | if( s > 0 ) |
266 | 0 | { |
267 | 0 | d = d<<s; |
268 | 0 | n->hi = (n->hi<<s) | (n->lo>>(32-s)); |
269 | 0 | n->lo = n->lo << s; |
270 | 0 | } |
271 | |
|
272 | 0 | d1 = HiPart(d); |
273 | 0 | d0 = LoPart(d); |
274 | |
|
275 | 0 | m = ((unsigned int)(n->hi/d1)) * d0; |
276 | 0 | r1 = ((n->hi%d1)<<16) + HiPart(n->lo); |
277 | 0 | if( r1 < m ) |
278 | 0 | { |
279 | 0 | r1 += d; |
280 | 0 | if( (r1>=d) && (r1<m) ) |
281 | 0 | r1 += d; |
282 | 0 | } |
283 | 0 | r1 -= m; |
284 | |
|
285 | 0 | m = ((unsigned int)(r1/d1)) * d0; |
286 | 0 | r0 = ((r1%d1)<<16) + LoPart(n->lo); |
287 | 0 | if( r0 < m ) |
288 | 0 | { |
289 | 0 | r0 += d; |
290 | 0 | if( (r0>=d) && (r0<m) ) |
291 | 0 | r0 += d; |
292 | 0 | } |
293 | 0 | r0 -= m; |
294 | |
|
295 | 0 | return r0 >> s; |
296 | 0 | } |
297 | | |
298 | | static int DeterminePotency( unsigned int m, unsigned int a ) |
299 | 0 | { |
300 | 0 | DoubleType d; |
301 | 0 | unsigned int k; |
302 | 0 | unsigned int b; |
303 | 0 | int s; |
304 | |
|
305 | 0 | b = a-1; |
306 | 0 | k = b; |
307 | 0 | s = 1; |
308 | 0 | while( (k!=0) && (s<100) ) |
309 | 0 | { |
310 | 0 | DoubleMultiply(k,b,&d); |
311 | 0 | k = DoubleModulus(&d,m); |
312 | 0 | s++; |
313 | 0 | } |
314 | 0 | return s; |
315 | 0 | } |
316 | | |
317 | | static int DetermineFactors( unsigned int x, unsigned int *factors ) |
318 | 0 | { |
319 | 0 | unsigned int *ptr; |
320 | 0 | unsigned int half; |
321 | 0 | unsigned int i; |
322 | |
|
323 | 0 | half = x/2; |
324 | 0 | ptr = factors; |
325 | 0 | for( i=1; i<MAXPRIMES; i++ ) |
326 | 0 | { |
327 | 0 | if( (x%primes[i]) == 0 ) |
328 | 0 | *ptr++ = primes[i]; |
329 | 0 | if( (unsigned int)(primes[i]) >= half ) |
330 | 0 | return ptr-factors; |
331 | 0 | } |
332 | | |
333 | 0 | for( i=primes[MAXPRIMES-1]+2; i<=half; i+=2 ) |
334 | 0 | if( IsOddPrime(i) && ((x%i)==0) ) |
335 | 0 | *ptr++ = i; |
336 | 0 | return ptr-factors; |
337 | 0 | } |
338 | | |
339 | | static unsigned int DetermineIncrement( unsigned int m ) |
340 | 0 | { |
341 | 0 | unsigned int hi,lo; |
342 | 0 | unsigned int half; |
343 | 0 | unsigned int i; |
344 | | |
345 | | /* 1/2 + sqrt(3)/6 */ |
346 | 0 | hi = (int)floor(0.7886751345948*m+0.5); |
347 | 0 | if( RelativelyPrime(m,hi) ) |
348 | 0 | return hi; |
349 | | |
350 | | /* 1/2 - sqrt(3)/6 */ |
351 | 0 | lo = (int)floor(0.2113248654052*m+0.5); |
352 | 0 | if( RelativelyPrime(m,lo) ) |
353 | 0 | return lo; |
354 | | |
355 | 0 | half = m/2; |
356 | 0 | for( i=1; i<half; i++ ) |
357 | 0 | { |
358 | 0 | if( RelativelyPrime(m,hi+i) ) |
359 | 0 | return hi+i; |
360 | 0 | if( RelativelyPrime(m,hi-i) ) |
361 | 0 | return hi-i; |
362 | 0 | if( RelativelyPrime(m,lo+i) ) |
363 | 0 | return lo+i; |
364 | 0 | if( RelativelyPrime(m,lo-i) ) |
365 | 0 | return lo-i; |
366 | 0 | } |
367 | 0 | return 1; |
368 | 0 | } |
369 | | |
370 | | static int DetermineSequence( unsigned int m, unsigned int *pm, |
371 | | unsigned int *pa, |
372 | | unsigned int *pc ) |
373 | 0 | { |
374 | 0 | unsigned int fact[MAXFACT]; |
375 | 0 | unsigned int a=0, c; |
376 | 0 | unsigned int b; |
377 | 0 | int pot,best; |
378 | 0 | int count; |
379 | 0 | int flag; |
380 | 0 | int i; |
381 | |
|
382 | 0 | do |
383 | 0 | { |
384 | 0 | best = 0; |
385 | |
|
386 | 0 | count = DetermineFactors(m,fact); |
387 | 0 | if( (m&3) == 0 ) |
388 | 0 | fact[0] = 4; |
389 | |
|
390 | 0 | if( count ) |
391 | 0 | { |
392 | 0 | for( b=m-2; b>0; b-- ) |
393 | 0 | { |
394 | 0 | flag = True; |
395 | 0 | for( i=0; i<count; i++ ) |
396 | 0 | if( b%fact[i] ) |
397 | 0 | { |
398 | 0 | flag = False; |
399 | 0 | break; |
400 | 0 | } |
401 | |
|
402 | 0 | if( flag ) |
403 | 0 | { |
404 | 0 | pot = DeterminePotency(m,b+1); |
405 | 0 | if( pot > best ) |
406 | 0 | { |
407 | 0 | best = pot; |
408 | 0 | a = b+1; |
409 | 0 | } |
410 | 0 | } |
411 | 0 | } |
412 | |
|
413 | 0 | } |
414 | |
|
415 | 0 | m++; |
416 | 0 | } |
417 | 0 | while( best < 3 ); |
418 | 0 | m--; |
419 | |
|
420 | 0 | c = DetermineIncrement(m); |
421 | |
|
422 | 0 | *pm = m; |
423 | 0 | *pa = a; |
424 | 0 | *pc = c; |
425 | 0 | return best; |
426 | 0 | } |
427 | | |
428 | | |
429 | | static void GenerateSequence( unsigned int p, unsigned int m, |
430 | | unsigned int a, unsigned int c ) |
431 | 0 | { |
432 | 0 | unsigned int i; |
433 | 0 | unsigned int x; |
434 | 0 | DoubleType d; |
435 | 0 |
|
436 | 0 | x = 0; /* seed */ |
437 | 0 | for( i=0; i<p; i++ ) |
438 | 0 | { |
439 | 0 | // printf("%u\n",x); |
440 | 0 |
|
441 | 0 | do |
442 | 0 | { |
443 | 0 | DoubleMultiply(a,x,&d); |
444 | 0 | DoubleAdd(&d,c); |
445 | 0 | x = DoubleModulus(&d,m); |
446 | 0 | } |
447 | 0 | while( x >= p ); |
448 | 0 | } |
449 | 0 | } |
450 | | |
451 | | //********************************************** |
452 | | //***** Member functions from Random class ***** |
453 | | //********************************************** |
454 | | |
455 | | OBRandom::OBRandom(bool useSysRand) |
456 | 0 | { |
457 | |
|
458 | 0 | this->OBRandomUseSysRand= useSysRand; |
459 | 0 | p = 70092; |
460 | 0 | DetermineSequence(p,&m,&a,&c); |
461 | 0 | x = 0; /* seed */ |
462 | |
|
463 | 0 | if (useSysRand) |
464 | 0 | this->TimeSeed(); |
465 | 0 | } |
466 | | |
467 | | int OBRandom::NextInt() |
468 | 0 | { |
469 | 0 | if (OBRandomUseSysRand) |
470 | 0 | { |
471 | 0 | return(rand()); |
472 | 0 | } |
473 | 0 | do |
474 | 0 | { |
475 | 0 | DoubleMultiply(a,x,&d); |
476 | 0 | DoubleAdd(&d,c); |
477 | 0 | x = DoubleModulus(&d,m); |
478 | 0 | } |
479 | 0 | while( x >= p ); |
480 | |
|
481 | 0 | return(x); |
482 | 0 | } |
483 | | |
484 | | double OBRandom::NextFloat() |
485 | 0 | { |
486 | |
|
487 | 0 | if (OBRandomUseSysRand) |
488 | 0 | { |
489 | 0 | return(double(rand())/double(RAND_MAX)); |
490 | 0 | } |
491 | 0 | do |
492 | 0 | { |
493 | 0 | DoubleMultiply(a,x,&d); |
494 | 0 | DoubleAdd(&d,c); |
495 | 0 | x = DoubleModulus(&d,m); |
496 | 0 | } |
497 | 0 | while( x >= p ); |
498 | |
|
499 | 0 | return((double)x/p); |
500 | 0 | } |
501 | | |
502 | | void OBRandom::TimeSeed() |
503 | 0 | { |
504 | | #ifdef WIN32 |
505 | | // for VC++ do it this way |
506 | | time_t ltime; |
507 | | time(<ime); |
508 | | const long secs= long(ltime); |
509 | | x= secs % p; |
510 | | srand( (unsigned)time( NULL ) ); |
511 | | #else |
512 | |
|
513 | 0 | timeval time; |
514 | 0 | gettimeofday(&time, (struct timezone *)nullptr); |
515 | 0 | x = (time.tv_usec%p); |
516 | 0 | srand( x ); |
517 | | #ifdef HAVE_SRANDDEV |
518 | | sranddev(); |
519 | | #endif |
520 | |
|
521 | 0 | #endif |
522 | 0 | } |
523 | | |
524 | 0 | double OBRandom::Normal(double mu, double sigma) { |
525 | 0 | const int n = 12; |
526 | 0 | double z = -0.5 * n; |
527 | 0 | for (int _ = 0; _ < n; _++) { |
528 | 0 | z += NextFloat(); |
529 | 0 | } |
530 | 0 | return mu + z * sigma; |
531 | 0 | } |
532 | | |
533 | 0 | bool OBRandom::Bernoulli(double p) { |
534 | 0 | return UniformReal(0.0, 1.0) <= p; |
535 | 0 | } |
536 | | |
537 | 0 | uint_fast64_t OBRandomMT::randomSeed() const { |
538 | 0 | auto ob_random_seed = std::getenv("OB_RANDOM_SEED"); |
539 | 0 | if (ob_random_seed && ob_random_seed[0] != '\0') { |
540 | 0 | return std::atol(ob_random_seed); |
541 | 0 | } |
542 | | #if defined(WIN32) || defined(__MINGW32__) |
543 | | // for VC++ do it this way |
544 | | time_t ltime; |
545 | | time(<ime); |
546 | | return ltime; |
547 | | #else |
548 | 0 | return std::random_device{}(); |
549 | 0 | #endif |
550 | 0 | } |
551 | | |
552 | 0 | int OBRandomMT::NextInt() const { |
553 | 0 | return UniformInt(0, std::numeric_limits<int>::max()); |
554 | 0 | } |
555 | | |
556 | 0 | double OBRandomMT::NextFloat() const { |
557 | 0 | return UniformReal(0.0, 1.0); |
558 | 0 | } |
559 | | |
560 | 0 | double OBRandomMT::Normal(double mu, double sigma) const { |
561 | 0 | std::normal_distribution<double> n{mu, sigma}; |
562 | 0 | return n(*prng); |
563 | 0 | } |
564 | | |
565 | 0 | bool OBRandomMT::Bernoulli(double p) const { |
566 | 0 | std::bernoulli_distribution b{p}; |
567 | 0 | return b(*prng); |
568 | 0 | } |
569 | | |
570 | | } //end namespace OpenBabel |
571 | | |
572 | | //! \file rand.cpp |
573 | | //! \brief Pseudo random number generator. |