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.080001';
3             # ABSTRACT: Cryptographically-secure, cross-platform replacement for rand()
4              
5 5     5   132662 use strict;
  5         9  
  5         158  
6 5     5   117 use 5.008;
  5         16  
7 5     5   23 use base qw(Exporter);
  5         7  
  5         481  
8 5     5   1635 use Math::Random::Secure::RNG;
  5         13  
  5         184  
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   28 use constant DIVIDE_BY => 2**32;
  5         6  
  5         1636  
15              
16             our $RNG;
17              
18             our @EXPORT_OK = qw(rand srand irand);
19              
20             sub rand (;$) {
21 40000     40000 1 77761 my ($limit) = @_;
22 40000         34884 my $int = irand();
23 40000         41814 return _to_float($int, $limit);
24             }
25              
26             sub irand (;$) {
27 80605     80605 1 113184 my ($limit) = @_;
28 80605 100       92375 Math::Random::Secure::srand() if !defined $RNG;
29 80605         1078195 my $int = $RNG->irand();
30 80605 100       2144193 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         29641 return int(_to_float($int, $limit));
36             }
37 50605         43516 return $int;
38             }
39              
40             sub srand (;$) {
41 17     17 1 9062 my ($value) = @_;
42 17 100       42 if (defined $RNG) {
43 14 100       30 if (defined $value) {
44 12         258 $RNG->seed($value);
45             }
46             else {
47 2         48 $RNG->clear_seed;
48             }
49 14         234 $RNG->clear_rng;
50             }
51             else {
52 3         4 my %args;
53 3 50       12 if (defined $value) {
54 0         0 $args{seed} = $value;
55             }
56 3         39 $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         258 return $RNG->seed;
61             }
62              
63             sub _to_float {
64 70000     70000   52930 my ($integer, $limit) = @_;
65 70000 100       79884 $limit = 1 if !$limit;
66 70000         124309 return ($integer / DIVIDE_BY) * $limit;
67             }
68              
69             __PACKAGE__
70              
71             __END__