first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / mathematics / chaos.h
1 #ifndef CHAOS_CLASS
2 #define CHAOS_CLASS
3
4 //////////////
5 // Name   : chaos
6 // Author : Chris Koeritz
7 //////////////
8 // Copyright (c) 1991-$now By Author.  This program is free software; you can
9 // redistribute it and/or modify it under the terms of the GNU General Public
10 // License as published by the Free Software Foundation:
11 //     http://www.gnu.org/licenses/gpl.html
12 // Please send updates for this code to: fred@gruntose.com -- Thanks, fred.
13 //////////////
14
15 #include <basis/definitions.h>
16 #include <basis/enhance_cpp.h>
17 #include <basis/environment.h>
18 #include <timely/time_stamp.h>
19
20 //#define DEBUG_CHAOS
21   // uncomment for noisy logging.
22
23 #ifdef DEBUG_CHAOS
24   #include <stdio.h>
25 #endif
26 #include <stdlib.h>
27 #include <time.h>
28 #ifdef __UNIX__
29   #include <sys/times.h>
30 #endif
31
32 namespace mathematics {
33
34 // gets a 32 bit integer from the 15 bit random generator.  it's 15 bit because
35 // rand() only generates numbers up to the MAX_RAND, which in the visual c++
36 // case is limited to 0x7FFF.  so, we let the first random number generated
37 // serve as the upper two bytes and we shift another one over a bit to cover
38 // the whole range of the third and fourth byte, except for that last bit, 
39 // which is added in as a binary random value.
40 #define GET_32_BIT_RAND_YO \
41   basis::un_int ranval = (basis::un_int(rand()) << 16) + (basis::un_int(rand()) << 1) \
42        + (basis::un_int(rand()) % 2)
43
44 //! a platform-independent way to acquire random numbers in a specific range.
45 /*!
46   This object also re-seeds the underlying system's random seed when retrain()
47   is invoked.
48 */
49
50 class chaos : public virtual basis::nameable
51 {
52 public:
53   chaos() { retrain(); }
54   virtual ~chaos() {}
55
56   DEFINE_CLASS_NAME("chaos");
57
58   void retrain()
59     //!< Scrambles the OS's random seed and then provides pseudo-random values.
60   {
61     static unsigned int __flaxen = 0;
62     if (!__flaxen) {
63       time_t time_num;
64       time(&time_num);
65       // "t" is an ugly pointer into system data that contains the time nicely
66       // broken up into segments.  the pointer cannot be freed!
67       tm *t = localtime(&time_num);
68       int add_in_milliseconds = basis::environment::system_uptime();
69       // create a good random number seed from the time.
70 #ifdef DEBUG_CHAOS
71       printf("day %d hour %d min %d sec %d", (int)t->tm_mday, (int)t->tm_hour,
72           (int)t->tm_min, (int)t->tm_sec);
73 #endif
74       // we really don't care very much about the small chance of this being
75       // initialized to zero again.  the chance of that happening more than once
76       // should be pretty astronomical.
77       __flaxen = (t->tm_sec + 60 * t->tm_mday + 60 * 31 * t->tm_hour
78         + 24 * 60 * 31 * t->tm_min) ^ add_in_milliseconds;
79       // initialize random generator.
80       srand(int(__flaxen));
81     }
82   }
83
84   // Keep in mind for the inclusive and exclusive functions that a range which
85   // is too large might not be dealt with well.  This is because the random
86   // functions provided by the O.S. may not support the full range of integers.
87
88   int inclusive(int low, int high) const
89     //!< Returns a pseudo-random number r, such that "low" <= r <= "high".
90   {
91     if (high < low) return low;
92     unsigned int range = high - low + 1;
93     GET_32_BIT_RAND_YO;
94     int adjusted = ranval % range + low;
95     return adjusted;
96   }
97
98   int exclusive(int low, int high) const
99     //!< Returns a pseudo-random number r, such that "low" < r < "high".
100   {
101     if (high < low) return low + 1;
102     unsigned int range = high - low - 1;
103     GET_32_BIT_RAND_YO;
104     int adjusted = ranval % range + low + 1;
105     return adjusted;
106   }
107
108 };
109
110 } //namespace.
111
112 #endif
113