/* 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 "xlstat.h"
typedef LVAL (*subrfun)(V);
LOCAL LVAL datareduce1 P4H(subrfun, subrfun, LVAL, int);
LVAL xssum(V) { return(datareduce1(xssum, xadd, cvfixnum((FIXTYPE) 0), FALSE)); }
LVAL xsprod(V) { return(datareduce1(xsprod, xmul, cvfixnum((FIXTYPE) 1), FALSE)); }
LVAL xsmin(V) { return(datareduce1(xsmin, xmin, NIL, FALSE)); }
LVAL xsmax(V) { return(datareduce1(xsmax, xmax, NIL, FALSE)); }
LVAL xscount(V) { return(datareduce1(xscount, xadd, cvfixnum((FIXTYPE) 0), TRUE)); }
LOCAL LVAL datareduce1 P4C(subrfun, f, subrfun, bf, LVAL, nullval, int, count)
{
LVAL fcn, x, result;
switch (xlargc) {
case 0: result = nullval; break;
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 = xlcallsubr1(f, x);
xlpop();
}
return(result);
}
LOCAL int all_simple P1C(LVAL, x)
{
int i, n;
switch (ntype(x)) {
case CONS:
for (; consp(x); x = cdr(x))
if (compoundp(car(x))) return(FALSE);
break;
case VECTOR:
n = getsize(x);
for (i = 0; i < n; i++)
if (compoundp(getelement(x, i))) return(FALSE);
break;
case TVEC:
break;
case SYMBOL:
if (null(x)) break;
/* else fall through */
default:
xlerror("not a sequence", x);
}
return(TRUE);
}
static LVAL lastcdr P1C(LVAL, x)
{
LVAL last = NIL;
for (; consp(x); x = cdr(x)) last = x;
return(last);
}
static LVAL elementlist P1C(LVAL, x)
{
LVAL next, last, result;
if (!compoundp(x)) result = consa(x);
else {
xlprot1(x);
x = compounddataseq(x);
x = (listp(x)) ? copylist(x) : coerce_to_list(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 P1C(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(V) { return(elementseq(xlgetarg())); }
static LVAL base_ifelse(V)
{
LVAL a, b, c;
a = xlgetarg();
b = xlgetarg();
c = xlgetarg();
xllastarg();
return((a != NIL) ? b : c);
}
LVAL xsifelse(V) { return(subr_map_elements(base_ifelse)); }
typedef struct {
double real, imag;
int complex;
} Number;
static VOID make_number P2C(Number *, num, LVAL, x)
{
if (realp(x)) {
num->real = makefloat(x);
num->imag = 0.0;
num->complex = FALSE;
}
else if (complexp(x)) {
num->real = makefloat(getreal(x));
num->imag = makefloat(getimag(x));
num->complex = TRUE;
}
else xlerror("not a number", x);
}
static VOID base_mean P3C(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(V)
{
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(V)
{
LVAL x, result, temp, elem;
int n, N, replace, i, j;
x = xlgaseq();
n = getfixnum(xlgafixnum());
N = seqlen(x);
replace = (moreargs()) ? (xlgetarg() != NIL) : FALSE;
xllastarg();
if (! replace && n > N) n = N;
xlstkcheck(4);
xlprotect(x);
xlsave(result);
xlsave(elem);
xlsave(temp);
x = (listp(x)) ? coerce_to_tvec(x, s_true) : copyvector(x);
result = NIL;
if (N > 0 && n > 0) {
for (i = 0; i < n; i++) {
j = (replace) ? osrand(N) : i + osrand(N - i);
elem = gettvecelement(x, j);
result = cons(elem, result);
if (! replace) { /* swap elements i and j */
temp = gettvecelement(x, i);
settvecelement(x, i, elem);
settvecelement(x, j, temp);
}
}
}
xlpopn(4);
return(result);
}
syntax highlighted by Code2HTML, v. 0.9.1