Mercurial > octave
comparison libinterp/corefcn/rand.cc @ 20894:e528d7ab1cad
rand.cc: Overhaul file to make use of new C++ archetype.
* rand.cc (do_rand): Declare variables as late as possible. Eliminate '{', '}'
around code blocks with a single statement. Delete else statement when first of
if statement is error(). Delete unused goto label "done:".
* rand.cc (Frand, Frandn, Frande): Simplify code to single line.
* rand.cc (Frandg, Frandp): Don't use retval. Delete else statement when first of
if statement is error().
* rand.cc (Frandperm): Delete unused retval variable.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 14 Dec 2015 14:16:19 -0800 |
parents | 1142cf6abc0d |
children | 48b2ad5ee801 |
comparison
equal
deleted
inserted
replaced
20893:384ff5aa9437 | 20894:e528d7ab1cad |
---|---|
55 | 55 |
56 static octave_value | 56 static octave_value |
57 do_rand (const octave_value_list& args, int nargin, const char *fcn, | 57 do_rand (const octave_value_list& args, int nargin, const char *fcn, |
58 const std::string& distribution, bool additional_arg = false) | 58 const std::string& distribution, bool additional_arg = false) |
59 { | 59 { |
60 octave_value retval; | |
61 NDArray a; | 60 NDArray a; |
62 int idx = 0; | 61 int idx = 0; |
63 dim_vector dims; | |
64 bool is_single = false; | 62 bool is_single = false; |
65 | |
66 unwind_protect frame; | |
67 // Restore current distribution on any exit. | |
68 frame.add_fcn (octave_rand::distribution, | |
69 octave_rand::distribution ()); | |
70 | |
71 octave_rand::distribution (distribution); | |
72 | 63 |
73 if (nargin > 0 && args(nargin-1).is_string ()) | 64 if (nargin > 0 && args(nargin-1).is_string ()) |
74 { | 65 { |
75 std::string s_arg = args(nargin-1).string_value (); | 66 std::string s_arg = args(nargin-1).string_value (); |
76 | 67 |
96 idx++; | 87 idx++; |
97 nargin--; | 88 nargin--; |
98 } | 89 } |
99 } | 90 } |
100 | 91 |
92 octave_value retval; | |
93 dim_vector dims; | |
94 | |
95 unwind_protect frame; | |
96 // Restore current distribution on any exit. | |
97 frame.add_fcn (octave_rand::distribution, | |
98 octave_rand::distribution ()); | |
99 | |
100 octave_rand::distribution (distribution); | |
101 | |
101 switch (nargin) | 102 switch (nargin) |
102 { | 103 { |
103 case 0: | 104 case 0: |
104 { | 105 { |
105 if (additional_arg) | 106 if (additional_arg) |
109 dims.resize (2); | 110 dims.resize (2); |
110 | 111 |
111 dims(0) = 1; | 112 dims(0) = 1; |
112 dims(1) = 1; | 113 dims(1) = 1; |
113 } | 114 } |
115 | |
114 goto gen_matrix; | 116 goto gen_matrix; |
115 } | 117 } |
116 break; | 118 break; |
117 | 119 |
118 case 1: | 120 case 1: |
122 if (tmp.is_string ()) | 124 if (tmp.is_string ()) |
123 { | 125 { |
124 std::string s_arg = tmp.string_value (); | 126 std::string s_arg = tmp.string_value (); |
125 | 127 |
126 if (s_arg == "dist") | 128 if (s_arg == "dist") |
127 { | 129 retval = octave_rand::distribution (); |
128 retval = octave_rand::distribution (); | |
129 } | |
130 else if (s_arg == "seed") | 130 else if (s_arg == "seed") |
131 { | 131 retval = octave_rand::seed (); |
132 retval = octave_rand::seed (); | |
133 } | |
134 else if (s_arg == "state" || s_arg == "twister") | 132 else if (s_arg == "state" || s_arg == "twister") |
135 { | 133 retval = octave_rand::state (fcn); |
136 retval = octave_rand::state (fcn); | |
137 } | |
138 else if (s_arg == "uniform") | 134 else if (s_arg == "uniform") |
139 { | 135 octave_rand::uniform_distribution (); |
140 octave_rand::uniform_distribution (); | |
141 } | |
142 else if (s_arg == "normal") | 136 else if (s_arg == "normal") |
143 { | 137 octave_rand::normal_distribution (); |
144 octave_rand::normal_distribution (); | |
145 } | |
146 else if (s_arg == "exponential") | 138 else if (s_arg == "exponential") |
147 { | 139 octave_rand::exponential_distribution (); |
148 octave_rand::exponential_distribution (); | |
149 } | |
150 else if (s_arg == "poisson") | 140 else if (s_arg == "poisson") |
151 { | 141 octave_rand::poisson_distribution (); |
152 octave_rand::poisson_distribution (); | |
153 } | |
154 else if (s_arg == "gamma") | 142 else if (s_arg == "gamma") |
155 { | 143 octave_rand::gamma_distribution (); |
156 octave_rand::gamma_distribution (); | |
157 } | |
158 else | 144 else |
159 error ("%s: unrecognized string argument", fcn); | 145 error ("%s: unrecognized string argument", fcn); |
160 } | 146 } |
161 else if (tmp.is_scalar_type ()) | 147 else if (tmp.is_scalar_type ()) |
162 { | 148 { |
163 double dval = tmp.double_value (); | 149 double dval = tmp.double_value (); |
164 | 150 |
165 if (xisnan (dval)) | 151 if (xisnan (dval)) |
166 error ("%s: NaN is invalid matrix dimension", fcn); | 152 error ("%s: NaN is invalid matrix dimension", fcn); |
167 else | 153 |
168 { | 154 dims.resize (2); |
169 dims.resize (2); | 155 |
170 | 156 dims(0) = NINTbig (tmp.double_value ()); |
171 dims(0) = NINTbig (tmp.double_value ()); | 157 dims(1) = NINTbig (tmp.double_value ()); |
172 dims(1) = NINTbig (tmp.double_value ()); | 158 |
173 | 159 goto gen_matrix; |
174 goto gen_matrix; | |
175 } | |
176 } | 160 } |
177 else if (tmp.is_range ()) | 161 else if (tmp.is_range ()) |
178 { | 162 { |
179 Range r = tmp.range_value (); | 163 Range r = tmp.range_value (); |
180 | 164 |
181 if (r.all_elements_are_ints ()) | 165 if (! r.all_elements_are_ints ()) |
166 error ("%s: all elements of range must be integers", fcn); | |
167 | |
168 octave_idx_type n = r.numel (); | |
169 | |
170 dims.resize (n); | |
171 | |
172 octave_idx_type base = NINTbig (r.base ()); | |
173 octave_idx_type incr = NINTbig (r.inc ()); | |
174 | |
175 for (octave_idx_type i = 0; i < n; i++) | |
182 { | 176 { |
183 octave_idx_type n = r.numel (); | 177 // Negative dimensions treated as zero for Matlab compatibility |
184 | 178 dims(i) = base >= 0 ? base : 0; |
185 dims.resize (n); | 179 base += incr; |
186 | |
187 octave_idx_type base = NINTbig (r.base ()); | |
188 octave_idx_type incr = NINTbig (r.inc ()); | |
189 | |
190 for (octave_idx_type i = 0; i < n; i++) | |
191 { | |
192 // Negative dimensions are treated as zero for Matlab | |
193 // compatibility | |
194 dims(i) = base >= 0 ? base : 0; | |
195 base += incr; | |
196 } | |
197 | |
198 goto gen_matrix; | |
199 | |
200 } | 180 } |
201 else | 181 |
202 error ("%s: all elements of range must be integers", fcn); | 182 goto gen_matrix; |
203 } | 183 } |
204 else if (tmp.is_matrix_type ()) | 184 else if (tmp.is_matrix_type ()) |
205 { | 185 { |
206 Array<int> iv; | 186 Array<int> iv; |
207 | 187 |
218 | 198 |
219 dims.resize (len); | 199 dims.resize (len); |
220 | 200 |
221 for (octave_idx_type i = 0; i < len; i++) | 201 for (octave_idx_type i = 0; i < len; i++) |
222 { | 202 { |
223 // Negative dimensions are treated as zero for Matlab | 203 // Negative dimensions treated as zero for Matlab compatibility |
224 // compatibility | |
225 octave_idx_type elt = iv(i); | 204 octave_idx_type elt = iv(i); |
226 dims(i) = elt >=0 ? elt : 0; | 205 dims(i) = elt >=0 ? elt : 0; |
227 } | 206 } |
228 | 207 |
229 goto gen_matrix; | 208 goto gen_matrix; |
280 | 259 |
281 for (int i = 0; i < nargin; i++) | 260 for (int i = 0; i < nargin; i++) |
282 { | 261 { |
283 octave_idx_type elt = args(idx+i).xint_value ("%s: dimension must be a scalar or array of integers", fcn); | 262 octave_idx_type elt = args(idx+i).xint_value ("%s: dimension must be a scalar or array of integers", fcn); |
284 | 263 |
285 // Negative is zero for Matlab compatibility | 264 // Negative dimensions treated as zero for Matlab compatibility |
286 dims(i) = elt >= 0 ? elt : 0; | 265 dims(i) = elt >= 0 ? elt : 0; |
287 } | 266 } |
288 | 267 |
289 goto gen_matrix; | 268 goto gen_matrix; |
290 } | 269 } |
291 } | 270 } |
292 break; | 271 break; |
293 } | 272 } |
294 | 273 |
295 done: | 274 // No "goto gen_matrix" in code path. Must be done. |
296 | |
297 return retval; | 275 return retval; |
298 | 276 |
299 gen_matrix: | 277 gen_matrix: |
300 | 278 |
301 dims.chop_trailing_singletons (); | 279 dims.chop_trailing_singletons (); |
312 error ("%s: mismatch in argument size", fcn); | 290 error ("%s: mismatch in argument size", fcn); |
313 | 291 |
314 octave_idx_type len = a.numel (); | 292 octave_idx_type len = a.numel (); |
315 FloatNDArray m (dims); | 293 FloatNDArray m (dims); |
316 float *v = m.fortran_vec (); | 294 float *v = m.fortran_vec (); |
295 | |
317 for (octave_idx_type i = 0; i < len; i++) | 296 for (octave_idx_type i = 0; i < len; i++) |
318 v[i] = octave_rand::float_scalar (a(i)); | 297 v[i] = octave_rand::float_scalar (a(i)); |
298 | |
319 return m; | 299 return m; |
320 } | 300 } |
321 } | 301 } |
322 else | 302 else |
323 return octave_rand::float_nd_array (dims); | 303 return octave_rand::float_nd_array (dims); |
334 error ("%s: mismatch in argument size", fcn); | 314 error ("%s: mismatch in argument size", fcn); |
335 | 315 |
336 octave_idx_type len = a.numel (); | 316 octave_idx_type len = a.numel (); |
337 NDArray m (dims); | 317 NDArray m (dims); |
338 double *v = m.fortran_vec (); | 318 double *v = m.fortran_vec (); |
319 | |
339 for (octave_idx_type i = 0; i < len; i++) | 320 for (octave_idx_type i = 0; i < len; i++) |
340 v[i] = octave_rand::scalar (a(i)); | 321 v[i] = octave_rand::scalar (a(i)); |
322 | |
341 return m; | 323 return m; |
342 } | 324 } |
343 } | 325 } |
344 else | 326 else |
345 return octave_rand::nd_array (dims); | 327 return octave_rand::nd_array (dims); |
433 @qcode{\"double\"} or @qcode{\"single\"} argument. These are the only valid\n\ | 415 @qcode{\"double\"} or @qcode{\"single\"} argument. These are the only valid\n\ |
434 classes.\n\ | 416 classes.\n\ |
435 @seealso{randn, rande, randg, randp}\n\ | 417 @seealso{randn, rande, randg, randp}\n\ |
436 @end deftypefn") | 418 @end deftypefn") |
437 { | 419 { |
438 octave_value retval; | 420 return do_rand (args, args.length (), "rand", "uniform"); |
439 | |
440 int nargin = args.length (); | |
441 | |
442 retval = do_rand (args, nargin, "rand", "uniform"); | |
443 | |
444 return retval; | |
445 } | 421 } |
446 | 422 |
447 // FIXME: The old generator (selected when "seed" is set) will not | 423 // FIXME: The old generator (selected when "seed" is set) will not |
448 // work properly if compiled to use 64-bit integers. | 424 // work properly if compiled to use 64-bit integers. |
449 | 425 |
562 @url{http://www.jstatsoft.org/v05/i08/}\n\ | 538 @url{http://www.jstatsoft.org/v05/i08/}\n\ |
563 \n\ | 539 \n\ |
564 @seealso{rand, rande, randg, randp}\n\ | 540 @seealso{rand, rande, randg, randp}\n\ |
565 @end deftypefn") | 541 @end deftypefn") |
566 { | 542 { |
567 octave_value retval; | 543 return do_rand (args, args.length (), "randn", "normal"); |
568 | |
569 int nargin = args.length (); | |
570 | |
571 retval = do_rand (args, nargin, "randn", "normal"); | |
572 | |
573 return retval; | |
574 } | 544 } |
575 | 545 |
576 /* | 546 /* |
577 %!test | 547 %!test |
578 %! ## Test fixed state | 548 %! ## Test fixed state |
634 @url{http://www.jstatsoft.org/v05/i08/}\n\ | 604 @url{http://www.jstatsoft.org/v05/i08/}\n\ |
635 \n\ | 605 \n\ |
636 @seealso{rand, randn, randg, randp}\n\ | 606 @seealso{rand, randn, randg, randp}\n\ |
637 @end deftypefn") | 607 @end deftypefn") |
638 { | 608 { |
639 octave_value retval; | 609 return do_rand (args, args.length (), "rande", "exponential"); |
640 | |
641 int nargin = args.length (); | |
642 | |
643 retval = do_rand (args, nargin, "rande", "exponential"); | |
644 | |
645 return retval; | |
646 } | 610 } |
647 | 611 |
648 /* | 612 /* |
649 %!test | 613 %!test |
650 %! ## Test fixed state | 614 %! ## Test fixed state |
776 @qcode{\"double\"} or @qcode{\"single\"} argument. These are the only valid\n\ | 740 @qcode{\"double\"} or @qcode{\"single\"} argument. These are the only valid\n\ |
777 classes.\n\ | 741 classes.\n\ |
778 @seealso{rand, randn, rande, randp}\n\ | 742 @seealso{rand, randn, rande, randp}\n\ |
779 @end deftypefn") | 743 @end deftypefn") |
780 { | 744 { |
781 octave_value retval; | |
782 | |
783 int nargin = args.length (); | 745 int nargin = args.length (); |
784 | 746 |
785 if (nargin < 1) | 747 if (nargin < 1) |
786 error ("randg: insufficient arguments"); | 748 error ("randg: insufficient arguments"); |
787 else | 749 |
788 retval = do_rand (args, nargin, "randg", "gamma", true); | 750 return do_rand (args, nargin, "randg", "gamma", true); |
789 | |
790 return retval; | |
791 } | 751 } |
792 | 752 |
793 /* | 753 /* |
794 %!test | 754 %!test |
795 %! randg ("state", 12) | 755 %! randg ("state", 12) |
1005 @qcode{\"double\"} or @qcode{\"single\"} argument. These are the only valid\n\ | 965 @qcode{\"double\"} or @qcode{\"single\"} argument. These are the only valid\n\ |
1006 classes.\n\ | 966 classes.\n\ |
1007 @seealso{rand, randn, rande, randg}\n\ | 967 @seealso{rand, randn, rande, randg}\n\ |
1008 @end deftypefn") | 968 @end deftypefn") |
1009 { | 969 { |
1010 octave_value retval; | |
1011 | |
1012 int nargin = args.length (); | 970 int nargin = args.length (); |
1013 | 971 |
1014 if (nargin < 1) | 972 if (nargin < 1) |
1015 error ("randp: insufficient arguments"); | 973 error ("randp: insufficient arguments"); |
1016 else | 974 |
1017 retval = do_rand (args, nargin, "randp", "poisson", true); | 975 return do_rand (args, nargin, "randp", "poisson", true); |
1018 | |
1019 return retval; | |
1020 } | 976 } |
1021 | 977 |
1022 /* | 978 /* |
1023 %!test | 979 %!test |
1024 %! randp ("state", 12); | 980 %! randp ("state", 12); |
1119 randomization is performed using rand(). All permutations are equally\n\ | 1075 randomization is performed using rand(). All permutations are equally\n\ |
1120 likely.\n\ | 1076 likely.\n\ |
1121 @seealso{perms}\n\ | 1077 @seealso{perms}\n\ |
1122 @end deftypefn") | 1078 @end deftypefn") |
1123 { | 1079 { |
1124 octave_value retval; | |
1125 | |
1126 #ifdef USE_UNORDERED_MAP_WITH_TR1 | 1080 #ifdef USE_UNORDERED_MAP_WITH_TR1 |
1127 using std::tr1::unordered_map; | 1081 using std::tr1::unordered_map; |
1128 #else | 1082 #else |
1129 using std::unordered_map; | 1083 using std::unordered_map; |
1130 #endif | 1084 #endif |
1197 } | 1151 } |
1198 } | 1152 } |
1199 } | 1153 } |
1200 else | 1154 else |
1201 { | 1155 { |
1202 | |
1203 // Perform the Knuth shuffle of the first m entries | 1156 // Perform the Knuth shuffle of the first m entries |
1204 for (octave_idx_type i = 0; i < m; i++) | 1157 for (octave_idx_type i = 0; i < m; i++) |
1205 { | 1158 { |
1206 octave_idx_type k = i + | 1159 octave_idx_type k = i + |
1207 gnulib::floor (rvec[i] * (n - i)); | 1160 gnulib::floor (rvec[i] * (n - i)); |