home *** CD-ROM | disk | FTP | other *** search
- /* statistics - Basic statistical functions for XLISP-STAT. */
- /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
- /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
- /* You may give out copies of this software; for conditions see the */
- /* file COPYING included with this distribution. */
-
- #include "xlisp.h"
- #include "osdef.h"
- #ifdef ANSI
- #include "xlproto.h"
- #include "xlsproto.h"
- #include "osproto.h"
- #else
- #include "xlfun.h"
- #include "xlsfun.h"
- #include "osfun.h"
- #endif ANSI
-
- #ifdef ANSI
- LVAL datareduce1(LVAL (*)(),LVAL (*)(),LVAL,int),lastcdr(LVAL),
- elementlist(LVAL),basequant(void),quant(void),base_ifelse(void);
- int all_simple(LVAL);
- void make_number(Number *,LVAL),base_mean(int *,Number *,LVAL);
- #else
- LVAL datareduce1),lastcdr(),
- elementlist(),basequant(),quant(),base_ifelse();
- int all_simple();
- void make_number),base_mean();
- #endif ANSI
-
- LVAL xssum() { return(datareduce1(xssum, xsradd, cvfixnum((FIXTYPE) 0), FALSE)); }
- LVAL xsprod() { return(datareduce1(xsprod, xsrmul, cvfixnum((FIXTYPE) 1), FALSE)); }
- LVAL xsmin() { return(datareduce1(xsmin, xsrmin, NIL, FALSE)); }
- LVAL xsmax() { return(datareduce1(xsmax, xsrmax, NIL, FALSE)); }
- LVAL xscount() { return(datareduce1(xscount, xsradd, cvfixnum((FIXTYPE) 0), TRUE)); }
-
- static LVAL datareduce1(f, bf, nullval, count)
- LVAL (*f)(), (*bf)(), nullval;
- int count;
- {
- LVAL fcn, x, result;
-
- switch (xlargc) {
- case 0: result = nullval;
- case 1:
- if (compoundp(peekarg(0))) {
- xlstkcheck(2);
- xlsave(x);
- xlsave(fcn);
- fcn = cvsubr(bf, SUBR, 0);
- x = subr_map_elements(f);
- x = compounddataseq(x);
- result = reduce(fcn, x, FALSE, NIL);
- xlpopn(2);
- }
- else result = (count) ? cvfixnum((FIXTYPE) 1) : xlgetarg();
- break;
- default:
- xlsave1(x);
- x = makearglist(xlargc, xlargv);
- result = xscallsubr1(f, x);
- xlpop();
- }
- return(result);
- }
-
- /* check if all elements of the sequence x are simple (i. e. not compound) */
- LOCAL int all_simple(x)
- LVAL x;
- {
- int i, n;
-
- if (! sequencep(x)) xlerror("not a sequence", x);
- if (listp(x)) {
- for (; consp(x); x = cdr(x))
- if (compoundp(car(x))) return(FALSE);
- }
- else {
- n = getsize(x);
- for (i = 0; i < n; i++)
- if (compoundp(getelement(x, i))) return(FALSE);
- }
- return(TRUE);
- }
-
- static LVAL lastcdr(x)
- LVAL x;
- {
- LVAL last = NIL;
-
- for (; consp(x); x = cdr(x)) last = x;
-
- return(last);
- }
-
- static LVAL elementlist(x)
- LVAL x;
- {
- LVAL next, last, result;
-
- if (!compoundp(x)) result = consa(x);
- else {
- xlprot1(x);
- x = compounddataseq(x);
- x = (vectorp(x)) ? coerce_to_list(x) : copylist(x);
- if (all_simple(x)) result = x;
- else {
- for (next = x; consp(next); next = cdr(next))
- rplaca(next, elementlist(car(next)));
- result = car(x);
- last = lastcdr(car(x));
- for (next = cdr(x); consp(next); next = cdr(next)) {
- rplacd(last, car(next));
- last = lastcdr(car(next));
- }
- }
- xlpop();
- }
- return(result);
- }
-
- LVAL elementseq(x)
- LVAL x;
- {
- if (! compoundp(x)) xlerror("not a compound data item", x);
- x = compounddataseq(x);
- if (all_simple(x)) return(x);
- else return(elementlist(x));
- }
-
- LVAL xselement_seq() { return(elementseq(xlgetarg())); }
-
- static LVAL data;
-
- static LVAL basequant()
- {
- LVAL prob;
- double p, lowelem, highelem;
- int lowk, highk, n;
-
- prob = xlgetarg();
- p = makedouble(prob);
- if ((0.0 > p) || (1.0 < p))
- xlerror("not a probability", prob);
- xllastarg();
-
- n = getsize(data);
- lowk = (n - 1) * p;
- highk = (n - 1) - floor((n - 1) * (1 - p));
- lowelem = makedouble(getelement(data, lowk));
- highelem = makedouble(getelement(data, highk));
- return(cvflonum((FLOTYPE) (lowelem + highelem) / 2.0));
- }
-
- static LVAL quant() { return(recursive_subr_map_elements(basequant, quant)); }
-
- LVAL xsquantile()
- {
- LVAL result;
-
- xlsave1(data);
- data = xlgetarg();
- data = xscallsubr1(xssortdata, data);
- data = coerce_to_vector(data);
- result = quant();
- xlpop();
- return(result);
- }
-
- static LVAL base_ifelse()
- {
- LVAL a, b, c;
-
- a = xlgetarg();
- b = xlgetarg();
- c = xlgetarg();
- xllastarg();
-
- return((a != NIL) ? b : c);
- }
-
- LVAL xsifelse() { return(subr_map_elements(base_ifelse)); }
- /* in xlsdef.h JKL
- typedef struct {
- double real, imag;
- int complex;
- } Number;
- */
- static void make_number(num, x)
- Number *num;
- LVAL x;
- {
- if (fixp(x) || floatp(x)) {
- num->real = makedouble(x);
- num->imag = 0.0;
- num->complex = FALSE;
- }
- else if (complexp(x)) {
- num->real = makedouble(realpart(x));
- num->imag = makedouble(imagpart(x));
- num->complex = TRUE;
- }
- else xlerror("not a number", x);
- }
-
- static void base_mean(count, mean, x)
- int *count;
- Number *mean;
- LVAL x;
- {
- LVAL y;
- Number num;
- double c, p, q;
- int i, n;
-
- if (! compoundp(x)) {
- c = *count; p = c / (c + 1.0); q = 1.0 - p;
- make_number(&num, x);
- mean->real = p * mean->real + q * num.real;
- mean->complex = mean->complex || num.complex;
- if (mean->complex) mean->imag = p * mean->imag + q * num.imag;
- (*count)++;
- }
- else {
- x = compounddataseq(x);
- n = seqlen(x);
- for (i = 0; i < n; i++) {
- y = getnextelement(&x, i);
- base_mean(count, mean, y);
- }
- }
- }
-
- LVAL xsmean()
- {
- Number mean;
- int count;
- LVAL x;
-
- x = xlgetarg();
- xllastarg();
-
- mean.real = 0.0; mean.imag = 0.0; mean.complex = FALSE;
- count = 0;
- base_mean(&count, &mean, x);
- if (mean.complex) return(newdcomplex(mean.real,mean.imag));
- else return(cvflonum((FLOTYPE) mean.real));
- }
-
- LVAL xssample()
- {
- LVAL x, result, temp;
- int n, N, replace, i, j;
-
- x = xsgetsequence();
- n = getfixnum(xlgafixnum());
- N = seqlen(x);
- replace = (moreargs()) ? (xlgetarg() != NIL) : FALSE;
-
- xlstkcheck(2);
- xlprotect(x);
- xlsave(result);
- x = (listp(x)) ? coerce_to_vector(x) : copyvector(x);
- /* result = NIL; not needed JKL */
- if (N > 0 && n > 0) {
- for (i = 0; i < n; i++) {
- j = (replace) ? osrand(N) : i + osrand(N - i);
- result = cons(getelement(x, j), result);
- if (! replace) { /* swap elements i and j */
- temp = getelement(x, i);
- setelement(x, i, getelement(x, j));
- setelement(x, j, temp);
- }
- }
- }
- xlpopn(2);
- return(result);
- }
-