PreviousUpNext

15.4.979  src/lib/src/rand.pkg

## rand.pkg

# Compiled by:
#     src/lib/std/standard.lib

# Random number generator taken from Paulson, pages 170-171.
# Recommended by Stephen K. Park and Keith W. Miller, 
# Random number generators: good ones are hard to find,
# CACM 31 (1988), 1192-1201
# Updated to include the new preferred multiplier of 48271
# CACM 36 (1993), 105-110
# Updated to use on tagged_unt.
#
# Note: The Random package provides a better generator.


###               "The generation of random numbers is
###                too important to be left to chance."
###
###                               -- Robert Coveyou

###               "We must believe in luck.
###                For how else can we explain the
###                success of those we don't like?"
###
###                           -- Jean Cocteau



stipulate
    package f8b =  eight_byte_float;                                    # eight_byte_float      is from   src/lib/std/eight-byte-float.pkg
herein

    package   rand
    : (weak)  Rand                                                      # Rand                  is from   src/lib/src/rand.api
    {
        Rand  = tagged_unt::Unt;
        Rand' = one_word_int::Int;  #  internal representation 

        my a:  Rand' = 48271;
        my m:  Rand' = 2147483647;  #  2^31 - 1 

        m_1 =  m - 1;

        q =  m / a;
        r =  m % a;

        ext_to_int = one_word_int::from_multiword_int o tagged_unt::to_multiword_int;
        int_to_ext = tagged_unt::from_multiword_int o one_word_int::to_multiword_int;

        my rand_min:  Rand = 0u1;
        my rand_max:  Rand = int_to_ext m_1;

        fun check 0u0 => 1;
            check 0ux7fffffff => m_1;
            check seed => ext_to_int seed;
        end;

        fun random' seed
            =
            {   hi = seed / q;
                lo = seed % q;
                test = a * lo - r * hi;

                test > 0   ??  test
                           ::  test + m;
            };

        random =  int_to_ext  o  random'  o  check;

        fun make_random seed
            =
            {   seed = REF (check seed);

               {.   seed := random' *seed;
                    int_to_ext *seed;
                };
            };

        float_m = f8b::from_multiword_int (one_word_int::to_multiword_int m);

        fun normalize s
            =
            (f8b::from_multiword_int (tagged_unt::to_multiword_int s)) / float_m;

        fun range (i, j)
            = 
            if (j < i)
                #
                lib_base::failure { module=>"Random", fn=>"range", msg=>"hi < lo"};

            elif (j == i)

                \\ _ = i;
            else
                rrr = one_word_int::from_int j - one_word_int::from_int i;

                convert = tagged_unt::to_int_x o tagged_unt::from_multiword_int o one_word_int::to_multiword_int;

                if (rrr == m)  tagged_unt::to_int_x;
                else           \\ s =  i + convert ((ext_to_int s) % (rrr+1));
                fi;
            fi;

    };  #  rand 
end;


## COPYRIGHT (c) 1991 by AT&T Bell Laboratories.  See SMLNJ-COPYRIGHT file for details.
## COPYRIGHT (c) 1998 by AT&T Laboratories.       See SMLNJ-COPYRIGHT file for details.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext