File Coverage

blib/lib/Math/Random/Free.pm
Criterion Covered Total %
statement 35 47 74.4
branch 11 24 45.8
condition n/a
subroutine 10 11 90.9
pod 0 7 0.0
total 56 89 62.9


line stmt bran cond sub pod time code
1             package Math::Random::Free;
2              
3 1     1   512 use strict;
  1         3  
  1         27  
4 1     1   6 use warnings;
  1         1  
  1         45  
5              
6             # ABSTRACT: Free drop-in replacement for Math::Random
7             our $VERSION = '0.2.0'; # VERSION
8              
9             =pod
10              
11             =head1 NAME
12              
13             Math::Random::Free - free drop-in replacement for Math::Random
14              
15             =head1 DESCRIPTION
16              
17             This is free (see below) implementation of L
18             0.72, serving as drop-in replacement for this module.
19              
20             =head1 MOTIVATION
21              
22             L is a great and widely-used module for the
23             generation of random numbers and permutations. Despite being open-source,
24             L does not fulfill free open-source software
25             definitions as established by the Open Source Initiative
26             (L) and the Debian Project
27             (L, a.k.a. DFSG). This
28             is mostly because C code cannot be copied nor distributed for
29             direct commercial advantage. Math::Random::Free is created to free the
30             code depending on L from these limitations.
31              
32             =cut
33              
34 1     1   559 use Digest::SHA qw( sha1_hex );
  1         3203  
  1         89  
35 1     1   8 use List::Util qw( shuffle );
  1         1  
  1         760  
36              
37             require Exporter;
38             our @ISA = qw(Exporter);
39             our @EXPORT = qw(
40             random_normal
41             random_permutation
42             random_permuted_index
43             random_set_seed_from_phrase
44             );
45             our @EXPORT_OK = qw(
46             random_exponential
47             random_normal
48             random_permutation
49             random_permuted_index
50             random_set_seed_from_phrase
51             random_uniform
52             random_uniform_integer
53             );
54             our $PI = 4 * atan2( 1, 1 );
55              
56             =head1 SUPPORT
57              
58             our @EXPORT = qw(
59             random_normal
60             random_permutation
61             random_permuted_index
62             random_set_seed_from_phrase
63             );
64             our @EXPORT_OK = qw(
65             random_exponential
66             random_normal
67             random_permutation
68             random_permuted_index
69             random_set_seed_from_phrase
70             random_uniform
71             random_uniform_integer
72             );
73              
74             =cut
75              
76             sub random_exponential
77             {
78 2     2 0 9 my( $n, $rate ) = @_;
79              
80 2 50       8 $n = 1 unless defined $n;
81 2 50       5 $rate = 1 unless defined $rate;
82              
83 2 50       5 if( wantarray ) {
84 0         0 return map { scalar random_exponential( $n, $rate ) } 1..$n;
  0         0  
85             } else {
86 2         10 return log( 1 - rand ) / -$rate;
87             }
88             }
89              
90             sub random_normal
91             {
92 12     12 0 28 my( $n, $mean, $sd ) = @_;
93              
94 12 50       23 $n = 1 unless defined $n;
95 12 100       22 $mean = 0 unless defined $mean;
96 12 100       20 $sd = 1 unless defined $sd;
97              
98 12 100       22 if( wantarray ) {
99 2         4 return map { scalar random_normal( $n, $mean, $sd ) } 1..$n;
  10         24  
100             } else {
101             # Box-Muller method
102 10         100 return $mean + $sd * cos( 2 * $PI * (1 - rand) )
103             * sqrt( -2 * log(1 - rand) );
104             }
105             }
106              
107             sub random_permutation
108             {
109 2     2 0 14 my( @array ) = @_;
110 2         7 return @array[random_permuted_index( scalar @array )];
111             }
112              
113             sub random_permuted_index
114             {
115 2     2 0 3 my( $n ) = @_;
116              
117 2         23 return shuffle 0..$n-1;
118             }
119              
120             sub random_set_seed_from_phrase
121             {
122 8     8 0 2660 my( $seed ) = @_;
123              
124             # On 64-bit machine the max. value for srand() seems to be 2**50-1
125 8         63 srand hex substr( sha1_hex( $seed ), 0, 6 );
126             }
127              
128             sub random_uniform
129             {
130 0     0 0 0 my( $n, $low, $high ) = @_;
131              
132 0 0       0 $n = 1 unless defined $n;
133 0 0       0 $low = 0 unless defined $low;
134 0 0       0 $high = 1 unless defined $high;
135              
136 0 0       0 if( wantarray ) {
137 0         0 return map { rand() * ($high - $low) + $low } 1..$n;
  0         0  
138             } else {
139 0         0 return rand() * ($high - $low) + $low;
140             }
141             }
142              
143             sub random_uniform_integer
144             {
145 2     2 0 11 my( $n, $low, $high ) = @_;
146              
147 2         5 my $range = int($high) - int($low) + 1;
148              
149 2 50       7 if( wantarray ) {
150 0         0 return map { int( rand($range) + $low ) } 1..$n;
  0         0  
151             } else {
152 2         11 return int( rand($range) + $low );
153             }
154             }
155              
156             =head1 CAVEATS
157              
158             This module has only a subset of L subroutines
159             (contributions welcome), implemented using either Perl core subroutines
160             or other well-known modules. Thus Math::Random::Free is neither as
161             complete, nor as fast, nor as random as L.
162             Also Math::Random::Free does not aim for cryptographic security.
163              
164             While Math::Random::Free supports seed setting, it does that differently
165             from L. It means that one should not expect
166             the same seed producing identical random sequences in both modules.
167              
168             As Math::Random::Free employs L for producing
169             random permutations, these are influenced by C<$List::Util::RAND>
170             variable.
171              
172             =head1 TESTED WITH
173              
174             =over 4
175              
176             =item *
177              
178             L 0.02
179              
180             =back
181              
182             =head1 AUTHOR
183              
184             Andrius Merkys, L
185              
186             =cut
187              
188             1;