generators.lisp 6.76 KB
Newer Older
1 2
;; Generators of random numbers.
;; Liam Healy, Sat Jul 15 2006 - 14:43
Liam Healy's avatar
Liam Healy committed
3
;; Time-stamp: <2009-01-25 09:57:17EST generators.lisp>
lhealy's avatar
lhealy committed
4
;; $Id$
liam's avatar
liam committed
5 6 7

(in-package :gsl)

8 9
;;; /usr/include/gsl/gsl_rng.h

liam's avatar
liam committed
10
;;;;****************************************************************************
11
;;;; Object
liam's avatar
liam committed
12 13
;;;;****************************************************************************

14 15 16
(defmobject random-number-generator
    "gsl_rng"
  ((rng-type :pointer))
Liam Healy's avatar
Liam Healy committed
17 18
  "random number generator"
  :documentation			; FDL
19 20 21 22 23 24 25 26 27 28
  "Make and optionally initialize (or `seed') the random number
   generator of the specified type.  If the generator is seeded with
   the same value of s on two different runs, the same stream of
   random numbers will be generated by successive calls.  If different
   values of s are supplied, then the generated streams of random
   numbers should be completely different.  If the seed s is zero then
   the standard seed from the original implementation is used instead.
   For example, the original Fortran source code for the *ranlux*
   generator used a seed of 314159265, and so choosing s equal to zero
   reproduces this when using *ranlux*."
Liam Healy's avatar
Liam Healy committed
29 30
  :initialize-suffix ("set" :void)
  :initialize-args ((value :ulong)))
liam's avatar
liam committed
31 32 33 34 35

;;;;****************************************************************************
;;;; Seed
;;;;****************************************************************************

36 37 38 39
(defmpar *default-seed*
    "gsl_rng_default_seed"
  "The default seed for random number generators."
  :ulong nil)
liam's avatar
liam committed
40 41 42 43 44

;;;;****************************************************************************
;;;; Sampling
;;;;****************************************************************************

