ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/rand.cpp
Revision: 2440
Committed: Wed Nov 16 19:42:11 2005 UTC (18 years, 7 months ago) by tim
File size: 13194 byte(s)
Log Message:
adding openbabel

File Contents

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