File Coverage

blib/lib/Math/RandomOrg.pm
Criterion Covered Total %
statement 35 73 47.9
branch 10 30 33.3
condition 2 14 14.2
subroutine 8 10 80.0
pod 4 4 100.0
total 59 131 45.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Math::RandomOrg - Retrieve random numbers and data from random.org.
4              
5             =head1 SYNOPSIS
6              
7             use Math::RandomOrg qw(randnum randbyte);
8             my $number = randnum(0, 10);
9             my $octet = randbyte(1);
10              
11             =head1 DESCRIPTION
12              
13             Math::RandomOrg provides functions for retrieving random data from the random.org server.
14             Data may be retrieved in an integer or byte-stream format using the C and C functions respectively.
15              
16             =head1 REQUIRES
17              
18             =over 4
19              
20             =item Carp
21              
22             =item Exporter
23              
24             =item Math::BigInt
25              
26             =item LWP::Simple
27              
28             =back
29              
30             =head1 EXPORT
31              
32             None by default. You may request the following symbols be exported:
33              
34             =over 4
35              
36             =item * randnum
37              
38             =item * randbyte
39              
40             =back
41              
42             =cut
43              
44             package Math::RandomOrg;
45              
46 2     2   22694 use strict;
  2         6  
  2         81  
47 2     2   11 use warnings;
  2         4  
  2         227  
48              
49             our ($VERSION, @ISA, @EXPORT, @EXPORT_OK);
50              
51             require Exporter;
52             @ISA = qw(Exporter);
53              
54             @EXPORT_OK = qw( checkbuf randnum randbyte randseq );
55             @EXPORT = qw();
56             $VERSION = '0.04';
57              
58 2     2   10 use Carp;
  2         5  
  2         708  
59 2     2   27109 use Math::BigInt;
  2         88721  
  2         13  
60 2     2   69800 use LWP::Simple ();
  2         283370  
  2         382  
