Mercurial > hg > octave-max
annotate liboctave/oct-rand.cc @ 7535:bda16af4fd2f
oct-rand.cc (get_dist_id): initialize retval
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 26 Feb 2008 18:45:57 -0500 |
parents | ff52243af934 |
children | 4dda6fbc8ba6 |
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; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
200 else if (d == "gamma" || d == "rangd") |
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 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
203 (*current_liboctave_error_handler) ("rand: invalid distribution"); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
204 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
205 return retval; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
206 } |
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 static void |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
209 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
|
210 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
211 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
|
212 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
|
213 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
214 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
|
215 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
216 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
|
217 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
|
218 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
219 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
|
220 oct_set_state (tmp); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
221 else |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
222 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
|
223 } |
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 static inline void |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
226 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
|
227 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
228 if (dist != current_distribution) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
229 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
230 current_distribution = dist; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
231 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
232 set_internal_state (rand_states[dist]); |
5730 | 233 } |
4308 | 234 } |
235 | |
236 double | |
237 octave_rand::seed (void) | |
238 { | |
5730 | 239 if (! old_initialized) |
240 do_old_initialization (); | |
4308 | 241 |
5275 | 242 union d2i { double d; octave_idx_type i[2]; }; |
4308 | 243 union d2i u; |
6435 | 244 |
245 oct_mach_info::float_format ff = oct_mach_info::native_float_format (); | |
246 | |
247 switch (ff) | |
248 { | |
249 case oct_mach_info::flt_fmt_ieee_big_endian: | |
250 F77_FUNC (getsd, GETSD) (u.i[1], u.i[0]); | |
251 break; | |
252 default: | |
253 F77_FUNC (getsd, GETSD) (u.i[0], u.i[1]); | |
254 break; | |
255 } | |
256 | |
4308 | 257 return u.d; |
258 } | |
259 | |
260 void | |
261 octave_rand::seed (double s) | |
262 { | |
5730 | 263 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
|
264 |
4308 | 265 maybe_initialize (); |
266 | |
6435 | 267 int i0, i1; |
5275 | 268 union d2i { double d; octave_idx_type i[2]; }; |
4308 | 269 union d2i u; |
270 u.d = s; | |
6435 | 271 |
272 oct_mach_info::float_format ff = oct_mach_info::native_float_format (); | |
273 | |
274 switch (ff) | |
275 { | |
276 case oct_mach_info::flt_fmt_ieee_big_endian: | |
277 i1 = force_to_fit_range (u.i[0], 1, 2147483563); | |
278 i0 = force_to_fit_range (u.i[1], 1, 2147483399); | |
279 break; | |
280 default: | |
281 i0 = force_to_fit_range (u.i[0], 1, 2147483563); | |
282 i1 = force_to_fit_range (u.i[1], 1, 2147483399); | |
283 break; | |
284 } | |
285 | |
4308 | 286 F77_FUNC (setsd, SETSD) (i0, i1); |
287 } | |
288 | |
5730 | 289 ColumnVector |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
290 octave_rand::state (const std::string& d) |
5730 | 291 { |
292 if (! new_initialized) | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
293 initialize_rand_states (); |
5730 | 294 |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
295 return rand_states[d.empty () ? current_distribution : get_dist_id (d)]; |
5730 | 296 } |
297 | |
298 void | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
299 octave_rand::state (const ColumnVector& s, const std::string& d) |
5730 | 300 { |
301 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
|
302 |
5730 | 303 maybe_initialize (); |
304 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
305 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
|
306 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
307 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
|
308 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
309 ColumnVector saved_state; |
5730 | 310 |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
311 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
|
312 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
|
313 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
314 set_internal_state (s); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
315 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
316 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
|
317 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
318 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
|
319 rand_states[old_dist] = saved_state; |
5730 | 320 } |
321 | |
4308 | 322 std::string |
323 octave_rand::distribution (void) | |
324 { | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
325 std::string retval; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
326 |
4308 | 327 maybe_initialize (); |
328 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
329 switch (current_distribution) |
4308 | 330 { |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
331 case uniform_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
332 retval = "uniform"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
333 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
334 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
335 case normal_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
336 retval = "normal"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
337 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
338 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
339 case expon_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
340 retval = "exponential"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
341 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
342 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
343 case poisson_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
344 retval = "poisson"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
345 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
346 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
347 case gamma_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
348 retval = "gamma"; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
349 break; |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
350 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
351 default: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
352 (*current_liboctave_error_handler) ("rand: invalid distribution"); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
353 break; |
4308 | 354 } |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
355 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
356 return retval; |
4308 | 357 } |
358 | |
359 void | |
360 octave_rand::distribution (const std::string& d) | |
361 { | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
362 switch (get_dist_id (d)) |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
363 { |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
364 case uniform_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
365 octave_rand::uniform_distribution (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
366 break; |
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 normal_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
369 octave_rand::normal_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 expon_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
373 octave_rand::exponential_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 poisson_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
377 octave_rand::poisson_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 gamma_dist: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
381 octave_rand::gamma_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 default: |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
385 (*current_liboctave_error_handler) ("rand: invalid 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 } |
4308 | 388 } |
389 | |
390 void | |
391 octave_rand::uniform_distribution (void) | |
392 { | |
393 maybe_initialize (); | |
394 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
395 switch_to_generator (uniform_dist); |
4308 | 396 |
397 F77_FUNC (setcgn, SETCGN) (uniform_dist); | |
398 } | |
399 | |
400 void | |
401 octave_rand::normal_distribution (void) | |
402 { | |
403 maybe_initialize (); | |
404 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
405 switch_to_generator (normal_dist); |
4308 | 406 |
407 F77_FUNC (setcgn, SETCGN) (normal_dist); | |
408 } | |
409 | |
5730 | 410 void |
411 octave_rand::exponential_distribution (void) | |
412 { | |
413 maybe_initialize (); | |
414 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
415 switch_to_generator (expon_dist); |
5730 | 416 |
417 F77_FUNC (setcgn, SETCGN) (expon_dist); | |
418 } | |
419 | |
420 void | |
421 octave_rand::poisson_distribution (void) | |
422 { | |
423 maybe_initialize (); | |
424 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
425 switch_to_generator (poisson_dist); |
5730 | 426 |
427 F77_FUNC (setcgn, SETCGN) (poisson_dist); | |
428 } | |
429 | |
430 void | |
431 octave_rand::gamma_distribution (void) | |
432 { | |
433 maybe_initialize (); | |
434 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
435 switch_to_generator (gamma_dist); |
5730 | 436 |
437 F77_FUNC (setcgn, SETCGN) (gamma_dist); | |
438 } | |
439 | |
440 | |
4308 | 441 double |
5730 | 442 octave_rand::scalar (double a) |
4308 | 443 { |
444 maybe_initialize (); | |
445 | |
446 double retval = 0.0; | |
447 | |
5730 | 448 if (use_old_generators) |
4308 | 449 { |
5730 | 450 switch (current_distribution) |
451 { | |
452 case uniform_dist: | |
453 F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, retval); | |
454 break; | |
4308 | 455 |
5730 | 456 case normal_dist: |
457 F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, retval); | |
458 break; | |
4308 | 459 |
5730 | 460 case expon_dist: |
461 F77_FUNC (dgenexp, DGENEXP) (1.0, retval); | |
462 break; | |
4308 | 463 |
5730 | 464 case poisson_dist: |
465 if (a < 0.0 || xisnan(a) || xisinf(a)) | |
466 retval = octave_NaN; | |
467 else | |
468 { | |
469 // workaround bug in ignpoi, by calling with different Mu | |
470 F77_FUNC (dignpoi, DIGNPOI) (a + 1, retval); | |
471 F77_FUNC (dignpoi, DIGNPOI) (a, retval); | |
472 } | |
473 break; | |
4308 | 474 |
5730 | 475 case gamma_dist: |
476 if (a <= 0.0 || xisnan(a) || xisinf(a)) | |
477 retval = octave_NaN; | |
478 else | |
479 F77_FUNC (dgengam, DGENGAM) (1.0, a, retval); | |
480 break; | |
4308 | 481 |
5730 | 482 default: |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
483 (*current_liboctave_error_handler) ("rand: invalid distribution"); |
5730 | 484 break; |
4308 | 485 } |
486 } | |
487 else | |
4543 | 488 { |
489 switch (current_distribution) | |
490 { | |
491 case uniform_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
492 retval = oct_randu (); |
4543 | 493 break; |
494 | |
495 case normal_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
496 retval = oct_randn (); |
5730 | 497 break; |
498 | |
499 case expon_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
500 retval = oct_rande (); |
5730 | 501 break; |
502 | |
503 case poisson_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
504 retval = oct_randp (a); |
5730 | 505 break; |
506 | |
507 case gamma_dist: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
508 retval = oct_randg (a); |
4543 | 509 break; |
510 | |
511 default: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
512 (*current_liboctave_error_handler) ("rand: invalid distribution"); |
4543 | 513 break; |
514 } | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
515 |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
516 save_state (); |
4543 | 517 } |
518 | |
519 return retval; | |
520 } | |
521 | |
5730 | 522 #define MAKE_RAND(len) \ |
4308 | 523 do \ |
524 { \ | |
525 double val; \ | |
5730 | 526 for (volatile octave_idx_type i = 0; i < len; i++) \ |
4308 | 527 { \ |
528 OCTAVE_QUIT; \ | |
5730 | 529 RAND_FUNC (val); \ |
530 v[i] = val; \ | |
4308 | 531 } \ |
532 } \ | |
533 while (0) | |
534 | |
5730 | 535 static void |
536 fill_rand (octave_idx_type len, double *v, double a) | |
537 { | |
538 maybe_initialize (); | |
539 | |
540 if (len < 1) | |
541 return; | |
542 | |
543 switch (current_distribution) | |
544 { | |
545 case uniform_dist: | |
546 if (use_old_generators) | |
547 { | |
548 #define RAND_FUNC(x) F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x) | |
549 MAKE_RAND (len); | |
550 #undef RAND_FUNC | |
551 } | |
552 else | |
553 oct_fill_randu (len, v); | |
554 break; | |
555 | |
556 case normal_dist: | |
557 if (use_old_generators) | |
558 { | |
559 #define RAND_FUNC(x) F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x) | |
560 MAKE_RAND (len); | |
561 #undef RAND_FUNC | |
562 } | |
563 else | |
564 oct_fill_randn (len, v); | |
565 break; | |
566 | |
567 case expon_dist: | |
568 if (use_old_generators) | |
569 { | |
570 #define RAND_FUNC(x) F77_FUNC (dgenexp, DGENEXP) (1.0, x) | |
571 MAKE_RAND (len); | |
572 #undef RAND_FUNC | |
573 } | |
574 else | |
575 oct_fill_rande (len, v); | |
576 break; | |
577 | |
578 case poisson_dist: | |
579 if (use_old_generators) | |
580 { | |
581 if (a < 0.0 || xisnan(a) || xisinf(a)) | |
582 #define RAND_FUNC(x) x = octave_NaN; | |
583 MAKE_RAND (len); | |
584 #undef RAND_FUNC | |
585 else | |
586 { | |
587 // workaround bug in ignpoi, by calling with different Mu | |
588 double tmp; | |
589 F77_FUNC (dignpoi, DIGNPOI) (a + 1, tmp); | |
590 #define RAND_FUNC(x) F77_FUNC (dignpoi, DIGNPOI) (a, x) | |
591 MAKE_RAND (len); | |
592 #undef RAND_FUNC | |
593 } | |
594 } | |
595 else | |
596 oct_fill_randp (a, len, v); | |
597 break; | |
598 | |
599 case gamma_dist: | |
600 if (use_old_generators) | |
601 { | |
602 if (a <= 0.0 || xisnan(a) || xisinf(a)) | |
603 #define RAND_FUNC(x) x = octave_NaN; | |
604 MAKE_RAND (len); | |
605 #undef RAND_FUNC | |
606 else | |
607 #define RAND_FUNC(x) F77_FUNC (dgengam, DGENGAM) (1.0, a, x) | |
608 MAKE_RAND (len); | |
609 #undef RAND_FUNC | |
610 } | |
611 else | |
612 oct_fill_randg (a, len, v); | |
613 break; | |
614 | |
615 default: | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
616 (*current_liboctave_error_handler) ("rand: invalid distribution"); |
5730 | 617 break; |
618 } | |
619 | |
7533
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
620 save_state (); |
ff52243af934
save state separately for each MT random number generator
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
621 |
5730 | 622 return; |
623 } | |
624 | |
625 Matrix | |
626 octave_rand::matrix (octave_idx_type n, octave_idx_type m, double a) | |
627 { | |
628 Matrix retval; | |
629 | |
630 if (n >= 0 && m >= 0) | |
631 { | |
632 retval.resize (n, m); | |
633 | |
634 if (n > 0 && m > 0) | |
635 fill_rand (retval.capacity(), retval.fortran_vec(), a); | |
636 } | |
637 else | |
638 (*current_liboctave_error_handler) ("rand: invalid negative argument"); | |
639 | |
640 return retval; | |
641 } | |
642 | |
643 NDArray | |
644 octave_rand::nd_array (const dim_vector& dims, double a) | |
645 { | |
646 NDArray retval; | |
647 | |
648 if (! dims.all_zero ()) | |
649 { | |
650 retval.resize (dims); | |
651 | |
652 fill_rand (retval.capacity(), retval.fortran_vec(), a); | |
653 } | |
654 | |
655 return retval; | |
656 } | |
657 | |
4308 | 658 Array<double> |
5730 | 659 octave_rand::vector (octave_idx_type n, double a) |
4308 | 660 { |
661 maybe_initialize (); | |
662 | |
663 Array<double> retval; | |
664 | |
665 if (n > 0) | |
666 { | |
667 retval.resize (n); | |
668 | |
5730 | 669 fill_rand (retval.capacity(), retval.fortran_vec(), a); |
4308 | 670 } |
671 else if (n < 0) | |
672 (*current_liboctave_error_handler) ("rand: invalid negative argument"); | |
673 | |
674 return retval; | |
675 } | |
676 | |
677 /* | |
678 ;;; Local Variables: *** | |
679 ;;; mode: C++ *** | |
680 ;;; End: *** | |
681 */ |