home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
applications
/
xlispstat
/
src
/
src2.lzh
/
XLisp-Stat
/
basics.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-02
|
20KB
|
726 lines
/* basics - Basic functions for manipulating compound data */
/* 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"
#else
#include "xlfun.h"
#include "xlsfun.h"
#endif ANSI
#include "xlsvar.h"
#ifdef ANSI
int ordered_nneg_seq(LVAL),allfixargs(void),
translate_index(int,LVAL,LVAL,LVAL,LVAL,LVAL,LVAL);
void permute_indices(LVAL,LVAL,LVAL,int),indices_from_rowmajor(LVAL,int,LVAL),
setcons(LVAL,LVAL,LVAL);
#else
int ordered_nneg_seq(),allfixargs(),
translate_index();
void permute_indices(),indices_from_rowmajor(),setcons();
#endif ANSI
/**************************************************************************/
/** **/
/** Sequence Predicate **/
/** **/
/**************************************************************************/
/* internal sequencep */
/*sequencep(x) defined as a macro in xlsdef.h JKL
LVAL x;
{
return(listp(x) || simplevectorp(x));
}
*/
/* Built in SEQUENCEP */
LVAL xssequencep()
{
LVAL x;
x = xlgetarg();
xllastarg();
return((sequencep(x)) ? s_true : NIL);
}
/**************************************************************************/
/** **/
/** Copying Functions **/
/** **/
/**************************************************************************/
/* Built in COPY-VECTOR function */
LVAL xscopyvector()
{
LVAL v;
v = xlgavector();
xllastarg();
return(copyvector(v));
}
#define copyseq(x) ((vectorp(x)) ? copyvector(x) : copylist(x))
/* internal array copying function */
LVAL copyarray(array)
LVAL array;
{
LVAL dim, data, result;
if (simplevectorp(array)) result = copyvector(array);
else if (displacedarrayp(array)) {
/* protext some pointers */
xlstkcheck(3);
xlsave(result);
xlsave(dim);
xlsave(data);
dim = copyseq(displacedarraydim(array));
data = copyvector(arraydata(array));
result = makedisplacedarray(dim, data);
/* restore the stack frame */
xlpopn(3);
}
else xlerror("not an array", array);
return(result);
}
LVAL xscopyarray()
{
LVAL array;
array = xsgetarray();
xllastarg();
return(copyarray(array));
}
/**************************************************************************/
/** **/
/** Compound Data Decomposition Functions **/
/** **/
/**************************************************************************/
/* Built in SPLIT-LIST function */
LVAL xssplitlist()
{
LVAL data;
int n;
data = xlgalist();
n = getfixnum(xlgafixnum());
xllastarg();
return(splitlist(data, n));
}
/**************************************************************************/
/** **/
/** WHICH Function **/
/** **/
/**************************************************************************/
/* Built in WHICH function. Generates indices in the data sequence of */
/* a compound data item where argument elements are not nil. Should do */
/* something more reasonable for non sequence compound data. */
LVAL xswhich()
{
LVAL x, result, data, index, tail;
int i, n;
/* protect the result pointer */
xlstkcheck(3);
xlsave(result);
xlsave(index);
xlsave(data);
x = xlgetarg();
xllastarg();
if (compoundp(x)) {
data = compounddataseq(x);
n = compounddatalen(x);
for (i = 0; i < n; i++)
if (getnextelement(&x, i) != NIL) {
index = cvfixnum((FIXTYPE) i);
if (result == NIL) {
result = consa(index);
tail = result;
}
else {
rplacd(tail, consa(index));
tail = cdr(tail);
}
}
}
else xlbadtype(x);
/* restore the stack frame */
xlpopn(3);
return(result);
}
/**************************************************************************/
/** **/
/** List Construction Functions **/
/** **/
/**************************************************************************/
/* internal version of ISEQ function */
LVAL iseq(m, n)
int m, n;
{
int length, i;
LVAL result, next;
/* protect the result pointer */
xlsave1(result);
length = abs(n - m) + 1;
result = mklist(length, NIL);
for (next = result, i = m; consp(next); next = cdr(next),
(m <= n) ? i++ : i--)
rplaca(next, cvfixnum((FIXTYPE) i));
/* restore the stack frame */
xlpop();
return(result);
}
/* Built in ISEQ function. Generates a list of consecutive integers */
LVAL xsiseq()
{
int n, m;
m = getfixnum(xlgafixnum());
if (moreargs()) n = getfixnum(xlgafixnum());
else if (m > 0) {
n = m - 1;
m = 0;
}
else if (m < 0) {
m = m + 1;
n = 0;
}
else return(NIL);
xllastarg();
return(iseq(m, n));
}
/* Built in REPEAT function */
LVAL xsrepeat()
{
LVAL data, result;
int reps;
if (xlargc != 2) xlfail("wrong number of arguments");
else if (compoundp(xlargv[1])) {
xlsave1(result);
result = subr_map_elements(xsrepeat);
result = coerce_to_list(result);
result = nested_list_to_list(result, 2);
xlpop();
}
else {
data = xlgetarg();
reps = getfixnum(checknonnegint(xlgetarg()));
xllastarg();
result = lrepeat(data, reps);
}
return(result);
}
/**************************************************************************/
/** **/
/** Subset Selection and Mutation Functions **/
/** **/
/**************************************************************************/
/* is x an ordered list of nonnegative positive integers? */
LOCAL ordered_nneg_seq(x)
LVAL x;
{
LVAL elem;
int n, i, length;
length = (simplevectorp(x)) ? getsize(x) : 0;
if (sequencep(x)) {
for (n = 0, i = 0; consp(x) || i < length; i++) {
elem = checknonnegint(getnextelement(&x, i));
if (n > getfixnum(elem)) return(FALSE);
else n = getfixnum(elem);
}
return(TRUE);
}
else return(FALSE);
}
/* select or set the subsequence corresponding to the specified indices */
LVAL subsequence(x, indices, set_values, values)
LVAL x, indices, values;
int set_values;
{
int rlen, dlen, vlen, i, j;
LVAL data, result, nextx, nextr, index, elem;
/* Check the input data */
if (! sequencep(x)) xlerror("not a sequence", x);
if (set_values && ! sequencep(values))
xlerror(" bad value sequence", values);
/* protect some pointers */
xlstkcheck(2)
xlsave(result);
xlsave(data);
/* Find the data sizes */
data = (ordered_nneg_seq(indices)) ? x : coerce_to_vector(x);
dlen = (vectorp(data)) ? getsize(data) : llength(data);
rlen = (vectorp(indices)) ? getsize(indices) : llength(indices);
if (set_values) {
vlen = (vectorp(values)) ? getsize(values) : llength(values);
if (vlen != rlen && indices != s_true)
xlfail("value and index sequences do not match");
}
/* set up the result/value sequence */
if (set_values) result = values;
else result = (listp(x)) ? mklist(rlen, NIL) : newvector(rlen);
/* get or set the sequence elements */
if (indices == s_true) /* do all indices */
if (set_values)
for (i = 0; i < dlen; i++)
setnextelement(&x, i, getnextelement(&values, i));
else
result = x;
else if (sequencep(indices)) {
if (set_values) {
for (nextx = x, nextr = result, i = 0, j = 0; i < rlen; i++) {
index = getnextelement(&indices, i);
if (dlen <= getfixnum(index)) xlerror("index out of range", index);
elem = getnextelement(&result, i);
if (listp(x)) {
if (j > getfixnum(index)) {
j = 0;
nextx = x;
}
for (; j < getfixnum(index) && consp(nextx);
j++, nextx = cdr(nextx))
;
rplaca(nextx, elem);
}
else
setelement(x, getfixnum(index), elem);
}
}
else
for (nextx = data, nextr = result, i = 0, j = 0; i < rlen; i++) {
index = getnextelement(&indices, i);
if (dlen <= getfixnum(index)) xlerror("index out of range", index);
if (listp(data)) { /* indices must be ordered */
for (; j < getfixnum(index) && consp(nextx); j++, nextx = cdr(nextx))
;
elem = car(nextx);
}
else
elem = getelement(data, getfixnum(index));
setnextelement(&nextr, i, elem);
}
}
else xlerror("bad indices", indices);
/* restore the stack frame */
xlpopn(2);
return(result);
}
/* translate row major index in resulting submatrix to row major index in */
/* the original matrix */
old_rowmajor_index(index, indices, dim, olddim)
int index;
LVAL indices, dim, olddim;
{
int face, oldface, rank, i, oldindex;
rank = getsize(dim);
for (face = 1, oldface = 1, i = 0; i < rank; i++) {
face *= getfixnum(getelement(dim, i));
oldface *= getfixnum(getelement(olddim, i));
}
for (oldindex = 0, i = 0; i < rank; i++) {
face /= getfixnum(getelement(dim, i));
oldface /= getfixnum(getelement(olddim, i));
oldindex +=
oldface *
getfixnum(getelement(getelement(indices, i), index / face));
index = index % face;
}
return(oldindex);
}
/* extract or set subarray for the indices from a displaced array */
LVAL subarray(a, indexlist, set_values, values)
LVAL a, indexlist, values;
int set_values;
{
LVAL indices, index, dim, vdim, data, result_data, olddim, result;
int rank, n, i, j, k;
/* protect some pointers */
xlstkcheck(4);
xlsave(indices);
xlsave(dim);
xlsave(olddim);
xlsave(result);
if (! displacedarrayp(a)) xlerror("not a displaced array", a);
if (! listp(indexlist)) xlerror("bad index list", indices);
if (llength(indexlist) != arrayrank(a)) xlfail("wrong number of indices");
indices = coerce_to_vector(indexlist);
olddim = displacedarraydim(a);
olddim = coerce_to_vector(olddim);
/* compute the result dimension vector and fix up the indices */
rank = arrayrank(a);
dim = newvector(rank);
for (i = 0; i < rank; i++) {
index = getelement(indices, i);
n = getfixnum(getelement(olddim, i));
if (index == s_true) {
index = newvector(n);
setelement(indices, i, index);
for (j = 0; j < n; j++)
setelement(index, j, cvfixnum((FIXTYPE) j));
}
else {
index = coerce_to_vector(index);
k = getsize(index);
for (j = 0; j < k; j++)
if (n <= getfixnum(checknonnegint(getelement(index, j))))
xlerror("index out of bounds", getelement(index, j));
setelement(indices, i, index);
}
setelement(dim, i, cvfixnum((FIXTYPE) getsize(index)));
}
/* set up the result or check the values*/
if (set_values) {
if (! compoundp(values))
result = newarray(dim, s_ielement, values);
else {
if (! displacedarrayp(values) || rank != arrayrank(values))
xlerror("bad values array", values);
vdim = displacedarraydim(values);
for (i = 0; i < rank; i++)
if (getfixnum(getnextelement(&vdim, i))
!= getfixnum(getelement(dim, i)))
xlerror("bad value array dimensions", values);
result = values;
}
}
else
result = newarray(dim, NIL, NIL);
/* compute the result or set the values */
data = arraydata(a);
result_data = arraydata(result);
n = getsize(result_data);
for (i = 0; i < n; i++) {
k = old_rowmajor_index(i, indices, dim, olddim);
if (0 > k || k >= getsize(data)) xlfail("index out of range");
if (set_values)
setelement(data, k, getelement(result_data, i));
else
setelement(result_data, i, getelement(data, k));
}
/* restore the stack frame */
xlpopn(4);
return(result);
}
/* are all arguments beyond the first fixnums? */
LOCAL allfixargs()
{
int i;
for (i = 1; i < xlargc; i++)
if (! fixp(xlargv[i])) return(FALSE);
return(TRUE);
}
/* Built in SELECT function */
LVAL xsselect()
{
LVAL x, indices, result;
if (allfixargs()) {
if (displacedarrayp(peekarg(0))) result = xsaref();
else result = xselt();
}
else if (sequencep(peekarg(0))) {
x = xlgetarg();
indices = xlgetarg();
result = subsequence(x, indices, FALSE, NIL);
}
else if (displacedarrayp(peekarg(0))) {
xlsave1(indices);
x = xlgetarg();
indices = makearglist(xlargc, xlargv);
result = subarray(x, indices, FALSE, NIL);
xlpop();
}
else xlbadtype(xlgetarg());
return(result);
}
static void setcons(x, first, rest)
LVAL x, first, rest;
{
x->n_type = CONS;
rplaca(x, first);
rplacd(x, rest);
}
/* Built in SET-SELECT (SETF method for SELECT) */
/* This function uses node data to avoid creating garbage nodes. */
/* This use of nodes *should* be safe, since there *should* be */
/* no chance of a garbage collection during this operation. */
LVAL xssetselect()
{
LVAL x, indices, values, next;
struct node index_node, value_node;
LVAL i_list = &index_node, v_list = &value_node;
xlsave1(indices);
xlsave1(values);
x = xlgetarg();
indices = makearglist(xlargc, xlargv);
if (! consp(cdr(indices))) xltoofew();
else {
for (next = indices; consp(cdr(cdr(next))); next = cdr(next))
;
values = car(cdr(next));
rplacd(next, NIL);
}
if (sequencep(x)) {
if (! consp(indices)) xlerror("bad indices", indices);
indices = car(indices);
if (fixp(indices)) {
setcons(i_list, indices, NIL);
setcons(v_list, values, NIL);
subsequence(x, i_list, TRUE, v_list);
}
else
subsequence(x, indices, TRUE, values);
}
else if (displacedarrayp(x))
subarray(x, indices, TRUE, values);
else xlbadtype(x);
xlpopn(2);
return(values);
}
/**************************************************************************/
/** **/
/** Array Permutation Function **/
/** **/
/**************************************************************************/
/* permute x into y using perm; all should be vectors; If check is TRUE */
/* the routine will check to make sure no indices are reused, but x */
/* will be destroyed. */
static void permute_indices(x, y, perm, check)
LVAL x, y, perm;
int check;
{
LVAL index;
int rank, i, k;
rank = getsize(x);
for (i = 0; i < rank; i++) {
index = getelement(perm, i);
if (! fixp(index)) xlerror("bad permutation sequence", perm);
k = getfixnum(index);
if (k < 0 || k >= rank) xlerror("bad permutation sequence", perm);
setelement(y, i, getelement(x, k));
if (check)
setelement(x, k, NIL); /* to insure dimensions are not re-used */
}
}
/* compute indices in a from rowmajor index k, put in vector result */
/* The indices are stored in cons cells, which are treated locally */
/* fixnums. This SEEMS to be safe since it is entirely local, but */
/* it may be dangerous...... */
static void indices_from_rowmajor(a, k, result)
LVAL a, result;
int k;
{
LVAL next, dim;
int face, i, rank;
if (! displacedarrayp(a)) xlerror("not a displaced array", a);
if (0 > k || k >= getsize(arraydata(a))) xlfail("index out of range");
dim = displacedarraydim(a);
rank = arrayrank(a);
for (i = 0, face = 1, next = dim; i < rank; i++)
face *= getfixnum(getnextelement(&next, i));
for (i = 0, next = dim; i < rank; i++) {
face /= getfixnum(getnextelement(&next, i));
setfixnum(getelement(result, i),(FIXTYPE) k / face);
k = k % face;
}
}
/* Translate row major index in original array to row major index in new */
/* array. Use indices vectors and ilist for temporary storage. */
static translate_index(i, result, x, perm, indices, oldindices, ilist)
LVAL result, x, perm, indices, oldindices, ilist;
int i;
{
LVAL next;
int rank, k;
rank = arrayrank(x);
indices_from_rowmajor(x, i, oldindices);
permute_indices(oldindices, indices, perm, FALSE);
for (next = ilist, k = 0; k < rank && consp(next); k++, next = cdr(next))
rplaca(next, getelement(indices, k));
return(rowmajorindex(result, ilist, FALSE));
}
/* Built in PERMUTE-ARRAY function */
LVAL xspermutearray()
{
LVAL x, perm, result, data, result_data, dim, olddim, indices;
LVAL oldindices, ilist;
int rank, i, k, n;
/* protect some pointers */
xlstkcheck(7);
xlsave(result);
xlsave(dim);
xlsave(olddim);
xlsave(indices);
xlsave(oldindices);
xlsave(perm);
xlsave(ilist);
/* Get and ckeck the arguments */
x = xsgetdisplacedarray();
perm = xsgetsequence();
perm = coerce_to_vector(perm);
if (getsize(perm) != arrayrank(x)) xlerror("bad permutation sequence", perm);
xllastarg();
/* get old dimension vector */
olddim = coerce_to_vector(displacedarraydim(x));
rank = getsize(perm);
/* construct new dimension vector */
dim = newvector(rank);
olddim = copyvector(olddim); /* since permute_indices will destroy this */
permute_indices(olddim, dim, perm, TRUE);
/* make result array and the index vectors and lists */
result = newarray(dim, NIL, NIL);
indices = newvector(rank);
oldindices = newvector(rank);
for (i = 0; i < rank; i++)
setelement(oldindices, i, consa(NIL));
ilist = mklist(rank, NIL);
/* fill in the result */
data = arraydata(x);
result_data = arraydata(result);
if (getsize(data) != getsize(result_data)) xlfail("bad data");
n = getsize(data);
for (i = 0; i < n; i++) {
k = translate_index(i, result, x, perm, indices, oldindices, ilist);
setelement(result_data, k, getelement(data, i));
}
/* restore stack */
xlpopn(7);
return(result);
}
#ifdef SAVERESTORE
/* xrestore - restore a saved memory image */
LVAL xsrestore()
{
extern jmp_buf top_level;
unsigned char *name;
LVAL hlist;
/* get the file name, verbose flag and print flag */
name = getstring(xlgetfname());
xllastarg();
/* dispose of all hardware objects */
if (consp(getvalue(s_hardware_objects))) {
xlsave1(hlist);
hlist = copylist(getvalue(s_hardware_objects));
for (; consp(hlist); hlist = cdr(hlist))
send_message(car(cdr(cdr(car(hlist)))), sk_dispose);
xlpop();
}
/* restore the saved memory image */
if (!xlirestore(name))
return (NIL);
/* restore hardware items (this may be dangerous) */
if (symbolp(s_listener) && objectp(getvalue(s_listener)))
send_message(getvalue(s_listener), sk_allocate);
if (consp(getvalue(s_hardware_objects))) {
xlsave1(hlist);
hlist = copylist(getvalue(s_hardware_objects));
setvalue(s_hardware_objects, NIL);
for (; consp(hlist); hlist = cdr(hlist))
send_message(car(cdr(cdr(car(hlist)))), sk_allocate);
xlpop();
}
/* return directly to the top level */
stdputstr("[ returning to the top level ]\n");
longjmp(top_level,1);
}
#endif