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