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));