diff options
author | Bryan Newbold <bnewbold@robocracy.org> | 2017-02-20 00:05:23 -0800 |
---|---|---|
committer | Bryan Newbold <bnewbold@robocracy.org> | 2017-02-20 00:05:23 -0800 |
commit | 5ca6e8e6a4e5c022a6fb5d28f30219c22c99eda8 (patch) | |
tree | 9b744b9dbf39e716e56daa620e2f3041968caf19 /unif.c | |
download | scm-5ca6e8e6a4e5c022a6fb5d28f30219c22c99eda8.tar.gz scm-5ca6e8e6a4e5c022a6fb5d28f30219c22c99eda8.zip |
Import Upstream version 4e6upstream/4e6
Diffstat (limited to 'unif.c')
-rw-r--r-- | unif.c | 2000 |
1 files changed, 2000 insertions, 0 deletions
@@ -0,0 +1,2000 @@ +/* Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * As a special exception, the Free Software Foundation gives permission + * for additional uses of the text contained in its release of GUILE. + * + * The exception is that, if you link the GUILE library with other files + * to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the GUILE library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the + * Free Software Foundation under the name GUILE. If you copy + * code from other Free Software Foundation releases into a copy of + * GUILE, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for GUILE, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + */ + +/* "unif.c" Uniform vectors and arrays + Authors: Aubrey Jaffer & Radey Shouman. + +The set of uniform vector types is: + Vector of: Called: +char string +boolean bvect +signed int ivect +unsigned int uvect +float fvect +double dvect +complex double cvect +*/ + +#include "scm.h" + +#ifndef STDC_HEADERS + int ungetc P((int c, FILE *stream)); + sizet fwrite (); +#endif + +long tc16_array = 0; + +char s_resizuve[] = "vector-set-length!"; +SCM resizuve(vect, len) + SCM vect, len; +{ + long l = INUM(len); + sizet siz, sz; + ASRTGO(NIMP(vect), badarg1); + switch TYP7(vect) { + default: badarg1: wta(vect, (char *)ARG1, s_resizuve); + case tc7_string: + ASRTGO(vect != nullstr, badarg1); + sz = sizeof(char); + l++; + break; + case tc7_vector: + ASRTGO(vect != nullvect, badarg1); + sz = sizeof(SCM); + break; +#ifdef ARRAYS + case tc7_bvect: + l = (l+LONG_BIT-1)/LONG_BIT; + case tc7_uvect: + case tc7_ivect: + sz = sizeof(long); + break; +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: + sz = sizeof(float); + break; +# endif + case tc7_dvect: + sz = sizeof(double); + break; + case tc7_cvect: + sz = 2*sizeof(double); + break; +# endif +#endif + } + ASSERT(INUMP(len), len, ARG2, s_resizuve); + if (!l) l = 1L; + siz = l * sz; + if (siz != l * sz) wta(MAKINUM(l * sz), (char *) NALLOC, s_resizuve); + DEFER_INTS; + SETCHARS(vect, (char *)must_realloc((char *)CHARS(vect), + (long)LENGTH(vect)*sz, + (long)siz, s_resizuve)); + if VECTORP(vect) { + sz = LENGTH(vect); + while(l > sz) VELTS(vect)[--l] = UNSPECIFIED; + } + else if STRINGP(vect) CHARS(vect)[l-1] = 0; + SETLENGTH(vect, INUM(len), TYP7(vect)); + ALLOW_INTS; + return vect; +} + +#ifdef ARRAYS + +# ifdef FLOATS +# ifdef SINGLES +SCM makflo (x) + float x; +{ + SCM z; + if (x==0.0) return flo0; + NEWCELL(z); + DEFER_INTS; + CAR(z) = tc_flo; + FLO(z) = x; + ALLOW_INTS; + return z; +} +# endif +# endif + +SCM make_uve(k, prot) + long k; + SCM prot; +{ + SCM v; + long i, type; + if (BOOL_T==prot) { + i = sizeof(long)*((k+LONG_BIT-1)/LONG_BIT); + type = tc7_bvect; + } + else if ICHRP(prot) { + i = sizeof(char)*k; + type = tc7_string; + } + else if INUMP(prot) { + i = sizeof(long)*k; + if (INUM(prot)>0) type = tc7_uvect; + else type = tc7_ivect; + } + else +# ifdef FLOATS + if (IMP(prot) || !INEXP(prot)) +# endif + /* Huge non-unif vectors are NOT supported. */ + return make_vector(MAKINUM(k), UNDEFINED); /* no special vector */ +# ifdef FLOATS +# ifdef SINGLES + else if SINGP(prot) { +# ifdef CDR_DOUBLES + double x = FLO(prot); + float fx = x; + if (x != fx) { + i = sizeof(double)*k; + type = tc7_dvect; + } + else +# endif + { + i = sizeof(float)*k; + type = tc7_fvect; + } + } +# endif + else if (CPLXP(prot)) { + i = 2*sizeof(double)*k; + type = tc7_cvect; + } + else { + i = sizeof(double)*k; + type = tc7_dvect; + } +# endif + + NEWCELL(v); + DEFER_INTS; + SETCHARS(v, must_malloc((i ? i : 1L), s_vector)); + SETLENGTH(v, (k<LENGTH_MAX ? k : LENGTH_MAX), type); + ALLOW_INTS; + return v; +} + +static char s_uve_len[] = "uniform-vector-length"; +SCM uve_len(v) + SCM v; +{ + ASRTGO(NIMP(v), badarg1); + switch TYP7(v) { + default: badarg1: wta(v, (char *)ARG1, s_uve_len); + case tc7_bvect: + case tc7_string: + case tc7_uvect: + case tc7_ivect: + case tc7_fvect: + case tc7_dvect: + case tc7_cvect: + case tc7_vector: + return MAKINUM(LENGTH(v)); + } +} + +SCM arrayp(v, prot) + SCM v, prot; +{ + int nprot = UNBNDP(prot), enclosed = 0; + if IMP(v) return BOOL_F; + loop: + switch TYP7(v) { + case tc7_smob: if (!ARRAYP(v)) return BOOL_F; + if (nprot) return BOOL_T; + if (enclosed++) return BOOL_F; + v = ARRAY_V(v); + goto loop; + case tc7_bvect: return nprot || BOOL_T==prot ? BOOL_T : BOOL_F; + case tc7_string: return nprot || ICHRP(prot) ? BOOL_T : BOOL_F; + case tc7_uvect: + return nprot || (INUMP(prot) && INUM(prot)>0) ? BOOL_T : BOOL_F; + case tc7_ivect: + return nprot || (INUMP(prot) && INUM(prot)<=0) ? BOOL_T : BOOL_F; +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: return nprot || (NIMP(prot) && SINGP(prot)) ? BOOL_T : BOOL_F; +# endif + case tc7_dvect: return nprot || (NIMP(prot) && REALP(prot)) ? BOOL_T : BOOL_F; + case tc7_cvect: return nprot || (NIMP(prot) && CPLXP(prot)) ? BOOL_T : BOOL_F; +# endif + case tc7_vector: return nprot || NULLP(prot) ? BOOL_T : BOOL_F; + default:; + } + return BOOL_F; +} +SCM array_rank(ra) + SCM ra; +{ + if IMP(ra) return INUM0; + switch (TYP7(ra)) { + default: return INUM0; + case tc7_string: case tc7_vector: case tc7_bvect: + case tc7_uvect: case tc7_ivect: case tc7_fvect: + case tc7_cvect: case tc7_dvect: + return MAKINUM(1L); + case tc7_smob: + if ARRAYP(ra) return MAKINUM(ARRAY_NDIM(ra)); + return INUM0; + } +} +static char s_array_dims[] = "array-dimensions"; +SCM array_dims(ra) + SCM ra; +{ + SCM res=EOL; + sizet k; + array_dim *s; + if IMP(ra) return BOOL_F; + switch (TYP7(ra)) { + default: return BOOL_F; + case tc7_string: case tc7_vector: case tc7_bvect: + case tc7_uvect: case tc7_ivect: case tc7_fvect: + case tc7_cvect: case tc7_dvect: + return cons(MAKINUM(LENGTH(ra)), EOL); + case tc7_smob: + if (!ARRAYP(ra)) return BOOL_F; + k = ARRAY_NDIM(ra); + s = ARRAY_DIMS(ra); + while (k--) + res = cons(s[k].lbnd ? cons2(MAKINUM(s[k].lbnd), MAKINUM(s[k].ubnd), EOL) : + MAKINUM(1+(s[k].ubnd)) + , res); + return res; + } +} +static char s_bad_ind[] = "Bad array index"; +long aind(ra, args, what) + SCM ra, args; + char *what; +{ + SCM ind; + register long j; + register sizet pos = ARRAY_BASE(ra); + register sizet k = ARRAY_NDIM(ra); + array_dim *s = ARRAY_DIMS(ra); + if INUMP(args) { + ASSERT(1==k, UNDEFINED, WNA, what); + j = INUM(args); + ASSERT(j >= (s->lbnd) && j <= (s->ubnd), args, OUTOFRANGE, what); + return pos + (j - s->lbnd)*(s->inc); + } + ASSERT((IMP(args) ? NULLP(args) : CONSP(args)), args, s_bad_ind, what); + while (k && NIMP(args)) { + ind = CAR(args); + args = CDR(args); + ASSERT(INUMP(ind), ind, s_bad_ind, what); + j = INUM(ind); + ASSERT(j >= (s->lbnd) && j <= (s->ubnd), ind, OUTOFRANGE, what); + pos += (j - s->lbnd)*(s->inc); + k--; + s++; + } + ASSERT(0==k && NULLP(args), UNDEFINED, WNA, what); + return pos; +} + +SCM make_ra(ndim) + int ndim; +{ + SCM ra; + NEWCELL(ra); + DEFER_INTS; + SETCDR(ra, must_malloc((long)(sizeof(array)+ndim*sizeof(array_dim)), + "array")); + CAR(ra) = ((long)ndim << 17) + tc16_array; + ARRAY_V(ra) = nullvect; + ALLOW_INTS; + return ra; +} + +static char s_bad_spec[] = "Bad array dimension"; +/* Increments will still need to be set. */ +SCM shap2ra(args, what) + SCM args; + char *what; +{ + array_dim *s; + SCM ra, spec, sp; + int ndim = ilength(args); + ASSERT(0 <= ndim, args, s_bad_spec, what); + ra = make_ra(ndim); + ARRAY_BASE(ra) = 0; + s = ARRAY_DIMS(ra); + for (; NIMP(args); s++, args = CDR(args)) { + spec = CAR(args); + if IMP(spec) { + ASSERT(INUMP(spec)&&INUM(spec)>=0, spec, s_bad_spec, what); + s->lbnd = 0; + s->ubnd = INUM(spec) - 1; + s->inc = 1; + } + else { + ASSERT(CONSP(spec) && INUMP(CAR(spec)), spec, s_bad_spec, what); + s->lbnd = INUM(CAR(spec)); + sp = CDR(spec); + ASSERT(INUMP(CAR(sp)) && NULLP(CDR(sp)), + spec, s_bad_spec, what); + s->ubnd = INUM(CAR(sp)); + s->inc = 1; + } + } + return ra; +} + +static char s_uve_fill[] = "uniform-vector-fill!"; +int rafill(ra, fill, ignore) + SCM ra, fill, ignore; +{ + sizet i, n; + long inc = 1; + sizet base = 0; + if ARRAYP(ra) { + n = ARRAY_DIMS(ra)->ubnd - ARRAY_DIMS(ra)->lbnd + 1; + inc = ARRAY_DIMS(ra)->inc; + base = ARRAY_BASE(ra); + ra = ARRAY_V(ra); + } + else + n = LENGTH(ra); + switch TYP7(ra) { + badarg2: wta(fill, (char *)ARG2, s_uve_fill); + default: ASSERT(NFALSEP(arrayp(ra, UNDEFINED)), ra, ARG1, s_uve_fill); + for (i = base; n--; i += inc) + aset(ra, fill, MAKINUM(i)); + break; + case tc7_vector: { + SCM *ve = VELTS(ra); + for (i = base; n--; i += inc) + ve[i] = fill; + break; + } + case tc7_string: { + char *ve = CHARS(ra); + SCM f = ICHR(fill); + ASRTGO(ICHRP(fill), badarg2); + for (i = base; n--; i += inc) + ve[i] = f; + break; + } + case tc7_bvect: { + long *ve = (long *)VELTS(ra); + if (1==inc && (n >= LONG_BIT || n==LENGTH(ra))) { + i = base/LONG_BIT; + if (BOOL_F==fill) { + if (base % LONG_BIT) /* leading partial word */ + ve[i++] &= ~(~0L << (base % LONG_BIT)); + for (; i < (base + n)/LONG_BIT; i++) + ve[i] = 0L; + if ((base + n) % LONG_BIT) /* trailing partial word */ + ve[i] &= (~0L << ((base + n) % LONG_BIT)); + } + else if (BOOL_T==fill) { + if (base % LONG_BIT) + ve[i++] |= ~0L << (base % LONG_BIT); + for (; i < (base + n)/LONG_BIT; i++) + ve[i] = ~0L; + if ((base + n) % LONG_BIT) + ve[i] |= ~(~0L << ((base + n) % LONG_BIT)); + } + else goto badarg2; + } + else { + if (BOOL_F==fill) + for (i = base; n--; i += inc) + ve[i/LONG_BIT] &= ~(1L<<(i%LONG_BIT)); + else if (BOOL_T==fill) + for (i = base; n--; i += inc) + ve[i/LONG_BIT] |= (1L<<(i%LONG_BIT)); + else goto badarg2; + } + break; + } + case tc7_uvect: + case tc7_ivect: + { + long *ve = VELTS(ra); + long f = (tc7_uvect==TYP7(ra) ? + num2ulong(fill, (char *)ARG2, s_uve_fill) : + num2long(fill, (char *)ARG2, s_uve_fill)); + for (i = base; n--; i += inc) + ve[i] = f; + break; + } +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: { + float *ve = (float *)VELTS(ra); + float f = num2dbl(fill, (char *)ARG2, s_uve_fill); + for (i = base; n--; i += inc) + ve[i] = f; + break; + } +# endif /* SINGLES */ + case tc7_dvect: { + double *ve = (double *)VELTS(ra); + double f = num2dbl(fill, (char *)ARG2, s_uve_fill); + for (i = base; n--; i += inc) + ve[i] = f; + break; + } + case tc7_cvect: { + double fr, fi=0.0; + double (*ve)[2] = (double (*)[2])VELTS(ra); + if (NIMP(fill) && CPLXP(fill)) { + fr = REAL(fill); + fi = IMAG(fill); + } + else + fr = num2dbl(fill, (char *)ARG2, s_uve_fill); + for (i = base; n--; i += inc) { + ve[i][0] = fr; + ve[i][1] = fi; + } + break; + } +# endif /* FLOATS */ + } + return 1; +} +SCM uve_fill(uve, fill) + SCM uve, fill; +{ + + ASSERT(NIMP(uve) && (!ARRAYP(uve) || 1==ARRAY_NDIM(uve)), + uve, ARG1, s_uve_fill); + rafill(uve, fill, EOL); + return UNSPECIFIED; +} + +static char s_dims2ura[] = "dimensions->uniform-array"; +SCM dims2ura(dims, prot, fill) + SCM dims, prot, fill; +{ + sizet k, vlen = 1; + long rlen = 1; + array_dim *s; + SCM ra; + if INUMP(dims) + if (INUM(dims) < LENGTH_MAX) { + ra = make_uve(INUM(dims), prot); + if NNULLP(fill) + rafill(ra, CAR(fill), EOL); + return ra; + } + else + dims = cons(dims, EOL); + ASSERT(NULLP(dims) || (NIMP(dims) && CONSP(dims)), dims, ARG1, s_dims2ura); + ra = shap2ra(dims, s_dims2ura); + CAR(ra) |= ARRAY_CONTIGUOUS; + s = ARRAY_DIMS(ra); + k = ARRAY_NDIM(ra); + while (k--) { + s[k].inc = (rlen > 0 ? rlen : 0); + rlen = (s[k].ubnd - s[k].lbnd + 1)*s[k].inc; + vlen *= (s[k].ubnd - s[k].lbnd + 1); + } + if (rlen < LENGTH_MAX) + ARRAY_V(ra) = make_uve((rlen > 0 ? rlen : 0L), prot); + else { + sizet bit; + switch TYP7(make_uve(0L, prot)) { + default: bit = LONG_BIT; break; + case tc7_vector: wta(dims, (char *)OUTOFRANGE, s_dims2ura); + case tc7_bvect: bit = 1; break; + case tc7_string: bit = CHAR_BIT; break; + case tc7_fvect: bit = sizeof(float)*CHAR_BIT/sizeof(char); break; + case tc7_dvect: bit = sizeof(double)*CHAR_BIT/sizeof(char); break; + case tc7_cvect: bit = 2*sizeof(double)*CHAR_BIT/sizeof(char); break; + } + ARRAY_BASE(ra) = (LONG_BIT + bit - 1)/bit; + rlen += ARRAY_BASE(ra); + ARRAY_V(ra) = make_uve(rlen, prot); + *((long *)VELTS(ARRAY_V(ra))) = rlen; + } + if NNULLP(fill) { + ASSERT(1==ilength(fill), UNDEFINED, WNA, s_dims2ura); + rafill(ARRAY_V(ra), CAR(fill), EOL); + } + if (1==ARRAY_NDIM(ra) && 0==ARRAY_BASE(ra)) + if (s->ubnd < s->lbnd || (0==s->lbnd && 1==s->inc)) return ARRAY_V(ra); + return ra; +} + +void ra_set_contp(ra) + SCM ra; +{ + sizet k = ARRAY_NDIM(ra); + long inc; + if (k) inc = ARRAY_DIMS(ra)[k-1].inc; + while (k--) { + if (inc != ARRAY_DIMS(ra)[k].inc) { + CAR(ra) &= ~ARRAY_CONTIGUOUS; + return; + } + inc *= (ARRAY_DIMS(ra)[k].ubnd - ARRAY_DIMS(ra)[k].lbnd + 1); + } + CAR(ra) |= ARRAY_CONTIGUOUS; +} +char s_make_sh_array[] = "make-shared-array"; +SCM make_sh_array(oldra, mapfunc, dims) + SCM oldra; + SCM mapfunc; + SCM dims; +{ + SCM ra; + SCM inds, indptr; + SCM imap; + sizet i, k; + long old_min, new_min, old_max, new_max; + array_dim *s; + ASSERT(BOOL_T==procedurep(mapfunc), mapfunc, ARG2, s_make_sh_array); + ASSERT(NIMP(oldra) && arrayp(oldra, UNDEFINED), oldra, ARG1, s_make_sh_array); + ra = shap2ra(dims, s_make_sh_array); + if (ARRAYP(oldra)) { + ARRAY_V(ra) = ARRAY_V(oldra); + old_min = old_max = ARRAY_BASE(oldra); + s=ARRAY_DIMS(oldra); + k = ARRAY_NDIM(oldra); + while (k--) { + if (s[k].inc > 0) + old_max += (s[k].ubnd - s[k].lbnd)*s[k].inc; + else + old_min += (s[k].ubnd - s[k].lbnd)*s[k].inc; + } + } + else { + ARRAY_V(ra) = oldra; + old_min = 0; + old_max = (long)LENGTH(oldra) - 1; + } + inds = EOL; + s = ARRAY_DIMS(ra); + for (k = 0; k < ARRAY_NDIM(ra); k++) { + inds = cons(MAKINUM(s[k].lbnd), inds); + if (s[k].ubnd < s[k].lbnd) { + if (1==ARRAY_NDIM(ra)) + ra = make_uve(0L, array_prot(ra)); + else + ARRAY_V(ra) = make_uve(0L, array_prot(ra)); + return ra; + } + } + imap = apply(mapfunc, reverse(inds), EOL); + if ARRAYP(oldra) + i = (sizet)aind(oldra, imap, s_make_sh_array); + else { + if NINUMP(imap) { + ASSERT(1==ilength(imap) && INUMP(CAR(imap)), + imap, s_bad_ind, s_make_sh_array); + imap = CAR(imap); + } + i = INUM(imap); + } + ARRAY_BASE(ra) = new_min = new_max = i; + indptr = inds; + k = ARRAY_NDIM(ra); + while (k--) { + if (s[k].ubnd > s[k].lbnd) { + CAR(indptr) = MAKINUM(INUM(CAR(indptr))+1); + imap = apply(mapfunc, reverse(inds), EOL); + if ARRAYP(oldra) + s[k].inc = aind(oldra, imap, s_make_sh_array) - i; + else { + if NINUMP(imap) { + ASSERT(1==ilength(imap) && INUMP(CAR(imap)), + imap, s_bad_ind, s_make_sh_array); + imap = CAR(imap); + } + s[k].inc = (long)INUM(imap) - i; + } + i += s[k].inc; + if (s[k].inc > 0) + new_max += (s[k].ubnd - s[k].lbnd)*s[k].inc; + else + new_min += (s[k].ubnd - s[k].lbnd)*s[k].inc; + } + else + s[k].inc = new_max - new_min + 1; /* contiguous by default */ + indptr = CDR(indptr); + } + ASSERT(old_min <= new_min && old_max >= new_max, UNDEFINED, + "mapping out of range", s_make_sh_array); + if (1==ARRAY_NDIM(ra) && 0==ARRAY_BASE(ra)) { + if (1==s->inc && 0==s->lbnd + && LENGTH(ARRAY_V(ra))==1+s->ubnd) return ARRAY_V(ra); + if (s->ubnd < s->lbnd) return make_uve(0L, array_prot(ra)); + } + ra_set_contp(ra); + return ra; +} + +/* args are RA . DIMS */ +static char s_trans_array[] = "transpose-array"; +SCM trans_array(args) + SCM args; +{ + SCM ra, res, vargs, *ve = &vargs; + array_dim *s, *r; + int ndim, i, k; + ASSERT(NIMP(args), UNDEFINED, WNA, s_trans_array); + ra = CAR(args); + args = CDR(args); + switch TYP7(ra) { + default: badarg: wta(ra, (char *)ARG1, s_trans_array); + case tc7_bvect: case tc7_string: case tc7_uvect: case tc7_ivect: + case tc7_fvect: case tc7_dvect: case tc7_cvect: case tc7_vector: + ASSERT(NIMP(args) && NULLP(CDR(args)), UNDEFINED, WNA, s_trans_array); + ASSERT(INUM0==CAR(args), CAR(args), ARG1, s_trans_array); + return ra; + case tc7_smob: ASRTGO(ARRAYP(ra), badarg); + vargs = vector(args); + ASSERT(LENGTH(vargs)==ARRAY_NDIM(ra), UNDEFINED, WNA, s_trans_array); + ve = VELTS(vargs); + ndim = 0; + for (k = 0; k < ARRAY_NDIM(ra); k++) { + i = INUM(ve[k]); + ASSERT(INUMP(ve[k]) && i >=0 && i < ARRAY_NDIM(ra), + ve[k], ARG2, s_trans_array); + if (ndim < i) ndim = i; + } + ndim++; + res = make_ra(ndim); + ARRAY_V(res) = ARRAY_V(ra); + ARRAY_BASE(res) = ARRAY_BASE(ra); + for (k = ndim; k--;) { + ARRAY_DIMS(res)[k].lbnd = 0; + ARRAY_DIMS(res)[k].ubnd = -1; + } + for (k = ARRAY_NDIM(ra); k--;) { + i = INUM(ve[k]); + s = &(ARRAY_DIMS(ra)[k]); + r = &(ARRAY_DIMS(res)[i]); + if (r->ubnd < r->lbnd) { + r->lbnd = s->lbnd; + r->ubnd = s->ubnd; + r->inc = s->inc; + ndim--; + } + else { + if (r->ubnd > s->ubnd) + r->ubnd = s->ubnd; + if (r->lbnd < s->lbnd) { + ARRAY_BASE(res) += (s->lbnd - r->lbnd)*r->inc; + r->lbnd = s->lbnd; + } + r->inc += s->inc; + } + } + ASSERT(ndim <= 0, args, "bad argument list", s_trans_array); + ra_set_contp(res); + return res; + } +} + +/* args are RA . AXES */ +static char s_encl_array[] = "enclose-array"; +SCM encl_array(axes) + SCM axes; +{ + SCM axv, ra, res, ra_inr; + array_dim vdim, *s = &vdim; + int ndim, j, k, ninr, noutr; + ASSERT(NIMP(axes), UNDEFINED, WNA, s_encl_array); + ra = CAR(axes); + axes = CDR(axes); + if NULLP(axes) + axes = cons((ARRAYP(ra) ? MAKINUM(ARRAY_NDIM(ra) - 1) : INUM0), EOL); + ninr = ilength(axes); + ra_inr = make_ra(ninr); + ASRTGO(NIMP(ra), badarg1); + switch TYP7(ra) { + default: badarg1: wta(ra, (char *)ARG1, s_encl_array); + case tc7_string: case tc7_bvect: case tc7_uvect: case tc7_ivect: + case tc7_fvect: case tc7_dvect: case tc7_cvect: case tc7_vector: + s->lbnd = 0; + s->ubnd = LENGTH(ra) - 1; + s->inc = 1; + ARRAY_V(ra_inr) = ra; + ARRAY_BASE(ra_inr) = 0; + ndim = 1; + break; + case tc7_smob: ASRTGO(ARRAYP(ra), badarg1); + s = ARRAY_DIMS(ra); + ARRAY_V(ra_inr) = ARRAY_V(ra); + ARRAY_BASE(ra_inr) = ARRAY_BASE(ra); + ndim = ARRAY_NDIM(ra); + break; + } + noutr = ndim - ninr; + axv = make_string(MAKINUM(ndim), MAKICHR(0)); + ASSERT(0 <= noutr && 0 <= ninr, UNDEFINED, WNA, s_encl_array); + res = make_ra(noutr); + ARRAY_BASE(res) = ARRAY_BASE(ra_inr); + ARRAY_V(res) = ra_inr; + for (k = 0; k < ninr; k++, axes = CDR(axes)) { + j = INUM(CAR(axes)); + ASSERT(INUMP(CAR(axes)) && j<ndim, CAR(axes), "bad axis", s_encl_array); + ARRAY_DIMS(ra_inr)[k].lbnd = s[j].lbnd; + ARRAY_DIMS(ra_inr)[k].ubnd = s[j].ubnd; + ARRAY_DIMS(ra_inr)[k].inc = s[j].inc; + CHARS(axv)[j] = 1; + } + for (j = 0, k = 0; k < noutr; k++, j++) { + while (CHARS(axv)[j]) j++; + ARRAY_DIMS(res)[k].lbnd = s[j].lbnd; + ARRAY_DIMS(res)[k].ubnd = s[j].ubnd; + ARRAY_DIMS(res)[k].inc = s[j].inc; + } + ra_set_contp(ra_inr); + ra_set_contp(res); + return res; +} + +static char s_array_inbp[] = "array-in-bounds?"; +SCM array_inbp(args) + SCM args; +{ + SCM v, ind = EOL; + register long j; + ASRTGO(NIMP(args), wna); + v = CAR(args); + args = CDR(args); + if IMP(v) goto scalar; + switch TYP7(v) { + default: + scalar: if NULLP(args) return BOOL_T; + badarg1: wta(v, (char *)ARG1, s_array_inbp); + wna: wta(UNDEFINED, (char *)WNA, s_array_inbp); + case tc7_smob: + if (ARRAYP(v)) { + SCM ret = BOOL_T; + register sizet k = ARRAY_NDIM(v); + array_dim *s = ARRAY_DIMS(v); + while (k && NIMP(args)) { + ind = CAR(args); + args = CDR(args); + ASSERT(INUMP(ind), ind, s_bad_ind, s_array_inbp); + j = INUM(ind); + if (j < (s->lbnd) || j > (s->ubnd)) ret = BOOL_F; + k--; + s++; + } + ASRTGO(0==k && NULLP(args), wna); + return ret; + } + else goto scalar; + case tc7_bvect: case tc7_string: case tc7_uvect: case tc7_ivect: + case tc7_fvect: case tc7_dvect: case tc7_cvect: case tc7_vector: + ASRTGO(NIMP(args) && NULLP(CDR(args)), wna); + ind = CAR(args); + ASSERT(INUMP(ind), ind, s_bad_ind, s_array_inbp); + j = INUM(ind); + return j >= 0 && j < LENGTH(v) ? BOOL_T : BOOL_F; + } +} +static char s_aref[] = "array-ref"; +SCM aref(v, args) + SCM v, args; +{ + long pos; + if IMP(v) { + ASRTGO(NULLP(args), badarg); + return v; + } + else if ARRAYP(v) { + pos = aind(v, args, s_aref); + v = ARRAY_V(v); + } + else { + if NIMP(args) { + ASSERT(CONSP(args) && INUMP(CAR(args)), args, ARG2, s_aref); + pos = INUM(CAR(args)); + ASRTGO(NULLP(CDR(args)), wna); + } + else { + ASSERT(INUMP(args), args, ARG2, s_aref); + pos = INUM(args); + } + ASRTGO(pos >= 0 && pos < LENGTH(v), outrng); + } + switch TYP7(v) { + default: if NULLP(args) return v; + badarg: wta(v, (char *)ARG1, s_aref); + outrng: wta(MAKINUM(pos), (char *)OUTOFRANGE, s_aref); + wna: wta(UNDEFINED, (char *)WNA, s_aref); + case tc7_smob: { /* enclosed */ + int k = ARRAY_NDIM(v); + SCM res = make_ra(k); + if (!ARRAYP(v)) { + ASRTGO(NULLP(args),badarg); + return v; + } + ARRAY_V(res) = ARRAY_V(v); + ARRAY_BASE(res) = pos; + while (k--) { + ARRAY_DIMS(res)[k].lbnd = ARRAY_DIMS(v)[k].lbnd; + ARRAY_DIMS(res)[k].ubnd = ARRAY_DIMS(v)[k].ubnd; + ARRAY_DIMS(res)[k].inc = ARRAY_DIMS(v)[k].inc; + } + return res; + } + case tc7_bvect: + if (VELTS(v)[pos/LONG_BIT]&(1L<<(pos%LONG_BIT))) + return BOOL_T; + else return BOOL_F; + case tc7_string: + return MAKICHR(CHARS(v)[pos]); +# ifdef INUMS_ONLY + case tc7_uvect: + case tc7_ivect: + return MAKINUM(VELTS(v)[pos]); +# else + case tc7_uvect: + return ulong2num(VELTS(v)[pos]); + case tc7_ivect: + return long2num(VELTS(v)[pos]); +# endif +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: + return makflo(((float *)CDR(v))[pos]); +# endif + case tc7_dvect: + return makdbl(((double *)CDR(v))[pos], 0.0); + case tc7_cvect: + return makdbl(((double *)CDR(v))[2*pos], + ((double *)CDR(v))[2*pos+1]); +# endif + case tc7_vector: + return VELTS(v)[pos]; + } +} +SCM scm_array_ref(args) + SCM args; +{ + ASSERT(NIMP(args), UNDEFINED, WNA, s_aref); + return aref(CAR(args), CDR(args)); +} + +/* Internal version of aref for uves that does no error checking and + tries to recycle conses. (Make *sure* you want them recycled.) */ +SCM cvref(v, pos, last) + SCM v; + sizet pos; + SCM last; +{ + switch TYP7(v) { + default: wta(v, (char *)ARG1, "PROGRAMMING ERROR: cvref"); + case tc7_bvect: + if (VELTS(v)[pos/LONG_BIT]&(1L<<(pos%LONG_BIT))) + return BOOL_T; + else return BOOL_F; + case tc7_string: + return MAKICHR(CHARS(v)[pos]); +# ifdef INUMS_ONLY + case tc7_uvect: + case tc7_ivect: + return MAKINUM(VELTS(v)[pos]); +# else + case tc7_uvect: + return ulong2num(VELTS(v)[pos]); + case tc7_ivect: + return long2num(VELTS(v)[pos]); +# endif +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: + if (NIMP(last) && (last != flo0) && (tc_flo==CAR(last))) { + FLO(last) = ((float *)CDR(v))[pos]; + return last; + } + return makflo(((float *)CDR(v))[pos]); +# endif + case tc7_cvect: + if (0.0!=((double *)CDR(v))[2*pos+1]) { + if (NIMP(last) && tc_dblc==CAR(last)) { + REAL(last) = ((double *)CDR(v))[2*pos]; + IMAG(last) = ((double *)CDR(v))[2*pos+1]; + return last; + } + return makdbl(((double *)CDR(v))[2*pos], + ((double *)CDR(v))[2*pos+1]); + } + else pos *= 2; + /* Fall through */ + case tc7_dvect: +# ifdef CDR_DOUBLES + if (NIMP(last) && (last != flo0) && (tc_flo==CAR(last))) { + FLO(last) = ((double *)CDR(v))[pos]; + return last; + } +# else +# ifdef SINGLES + if (NIMP(last) && tc_dblr==CAR(last)) +# else + if (NIMP(last) && (last != flo0) && (tc_dblr==CAR(last))) +# endif + { + REAL(last) = ((double *)CDR(v))[pos]; + return last; + } +# endif /* ndef CDR_DOUBLES */ + return makdbl(((double *)CDR(v))[pos], 0.0); +# endif /* def FLOATS */ + case tc7_vector: + return VELTS(v)[pos]; + case tc7_smob: { /* enclosed array */ + int k = ARRAY_NDIM(v); + if (IMP(last) || (!ARRAYP(last))) { + last = make_ra(k); + ARRAY_V(last) = ARRAY_V(v); + while (k--) { + ARRAY_DIMS(last)[k].ubnd = ARRAY_DIMS(v)[k].ubnd; + ARRAY_DIMS(last)[k].lbnd = ARRAY_DIMS(v)[k].lbnd; + ARRAY_DIMS(last)[k].inc = ARRAY_DIMS(v)[k].inc; + } + } + ARRAY_BASE(last) = pos; + return last; + } + } +} + +static char s_aset[] = "array-set!"; +SCM aset(v, obj, args) + SCM v, obj, args; +{ + long pos; + ASRTGO(NIMP(v), badarg1); + if ARRAYP(v) { + pos = aind(v, args, s_aset); + v = ARRAY_V(v); + } + else { + if NIMP(args) { + ASSERT(CONSP(args) && INUMP(CAR(args)), args, ARG2, s_aset); + pos = INUM(CAR(args)); + ASRTGO(NULLP(CDR(args)), wna); + } + else { + ASSERT(INUMP(args), args, ARG2, s_aset); + pos = INUM(args); + } + ASRTGO(pos >= 0 && pos < LENGTH(v), outrng); + } + switch TYP7(v) { + default: badarg1: wta(v, (char *)ARG1, s_aset); + outrng: wta(MAKINUM(pos), (char *)OUTOFRANGE, s_aset); + wna: wta(UNDEFINED, (char *)WNA, s_aset); + case tc7_smob: /* enclosed */ + goto badarg1; + case tc7_bvect: + if (BOOL_F==obj) + VELTS(v)[pos/LONG_BIT] &= ~(1L<<(pos%LONG_BIT)); + else if (BOOL_T==obj) + VELTS(v)[pos/LONG_BIT] |= (1L<<(pos%LONG_BIT)); + else badarg2: wta(obj, (char *)ARG2, s_aset); + break; + case tc7_string: + ASRTGO(ICHRP(obj), badarg2); + CHARS(v)[pos] = ICHR(obj); break; +# ifdef INUMS_ONLY + case tc7_uvect: + ASRTGO(INUM(obj) >= 0, badarg2); + case tc7_ivect: + ASRTGO(INUMP(obj), badarg2); VELTS(v)[pos] = INUM(obj); break; +# else + case tc7_uvect: + VELTS(v)[pos] = num2ulong(obj, (char *)ARG2, s_aset); break; + case tc7_ivect: + VELTS(v)[pos] = num2long(obj, (char *)ARG2, s_aset); break; +# endif +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: + ((float*)VELTS(v))[pos] = (float)num2dbl(obj, (char *)ARG2, s_aset); break; +# endif + case tc7_dvect: + ((double*)VELTS(v))[pos] = num2dbl(obj, (char *)ARG2, s_aset); break; + case tc7_cvect: + if (NIMP(obj) && CPLXP(obj)) { + ((double *)CDR(v))[2*pos] = REALPART(obj); + ((double *)CDR(v))[2*pos+1] = IMAG(obj); + } + else { + ((double *)CDR(v))[2*pos] = num2dbl(obj, (char *)ARG2, s_aset); + ((double *)CDR(v))[2*pos+1] = 0.0; + } + break; +# endif + case tc7_vector: + VELTS(v)[pos] = obj; break; + } + return UNSPECIFIED; +} + +static char s_array_contents[] = "array-contents"; +SCM array_contents(ra, strict) + SCM ra, strict; +{ + SCM sra; + if IMP(ra) return BOOL_F; + switch TYP7(ra) { + default: + return BOOL_F; + case tc7_vector: case tc7_string: case tc7_bvect: case tc7_uvect: + case tc7_ivect: case tc7_fvect: case tc7_dvect: case tc7_cvect: + return ra; + case tc7_smob: { + sizet k, ndim = ARRAY_NDIM(ra), len = 1; + if (!ARRAYP(ra) || !ARRAY_CONTP(ra)) return BOOL_F; + for (k = 0; k < ndim; k++) + len *= ARRAY_DIMS(ra)[k].ubnd - ARRAY_DIMS(ra)[k].lbnd + 1; + if (!UNBNDP(strict)) { + if (ndim && (1 != ARRAY_DIMS(ra)[ndim-1].inc)) return BOOL_F; + if (tc7_bvect==TYP7(ARRAY_V(ra))) { + if (ARRAY_BASE(ra)%LONG_BIT) return BOOL_F; + if (len != LENGTH(ARRAY_V(ra)) && len%LONG_BIT) return BOOL_F; + } + } + if ((len==LENGTH(ARRAY_V(ra))) && 0==ARRAY_BASE(ra) && ARRAY_DIMS(ra)->inc) + return ARRAY_V(ra); + sra = make_ra(1); + ARRAY_DIMS(sra)->lbnd = 0; + ARRAY_DIMS(sra)->ubnd = len - 1; + ARRAY_V(sra) = ARRAY_V(ra); + ARRAY_BASE(sra) = ARRAY_BASE(ra); + ARRAY_DIMS(sra)->inc = (ndim ? ARRAY_DIMS(ra)[ndim - 1].inc : 1); + return sra; + } + } +} + +static char s_uve_rd[] = "uniform-vector-read!"; +SCM uve_read(v, port) + SCM v, port; +{ + long sz, len, ans; + long start=0; + if UNBNDP(port) port = cur_inp; + else ASSERT(NIMP(port) && OPINFPORTP(port), port, ARG2, s_uve_rd); + ASRTGO(NIMP(v), badarg1); + len = LENGTH(v); + loop: + switch TYP7(v) { + default: badarg1: wta(v, (char *)ARG1, s_uve_rd); + case tc7_smob: + v = array_contents(v, BOOL_T); + ASRTGO(NIMP(v), badarg1); + if ARRAYP(v) { + array_dim *d = ARRAY_DIMS(v); + start = ARRAY_BASE(v); + len = d->inc * (d->ubnd - d->lbnd + 1); + v = ARRAY_V(v); + } + else + len = LENGTH(v); + goto loop; + case tc7_string: + sz = sizeof(char); + break; + case tc7_bvect: + len = (len+LONG_BIT-1)/LONG_BIT; + start /= LONG_BIT; + case tc7_uvect: + case tc7_ivect: + sz = sizeof(long); + break; +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: + sz = sizeof(float); + break; +# endif + case tc7_dvect: + sz = sizeof(double); + break; + case tc7_cvect: + sz = 2*sizeof(double); + break; +# endif + } + /* An ungetc before an fread will not work on some systems if setbuf(0). + do #define NOSETBUF in scmfig.h to fix this. */ + if CRDYP(port) { /* UGGH!!! */ + ungetc(CGETUN(port), STREAM(port)); + CLRDY(port); /* Clear ungetted char */ + } + SYSCALL(ans = fread(CHARS(v)+start*sz, (sizet)sz, (sizet)len, STREAM(port));); + if (TYP7(v)==tc7_bvect) ans *= LONG_BIT; + return MAKINUM(ans); +} + +static char s_uve_wr[] = "uniform-vector-write"; +SCM uve_write(v, port) + SCM v, port; +{ + long sz, len, ans; + long start=0; + if UNBNDP(port) port = cur_outp; + else ASSERT(NIMP(port) && OPOUTFPORTP(port), port, ARG2, s_uve_wr); + ASRTGO(NIMP(v), badarg1); + len = LENGTH(v); + loop: + switch TYP7(v) { + default: badarg1: wta(v, (char *)ARG1, s_uve_wr); + case tc7_smob: + v = array_contents(v, BOOL_T); + ASRTGO(NIMP(v), badarg1); + if ARRAYP(v) { + array_dim *d = ARRAY_DIMS(v); + start = ARRAY_BASE(v); + len = d->inc * (d->ubnd - d->lbnd + 1); + v = ARRAY_V(v); + } + else + len = LENGTH(v); + goto loop; + case tc7_string: + sz = sizeof(char); + break; + case tc7_bvect: + len = (len+LONG_BIT-1)/LONG_BIT; + start /= LONG_BIT; + case tc7_uvect: + case tc7_ivect: + sz = sizeof(long); + break; +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: + sz = sizeof(float); + break; +# endif + case tc7_dvect: + sz = sizeof(double); + break; + case tc7_cvect: + sz = 2*sizeof(double); + break; +# endif + } + SYSCALL(ans = fwrite(CHARS(v)+start*sz, (sizet)sz, (sizet)len, STREAM(port));); + if (TYP7(v)==tc7_bvect) ans *= LONG_BIT; + return MAKINUM(ans); +} + +static char cnt_tab[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; +static char s_count[] = "bit-count"; +SCM lcount(item, seq) + SCM item, seq; +{ + long i, imin, ubnd, lbnd = 0; + int enclosed = 0; + register unsigned long cnt = 0, w; + ASSERT(NIMP(seq), seq, ARG2, s_count); + ubnd = LENGTH(seq) - 1; + tail: + switch TYP7(seq) { + default: badarg2: wta(seq, (char *)ARG2, s_count); + case tc7_bvect: + if (lbnd>ubnd) return INUM0; + i = ubnd/LONG_BIT; + imin = lbnd/LONG_BIT; + w = VELTS(seq)[i]; + if FALSEP(item) w = ~w; + w <<= LONG_BIT-1-(ubnd%LONG_BIT); + w >>= LONG_BIT-1-(ubnd%LONG_BIT); /* There may be only a partial word. */ + while (imin < i--) { + for(;w;w >>= 4) cnt += cnt_tab[w & 0x0f]; + w = VELTS(seq)[i]; + if FALSEP(item) w = ~w; + } + w >>= (lbnd%LONG_BIT); + for(;w;w >>= 4) cnt += cnt_tab[w & 0x0f]; + return MAKINUM(cnt); + case tc7_smob: + ASRTGO(ARRAYP(seq) && 1==ARRAY_NDIM(seq) && 0==enclosed++, badarg2); + { + long n, inc = ARRAY_DIMS(seq)->inc; + switch (inc) { + default: + i = ARRAY_BASE(seq); + n = ARRAY_DIMS(seq)->ubnd - ARRAY_DIMS(seq)->lbnd + 1; + if (n<=0) return INUM0; + seq = ARRAY_V(seq); + if FALSEP(item) + for (;n--; i+=inc) + if (!((VELTS(seq)[i/LONG_BIT]) & (1L<<(i%LONG_BIT)))) cnt++; + else + for (;n--; i+=inc) + if ((VELTS(seq)[i/LONG_BIT]) & (1L<<(i%LONG_BIT))) cnt++; + return MAKINUM(cnt); + case 1: + lbnd = ARRAY_BASE(seq); + ubnd = lbnd + (ARRAY_DIMS(seq)->ubnd - ARRAY_DIMS(seq)->lbnd)*inc; + seq = ARRAY_V(seq); + goto tail; + case -1: + ubnd = ARRAY_BASE(seq); + lbnd = ubnd + (ARRAY_DIMS(seq)->ubnd - ARRAY_DIMS(seq)->lbnd)*inc; + seq = ARRAY_V(seq); + goto tail; + } + } + } +} +static char s_uve_pos[] = "bit-position"; +SCM position(item, v, k) + SCM item, v, k; +{ + long i, len, lenw, xbits, pos = INUM(k), offset = 0; + int enclosed = 0; + register unsigned long w; + ASSERT(NIMP(v), v, ARG2, s_uve_pos); + ASSERT(INUMP(k), k, ARG3, s_uve_pos); + len = LENGTH(v); + tail: + switch TYP7(v) { + default: badarg2: wta(v, (char *)ARG2, s_uve_pos); + case tc7_bvect: + ASSERT((pos <= len) && (pos >= 0), k, OUTOFRANGE, s_uve_pos); + if (pos==len) return BOOL_F; + if (0==len) return MAKINUM(-1L); + lenw = (len-1)/LONG_BIT; /* watch for part words */ + i = pos/LONG_BIT; + w = VELTS(v)[i]; + if FALSEP(item) w = ~w; + xbits = (pos%LONG_BIT); + pos -= xbits; + w = ((w >> xbits) << xbits); + xbits = LONG_BIT-1-(len-1)%LONG_BIT; + while (!0) { + if (w && (i==lenw)) + w = ((w << xbits) >> xbits); + if (w) while (w) switch (w & 0x0f) + { + default: return MAKINUM(pos-offset); + case 2: case 6: case 10: case 14: return MAKINUM(pos+1-offset); + case 4: case 12: return MAKINUM(pos+2-offset); + case 8: return MAKINUM(pos+3-offset); + case 0: pos += 4; w >>= 4; + } + if (++i > lenw) break; + pos += LONG_BIT; + w = VELTS(v)[i]; + if FALSEP(item) w = ~w; + } + return BOOL_F; + case tc7_smob: ASRTGO(ARRAYP(v) && 1==ARRAY_NDIM(v) && !enclosed++, badarg2); + ASSERT(pos >= ARRAY_DIMS(v)->lbnd, k, OUTOFRANGE, s_uve_pos); + if (1==ARRAY_DIMS(v)->inc) { + len = ARRAY_DIMS(v)->ubnd - ARRAY_DIMS(v)->lbnd + ARRAY_BASE(v) + 1; + offset = ARRAY_BASE(v) - ARRAY_DIMS(v)->lbnd; + pos += offset; + v = ARRAY_V(v); + goto tail; + } + else { + long inc = ARRAY_DIMS(v)->inc; + long ubnd = ARRAY_DIMS(v)->ubnd; + if (ubnd < ARRAY_DIMS(v)->lbnd) + return MAKINUM(ARRAY_DIMS(v)->lbnd - 1); + i = ARRAY_BASE(v) + (pos - ARRAY_DIMS(v)->lbnd)*inc; + v = ARRAY_V(v); + for (; pos <= ubnd; pos++) { + if (item == + ((VELTS(v)[i/LONG_BIT])&(1L<<(i%LONG_BIT)) ? BOOL_T : BOOL_F)) + return MAKINUM(pos); + i += inc; + } + return BOOL_F; + } + } +} + +static char s_bit_set[] = "bit-set*!"; +SCM bit_set(v, kv, obj) + SCM v, kv, obj; +{ + register long i, k, vlen; + ASRTGO(NIMP(v), badarg1); + ASRTGO(NIMP(kv), badarg2); + switch TYP7(kv) { + default: badarg2: wta(kv, (char *)ARG2, s_bit_set); + case tc7_uvect: + switch TYP7(v) { + default: badarg1: wta(v, (char *)ARG1, s_bit_set); + case tc7_bvect: + vlen = LENGTH(v); + if (BOOL_F==obj) for (i = LENGTH(kv);i;) { + k = VELTS(kv)[--i]; + ASSERT((k < vlen), MAKINUM(k), OUTOFRANGE, s_bit_set); + VELTS(v)[k/LONG_BIT] &= ~(1L<<(k%LONG_BIT)); + } + else if (BOOL_T==obj) for (i = LENGTH(kv); i;) { + k = VELTS(kv)[--i]; + ASSERT((k < vlen), MAKINUM(k), OUTOFRANGE, s_bit_set); + VELTS(v)[k/LONG_BIT] |= (1L<<(k%LONG_BIT)); + } + else + badarg3: wta(obj, (char *)ARG3, s_bit_set); + } + break; + case tc7_bvect: + ASRTGO(TYP7(v)==tc7_bvect && LENGTH(v)==LENGTH(kv), badarg1); + if (BOOL_F==obj) + for (k = (LENGTH(v)+LONG_BIT-1)/LONG_BIT;k--;) + VELTS(v)[k] &= ~(VELTS(kv)[k]); + else if (BOOL_T==obj) + for (k = (LENGTH(v)+LONG_BIT-1)/LONG_BIT;k--;) + VELTS(v)[k] |= VELTS(kv)[k]; + else goto badarg3; + break; + } + return UNSPECIFIED; +} + +static char s_bit_count[] = "bit-count*"; +SCM bit_count(v, kv, obj) + SCM v, kv, obj; +{ + register long i, vlen, count = 0; + register unsigned long k; + ASRTGO(NIMP(v), badarg1); + ASRTGO(NIMP(kv), badarg2); + switch TYP7(kv) { + default: badarg2: wta(kv, (char *)ARG2, s_bit_count); + case tc7_uvect: + switch TYP7(v) { + default: badarg1: wta(v, (char *)ARG1, s_bit_count); + case tc7_bvect: + vlen = LENGTH(v); + if (BOOL_F==obj) for (i = LENGTH(kv);i;) { + k = VELTS(kv)[--i]; + ASSERT((k < vlen), MAKINUM(k), OUTOFRANGE, s_bit_count); + if (!(VELTS(v)[k/LONG_BIT] & (1L<<(k%LONG_BIT)))) count++; + } + else if (BOOL_T==obj) for (i = LENGTH(kv); i;) { + k = VELTS(kv)[--i]; + ASSERT((k < vlen), MAKINUM(k), OUTOFRANGE, s_bit_count); + if (VELTS(v)[k/LONG_BIT] & (1L<<(k%LONG_BIT))) count++; + } + else + badarg3: wta(obj, (char *)ARG3, s_bit_count); + } + break; + case tc7_bvect: + ASRTGO(TYP7(v)==tc7_bvect && LENGTH(v)==LENGTH(kv), badarg1); + if (0==LENGTH(v)) return INUM0; + ASRTGO(BOOL_T==obj || BOOL_F==obj, badarg3); + obj = (BOOL_T==obj); + i = (LENGTH(v)-1)/LONG_BIT; + k = VELTS(kv)[i] & (obj ? VELTS(v)[i] : ~VELTS(v)[i]); + k <<= LONG_BIT-1-((LENGTH(v)-1)%LONG_BIT); + while (!0) { + for(;k;k >>= 4) count += cnt_tab[k & 0x0f]; + if (0==i--) return MAKINUM(count); + k = VELTS(kv)[i] & (obj ? VELTS(v)[i] : ~VELTS(v)[i]); + } + } + return MAKINUM(count); +} + +static char s_bit_inv[] = "bit-invert!"; +SCM bit_inv(v) + SCM v; +{ + register long k; + ASRTGO(NIMP(v), badarg1); + k = LENGTH(v); + switch TYP7(v) { + case tc7_bvect: + for (k = (k+LONG_BIT-1)/LONG_BIT;k--;) + VELTS(v)[k] = ~VELTS(v)[k]; + break; + default: badarg1: wta(v, (char *)ARG1, s_bit_inv); + } + return UNSPECIFIED; +} + +static char s_strup[] = "string-upcase!"; +SCM strup(v) + SCM v; +{ + register long k; + register unsigned char *cs; + ASRTGO(NIMP(v), badarg1); + k = LENGTH(v); + switch TYP7(v) { + case tc7_string: + cs = UCHARS(v); + while (k--) cs[k] = upcase[cs[k]]; + break; + default: badarg1: wta(v, (char *)ARG1, s_strup); + } + return v; +} + +static char s_strdown[] = "string-downcase!"; +SCM strdown(v) + SCM v; +{ + register long k; + register unsigned char *cs; + ASRTGO(NIMP(v), badarg1); + k = LENGTH(v); + switch TYP7(v) { + case tc7_string: + cs = UCHARS(v); + while (k--) cs[k] = downcase[cs[k]]; + break; + default: badarg1: wta(v, (char *)ARG1, s_strdown); + } + return v; +} + +# include <ctype.h> +static char s_strcap[] = "string-capitalize!"; +SCM strcap(v) + SCM v; +{ + long i = 0, len; + register unsigned char *str; + register int non_first_alpha = 0; + ASRTGO(NIMP(v), badarg1); + len = LENGTH(v); + switch TYP7(v) { + case tc7_string: + for (str = UCHARS(v);i < len; i++) { + int c = str[i]; + if (isascii(c) && isalpha(c)) + if (non_first_alpha) str[i] = downcase[c]; + else { + non_first_alpha = !0; + str[i] = upcase[c]; + } + else non_first_alpha = 0; + } + break; + default: badarg1: wta(v, (char *)ARG1, s_strcap); + } + return v; +} + +SCM istr2bve(str, len) + char *str; + long len; +{ + SCM v = make_uve(len, BOOL_T); + long *data = (long *)VELTS(v); + register unsigned long mask; + register long k; + register long j; + for (k = 0; k < (len+LONG_BIT-1)/LONG_BIT; k++) { + data[k] = 0L; + j = len - k*LONG_BIT; + if (j > LONG_BIT) j = LONG_BIT; + for (mask = 1L; j--; mask <<= 1) + switch (*str++) { + case '0': break; + case '1': data[k] |= mask; break; + default: return BOOL_F; + } + } + return v; +} + +static SCM ra2l(ra, base, k) + SCM ra; + sizet base; + sizet k; +{ + register SCM res = EOL; + register long inc = ARRAY_DIMS(ra)[k].inc; + register sizet i; + if (ARRAY_DIMS(ra)[k].ubnd < ARRAY_DIMS(ra)[k].lbnd) return EOL; + i = base + (1 + ARRAY_DIMS(ra)[k].ubnd - ARRAY_DIMS(ra)[k].lbnd)*inc; + if (k < ARRAY_NDIM(ra) - 1) { + do { + i -= inc; + res = cons(ra2l(ra, i, k+1), res); + } while (i != base); + } + else + do { + i -= inc; + res = cons(cvref(ARRAY_V(ra), i, UNDEFINED), res); + } while (i != base); + return res; +} + +static char s_array2list[] = "array->list"; +SCM array2list(v) + SCM v; +{ + SCM res = EOL; + register long k; + ASRTGO(NIMP(v), badarg1); + switch TYP7(v) { + default: badarg1: wta(v, (char *)ARG1, s_array2list); + case tc7_smob: ASRTGO(ARRAYP(v), badarg1); + return ra2l(v, ARRAY_BASE(v), 0); + case tc7_vector: return vector2list(v); + case tc7_string: return string2list(v); + case tc7_bvect: { + long *data = (long *)VELTS(v); + register unsigned long mask; + for (k = (LENGTH(v)-1)/LONG_BIT; k > 0; k--) + for (mask = 1L<<(LONG_BIT-1); mask; mask >>=1) + res = cons(((long *)data)[k] & mask ? BOOL_T : BOOL_F, res); + for (mask = 1L<<((LENGTH(v)%LONG_BIT)-1); mask; mask >>=1) + res = cons(((long *)data)[k] & mask ? BOOL_T : BOOL_F, res); + return res; + } +# ifdef INUMS_ONLY + case tc7_uvect: + case tc7_ivect: { + long *data = (long *)VELTS(v); + for (k = LENGTH(v) - 1; k >= 0; k--) + res = cons(MAKINUM(data[k]), res); + return res; + } +# else + case tc7_uvect: { + long *data = (long *)VELTS(v); + for (k = LENGTH(v) - 1; k >= 0; k--) + res = cons(ulong2num(data[k]), res); + return res; + } + case tc7_ivect: { + long *data = (long *)VELTS(v); + for (k = LENGTH(v) - 1; k >= 0; k--) + res = cons(long2num(data[k]), res); + return res; + } +# endif +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: { + float *data = (float *)VELTS(v); + for (k = LENGTH(v) - 1; k >= 0; k--) + res = cons(makflo(data[k]), res); + return res; + } +# endif /*SINGLES*/ + case tc7_dvect: { + double *data = (double *)VELTS(v); + for (k = LENGTH(v) - 1; k >= 0; k--) + res = cons(makdbl(data[k], 0.0), res); + return res; + } + case tc7_cvect: { + double (*data)[2] = (double (*)[2])VELTS(v); + for (k = LENGTH(v) - 1; k >= 0; k--) + res = cons(makdbl(data[k][0], data[k][1]), res); + return res; + } +# endif /*FLOATS*/ + } +} + +static int l2ra P((SCM lst, SCM ra, sizet base, sizet k)); +static char s_bad_ralst[] = "Bad array contents list"; +static char s_list2ura[] = "list->uniform-array"; +SCM list2ura(ndim, prot, lst) + SCM ndim; + SCM prot; + SCM lst; +{ + SCM shp=EOL; + SCM row=lst; + SCM ra; + sizet k; + long n; + ASSERT(INUMP(ndim), ndim, ARG1, s_list2ura); + k = INUM(ndim); + for (; k--; NIMP(row) && (row = CAR(row))) { + n = ilength(row); + ASSERT(n>=0, lst, ARG2, s_list2ura); + shp = cons(MAKINUM(n), shp); + } + ra = dims2ura(reverse(shp), prot, EOL); + if NULLP(shp) { + ASRTGO(1==ilength(lst), badlst); + aset(ra, CAR(lst), EOL); + return ra; + } + if (!ARRAYP(ra)) { + for (k = 0; k < LENGTH(ra); k++, lst = CDR(lst)) + aset(ra, CAR(lst), MAKINUM(k)); + return ra; + } + if (l2ra(lst, ra, ARRAY_BASE(ra), 0)) + return ra; + else + badlst: wta(lst, s_bad_ralst, s_list2ura); + return BOOL_F; +} + +static int l2ra(lst, ra, base, k) + SCM lst; + SCM ra; + sizet base; + sizet k; +{ + register long inc = ARRAY_DIMS(ra)[k].inc; + register long n = (1 + ARRAY_DIMS(ra)[k].ubnd - ARRAY_DIMS(ra)[k].lbnd); + int ok = 1; + if (n <= 0) return (EOL==lst); + if (k < ARRAY_NDIM(ra) - 1) { + while (n--) { + if (IMP(lst) || NCONSP(lst)) return 0; + ok = ok && l2ra(CAR(lst), ra, base, k+1); + base += inc; + lst = CDR(lst); + } + if NNULLP(lst) return 0; + } + else { + while (n--) { + if (IMP(lst) || NCONSP(lst)) return 0; + ok = ok && aset(ARRAY_V(ra), CAR(lst), MAKINUM(base)); + base += inc; + lst = CDR(lst); + } + if NNULLP(lst) return 0; + } + return ok; +} + +static void rapr1(ra, j, k, port, writing) + SCM ra; + sizet j; + sizet k; + SCM port; + int writing; +{ + long inc = 1; + long n = LENGTH(ra); + int enclosed = 0; + tail: + switch TYP7(ra) { + case tc7_smob: + if (enclosed++) { + ARRAY_BASE(ra) = j; + if (n-- > 0) iprin1(ra, port, writing); + for (j += inc; n-- > 0; j += inc) { + lputc(' ', port); + ARRAY_BASE(ra) = j; + iprin1(ra, port, writing); + } + break; + } + if (k+1 < ARRAY_NDIM(ra)) { + long i; + inc = ARRAY_DIMS(ra)[k].inc; + for (i = ARRAY_DIMS(ra)[k].lbnd; i < ARRAY_DIMS(ra)[k].ubnd; i++) { + lputc('(', port); + rapr1(ra, j, k+1, port, writing); + lputs(") ", port); + j += inc; + } + if (i==ARRAY_DIMS(ra)[k].ubnd) { /* could be zero size. */ + lputc('(', port); + rapr1(ra, j, k+1, port, writing); + lputc(')', port); + } + break; + } + if ARRAY_NDIM(ra) { /* Could be zero-dimensional */ + inc = ARRAY_DIMS(ra)[k].inc; + n = (ARRAY_DIMS(ra)[k].ubnd - ARRAY_DIMS(ra)[k].lbnd + 1); + } + else + n = 1; + ra = ARRAY_V(ra); + goto tail; + default: + if (n-- > 0) iprin1(cvref(ra, j, UNDEFINED), port, writing); + for (j += inc; n-- > 0; j += inc) { + lputc(' ', port); + iprin1(cvref(ra, j, UNDEFINED), port, writing); + } + break; + case tc7_string: + if (n-- > 0) iprin1(MAKICHR(CHARS(ra)[j]), port, writing); + if (writing) + for (j += inc; n-- > 0; j += inc) { + lputc(' ', port); + iprin1(MAKICHR(CHARS(ra)[j]), port, writing); + } + else + for (j += inc; n-- > 0; j += inc) + lputc(CHARS(ra)[j], port); + break; + case tc7_uvect: + if (n-- > 0) iprin1(ulong2num(VELTS(ra)[j]), port, writing); + for (j += inc; n-- > 0; j += inc) { + lputc(' ', port); + iprin1(ulong2num(VELTS(ra)[j]), port, writing); + } + break; + case tc7_ivect: + if (n-- > 0) intprint(VELTS(ra)[j], 10, port); + for (j += inc; n-- > 0; j += inc) { + lputc(' ', port); + intprint(VELTS(ra)[j], 10, port); + } + break; +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: +# endif /*SINGLES*/ + case tc7_dvect: + case tc7_cvect: + if (n-- > 0) { + SCM z = cvref(ra, j, UNDEFINED); + floprint(z, port, writing); + for (j += inc; n-- > 0; j += inc) { + lputc(' ', port); + z = cvref(ra, j, z); + floprint(z, port, writing); + } + } + break; +# endif /*FLOATS*/ + } +} +int raprin1(exp, port, writing) + SCM exp; + SCM port; + int writing; +{ + SCM v = exp; + sizet base = 0; + lputc('#', port); + tail: + switch TYP7(v) { + case tc7_smob: { + long ndim = ARRAY_NDIM(v); + base = ARRAY_BASE(v); + v = ARRAY_V(v); + if ARRAYP(v) { + lputs("<enclosed-array ", port); + rapr1(exp, base, 0, port, writing); + lputc('>', port); + return 1; + } + else { + intprint(ndim, 10, port); + goto tail; + } + } + case tc7_bvect: + if (exp==v) { /* a uve, not an array */ + register long i, j, w; + lputc('*', port); + for(i = 0;i<(LENGTH(exp))/LONG_BIT;i++) { + w = VELTS(exp)[i]; + for(j = LONG_BIT;j;j--) { + lputc(w&1?'1':'0', port); + w >>= 1; + } + } + j = LENGTH(exp)%LONG_BIT; + if (j) { + w = VELTS(exp)[LENGTH(exp)/LONG_BIT]; + for(;j;j--) { + lputc(w&1?'1':'0', port); + w >>= 1; + } + } + return 1; + } + else + lputc('b', port); break; + case tc7_string: + lputc('a', port); break; + case tc7_uvect: + lputc('u', port); break; + case tc7_ivect: + lputc('e', port); break; +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: + lputc('s', port); break; +# endif /*SINGLES*/ + case tc7_dvect: + lputc('i', port); break; + case tc7_cvect: + lputc('c', port); break; +# endif /*FLOATS*/ + } + lputc('(', port); + rapr1(exp, base, 0, port, writing); + lputc(')', port); + return 1; +} + +static char s_array_prot[] = "array-prototype"; +SCM array_prot(ra) + SCM ra; +{ + int enclosed = 0; + ASRTGO(NIMP(ra), badarg); + loop: + switch TYP7(ra) { + default: badarg: wta(ra, (char *)ARG1, s_array_prot); + case tc7_smob: ASRTGO(ARRAYP(ra), badarg); + if (enclosed++) return UNSPECIFIED; + ra = ARRAY_V(ra); + goto loop; + case tc7_vector: return EOL; + case tc7_bvect: return BOOL_T; + case tc7_string: return MAKICHR('a'); + case tc7_uvect: return MAKINUM(1L); + case tc7_ivect: return MAKINUM(-1L); +# ifdef FLOATS +# ifdef SINGLES + case tc7_fvect: return makflo(1.0); +# endif + case tc7_dvect: return makdbl(1.0/3.0, 0.0); + case tc7_cvect: return makdbl(0.0, 1.0); +# endif + } +} + +static iproc subr3s[] = { + {"uniform-vector-set1!", aset}, + {s_uve_pos, position}, + {s_bit_set, bit_set}, + {s_bit_count, bit_count}, + {s_list2ura, list2ura}, + {0, 0}}; + +static iproc subr2s[] = { + {"uniform-vector-ref", aref}, + {s_resizuve, resizuve}, + {s_count, lcount}, + {s_uve_fill, uve_fill}, + {0, 0}}; + +static iproc subr1s[] = { + {"array-rank", array_rank}, + {s_array_dims, array_dims}, + {s_array2list, array2list}, + {s_uve_len, uve_len}, + {s_bit_inv, bit_inv}, + {s_strdown, strdown}, + {s_strcap, strcap}, + {s_strup, strup}, + {s_array_prot, array_prot}, + {0, 0}}; + +static iproc lsubrs[] = { + {s_aref, scm_array_ref}, + {s_trans_array, trans_array}, + {s_encl_array, encl_array}, + {s_array_inbp, array_inbp}, + {0, 0}}; + +static iproc lsubr2s[] = { + {s_make_sh_array, make_sh_array}, + {s_dims2ura, dims2ura}, + {s_aset, aset}, + {0, 0}}; + +static iproc subr2os[] = { + {"array?", arrayp}, + {s_array_contents, array_contents}, + {s_uve_rd, uve_read}, + {s_uve_wr, uve_write}, + {0, 0}}; + +static SCM markra(ptr) + SCM ptr; +{ + if GC8MARKP(ptr) return BOOL_F; + SETGC8MARK(ptr); + return ARRAY_V(ptr); +} +static sizet freera(ptr) + CELLPTR ptr; +{ + must_free(CHARS(ptr)); + return sizeof(array) + ARRAY_NDIM(ptr)*sizeof(array_dim); +} +static smobfuns rasmob = {markra, freera, raprin1, 0}; + /* 0 replaced by raequal in init_ramap() */ + +/* This must be done after init_scl() */ +void init_unif() +{ + init_iprocs(subr3s, tc7_subr_3); + init_iprocs(subr2s, tc7_subr_2); + init_iprocs(subr1s, tc7_subr_1); + init_iprocs(lsubrs, tc7_lsubr); + init_iprocs(lsubr2s, tc7_lsubr_2); + init_iprocs(subr2os, tc7_subr_2o); + tc16_array = newsmob(&rasmob); + add_feature(s_array); + add_feature("string-case"); +} + +#else /* ARRAYS */ + +int raprin1(exp, port, writing) + SCM exp; + SCM port; + int writing; +{ + return 0; +} + +SCM istr2bve(str, len) + char *str; + long len; +{ + return BOOL_F; +} + +SCM array_equal(ra0, ra1) + SCM ra0, ra1; +{ + return BOOL_F; +} + +void init_unif() +{ + make_subr(s_resizuve, tc7_subr_2, resizuve); +} + +#endif /* ARRAYS */ |