| 1 | ;; Spherical Vector distribution |
|---|
| 2 | ;; Liam Healy, Sun Oct 22 2006 |
|---|
| 3 | ;; Time-stamp: <2008-02-17 13:25:44EST spherical-vector.lisp> |
|---|
| 4 | ;; $Id$ |
|---|
| 5 | |
|---|
| 6 | (in-package :gsl) |
|---|
| 7 | |
|---|
| 8 | ;;; No test for #'direction-Nd yet. |
|---|
| 9 | |
|---|
| 10 | (defmfun direction-2d (generator) |
|---|
| 11 | "gsl_ran_dir_2d" |
|---|
| 12 | (((generator generator) :pointer) (x :double) (y :double)) |
|---|
| 13 | :c-return :void |
|---|
| 14 | :documentation ; FDL |
|---|
| 15 | "A random direction vector v = (x,y) in |
|---|
| 16 | two dimensions. The vector is normalized such that |
|---|
| 17 | |v|^2 = x^2 + y^2 = 1.") |
|---|
| 18 | |
|---|
| 19 | (defmfun direction-2d-trig-method (generator) |
|---|
| 20 | "gsl_ran_dir_2d_trig_method" |
|---|
| 21 | (((generator generator) :pointer) (x :double) (y :double)) |
|---|
| 22 | :c-return :void |
|---|
| 23 | :documentation ; FDL |
|---|
| 24 | "A random direction vector v = (x,y) in |
|---|
| 25 | two dimensions. The vector is normalized such that |
|---|
| 26 | |v|^2 = x^2 + y^2 = 1. Uses trigonometric functions.") |
|---|
| 27 | |
|---|
| 28 | (defmfun direction-3d (generator) |
|---|
| 29 | "gsl_ran_dir_3d" |
|---|
| 30 | (((generator generator) :pointer) (x :double) (y :double) (z :double)) |
|---|
| 31 | :c-return :void |
|---|
| 32 | :documentation ; FDL |
|---|
| 33 | "A random direction vector v = |
|---|
| 34 | (x,y,z) in three dimensions. The vector is normalized |
|---|
| 35 | such that |v|^2 = x^2 + y^2 + z^2 = 1. The method employed is |
|---|
| 36 | due to Robert E. Knop (CACM 13, 326 (1970)), and explained in Knuth, v2, |
|---|
| 37 | 3rd ed, p136. It uses the surprising fact that the distribution |
|---|
| 38 | projected along any axis is actually uniform (this is only true for 3 |
|---|
| 39 | dimensions).") |
|---|
| 40 | |
|---|
| 41 | (defmfun direction-Nd (generator x) |
|---|
| 42 | "gsl_ran_dir_nd" |
|---|
| 43 | (((generator generator) :pointer) ((dim0 x) size) ((gsl-array x) :pointer)) |
|---|
| 44 | :c-return :void |
|---|
| 45 | :return (x) |
|---|
| 46 | :documentation ; FDL |
|---|
| 47 | "A random direction vector v = (x_1,x_2,...,x_n) in n dimensions, |
|---|
| 48 | where n is the length of the vector x passed in. The vector is normalized such that |
|---|
| 49 | |v|^2 = x_1^2 + x_2^2 + ... + x_n^2 = 1. The method |
|---|
| 50 | uses the fact that a multivariate gaussian distribution is spherically |
|---|
| 51 | symmetric. Each component is generated to have a gaussian distribution, |
|---|
| 52 | and then the components are normalized. The method is described by |
|---|
| 53 | Knuth, v2, 3rd ed, p135--136, and attributed to G. W. Brown, Modern |
|---|
| 54 | Mathematics for the Engineer (1956).") |
|---|
| 55 | |
|---|
| 56 | ;;; Examples and unit test |
|---|
| 57 | #| |
|---|
| 58 | (make-tests spherical-vector |
|---|
| 59 | (letm ((rng (random-number-generator *mt19937* 0))) |
|---|
| 60 | (loop for i from 0 to 4 |
|---|
| 61 | append |
|---|
| 62 | (multiple-value-list (direction-2d rng)))) |
|---|
| 63 | (letm ((rng (random-number-generator *mt19937* 0))) |
|---|
| 64 | (loop for i from 0 to 4 |
|---|
| 65 | append |
|---|
| 66 | (multiple-value-list (direction-2d-trig-method rng)))) |
|---|
| 67 | (letm ((rng (random-number-generator *mt19937* 0))) |
|---|
| 68 | (loop for i from 0 to 2 |
|---|
| 69 | append |
|---|
| 70 | (multiple-value-list (direction-3d rng))))) |
|---|
| 71 | |# |
|---|
| 72 | |
|---|
| 73 | (LISP-UNIT:DEFINE-TEST SPHERICAL-VECTOR |
|---|
| 74 | (LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 75 | (LIST |
|---|
| 76 | (LIST -0.617745613497854d0 -0.7863779988047479d0 |
|---|
| 77 | 0.993748310886084d0 0.1116436053298841d0 |
|---|
| 78 | -0.9458104280982743d0 0.3247193158722761d0 |
|---|
| 79 | 0.45726622946182216d0 0.8893298574734622d0 |
|---|
| 80 | -0.46325616159849964d0 -0.8862244234622655d0)) |
|---|
| 81 | (MULTIPLE-VALUE-LIST |
|---|
| 82 | (LETM ((RNG (RANDOM-NUMBER-GENERATOR *MT19937* 0))) |
|---|
| 83 | (LOOP FOR I FROM 0 TO 4 APPEND |
|---|
| 84 | (MULTIPLE-VALUE-LIST |
|---|
| 85 | (DIRECTION-2D RNG)))))) |
|---|
| 86 | (LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 87 | (LIST |
|---|
| 88 | (LIST 0.9999986835208556d0 -0.0016226387631051197d0 |
|---|
| 89 | 0.5203010106077766d0 0.8539829379797504d0 |
|---|
| 90 | -0.2035120531038584d0 0.9790724407527016d0 |
|---|
| 91 | 0.9454753227485545d0 -0.3256937427607672d0 |
|---|
| 92 | 0.11500033916619544d0 0.9933654523848008d0)) |
|---|
| 93 | (MULTIPLE-VALUE-LIST |
|---|
| 94 | (LETM ((RNG (RANDOM-NUMBER-GENERATOR *MT19937* 0))) |
|---|
| 95 | (LOOP FOR I FROM 0 TO 4 APPEND |
|---|
| 96 | (MULTIPLE-VALUE-LIST |
|---|
| 97 | (DIRECTION-2D-TRIG-METHOD RNG)))))) |
|---|
| 98 | (LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 99 | (LIST |
|---|
| 100 | (LIST -0.09129925750445994d0 0.18782185357162273d0 |
|---|
| 101 | 0.977950610665004d0 -0.9051182961559773d0 |
|---|
| 102 | -0.050683764485791594d0 -0.4221279734645046d0 |
|---|
| 103 | 0.13993766535985133d0 0.8385462620524484d0 |
|---|
| 104 | -0.526552576872909d0)) |
|---|
| 105 | (MULTIPLE-VALUE-LIST |
|---|
| 106 | (LETM ((RNG (RANDOM-NUMBER-GENERATOR *MT19937* 0))) |
|---|
| 107 | (LOOP FOR I FROM 0 TO 2 APPEND |
|---|
| 108 | (MULTIPLE-VALUE-LIST |
|---|
| 109 | (DIRECTION-3D RNG))))))) |
|---|
| 110 | |
|---|