liam's avatar
liam committed
45
(defmfun get-random-number (generator)
46
  "gsl_rng_get" (((mpointer generator) :pointer))
liam's avatar
liam committed
47
  :c-return :ulong
liam's avatar
liam committed
48
  :documentation			; FDL
liam's avatar
liam committed
49 50
  "Generate a random integer.  The
   minimum and maximum values depend on the algorithm used, but all
liam's avatar
liam committed
51 52 53
   integers in the range [min, max] are equally likely.  The
   values of min and max can determined using the auxiliary
   functions #'rng-max and #'rng-min.")
liam's avatar
liam committed
54

liam's avatar
liam committed
55
(defmfun uniform (generator)
56
  "gsl_rng_uniform" (((mpointer generator) :pointer))
liam's avatar
liam committed
57
  :c-return :double
liam's avatar
liam committed
58
  :documentation			; FDL
liam's avatar
liam committed
59 60 61 62 63 64 65 66 67
  "A double precision floating point number uniformly
   distributed in the range [0,1).  The range includes 0.0 but excludes 1.0.
   The value is typically obtained by dividing the result of
   #'rng-get by (+ (rng-max generator) 1.0) in double
   precision.  Some generators compute this ratio internally so that they
   can provide floating point numbers with more than 32 bits of randomness
   (the maximum number of bits that can be portably represented in a single
   :ulong.")

liam's avatar
liam committed
68
(defmfun uniform>0 (generator)
69
  "gsl_rng_uniform_pos" (((mpointer generator) :pointer))
liam's avatar
liam committed
70
  :c-return :double
liam's avatar
liam committed
71
  :documentation			; FDL
liam's avatar
liam committed
72 73 74
  "Return a positive double precision floating point number
   uniformly distributed in the range (0,1), excluding both 0.0 and 1.0.
   The number is obtained by sampling the generator with the algorithm of
liam's avatar
liam committed
75
   #'uniform until a non-zero value is obtained.  You can use
liam's avatar
liam committed
76 77
   this function if you need to avoid a singularity at 0.0.")

liam's avatar
liam committed
78
(defmfun uniform-fixnum (generator upperbound)
79 80
  "gsl_rng_uniform_int"
  (((mpointer generator) :pointer) (upperbound :ulong))
liam's avatar
liam committed
81
  :c-return :ulong
liam's avatar
liam committed
82
  :documentation			; FDL
liam's avatar
liam committed
83 84 85 86 87 88 89 90 91 92 93
  "Generate a random integer from 0 to upperbound-1 inclusive.
   All integers in the range are equally likely, regardless
   of the generator used.  An offset correction is applied so that zero is
   always returned with the correct probability, for any minimum value of
   the underlying generator.  If upperbound is larger than the range
   of the generator then the function signals an error.")

;;;;****************************************************************************
;;;; Information functions about instances
;;;;****************************************************************************

94 95
(defmfun name ((rng-instance random-number-generator))
  "gsl_rng_name" (((mpointer rng-instance) :pointer))
Liam Healy's avatar
Liam Healy committed
96
  :definition :method
97
  :c-return :string)
liam's avatar
liam committed
98

liam's avatar
liam committed
99
(defmfun rng-max (rng-instance)
100
  "gsl_rng_max" (((mpointer rng-instance) :pointer))
liam's avatar
liam committed
101
  :c-return :unsigned-long
liam's avatar
liam committed
102
  :documentation "The largest value that #'get-random-number
liam's avatar
liam committed
103 104
   can return.")

liam's avatar
liam committed
105
(defmfun rng-min (rng-instance)
106
  "gsl_rng_min" (((mpointer rng-instance) :pointer))
liam's avatar
liam committed
107
  :c-return :unsigned-long
liam's avatar
liam committed
108 109
  :documentation			; FDL
  "The smallest value that #'get-random-number
liam's avatar
liam committed
110 111 112 113
   can return.  Usually this value is zero.  There are some generators with
   algorithms that cannot return zero, and for these generators the minimum
   value is 1.")

114 115 116 117 118
(export 'rng-state)
(defgeneric rng-state (rng-instance)
  (:documentation			; FDL
   "A pointer to the state of generator."))

liam's avatar
liam committed
119
(defmfun rng-state ((rng-instance random-number-generator))
120
  "gsl_rng_state" (((mpointer rng-instance) :pointer))
liam's avatar
liam committed
121
  :c-return :pointer
Liam Healy's avatar
Liam Healy committed
122
  :definition :method
123 124 125 126 127 128
  :index gsl-random-state)

(export 'rng-size)
(defgeneric rng-size (rng-instance)
  (:documentation			; FDL
   "The size of the generator."))
liam's avatar
liam committed
129

liam's avatar
liam committed
130
(defmfun rng-size ((rng-instance random-number-generator))
131
  "gsl_rng_size" (((mpointer rng-instance) :pointer))
Liam Healy's avatar
Liam Healy committed
132 133
  :c-return sizet
  :definition :method
134
  :index gsl-random-state)
liam's avatar
liam committed
135 136 137 138 139

(export 'gsl-random-state)
(defun gsl-random-state (rng-instance)
  "The complete state of a given random number generator, specified
   as a vector of bytes."
140
  (let* ((gen rng-instance)
liam's avatar
liam committed
141 142 143 144 145 146 147 148 149 150 151 152 153
	 (ans
	  (make-array (rng-size gen)
		      :element-type '(unsigned-byte 8))))
    (loop for i from 0 below (length ans)
       do
       (setf (aref ans i)
	     (mem-aref (rng-state gen) :uint8 i)))
    ans))

;;;;****************************************************************************
;;;; Copying state
;;;;****************************************************************************

Liam Healy's avatar
Liam Healy committed
154 155
(defmfun copy-to-destination
    ((source random-number-generator) (destination random-number-generator))
liam's avatar
liam committed
156
  "gsl_rng_memcpy"
157
  (((mpointer destination) :pointer) ((mpointer source) :pointer))
Liam Healy's avatar
Liam Healy committed
158
  :definition :method
Liam Healy's avatar
Liam Healy committed
159
  :index copy
160 161 162 163 164 165
  :documentation			; FDL
  "Copy the random number generator source into the
   pre-existing generator destination,
   making destination into an exact copy
   of source.  The two generators must be of the same type.")

Liam Healy's avatar
Liam Healy committed
166
(defmfun copy-making-destination ((instance random-number-generator))
167
  "gsl_rng_clone" (((mpointer instance) :pointer))
168
  :definition :method
Liam Healy's avatar
Liam Healy committed
169 170
  :c-return :pointer
  :index copy)
liam's avatar
liam committed
171 172 173 174 175

;;;;****************************************************************************
;;;; Examples and unit test
;;;;****************************************************************************

Liam Healy's avatar
Liam Healy committed
176
(save-test random-number-generators
177
 (let ((rng (make-random-number-generator *mt19937* 0)))
liam's avatar
liam committed
178 179 180
   (loop for i from 0 to 10
	 collect
	 (uniform-fixnum rng 1000)))
181
 (let ((rng (make-random-number-generator *cmrg* 0)))
liam's avatar
liam committed
182
   (loop for i from 0 to 10 collect (uniform rng))))