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