1package Math::Random::ISAAC;
2BEGIN {
3  $Math::Random::ISAAC::VERSION = '1.004';
4}
5# ABSTRACT: Perl interface to the ISAAC PRNG algorithm
6
7use strict;
8use warnings;
9use Carp ();
10
11our $DRIVER = 'PP';
12
13# Try to load the XS version first
14eval {
15  require Math::Random::ISAAC::XS;
16  $DRIVER = 'XS';
17};
18
19# Fall back on the Perl version
20if ($@) {
21  require Math::Random::ISAAC::PP;
22}
23
24
25# Wrappers around the actual methods
26sub new {
27  my ($class, @seed) = @_;
28
29  Carp::croak('You must call this as a class method') if ref($class);
30
31  my $self = {
32  };
33
34  if ($DRIVER eq 'XS') {
35    $self->{backend} = Math::Random::ISAAC::XS->new(@seed);
36  }
37  else {
38    $self->{backend} = Math::Random::ISAAC::PP->new(@seed);
39  }
40
41  bless($self, $class);
42  return $self;
43}
44
45
46# This package should have an interface similar to the builtin Perl
47# random number routines; these are methods, not functions, so they
48# are not problematic
49## no critic (ProhibitBuiltinHomonyms)
50
51sub rand {
52  my ($self) = @_;
53
54  Carp::croak('You must call this method as an object') unless ref($self);
55
56  return $self->{backend}->rand();
57}
58
59
60sub irand {
61  my ($self) = @_;
62
63  Carp::croak('You must call this method as an object') unless ref($self);
64
65  return $self->{backend}->irand();
66}
67
68
691;
70
71__END__
72=pod
73
74=head1 NAME
75
76Math::Random::ISAAC - Perl interface to the ISAAC PRNG algorithm
77
78=head1 VERSION
79
80version 1.004
81
82=head1 SYNOPSIS
83
84  use Math::Random::ISAAC;
85
86  my $rng = Math::Random::ISAAC->new(@seeds);
87
88  for (0..30) {
89    print 'Result: ' . $rng->irand() . "\n";
90  }
91
92=head1 DESCRIPTION
93
94As with other Pseudo-Random Number Generator (PRNG) algorithms like the
95Mersenne Twister (see L<Math::Random::MT>), this algorithm is designed to
96take some seed information and produce seemingly random results as output.
97
98However, ISAAC (Indirection, Shift, Accumulate, Add, and Count) has different
99goals than these commonly used algorithms. In particular, it's really fast -
100on average, it requires only 18.75 machine cycles to generate a 32-bit value.
101This makes it suitable for applications where a significant amount of random
102data needs to be produced quickly, such solving using the Monte Carlo method
103or for games.
104
105The results are uniformly distributed, unbiased, and unpredictable unless
106you know the seed. The algorithm was published by Bob Jenkins in the late
10790s and despite the best efforts of many security researchers, no feasible
108attacks have been found to date.
109
110=head2 USAGE WARNING
111
112There was no method supplied to provide the initial seed data by the author.
113On his web site, Bob Jenkins writes:
114
115  Seeding a random number generator is essentially the same problem as
116  encrypting the seed with a block cipher.
117
118In the same spirit, by default, this module does not seed the algorithm at
119all -- it simply fills the state with zeroes -- if no seed is provided.
120The idea is to remind users that selecting good seed data for their purpose
121is important, and for the module to conveniently set it to something like
122C<localtime> behind-the-scenes hurts users in the long run, since they don't
123understand the limitations of doing so.
124
125The type of seed you might want to use depends entirely on the purpose of
126using this algorithm in your program in the first place. Here are some
127possible seeding methods:
128
129=over
130
131=item 1 Math::TrulyRandom
132
133The L<Math::TrulyRandom> module provides a way of obtaining truly random
134data by using timing interrupts. This is probably one of the better ways
135to seed the algorithm.
136
137=item 2 /dev/random
138
139Using the system random device is, in principle, the best idea, since it
140gathers entropy from various sources including interrupt timing, other
141device interrupts, etc. However, it's not portable to anything other than
142Unix-like platforms, and might not produce good data on some systems.
143
144=item 3 localtime()
145
146This works for basic things like simulations, but results in not-so-random
147output, especially if you create new instances quickly (as the seeds would
148be the same within per-second resolution).
149
150=item 4 Time::HiRes
151
152In theory, using L<Time::HiRes> is the same as option (2), but you get a
153higher resolution time so you're less likely to have the same seed twice.
154Note that you need to transform the output into an integer somehow, perhaps
155by taking the least significant bits or using a hash function. This would
156be less prone to duplicate instances, but it's still not ideal.
157
158=back
159
160=head1 METHODS
161
162=head2 new
163
164  Math::Random::ISAAC->new( @seeds )
165
166Creates a C<Math::Random::ISAAC> object, based upon either the optimized
167C/XS version of the algorithm, L<Math::Random::ISAAC::XS>, or falls back
168to the included Pure Perl module, L<Math::Random::ISAAC::PP>.
169
170Example code:
171
172  my $rng = Math::Random::ISAAC->new(time);
173
174This method will return an appropriate B<Math::Random::ISAAC> object or
175throw an exception on error.
176
177=head2 rand
178
179  $rng->rand()
180
181Returns a random double-precision floating point number which is normalized
182between 0 and 1 (inclusive; it's a closed interval).
183
184Internally, this simply takes the uniformly distributed unsigned integer from
185C<$rng-E<gt>irand()> and divides it by C<2**32-1> (maximum unsigned integer
186size)
187
188Example code:
189
190  my $next = $rng->rand();
191
192This method will return a double-precision floating point number or throw an
193exception on error.
194
195=head2 irand
196
197  $rng->irand()
198
199Returns the next unsigned 32-bit random integer. It will return a value with
200a value such that: B<0 E<lt>= x E<lt>= 2**32-1>.
201
202Example code:
203
204  my $next = $rng->irand();
205
206This method will return a 32-bit unsigned integer or throw an exception on
207error.
208
209=head1 PURPOSE
210
211The intent of this module is to provide single simple interface to the two
212compatible implementations of this module, namely, L<Math::Random::ISAAC::XS>
213and L<Math::Random::ISAAC::PP>.
214
215If, for some reason, you need to determine what version of the module is
216actually being included by C<Math::Random::ISAAC>, then:
217
218  print 'Backend type: ', $Math::Random::ISAAC::DRIVER, "\n";
219
220In order to force use of one or the other, simply load the appropriate module:
221
222  use Math::Random::ISAAC::XS;
223  my $rng = Math::Random::ISAAC::XS->new();
224  # or
225  use Math::Random::ISAAC::PP;
226  my $rng = Math::Random::ISAAC::PP->new();
227
228=head1 ACKNOWLEDGEMENTS
229
230=over
231
232=item *
233
234Special thanks to Bob Jenkins E<lt>bob_jenkins@burtleburtle.netE<gt> for
235devising this very clever algorithm and releasing it into the public domain.
236
237=item *
238
239Thanks to John L. Allen (contact unknown) for providing a Perl port of the
240original ISAAC code, upon which C<Math::Random::ISAAC::PP> is heavily based.
241His version is available on Bob's web site, in the SEE ALSO section.
242
243=back
244
245=head1 SEE ALSO
246
247L<Math::Random::ISAAC::XS>, the C/XS optimized version of this module, which
248will be used automatically if available.
249
250L<http://burtleburtle.net/bob/rand/isaacafa.html>, Bob Jenkins' page about
251ISAAC, which explains the algorithm as well as potential attacks.
252
253L<http://eprint.iacr.org/2006/438.pdf>, a paper entitled "On the pseudo-random
254generator ISAAC," which claims there are many seeds which will produce
255non-uniform results. The author, Jean-Philippe Aumasson, argues ISAAC should
256be using rotations (circular shifts) instead of normal shifts to increase
257diffusion of the state, among other things.
258
259L<http://eprint.iacr.org/2001/049.pdf>, a paper by Marina Pudovkina discussing
260plaintext attacks on the ISAAC keystream generator. Among other things, it
261notes that the time complexity is B<Tmet = 4.67*10^1240>, so it remains a
262secure cipher for practical applications.
263
264=head1 CAVEATS
265
266=over
267
268=item *
269
270There is no method that allows re-seeding of algorithms. This is not really
271necessary because one can simply call C<new> again with the new seed data
272periodically.
273
274But he also provides a simple workaround:
275
276  As ISAAC is intended to be a secure cipher, if you want to reseed it,
277  one way is to use some other cipher to seed some initial version of ISAAC,
278  then use ISAAC's output as a seed for other instances of ISAAC whenever
279  they need to be reseeded.
280
281=item *
282
283There is no way to clone a PRNG instance. I'm not sure why this is might
284even be necessary or useful. File a bug report with an explanation why and
285I'll consider adding it to the next release.
286
287=back
288
289=head1 BUGS
290
291Please report any bugs or feature requests on the bugtracker website
292http://rt.cpan.org/NoAuth/Bugs.html?Dist=Math-Random-ISAAC
293
294When submitting a bug or request, please include a test-file or a
295patch to an existing test-file that illustrates the bug or desired
296feature.
297
298=head1 AUTHOR
299
300Jonathan Yu <jawnsy@cpan.org>
301
302=head1 COPYRIGHT AND LICENSE
303
304Legally speaking, this package and its contents are:
305
306  Copyright (c) 2011 by Jonathan Yu <jawnsy@cpan.org>.
307
308But this is really just a legal technicality that allows the author to
309offer this package under the public domain and also a variety of licensing
310options. For all intents and purposes, this is public domain software,
311which means you can do whatever you want with it.
312
313The software is provided "AS IS", without warranty of any kind, express or
314implied, including but not limited to the warranties of merchantability,
315fitness for a particular purpose and noninfringement. In no event shall the
316authors or copyright holders be liable for any claim, damages or other
317liability, whether in an action of contract, tort or otherwise, arising from,
318out of or in connection with the software or the use or other dealings in
319the software.
320
321=cut
322
323