1 //   Copyright (c)  2010  John Abbott
2 
3 //   This file is part of the source of CoCoALib, the CoCoA Library.
4 
5 //   CoCoALib is free software: you can redistribute it and/or modify
6 //   it under the terms of the GNU General Public License as published by
7 //   the Free Software Foundation, either version 3 of the License, or
8 //   (at your option) any later version.
9 
10 //   CoCoALib is distributed in the hope that it will be useful,
11 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //   GNU General Public License for more details.
14 
15 //   You should have received a copy of the GNU General Public License
16 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
17 
18 
19 #include "CoCoA/BuildInfo.H"
20 #include "CoCoA/GlobalManager.H"
21 #include "CoCoA/error.H"
22 #include "CoCoA/random.H"
23 
24 #include <iostream>
25 using std::cerr;
26 using std::endl;
27 #include <limits>
28 using std::numeric_limits;
29 #include <vector>
30 using std::vector;
31 
32 
33 namespace CoCoA
34 {
35 
program()36   void program()
37   {
38     // This test checks the behaviour of the RandomLong function which
39     // generates pseudo-random machine integer values from a RandomSource.
40     GlobalManager CoCoAFoundations;
41 
42     RandomSource RndSrc;
43 
44     // Check that the arg checks are working, and that generated values
45     // are within the specified range.
46     for (int i=-9; i < 10; ++i)
47       for (int j=-9; j < 10; ++j)
48         for (int k=0; k < 100; ++k)
49         {
50           try
51           {
52             const long rnd = RandomLong(RndSrc, i, j);
53             CoCoA_ASSERT_ALWAYS(i <= j && i <= rnd && rnd <= j);
54           }
55           catch (const ErrorInfo& err) { CoCoA_ASSERT_ALWAYS(err == ERR::BadArg); }
56         }
57 
58 
59     {
60       // Check that we can generate the full range of longs
61       const int NumIters = 2147000;
62       const long lwb = numeric_limits<long>::min();
63       const long upb = numeric_limits<long>::max();
64       long smallest = 0;
65       long largest = 0;
66       for (int i=0; i < NumIters; ++i)
67       {
68         const long rnd = RandomLong(RndSrc, lwb, upb);
69         if (rnd > largest)  largest = rnd;
70         else if (rnd < smallest)  smallest = rnd;
71       }
72       CoCoA_ASSERT_ALWAYS(smallest < lwb + 14*(upb/NumIters)); // 99.9% chance of being true
73       CoCoA_ASSERT_ALWAYS(largest > upb - 14*(upb/NumIters));  // 99.9% chance of being true
74     }
75 
76 
77     // Generate some histograms, and check that they are fairly uniform.
78     const long NumCases = 10;
79     const long ExpectedFreq = 10000;
80     const long NumTrials = ExpectedFreq*NumCases;
81     for (int lwb=-12345; lwb < 23456; lwb += 321)
82     {
83       vector<long> hist(NumCases);
84       for (long i=0; i < NumTrials; ++i)
85         ++hist[RandomLong(RndSrc, lwb, lwb+NumCases-1) - lwb];
86 
87       int min = ExpectedFreq;
88       int max = 0;
89       for (int i=0; i < NumCases; ++i)
90       {
91         if (hist[i] > max)  max = hist[i];
92         else if (hist[i] < min)  min = hist[i];
93       }
94       CoCoA_ASSERT_ALWAYS(min > 0.8*max);
95     }
96 
97   }
98 
99 } // end of namespace CoCoA
100 
101 
102 // Use main() to handle any uncaught exceptions and warn the user about them.
main()103 int main()
104 {
105   try
106   {
107     CoCoA::program();
108     return 0;
109   }
110   catch (const CoCoA::ErrorInfo& err)
111   {
112     cerr << "***ERROR***  UNCAUGHT CoCoA Error";
113     ANNOUNCE(cerr, err);
114   }
115   catch (const std::exception& exc)
116   {
117     cerr << "***ERROR***  UNCAUGHT std::exception: " << exc.what() << endl;
118   }
119   catch(...)
120   {
121     cerr << "***ERROR***  UNCAUGHT UNKNOWN EXCEPTION" << endl;
122   }
123 
124   CoCoA::BuildInfo::PrintAll(cerr);
125   return 1;
126 }
127