* Numerical operations::
* Numerical input and output::
* Fixnum and Flonum Operations::
-* Random Numbers::
+* Random Number Generation::
@end menu
@node Numerical types, Exactness, Numbers, Numbers
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
(@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
(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
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.
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