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.perl.org/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

Reply via email to