File Coverage

blib/lib/Math/Random/Secure.pm
Criterion Covered Total %
statement 36 37 97.3
branch 11 12 91.6
condition n/a
subroutine 9 9 100.0
pod 3 3 100.0
total 59 61 96.7


line stmt bran cond sub pod time code
1             package Math::Random::Secure;
2             $Math::Random::Secure::VERSION = '0.08';
3             # ABSTRACT: Cryptographically-secure, cross-platform replacement for rand()
4              
5 5     5   174841 use strict;
  5         6  
  5         109  
6 5     5   83 use 5.008;
  5         10  
7 5     5   16 use base qw(Exporter);
  5         6  
  5         378  
8 5     5   1450 use Math::Random::Secure::RNG;
  5         11  
  5         161  
9              
10             # ISAAC, a 32-bit generator, should only be capable of generating numbers
11             # between 0 and 2^32 - 1. We want _to_float to generate numbers possibly
12             # including 0, but always less than 1.0. Dividing the integer produced
13             # by irand() by this number should do that exactly.
14 5     5   33 use constant DIVIDE_BY => 2**32;
  5         5  
  5         1343  
15              
16             our $RNG;
17              
18             our @EXPORT_OK = qw(rand srand irand);
19              
20             sub rand (;$) {
21 40000     40000 1 74122 my ($limit) = @_;
22 40000         33959 my $int = irand();
23 40000         37968 return _to_float($int, $limit);
24             }
25              
26             sub irand (;$) {
27 80605     80605 1 115580 my ($limit) = @_;
28 80605 100       92586 Math::Random::Secure::srand() if !defined $RNG;
29 80605         1144608 my $int = $RNG->irand();
30 80605 100       2293491 if (defined $limit) {
31             # We can't just use the mod operator because it will bias
32             # our output. Search for "modulo bias" on the Internet for
33             # details. This is slower than mod(), but does not have a bias,
34             # as demonstrated by our uniform.t test.
35 30000         30309 return int(_to_float($int, $limit));
36             }
37 50605         45135 return $int;
38             }
39              
40             sub srand (;$) {
41 17     17 1 18625 my ($value) = @_;
42 17 100       72 if (defined $RNG) {
43 14 100       46 if (defined $value) {
44 12         388 $RNG->seed($value);
45             }
46             else {
47 2         82 $RNG->clear_seed;
48             }
49 14         442 $RNG->clear_rng;
50             }
51             else {
52 3         5 my %args;
53 3 50       13 if (defined $value) {
54 0         0 $args{seed} = $value;
55             }
56 3         47 $RNG = Math::Random::Secure::RNG->new(%args);
57             }
58             # This makes srand return the seed and also makes sure that we
59             # get the seed right now, if no $value was passed.
60 17         1407 return $RNG->seed;
61             }
62              
63             sub _to_float {
64 70000     70000   50162 my ($integer, $limit) = @_;
65 70000 100       79175 $limit = 1 if !$limit;
66 70000         136358 return ($integer / DIVIDE_BY) * $limit;
67             }
68              
69             __PACKAGE__
70              
71             __END__