#ifndef lint
#ifdef __GNUC__
#define ATTRIBUTE(attrs) __attribute__(attrs)
#else
#define ATTRIBUTE(attrs)
#endif
static char Rcs_Id[] ATTRIBUTE((used)) =
"$Id: rdtest.c,v 1.11 2013-01-05 01:18:52-08 geoff Exp $";
#endif
/*
* Test the random-distribution library. Usage:
*
* rdtest seed how_many distribution [params...]
*
* where:
*
* seed is the random seed. If seed is zero, the package's
* automatic seed generator is used.
* how_many
* is how many random numbers to generate.
* distribution
* is the distribution to draw from (see below).
* params are the parameters to the distribution (see below).
*
* Distributions supported:
*
* iuniform A uniform distribution of integers on the interval [p1, p2).
* uniform A uniform distribution on the interval [p1, p2).
* exponential Exponential with mean p1, default 1.
* erlang p1-Erlang with mean p2.
* weibull Weibull with shape parameter p1 and scale parameter p2.
* normal Normal with mean p1 and standard deviation p2.
* lognormal Lognormal with scale parameter p1 and shape parameter p2.
* triangular Triangular on the interval (p1, p2) with mode at p3.
* empirical p1 with probability p2, p3 with probability p4, ...,
* p(2n+1) with probability p(2n). Actually, the
* "probabilities" are
* weights, and do not need to sum to 1.
* continuous_empirical
* p1 to p3 with probability p2, p3 to p5 with
* probability p4, ..., p(2n+1) to p(2n+2) with
* probability p(2n). Actually, the "probabilities" are
* weights, and do not need to sum to 1.
*
* $Log: rdtest.c,v $
* Revision 1.11 2013-01-05 01:18:52-08 geoff
* Fix a lot of compiler warnings.
*
* Revision 1.10 2012-12-30 16:24:49-08 geoff
* Use gcc attributes to suppress warnings on Rcs_Id.
*
* Revision 1.9 2010-12-10 03:28:19-08 geoff
* Support the new empirical_distribution interface.
*
* Revision 1.8 2008-07-26 11:34:01+12 geoff
* Fix notation for intervals in commentary.
*
* Revision 1.7 2007/10/26 07:21:06 geoff
* Fix the usage message to be correct.
*
* Revision 1.6 2004/03/30 07:29:43 geoff
* Document the program better, and allow the random seed to be
* controlled for verification testing.
*
* Revision 1.5 2003/09/11 05:50:53 geoff
* Include string.h to get the declaration of strcmp.
*
* Revision 1.4 2001/06/18 10:09:24 geoff
* Get rid of some warning messages.
*
* Revision 1.3 2001/04/10 09:11:38 geoff
* Add a tiny bit of explanatory commentary. When testing the empirical
* distribution, expect the parameters to give individual probabilities,
* not running sums. In other words, calculate the running sums for the
* user before generating the distribution.
*
* Revision 1.2 2001/04/09 08:47:19 geoff
* Add RCS ID keywords. Give a name to a magic number I missed.
*
*/
#include "randistrs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char * argv[]);
static void usage(void);
#define SEED_PARAM 1 /* Offset of seed param in argv */
#define COUNT_PARAM 2 /* Offset of count param in argv */
#define DISTR_PARAM 3 /* Offset of distr param in argv */
#define PARAM_OFFSET 4 /* Offset of params in argv */
int main(
int argc, /* Argument count */
char * argv[]) /* Argument vector */
{
rd_empirical_control*
control = NULL; /* Control if empirical distr. */
size_t how_many; /* How many numbers to generate */
size_t i; /* Loop index */
size_t needed_params = 0;
/* Number of params needed by distr */
size_t n_params; /* Number of parameters */
size_t n_probs = 0; /* Number of empirical probabilites */
double * params; /* Parameters of distribution */
double * probs = NULL; /* Probabilities for empirical */
double ran_value = 0.0;
/* Value generated by PRNG */
uint32_t seed; /* Seed for PRNG */
double * values = NULL; /* Values for empirical */
if (argc <= PARAM_OFFSET)
usage();
seed = atoi (argv[SEED_PARAM]);
how_many = atoi (argv[COUNT_PARAM]);
n_params = argc - PARAM_OFFSET;
params = (double *) malloc (sizeof (double) * n_params);
if (params == NULL)
{
(void) fprintf (stderr, "rdtest: can't malloc params\n");
return 1;
}
for (i = 0; i < n_params; i++)
params[i] = atof (argv[i + PARAM_OFFSET]);
if (strcmp (argv[DISTR_PARAM], "iuniform") == 0)
needed_params = 2;
else if (strcmp (argv[DISTR_PARAM], "uniform") == 0)
needed_params = 2;
else if (strcmp (argv[DISTR_PARAM], "exponential") == 0)
needed_params = 1;
else if (strcmp (argv[DISTR_PARAM], "erlang") == 0)
{
if (n_params < 2 || params[0] < 1.0)
usage();
needed_params = 2;
}
else if (strcmp (argv[DISTR_PARAM], "weibull") == 0)
needed_params = 2;
else if (strcmp (argv[DISTR_PARAM], "normal") == 0)
needed_params = 2;
else if (strcmp (argv[DISTR_PARAM], "lognormal") == 0)
needed_params = 2;
else if (strcmp (argv[DISTR_PARAM], "triangular") == 0)
needed_params = 3;
else if (strcmp (argv[DISTR_PARAM], "empirical") == 0)
{
if (n_params % 2 != 0 || n_params < 4)
usage();
n_probs = n_params / 2;
probs = (double *) malloc (sizeof (double) * n_probs);
values = (double *) malloc (sizeof (double) * (n_probs + 1));
if (probs == NULL || values == NULL)
{
(void) fprintf (stderr, "rdtest: can't malloc probs/values\n");
return 1;
}
for (i = 0; i < n_probs; i++)
{
values[i] = params[i * 2];
probs[i] = params[i * 2 + 1];
if (probs[i] < 0)
{
(void)fprintf(stderr, "rdtest: negative probability given\n");
exit(2);
}
}
values[n_probs] = 0.0; /* Just for cleanliness */
needed_params = n_params;
control = rd_empirical_setup(n_probs, probs, values);
}
else if (strcmp(argv[DISTR_PARAM], "continuous_empirical") == 0)
{
if (n_params % 2 == 0 || n_params < 5)
usage();
n_probs = (n_params - 1) / 2;
probs = (double *) malloc (sizeof (double) * n_probs);
values = (double *) malloc (sizeof (double) * (n_probs + 1));
if (probs == NULL || values == NULL)
{
(void) fprintf (stderr, "rdtest: can't malloc probs/values\n");
return 1;
}
for (i = 0; i < n_probs; i++)
{
values[i] = params[i * 2];
probs[i] = params[i * 2 + 1];
if (probs[i] < 0)
{
(void)fprintf(stderr, "rdtest: negative probability given\n");
exit(2);
}
}
values[n_probs] = params[n_probs * 2];
needed_params = n_params;
control = rd_empirical_setup(n_probs, probs, values);
}
else
usage();
if (n_params != needed_params)
usage();
/*
* Pick a seed
*/
if (seed == 0)
mt_goodseed();
else
mt_seed32(seed);
for (i = 0; i < how_many; i++)
{
if (strcmp (argv[DISTR_PARAM], "iuniform") == 0)
ran_value = rd_iuniform ((int32_t)params[0], (int32_t)params[1]);
else if (strcmp (argv[DISTR_PARAM], "uniform") == 0)
ran_value = rd_uniform (params[0], params[1]);
else if (strcmp (argv[DISTR_PARAM], "exponential") == 0)
ran_value = rd_exponential (params[0]);
else if (strcmp (argv[DISTR_PARAM], "erlang") == 0)
ran_value = rd_erlang ((int) params[0], params[1]);
else if (strcmp (argv[DISTR_PARAM], "weibull") == 0)
ran_value = rd_weibull (params[0], params[1]);
else if (strcmp (argv[DISTR_PARAM], "normal") == 0)
ran_value = rd_normal (params[0], params[1]);
else if (strcmp (argv[DISTR_PARAM], "lognormal") == 0)
ran_value = rd_lognormal (params[0], params[1]);
else if (strcmp (argv[DISTR_PARAM], "triangular") == 0)
ran_value = rd_triangular (params[0], params[1], params[2]);
else if (strcmp (argv[DISTR_PARAM], "empirical") == 0)
ran_value = rd_double_empirical (control);
else if (strcmp (argv[DISTR_PARAM], "continuous_empirical") == 0)
ran_value = rd_continuous_empirical (control);
(void) printf ("%f\n", ran_value);
}
return 0;
}
static void usage(void)
{
(void) fprintf (stderr, "Usage: rdtest seed count distribution p0 ...\n");
(void) fprintf (stderr, "Distributions:\n");
(void) fprintf (stderr, "\tiuniform lower upper\n");
(void) fprintf (stderr, "\tuniform lower upper\n");
(void) fprintf (stderr, "\texponential mean\n");
(void) fprintf (stderr, "\terlang p mean\n");
(void) fprintf (stderr, "\tweibull shape scale\n");
(void) fprintf (stderr, "\tnormal mean sigma\n");
(void) fprintf (stderr, "\tlognormal shape scale\n");
(void) fprintf (stderr, "\ttriangular lower upper mode\n");
(void) fprintf (stderr, "\tempirical v0 p0 v1 p1 ... vn-1 pn-1\n");
(void) fprintf (stderr,
"\tcontinuous_empirical v0 p0 v1 p1 ... vn-1 pn-1 vn\n");
exit(2);
}