# HG changeset patch # User Steve Losh # Date 1489706931 0 # Node ID 5d2375b8ba787c71b9f658c3b3128a93af3cc530 # Parent 97926c261ee7c5ac074d094f2f9a17a84db36191 Update docs diff -r 97926c261ee7 -r 5d2375b8ba78 docs/02-usage.markdown --- a/docs/02-usage.markdown Thu Mar 16 22:39:40 2017 +0000 +++ b/docs/02-usage.markdown Thu Mar 16 23:28:51 2017 +0000 @@ -1,9 +1,116 @@ Usage ===== -cl-pcg is... +`cl-pcg` is a [permuted congruential generator][pcg] implementation in pure +Common Lisp. It provides a high-level API and a low-level API. [pcg]: http://www.pcg-random.org/ [TOC] +The High-Level API +------------------ + +The high-level API is what you should start (and probably end) with. It +typechecks the arguments you pass in and offers a nice interface for generating +random numbers. + +### Creating a Generator + +To create a generator you can use the `make-pcg` function: + + :::lisp + (defparameter *gen* (make-pcg)) + +`make-pcg` takes two keyword parameters: + +* `:seed` should be an `(unsigned-byte 64)`. If omitted a random seed will be + generated with the underlying implementation's `cl:random` function. +* `:stream-id` should be an `(unsigned-byte 32)`. The default is `0`. Streams + provide a way to "split" a PCG into multiple generators — check out the PCG + site for more information on this. + +Once you've got a PCG object you can use it to generate some numbers. + +### Generating Numbers + +You can use the `pcg-random` function to generate random numbers: + + :::lisp + (defparameter *gen* (make-pcg)) + + (pcg-random *gen* 10) + ; => a random number from 0 (inclusive) to 10 (exclusive) + +`pcg-random` is flexible and takes a number of optional arguments to help you +generate the kinds of numbers you need. Its lambda list looks like this: + + :::lisp + (pcg bound &optional max inclusive?) + +If only `bound` is given, the function acts much like `cl:random`. + +If `max` is also given, a random number in `[bound, max)` is chosen. + +If `inclusive?` is also given, a random number in `[bound, max]` is chosen. + +For example: + + :::lisp + (defparameter *gen* (make-pcg)) + + (pcg-random *gen* 10) ; => [0, 10) + (pcg-random *gen* 15 28) ; => [15, 28) + (pcg-random *gen* 15 28 t) ; => [15, 28] <- inclusive endpoint! + +`pcg-random` can also generate `single-float`s if `bound` and `max` are given as +`single-float`s. + +### The Global Generator + +If you don't want to bother creating a fresh PCG object you can pass `t` to the +high-level API to use a globally-defined one: + + :::lisp + (pcg-random t 10) + +### Advancing & Rewinding + +Sometimes it can be useful to advance or rewind a generator by a certain number +of steps. The `(pcg-advance pcg steps)` and `(pcg-rewind pcg steps)` can be +used to do this: + + :::lisp + (defparameter *gen* (make-pcg)) + + ;; Get three numbers + (pcg-random *gen* 1000) ; => 708 + (pcg-random *gen* 1000) ; => 964 + (pcg-random *gen* 1000) ; => 400 + + ;; Rewind three steps + (pcg-rewind *gen* 3) + + ;; Get the same three numbers + (pcg-random *gen* 1000) ; => 708 + (pcg-random *gen* 1000) ; => 964 + (pcg-random *gen* 1000) ; => 400 + +These functions are `O(log₂(steps))` so they'll be fast even for ludicrously +large values of `steps`. + + +The Low-Level API +----------------- + +The low-level API is what you want if you need raw speed. It consists of all +functions in the API whose names end in `%`, like `pcg-random%`. All of these +functions are `declaim`ed inline for easy embedding into hot loops. + +As an arbitrary example, the main function in this API (`pcg-random%`) is about +100 bytes of machine code, so it's suitable for inlining when you really need +performance. + +The low-level API assumes you will pass in arguments of the correct type. If +you fuck this up, all bets are off. Read the code to figure out exactly what +you need to pass in (or just use the high-level API like a sane person). diff -r 97926c261ee7 -r 5d2375b8ba78 docs/03-reference.markdown --- a/docs/03-reference.markdown Thu Mar 16 22:39:40 2017 +0000 +++ b/docs/03-reference.markdown Thu Mar 16 23:28:51 2017 +0000 @@ -12,3 +12,114 @@ ## Package `PCG` +### `MAKE-PCG` (function) + + (MAKE-PCG &KEY (SEED NIL) (STREAM-ID 0)) + +Create and return a new PCG. + + If `seed` is `nil`, a fresh random seed will be generated with the + implementation's `cl:random` function, as if by: + + (random ... (make-random-state t)) + + + +### `MAKE-PCG%` (function) + + (MAKE-PCG% SEED STREAM-ID) + +Create and return a new `pcg` for the given `seed` and `stream-id`. + + This is a low-level function that assumes you are passing in the correct types. + + + +### `PCG` (struct) + +Slots: `STATE`, `INCREMENT` + +### `PCG-ADVANCE` (function) + + (PCG-ADVANCE PCG STEPS) + +Advance the state of `pcg` by `steps` steps. + + This function returns `nil` and is only useful for its side effects. + + + +### `PCG-ADVANCE%` (function) + + (PCG-ADVANCE% PCG STEPS) + +Advance the state of `pcg` by `steps` steps. + + This function returns `nil` and is only useful for its side effects. + + This is a low-level function that assumes you are passing in the correct types. + + + +### `PCG-RANDOM` (function) + + (PCG-RANDOM PCG BOUND &OPTIONAL MAX INCLUSIVE?) + +### `PCG-RANDOM%` (function) + + (PCG-RANDOM% PCG) + +Return a random `(unsigned-byte 32)`. + + As a side effect, the state of `pcg` will be advanced. + + This is a low-level function that assumes you are passing in the correct types. + + + +### `PCG-RANDOM-BOUNDED%` (function) + + (PCG-RANDOM-BOUNDED% PCG BOUND) + +Return a random integer between `0` (inclusive) and `bound` (exclusive). + + As a side effect, the state of `pcg` will be advanced. + + This is a low-level function that assumes you are passing in the correct types. + + + +### `PCG-RANDOM-FLOAT%` (function) + + (PCG-RANDOM-FLOAT% PCG) + +Return a random `single-float` between `0.0` and `1.0`. + + As a side effect, the state of `pcg` will be advanced. + + This is a low-level function that assumes you are passing in the correct types. + + + +### `PCG-REWIND` (function) + + (PCG-REWIND PCG STEPS) + +Rewind the state of `pcg` by `steps` steps. + + This function returns `nil` and is only useful for its side effects. + + + +### `PCG-REWIND%` (function) + + (PCG-REWIND% PCG STEPS) + +Rewind the state of `pcg` by `steps` steps. + + This function returns `nil` and is only useful for its side effects. + + This is a low-level function that assumes you are passing in the correct types. + + + diff -r 97926c261ee7 -r 5d2375b8ba78 package.lisp --- a/package.lisp Thu Mar 16 22:39:40 2017 +0000 +++ b/package.lisp Thu Mar 16 23:28:51 2017 +0000 @@ -1,4 +1,19 @@ (defpackage :pcg (:use :cl :pcg.quickutils) (:export + ;; High-Level API + :pcg + :make-pcg + :pcg-random + :pcg-advance + :pcg-rewind + + ;; Low-Level API + :make-pcg% + :pcg-random% + :pcg-random-bounded% + :pcg-random-float% + :pcg-advance% + :pcg-rewind% + ))