| 1 |
(in-package :alexandria) |
|---|
| 2 |
|
|---|
| 3 |
(declaim (inline clamp)) |
|---|
| 4 |
(defun clamp (number min max) |
|---|
| 5 |
"Clamps the NUMBER into [MIN, MAX] range. Returns MIN if NUMBER lesser then |
|---|
| 6 |
MIN and MAX if NUMBER is greater then MAX, otherwise returns NUMBER." |
|---|
| 7 |
(if (< number min) |
|---|
| 8 |
min |
|---|
| 9 |
(if (> number max) |
|---|
| 10 |
max |
|---|
| 11 |
number))) |
|---|
| 12 |
|
|---|
| 13 |
(defun gaussian-random (&optional min max) |
|---|
| 14 |
"Returns two gaussian random double floats as the primary and secondary value, |
|---|
| 15 |
optionally constrained by MIN and MAX. Gaussian random numbers form a standard |
|---|
| 16 |
normal distribution around 0.0d0." |
|---|
| 17 |
(labels ((gauss () |
|---|
| 18 |
(loop |
|---|
| 19 |
for x1 = (- (random 2.0d0) 1.0d0) |
|---|
| 20 |
for x2 = (- (random 2.0d0) 1.0d0) |
|---|
| 21 |
for w = (+ (expt x1 2) (expt x2 2)) |
|---|
| 22 |
when (< w 1.0d0) |
|---|
| 23 |
do (let ((v (sqrt (/ (* -2.0d0 (log w)) w)))) |
|---|
| 24 |
(return (values (* x1 v) (* x2 v)))))) |
|---|
| 25 |
(guard (x min max) |
|---|
| 26 |
(unless (<= min x max) |
|---|
| 27 |
(tagbody |
|---|
| 28 |
:retry |
|---|
| 29 |
(multiple-value-bind (x1 x2) (gauss) |
|---|
| 30 |
(when (<= min x1 max) |
|---|
| 31 |
(setf x x1) |
|---|
| 32 |
(go :done)) |
|---|
| 33 |
(when (<= min x2 max) |
|---|
| 34 |
(setf x x2) |
|---|
| 35 |
(go :done)) |
|---|
| 36 |
(go :retry)) |
|---|
| 37 |
:done)) |
|---|
| 38 |
x)) |
|---|
| 39 |
(multiple-value-bind (g1 g2) (gauss) |
|---|
| 40 |
(values (guard g1 (or min g1) (or max g1)) |
|---|
| 41 |
(guard g2 (or min g2) (or max g2)))))) |
|---|
| 42 |
|
|---|
| 43 |
(declaim (inline iota)) |
|---|
| 44 |
(defun iota (n &key (start 0) (step 1)) |
|---|
| 45 |
"Return a list of n numbers, starting from START (with numeric contagion |
|---|
| 46 |
from STEP applied), each consequtive number being the sum of the previous one |
|---|
| 47 |
and STEP. START defaults to 0 and STEP to 1. |
|---|
| 48 |
|
|---|
| 49 |
Examples: |
|---|
| 50 |
|
|---|
| 51 |
(iota 4) => (0 1 2 3 4) |
|---|
| 52 |
(iota 3 :start 1 :step 1.0) => (1.0 2.0 3.0) |
|---|
| 53 |
(iota 3 :start -1 :step -1/2) => (-1 -3/2 -2) |
|---|
| 54 |
" |
|---|
| 55 |
(declare (type (integer 0) n) (number start step)) |
|---|
| 56 |
(loop repeat n |
|---|
| 57 |
;; KLUDGE: get numeric contagion right for the first element too |
|---|
| 58 |
for i = (+ start (- step step)) then (+ i step) |
|---|
| 59 |
collect i)) |
|---|
| 60 |
|
|---|
| 61 |
(declaim (inline map-iota)) |
|---|
| 62 |
(defun map-iota (function n &key (start 0) (step 1)) |
|---|
| 63 |
"Calls FUNCTION with N numbers, starting from START (with numeric contagion |
|---|
| 64 |
from STEP applied), each consequtive number being the sum of the previous one |
|---|
| 65 |
and STEP. START defaults to 0 and STEP to 1. Returns N. |
|---|
| 66 |
|
|---|
| 67 |
Examples: |
|---|
| 68 |
|
|---|
| 69 |
(map-iota #'print 3 :start 1 :step 1.0) => 3 |
|---|
| 70 |
;;; 1.0 |
|---|
| 71 |
;;; 2.0 |
|---|
| 72 |
;;; 3.0 |
|---|
| 73 |
" |
|---|
| 74 |
(declare (type (integer 0) n) (number start step)) |
|---|
| 75 |
(loop repeat n |
|---|
| 76 |
;; KLUDGE: get numeric contagion right for the first element too |
|---|
| 77 |
for i = (+ start (- step step)) then (+ i step) |
|---|
| 78 |
do (funcall function i)) |
|---|
| 79 |
n) |
|---|
| 80 |
|
|---|
| 81 |
(declaim (inline lerp)) |
|---|
| 82 |
(defun lerp (v a b) |
|---|
| 83 |
"Returns the result of linear interpolation between A and B, using the |
|---|
| 84 |
interpolation coefficient V." |
|---|
| 85 |
(+ a (* v (- b a)))) |
|---|
| 86 |
|
|---|
| 87 |
(declaim (inline mean)) |
|---|
| 88 |
(defun mean (sample) |
|---|
| 89 |
"Returns the mean of SAMPLE. SAMPLE must be a sequence of numbers." |
|---|
| 90 |
(/ (reduce #'+ sample) (length sample))) |
|---|
| 91 |
|
|---|
| 92 |
(declaim (inline median)) |
|---|
| 93 |
(defun median (sample) |
|---|
| 94 |
"Returns median of SAMPLE. SAMPLE must be a sequence of real numbers." |
|---|
| 95 |
(let* ((vector (sort (copy-sequence 'vector sample) #'<)) |
|---|
| 96 |
(length (length vector)) |
|---|
| 97 |
(middle (truncate length 2))) |
|---|
| 98 |
(if (oddp length) |
|---|
| 99 |
(aref vector middle) |
|---|
| 100 |
(/ (+ (aref vector middle) (aref vector (1+ middle))) 2)))) |
|---|
| 101 |
|
|---|
| 102 |
(declaim (inline variance)) |
|---|
| 103 |
(defun variance (sample &key (biased t)) |
|---|
| 104 |
"Variance of SAMPLE. Returns the biased variance if BIASED is true (the default), |
|---|
| 105 |
and the unbiased estimator of variance if BIASED is false. SAMPLE must be a |
|---|
| 106 |
sequence of numbers." |
|---|
| 107 |
(let ((mean (mean sample))) |
|---|
| 108 |
(/ (reduce (lambda (a b) |
|---|
| 109 |
(+ a (expt (- b mean) 2))) |
|---|
| 110 |
sample |
|---|
| 111 |
:initial-value 0) |
|---|
| 112 |
(- (length sample) (if biased 0 1))))) |
|---|
| 113 |
|
|---|
| 114 |
(declaim (inline standard-deviation)) |
|---|
| 115 |
(defun standard-deviation (sample &key (biased t)) |
|---|
| 116 |
"Standard deviation of SAMPLE. Returns the biased standard deviation if |
|---|
| 117 |
BIASED is true (the default), and the square root of the unbiased estimator |
|---|
| 118 |
for variance if BIASED is false (which is not the same as the unbiased |
|---|
| 119 |
estimator for standard deviation). SAMPLE must be a sequence of numbers." |
|---|
| 120 |
(sqrt (variance sample :biased biased))) |
|---|
| 121 |
|
|---|
| 122 |
(define-modify-macro maxf (&rest numbers) max |
|---|
| 123 |
"Modify-macro for MAX. Sets place designated by the first argument to the |
|---|
| 124 |
maximum of its original value and NUMBERS.") |
|---|
| 125 |
|
|---|
| 126 |
(define-modify-macro minf (&rest numbers) min |
|---|
| 127 |
"Modify-macro for MIN. Sets place designated by the first argument to the |
|---|
| 128 |
minimum of its original value and NUMBERS.") |
|---|
| 129 |
|
|---|
| 130 |
;;;; Factorial |
|---|
| 131 |
|
|---|
| 132 |
;;; KLUDGE: This is really dependant on the numbers in question: for |
|---|
| 133 |
;;; small numbers this is larger, and vice versa. Ideally instead of a |
|---|
| 134 |
;;; constant we would have RANGE-FAST-TO-MULTIPLY-DIRECTLY-P. |
|---|
| 135 |
(defconstant +factorial-bisection-range-limit+ 8) |
|---|
| 136 |
|
|---|
| 137 |
;;; KLUDGE: This is really platform dependant: ideally we would use |
|---|
| 138 |
;;; (load-time-value (find-good-direct-multiplication-limit)) instead. |
|---|
| 139 |
(defconstant +factorial-direct-multiplication-limit+ 13) |
|---|
| 140 |
|
|---|
| 141 |
(defun %multiply-range (i j) |
|---|
| 142 |
;; We use a a bit of cleverness here: |
|---|
| 143 |
;; |
|---|
| 144 |
;; 1. For large factorials we bisect in order to avoid expensive bignum |
|---|
| 145 |
;; multiplications: 1 x 2 x 3 x ... runs into bignums pretty soon, |
|---|
| 146 |
;; and once it does that all further multiplications will be with bignums. |
|---|
| 147 |
;; |
|---|
| 148 |
;; By instead doing the multiplication in a tree like |
|---|
| 149 |
;; ((1 x 2) x (3 x 4)) x ((5 x 6) x (7 x 8)) |
|---|
| 150 |
;; we manage to get less bignums. |
|---|
| 151 |
;; |
|---|
| 152 |
;; 2. Division isn't exactly free either, however, so we don't bisect |
|---|
| 153 |
;; all the way down, but multiply ranges of integers close to each |
|---|
| 154 |
;; other directly. |
|---|
| 155 |
;; |
|---|
| 156 |
;; For even better results it should be possible to use prime |
|---|
| 157 |
;; factorization magic, but Nikodemus ran out of steam. |
|---|
| 158 |
;; |
|---|
| 159 |
;; KLUDGE: We support factorials of bignums, but it seems quite |
|---|
| 160 |
;; unlikely anyone would ever be able to use them on a modern lisp, |
|---|
| 161 |
;; since the resulting numbers are unlikely to fit in memory... but |
|---|
| 162 |
;; it would be extremely unelegant to define FACTORIAL only on |
|---|
| 163 |
;; fixnums, _and_ on lisps with 16 bit fixnums this can actually be |
|---|
| 164 |
;; needed. |
|---|
| 165 |
(labels ((bisect (j k) |
|---|
| 166 |
(declare (type (integer 1 #.most-positive-fixnum) j k)) |
|---|
| 167 |
(if (< (- k j) +factorial-bisection-range-limit+) |
|---|
| 168 |
(multiply-range j k) |
|---|
| 169 |
(let ((middle (+ j (truncate (- k j) 2)))) |
|---|
| 170 |
(* (bisect j middle) |
|---|
| 171 |
(bisect (+ middle 1) k))))) |
|---|
| 172 |
(bisect-big (j k) |
|---|
| 173 |
(declare (type (integer 1) j k)) |
|---|
| 174 |
(if (= j k) |
|---|
| 175 |
j |
|---|
| 176 |
(let ((middle (+ j (truncate (- k j) 2)))) |
|---|
| 177 |
(* (if (<= middle most-positive-fixnum) |
|---|
| 178 |
(bisect j middle) |
|---|
| 179 |
(bisect-big j middle)) |
|---|
| 180 |
(bisect-big (+ middle 1) k))))) |
|---|
| 181 |
(multiply-range (j k) |
|---|
| 182 |
(declare (type (integer 1 #.most-positive-fixnum) j k)) |
|---|
| 183 |
(do ((f k (* f m)) |
|---|
| 184 |
(m (1- k) (1- m))) |
|---|
| 185 |
((< m j) f) |
|---|
| 186 |
(declare (type (integer 0 (#.most-positive-fixnum)) m) |
|---|
| 187 |
(type unsigned-byte f))))) |
|---|
| 188 |
(bisect i j))) |
|---|
| 189 |
|
|---|
| 190 |
(declaim (inline factorial)) |
|---|
| 191 |
(defun %factorial (n) |
|---|
| 192 |
(if (< n 2) |
|---|
| 193 |
1 |
|---|
| 194 |
(%multiply-range 1 n))) |
|---|
| 195 |
|
|---|
| 196 |
(defun factorial (n) |
|---|
| 197 |
"Factorial of non-negative integer N." |
|---|
| 198 |
(check-type n (integer 0)) |
|---|
| 199 |
(%factorial n)) |
|---|
| 200 |
|
|---|
| 201 |
;;;; Combinatorics |
|---|
| 202 |
|
|---|
| 203 |
(defun binomial-coefficient (n k) |
|---|
| 204 |
"Binomial coefficient of N and K, also expressed as N choose K. This is the |
|---|
| 205 |
number of K element combinations given N choises. N must be equal to or |
|---|
| 206 |
greater then K." |
|---|
| 207 |
(check-type n (integer 0)) |
|---|
| 208 |
(check-type k (integer 0)) |
|---|
| 209 |
(assert (>= n k)) |
|---|
| 210 |
(if (or (zerop k) (= n k)) |
|---|
| 211 |
1 |
|---|
| 212 |
(let ((n-k (- n k))) |
|---|
| 213 |
(if (= 1 n-k) |
|---|
| 214 |
n |
|---|
| 215 |
;; General case, avoid computing the 1x...xK twice: |
|---|
| 216 |
;; |
|---|
| 217 |
;; N! 1x...xN (K+1)x...xN |
|---|
| 218 |
;; -------- = ---------------- = ------------, N>1 |
|---|
| 219 |
;; K!(N-K)! 1x...xK x (N-K)! (N-K)! |
|---|
| 220 |
(/ (%multiply-range (+ k 1) n) |
|---|
| 221 |
(%factorial n-k)))))) |
|---|
| 222 |
|
|---|
| 223 |
(defun subfactorial (n) |
|---|
| 224 |
"Subfactorial of the non-negative integer N." |
|---|
| 225 |
(check-type n (integer 0)) |
|---|
| 226 |
(case n |
|---|
| 227 |
(0 1) |
|---|
| 228 |
(1 0) |
|---|
| 229 |
(otherwise |
|---|
| 230 |
(floor (/ (+ 1 (factorial n)) (exp 1)))))) |
|---|
| 231 |
|
|---|
| 232 |
(defun count-permutations (n &optional (k n)) |
|---|
| 233 |
"Number of K element permutations for a sequence of N objects. |
|---|
| 234 |
R defaults to N" |
|---|
| 235 |
;; FIXME: Use %multiply-range and take care of 1 and 2, plus |
|---|
| 236 |
;; check types. |
|---|
| 237 |
(/ (factorial n) |
|---|
| 238 |
(factorial (- n k)))) |
|---|