Raku / old-issue-tracker

Tickets from RT
https://github.com/Raku/old-issue-tracker/issues
2 stars 1 forks source link

.pick on large ranges gives unexpected results on Windows only #6059

Open p6rt opened 7 years ago

p6rt commented 7 years ago

Migrated from rt.perl.org#130723 (status was 'open')

Searchable as RT130723$

p6rt commented 7 years ago

From @mscha

On my self-compiled Linux build of Rakudo Star 2017.01​:

% perl6 -e 'say (-524288..^524288).pick(50)' (445052 -427 442649 66610 133030 238409 -250288 438259 508787 423778 90030 28568 -372417 143522 -335109 -156474 -395940 -124515 517779 398864 -494020 -303173 -4646 253705 -263919 204704 328943 -230539 276553 -142475 -311381 -224414 410534 -58726 -27584 -135264 -222462 79964 -177401 -413056 -279021 -445158 -161601 61337 -101262 -66850 -285553 -506522 366891 289163)

This looks pretty normal.

But on my Windows machine, using the 64-bit version of Rakudo Star 2017.01, downloaded from http://rakudo.org/downloads/star/ , I get​:

% perl6 -e 'say (-524288..^524288).pick(50)' (-504365 -504962 -520900 -503012 -504515 -514927 -524063 -511982 -503130 -511610 -515842 -518903 -505137 -513172 -504845 -512334 -513608 -518507 -512159 -508672 -492893 -503150 -501718 -515295 -495598 -513483 -507283 -493687 -494653 -498803 -497266 -519193 -510278 -503827 -501717 -514772 -507593 -500763 -509913 -509046 -523590 -516283 -499038 -501134 -499195 -496352 -495618 -522092 -504550 -498746)

I.e., I consistently get numbers close to the bottom end of the range.

p6rt commented 7 years ago

From @nwc10

OK, this is a bit of guessing, and I would like to think that I've guessed wrongly because someone else *should* have hit this before...

On Sun, Feb 05, 2017 at 03​:21​:12PM -0800, Michael Schaap wrote​:

# New Ticket Created by Michael Schaap # Please include the string​: [perl #​130723] # in the subject line of all future correspondence about this issue. # \<URL​: https://rt-archive.perl.org/perl6/Ticket/Display.html?id=130723 >

On my self-compiled Linux build of Rakudo Star 2017.01​:

% perl6 -e 'say (-524288..^524288).pick(50)' (445052 -427 442649 66610 133030 238409 -250288 438259 508787 423778 90030 28568 -372417 143522 -335109 -156474 -395940 -124515 517779 398864 -494020 -303173 -4646 253705 -263919 204704 328943 -230539 276553 -142475 -311381 -224414 410534 -58726 -27584 -135264 -222462 79964 -177401 -413056 -279021 -445158 -161601 61337 -101262 -66850 -285553 -506522 366891 289163)

This looks pretty normal.

But on my Windows machine, using the 64-bit version of Rakudo Star 2017.01, downloaded from http://rakudo.org/downloads/star/ , I get​:

% perl6 -e 'say (-524288..^524288).pick(50)' (-504365 -504962 -520900 -503012 -504515 -514927 -524063 -511982 -503130 -511610 -515842 -518903 -505137 -513172 -504845 -512334 -513608 -518507 -512159 -508672 -492893 -503150 -501718 -515295 -495598 -513483 -507283 -493687 -494653 -498803 -497266 -519193 -510278 -503827 -501717 -514772 -507593 -500763 -509913 -509046 -523590 -516283 -499038 -501134 -499195 -496352 -495618 -522092 -504550 -498746)

I.e., I consistently get numbers close to the bottom end of the range.

Windows. Random numbers.

3rdparty/libtommath/bn_mp_rand.c has​:

  /* first place a random non-zero digit */   do {   d = ((mp_digit) abs (MP_GEN_RANDOM())) & MP_MASK;   } while (d == 0);

  if ((res = mp_add_d (a, d, a)) != MP_OKAY) {   return res;   }

  while (--digits > 0) {   if ((res = mp_lshd (a, 1)) != MP_OKAY) {   return res;   }

  if ((res = mp_add_d (a, ((mp_digit) abs (MP_GEN_RANDOM())), a)) != MP_OKAY) {   return res;   }   }

3rdparty/libtommath/tommath.h has​:

/* use arc4random on platforms that support it */ #ifdef MP_USE_ALT_RAND   #define MP_GEN_RANDOM() arc4random() #else   #define MP_GEN_RANDOM() rand() #endif

#define MP_DIGIT_BIT DIGIT_BIT #define MP_MASK ((((mp_digit)1)\<\<((mp_digit)DIGIT_BIT))-((mp_digit)1)) #define MP_DIGIT_MAX MP_MASK

and

#ifdef MP_31BIT
  /* this is an extension that uses 31-bit digits */   #define DIGIT_BIT 31 #else   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */   #define DIGIT_BIT 28   #define MP_28BIT #endif

Which I think means that it's either using 28 or 31 bit "digits".

IIRC rand() on Win32 only returns 15 bit values. Most *nix systems return 31 bit values. ANSI C only mandates 15 bit as a minimum.

If so, this third-party code is buggy.

But if that's true, why on Earth has no-one else hit this before?

Nicholas Clark

p6rt commented 7 years ago

The RT System itself - Status changed from 'new' to 'open'

p6rt commented 7 years ago

From @geekosaur

On Mon, Feb 6, 2017 at 3​:31 PM, Nicholas Clark \nick@&#8203;ccl4\.org wrote​:

OK, this is a bit of guessing, and I would like to think that I've guessed wrongly because someone else *should* have hit this before...

You'd be surprised. Verifying randomness is fairly tricky... and Perl 3 went through this on a bunch of platforms where the random bits needed to be tuned per platform (before there was any sort of standardization between unixlikes, not to mention Windows, VMS, ...). Nobody noticed for several years that the randbits were wrong on various platforms --- and not all of those platforms were obscure.

-- brandon s allbery kf8nh sine nomine associates allbery.b@​gmail.com ballbery@​sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net