Mercurial > octave
annotate liboctave/oct-rand.cc @ 7536:4dda6fbc8ba6
oct-rand.cc: fix typo
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 26 Feb 2008 20:29:58 -0500 |
parents | bda16af4fd2f |
children | a2950622f070 72830070a17b |
rev | line source |
---|---|
4308 | 1 /* |
2 | |
7017 | 3 Copyright (C) 2003, 2005, 2006, 2007 John W. Eaton |
4308 | 4 |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
7016 | 9 Free Software Foundation; either version 3 of the License, or (at your |
10 option) any later version. | |
4308 | 11 |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
7016 | 18 along with Octave; see the file COPYING. If not, see |
19 <http://www.gnu.org/licenses/>. | |
4308 | 20 |
21 */ | |
22 | |
23 #ifdef HAVE_CONFIG_H | |
24 #include <config.h> | |
25 #endif | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
26 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
27 #include <map> |
5730 | 28 #include <vector> |
4308 | 29 |
30 #include "f77-fcn.h" | |
5730 | 31 #include "lo-ieee.h" |
4308 | 32 #include "lo-error.h" |
5730 | 33 #include "lo-mappers.h" |
4308 | 34 #include "oct-rand.h" |
4415 | 35 #include "oct-time.h" |
5730 | 36 #include "data-conv.h" |
37 #include "randmtzig.h" | |
38 #include "randpoisson.h" | |
39 #include "randgamma.h" | |
6435 | 40 #include "mach-info.h" |
4308 | 41 |
7535
bda16af4fd2f
oct-rand.cc (get_dist_id): initialize retval
John W. Eaton <jwe@octave.org>
parents:
7533
diff
changeset
|
42 static const int unknown_dist = 0; |
bda16af4fd2f
oct-rand.cc (get_dist_id): initialize retval
John W. Eaton <jwe@octave.org>
parents:
7533
diff
changeset
|
43 static const int uniform_dist = 1; |
bda16af4fd2f
oct-rand.cc (get_dist_id): initialize retval
John W. Eaton <jwe@octave.org>
parents:
7533
diff
changeset
|
44 static const int normal_dist = 2; |
bda16af4fd2f
oct-rand.cc (get_dist_id): initialize retval
John W. Eaton <jwe@octave.org>
parents:
7533
diff
changeset
|
45 static const int expon_dist = 3; |
bda16af4fd2f
oct-rand.cc (get_dist_id): initialize retval
John W. Eaton <jwe@octave.org>
parents:
7533
diff
changeset
|
46 static const int poisson_dist = 4; |
bda16af4fd2f
oct-rand.cc (get_dist_id): initialize retval
John W. Eaton <jwe@octave.org>
parents:
7533
diff
changeset
|
47 static const int gamma_dist = 5; |
4308 | 48 |
49 // Current distribution of random numbers. | |
50 static int current_distribution = uniform_dist; | |
51 | |
5730 | 52 // Has the seed/state been set yet? |
53 static bool old_initialized = false; | |
54 static bool new_initialized = false; | |
55 static bool use_old_generators = false; | |
4308 | 56 |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
57 std::map<int, ColumnVector> rand_states; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
58 |
4308 | 59 extern "C" |
60 { | |
4552 | 61 F77_RET_T |
62 F77_FUNC (dgennor, DGENNOR) (const double&, const double&, double&); | |
4308 | 63 |
4552 | 64 F77_RET_T |
65 F77_FUNC (dgenunf, DGENUNF) (const double&, const double&, double&); | |
66 | |
67 F77_RET_T | |
5730 | 68 F77_FUNC (dgenexp, DGENEXP) (const double&, double&); |
69 | |
70 F77_RET_T | |
71 F77_FUNC (dignpoi, DIGNPOI) (const double&, double&); | |
72 | |
73 F77_RET_T | |
74 F77_FUNC (dgengam, DGENGAM) (const double&, const double&, double&); | |
75 | |
76 F77_RET_T | |
5275 | 77 F77_FUNC (setall, SETALL) (const octave_idx_type&, const octave_idx_type&); |
4308 | 78 |
4552 | 79 F77_RET_T |
5275 | 80 F77_FUNC (getsd, GETSD) (octave_idx_type&, octave_idx_type&); |
4308 | 81 |
4552 | 82 F77_RET_T |
5275 | 83 F77_FUNC (setsd, SETSD) (const octave_idx_type&, const octave_idx_type&); |
4308 | 84 |
4552 | 85 F77_RET_T |
5275 | 86 F77_FUNC (setcgn, SETCGN) (const octave_idx_type&); |
4308 | 87 } |
88 | |
5275 | 89 static octave_idx_type |
90 force_to_fit_range (octave_idx_type i, octave_idx_type lo, octave_idx_type hi) | |
4308 | 91 { |
92 assert (hi > lo && lo >= 0 && hi > lo); | |
93 | |
94 i = i > 0 ? i : -i; | |
95 | |
96 if (i < lo) | |
97 i = lo; | |
98 else if (i > hi) | |
99 i = i % hi; | |
100 | |
101 return i; | |
102 } | |
103 | |
104 // Make the random number generator give us a different sequence every | |
105 // time we start octave unless we specifically set the seed. The | |
106 // technique used below will cycle monthly, but it it does seem to | |
107 // work ok to give fairly different seeds each time Octave starts. | |
108 | |
109 static void | |
5730 | 110 do_old_initialization (void) |
4308 | 111 { |
4415 | 112 octave_localtime tm; |
6326 | 113 int stored_distribution = current_distribution; |
114 F77_FUNC (setcgn, SETCGN) (uniform_dist); | |
115 | |
4415 | 116 int hour = tm.hour() + 1; |
117 int minute = tm.min() + 1; | |
118 int second = tm.sec() + 1; | |
4308 | 119 |
5275 | 120 octave_idx_type s0 = tm.mday() * hour * minute * second; |
121 octave_idx_type s1 = hour * minute * second; | |
4308 | 122 |
123 s0 = force_to_fit_range (s0, 1, 2147483563); | |
124 s1 = force_to_fit_range (s1, 1, 2147483399); | |
125 | |
126 F77_FUNC (setall, SETALL) (s0, s1); | |
6326 | 127 F77_FUNC (setcgn, SETCGN) (stored_distribution); |
4308 | 128 |
5730 | 129 old_initialized = true; |
4308 | 130 } |
131 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
132 static ColumnVector |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
133 get_internal_state (void) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
134 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
135 ColumnVector s (MT_N + 1); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
136 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
137 OCTAVE_LOCAL_BUFFER (uint32_t, tmp, MT_N + 1); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
138 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
139 oct_get_state (tmp); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
140 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
141 for (octave_idx_type i = 0; i <= MT_N; i++) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
142 s.elem (i) = static_cast<double> (tmp [i]); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
143 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
144 return s; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
145 } |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
146 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
147 static inline void |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
148 save_state (void) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
149 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
150 rand_states[current_distribution] = get_internal_state ();; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
151 } |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
152 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
153 static void |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
154 initialize_rand_states (void) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
155 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
156 if (! new_initialized) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
157 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
158 oct_init_by_entropy (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
159 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
160 ColumnVector s = get_internal_state (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
161 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
162 rand_states[uniform_dist] = s; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
163 rand_states[normal_dist] = s; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
164 rand_states[expon_dist] = s; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
165 rand_states[poisson_dist] = s; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
166 rand_states[gamma_dist] = s; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
167 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
168 new_initialized = true; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
169 } |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
170 } |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
171 |
4308 | 172 static inline void |
173 maybe_initialize (void) | |
174 { | |
5730 | 175 if (use_old_generators) |
176 { | |
177 if (! old_initialized) | |
178 do_old_initialization (); | |
179 } | |
180 else | |
181 { | |
182 if (! new_initialized) | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
183 initialize_rand_states (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
184 } |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
185 } |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
186 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
187 static int |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
188 get_dist_id (const std::string& d) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
189 { |
7535
bda16af4fd2f
oct-rand.cc (get_dist_id): initialize retval
John W. Eaton <jwe@octave.org>
parents:
7533
diff
changeset
|
190 int retval = unknown_dist; |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
191 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
192 if (d == "uniform" || d == "rand") |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
193 retval = uniform_dist; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
194 else if (d == "normal" || d == "randn") |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
195 retval = normal_dist; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
196 else if (d == "exponential" || d == "rande") |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
197 retval = expon_dist; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
198 else if (d == "poisson" || d == "randp") |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
199 retval = poisson_dist; |
7536 | 200 else if (d == "gamma" || d == "randg") |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
201 retval = gamma_dist; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
202 else |
7536 | 203 (*current_liboctave_error_handler) |
204 ("rand: invalid distribution `%s'", d.c_str ()); | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
205 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
206 return retval; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
207 } |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
208 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
209 static void |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
210 set_internal_state (const ColumnVector& s) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
211 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
212 octave_idx_type len = s.length (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
213 octave_idx_type n = len < MT_N + 1 ? len : MT_N + 1; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
214 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
215 OCTAVE_LOCAL_BUFFER (uint32_t, tmp, MT_N + 1); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
216 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
217 for (octave_idx_type i = 0; i < n; i++) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
218 tmp[i] = static_cast<uint32_t> (s.elem(i)); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
219 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
220 if (len == MT_N + 1 && tmp[MT_N] <= MT_N && tmp[MT_N] > 0) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
221 oct_set_state (tmp); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
222 else |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
223 oct_init_by_array (tmp, len); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
224 } |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
225 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
226 static inline void |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
227 switch_to_generator (int dist) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
228 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
229 if (dist != current_distribution) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
230 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
231 current_distribution = dist; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
232 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
233 set_internal_state (rand_states[dist]); |
5730 | 234 } |
4308 | 235 } |
236 | |
237 double | |
238 octave_rand::seed (void) | |
239 { | |
5730 | 240 if (! old_initialized) |
241 do_old_initialization (); | |
4308 | 242 |
5275 | 243 union d2i { double d; octave_idx_type i[2]; }; |
4308 | 244 union d2i u; |
6435 | 245 |
246 oct_mach_info::float_format ff = oct_mach_info::native_float_format (); | |
247 | |
248 switch (ff) | |
249 { | |
250 case oct_mach_info::flt_fmt_ieee_big_endian: | |
251 F77_FUNC (getsd, GETSD) (u.i[1], u.i[0]); | |
252 break; | |
253 default: | |
254 F77_FUNC (getsd, GETSD) (u.i[0], u.i[1]); | |
255 break; | |
256 } | |
257 | |
4308 | 258 return u.d; |
259 } | |
260 | |
261 void | |
262 octave_rand::seed (double s) | |
263 { | |
5730 | 264 use_old_generators = true; |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
265 |
4308 | 266 maybe_initialize (); |
267 | |
6435 | 268 int i0, i1; |
5275 | 269 union d2i { double d; octave_idx_type i[2]; }; |
4308 | 270 union d2i u; |
271 u.d = s; | |
6435 | 272 |
273 oct_mach_info::float_format ff = oct_mach_info::native_float_format (); | |
274 | |
275 switch (ff) | |
276 { | |
277 case oct_mach_info::flt_fmt_ieee_big_endian: | |
278 i1 = force_to_fit_range (u.i[0], 1, 2147483563); | |
279 i0 = force_to_fit_range (u.i[1], 1, 2147483399); | |
280 break; | |
281 default: | |
282 i0 = force_to_fit_range (u.i[0], 1, 2147483563); | |
283 i1 = force_to_fit_range (u.i[1], 1, 2147483399); | |
284 break; | |
285 } | |
286 | |
4308 | 287 F77_FUNC (setsd, SETSD) (i0, i1); |
288 } | |
289 | |
5730 | 290 ColumnVector |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
291 octave_rand::state (const std::string& d) |
5730 | 292 { |
293 if (! new_initialized) | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
294 initialize_rand_states (); |
5730 | 295 |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
296 return rand_states[d.empty () ? current_distribution : get_dist_id (d)]; |
5730 | 297 } |
298 | |
299 void | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
300 octave_rand::state (const ColumnVector& s, const std::string& d) |
5730 | 301 { |
302 use_old_generators = false; | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
303 |
5730 | 304 maybe_initialize (); |
305 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
306 int old_dist = current_distribution; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
307 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
308 int new_dist = d.empty () ? current_distribution : get_dist_id (d); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
309 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
310 ColumnVector saved_state; |
5730 | 311 |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
312 if (old_dist != new_dist) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
313 saved_state = get_internal_state (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
314 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
315 set_internal_state (s); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
316 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
317 rand_states[new_dist] = get_internal_state (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
318 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
319 if (old_dist != new_dist) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
320 rand_states[old_dist] = saved_state; |
5730 | 321 } |
322 | |
4308 | 323 std::string |
324 octave_rand::distribution (void) | |
325 { | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
326 std::string retval; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
327 |
4308 | 328 maybe_initialize (); |
329 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
330 switch (current_distribution) |
4308 | 331 { |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
332 case uniform_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
333 retval = "uniform"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
334 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
335 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
336 case normal_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
337 retval = "normal"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
338 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
339 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
340 case expon_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
341 retval = "exponential"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
342 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
343 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
344 case poisson_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
345 retval = "poisson"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
346 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
347 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
348 case gamma_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
349 retval = "gamma"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
350 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
351 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
352 default: |
7536 | 353 (*current_liboctave_error_handler) |
354 ("rand: invalid distribution ID = %d", current_distribution); | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
355 break; |
4308 | 356 } |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
357 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
358 return retval; |
4308 | 359 } |
360 | |
361 void | |
362 octave_rand::distribution (const std::string& d) | |
363 { | |
7536 | 364 int id = get_dist_id (d); |
365 | |
366 switch (id) | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
367 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
368 case uniform_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
369 octave_rand::uniform_distribution (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
370 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
371 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
372 case normal_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
373 octave_rand::normal_distribution (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
374 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
375 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
376 case expon_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
377 octave_rand::exponential_distribution (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
378 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
379 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
380 case poisson_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
381 octave_rand::poisson_distribution (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
382 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
383 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
384 case gamma_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
385 octave_rand::gamma_distribution (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
386 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
387 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
388 default: |
7536 | 389 (*current_liboctave_error_handler) |
390 ("rand: invalid distribution ID = %d", id); | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
391 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
392 } |
4308 | 393 } |
394 | |
395 void | |
396 octave_rand::uniform_distribution (void) | |
397 { | |
398 maybe_initialize (); | |
399 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
400 switch_to_generator (uniform_dist); |
4308 | 401 |
402 F77_FUNC (setcgn, SETCGN) (uniform_dist); | |
403 } | |
404 | |
405 void | |
406 octave_rand::normal_distribution (void) | |
407 { | |
408 maybe_initialize (); | |
409 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
410 switch_to_generator (normal_dist); |
4308 | 411 |
412 F77_FUNC (setcgn, SETCGN) (normal_dist); | |
413 } | |
414 | |
5730 | 415 void |
416 octave_rand::exponential_distribution (void) | |
417 { | |
418 maybe_initialize (); | |
419 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
420 switch_to_generator (expon_dist); |
5730 | 421 |
422 F77_FUNC (setcgn, SETCGN) (expon_dist); | |
423 } | |
424 | |
425 void | |
426 octave_rand::poisson_distribution (void) | |
427 { | |
428 maybe_initialize (); | |
429 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
430 switch_to_generator (poisson_dist); |
5730 | 431 |
432 F77_FUNC (setcgn, SETCGN) (poisson_dist); | |
433 } | |
434 | |
435 void | |
436 octave_rand::gamma_distribution (void) | |
437 { | |
438 maybe_initialize (); | |
439 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
440 switch_to_generator (gamma_dist); |
5730 | 441 |
442 F77_FUNC (setcgn, SETCGN) (gamma_dist); | |
443 } | |
444 | |
445 | |
4308 | 446 double |
5730 | 447 octave_rand::scalar (double a) |
4308 | 448 { |
449 maybe_initialize (); | |
450 | |
451 double retval = 0.0; | |
452 | |
5730 | 453 if (use_old_generators) |
4308 | 454 { |
5730 | 455 switch (current_distribution) |
456 { | |
457 case uniform_dist: | |
458 F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, retval); | |
459 break; | |
4308 | 460 |
5730 | 461 case normal_dist: |
462 F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, retval); | |
463 break; | |
4308 | 464 |
5730 | 465 case expon_dist: |
466 F77_FUNC (dgenexp, DGENEXP) (1.0, retval); | |
467 break; | |
4308 | 468 |
5730 | 469 case poisson_dist: |
470 if (a < 0.0 || xisnan(a) || xisinf(a)) | |
471 retval = octave_NaN; | |
472 else | |
473 { | |
474 // workaround bug in ignpoi, by calling with different Mu | |
475 F77_FUNC (dignpoi, DIGNPOI) (a + 1, retval); | |
476 F77_FUNC (dignpoi, DIGNPOI) (a, retval); | |
477 } | |
478 break; | |
4308 | 479 |
5730 | 480 case gamma_dist: |
481 if (a <= 0.0 || xisnan(a) || xisinf(a)) | |
482 retval = octave_NaN; | |
483 else | |
484 F77_FUNC (dgengam, DGENGAM) (1.0, a, retval); | |
485 break; | |
4308 | 486 |
5730 | 487 default: |
7536 | 488 (*current_liboctave_error_handler) |
489 ("rand: invalid distribution ID = %d", current_distribution); | |
5730 | 490 break; |
4308 | 491 } |
492 } | |
493 else | |
4543 | 494 { |
495 switch (current_distribution) | |
496 { | |
497 case uniform_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
498 retval = oct_randu (); |
4543 | 499 break; |
500 | |
501 case normal_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
502 retval = oct_randn (); |
5730 | 503 break; |
504 | |
505 case expon_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
506 retval = oct_rande (); |
5730 | 507 break; |
508 | |
509 case poisson_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
510 retval = oct_randp (a); |
5730 | 511 break; |
512 | |
513 case gamma_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
514 retval = oct_randg (a); |
4543 | 515 break; |
516 | |
517 default: | |
7536 | 518 (*current_liboctave_error_handler) |
519 ("rand: invalid distribution ID = %d", current_distribution); | |
4543 | 520 break; |
521 } | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
522 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
523 save_state (); |
4543 | 524 } |
525 | |
526 return retval; | |
527 } | |
528 | |
5730 | 529 #define MAKE_RAND(len) \ |
4308 | 530 do \ |
531 { \ | |
532 double val; \ | |
5730 | 533 for (volatile octave_idx_type i = 0; i < len; i++) \ |
4308 | 534 { \ |
535 OCTAVE_QUIT; \ | |
5730 | 536 RAND_FUNC (val); \ |
537 v[i] = val; \ | |
4308 | 538 } \ |
539 } \ | |
540 while (0) | |
541 | |
5730 | 542 static void |
543 fill_rand (octave_idx_type len, double *v, double a) | |
544 { | |
545 maybe_initialize (); | |
546 | |
547 if (len < 1) | |
548 return; | |
549 | |
550 switch (current_distribution) | |
551 { | |
552 case uniform_dist: | |
553 if (use_old_generators) | |
554 { | |
555 #define RAND_FUNC(x) F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x) | |
556 MAKE_RAND (len); | |
557 #undef RAND_FUNC | |
558 } | |
559 else | |
560 oct_fill_randu (len, v); | |
561 break; | |
562 | |
563 case normal_dist: | |
564 if (use_old_generators) | |
565 { | |
566 #define RAND_FUNC(x) F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x) | |
567 MAKE_RAND (len); | |
568 #undef RAND_FUNC | |
569 } | |
570 else | |
571 oct_fill_randn (len, v); | |
572 break; | |
573 | |
574 case expon_dist: | |
575 if (use_old_generators) | |
576 { | |
577 #define RAND_FUNC(x) F77_FUNC (dgenexp, DGENEXP) (1.0, x) | |
578 MAKE_RAND (len); | |
579 #undef RAND_FUNC | |
580 } | |
581 else | |
582 oct_fill_rande (len, v); | |
583 break; | |
584 | |
585 case poisson_dist: | |
586 if (use_old_generators) | |
587 { | |
588 if (a < 0.0 || xisnan(a) || xisinf(a)) | |
589 #define RAND_FUNC(x) x = octave_NaN; | |
590 MAKE_RAND (len); | |
591 #undef RAND_FUNC | |
592 else | |
593 { | |
594 // workaround bug in ignpoi, by calling with different Mu | |
595 double tmp; | |
596 F77_FUNC (dignpoi, DIGNPOI) (a + 1, tmp); | |
597 #define RAND_FUNC(x) F77_FUNC (dignpoi, DIGNPOI) (a, x) | |
598 MAKE_RAND (len); | |
599 #undef RAND_FUNC | |
600 } | |
601 } | |
602 else | |
603 oct_fill_randp (a, len, v); | |
604 break; | |
605 | |
606 case gamma_dist: | |
607 if (use_old_generators) | |
608 { | |
609 if (a <= 0.0 || xisnan(a) || xisinf(a)) | |
610 #define RAND_FUNC(x) x = octave_NaN; | |
611 MAKE_RAND (len); | |
612 #undef RAND_FUNC | |
613 else | |
614 #define RAND_FUNC(x) F77_FUNC (dgengam, DGENGAM) (1.0, a, x) | |
615 MAKE_RAND (len); | |
616 #undef RAND_FUNC | |
617 } | |
618 else | |
619 oct_fill_randg (a, len, v); | |
620 break; | |
621 | |
622 default: | |
7536 | 623 (*current_liboctave_error_handler) |
624 ("rand: invalid distribution ID = %d", current_distribution); | |
5730 | 625 break; |
626 } | |
627 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
628 save_state (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
629 |
5730 | 630 return; |
631 } | |
632 | |
633 Matrix | |
634 octave_rand::matrix (octave_idx_type n, octave_idx_type m, double a) | |
635 { | |
636 Matrix retval; | |
637 | |
638 if (n >= 0 && m >= 0) | |
639 { | |
640 retval.resize (n, m); | |
641 | |
642 if (n > 0 && m > 0) | |
643 fill_rand (retval.capacity(), retval.fortran_vec(), a); | |
644 } | |
645 else | |
646 (*current_liboctave_error_handler) ("rand: invalid negative argument"); | |
647 | |
648 return retval; | |
649 } | |
650 | |
651 NDArray | |
652 octave_rand::nd_array (const dim_vector& dims, double a) | |
653 { | |
654 NDArray retval; | |
655 | |
656 if (! dims.all_zero ()) | |
657 { | |
658 retval.resize (dims); | |
659 | |
660 fill_rand (retval.capacity(), retval.fortran_vec(), a); | |
661 } | |
662 | |
663 return retval; | |
664 } | |
665 | |
4308 | 666 Array<double> |
5730 | 667 octave_rand::vector (octave_idx_type n, double a) |
4308 | 668 { |
669 maybe_initialize (); | |
670 | |
671 Array<double> retval; | |
672 | |
673 if (n > 0) | |
674 { | |
675 retval.resize (n); | |
676 | |
5730 | 677 fill_rand (retval.capacity(), retval.fortran_vec(), a); |
4308 | 678 } |
679 else if (n < 0) | |
680 (*current_liboctave_error_handler) ("rand: invalid negative argument"); | |
681 | |
682 return retval; | |
683 } | |
684 | |
685 /* | |
686 ;;; Local Variables: *** | |
687 ;;; mode: C++ *** | |
688 ;;; End: *** | |
689 */ |