/* xltvec.c - typed vectors */
/* 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"
LOCAL int typecode P1H(LVAL);
LOCAL int typesize P1H(int);
LOCAL FIXTYPE getirealpart P1C(LVAL, x)
{
switch (ntype(x)) {
case FIXNUM:
return getfixnum(x);
case COMPLEX:
if (fixp(getreal(x)))
return getfixnum(getreal(x));
else
xlbadtype(x);
break;
default:
xlbadtype(x);
}
return 0; /* not reached */
}
LOCAL FIXTYPE getiimagpart P1C(LVAL, x)
{
switch (ntype(x)) {
case FIXNUM:
return 0;
case COMPLEX:
if (fixp(getimag(x)))
return getfixnum(getimag(x));
else
xlbadtype(x);
break;
default:
xlbadtype(x);
}
return 0; /* not reached */
}
LOCAL FLOTYPE getdrealpart P1C(LVAL, x)
{
switch (ntype(x)) {
case FIXNUM:
return (FLOTYPE) getfixnum(x);
case FLONUM:
return getflonum(x);
case COMPLEX:
return makefloat(getreal(x));
default:
xlbadtype(x);
}
return 0; /* not reached */
}
LOCAL FLOTYPE getdimagpart P1C(LVAL, x)
{
switch (ntype(x)) {
case FIXNUM:
case FLONUM:
return 0.0;
case COMPLEX:
return makefloat(getimag(x));
default:
xlbadtype(x);
}
return 0; /* not reached */
}
LOCAL int typecode P1C(LVAL, x)
{
x = xlparsetype(x);
if (x == a_char) return(CD_CHARACTER);
else if (x == a_fixnum) return(CD_FIXTYPE);
else if (x == a_flonum) return(CD_FLOTYPE);
else if (consp(x) && consp(cdr(x)) && car(x) == a_complex) {
x = xlparsetype(car(cdr(x)));
if (x == a_fixnum) return(CD_CXFIXTYPE);
else if (x == a_flonum) return(CD_CXFLOTYPE);
else return(CD_TRUE);
}
else if (x == s_c_char) return(CD_CHAR);
else if (x == s_c_uchar) return(CD_UCHAR);
else if (x == s_c_short) return(CD_SHORT);
else if (x == s_c_int) return(CD_INT);
else if (x == s_c_long) return(CD_LONG);
else if (x == s_c_float) return(CD_FLOAT);
else if (x == s_c_double) return(CD_DOUBLE);
else if (x == s_c_complex) return(CD_COMPLEX);
else if (x == s_c_dcomplex) return(CD_DCOMPLEX);
else return(CD_TRUE);
}
LOCAL int typesize P1C(int, code)
{
switch(code) {
case CD_CHARACTER: return(sizeof(char));
case CD_FIXTYPE: return(sizeof(FIXTYPE));
case CD_FLOTYPE: return(sizeof(FLOTYPE));
case CD_CXFIXTYPE: return(2 * sizeof(FIXTYPE));
case CD_CXFLOTYPE: return(2 * sizeof(FLOTYPE));
case CD_CHAR: return(sizeof(char));
case CD_SHORT: return(sizeof(short));
case CD_INT: return(sizeof(int));
case CD_LONG: return(sizeof(long));
case CD_FLOAT: return(sizeof(float));
case CD_DOUBLE: return(sizeof(double));
case CD_COMPLEX: return(2 * sizeof(float));
case CD_DCOMPLEX: return(2 * sizeof(double));
default: return(1);
}
}
LVAL mktvec P2C(int, n, LVAL, etype)
{
LVAL val;
int type;
type = typecode(etype);
if (type == CD_TRUE)
val = newvector(n);
else if (type == CD_CHARACTER) {
int i;
val = newstring(n);
for (i = 0; i < n; i++)
setstringch(val, i, ' ');
}
else {
val = newtvec(n, typesize(type));
settvectype(val, type);
}
return(val);
}
#define settvecdataelt(c, t, i, v) (((t *) (c))[i] = ((t) (v)))
#define gettvecdataelt(c, t, i) (((t *) (c))[i])
#define CVFIX(x) cvfixnum((FIXTYPE) (x))
#define CVFLO(x) cvflonum((FLOTYPE) (x))
#define u_char unsigned char
#define u_short unsigned short
#define u_int unsigned int
#define u_long unsigned long
int gettvecsize P1C(LVAL, x)
{
switch(ntype(x)) {
case VECTOR: return(getsize(x));
case STRING: return(getslength(x));
case TVEC: return(gettlength(x) / typesize(gettvectype(x)));
default: xlbadtype(x);
}
/* not reacched */
return 0;
}
LVAL gettvecelement P2C(LVAL, x, int, i)
{
double rval, ival;
FIXTYPE irval, iival;
ALLOCTYPE *v;
int type;
switch (ntype(x)) {
case VECTOR: return(getelement(x, i));
case STRING: return(cvchar(getstringch(x, i)));
case TVEC:
type = gettvectype(x);
v = gettvecdata(x);
switch (type) {
case CD_CHARACTER: return(cvchar(gettvecdataelt(v, char, i)));
case CD_FIXTYPE: return(CVFIX(gettvecdataelt(v, FIXTYPE, i)));
case CD_FLOTYPE: return(CVFLO(gettvecdataelt(v, FLOTYPE, i)));
case CD_CXFIXTYPE:
irval = gettvecdataelt(v, FIXTYPE, 2 * i);
iival = gettvecdataelt(v, FIXTYPE, 2 * i + 1);
return(newicomplex(irval, iival));
case CD_CXFLOTYPE:
rval = gettvecdataelt(v, FLOTYPE, 2 * i);
ival = gettvecdataelt(v, FLOTYPE, 2 * i + 1);
return(newdcomplex(rval, ival));
case CD_CHAR: return(CVFIX(gettvecdataelt(v, char, i)));
case CD_UCHAR: return(CVFIX(gettvecdataelt(v, unsigned char, i)));
case CD_SHORT: return(CVFIX(gettvecdataelt(v, short, i)));
case CD_INT: return(CVFIX(gettvecdataelt(v, int, i)));
case CD_LONG: return(CVFIX(gettvecdataelt(v, long, i)));
case CD_FLOAT: return(CVFLO(gettvecdataelt(v, float, i)));
case CD_DOUBLE: return(CVFLO(gettvecdataelt(v, double, i)));
case CD_COMPLEX:
rval = gettvecdataelt(v, float, 2 * i);
ival = gettvecdataelt(v, float, 2 * i + 1);
return(newdcomplex(rval, ival));
case CD_DCOMPLEX:
rval = gettvecdataelt(v, double, 2 * i);
ival = gettvecdataelt(v, double, 2 * i + 1);
return(newdcomplex(rval, ival));
default:
xlbadtype(x);
}
default:
xlbadtype(x);
}
/* not reached */
return(NIL);
}
VOID settvecelement P3C(LVAL, x, int, i, LVAL, item)
{
ALLOCTYPE *v;
int type;
switch (ntype(x)) {
case VECTOR: setelement(x, i, item); break;
case STRING:
if (! charp(item)) xlbadtype(item);
setstringch(x, i, getchcode(item));
break;
case TVEC:
type = gettvectype(x);
v = gettvecdata(x);
switch (type) {
case CD_CHARACTER:
if (! charp(item)) xlbadtype(item);
settvecdataelt(v, char, i, getchcode(item));
break;
case CD_FIXTYPE:
if (! fixp(item)) xlbadtype(item);
settvecdataelt(v, FIXTYPE, i, getfixnum(item));
break;
case CD_FLOTYPE:
settvecdataelt(v, FLOTYPE, i, MAKEFLOAT(item));
break;
case CD_CXFIXTYPE:
settvecdataelt(v, FIXTYPE, 2 * i, getirealpart(item));
settvecdataelt(v, FIXTYPE, 2 * i + 1, getiimagpart(item));
break;
case CD_CXFLOTYPE:
settvecdataelt(v, FLOTYPE, 2 * i, getdrealpart(item));
settvecdataelt(v, FLOTYPE, 2 * i + 1, getdimagpart(item));
break;
case CD_CHAR:
if (! fixp(item)) xlbadtype(item);
settvecdataelt(v, char, i, getfixnum(item));
break;
case CD_UCHAR:
if (! fixp(item)) xlbadtype(item);
settvecdataelt(v, unsigned char, i, getfixnum(item));
break;
case CD_SHORT:
if (! fixp(item)) xlbadtype(item);
settvecdataelt(v, short, i, getfixnum(item));
break;
case CD_INT:
if (! fixp(item)) xlbadtype(item);
settvecdataelt(v, int, i, getfixnum(item));
break;
case CD_LONG:
if (! fixp(item)) xlbadtype(item);
settvecdataelt(v, long, i, getfixnum(item));
break;
case CD_FLOAT:
settvecdataelt(v, float, i, MAKEFLOAT(item));
break;
case CD_DOUBLE:
settvecdataelt(v, double, i, MAKEFLOAT(item));
break;
case CD_COMPLEX:
settvecdataelt(v, float, 2 * i, getdrealpart(item));
settvecdataelt(v, float, 2 * i + 1, getdimagpart(item));
break;
case CD_DCOMPLEX:
settvecdataelt(v, double, 2 * i, getdrealpart(item));
settvecdataelt(v, double, 2 * i + 1, getdimagpart(item));
break;
default:
xlbadtype(x);
}
break;
default:
xlbadtype(x);
}
}
LVAL gettvecetype P1C(LVAL, x)
{
switch (ntype(x)) {
case VECTOR: return(s_true);
case STRING: return(a_char);
case TVEC:
switch (gettvectype(x)) {
case CD_CHARACTER: return(a_char);
case CD_FIXTYPE: return(a_fixnum);
case CD_FLOTYPE: return(a_flonum);
case CD_CXFIXTYPE: return(cons(a_complex, consa(a_fixnum)));
case CD_CXFLOTYPE: return(cons(a_complex, consa(a_flonum)));
case CD_CHAR: return(s_c_char);
case CD_UCHAR: return(s_c_uchar);
case CD_SHORT: return(s_c_short);
case CD_INT: return(s_c_int);
case CD_LONG: return(s_c_long);
case CD_FLOAT: return(s_c_float);
case CD_DOUBLE: return(s_c_double);
case CD_COMPLEX: return(s_c_complex);
case CD_DCOMPLEX: return(s_c_dcomplex);
default: xlbadtype(x);
}
default: xlbadtype(x);
}
/* not reached */
return(NIL);
}
int gettveceltsize P1C(LVAL, x)
{
switch (ntype(x)) {
case VECTOR: return(sizeof(LVAL));
case STRING: return(1);
case TVEC: return(typesize(gettvectype(x)));
default: xlbadtype(x);
}
/* not reached */
return(0);
}
VOID xlreplace P6C(LVAL, x, LVAL, y,
int, start1, int, end1,
int, start2, int, end2)
{
int n1, n2, i, j;
n1 = listp(x) ? llength(x) : gettvecsize(x);
n2 = listp(y) ? llength(y) : gettvecsize(y);
if (! (0 <= start1 && start1 <= end1 && end1 <= n1) ||
! (0 <= start2 && start2 <= end2 && end2 <= n2))
xlfail("range error");
/* adjust list arguments */
if (consp(x))
while (start1 > 0) { start1--; end1--; x = cdr(x); }
if (consp(y))
while (start2 > 0) { start2--; end2--; y = cdr(y); }
/* quick return for no copying */
if (start1 >= end1 || start2 >= end2)
return;
/* do the replacement */
switch (ntype(x)) {
case CONS:
switch (ntype(y)) {
case CONS:
for (; end1 > 0 && end2 > 0; x = cdr(x), y = cdr(y), end1--, end2--)
rplaca(x, car(y));
break;
case VECTOR:
for (i = start2; end1 > 0 && i < end2; x = cdr(x), end1--, i++)
rplaca(x, getelement(y, i));
break;
case STRING:
case TVEC:
for (i = start2; end1 > 0 && i < end2; x = cdr(x), end1--, i++)
rplaca(x, gettvecelement(y, i));
break;
default:
xlbadtype(y);
}
break;
case VECTOR:
switch (ntype(y)) {
case CONS:
for (i = start1; i < end1 && end2 > 0; i++, y = cdr(y), end2--)
setelement(x, i, car(y));
break;
case VECTOR:
for (i = start1, j = start2; i < end1 && j < end2; i++, j++)
setelement(x, i, getelement(y, j));
break;
case STRING:
case TVEC:
for (i = start1, j = start2; i < end1 && j < end2; i++, j++)
setelement(x, i, gettvecelement(y, j));
break;
default:
xlbadtype(y);
}
break;
case STRING:
case TVEC:
switch (ntype(y)) {
case CONS:
for (i = start1; i < end1 && end2 > 0; i++, y = cdr(y), end2--)
settvecelement(x, i, car(y));
break;
case VECTOR:
for (i = start1, j = start2; i < end1 && j < end2; i++, j++)
settvecelement(x, i, getelement(y, j));
break;
case STRING:
case TVEC:
if (gettvectype(x) == gettvectype(y)) {
char *dx, *dy;
int nbytes;
dx = ((char *) gettvecdata(x)) + start1;
dy = ((char *) gettvecdata(y)) + start2;
end1 -= start1;
end2 -= start2;
nbytes = ((end1 < end2) ? end1 : end2) * typesize(gettvectype(x));
MEMCPY(dx, dy, nbytes);
}
else
for (i = start1, j = start2; i < end1 && j < end2; i++, j++)
settvecelement(x, i, gettvecelement(y, j));
break;
default:
xlbadtype(y);
}
break;
default:
xlbadtype(x);
}
return;
}
LVAL xtveceltsize(V)
{
LVAL x = xlgetarg();
xllastarg();
return cvfixnum(gettveceltsize(x));
}
syntax highlighted by Code2HTML, v. 0.9.1