# HG changeset patch # User Steve Losh # Date 1513637599 18000 # Node ID f4d8d363a9dc0ed5d70322e0f8d3b62190f76679 # Parent d997d6e268a3e497c3bec35127aa2f0af23703e6 In quicklisp now diff -r d997d6e268a3 -r f4d8d363a9dc docs/01-installation.markdown --- a/docs/01-installation.markdown Fri Sep 08 19:42:27 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -Installation -============ - -`cl-pcg` is compatible with Quicklisp, but not *in* Quicklisp (yet?). You can -clone the repository into your [Quicklisp local-projects][local] directory for -now. - -[local]: https://www.quicklisp.org/beta/faq.html#local-project diff -r d997d6e268a3 -r f4d8d363a9dc docs/01-usage.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/01-usage.markdown Mon Dec 18 17:53:19 2017 -0500 @@ -0,0 +1,134 @@ +Usage +===== + +`cl-pcg` is a [permuted congruential generator][pcg] implementation in pure +Common Lisp. It provides a high-level API and a low-level API. + +PCGs are **not** cryptographically secure. If you need that, look elsewhere. + +[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! + +`inclusive?` is treated as a generalized boolean, so you can write `(pcg-random +gen -10 10 :inclusive)` if you feel it reads better. + +`pcg-random` can also generate `single-float`s if `bound` and/or `max` are given +as `single-float`s: + + :::lisp + (defparameter *gen* (make-pcg)) + + (pcg-random *gen* 10.0) ; => [0.0, 10.0] + (pcg-random *gen* 0 10.0) ; => [0.0, 10.0] + (pcg-random *gen* -1.0 1.0) ; => [-1.0, 1.0] + +### 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)` functions +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). + +Limitations +----------- + +You can only generate 32-bit integers, and only single floats. This will change +whenever I get around to fixing things up. diff -r d997d6e268a3 -r f4d8d363a9dc docs/02-reference.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/02-reference.markdown Mon Dec 18 17:53:19 2017 -0500 @@ -0,0 +1,140 @@ +# API Reference + +The following is a list of all user-facing parts of `cl-pcg`. + +If there are backwards-incompatible changes to anything listed here, they will +be noted in the changelog and the author will feel bad. + +Anything not listed here is subject to change at any time with no warning, so +don't touch it. + +[TOC] + +## 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?) + +Generate and return a random number in the specified interval. + + If `max` is omitted the interval will be `[0, bound)`. + + If `max` is given the interval will be `[bound, max)`. + + If `inclusive?` is given the interval will be `[bound, max]`. + + If either of `bound` or `max` are floats, the result will be a float. + Otherwise the result will be an integer. + + As a side effect, the state of `pcg` will be advanced. + + + +### `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 d997d6e268a3 -r f4d8d363a9dc docs/02-usage.markdown --- a/docs/02-usage.markdown Fri Sep 08 19:42:27 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -Usage -===== - -`cl-pcg` is a [permuted congruential generator][pcg] implementation in pure -Common Lisp. It provides a high-level API and a low-level API. - -PCGs are **not** cryptographically secure. If you need that, look elsewhere. - -[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! - -`inclusive?` is treated as a generalized boolean, so you can write `(pcg-random -gen -10 10 :inclusive)` if you feel it reads better. - -`pcg-random` can also generate `single-float`s if `bound` and/or `max` are given -as `single-float`s: - - :::lisp - (defparameter *gen* (make-pcg)) - - (pcg-random *gen* 10.0) ; => [0.0, 10.0] - (pcg-random *gen* 0 10.0) ; => [0.0, 10.0] - (pcg-random *gen* -1.0 1.0) ; => [-1.0, 1.0] - -### 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)` functions -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). - -Limitations ------------ - -You can only generate 32-bit integers, and only single floats. This will change -whenever I get around to fixing things up. diff -r d997d6e268a3 -r f4d8d363a9dc docs/03-changelog.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/03-changelog.markdown Mon Dec 18 17:53:19 2017 -0500 @@ -0,0 +1,11 @@ +Changelog +========= + +Here's the list of changes in each released version. + +[TOC] + +v1.0.0 +------ + +Initial release. diff -r d997d6e268a3 -r f4d8d363a9dc docs/03-reference.markdown --- a/docs/03-reference.markdown Fri Sep 08 19:42:27 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -# API Reference - -The following is a list of all user-facing parts of `cl-pcg`. - -If there are backwards-incompatible changes to anything listed here, they will -be noted in the changelog and the author will feel bad. - -Anything not listed here is subject to change at any time with no warning, so -don't touch it. - -[TOC] - -## 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?) - -Generate and return a random number in the specified interval. - - If `max` is omitted the interval will be `[0, bound)`. - - If `max` is given the interval will be `[bound, max)`. - - If `inclusive?` is given the interval will be `[bound, max]`. - - If either of `bound` or `max` are floats, the result will be a float. - Otherwise the result will be an integer. - - As a side effect, the state of `pcg` will be advanced. - - - -### `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 d997d6e268a3 -r f4d8d363a9dc docs/04-changelog.markdown --- a/docs/04-changelog.markdown Fri Sep 08 19:42:27 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -Changelog -========= - -Here's the list of changes in each released version. - -[TOC] - -v1.0.0 ------- - -Initial release. diff -r d997d6e268a3 -r f4d8d363a9dc docs/api.lisp --- a/docs/api.lisp Fri Sep 08 19:42:27 2017 -0400 +++ b/docs/api.lisp Mon Dec 18 17:53:19 2017 -0500 @@ -13,7 +13,7 @@ (d-api:generate-documentation :cl-pcg - #p"docs/03-reference.markdown" + #p"docs/02-reference.markdown" (list "PCG") *header* :title "API Reference") diff -r d997d6e268a3 -r f4d8d363a9dc docs/index.markdown --- a/docs/index.markdown Fri Sep 08 19:42:27 2017 -0400 +++ b/docs/index.markdown Mon Dec 18 17:53:19 2017 -0500 @@ -7,9 +7,13 @@ PCGs are **not** cryptographically secure. If you need that, look elsewhere. +`cl-pcg` can be installed with [Quicklisp][]: `(ql:quickload :cl-pcg)` + [pcg]: http://www.pcg-random.org/ * **License:** MIT * **Documentation:** * **Mercurial:** * **Git:** + +[quicklisp]: https://quicklisp.org/