src/Tools/Metis/src/Random.sml
changeset 39348 6f9c9899f99f
child 39408 65a379f4c8f3
equal deleted inserted replaced
39347:50dec19e682b 39348:6f9c9899f99f
       
     1 (*  Title:      Tools/random_word.ML
       
     2     Author:     Makarius
       
     3 
       
     4 Simple generator for pseudo-random numbers, using unboxed word
       
     5 arithmetic only.  Unprotected concurrency introduces some true
       
     6 randomness.
       
     7 *)
       
     8 
       
     9 structure Random :> Random =
       
    10 struct
       
    11 
       
    12 (* random words: 0w0 <= result <= max_word *)
       
    13 
       
    14 (*minimum length of unboxed words on all supported ML platforms*)
       
    15 val _ = Word.wordSize >= 30
       
    16   orelse raise Fail ("Bad platform word size");
       
    17 
       
    18 val max_word = 0wx3FFFFFFF;
       
    19 val top_bit = 0wx20000000;
       
    20 
       
    21 (*multiplier according to Borosh and Niederreiter (for modulus = 2^30),
       
    22   see http://random.mat.sbg.ac.at/~charly/server/server.html*)
       
    23 val a = 0w777138309;
       
    24 fun step x = Word.andb (a * x + 0w1, max_word);
       
    25 
       
    26 fun change r f = r := f (!r);
       
    27 local val rand = (*Unsynchronized.*)ref 0w1
       
    28 in fun nextWord () = ((*Unsynchronized.*)change rand step; ! rand) end;
       
    29 
       
    30 (*NB: higher bits are more random than lower ones*)
       
    31 fun nextBool () = Word.andb (nextWord (), top_bit) = 0w0;
       
    32 
       
    33 
       
    34 (* random integers: 0 <= result < k *)
       
    35 
       
    36 val max_int = Word.toInt max_word;
       
    37 
       
    38 fun nextInt k =
       
    39   if k <= 0 orelse k > max_int then raise Fail ("next_int: out of range")
       
    40   else if k = max_int then Word.toInt (nextWord ())
       
    41   else Word.toInt (Word.mod (nextWord (), Word.fromInt k));
       
    42 
       
    43 (* random reals: 0.0 <= result < 1.0 *)
       
    44 
       
    45 val scaling = real max_int + 1.0;
       
    46 fun nextReal () = real (Word.toInt (nextWord ())) / scaling;
       
    47 
       
    48 end;