61              
62             my $RAND_MIN = new Math::BigInt "-1000000000"; # random.org fixed min
63             my $RAND_MAX = new Math::BigInt "1000000000"; # random.org fixed max
64             my $NUM_BUF = 256; # at least, request this number of random integers in each request to random.org
65              
66             =head1 FUNCTIONS
67              
68             =over 4
69              
70             =cut
71              
72             {
73             my @randnums;
74              
75             =item C
76              
77             This routine takes no parameters and simply returns a single value (e.g.,
78             C<28%>) telling you how full the buffer is. At 100%, the buffer is full
79             and you are free to hit it with automated clients. At 0%, the buffer is
80             empty and requests will hang. When less than 100%, the buffer is being
81             filled continually, but doing so takes time. I advise people with
82             automated clients to check the buffer level every once in a while and only
83             issue requests when the buffer level is 20% or higher.
84              
85             =cut
86              
87             sub checkbuf {
88 0     0 1 0 my $url = "http://www.random.org/cgi-bin/checkbuf";
89 0         0 my $data = LWP::Simple::get( $url );
90 0 0       0 if (defined($data)) {
91 0         0 $data =~ s/\%//;
92 0         0 return $data;
93             } else {
94 0         0 carp "HTTP GET failed for $url";
95 0         0 return;
96             }
97             }
98              
99             =item C
100              
101             Return an integer (specifically a Math::BigInt object) between the bounds [ $min, $max ] (inclusive).
102              
103             By default, $max and $min are positive and negative 1e9, respectively. These default
104             values represent random.org's current extrema for the bounds of the randnum function.
105             Therefore, $min and $max may not exceed the default values.
106              
107             =cut
108             sub randnum (;$$) {
109 2     2   19 use integer;
  2         5  
  2         19  
110 180 50   180 1 96588 my $min = new Math::BigInt (defined($_[0]) ? $_[0] : $RAND_MIN);
111 180 50       27730 my $max = new Math::BigInt (defined($_[1]) ? $_[1] : $RAND_MAX);
112 180 50 33     9078 if ($min < $RAND_MIN or $max > $RAND_MAX) {
113 0         0 carp "The $min and $max arguments to the randnum() function may not exceed the bounds ($RAND_MIN, $RAND_MAX)!";
114 0         0 return undef;
115             }
116 180 50       17355 if ($#randnums == -1) {
117 180         2087 my $url = "http://www.random.org/cgi-bin/randnum?num=${NUM_BUF}&min=${RAND_MIN}&max=${RAND_MAX}&col=1";
118 180         16626 my $data = LWP::Simple::get( $url );
119 180 50       86807466 if (defined($data)) {
120 0         0 @randnums = map { new Math::BigInt $_ } (split(/\n/, $data));
  0         0  
121             } else {
122 180         80662 carp "HTTP GET failed for $url";
123 180         2995 return undef;
124             }
125             }
126 0         0 my $num = shift(@randnums);
127            
128 0         0 $num -= $RAND_MIN;
129 0         0 $num *= (1 + $max - $min);
130 0         0 $num /= ($RAND_MAX - $RAND_MIN);
131 0         0 $num += $min;
132            
133 0         0 return $num;
134             }
135              
136             my $randbytes = '';
137              
138             =item C
139              
140             Returns an octet-string of specified length (defaults to one byte), which contains random bytes.
141              
142             $length may not exceed 16,384, as this is the maximum number of bytes retrievable from the
143             random.org server in one request, and making multiple requests for an unbounded amount of
144             data would unfairly tax the random.org server. If you need large amounts of random data,
145             you may wish to try the Math::TrulyRandom module.
146              
147             =cut
148             sub randbyte (;$) {
149 10   50 10 1 5382 my $length = +(shift || 1);
150 10 50       52 if ($length > 16_384) {
    100          
151 0         0 carp "randbyte() should not be used to generate random data larger than 16,384 bytes (lest we swamp random.org's entropy source).";
152 0         0 return '';
153             } elsif (length($randbytes) < $length) {
154 1 50       3 my $nbytes = ($length > 512) ? $length : 512;
155 1         5 my $url = "http://www.random.org/cgi-bin/randbyte?nbytes=${nbytes}&format=f";
156 1         7 my $data = LWP::Simple::get( $url );
157 1 50       625881 if (defined($data)) {
158 1         6 $randbytes .= $data;
159             } else {
160 0         0 carp "HTTP GET failed for $url";
161 0         0 return undef;
162             }
163             }
164 10         47 return substr($randbytes, 0, $length, '');
165             }
166             }
167              
168             =item C
169              
170             The randseq script returns a randomized sequence of numbers. This corresponds to dropping a number of lottery tickets into a hat and drawing them out in random order. Hence, each number in a randomized sequence occurs exactly once.
171              
172             Example: C will return the numbers between 1 and 10 (both inclusive) in a random order.
173              
174             =cut
175              
176             sub randseq (;$$) {
177 0     0 1   my ($min, $max) = @_;
178 0 0 0       return if ( (! defined $min) || (! defined $max) || ($min !~ /^\-?\d+$/) || ($max !~ /^\-?\d+$/) );
      0        
      0        
179 0 0         if ($max < $min) {
180 0           carp "MAX must be greater than MIN.";
181 0           return;
182             }
183 0 0         if ($max - $min > 10000) {
184 0           carp "random.org restricts the size of sequences to <= 10,000.";
185 0           return;
186             }
187 0           my @sequence = ();
188 0           my $url = "http://www.random.org/cgi-bin/randseq?min=$min&max=$max";
189 0           my $data = LWP::Simple::get( $url );
190 0 0         if (defined($data)) {
191 0           @sequence = map { new Math::BigInt $_ } (split(/\n/, $data));
  0            
192             } else {
193 0           carp "HTTP GET failed for $url";
194 0           return undef;
195             }
196            
197 0 0         return wantarray ? @sequence : \@sequence;
198             }
199              
200             1;
201             __END__