Coverage Report

Created: 2026-10-17 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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(&ltime);
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(&ltime);
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.