Subject: | Bad interaction with drand48 |
This relates to one of the CAVEAT notes in the documentation, and is
really the fault of broken drand48, but it occurs on nearly every UNIX
system as well as Cygwin, and interacts very badly with a common use
case for Math::BigInt::Random::OO.
See <https://rt.perl.org/rt3/Ticket/Display.html?id=115928#txn-1177386>
for what I wrote up about CORE::rand.
I was trying to get random integers of various digit lengths, and
noticed that they all came out even. Some lengths work fine (e.g. 14),
others do not (e.g. 15, 80). Test:
perl -MMath::BigInt::Random::OO -E 'my $gen =
Math::BigInt::Random::OO->new(length=>15); my $n = 50000; for (1..$n) {
$freq{$gen->generate % 10}++ } printf("%4d %6.3f%%\n", $_,
100.0*$freq{$_}/$n) for sort {$a<=>$b} keys %freq;'
0 20.150%
2 19.964%
4 20.364%
6 19.796%
8 19.726%
The final bit of CORE::rand (drand48) alternates. But the way
Math::BigInt::Random::OO handles generating numbers of certain lengths
guarantees we call the upper bits once, then the lower bits a certain
number of times. For length 15 this is once, hence we always get a 0
ending bit.
I've reproduced this on Fedora x86_64 64-bit, Debian i386 32-bit, Debian
ia64 (Itanium 2) 64-bit, Debian sparc (US T1) 64-bit, Fedora ppc64
(Power7) 64-bit, NetBSD amd64 64-bit, and Cygwin i686 64-bit. Running a
C program using drand48 on the x86_64 machine shows that it is the culprit.
My preferred solution would be for Perl to make CORE::rand use an O/S
specific good default seed, then a better RNG (e.g. MT or ISAAC). But
barring that, perhaps something like:
my $rand_bits = $Config{randbits};
$rand_bits-- if $rand_bits == 48; # Protect against broken drand48
I realize this is a workaround, and rather hackish, but this one line
fix solves the problem on systems I've tested it on.