1# Tests the various random deviates
2
3use strict;
4use warnings;
5
6use Test::More 'tests' => 950;
7
8my @WARN;
9BEGIN {
10    # Warning signal handler
11    $SIG{__WARN__} = sub { push(@WARN, @_); };
12}
13
14use_ok('Math::Random::MT::Auto', qw(exponential erlang poisson
15                                    binomial shuffle));
16can_ok('Math::Random::MT::Auto', qw(exponential erlang poisson
17                                    binomial shuffle));
18can_ok('main', qw(exponential erlang poisson
19                                    binomial shuffle));
20
21# Check for warnings
22if (! ok(! @WARN, 'Acquired seed data')) {
23    diag('Seed warnings: ' . join(' | ', @WARN));
24}
25undef(@WARN);
26
27my (@rn);
28
29# Test several values from exponential()
30undef(@rn);
31for my $ii (0 .. 9) {
32    eval { $rn[$ii] = exponential(); };
33    ok(! $@,                        'exponential() died: ' . $@);
34    ok(defined($rn[$ii]),           'Got a random number');
35    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
36    ok($rn[$ii] > 0.0,              'Positive: ' . $rn[$ii]);
37    for my $jj (0 .. $ii-1) {
38        ok($rn[$jj] != $rn[$ii],    'Randomized');
39    }
40}
41
42# Test several values from erlang() for small order
43undef(@rn);
44for my $ii (0 .. 9) {
45    eval { $rn[$ii] = erlang(3); };
46    ok(! $@,                        'erlang(3) died: ' . $@);
47    ok(defined($rn[$ii]),           'Got a random number');
48    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
49    ok($rn[$ii] > 0.0,              'Positive: ' . $rn[$ii]);
50    for my $jj (0 .. $ii-1) {
51        ok($rn[$jj] != $rn[$ii],    'Randomized');
52    }
53}
54
55# Test several values from erlang() for larger order
56undef(@rn);
57for my $ii (0 .. 9) {
58    eval { $rn[$ii] = erlang(10); };
59    ok(! $@,                        'erlang(10) died: ' . $@);
60    ok(defined($rn[$ii]),           'Got a random number');
61    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
62    ok($rn[$ii] > 0.0,              'Positive: ' . $rn[$ii]);
63    for my $jj (0 .. $ii-1) {
64        ok($rn[$jj] != $rn[$ii],    'Randomized');
65    }
66}
67
68# Test several values from poisson() for small order
69undef(@rn);
70for my $ii (0 .. 9) {
71    eval { $rn[$ii] = poisson(3); };
72    ok(! $@,                        'poisson(3) died: ' . $@);
73    ok(defined($rn[$ii]),           'Got a random number');
74    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
75    ok(int($rn[$ii]) == $rn[$ii] &&
76       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
77}
78
79# Test several values from poisson() for large order
80undef(@rn);
81for my $ii (0 .. 9) {
82    eval { $rn[$ii] = poisson(30); };
83    ok(! $@,                        'poisson(30) died: ' . $@);
84    ok(defined($rn[$ii]),           'Got a random number');
85    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
86    ok(int($rn[$ii]) == $rn[$ii] &&
87       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
88}
89
90# Test several values from binomial() for small trial count
91undef(@rn);
92for my $ii (0 .. 9) {
93    eval { $rn[$ii] = binomial(0.5, 15); };
94    ok(! $@,                        'binomial(0.5, 15) died: ' . $@);
95    ok(defined($rn[$ii]),           'Got a random number');
96    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
97    ok(int($rn[$ii]) == $rn[$ii] &&
98       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
99}
100
101# Test several values from binomial() for small mean
102undef(@rn);
103for my $ii (0 .. 9) {
104    eval { $rn[$ii] = binomial(0.01, 30); };
105    ok(! $@,                        'binomial(0.01, 30) died: ' . $@);
106    ok(defined($rn[$ii]),           'Got a random number');
107    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
108    ok(int($rn[$ii]) == $rn[$ii] &&
109       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
110}
111
112# Test several values from binomial()
113undef(@rn);
114for my $ii (0 .. 9) {
115    eval { $rn[$ii] = binomial(0.8, 50); };
116    ok(! $@,                        'binomial(0.8, 50) died: ' . $@);
117    ok(defined($rn[$ii]),           'Got a random number');
118    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
119    ok(int($rn[$ii]) == $rn[$ii] &&
120       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
121}
122
123# Test of shuffle()
124my @data = (
125    [ 'xyz' ], 'abc', 1, 0.0, 1e-3, { 'q' => 42 }, sub { return (99); }
126);
127my $shuf;
128eval { $shuf = shuffle(@data); };
129ok(! $@, 'shuffle okay');
130for my $x (@$shuf) {
131    my $found = 0;
132    for my $y (@data) {
133        if (ref($x) eq 'CODE') {
134            if (ref($y) eq 'CODE') {
135                pass('shuffle - code ref okay');
136                $found = 1;
137                last;
138            }
139        } elsif (ref($x) eq 'ARRAY') {
140            if (ref($y) eq 'ARRAY') {
141                is_deeply($x, $y, 'shuffle - array okay');
142                $found = 1;
143                last;
144            }
145        } elsif (ref($x) eq 'HASH') {
146            if (ref($y) eq 'HASH') {
147                is_deeply($x, $y, 'shuffle - hash okay');
148                $found = 1;
149                last;
150            }
151        } elsif (Scalar::Util::looks_like_number($x)) {
152            if (Scalar::Util::looks_like_number($y) && ($x == $y)) {
153                pass("shuffle - $x okay");
154                $found = 1;
155                last;
156            }
157        } elsif (! ref($y) && ! Scalar::Util::looks_like_number($y) && ($x eq $y)) {
158            pass("shuffle - $x okay");
159            $found = 1;
160            last;
161        }
162    }
163    if (! $found) {
164        fail('shuffle element not found');
165    }
166}
167my @shuf;
168eval { @shuf = shuffle(@data); };
169ok(! $@, 'shuffle okay');
170for my $x (@shuf) {
171    my $found = 0;
172    for my $y (@data) {
173        if (ref($x) eq 'CODE') {
174            if (ref($y) eq 'CODE') {
175                pass('shuffle - code ref okay');
176                $found = 1;
177                last;
178            }
179        } elsif (ref($x) eq 'ARRAY') {
180            if (ref($y) eq 'ARRAY') {
181                is_deeply($x, $y, 'shuffle - array okay');
182                $found = 1;
183                last;
184            }
185        } elsif (ref($x) eq 'HASH') {
186            if (ref($y) eq 'HASH') {
187                is_deeply($x, $y, 'shuffle - hash okay');
188                $found = 1;
189                last;
190            }
191        } elsif (Scalar::Util::looks_like_number($x)) {
192            if (Scalar::Util::looks_like_number($y) && ($x == $y)) {
193                pass("shuffle - $x okay");
194                $found = 1;
195                last;
196            }
197        } elsif (! ref($y) && ! Scalar::Util::looks_like_number($y) && ($x eq $y)) {
198            pass("shuffle - $x okay");
199            $found = 1;
200            last;
201        }
202    }
203    if (! $found) {
204        fail('shuffle element not found');
205    }
206}
207eval { shuffle(\@data); };
208ok(! $@, 'shuffle okay');
209for my $x (@data) {
210    my $found = 0;
211    for my $y (@data) {
212        if (ref($x) eq 'CODE') {
213            if (ref($y) eq 'CODE') {
214                pass('shuffle - code ref okay');
215                $found = 1;
216                last;
217            }
218        } elsif (ref($x) eq 'ARRAY') {
219            if (ref($y) eq 'ARRAY') {
220                is_deeply($x, $y, 'shuffle - array okay');
221                $found = 1;
222                last;
223            }
224        } elsif (ref($x) eq 'HASH') {
225            if (ref($y) eq 'HASH') {
226                is_deeply($x, $y, 'shuffle - hash okay');
227                $found = 1;
228                last;
229            }
230        } elsif (Scalar::Util::looks_like_number($x)) {
231            if (Scalar::Util::looks_like_number($y) && ($x == $y)) {
232                pass("shuffle - $x okay");
233                $found = 1;
234                last;
235            }
236        } elsif (! ref($y) && ! Scalar::Util::looks_like_number($y) && ($x eq $y)) {
237            pass("shuffle - $x okay");
238            $found = 1;
239            last;
240        }
241    }
242    if (! $found) {
243        fail('shuffle element not found');
244    }
245}
246
247
248# Create PRNG object
249my $prng;
250eval { $prng = Math::Random::MT::Auto->new(); };
251if (! ok(! $@, '->new works')) {
252    diag('->new died: ' . $@);
253}
254isa_ok($prng, 'Math::Random::MT::Auto');
255can_ok($prng, qw(rand irand gaussian exponential erlang poisson binomial
256                 shuffle get_seed set_seed get_state set_state));
257
258# Check for warnings
259if (! ok(! @WARN, 'Acquired seed data')) {
260    diag('Seed warnings: ' . join(' | ', @WARN));
261}
262undef(@WARN);
263
264# Test several values from exponential()
265undef(@rn);
266for my $ii (0 .. 9) {
267    eval { $rn[$ii] = $prng->exponential(2); };
268    ok(! $@,                        '$prng->exponential() died: ' . $@);
269    ok(defined($rn[$ii]),           'Got a random number');
270    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
271    ok($rn[$ii] > 0.0,              'Positive: ' . $rn[$ii]);
272    for my $jj (0 .. $ii-1) {
273        ok($rn[$jj] != $rn[$ii],    'Randomized');
274    }
275}
276
277# Test several values from erlang() for small order
278undef(@rn);
279for my $ii (0 .. 9) {
280    eval { $rn[$ii] = $prng->erlang(3); };
281    ok(! $@,                        '$prng->erlang(3) died: ' . $@);
282    ok(defined($rn[$ii]),           'Got a random number');
283    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
284    ok($rn[$ii] > 0.0,              'Positive: ' . $rn[$ii]);
285    for my $jj (0 .. $ii-1) {
286        ok($rn[$jj] != $rn[$ii],    'Randomized');
287    }
288}
289
290# Test several values from erlang() for larger order
291undef(@rn);
292for my $ii (0 .. 9) {
293    eval { $rn[$ii] = $prng->erlang(10); };
294    ok(! $@,                        '$prng->erlang(10) died: ' . $@);
295    ok(defined($rn[$ii]),           'Got a random number');
296    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
297    ok($rn[$ii] > 0.0,              'Positive: ' . $rn[$ii]);
298    for my $jj (0 .. $ii-1) {
299        ok($rn[$jj] != $rn[$ii],    'Randomized');
300    }
301}
302
303# Test several values from poisson() for small order
304undef(@rn);
305for my $ii (0 .. 9) {
306    eval { $rn[$ii] = $prng->poisson(3); };
307    ok(! $@,                        '$prng->poisson(3) died: ' . $@);
308    ok(defined($rn[$ii]),           'Got a random number');
309    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
310    ok(int($rn[$ii]) == $rn[$ii] &&
311       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
312}
313
314# Test several values from poisson() for large order
315undef(@rn);
316for my $ii (0 .. 9) {
317    eval { $rn[$ii] = $prng->poisson(30); };
318    ok(! $@,                        '$prng->poisson(30) died: ' . $@);
319    ok(defined($rn[$ii]),           'Got a random number');
320    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
321    ok(int($rn[$ii]) == $rn[$ii] &&
322       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
323}
324
325# Test several values from binomial() for small trial count
326undef(@rn);
327for my $ii (0 .. 9) {
328    eval { $rn[$ii] = $prng->binomial(0.5, 15); };
329    ok(! $@,                        '$prng->binomial(0.5, 15) died: ' . $@);
330    ok(defined($rn[$ii]),           'Got a random number');
331    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
332    ok(int($rn[$ii]) == $rn[$ii] &&
333       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
334}
335
336# Test several values from binomial() for small mean
337undef(@rn);
338for my $ii (0 .. 9) {
339    eval { $rn[$ii] = $prng->binomial(0.01, 30); };
340    ok(! $@,                        '$prng->binomial(0.01, 30) died: ' . $@);
341    ok(defined($rn[$ii]),           'Got a random number');
342    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
343    ok(int($rn[$ii]) == $rn[$ii] &&
344       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
345}
346
347# Test several values from binomial()
348undef(@rn);
349for my $ii (0 .. 9) {
350    eval { $rn[$ii] = $prng->binomial(0.8, 50); };
351    ok(! $@,                        '$prng->binomial(0.8, 50) died: ' . $@);
352    ok(defined($rn[$ii]),           'Got a random number');
353    ok(Scalar::Util::looks_like_number($rn[$ii]), 'Is a number: ' . $rn[$ii]);
354    ok(int($rn[$ii]) == $rn[$ii] &&
355       $rn[$ii] >= 0,               'Non-neg integer: ' . $rn[$ii]);
356}
357
358# Test of shuffle()
359eval { $shuf = $prng->shuffle($shuf); };
360ok(! $@, '$prng->shuffle okay');
361for my $x (@$shuf) {
362    my $found = 0;
363    for my $y (@data) {
364        if (ref($x) eq 'CODE') {
365            if (ref($y) eq 'CODE') {
366                pass('$prng->shuffle - code ref okay');
367                $found = 1;
368                last;
369            }
370        } elsif (ref($x) eq 'ARRAY') {
371            if (ref($y) eq 'ARRAY') {
372                is_deeply($x, $y, '$prng->shuffle - array okay');
373                $found = 1;
374                last;
375            }
376        } elsif (ref($x) eq 'HASH') {
377            if (ref($y) eq 'HASH') {
378                is_deeply($x, $y, '$prng->shuffle - hash okay');
379                $found = 1;
380                last;
381            }
382        } elsif (Scalar::Util::looks_like_number($x)) {
383            if (Scalar::Util::looks_like_number($y) && ($x == $y)) {
384                pass("\$prng->shuffle - $x okay");
385                $found = 1;
386                last;
387            }
388        } elsif (! ref($y) && ! Scalar::Util::looks_like_number($y) && ($x eq $y)) {
389            pass("\$prng->shuffle - $x okay");
390            $found = 1;
391            last;
392        }
393    }
394    if (! $found) {
395        fail('shuffle element not found');
396    }
397}
398
399exit(0);
400
401# EOF
402