home *** CD-ROM | disk | FTP | other *** search
- /* utilities - basic utility functions */
- /* 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 <stdlib.h>
- #include "xlisp.h"
- #include "osdef.h"
- #ifdef ANSI
- #include "xlproto.h"
- #include "xlsproto.h"
- #else
- #include "xlfun.h"
- #include "xlsfun.h"
- #endif ANSI
- #include "xlsvar.h"
-
- /************************************************************************/
- /** Basic Utilities **/
- /************************************************************************/
-
- /* find length of a list */
- int llength(x)
- LVAL x;
- {
- int n;
-
- for (n = 0; consp(x); n++, x = cdr(x));
-
- return(n);
- }
-
- /* return list of two elements */
- LVAL list2(x1, x2)
- LVAL x1, x2;
- {
- LVAL list, y1, y2;
-
- /* protect some pointers */
- xlstkcheck(3);
- xlsave(list);
- xlsave(y1); /* redundant initialization of y1 and y2 in macro JKL */
- xlsave(y2);
-
- y1 = x1;
- y2 = x2;
- list = consa(y2);
- list = cons(y1, list);
-
- /* restore the stack frame */
- xlpopn(3);
-
- return(list);
- }
-
- /* return list of three elements */
- LVAL list3(x1, x2, x3)
- LVAL x1, x2, x3;
- {
- LVAL list, y1, y2, y3;
-
- /* protect some pointers */
- xlstkcheck(4);
- xlsave(list);
- xlsave(y1); /* redundant initialization of y1, y2, and y3 in macro JKL */
- xlsave(y2);
- xlsave(y3);
-
- y1 = x1;
- y2 = x2;
- y3 = x3;
- list = consa(y3);
- list = cons(y2, list);
- list = cons(y1, list);
-
- /* restore the stack frame */
- xlpopn(4);
-
- return(list);
- }
-
- /* return the i-th argument, without popping it; signal an error if needed. */
- LVAL peekarg(i)
- int i;
- {
- if (xlargc <= i) xltoofew();
- else return(xlargv[i]);
- }
-
- /* Get the next argument from the list or the stack; cdr the list */
- LVAL getnextarg(plist, from_stack)
- LVAL *plist;
- int from_stack;
- {
- LVAL arg;
- if (from_stack) arg = xlgetarg();
- else if (consp(*plist)) {
- arg = car(*plist);
- *plist = cdr(*plist);
- }
- else
- xlfail("no arguments left");
- return(arg);
- }
-
- /* Get the next element in the sequence; cdr the pointer if it is a list */
- LVAL getnextelement(pseq, i)
- LVAL *pseq;
- int i;
- {
- LVAL value;
-
- if (vectorp(*pseq)) value = getelement(*pseq, i);
- else {
- if (! consp(*pseq)) xlerror("not a list", *pseq);
- value = car(*pseq);
- *pseq = cdr(*pseq);
- }
- return(value);
- }
-
- /* get and check a sequence argument */
- LVAL xsgetsequence()
- {
- LVAL arg;
-
- arg = xlgetarg();
- if (! sequencep(arg)) xlerror("not a sequence", arg);
- return(arg);
- }
-
- /* set a fixnum node */
- void setfixnum(node, val)
- LVAL node;
- FIXTYPE val;
- {
- node->n_fixnum = val;
- node->n_type = FIXNUM;
- }
-
- /* Set the next element in the sequence; cdr the pointer if it is a list */
- void setnextelement(pseq, i, value)
- LVAL *pseq, value;
- int i;
- {
- if (vectorp(*pseq)) setelement(*pseq, i, value);
- else {
- rplaca(*pseq, value);
- *pseq = cdr(*pseq);
- }
- }
-
- /* Check for a nonnegative integer */
- LVAL checknonnegint(x)
- LVAL x;
- {
- if (! fixp(x) || getfixnum(x) < 0) xlerror("Not a nonnegative integer", x);
- return(x);
- }
-
- /* return value of a number coerced to a double */
- double makedouble(x)
- LVAL x;
- {
- if (! numberp(x)) xlerror("not a number", x);
- return((fixp(x)) ? (double) getfixnum(x) : getflonum(x));
- }
-
- /************************************************************************/
- /** Function Application Utilities **/
- /************************************************************************/
-
- void pushargvec(fun, argc, argv)
- LVAL fun, *argv;
- int argc;
- {
- LVAL *newfp;
- int i;
-
- /* build a new argument stack frame */
- newfp = xlsp;
- pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
- pusharg(fun);
- pusharg(cvfixnum((FIXTYPE)argc));
-
- /* push the arguments */
- for (i = 0; i < argc; i++)
- pusharg(argv[i]);
-
- /* establish the new stack frame */
- xlfp = newfp;
- }
-
- LVAL xsapplysubr(f, args)
- #ifdef ANSI
- LVAL (*f)(void), args;
- #else
- LVAL (*f)(), args;
- #endif ANSI
- {
- LVAL *oldargv, val;
- int argc, oldargc;
-
- xlprot1(args); /* protect arguments while pushing */
- argc = pushargs(NIL, args);
- xlpop(); /* now they are protected since they are on the stack */
-
- oldargc = xlargc;
- oldargv = xlargv;
- xlargc = argc;
- xlargv = xlfp + 3;
- val = (*f)();
- xlargc = oldargc;
- xlargv = oldargv;
-
- /* remove the call frame */
- xlsp = xlfp;
- xlfp = xlfp - (int)getfixnum(*xlfp);
- return(val);
- }
-
- LVAL xscallsubrvec(f, argc, argv)
- #ifdef ANSI
- LVAL (*f)(void), *argv;
- #else
- LVAL (*f)(), *argv;
- #endif ANSI
- int argc;
- {
- LVAL *oldargv, val;
- int oldargc;
-
- pushargvec(NIL, argc, argv);
- oldargc = xlargc;
- oldargv = xlargv;
- xlargc = argc;
- xlargv = xlfp + 3;
- val = (*f)();
- xlargc = oldargc;
- xlargv = oldargv;
-
- /* remove the call frame */
- xlsp = xlfp;
- xlfp = xlfp - (int)getfixnum(*xlfp);
- return(val);
- }
-
- LVAL xscallsubr1(f, x)
- LVAL (*f)(), x;
- {
- return(xscallsubrvec(f, 1, &x));
- }
-
- LVAL xscallsubr2(f, x, y)
- LVAL (*f)(), x, y;
- {
- LVAL args[2];
-
- args[0] = x;
- args[1] = y;
- return(xscallsubrvec(f, 2, args));
- }
-
- LVAL xsfuncall1(fun, x)
- LVAL fun, x;
- {
- pushargvec(fun, 1, &x);
- return(xlapply(1));
- }
-
- LVAL xsfuncall2(fun, x, y)
- LVAL fun, x, y;
- {
- LVAL args[2];
-
- args[0] = x;
- args[1] = y;
- pushargvec(fun, 2, args);
- return(xlapply(2));
- }
-
- #ifdef DODO
- /************************************************************************/
- /** **/
- /** Temporary Storage Allocation Routines **/
- /** **/
- /************************************************************************/
-
- char *xstcalloc(n, size)
- int n, size;
- {
- char *result;
-
- if ((result = calloc((unsigned) n, (unsigned) size)) == NULL)
- xlfail("memory allocation failed");
- return(result);
- }
-
- void xstfree(ptr)
- /*char*/ void *ptr;/* changed JKL */
- {
- free(ptr);
- }
-
- /************************************************************************/
- /** **/
- /** Lisp to/from C/Fortran Data Conversion Routines **/
- /** **/
- /************************************************************************/
- double *data_to_double(x)
- LVAL x;
- {
- LVAL data, val;
- double *result;
- int n, rows, cols, i, j;
-
- if (matrixp(x)) n = getsize(arraydata(x));
- else if (sequencep(x)) n = seqlen(x);
- else xlerror("Bad data type", x);
-
- result = (double *) xstcalloc(n, sizeof(double));
-
- data = (sequencep(x)) ? x : arraydata(x);
-
- if (matrixp(x)) {
- rows = numrows(x);
- cols = numcols(x);
- for (i = 0; i < rows; i++)
- for (j = 0; j < cols; j++) {
- val = getelement(data, cols * i + j);
- if (! numberp(val)) {
- free(result);
- xlerror("element not a number", val);
- }
- result[i + rows * j] = (fixp(val)) ? getfixnum(val) : getflonum(val);
- }
- }
- else {
- for (i = 0; i < n; i++) {
- val = getnextelement(&x, i);
- if (! numberp(val)) {
- free(result);
- xlerror("element not a number", val);
- }
- result[i] = (fixp(val)) ? getfixnum(val) : getflonum(val);
- }
- }
- return(result);
- }
-
- LVAL double_to_matrix(x, n, k)
- double *x;
- int n, k;
- {
- LVAL dim, nn, kk, val, result, result_data;
- int i, j;
-
- /* protect some pointers */
- xlstkcheck(5);
- xlsave(dim);
- xlsave(nn);
- xlsave(kk);
- xlsave(val);
- xlsave(result);
-
- nn = cvfixnum((FIXTYPE) n);
- kk = cvfixnum((FIXTYPE) k);
- dim = list2(nn, kk);
- result = newarray(dim, NIL, NIL);
- result_data = arraydata(result);
-
- for (i = 0; i < n; i++)
- for (j = 0; j < k; j++) {
- val = cvflonum((FLOTYPE) x[i + n * j]);
- setelement(result_data, k * i + j, val);
- }
-
- /* restore the stack frame */
- xlpopn(5);
-
- return(result);
- }
-
- LVAL double_to_sequence(x, n, list)
- double *x;
- int n, list;
- {
- LVAL val, result, next;
- int i;
-
- /* protect some pointers */
- xlstkcheck(2);
- xlsave(val);
- xlsave(result);
-
- result = (list) ? mklist(n, NIL) : newvector(n);
-
- for (i = 0, next = result; i < n; i++) {
- val = cvflonum((FLOTYPE) x[i]);
- setnextelement(&next, i, val);
- }
-
- /* restore the stack frame */
- xlpopn(2);
-
- return(result);
- }
- #endif DODO
- /***********************************************************************/
- /** Sequence Coercion Functions **/
- /***********************************************************************/
-
- LVAL coerce_to_list(x)
- LVAL x;
- {
- LVAL next, result;
- int n, i;
-
- /* save the result pointer */
- xlsave1(result);
-
- if (displacedarrayp(x))
- result = array_to_nested_list(x);
- else if (vectorp(x)) {
- n = getsize(x);
- result = mklist(n, NIL);
- for (i = 0, next = result; i < n; i++, next = cdr(next))
- rplaca(next, getelement(x, i));
- }
- else if (objectp(x))
- return(NIL); /* include standard coercion message later */
- else if (listp(x))
- result = x;
- else if (atom(x)) {
- result = consa(x);
- }
- else result = NIL;
-
- /* restore the stack frame */
- xlpop();
-
- return(result);
- }
-
- LVAL coerce_to_vector(x)
- LVAL x;
- {
- LVAL next, result;
- int n, i;
-
- /* save the result pointer */
- xlsave1(result);
-
- if (displacedarrayp(x)) result = arraydata(x);
- else if (vectorp(x)) result = x;
- else if (objectp(x))
- return(NIL); /* include standard coercion message later */
- else if (listp(x)) {
- n = llength(x);
- result = newvector(n);
- for (i = 0, next = x; i < n; i++, next = cdr(next))
- setelement(result, i, car(next));
- }
- else if (atom(x)) {
- result = newvector(1);
- setelement(result, 0, x);
- }
- else result = NIL;
-
- /* restore the previous stack frame */
- xlpop();
-
- return(result);
- }
-
- /*************************************************************************/
- /** Copying Functions **/
- /*************************************************************************/
-
- LVAL copylist(list)
- LVAL list;
- {
- LVAL result, nextl, nextr;
-
- if (! listp(list)) xlerror("not a list", list);
-
- /* protect the result pointer */
- xlsave1(result);
-
- result = mklist(llength(list), NIL);
- for (nextl = list, nextr = result; consp(nextl);
- nextl = cdr(nextl), nextr = cdr(nextr)) {
- rplaca(nextr, car(nextl));
- }
-
- /* restore the stack frame */
- xlpop();
-
- return(result);
- }
-
- LVAL copyvector(v)
- LVAL v;
- {
- LVAL result;
- int n, i;
-
- if (! vectorp(v)) xlerror("not a vector", v);
-
- /* protect the result pointer */
- xlsave1(result);
-
- n = getsize(v);
- result = newvector(n);
- for (i = 0; i < n; i++) {
- setelement(result, i, getelement(v, i));
- }
-
- /* restore the stack frame */
- xlpop();
-
- return(result);
- }
-
- /***************************************************************************/
- /** Statistical Functions (sort of) **/
- /***************************************************************************/
-
- LVAL splitlist(list, len)
- LVAL list;
- int len;
- {
- LVAL result, sublist, next_r, next_s, next;
- int numlists, n;
-
- if (len < 1) xlfail("invalid length for sublists");
-
- /* protect some pointers */
- xlsave1(result);
-
- n = llength(list);
- if ((n % len) != 0)
- xlfail("list not divisible by this length");
- else
- numlists = n / len;
-
- result = mklist(numlists, NIL);
- for (next = list, next_r = result; consp(next_r); next_r = cdr(next_r)) {
- sublist = mklist(len, NIL);
- rplaca(next_r, sublist);
- for (next_s = sublist; consp(next_s);
- next_s = cdr(next_s), next = cdr(next))
- rplaca(next_s, car(next));
- }
-
- /* restore the stack frame */
- xlpop();
-
- return(result);
- }
-
- /* replicates a list n times */
- LVAL lrepeat(arg, n)
- LVAL arg;
- int n;
- {
- LVAL data, nextd, nextr, result;
-
- /* protect some pointers */
- xlstkcheck(2);
- xlsave(data);
- xlsave(result);
-
- data = coerce_to_list(arg);
-
- /* make new data list */
- result = mklist(n * llength(data), NIL);
-
- /* insert values from data into list */
- for (nextr = result, nextd = data; consp(nextr);
- nextr = cdr(nextr), nextd = cdr(nextd)) {
- if (nextd == NIL) nextd = data; /* cycle through the data */
- rplaca(nextr, car(nextd));
- }
-
- /* restore the stack frame */
- xlpopn(2);
-
- return(result);
- }
-
- /* Flatten a nested list to depth rank */
- LVAL nested_list_to_list(list, rank)
- LVAL list;
- int rank;
- {
- LVAL result;
- int i;
-
- /* protect the result pointer */
- xlsave1(result);
-
- for (i = 1, result = list; i < rank; i++)
- result = concatenate(s_list, result);
-
- /* restore the previous stack frame */
- xlpop();
-
- return (result);
- }
-
- int xsboolkey(key, dflt)
- LVAL key;
- int dflt;
- {
- LVAL val;
- int result = dflt;
-
- if (xlgetkeyarg(key, &val)) result = ((val != NIL) ? TRUE : FALSE);
- return(result);
- }
-