GnmFunc: make this a GObject.
[gnumeric.git] / plugins / fn-random / functions.c
blobf88a6de1e97b9066322651b2ed6ca5bc9f0c5bdb
1 /*
2 * fn-random.c: Built in random number generation functions and functions
3 * registration
5 * Authors:
6 * Miguel de Icaza (miguel@gnu.org)
7 * Jukka-Pekka Iivonen (iivonen@iki.fi)
8 * Morten Welinder (terra@gnome.org)
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <https://www.gnu.org/licenses/>.
24 #include <gnumeric-config.h>
25 #include <gnumeric.h>
26 #include <func.h>
27 #include <mathfunc.h>
28 #include <gnm-random.h>
29 #include <rangefunc.h>
30 #include <value.h>
31 #include <expr.h>
32 #include <sheet.h>
33 #include <cell.h>
34 #include <collect.h>
35 #include <gnm-i18n.h>
37 #include <goffice/goffice.h>
38 #include <gnm-plugin.h>
40 GNM_PLUGIN_MODULE_HEADER;
42 /***************************************************************************/
44 static GnmFuncHelp const help_rand[] = {
45 { GNM_FUNC_HELP_NAME, F_("RAND:a random number between zero and one")},
46 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
47 { GNM_FUNC_HELP_EXAMPLES, "=RAND()" },
48 { GNM_FUNC_HELP_EXAMPLES, "=RAND()" },
49 { GNM_FUNC_HELP_SEEALSO, "RANDBETWEEN" },
50 { GNM_FUNC_HELP_END}
53 static GnmValue *
54 gnumeric_rand (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
56 return value_new_float (random_01 ());
59 /***************************************************************************/
61 static GnmFuncHelp const help_randuniform[] = {
62 { GNM_FUNC_HELP_NAME, F_("RANDUNIFORM:random variate from the uniform distribution from @{a} to @{b}") },
63 { GNM_FUNC_HELP_ARG, F_("a:lower limit of the uniform distribution") },
64 { GNM_FUNC_HELP_ARG, F_("b:upper limit of the uniform distribution") },
65 { GNM_FUNC_HELP_NOTE, F_("If @{a} > @{b} RANDUNIFORM returns #NUM!") },
66 { GNM_FUNC_HELP_EXAMPLES, "=RANDUNIFORM(1.4,4.2)" },
67 { GNM_FUNC_HELP_EXAMPLES, "=RANDUNIFORM(1.4,4.2)" },
68 { GNM_FUNC_HELP_SEEALSO, "RANDBETWEEN,RAND" },
69 { GNM_FUNC_HELP_END}
72 static GnmValue *
73 gnumeric_randuniform (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
75 gnm_float a = value_get_as_float (argv[0]);
76 gnm_float b = value_get_as_float (argv[1]);
78 if (a > b)
79 return value_new_error_NUM (ei->pos);
81 return value_new_float (a + ( random_01 () * (b - a) ) );
84 /***************************************************************************/
86 static GnmFuncHelp const help_randdiscrete[] = {
87 { GNM_FUNC_HELP_NAME, F_("RANDDISCRETE:random variate from a finite discrete distribution") },
88 { GNM_FUNC_HELP_ARG, F_("val_range:possible values of the random variable") },
89 { GNM_FUNC_HELP_ARG, F_("prob_range:probabilities of the corresponding values in @{val_range},"
90 " defaults to equal probabilities") },
91 { GNM_FUNC_HELP_DESCRIPTION, F_("RANDDISCRETE returns one of the values in the @{val_range}. "
92 "The probabilities for each value are given in the @{prob_range}.") },
93 { GNM_FUNC_HELP_NOTE, F_("If the sum of all values in @{prob_range} is not one, RANDDISCRETE returns #NUM!") },
94 { GNM_FUNC_HELP_NOTE, F_("If @{val_range} and @{prob_range} are not the same size, RANDDISCRETE returns #NUM!") },
95 { GNM_FUNC_HELP_NOTE, F_("If @{val_range} or @{prob_range} is not a range, RANDDISCRETE returns #VALUE!") },
96 { GNM_FUNC_HELP_EXAMPLES, "=RANDDISCRETE({1;3;5;7})" },
97 { GNM_FUNC_HELP_EXAMPLES, "=RANDDISCRETE({1;3;5;7})" },
98 { GNM_FUNC_HELP_SEEALSO, "RANDBETWEEN,RAND" },
99 { GNM_FUNC_HELP_END}
102 static GnmValue *
103 gnumeric_randdiscrete (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
105 GnmValue *res = NULL;
106 gnm_float *values = NULL;
107 gnm_float *probs = NULL;
108 int nv, np, i;
109 gnm_float p;
111 values = collect_floats_value (argv[0], ei->pos,
112 COLLECT_IGNORE_STRINGS |
113 COLLECT_IGNORE_BOOLS |
114 COLLECT_IGNORE_BLANKS,
115 &nv, &res);
116 if (res)
117 goto out;
119 if (argv[1]) {
120 probs = collect_floats_value (argv[1], ei->pos,
121 COLLECT_IGNORE_STRINGS |
122 COLLECT_IGNORE_BOOLS |
123 COLLECT_IGNORE_BLANKS,
124 &np, &res);
125 if (res)
126 goto out;
127 } else
128 np = nv;
130 if (nv < 1 || nv != np)
131 goto error;
133 if (probs) {
134 gnm_float pmin, psum;
136 gnm_range_min (probs, np, &pmin);
137 if (pmin < 0)
138 goto error;
140 gnm_range_sum (probs, np, &psum);
141 if (gnm_abs (psum - 1) > 1e-10)
142 goto error;
145 p = random_01 ();
146 if (probs) {
147 for (i = 0; i < np; i++) {
148 p -= probs[i];
149 if (p < 0)
150 break;
152 } else {
153 /* Uniform. */
154 i = (int)gnm_floor (p * nv);
157 /* MIN is needed because of the sum grace. */
158 res = value_new_float (values[MIN (i, nv - 1)]);
160 out:
161 g_free (values);
162 g_free (probs);
163 return res;
165 error:
166 res = value_new_error_NUM (ei->pos);
167 goto out;
170 /***************************************************************************/
172 static GnmFuncHelp const help_randexp[] = {
173 { GNM_FUNC_HELP_NAME, F_("RANDEXP:random variate from an exponential distribution") },
174 { GNM_FUNC_HELP_ARG, F_("b:parameter of the exponential distribution") },
175 { GNM_FUNC_HELP_EXAMPLES, "=RANDEXP(0.5)" },
176 { GNM_FUNC_HELP_EXAMPLES, "=RANDEXP(0.5)" },
177 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDBETWEEN" },
178 { GNM_FUNC_HELP_END}
181 static GnmValue *
182 gnumeric_randexp (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
184 gnm_float x = value_get_as_float (argv[0]);
186 return value_new_float (random_exponential (x));
189 /***************************************************************************/
191 static GnmFuncHelp const help_randpoisson[] = {
192 { GNM_FUNC_HELP_NAME, F_("RANDPOISSON:random variate from a Poisson distribution") },
193 { GNM_FUNC_HELP_ARG, F_("\xce\xbb:parameter of the Poisson distribution") },
194 { GNM_FUNC_HELP_NOTE, F_("If @{\xce\xbb} < 0 RANDPOISSON returns #NUM!") },
195 { GNM_FUNC_HELP_EXAMPLES, "=RANDPOISSON(30)" },
196 { GNM_FUNC_HELP_EXAMPLES, "=RANDPOISSON(30)" },
197 { GNM_FUNC_HELP_EXAMPLES, "=RANDPOISSON(2)" },
198 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDBETWEEN" },
199 { GNM_FUNC_HELP_END}
202 static GnmValue *
203 gnumeric_randpoisson (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
205 gnm_float x = value_get_as_float (argv[0]);
207 if (x < 0)
208 return value_new_error_NUM (ei->pos);
210 return value_new_float (random_poisson (x));
213 /***************************************************************************/
215 static GnmFuncHelp const help_randbinom[] = {
216 { GNM_FUNC_HELP_NAME, F_("RANDBINOM:random variate from a binomial distribution") },
217 { GNM_FUNC_HELP_ARG, F_("p:probability of success in a single trial") },
218 { GNM_FUNC_HELP_ARG, F_("n:number of trials") },
219 { GNM_FUNC_HELP_NOTE, F_("If @{p} < 0 or @{p} > 1 RANDBINOM returns #NUM!") },
220 { GNM_FUNC_HELP_NOTE, F_("If @{n} < 0 RANDBINOM returns #NUM!") },
221 { GNM_FUNC_HELP_EXAMPLES, "=RANDBINOM(0.5,10)" },
222 { GNM_FUNC_HELP_EXAMPLES, "=RANDBINOM(0.5,10)" },
223 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDBETWEEN" },
224 { GNM_FUNC_HELP_END}
227 static GnmValue *
228 gnumeric_randbinom (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
230 gnm_float p = value_get_as_float (argv[0]);
231 gnm_float trials = value_get_as_float (argv[1]);
233 if (p < 0 || p > 1 || trials < 0)
234 return value_new_error_NUM (ei->pos);
236 return value_new_float (random_binomial (p, gnm_floor (trials)));
239 /***************************************************************************/
241 static GnmFuncHelp const help_randbetween[] = {
242 { GNM_FUNC_HELP_NAME, F_("RANDBETWEEN:a random integer number between and "
243 "including @{bottom} and @{top}") },
244 { GNM_FUNC_HELP_ARG, F_("bottom:lower limit") },
245 { GNM_FUNC_HELP_ARG, F_("top:upper limit") },
246 { GNM_FUNC_HELP_NOTE, F_("If @{bottom} > @{top}, RANDBETWEEN returns #NUM!") },
247 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
248 { GNM_FUNC_HELP_EXAMPLES, "=RANDBETWEEN(3,7)" },
249 { GNM_FUNC_HELP_EXAMPLES, "=RANDBETWEEN(3,7)" },
250 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDUNIFORM" },
251 { GNM_FUNC_HELP_END}
254 static GnmValue *
255 gnumeric_randbetween (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
257 gnm_float bottom = value_get_as_float (argv[0]);
258 gnm_float top = value_get_as_float (argv[1]);
259 gnm_float choices;
261 if (bottom > top)
262 return value_new_error_NUM (ei->pos);
264 // Bottom is ceiled, top floored. We do this on the limits, not the
265 // resulting random number, in order to ensure all integers in the
266 // range have the same probability. Tests show that Excel 2013 does
267 // the same thing.
268 bottom = gnm_ceil (bottom);
269 top = gnm_floor (top);
271 // Rounding alert: adding 1 could add 2 after rounding.
272 choices = gnm_ceil ((top - bottom) + 0.875);
274 return value_new_float (bottom + gnm_floor (choices * random_01 ()));
277 /***************************************************************************/
279 static GnmFuncHelp const help_randnegbinom[] = {
280 { GNM_FUNC_HELP_NAME, F_("RANDNEGBINOM:random variate from a negative binomial distribution") },
281 { GNM_FUNC_HELP_ARG, F_("p:probability of success in a single trial") },
282 { GNM_FUNC_HELP_ARG, F_("n:number of failures") },
283 { GNM_FUNC_HELP_NOTE, F_("If @{p} < 0 or @{p} > 1 RANDNEGBINOM returns #NUM!") },
284 { GNM_FUNC_HELP_NOTE, F_("If @{n} < 1 RANDNEGBINOM returns #NUM!") },
285 { GNM_FUNC_HELP_EXAMPLES, "=RANDNEGBINOM(0.5,5)" },
286 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDBETWEEN" },
287 { GNM_FUNC_HELP_END}
290 static GnmValue *
291 gnumeric_randnegbinom (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
293 gnm_float p = value_get_as_float (argv[0]);
294 gnm_float failures = value_get_as_float (argv[1]);
296 if (p < 0 || p > 1 || failures < 1)
297 return value_new_error_NUM (ei->pos);
299 return value_new_float (random_negbinom (p, gnm_floor (failures)));
302 /***************************************************************************/
304 static GnmFuncHelp const help_randbernoulli[] = {
305 { GNM_FUNC_HELP_NAME, F_("RANDBERNOULLI:random variate from a Bernoulli distribution") },
306 { GNM_FUNC_HELP_ARG, F_("p:probability of success") },
307 { GNM_FUNC_HELP_NOTE, F_("If @{p} < 0 or @{p} > 1 RANDBERNOULLI returns #NUM!") },
308 { GNM_FUNC_HELP_EXAMPLES, "=RANDBERNOULLI(0.5)" },
309 { GNM_FUNC_HELP_EXAMPLES, "=RANDBERNOULLI(0.5)" },
310 { GNM_FUNC_HELP_EXAMPLES, "=RANDBERNOULLI(0.5)" },
311 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDBETWEEN" },
312 { GNM_FUNC_HELP_END}
315 static GnmValue *
316 gnumeric_randbernoulli (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
318 gnm_float p = value_get_as_float (argv[0]);
320 if (p < 0 || p > 1)
321 return value_new_error_NUM (ei->pos);
323 return value_new_float (random_bernoulli (p));
326 /***************************************************************************/
328 static GnmFuncHelp const help_randnorm[] = {
329 { GNM_FUNC_HELP_NAME, F_("RANDNORM:random variate from a normal distribution") },
330 { GNM_FUNC_HELP_ARG, F_("\xce\xbc:mean of the distribution") },
331 { GNM_FUNC_HELP_ARG, F_("\xcf\x83:standard deviation of the distribution") },
332 { GNM_FUNC_HELP_NOTE, F_("If @{\xcf\x83} < 0, RANDNORM returns #NUM!") },
333 { GNM_FUNC_HELP_EXAMPLES, "=RANDNORM(0,1)" },
334 { GNM_FUNC_HELP_EXAMPLES, "=RANDNORM(0,1)" },
335 { GNM_FUNC_HELP_SEEALSO, "RAND" },
336 { GNM_FUNC_HELP_END}
339 static GnmValue *
340 gnumeric_randnorm (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
342 gnm_float mean = value_get_as_float (argv[0]);
343 gnm_float stdev = value_get_as_float (argv[1]);
345 if (stdev < 0)
346 return value_new_error_NUM (ei->pos);
348 return value_new_float (stdev * random_normal () + mean);
351 /***************************************************************************/
353 static GnmFuncHelp const help_randcauchy[] = {
354 { GNM_FUNC_HELP_NAME, F_("RANDCAUCHY:random variate from a Cauchy or Lorentz distribution") },
355 { GNM_FUNC_HELP_ARG, F_("a:scale parameter of the distribution") },
356 { GNM_FUNC_HELP_NOTE, F_("If @{a} < 0 RANDCAUCHY returns #NUM!") },
357 { GNM_FUNC_HELP_EXAMPLES, "=RANDCAUCHY(1)" },
358 { GNM_FUNC_HELP_EXAMPLES, "=RANDCAUCHY(1)" },
359 { GNM_FUNC_HELP_SEEALSO, "RAND" },
360 { GNM_FUNC_HELP_END}
363 static GnmValue *
364 gnumeric_randcauchy (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
366 gnm_float a = value_get_as_float (argv[0]);
368 if (a < 0)
369 return value_new_error_NUM (ei->pos);
371 return value_new_float (random_cauchy (a));
374 /***************************************************************************/
376 static GnmFuncHelp const help_randlognorm[] = {
377 { GNM_FUNC_HELP_NAME, F_("RANDLOGNORM:random variate from a lognormal distribution") },
378 { GNM_FUNC_HELP_ARG, F_("\xce\xb6:parameter of the lognormal distribution") },
379 { GNM_FUNC_HELP_ARG, F_("\xcf\x83:standard deviation of the distribution") },
380 { GNM_FUNC_HELP_NOTE, F_("If @{\xcf\x83} < 0, RANDLOGNORM returns #NUM!") },
381 { GNM_FUNC_HELP_EXAMPLES, "=RANDLOGNORM(1,2)" },
382 { GNM_FUNC_HELP_EXAMPLES, "=RANDLOGNORM(1,2)" },
383 { GNM_FUNC_HELP_SEEALSO, "RAND" },
384 { GNM_FUNC_HELP_END}
387 static GnmValue *
388 gnumeric_randlognorm (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
390 gnm_float zeta = value_get_as_float (argv[0]);
391 gnm_float sigma = value_get_as_float (argv[1]);
393 return value_new_float (random_lognormal (zeta, sigma));
396 /***************************************************************************/
398 static GnmFuncHelp const help_randweibull[] = {
399 { GNM_FUNC_HELP_NAME, F_("RANDWEIBULL:random variate from a Weibull distribution") },
400 { GNM_FUNC_HELP_ARG, F_("a:scale parameter of the Weibull distribution") },
401 { GNM_FUNC_HELP_ARG, F_("b:shape parameter of the Weibull distribution") },
402 { GNM_FUNC_HELP_EXAMPLES, "=RANDWEIBULL(1,2)" },
403 { GNM_FUNC_HELP_EXAMPLES, "=RANDWEIBULL(1,2)" },
404 { GNM_FUNC_HELP_SEEALSO, "RAND" },
405 { GNM_FUNC_HELP_END}
408 static GnmValue *
409 gnumeric_randweibull (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
411 gnm_float a = value_get_as_float (argv[0]);
412 gnm_float b = value_get_as_float (argv[1]);
414 return value_new_float (random_weibull (a, b));
417 /***************************************************************************/
419 static GnmFuncHelp const help_randlaplace[] = {
420 { GNM_FUNC_HELP_NAME, F_("RANDLAPLACE:random variate from a Laplace distribution") },
421 { GNM_FUNC_HELP_ARG, F_("a:parameter of the Laplace distribution") },
422 { GNM_FUNC_HELP_EXAMPLES, "=RANDLAPLACE(1)" },
423 { GNM_FUNC_HELP_EXAMPLES, "=RANDLAPLACE(1)" },
424 { GNM_FUNC_HELP_SEEALSO, "RAND" },
425 { GNM_FUNC_HELP_END}
428 static GnmValue *
429 gnumeric_randlaplace (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
431 gnm_float a = value_get_as_float (argv[0]);
433 return value_new_float (random_laplace (a));
436 /***************************************************************************/
438 static GnmFuncHelp const help_randrayleigh[] = {
439 { GNM_FUNC_HELP_NAME, F_("RANDRAYLEIGH:random variate from a Rayleigh distribution") },
440 { GNM_FUNC_HELP_ARG, F_("\xcf\x83:scale parameter of the Rayleigh distribution") },
441 { GNM_FUNC_HELP_EXAMPLES, "=RANDRAYLEIGH(1)" },
442 { GNM_FUNC_HELP_EXAMPLES, "=RANDRAYLEIGH(1)" },
443 { GNM_FUNC_HELP_SEEALSO, "RAND" },
444 { GNM_FUNC_HELP_END}
447 static GnmValue *
448 gnumeric_randrayleigh (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
450 gnm_float sigma = value_get_as_float (argv[0]);
452 return value_new_float (random_rayleigh (sigma));
455 /***************************************************************************/
457 static GnmFuncHelp const help_randrayleightail[] = {
458 { GNM_FUNC_HELP_NAME, F_("RANDRAYLEIGHTAIL:random variate from the tail of a Rayleigh distribution") },
459 { GNM_FUNC_HELP_ARG, F_("a:lower limit of the tail") },
460 { GNM_FUNC_HELP_ARG, F_("\xcf\x83:scale parameter of the Rayleigh distribution") },
461 { GNM_FUNC_HELP_EXAMPLES, "=RANDRAYLEIGHTAIL(0.3,1)" },
462 { GNM_FUNC_HELP_EXAMPLES, "=RANDRAYLEIGHTAIL(0.3,1)" },
463 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDRAYLEIGH" },
464 { GNM_FUNC_HELP_END}
467 static GnmValue *
468 gnumeric_randrayleightail (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
470 gnm_float a = value_get_as_float (argv[0]);
471 gnm_float sigma = value_get_as_float (argv[1]);
473 return value_new_float (random_rayleigh_tail (a, sigma));
476 /***************************************************************************/
478 static GnmFuncHelp const help_randgamma[] = {
479 { GNM_FUNC_HELP_NAME, F_("RANDGAMMA:random variate from a Gamma distribution") },
480 { GNM_FUNC_HELP_ARG, F_("a:shape parameter of the Gamma distribution") },
481 { GNM_FUNC_HELP_ARG, F_("b:scale parameter of the Gamma distribution") },
482 { GNM_FUNC_HELP_NOTE, F_("If @{a} \xe2\x89\xa4 0, RANDGAMMA returns #NUM!") },
483 { GNM_FUNC_HELP_EXAMPLES, "=RANDGAMMA(1,2)" },
484 { GNM_FUNC_HELP_EXAMPLES, "=RANDGAMMA(1,2)" },
485 { GNM_FUNC_HELP_SEEALSO, "RAND" },
486 { GNM_FUNC_HELP_END}
489 static GnmValue *
490 gnumeric_randgamma (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
492 gnm_float a = value_get_as_float (argv[0]);
493 gnm_float b = value_get_as_float (argv[1]);
495 if (a <= 0)
496 return value_new_error_NUM (ei->pos);
498 return value_new_float (random_gamma (a, b));
501 /***************************************************************************/
503 static GnmFuncHelp const help_randpareto[] = {
504 { GNM_FUNC_HELP_NAME, F_("RANDPARETO:random variate from a Pareto distribution") },
505 { GNM_FUNC_HELP_ARG, F_("a:parameter of the Pareto distribution") },
506 { GNM_FUNC_HELP_ARG, F_("b:parameter of the Pareto distribution") },
507 { GNM_FUNC_HELP_EXAMPLES, "=RANDPARETO(1,2)" },
508 { GNM_FUNC_HELP_EXAMPLES, "=RANDPARETO(1,2)" },
509 { GNM_FUNC_HELP_SEEALSO, "RAND" },
510 { GNM_FUNC_HELP_END}
513 static GnmValue *
514 gnumeric_randpareto (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
516 gnm_float a = value_get_as_float (argv[0]);
517 gnm_float b = value_get_as_float (argv[1]);
519 return value_new_float (random_pareto (a, b));
522 /***************************************************************************/
524 static GnmFuncHelp const help_randfdist[] = {
525 { GNM_FUNC_HELP_NAME, F_("RANDFDIST:random variate from an F distribution") },
526 { GNM_FUNC_HELP_ARG, F_("df1:numerator degrees of freedom") },
527 { GNM_FUNC_HELP_ARG, F_("df2:denominator degrees of freedom") },
528 { GNM_FUNC_HELP_EXAMPLES, "=RANDFDIST(1,2)" },
529 { GNM_FUNC_HELP_EXAMPLES, "=RANDFDIST(1,2)" },
530 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDGAMMA" },
531 { GNM_FUNC_HELP_END}
534 static GnmValue *
535 gnumeric_randfdist (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
537 gnm_float nu1 = value_get_as_float (argv[0]);
538 gnm_float nu2 = value_get_as_float (argv[1]);
540 return value_new_float (random_fdist (nu1, nu2));
543 /***************************************************************************/
545 static GnmFuncHelp const help_randbeta[] = {
546 { GNM_FUNC_HELP_NAME, F_("RANDBETA:random variate from a Beta distribution") },
547 { GNM_FUNC_HELP_ARG, F_("a:parameter of the Beta distribution") },
548 { GNM_FUNC_HELP_ARG, F_("b:parameter of the Beta distribution") },
549 { GNM_FUNC_HELP_EXAMPLES, "=RANDBETA(1,2)" },
550 { GNM_FUNC_HELP_EXAMPLES, "=RANDBETA(1,2)" },
551 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDGAMMA" },
552 { GNM_FUNC_HELP_END}
555 static GnmValue *
556 gnumeric_randbeta (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
558 gnm_float a = value_get_as_float (argv[0]);
559 gnm_float b = value_get_as_float (argv[1]);
561 return value_new_float (random_beta (a, b));
564 /***************************************************************************/
566 static GnmFuncHelp const help_randlogistic[] = {
567 { GNM_FUNC_HELP_NAME, F_("RANDLOGISTIC:random variate from a logistic distribution") },
568 { GNM_FUNC_HELP_ARG, F_("a:parameter of the logistic distribution") },
569 { GNM_FUNC_HELP_EXAMPLES, "=RANDLOGISTIC(1)" },
570 { GNM_FUNC_HELP_EXAMPLES, "=RANDLOGISTIC(1)" },
571 { GNM_FUNC_HELP_SEEALSO, "RAND" },
572 { GNM_FUNC_HELP_END}
575 static GnmValue *
576 gnumeric_randlogistic (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
578 gnm_float a = value_get_as_float (argv[0]);
580 return value_new_float (random_logistic (a));
583 /***************************************************************************/
585 static GnmFuncHelp const help_randgeom[] = {
586 { GNM_FUNC_HELP_NAME, F_("RANDGEOM:random variate from a geometric distribution") },
587 { GNM_FUNC_HELP_ARG, F_("p:probability of success in a single trial") },
588 { GNM_FUNC_HELP_NOTE, F_("If @{p} < 0 or @{p} > 1 RANDGEOM returns #NUM!") },
589 { GNM_FUNC_HELP_EXAMPLES, "=RANDGEOM(0.4)" },
590 { GNM_FUNC_HELP_EXAMPLES, "=RANDGEOM(0.4)" },
591 { GNM_FUNC_HELP_SEEALSO, "RAND" },
592 { GNM_FUNC_HELP_END}
595 static GnmValue *
596 gnumeric_randgeom (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
598 gnm_float p = value_get_as_float (argv[0]);
600 if (p < 0 || p > 1)
601 return value_new_error_NUM (ei->pos);
603 return value_new_float (random_geometric (p));
606 /***************************************************************************/
608 static GnmFuncHelp const help_randhyperg[] = {
609 { GNM_FUNC_HELP_NAME, F_("RANDHYPERG:random variate from a hypergeometric distribution") },
610 { GNM_FUNC_HELP_ARG, F_("n1:number of objects of type 1") },
611 { GNM_FUNC_HELP_ARG, F_("n2:number of objects of type 2") },
612 { GNM_FUNC_HELP_ARG, F_("t:total number of objects selected") },
613 { GNM_FUNC_HELP_EXAMPLES, "=RANDHYPERG(21,1,9)" },
614 { GNM_FUNC_HELP_EXAMPLES, "=RANDHYPERG(21,1,9)" },
615 { GNM_FUNC_HELP_SEEALSO, "RAND" },
616 { GNM_FUNC_HELP_END}
619 static GnmValue *
620 gnumeric_randhyperg (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
622 gnm_float n1 = value_get_as_float (argv[0]);
623 gnm_float n2 = value_get_as_float (argv[1]);
624 gnm_float t = value_get_as_float (argv[2]);
626 return value_new_float (random_hypergeometric (gnm_floor (n1),
627 gnm_floor (n2),
628 gnm_floor (t)));
631 /***************************************************************************/
633 static GnmFuncHelp const help_randlog[] = {
634 { GNM_FUNC_HELP_NAME, F_("RANDLOG:random variate from a logarithmic distribution") },
635 { GNM_FUNC_HELP_ARG, F_("p:probability") },
636 { GNM_FUNC_HELP_NOTE, F_("If @{p} < 0 or @{p} > 1 RANDLOG returns #NUM!") },
637 { GNM_FUNC_HELP_EXAMPLES, "=RANDLOG(0.72)" },
638 { GNM_FUNC_HELP_EXAMPLES, "=RANDLOG(0.72)" },
639 { GNM_FUNC_HELP_SEEALSO, "RAND" },
640 { GNM_FUNC_HELP_END}
643 static GnmValue *
644 gnumeric_randlog (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
646 gnm_float p = value_get_as_float (argv[0]);
648 if (p < 0 || p > 1)
649 return value_new_error_NUM (ei->pos);
651 return value_new_float (random_logarithmic (p));
654 /***************************************************************************/
656 static GnmFuncHelp const help_randchisq[] = {
657 { GNM_FUNC_HELP_NAME, F_("RANDCHISQ:random variate from a Chi-square distribution") },
658 { GNM_FUNC_HELP_ARG, F_("df:degrees of freedom") },
659 { GNM_FUNC_HELP_EXAMPLES, "=RANDCHISQ(0.5)" },
660 { GNM_FUNC_HELP_EXAMPLES, "=RANDCHISQ(0.5)" },
661 { GNM_FUNC_HELP_SEEALSO, "RAND,RANDGAMMA" },
662 { GNM_FUNC_HELP_END}
665 static GnmValue *
666 gnumeric_randchisq (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
668 gnm_float nu = value_get_as_float (argv[0]);
670 return value_new_float (random_chisq (nu));
673 /***************************************************************************/
675 static GnmFuncHelp const help_randtdist[] = {
676 { GNM_FUNC_HELP_NAME, F_("RANDTDIST:random variate from a Student t distribution") },
677 { GNM_FUNC_HELP_ARG, F_("df:degrees of freedom") },
678 { GNM_FUNC_HELP_EXAMPLES, "=RANDTDIST(5)" },
679 { GNM_FUNC_HELP_EXAMPLES, "=RANDTDIST(5)" },
680 { GNM_FUNC_HELP_SEEALSO, "RAND" },
681 { GNM_FUNC_HELP_END}
684 static GnmValue *
685 gnumeric_randtdist (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
687 gnm_float nu = value_get_as_float (argv[0]);
689 return value_new_float (random_tdist (nu));
692 /***************************************************************************/
694 static GnmFuncHelp const help_randgumbel[] = {
695 { GNM_FUNC_HELP_NAME, F_("RANDGUMBEL:random variate from a Gumbel distribution") },
696 { GNM_FUNC_HELP_ARG, F_("a:parameter of the Gumbel distribution") },
697 { GNM_FUNC_HELP_ARG, F_("b:parameter of the Gumbel distribution") },
698 { GNM_FUNC_HELP_ARG, F_("type:type of the Gumbel distribution, defaults to 1") },
699 { GNM_FUNC_HELP_NOTE, F_("If @{type} is neither 1 nor 2, RANDGUMBEL returns #NUM!") },
700 { GNM_FUNC_HELP_EXAMPLES, "=RANDGUMBEL(0.5,1,2)" },
701 { GNM_FUNC_HELP_EXAMPLES, "=RANDGUMBEL(0.5,1,2)" },
702 { GNM_FUNC_HELP_SEEALSO, "RAND" },
703 { GNM_FUNC_HELP_END}
706 static GnmValue *
707 gnumeric_randgumbel (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
709 gnm_float a = value_get_as_float (argv[0]);
710 gnm_float b = value_get_as_float (argv[1]);
711 gnm_float type = argv[2] ? value_get_as_float (argv[2]) : 1;
713 if (type == 1)
714 return value_new_float (random_gumbel1 (a, b));
715 else if (type == 2)
716 return value_new_float (random_gumbel2 (a, b));
717 else
718 return value_new_error_NUM (ei->pos);
721 /***************************************************************************/
723 static GnmFuncHelp const help_randlevy[] = {
724 { GNM_FUNC_HELP_NAME, F_("RANDLEVY:random variate from a L\xc3\xa9vy distribution") },
725 { GNM_FUNC_HELP_ARG, F_("c:parameter of the L\xc3\xa9vy distribution") },
726 { GNM_FUNC_HELP_ARG, F_("\xce\xb1:parameter of the L\xc3\xa9vy distribution") },
727 { GNM_FUNC_HELP_ARG, F_("\xce\xb2:parameter of the L\xc3\xa9vy distribution, defaults to 0") },
728 { GNM_FUNC_HELP_DESCRIPTION, F_("For @{\xce\xb1} = 1, @{\xce\xb2}=0, the L\xc3\xa9vy distribution "
729 "reduces to the Cauchy (or Lorentzian) distribution.") },
730 { GNM_FUNC_HELP_DESCRIPTION, F_("For @{\xce\xb1} = 2, @{\xce\xb2}=0, the L\xc3\xa9vy distribution "
731 "reduces to the normal distribution.") },
732 { GNM_FUNC_HELP_NOTE, F_("If @{\xce\xb1} \xe2\x89\xa4 0 or @{\xce\xb1} > 2, RANDLEVY returns #NUM!") },
733 { GNM_FUNC_HELP_NOTE, F_("If @{\xce\xb2} < -1 or @{\xce\xb2} > 1, RANDLEVY returns #NUM!") },
734 { GNM_FUNC_HELP_EXAMPLES, "=RANDLEVY(0.5,0.1,1)" },
735 { GNM_FUNC_HELP_EXAMPLES, "=RANDLEVY(0.5,0.1,1)" },
736 { GNM_FUNC_HELP_SEEALSO, "RAND" },
737 { GNM_FUNC_HELP_END}
740 static GnmValue *
741 gnumeric_randlevy (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
743 gnm_float c = value_get_as_float (argv[0]);
744 gnm_float alpha = value_get_as_float (argv[1]);
745 gnm_float beta = argv[2] ? value_get_as_float (argv[2]): 0;
747 if (alpha <= 0 || alpha > 2 || beta < -1 || beta > 1)
748 return value_new_error_NUM (ei->pos);
750 return value_new_float (random_levy_skew (c, alpha, beta));
753 /***************************************************************************/
755 static GnmFuncHelp const help_randexppow[] = {
756 { GNM_FUNC_HELP_NAME, F_("RANDEXPPOW:random variate from an exponential power distribution") },
757 { GNM_FUNC_HELP_ARG, F_("a:scale parameter of the exponential power distribution") },
758 { GNM_FUNC_HELP_ARG, F_("b:exponent of the exponential power distribution") },
759 { GNM_FUNC_HELP_DESCRIPTION, F_("For @{b} = 1 the exponential power distribution "
760 "reduces to the Laplace distribution.") },
761 { GNM_FUNC_HELP_DESCRIPTION, F_("For @{b} = 2 the exponential power distribution "
762 "reduces to the normal distribution with \xcf\x83 = a/sqrt(2)") },
763 { GNM_FUNC_HELP_EXAMPLES, "=RANDEXPPOW(0.5,0.1)" },
764 { GNM_FUNC_HELP_EXAMPLES, "=RANDEXPPOW(0.5,0.1)" },
765 { GNM_FUNC_HELP_SEEALSO, "RAND" },
766 { GNM_FUNC_HELP_END}
769 static GnmValue *
770 gnumeric_randexppow (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
772 gnm_float a = value_get_as_float (argv[0]);
773 gnm_float b = value_get_as_float (argv[1]);
775 return value_new_float (random_exppow (a, b));
778 /***************************************************************************/
780 static GnmFuncHelp const help_randlandau[] = {
781 { GNM_FUNC_HELP_NAME, F_("RANDLANDAU:random variate from the Landau distribution") },
782 { GNM_FUNC_HELP_EXAMPLES, "=RANDLANDAU()" },
783 { GNM_FUNC_HELP_EXAMPLES, "=RANDLANDAU()" },
784 { GNM_FUNC_HELP_SEEALSO, "RAND" },
785 { GNM_FUNC_HELP_END}
788 static GnmValue *
789 gnumeric_randlandau (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
791 return value_new_float (random_landau ());
794 /***************************************************************************/
796 static GnmFuncHelp const help_randnormtail[] = {
797 { GNM_FUNC_HELP_NAME, F_("RANDNORMTAIL:random variate from the upper tail of a normal distribution with mean 0") },
798 { GNM_FUNC_HELP_ARG, F_("a:lower limit of the tail") },
799 { GNM_FUNC_HELP_ARG, F_("\xcf\x83:standard deviation of the normal distribution") },
800 { GNM_FUNC_HELP_NOTE, F_("The method is based on Marsaglia's famous "
801 "rectangle-wedge-tail algorithm (Ann Math Stat 32, 894-899 "
802 "(1961)), with this aspect explained in Knuth, v2, 3rd ed, p139, "
803 "586 (exercise 11).") },
804 { GNM_FUNC_HELP_EXAMPLES, "=RANDNORMTAIL(0.5,0.1)" },
805 { GNM_FUNC_HELP_SEEALSO, "RAND" },
806 { GNM_FUNC_HELP_END}
809 static GnmValue *
810 gnumeric_randnormtail (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
812 gnm_float a = value_get_as_float (argv[0]);
813 gnm_float sigma = value_get_as_float (argv[1]);
815 return value_new_float (random_gaussian_tail (a, sigma));
818 /***************************************************************************/
820 static GnmFuncHelp const help_simtable[] = {
821 { GNM_FUNC_HELP_NAME, F_("SIMTABLE:one of the values in the given argument list "
822 "depending on the round number of the simulation tool") },
823 { GNM_FUNC_HELP_ARG, F_("d1:first value") },
824 { GNM_FUNC_HELP_ARG, F_("d2:second value") },
825 { GNM_FUNC_HELP_DESCRIPTION, F_("SIMTABLE returns one of the values in the given argument list "
826 "depending on the round number of the simulation tool. When the "
827 "simulation tool is not activated, SIMTABLE returns @{d1}.\n"
828 "With the simulation tool and the SIMTABLE function you can "
829 "test given decision variables. Each SIMTABLE function contains "
830 "the possible values of a simulation variable. In most "
831 "valid simulation models you should have the same number of "
832 "values @{dN} for all decision variables. If the simulation is run "
833 "more rounds than there are values defined, SIMTABLE returns "
834 "#N/A error (e.g. if A1 contains `=SIMTABLE(1)' and A2 "
835 "`=SIMTABLE(1,2)', A1 yields #N/A error on the second round).\n"
836 "The successive use of the simulation tool also requires that you "
837 "give to the tool at least one input variable having RAND() or "
838 "any other RAND<distribution name>() function in it. "
839 "On each round, the simulation tool iterates for the given number "
840 "of rounds over all the input variables to reevaluate them. "
841 "On each iteration, "
842 "the values of the output variables are stored, and when "
843 "the round is completed, descriptive statistical information is "
844 "created according to the values.") },
845 { GNM_FUNC_HELP_EXAMPLES, "=SIMTABLE(223,225,227,229)" },
846 { GNM_FUNC_HELP_END}
849 typedef struct {
850 int index;
851 GnmValue *value;
852 } simtable_t;
854 static GnmValue *
855 callback_function_simtable (GnmEvalPos const *ep, GnmValue const *value, void *closure)
857 simtable_t *p = closure;
859 if (p->index == ep->sheet->simulation_round)
860 p->value = value_dup (value);
861 ++(p->index);
863 return NULL;
866 static GnmValue *
867 gnumeric_simtable (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
869 simtable_t p;
871 p.index = 0;
872 p.value = NULL;
874 function_iterate_argument_values
875 (ei->pos, callback_function_simtable, &p,
876 argc, argv, FALSE, CELL_ITER_IGNORE_BLANK);
878 /* See if there was any value worth using. */
879 if (p.value == NULL)
880 return value_new_error_NA (ei->pos);
882 return p.value;
885 /***************************************************************************/
886 /*gettext: For translations of the term skew-normal distribution see */
887 /* http://isi.cbs.nl/glossary/term3051.htm */
888 static GnmFuncHelp const help_randsnorm[] = {
889 { GNM_FUNC_HELP_NAME, F_("RANDSNORM:random variate from a skew-normal distribution") },
890 { GNM_FUNC_HELP_ARG, F_("\360\235\233\274:shape parameter of the skew-normal distribution, "
891 "defaults to 0") },
892 { GNM_FUNC_HELP_ARG, F_("\360\235\234\211:location parameter of the skew-normal distribution, "
893 "defaults to 0") },
894 { GNM_FUNC_HELP_ARG, F_("\360\235\234\224:scale parameter of the skew-normal distribution, "
895 "defaults to 1") },
896 { GNM_FUNC_HELP_DESCRIPTION, F_("The random variates are drawn from a skew-normal "
897 "distribution with shape parameter @{\360\235\233\274}. "
898 "When @{\360\235\233\274}=0, the skewness vanishes, and "
899 "we obtain the standard normal density; as \360\235\233\274"
900 " increases (in absolute value), the skewness of the "
901 "distribution increases; when @{\360\235\233\274} approaches "
902 "infinity the density converges to the so-called "
903 "half-normal (or folded normal) density function; "
904 "if the sign of @{\360\235\233\274} changes, the density "
905 "is reflected on the opposite side of the vertical axis.") },
906 { GNM_FUNC_HELP_NOTE, F_("The mean of a skew-normal distribution with location parameter @{\360\235\234\211}=0 "
907 "is not 0.") },
908 { GNM_FUNC_HELP_NOTE, F_("The standard deviation of a skew-normal distribution with scale parameter "
909 "@{\360\235\234\224}=1 is not 1.") },
910 { GNM_FUNC_HELP_NOTE, F_("The skewness of a skew-normal distribution is in general not @{\360\235\233\274}.") },
911 { GNM_FUNC_HELP_NOTE, F_("If @{\360\235\234\224} < 0, RANDSNORM returns #NUM!") },
912 { GNM_FUNC_HELP_EXAMPLES, "=RANDSNORM(-3,0,1)" },
913 { GNM_FUNC_HELP_EXAMPLES, "=RANDSNORM(-3,0,1)" },
914 { GNM_FUNC_HELP_SEEALSO, "RANDNORM,RANDSTDIST" },
915 { GNM_FUNC_HELP_END}
918 static GnmValue *
919 gnumeric_randsnorm (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
921 gnm_float alpha = 0.;
922 gnm_float mean = 0.;
923 gnm_float stdev = 1.;
924 gnm_float result;
926 if (argv[0]) {
927 alpha = value_get_as_float (argv[0]);
928 if (argv[1]) {
929 mean = value_get_as_float (argv[1]);
930 if (argv[2])
931 stdev = value_get_as_float (argv[2]);
935 if (stdev < 0)
936 return value_new_error_NUM (ei->pos);
938 result = ((alpha == 0.) ? random_normal () : random_skew_normal (alpha));
940 return value_new_float (stdev * result + mean);
943 /***************************************************************************/
945 static GnmFuncHelp const help_randstdist[] = {
946 { GNM_FUNC_HELP_NAME, F_("RANDSTDIST:random variate from a skew-t distribution") },
947 { GNM_FUNC_HELP_ARG, F_("df:degrees of freedom") },
948 { GNM_FUNC_HELP_ARG, F_("\360\235\233\274:shape parameter of the skew-t distribution, defaults to 0") },
949 { GNM_FUNC_HELP_NOTE, F_("The mean of a skew-t distribution is not 0.") },
950 { GNM_FUNC_HELP_NOTE, F_("The standard deviation of a skew-t distribution is not 1.") },
951 { GNM_FUNC_HELP_NOTE, F_("The skewness of a skew-t distribution is in general not @{\360\235\233\274}.") },
952 { GNM_FUNC_HELP_EXAMPLES, "=RANDSTDIST(5,-2)" },
953 { GNM_FUNC_HELP_EXAMPLES, "=RANDSTDIST(5,2)" },
954 { GNM_FUNC_HELP_SEEALSO, "RANDTDIST,RANDSNORM" },
955 { GNM_FUNC_HELP_END}
958 static GnmValue *
959 gnumeric_randstdist (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
961 gnm_float nu = value_get_as_float (argv[0]);
962 gnm_float alpha = argv[1] ? value_get_as_float (argv[1]) : 0.;
964 return ((alpha == 0.) ? value_new_float (random_tdist (nu))
965 : value_new_float (random_skew_tdist (nu, alpha)));
968 /***************************************************************************/
970 // Note: Most of the tests for these reside in sstest
972 GnmFuncDescriptor const random_functions[] = {
973 { "rand", "", help_rand,
974 gnumeric_rand, NULL,
975 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
976 GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
977 { "randbernoulli", "f", help_randbernoulli,
978 gnumeric_randbernoulli, NULL,
979 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
980 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
981 { "randbeta", "ff", help_randbeta,
982 gnumeric_randbeta, NULL,
983 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
984 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
985 { "randbetween", "ff", help_randbetween,
986 gnumeric_randbetween, NULL,
987 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
988 GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
989 { "randbinom", "ff", help_randbinom,
990 gnumeric_randbinom, NULL,
991 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
992 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
993 { "randcauchy", "f", help_randcauchy,
994 gnumeric_randcauchy, NULL,
995 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
996 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
997 { "randchisq", "f", help_randchisq,
998 gnumeric_randchisq, NULL,
999 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1000 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1001 { "randdiscrete", "r|r",
1002 help_randdiscrete, gnumeric_randdiscrete, NULL,
1003 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1004 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1005 { "randexp", "f", help_randexp,
1006 gnumeric_randexp, NULL,
1007 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1008 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1009 { "randexppow", "ff", help_randexppow,
1010 gnumeric_randexppow, NULL,
1011 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1012 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1013 { "randfdist", "ff", help_randfdist,
1014 gnumeric_randfdist, NULL,
1015 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1016 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1017 { "randgamma", "ff", help_randgamma,
1018 gnumeric_randgamma, NULL,
1019 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1020 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1021 { "randnormtail", "ff", help_randnormtail,
1022 gnumeric_randnormtail, NULL,
1023 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1024 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1025 { "randgeom", "f", help_randgeom,
1026 gnumeric_randgeom, NULL,
1027 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1028 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1029 { "randgumbel", "ff|f", help_randgumbel,
1030 gnumeric_randgumbel, NULL,
1031 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1032 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1033 { "randhyperg", "fff", help_randhyperg,
1034 gnumeric_randhyperg, NULL,
1035 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1036 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1037 { "randlandau", "", help_randlandau,
1038 gnumeric_randlandau, NULL,
1039 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1040 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1041 { "randlaplace", "f", help_randlaplace,
1042 gnumeric_randlaplace, NULL,
1043 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1044 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1045 { "randlevy", "ff|f", help_randlevy,
1046 gnumeric_randlevy, NULL,
1047 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1048 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1049 { "randlog", "f", help_randlog,
1050 gnumeric_randlog, NULL,
1051 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1052 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1053 { "randlogistic", "f", help_randlogistic,
1054 gnumeric_randlogistic, NULL,
1055 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1056 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1057 { "randlognorm", "ff", help_randlognorm,
1058 gnumeric_randlognorm, NULL,
1059 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1060 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1061 { "randnegbinom", "ff", help_randnegbinom,
1062 gnumeric_randnegbinom, NULL,
1063 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1064 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1065 { "randnorm", "ff", help_randnorm,
1066 gnumeric_randnorm, NULL,
1067 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1068 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1069 { "randpareto", "ff", help_randpareto,
1070 gnumeric_randpareto, NULL,
1071 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1072 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1073 { "randpoisson", "f", help_randpoisson,
1074 gnumeric_randpoisson, NULL,
1075 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1076 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1077 { "randrayleigh", "f", help_randrayleigh,
1078 gnumeric_randrayleigh, NULL,
1079 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1080 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1081 { "randrayleightail", "ff", help_randrayleightail,
1082 gnumeric_randrayleightail, NULL,
1083 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1084 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1085 { "randsnorm", "|fff", help_randsnorm,
1086 gnumeric_randsnorm, NULL,
1087 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1088 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1089 { "randstdist", "ff", help_randstdist,
1090 gnumeric_randstdist, NULL,
1091 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1092 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1093 { "randtdist", "f", help_randtdist,
1094 gnumeric_randtdist, NULL,
1095 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1096 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1097 { "randuniform", "ff", help_randuniform,
1098 gnumeric_randuniform, NULL,
1099 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1100 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1101 { "randweibull", "ff", help_randweibull,
1102 gnumeric_randweibull, NULL,
1103 GNM_FUNC_SIMPLE | GNM_FUNC_VOLATILE,
1104 GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1105 { "simtable", NULL, help_simtable,
1106 NULL, gnumeric_simtable,
1107 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1109 {NULL}