From: Taylor R Campbell Date: Sun, 30 Jun 2019 22:48:30 +0000 (+0000) Subject: Update random number generation section of manual. X-Git-Tag: mit-scheme-pucked-10.1.12~7^2~27 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=eac27dc721f7cb2695bb97a8f4c0c171bd52d2ce;p=mit-scheme.git Update random number generation section of manual. --- diff --git a/doc/ref-manual/numbers.texi b/doc/ref-manual/numbers.texi index cb4867742..8e4ed17c0 100644 --- a/doc/ref-manual/numbers.texi +++ b/doc/ref-manual/numbers.texi @@ -31,7 +31,7 @@ as fixed point and floating point are referred to by names such as * Numerical operations:: * Numerical input and output:: * Fixnum and Flonum Operations:: -* Random Numbers:: +* Random Number Generation:: @end menu @node Numerical types, Exactness, Numbers, Numbers @@ -1508,7 +1508,7 @@ Note that a numeric representation using a decimal point or an exponent marker is not recognized unless @var{radix} is @code{10}. @end deffn -@node Fixnum and Flonum Operations, Random Numbers, Numerical input and output, Numbers +@node Fixnum and Flonum Operations, Random Number Generation, Numerical input and output, Numbers @section Fixnum and Flonum Operations This section describes numerical operations that are restricted forms of @@ -2514,39 +2514,45 @@ call is surrounded by @code{flo:preserving-environment} (@pxref{Floating-Point Environment}). @end deffn -@node Random Numbers, , Fixnum and Flonum Operations, Numbers -@section Random Numbers -@cindex random number -@cindex pseudo-random number -@cindex number, pseudo-random - -MIT/GNU Scheme provides a facility for generating pseudo-random numbers. -The current implementation is a ``subtract-with-carry'' random-number -generator, based on the algorithm from @cite{A New Class of Random -Number Generators}, George Marsaglia and Arif Zaman, @cite{The Annals of -Applied Probability}, Vol.@: 1, No.@: 3, 1991. At the time it was -implemented, this was a good algorithm for general purposes, but the -state of the art in random-number generation is constantly changing. If -necessary, the implementation will be updated to use a new algorithm -while retaining the same interface. - -The interface described here is very similar to that of Common Lisp. - -@deffn procedure random modulus [state] -@var{Modulus} must be a positive real number. @code{random} returns a -pseudo-random number between zero (inclusive) and @var{modulus} -(exclusive). The exactness of the returned number is the same as the -exactness of @var{modulus}. Additionally, if @var{modulus} is an exact -integer, the returned number will be also. Usually, @var{modulus} is -either an exact integer or an inexact real; the current implementation -has been tuned to make these two cases fast. +@node Random Number Generation, , Fixnum and Flonum Operations, Numbers +@section Random Number Generation +@cindex random number generation +@cindex pseudorandom number generation +@cindex number, pseudorandom generation + +MIT/GNU Scheme provides a facility for random number generation. +The current implementation uses the ChaCha stream cipher, reseeding +itself at each request so that past outputs cannot be distinguished +from uniform random even if the state of memory is compromised in the +future. + +The interface described here is a mixture of the Common Lisp and SRFI +27 systems. + +@deffn procedure random m [state] +The argument @var{m} must be either an exact positive integer, or an +inexact positive real. + +@itemize @bullet +@item +If @var{m} is an exact positive integer, then @code{random} returns an +exact nonnegative integer below @var{m} with uniform distribution. + +@item +If @var{m} is an inexact positive real, then @code{random} returns an +inexact real in the interval @math{[0, m)} with uniform distribution. +@end itemize If @var{state} is given and not @code{#f}, it must be a random-state object; otherwise, it defaults to the @code{default-random-source}. -This object is used to maintain the state of the pseudo-random-number +This object is used to maintain the state of the pseudorandom number generator and is altered as a side effect of the @code{random} procedure. +Use of the default random state requires synchronization between +threads, so it is better for multithreaded programs to use explicit +states. + @example @group (random 1.0) @result{} .32744744667719056 @@ -2555,18 +2561,50 @@ procedure. (random 10) @result{} 8 (random 100) @result{} 38 (random 100) @result{} 63 -(random 100/3) @result{} 130501475769920525/6755399441055744 -(random 100/3) @result{} 170571694016427575/13510798882111488 @end group @end example @end deffn +@deffn procedure flo:random-unit-closed state +@deffnx procedure flo:random-unit-open state +@var{State} must be a random-state object. +@code{Flo:random-unit-closed} returns a flonum in the closed interval +@math{[0,1]} with uniform distribution. +In practical terms, the result is in the half-closed interval +@math{(0,1]} because the probability of returning 0 is +@math{2^{-1075}}, far below the standard probability @math{2^{-128}} +that means ``never'' in cryptographic engineering terms. + +@code{Flo:random-unit-open} is like @code{flo:random-unit-closed}, but +it explicitly rejects @code{0.0} and @code{1.0} as outputs, so that +the result is a floating-point number in the open interval +@math{(0,1)}. +@code{(flo:random-unit-open)} is equivalent @code{(random 1.)}, except +that it is faster. + +Callers should generally use @code{flo:random-unit-closed}, because +for the uniform distribution on the interval @math{[0,1]} of real +numbers, the probability of a real number that is rounded to the +floating-point @code{1.0} is the small but nonnegligible +@math{2^{-54}}, and arithmetic downstream should be prepared to handle +results that are rounded to @code{1.0} much more readily than results +that are rounded to @code{0.0} --- in other words, a requirement to +use @code{flo:random-unit-open} is evidence of bad numerics +downstream. +@end deffn + @deffn procedure flo:random-unit state -@var{State} must be a random-state object. @code{flo:random-unit} -returns a pseudo-random number between zero inclusive and one exclusive; -the returned number is always a flonum and therefore an inexact real -number. @code{flo:random-unit} is equivalent to @code{random} with a -@var{modulus} of @code{1.0}, except that it is faster. +Deprecated alias for @code{flo:random-unit-open}. +@end deffn + +@deffn procedure random-bytevector n [state] +Returns a bytevector of @var{n} bytes drawn independently uniformly at +random from @var{state}. +@end deffn + +@deffn procedure random-bytevector! bytevector [start end state] +Replaces the bytes in @var{bytevector} from @var{start} to @var{end} +by bytes drawn independently uniformly at random from @var{state}. @end deffn The next three definitions concern random-state objects. In addition to @@ -2574,7 +2612,7 @@ these definitions, it is important to know that random-state objects are specifically designed so that they can be saved to disk using the @code{fasdump} procedure, and later restored using the @code{fasload} procedure. This allows a particular random-state object to be saved in -order to replay a particular pseudo-random sequence. +order to replay a particular pseudorandom sequence. @defvr variable *random-state* This variable is @strong{deprecated}; pass an explicit state instead. @@ -2595,3 +2633,116 @@ clock). Returns @code{#t} if @var{object} is a random-state object, otherwise returns @code{#f}. @end deffn + +@deffn procedure export-random-state state +@deffnx procedure import-random-state state +@code{Export-random-state} returns an external representation of a +random state --- an object that can be safely read and written with +@code{read} and @code{write}, consisting only of nested lists, +vectors, symbols, and small exact integers. +@code{Import-random-state} creates a random state from its external +representation. +@end deffn + +In the MIT/GNU Scheme implementation of the SRFI 27 API, a ``random +source'' happens to be the same as a random state, but users should +not rely on this. + +@deffn procedure make-random-source +[SRFI 27] +Returns a random source. +Every random source created by @code{make-random-source} returns the +same sequence of outputs unless modified by +@code{random-source-state-set!}, @code{random-source-randomize!}, or +@code{random-source-pseudo-randomize!}. +@end deffn + +@deffn procedure random-source? object +[SRFI 27] +Returns @code{#t} if @var{object} is a random source, otherwise +returns @code{#f}. +@end deffn + +@deffn constant default-random-source +[SRFI 27] +The default random source, used by the various random procedures if no +explicit state is specified and @code{*random-state*} is false. +@end deffn + +@deffn procedure random-source-state-ref source +@deffnx procedure random-source-state-set! source exported-state +[SRFI 27] +@code{Random-source-state-ref} returns an external representation of a +random source --- an object that can be safely read and written with +@code{read} and @code{write}, consisting only of nested lists, +vectors, symbols, and small exact integers. +@code{Random-source-state-set!} replaces the innards of @var{source} +by the source represented by @var{exported-state} from +@code{random-source-state-ref}. +@end deffn + +@deffn procedure random-source-randomize! source +[SRFI 27] +Loads entropy from the environment into @var{source} so that its +subsequent outputs are nondeterministic. + +@strong{Warning:} Most implementations of SRFI 27 @emph{do not} make +subsequent outputs unpredictable with cryptography, so don't rely on +this. +@end deffn + +@deffn procedure random-source-pseudo-randomize! source i j +[SRFI 27] +The arguments @var{i} and @var{j} must be exact nonnegative integers +below @math{2^{128}}. +This procedure sets @var{source} to generate one of @math{2^{256}} +distinct possible streams of output, so that if @var{i} and @var{j} +are chosen uniformly at random, it is hard to distinguish the outputs +of the source from uniform random. + +@strong{Warning:} Most implementations of SRFI 27 @emph{do not} make +it hard to distinguish the outputs of the source from uniform random +even if the indices @var{i} and @var{j} are uniform random, so don't +rely on this. +@end deffn + +@deffn procedure random-integer n +[SRFI 27] +Returns an exact nonnegative integer below @var{n} chosen uniformly at +random. + +Equivalent to: + +@example +((random-source-make-integers default-random-source) n) +@end example +@end deffn + +@deffn procedure random-real +[SRFI 27] +Returns an inexact real in the open interval @math{(0, 1)} with +uniform distribution. + +Equivalent to: + +@example +((random-source-make-reals default-random-source)) +@end example +@end deffn + +@deffn procedure random-source-make-integers source +[SRFI 27] +Returns a procedure of one argument, @var{n}, that deterministically +draws from @var{source} a exact nonnegative integer below @var{n} with +uniform distribution. +@end deffn + +@deffn procedure random-source-make-reals source [unit] +[SRFI 27] +Returns a procedure of zero arguments that deterministically draws +from @var{source} an inexact real in the interval @math{(0,1)} with +uniform distribution. +If @var{unit} is specified, the results are instead uniform random +integral multiples of @var{unit} in @math{(0,1)} and of the same +exactness as @var{unit}. +@end deffn diff --git a/doc/ref-manual/scheme.texinfo b/doc/ref-manual/scheme.texinfo index d25f2feff..80cd248e8 100644 --- a/doc/ref-manual/scheme.texinfo +++ b/doc/ref-manual/scheme.texinfo @@ -206,7 +206,7 @@ Numbers * Numerical operations:: * Numerical input and output:: * Fixnum and Flonum Operations:: -* Random Numbers:: +* Random Number Generation:: Fixnum and Flonum Operations