|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 18265 (0x4759) Types: TextFile Names: »probdist.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/stat-5.3/eu/stat/src/probdist.c«
/* Copyright 1986 Gary Perlman */ #include "stat.h" PGM(probdist,Probability Distribution Functions,5.3,12/16/86) #define MAXFIELDS 50 /* max fields on input line */ #define MAXCHARS BUFSIZ /* maximum number of chars in lines */ #define MAXBIN 1000 /* max number of binomial trials */ extern double poz (), critz (); extern double pof (), critf (); extern double pochisq (), critchi (); extern double getratio (); #define BADPROB (-1.0) extern double pobin (); extern int critbin (), randbin (); extern double apobin (), acritbin (); #define crituni(p) (1.0 - (p)) #define probuni(val) (1.0 - (val)) extern double Maxrand; /* defined in random.c */ #define randuni() ((double) rand () / Maxrand) #define pot(val,df) pof ((val)*(val), 1, (df)) #define critt(p,df) sqrt (critf ((p), 1, (df))) #define U_NAME "uniform" #define F_NAME "F" #define T_NAME "t" #define Z_NAME "normal-z" #define B_NAME "binomial" #define C_NAME "chi-square" #define shortprint(val) printf ("%.6f\n", val) #define f_print(df1,df2,val,prob) \ printf ("%s %3d %3d %12.4f %10.6f\n", F_NAME, df1, df2, val, prob) #define t_print(df,val,prob) \ printf ("%s %3d %12.4f %10.6f\n", T_NAME, df, val, prob) #define chi_print(df,val,prob) \ printf ("%s %3d %12.4f %10.6f\n", C_NAME, df, val, prob) #define z_print(val,prob) \ printf ("%s %12.4f %10.6f\n", Z_NAME, val, prob) #define u_print(val,prob) \ printf ("%s %12.4f %10.6f\n", U_NAME, val, prob) #define b_print(N,p1,p2,val,prob) \ printf ("%s %3d %d/%d %3d %10.6f\n", B_NAME, N, p1, p2, val, prob) #define okdist(string) (strchr ("unztcxfb", *string) != NULL) #define okfunc(string) (strchr ("rpcq", *string) != NULL) #define badval(dist,val) fprintf (stderr, "%s: '%s' is not a legal %s distribution value\n", Argv0, val, dist) #define getsampsize(str,var) getposint (str, "random sample size", var) Boole Randinit = FALSE; /* has the random number generator been set */ int Seed; /* used to set random number generator */ Boole Verbose; /* verbose output format */ Boole InfoVersion; /* print version information */ Boole InfoLimits; /* print program limits */ Boole InfoOptions; /* print usage information */ \f /*FUNCTION getposint: convert string to positive integer with checking */ Status getposint (string, desc, iptr) char *string; char *desc; int *iptr; { if (!isinteger (string)) { fprintf (stderr, "%s: '%s' (%s) is not an integer\n", Argv0, string, desc); return (FAILURE); } *iptr = atoi (string); if (*iptr <= 0) { fprintf (stderr, "%s: '%d' (%s) should have been a positive integer\n", Argv0, *iptr, desc); return (FAILURE); } return (SUCCESS); } \f /*FUNCTION getratio: parse/return the ratio-of-two-integers, or decimal */ double getratio (str, p1, p2) char *str; /* input string is not affected */ int *p1, *p2; /* receptacles for p1/p2 */ { double p = 0.0; /* computed probability ratio */ char *sv = str; /* save for error messages */ *p1 = 0; /* initial values */ *p2 = 0; if (*str == '.' || *str == '0') /* decimal value, call atof() */ { if (number (str)) /* string must be numerical */ p = atof (str); else { fprintf (stderr, "%s: probability '%s' not a number\n", Argv0, sv); p = BADPROB; } } else { *p1 = atoi (str); while (isdigit (*str)) str++; if (*str != '/') /* slash delimiter */ p = BADPROB; else { str++; *p2 = atoi (str); while (isdigit (*str)) str++; if (*str) /* bad: extra stuff left over */ p = BADPROB; } if (*p1 > 0 && *p2 > 0) p = (double) *p1 / (double) *p2; } /* range check */ if (p == BADPROB) fprintf (stderr, "%s: ratio '%s' is malformed\n", Argv0, sv); else if (! (p > 0.0 && p < 1.0)) { fprintf (stderr, "%s: probability '%g' from '%s' not in (0,1)\n", Argv0, p, sv); p = BADPROB; } return (p); } Status getprob (str, pptr) char *str; double *pptr; { int p1, p2; *pptr = getratio (str, &p1, &p2); return (*pptr == BADPROB); } \f /*FUNCTION checkparams: check number of distribution parameters */ Status checkparams (dist, nstrings, nparam, desc) char *dist; char *desc; { if (nstrings != nparam+1) { fprintf (stderr, "%s: %s distribution requires %s with value\n", Argv0, dist, desc); return (FAILURE); } return (SUCCESS); } \f /*FUNCTION tell: tell correct usage for program, functions, distribution */ tellusage (commandline) Boole commandline; /* full command line usage */ { fprintf (stderr, "Usage: "); if (commandline) fprintf (stderr, "%s [-v] [-s seed] ", Argv0); fprintf (stderr, "function distribution [parameters] value\n"); } tellfunctions (function) char *function; { fprintf (stderr, "%s: '%s' is not a legal function\n", Argv0, function); fprintf (stderr, " Supported functions are: %s %s %s\n", "probability", "critical-value", "random-sample"); } telldistributions (dist) char *dist; { fprintf (stderr, "%s: '%s' is not a legal distribution\n", Argv0, dist); fprintf (stderr, " Supported distributions are: %s %s %s %s %s %s\n", U_NAME, Z_NAME, B_NAME, C_NAME, T_NAME, F_NAME); } \f /*FUNCTION initial: returns local version of optind, index to first operand */ int initial (argc, argv) char **argv; { extern char *optarg; /* option value accessed through this by getopt */ extern int optind; /* will be index to first operand */ int opterr = 0; /* count of number of errors */ int flag; /* option flag characters read in here */ while ((flag = getopt (argc, argv, "s:vLOV")) != EOF) switch (flag) { default: opterr++; break; case 's': /* random seed */ if (setint (argv[0], flag, optarg, &Seed, 1, MAXINT)) opterr++; break; case 'v': Verbose = TRUE; break; case 'O': InfoOptions = TRUE; break; case 'V': InfoVersion = TRUE; break; case 'L': InfoLimits = TRUE; break; } if (opterr) /* print usage message and bail out */ { tellusage (TRUE); exit (1); } usinfo (); return (optind); } \f /*FUNCTION main */ main (argc, argv) int argc; char **argv; { Status result = SUCCESS; int firstop; /* index of first operand */ char line[BUFSIZ]; char *array[MAXFIELDS]; int ncols; int linecount = 0; ARGV0; firstop = initial (argc, argv); if (firstop < argc) { if (result = probdist (argv+firstop, argc-firstop)) tellusage (TRUE); } else { checkstdin (); while (gets (line)) { linecount++; if (ncols = parselin (line, array, MAXFIELDS)) { if (probdist (array, ncols)) { fprintf (stderr, "\tError(s) found on input line %d\n", linecount); tellusage (FALSE); result = FAILURE; } } } } exit (result); } \f /*FUNCTION usinfo: provide on-line help */ usinfo () { if (InfoVersion) pver (Version); if (InfoLimits) { plim (Argv0); const (MAXCHARS, "maximum number of characters in lines"); const (MAXBIN, "maximum number of binomial trials"); const (1, "minimum sample size for random number generation"); const (0, "minimum probability"); const (1, "maximum probability"); } if (InfoOptions) { ppgm (Argv0, Purpose); iopt ('s', "seed", "integer random number generator seed", Seed); lopt ('v', "verbose output format", Verbose); oper ("[function", "prob, critval, or rand", ""); oper ("distrib'n", "f, t, u, x, z, or b distribution", ""); oper ("[params]", "parameters for distribution", ""); oper ("value]", "stat, prob, or count to match function", ""); } if (InfoVersion || InfoLimits || InfoOptions) exit (SUCCESS); } \f /*FUNCTION probdist: process probdist requests in string array */ probdist (string, nstrings) char **string; /* array of parameters: "prob" "f" "1" "2" "12.56" */ int nstrings; /* number of parameters */ { char *function; /* rand, prob, or crit */ char *dist; /* u, z/n, f, chisq/x, bin */ if (nstrings < 3) return (FAILURE); function = string[0]; dist = string[1]; string += 2; nstrings -= 2; if (isupper (*function)) *function = tolower (*function); if (isupper (*dist)) *dist = tolower (*dist); if (!okfunc (function) || !okdist (dist)) { if (!okfunc (function)) tellfunctions (function); if (!okdist (dist)) telldistributions (dist); return (FAILURE); } if (*function == 'r' && Randinit == FALSE) { initrand (Seed); Randinit = TRUE; } switch (*dist) { case 'b': return (pd_binomial (function, string, nstrings)); case 't': return (pd_t (function, string, nstrings)); case 'u': return (pd_uni (function, string, nstrings)); case 'n': case 'z': return (pd_z (function, string, nstrings)); case 'c': case 'x': return (pd_chisq (function, string, nstrings)); case 'f': return (pd_f (function, string, nstrings)); } return (0); } \f /*FUNCTION: uniform distribution */ Status pd_uni (function, string, nstrings) char *function; char **string; /* distrib parameters followed by value for function */ int nstrings; { char *svalue = string[nstrings-1]; double p; /* probability of value in distribution */ double stat; /* value in distribution */ int nrand; /* random sample size */ char *dist = U_NAME; /* distribution name */ if (checkparams (dist, nstrings, 0, "no parameters")) return (FAILURE); switch (*function) { case 'r': /* random number generation */ if (getsampsize (svalue, &nrand)) return (FAILURE); while (nrand--) { p = randuni (); stat = crituni (p); Verbose ? u_print (stat, p) : shortprint (stat); } break; case 'p': /* probability */ if (!number (svalue) || (stat = atof (svalue)) < 0.0 || stat > 1.0) { badval (dist, svalue); return (FAILURE); } p = probuni (stat); Verbose ? u_print (stat, p) : shortprint (p); break; case 'q': case 'c': /* critical value or quantile */ if (getprob (svalue, &p)) return (FAILURE); stat = crituni (p); Verbose ? u_print (stat, p) : shortprint (stat); break; } return (SUCCESS); } \f /*FUNCTION: normal z distribution */ Status pd_z (function, string, nstrings) char *function; char **string; /* distrib parameters followed by value for function */ int nstrings; { char *svalue = string[nstrings-1]; double p; /* probability of value in distribution */ double stat; /* value in distribution */ int nrand; /* random sample size */ char *dist = Z_NAME; /* distribution name */ if (checkparams (dist, nstrings, 0, "no parameters")) return (FAILURE); switch (*function) { case 'r': /* random number generation */ if (getsampsize (svalue, &nrand)) return (FAILURE); while (nrand--) { p = randuni (); stat = critz (p); Verbose ? z_print (stat, p) : shortprint (stat); } break; case 'p': /* probability */ if (!number (svalue)) { badval (dist, svalue); return (FAILURE); } stat = atof (svalue); p = poz (stat); Verbose ? z_print (stat, p) : shortprint (p); break; case 'q': case 'c': /* critical value or quantile */ if (getprob (svalue, &p)) return (FAILURE); stat = critz (p); Verbose ? z_print (stat, p) : shortprint (stat); break; } return (SUCCESS); } \f /*FUNCTION: Fisher F distribution */ Status pd_f (function, string, nstrings) char *function; char **string; /* distrib parameters followed by value for function */ int nstrings; { char *svalue = string[nstrings-1]; int df1; /* degrees of freedom numerator */ int df2; /* degrees of freedom denominator */ double p; /* probability of value in distribution */ double stat; /* value in distribution */ int nrand; /* random sample size */ char *dist = F_NAME; /* distribution name */ if (checkparams (dist, nstrings, 2, "two degrees of freedom")) return (FAILURE); if (getposint (string[0], "degrees of freedom numerator", &df1)) return (FAILURE); if (getposint (string[1], "degrees of freedom denominator", &df2)) return (FAILURE); switch (*function) { case 'r': /* random number generation */ if (getsampsize (svalue, &nrand)) return (FAILURE); while (nrand--) { p = randuni (); stat = critf (p, df1, df2); Verbose ? f_print (df1, df2, stat, p) : shortprint (stat); } break; case 'p': /* probability */ if (!number (svalue) || (stat = atof (svalue)) < 0.0) { badval (dist, svalue); return (FAILURE); } p = pof (stat, df1, df2); Verbose ? f_print (df1, df2, stat, p) : shortprint (p); break; case 'q': case 'c': /* critical value or quantile */ if (getprob (svalue, &p)) return (FAILURE); stat = critf (p, df1, df2); Verbose ? f_print (df1, df2, stat, p) : shortprint (stat); break; } return (SUCCESS); } \f /*FUNCTION: chi-sqaure distribution */ Status pd_chisq (function, string, nstrings) char *function; char **string; /* distrib parameters followed by value for function */ int nstrings; { char *svalue = string[nstrings-1]; int df; /* degrees of freedom */ double p; /* probability of value in distribution */ double stat; /* value in distribution */ int nrand; /* random sample size */ char *dist = C_NAME; /* distribution name */ if (checkparams (dist, nstrings, 1, "degrees of freedom")) return (FAILURE); if (getposint (string[0], "degrees of freedom", &df)) return (FAILURE); switch (*function) { case 'r': /* random number generation */ if (getsampsize (svalue, &nrand)) return (FAILURE); while (nrand--) { p = randuni (); stat = critchi (p, df); Verbose ? chi_print (df, stat, p) : shortprint (stat); } break; case 'p': /* probability */ if (!number (svalue) || (stat = atof (svalue)) < 0.0) { badval (dist, svalue); return (FAILURE); } p = pochisq (stat, df); Verbose ? chi_print (df, stat, p) : shortprint (p); break; case 'q': case 'c': if (getprob (svalue, &p)) return (FAILURE); stat = critchi (p, df); Verbose ? chi_print (df, stat, p) : shortprint (stat); break; } return (SUCCESS); } \f /*FUNCTION: Student's t distribution */ Status pd_t (function, string, nstrings) char *function; char **string; /* distrib parameters followed by value for function */ int nstrings; { char *svalue = string[nstrings-1]; int df; /* degrees of freedom */ double p; /* probability of value in distribution */ double stat; /* value in distribution */ int nrand; /* random sample size */ char *dist = T_NAME; /* distribution name */ if (checkparams (dist, nstrings, 1, "degrees of freedom")) return (FAILURE); if (getposint (string[0], "degrees of freedom", &df)) return (FAILURE); switch (*function) { case 'r': /* random number generation */ if (getsampsize (svalue, &nrand)) return (FAILURE); while (nrand--) { p = randuni (); stat = critt (p, df); Verbose ? t_print (df, stat, p) : shortprint (stat); } break; case 'p': /* probability */ if (!number (svalue)) { badval (dist, svalue); return (FAILURE); } stat = atof (svalue); p = pot (stat, df); Verbose ? t_print (df, stat, p) : shortprint (p); break; case 'q': case 'c': /* critical value or quantile */ if (getprob (svalue, &p)) return (FAILURE); stat = critt (p, df); Verbose ? t_print (df, stat, p) : shortprint (stat); break; } return (SUCCESS); } \f /*FUNCTION: binomial distribution */ Status pd_binomial (function, string, nstrings) char *function; char **string; /* distrib parameters followed by value for function */ int nstrings; { char *svalue = string[nstrings-1]; int N; /* number of Bernouli trials */ int p1, p2; /* probability ratio parameters */ double p = 0.0; /* prob of success == p1/p2 */ int r; /* number of successes */ int nrand; /* random sample size */ char *dist = B_NAME; /* distribution name */ if (checkparams (dist, nstrings, 2, "N and probability ratio")) return (FAILURE); if (getposint (string[0], "number of trials", &N)) return (FAILURE); if (N > MAXBIN) { fprintf (stderr, "%s: maximum binomial trials: %d\n", Argv0, MAXBIN); return (FAILURE); } if ((p = getratio (string[1], &p1, &p2)) == BADPROB) return (FAILURE); if (p1 == 0 || p2 == 0) /* maybe use approximate binomial */ { fprintf (stderr, "%s: invalid ratio supplied (%s)\n", Argv0, string[1]); return (FAILURE); } if (p2 > MAXBIN) { fprintf (stderr, "%s: maximum ratio denominator: %d\n", Argv0, MAXBIN); return (FAILURE); } switch (*function) { case 'r': /* random number generation */ if (getsampsize (svalue, &nrand)) return (FAILURE); while (nrand--) { r = randbin (N, p1, p2); Verbose ? b_print (N, p1, p2, r, p) : printf ("%d\n", r); } break; case 'p': /* probability */ if (!number (svalue) || (r = atoi (svalue)) < 0 || r > N) { badval (dist, svalue); return (FAILURE); } p = pobin (N, p1, p2, r); Verbose ? b_print (N, p1, p2, r, p) : shortprint (p); break; case 'q': case 'c': /* critical value or quantile */ if (getprob (svalue, &p)) return (FAILURE); r = critbin (N, p1, p2, &p); Verbose ? b_print (N, p1, p2, r, p) : printf ("%d\n", r); break; } return (SUCCESS); } \f /*FUNCTION randbin: return a random binomial number */ int randbin (N, p1, p2) register int N; /* distribution size */ int p1, p2; /* p = p1/p2 */ { double p = (double) p1 / (double) p2; int r = 0; /* number of successes */ extern double Maxrand; while (N-- > 0) if (((double) rand ()) / Maxrand < p) r++; return (r); }