home *** CD-ROM | disk | FTP | other *** search
- /* commonmath - xlisp math functions modified and augmented to */
- /* correspond more closely to Common Lisp standard */
- /* Modifications by Luke Tierney for */
- /* XLISP-STAT 2.0 Copyright (c) 1988 by Luke Tierney */
- /* xlmath - xlisp built-in arithmetic functions */
- /* Copyright (c) 1985, by David Michael Betz */
- /* All Rights Reserved */
- /* Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
- #include <math.h>
-
- #ifdef COMPLX
- /* These definititions used instead of those in XLMATH.C */
- /* Somewhat cleaned by by Tom Almy */
-
- /* external variables */
- extern LVAL true;
-
- #define IN 0
- #define FL 1
- #define CI 2
- #define CF 3
- #ifdef RATIOS
- #define RT 4
- #endif
-
- typedef struct {
- int mode;
- FIXTYPE val, crval, cival;
- #ifdef RATIOS
- FIXTYPE num, denom;
- #endif
- FLOTYPE fval, cfrval, cfival;
- } Number;
-
-
- typedef struct {
- double real, imag;
- } Complex;
-
-
- #ifdef ANSI /* local declarations */
- void XNEAR checkizero(FIXTYPE iarg);
- void XNEAR checkfzero(FLOTYPE farg);
- void XNEAR badiop(void);
- void XNEAR badfop(void);
- #ifdef RATIOS
- void XNEAR badrop(void);
- void XNEAR add_ratios(FIXTYPE *n1, FIXTYPE *d1, FIXTYPE n2, FIXTYPE d2);
- void XNEAR mult_ratios(FIXTYPE *n1, FIXTYPE *d1, FIXTYPE n2, FIXTYPE d2);
- #endif
- void XNEAR badcop(void);
- Complex XNEAR makecomplex(LVAL x);
- double XNEAR modulus(Complex c);
- Complex XNEAR cart2complex(double real, double imag);
- LVAL XNEAR cvcomplex(Complex c);
- Complex XNEAR polar2complex(double mod, double phi);
- Complex XNEAR csqrt(Complex c);
- Complex XNEAR cexp(Complex c);
- Complex XNEAR clog(Complex c);
- Complex XNEAR cmul(Complex c1, Complex c2);
- Complex XNEAR cexpt(Complex c1, Complex c2);
- Complex XNEAR cadd(Complex c1, Complex c2);
- Complex XNEAR csub(Complex c1, Complex c2);
- Complex XNEAR cdiv(Complex c1, Complex c2);
- Complex XNEAR csin(Complex c);
- Complex XNEAR ccos(Complex c);
- Complex XNEAR ctan(Complex c);
- Complex XNEAR casin(Complex c);
- Complex XNEAR cacos(Complex c);
- Complex XNEAR catan(Complex c);
- Complex XNEAR catan2(Complex n, Complex d);
- LVAL XNEAR readnumber(Number *num);
- void XNEAR setmode(Number *x, int mode);
- void XNEAR matchmodes(Number *x, Number *y);
- LVAL XNEAR lispnumber(Number *x);
- LVAL XNEAR binary(int which);
- LVAL XNEAR logbinary(int which);
- void XNEAR get_mod_arg(FLOTYPE *fval, int *mode);
- FIXTYPE XNEAR xget_gcd(FIXTYPE n, FIXTYPE m);
- LVAL XNEAR unary(int which);
- LVAL XNEAR unary2(int which);
- LVAL XNEAR predicate(int fcn);
- LVAL XNEAR compare(int fcn);
- LVAL XNEAR ccompare(int which);
- LVAL XNEAR xsgetreal(void);
- double XNEAR logarithm(FLOTYPE x, FLOTYPE base, int base_supplied);
- #endif
-
-
- /* Error checking and messages */
-
- /* checkizero - check for integer division by zero */
- LOCAL VOID XNEAR checkizero(iarg)
- FIXTYPE iarg;
- {
- if (iarg == 0)
- xlfail("illegal zero argument");
- }
-
- /* checkfzero - check for floating point division by zero or log of zero */
- LOCAL VOID XNEAR checkfzero(farg)
- FLOTYPE farg;
- {
- if (farg == 0.0)
- xlfail("illegal zero argument");
- }
-
- /* badiop - bad integer operation */
- LOCAL VOID XNEAR badiop()
- {
- xlfail("bad integer operation");
- }
-
- /* badfop - bad floating point operation */
- LOCAL VOID XNEAR badfop()
- {
- xlfail("bad floating point operation");
- }
-
- #ifdef RATIOS
- /* badrop - bad ratio operation */
- LOCAL VOID XNEAR badrop()
- {
- xlfail("bad ratio operation");
- }
- #endif
-
- /* badcop - bad complex number operation */
- LOCAL VOID XNEAR badcop()
- {
- xlfail("bad complex number operation");
- }
-
- /* TAA MOD badarg() removed, using preexisting xlbadtype which
- gives same message */
-
- /* complex - Complex number functions */
-
- /*TAA MOD--do inline with libm call*/
- #define phase(c) ((c).imag==0.0 && (c).real == 0.0 ? 0 : atan2((c).imag,(c).real))
-
- /* TAA Mod--do inline, old test for complexp inline as appropriate */
- /* badcomplex() eliminated since it didn't make sense (other numereric
- types were ok), so returned error is now from xlbadtype */
-
- #define realpart(x) (getelement(x, 0))
-
- #define imagpart(x) (getelement(x, 1))
-
-
- LOCAL Complex XNEAR makecomplex(x)
- LVAL x;
- {
- Complex c;
-
- if (numberp(x)) {
- c.real = makefloat(x);
- c.imag = 0.0;
- }
- else if (complexp(x)) {
- c.real = makefloat(realpart(x));
- c.imag = makefloat(imagpart(x));
- }
- else xlerror("not a number", x);
- return(c);
- }
-
- LOCAL double XNEAR modulus(c)
- Complex c;
- {
- return(sqrt(c.real * c.real + c.imag * c.imag));
- }
-
- LOCAL Complex XNEAR cart2complex(real, imag)
- double real, imag;
- {
- Complex val;
- val.real = real;
- val.imag = imag;
- return(val);
- }
-
- LOCAL LVAL XNEAR cvcomplex(c)
- Complex c;
- {
- return(newdcomplex(c.real, c.imag));
- }
-
- LOCAL Complex XNEAR polar2complex(mod, phi)
- double mod, phi;
- {
- Complex val;
- double cs, sn;
-
- if (phi == 0) {
- cs = 1.0;
- sn = 0.0;
- }
- else if (phi == PI / 2) {
- cs = 0.0;
- sn = 1.0;
- }
- else if (phi == PI) {
- cs = -1.0;
- sn = 0.0;
- }
- else if (phi == -PI / 2) {
- cs = 0.0;
- sn = -1.0;
- }
- else {
- cs = cos(phi);
- sn = sin(phi);
- }
- val.real = mod * cs;
- val.imag = mod * sn;
- return(val);
- }
-
- LOCAL Complex XNEAR csqrt(c)
- Complex c;
- {
- return(polar2complex(sqrt(modulus(c)), phase(c) / 2));
- }
-
- LOCAL Complex XNEAR cexp(c)
- Complex c;
- {
- return(polar2complex(exp(c.real), c.imag));
- }
-
- LOCAL Complex XNEAR clog(c)
- Complex c;
- {
- double mod;
-
- mod = modulus(c);
- checkfzero(mod);
- return(cart2complex(log(mod), phase(c)));
- }
-
- LOCAL Complex XNEAR cmul(c1, c2)
- Complex c1, c2;
- {
- #if 0 /* This is rediculous, says TAA */
- /* why pay the cost for the two conversions? */
- double m1, m2, p1, p2;
-
- m1 = modulus(c1);
- p1 = phase(c1);
- m2 = modulus(c2);
- p2 = phase(c2);
- return(polar2complex(m1 * m2, p1 + p2));
- #else
- Complex val;
-
- val.real = c1.real * c2.real - c1.imag * c2.imag;
- val.imag = c1.imag * c2.real + c1.real * c2.imag;
- return val;
- #endif
- }
-
- LOCAL Complex XNEAR cexpt(cb, cp)
- Complex cb, cp;
- {
- if (modulus(cp) == 0.0) return(cart2complex(1.0, 0.0));
- else return(cexp(cmul(clog(cb), cp)));
- }
-
- LOCAL Complex XNEAR cadd(c1, c2)
- Complex c1, c2;
- {
- return(cart2complex(c1.real + c2.real, c1.imag + c2.imag));
- }
-
- LOCAL Complex XNEAR csub(c1, c2)
- Complex c1, c2;
- {
- return(cart2complex(c1.real - c2.real, c1.imag - c2.imag));
- }
-
- LOCAL Complex XNEAR cdiv(c1, c2)
- Complex c1, c2;
- {
- #if 0
- double m1, m2, p1, p2;
-
- m1 = modulus(c1);
- p1 = phase(c1);
- m2 = modulus(c2);
- p2 = phase(c2);
- checkfzero(m2);
- return(polar2complex(m1 / m2, p1 - p2));
- #else /* replace with code that is faster */
- double ratio, temp;
-
- if (fabs(c2.real) > fabs(c2.imag)) {
- ratio = c2.imag / c2.real;
- temp = c2.real + ratio*c2.imag;
- return cart2complex((c1.real + c1.imag*ratio)/temp,
- (c1.imag - c1.real*ratio)/temp);
- }
- else {
- checkfzero(c2.imag);
- ratio = c2.real / c2.imag;
- temp = c2.imag + ratio*c2.real;
- return cart2complex ((c1.real*ratio + c1.imag)/temp,
- (c1.imag*ratio - c1.real)/temp);
- }
- #endif
- }
-
- LOCAL Complex XNEAR csin(c)
- Complex c;
- {
- Complex x1, x2, val;
-
- x1 = cart2complex(-c.imag, c.real);
- x2 = cart2complex(c.imag, -c.real);
- val = csub(cexp(x1), cexp(x2));
- return(cart2complex(val.imag / 2.0, -val.real / 2.0));
- }
-
- LOCAL Complex XNEAR ccos(c)
- Complex c;
- {
- Complex x1, x2, val;
-
- x1 = cart2complex(-c.imag, c.real);
- x2 = cart2complex(c.imag, -c.real);
- val = cadd(cexp(x1), cexp(x2));
- return(cart2complex(val.real / 2.0, val.imag / 2.0));
- }
-
- LOCAL Complex XNEAR ctan(c)
- Complex c;
- {
- Complex e1, e2, val;
-
- e1 = cexp(cart2complex(-c.imag, c.real));
- e2 = cexp(cart2complex(c.imag, -c.real));
- val = cdiv(csub(e1, e2), cadd(e1, e2));
- return(cart2complex(val.imag, -val.real));
- }
-
- LOCAL Complex XNEAR casin(c)
- Complex c;
- {
- Complex sx, ix, val;
-
- sx = cmul(c, c);
- sx = csqrt(cart2complex(1.0 - sx.real, - sx.imag));
- ix = cart2complex(-c.imag, c.real);
- val = clog(cadd(ix, sx));
- return(cart2complex(val.imag, -val.real));
- }
-
- LOCAL Complex XNEAR cacos(c)
- Complex c;
- {
- Complex sx, val;
-
- sx = cmul(c, c);
- sx = csqrt(cart2complex(1.0 - sx.real, - sx.imag));
- sx = cart2complex(-sx.imag, sx.real);
- val = clog(cadd(c, sx));
- return(cart2complex(val.imag, -val.real));
- }
-
- LOCAL Complex XNEAR catan(c)
- Complex c;
- {
- #if 0 /* This has been redefined in Jan 1989 */
- Complex sx, ix, val, one;
-
- sx = cmul(c, c);
- sx = cart2complex(1.0 + sx.real, sx.imag);
- one = cart2complex(1.0, 0.0);
- sx = csqrt(cdiv(one, sx));
- ix = cadd(one, cart2complex(-c.imag, c.real));
- val = clog(cmul(ix, sx));
- return(cart2complex(val.imag, -val.real));
- #else
- Complex sx, ix;
-
- sx = clog(cart2complex(1.0-c.imag, c.real));
- ix = clog(cart2complex(1.0+c.imag, -c.real));
- sx.real -= ix.real; /* complex addition w.o. subroutine call */
- sx.imag -= ix.imag;
- return cdiv(sx,cart2complex(0.0, 2.0));
- #endif
- }
-
- LOCAL Complex XNEAR catan2(n,d) /* by Tom Almy, and a kludge at that */
-
- Complex n, d;
- {
- double tmp;
-
- tmp = modulus(d);
- if (tmp == 0 || modulus(n)/tmp > 1e50 ) { /* worst case */
- tmp = phase(n) - phase(d);
- if (tmp < -PI) tmp += 2.0*PI;
- else if (tmp > PI) tmp -= 2.0*PI;
- return cart2complex(fabs(tmp) > PI/2.0 ? -PI/2.0 : PI/2.0 ,0.0);
- }
- n = cdiv(n,d); /* best case */
- return (catan(n));
- }
-
- /* Helper functions */
-
- LOCAL LVAL XNEAR readnumber(number)
- Number *number;
- {
- LVAL arg = xlgetarg(), real, imag;
-
- if (fixp(arg)) {
- number->mode = IN;
- number->val = getfixnum(arg);
- }
- else if (floatp(arg)) {
- number->mode = FL;
- number->fval = getflonum(arg);
- }
- #ifdef RATIOS
- else if (ratiop(arg)) {
- number->mode = RT;
- number->num = getnumer(arg);
- number->denom = getdenom(arg);
- }
- #endif
- else if (complexp(arg)) {
- real = realpart(arg);
- imag = imagpart(arg);
- if (fixp(real)) {
- number->mode = CI;
- number->crval = getfixnum(real);
- number->cival = getfixnum(imag);
- }
- else {
- number->mode = CF;
- number->cfrval = makefloat(real);
- number->cfival = makefloat(imag);
- }
- }
- else xlerror("not a number", arg);
- return(arg);
- }
-
- LOCAL VOID XNEAR setmode(x, mode)
- Number *x;
- int mode;
- {
- switch (mode) {
- #ifdef RATIOS
- case RT:
- if (x->mode != IN) return;
- x->mode = mode;
- x->num = x->val;
- x->denom = 1;
- break;
- #endif
- case FL:
- if (x->mode == IN) {
- x->mode = mode;
- x->fval = x->val;
- }
- #ifdef RATIOS
- else if (x->mode == RT) {
- x->mode = mode;
- x->fval = x->num / (FLOTYPE) x->denom;
- }
- #endif
- else return;
- break;
- case CI:
- if (x->mode != IN) return;
- x->mode = mode;
- x->crval = x->val;
- x->cival = 0;
- break;
- case CF:
- switch (x->mode) {
- case IN:
- x->mode = mode;
- x->cfrval = x->val;
- x->cfival = 0.0;
- break;
- #ifdef RATIOS
- case RT:
- x->mode = mode;
- x->cfrval = x->num / (FLOTYPE) x->denom;
- x->cfival = 0.0;
- break;
- #endif
- case FL:
- x->mode = mode;
- x->cfrval = x->fval;
- x->cfival = 0.0;
- break;
- case CI:
- x->mode = mode;
- x->cfrval = x->crval;
- x->cfival = x->cival;
- break;
- }
- break;
- }
- }
-
- LOCAL VOID XNEAR matchmodes(x, y)
- Number *x, *y;
- {
- int mode = x->mode;
- switch (mode) {
- case IN: mode = y->mode; break;
- case FL: if (y->mode == CI || y->mode == CF) mode = CF; break;
- #ifdef RATIOS
- case CI: if (y->mode == FL || y->mode == CF || y->mode == RT)
- mode = CF;
- break;
- #else
- case CI: if (y->mode == FL || y->mode == CF) mode = CF; break;
- #endif
- case CF: break;
- #ifdef RATIOS
- case RT: if (y->mode == CI) mode = CF;
- else if (y->mode != IN) mode = y->mode;
- break;
- #endif
- }
- if (x->mode != mode) setmode(x, mode);
- if (y->mode != mode) setmode(y, mode);
- }
-
- LOCAL LVAL XNEAR lispnumber(x)
- Number *x;
- {
- switch (x->mode) {
- case IN: return(cvfixnum(x->val));
- case FL: return(cvflonum(x->fval));
- case CI: return(newicomplex(x->crval, x->cival));
- case CF: return(newdcomplex(x->cfrval, x->cfival));
- #ifdef RATIOS
- case RT: return(cvratio (x->num, x->denom));
- #endif
- }
- return NIL; /* avoid warning messages */
- }
-
- #ifdef RATIOS
- LOCAL VOID XNEAR add_ratios (n1, d1, n2, d2)
- FIXTYPE *n1, *d1, n2, d2;
- {
- FIXTYPE lcm;
-
- lcm = *d1 * (d2 / xget_gcd(*d1, d2));
- *n1 = *n1 * (lcm / *d1) + n2 * (lcm / d2);
- *d1 = lcm;
- return;
- }
-
- LOCAL VOID XNEAR mult_ratios (n1, d1, n2, d2)
- FIXTYPE *n1, *d1, n2, d2;
- {
- FIXTYPE gcd;
-
- if ((*n1 *= n2) == 0) return;
- gcd = xget_gcd (*n1, *d1 *= d2);
- *n1 /= gcd;
- *d1 /= gcd;
- return;
- }
- #endif
-
- LOCAL LVAL XNEAR binary(which)
- int which;
- {
- LVAL larg;
- Number val, arg;
- FIXTYPE rtemp, itemp;
- FLOTYPE frtemp, fitemp;
-
- if (xlargc == 1 && (which == '-' || which == '/')) {
- val.mode = IN;
- switch (which) {
- case '-': val.val = 0; break;
- case '/': val.val = 1; break;
- }
- }
- else larg = readnumber(&val);
- while (moreargs()) {
- larg = readnumber(&arg);
- matchmodes(&val, &arg);
- switch (which) {
- case '+':
- switch (val.mode) {
- case IN: val.val += arg.val; break;
- case FL: val.fval += arg.fval; break;
- case CI: val.crval += arg.crval; val.cival += arg.cival; break;
- case CF: val.cfrval += arg.cfrval; val.cfival += arg.cfival; break;
- #ifdef RATIOS
- case RT:
- add_ratios (&val.num, &val.denom, arg.num, arg.denom);
- break;
- #endif
- }
- break;
- case '-':
- switch (val.mode) {
- case IN: val.val -= arg.val; break;
- case FL: val.fval -= arg.fval; break;
- case CI: val.crval -= arg.crval; val.cival -= arg.cival; break;
- case CF: val.cfrval -= arg.cfrval; val.cfival -= arg.cfival; break;
- #ifdef RATIOS
- case RT:
- add_ratios (&val.num, &val.denom, -arg.num, arg.denom);
- break;
- #endif
- }
- break;
- case '*':
- switch (val.mode) {
- case IN: val.val *= arg.val; break;
- case FL: val.fval *= arg.fval; break;
- case CI:
- rtemp = val.crval * arg.crval - val.cival * arg.cival;
- itemp = val.cival * arg.crval + val.crval * arg.cival;
- val.crval = rtemp; val.cival = itemp;
- break;
- case CF:
- frtemp = val.cfrval * arg.cfrval - val.cfival * arg.cfival;
- fitemp = val.cfival * arg.cfrval + val.cfrval * arg.cfival;
- val.cfrval = frtemp; val.cfival = fitemp;
- break;
- #ifdef RATIOS
- case RT:
- mult_ratios (&val.num, &val.denom, arg.num, arg.denom);
- break;
- #endif
- }
- break;
- case '/':
- switch (val.mode) {
- case IN:
- checkizero(arg.val);
- #ifdef RATIOS
- setmode(&val, RT);
- val.denom = arg.val;
- break;
- #else
- if (val.val % arg.val == 0) {
- val.val /= arg.val;
- break;
- }
- else {
- setmode(&val, FL);
- setmode(&arg, FL);
- }
- /* drop through */
- #endif
- case FL:
- checkfzero(arg.fval);
- val.fval /= arg.fval;
- break;
- case CI:
- setmode(&val, CF);
- setmode(&arg, CF);
- /* drop through */
- case CF:
- #if 0 /* we can do better */
- { double magn;
- magn = arg.cfrval * arg.cfrval + arg.cfival * arg.cfival;
- checkfzero(magn);
- frtemp = (val.cfrval * arg.cfrval + val.cfival * arg.cfival) / magn;
- fitemp = (val.cfival * arg.cfrval - val.cfrval * arg.cfival) / magn;
- val.cfrval = frtemp; val.cfival = fitemp;
- break;
- }
- #else
- { double ratio,temp;
- if (fabs(arg.cfrval) > fabs(arg.cfival)) {
- ratio = arg.cfival / arg.cfrval;
- temp = arg.cfrval + ratio*arg.cfival;
- frtemp = (val.cfrval + val.cfival*ratio)/temp;
- fitemp = (val.cfival - val.cfrval*ratio)/temp;
- }
- else {
- checkfzero(arg.cfival);
- ratio = arg.cfrval / arg.cfival;
- temp = arg.cfival + ratio*arg.cfrval;
- frtemp = (val.cfrval*ratio + val.cfival)/temp;
- fitemp = (val.cfival*ratio - val.cfrval)/temp;
- }
- val.cfrval = frtemp; val.cfival = fitemp;
- break;
- }
- #endif
- #ifdef RATIOS
- case RT:
- checkizero (arg.num);
- mult_ratios (&val.num, &val.denom, arg.denom, arg.num);
- break;
- #endif
- }
- break;
- case 'M':
- switch (val.mode) {
- case IN: val.val = (val.val > arg.val) ? val.val : arg.val; break;
- case FL: val.fval = (val.fval > arg.fval) ? val.fval : arg.fval; break;
- #ifdef RATIOS
- case RT:
- if ((val.num * arg.denom) < (arg.num * val.denom)) {
- val.num = arg.num;
- val.denom = arg.denom;
- }
- break;
- #endif
- default: xlbadtype(larg);
- }
- break;
- case 'm':
- switch (val.mode) {
- case IN: val.val = (val.val < arg.val) ? val.val : arg.val; break;
- case FL: val.fval = (val.fval < arg.fval) ? val.fval : arg.fval; break;
- #ifdef RATIOS
- case RT:
- if ((val.num * arg.denom) > (arg.num * val.denom)) {
- val.num = arg.num;
- val.denom = arg.denom;
- }
- break;
- #endif
- default: xlbadtype(larg);
- }
- break;
- }
- }
- return(lispnumber(&val));
- }
-
-
- /* This has been completely rewritten by Tom Almy to handle floating point
- arguments */
-
- LVAL xrem()
- {
- Number numer, div;
- double ftemp;
-
- readnumber(&numer);
- readnumber(&div);
- xllastarg();
-
- matchmodes(&numer, &div);
-
- switch (numer.mode) {
- case IN: checkizero(div.val);
- return (cvfixnum((FIXTYPE) numer.val % div.val));
- case FL: checkfzero(div.fval);
- modf(numer.fval / div.fval, &ftemp);
- return (cvflonum((FLOTYPE)(numer.fval - ftemp*div.fval)));
- #ifdef RATIOS
- case RT: checkizero(div.num);
- mult_ratios(&numer.num, &numer.denom, div.denom, div.num);
- numer.num %= numer.denom; /* get remainder */
- mult_ratios(&numer.num, &numer.denom, div.num, div.denom);
- return (cvratio(numer.num, numer.denom));
- #endif
- }
- badcop();
- return NIL; /* fool compiler into not giving warning */
- }
-
-
- LVAL xash() /* arithmetic shift left */
- {
- FIXTYPE arg, val;
-
- arg = getfixnum(xlgafixnum());
- val = getfixnum(xlgafixnum());
- xllastarg();
-
- return cvfixnum(val < 0 ? arg >> -val : arg << val);
- }
-
-
- LOCAL LVAL XNEAR logbinary(which)
- int which;
- {
- FIXTYPE val, arg; /* TAA Mod -- was int */
-
- switch (which) {
- case '&': val = -1; break;
- case '|': val = 0; break;
- case '^': val = 0; break;
- }
- while (moreargs()) {
- arg = getfixnum(xlgafixnum());
- switch (which) {
- case '&': val &= arg; break;
- case '|': val |= arg; break;
- case '^': val ^= arg; break;
- }
- }
- return(cvfixnum((FIXTYPE) val));
- }
-
- /* binary functions */
- /* TAA fix allowing (+) */
- LVAL xadd() { return (moreargs()?binary('+'):cvfixnum((FIXTYPE)0)); }
- LVAL xsub() { return (binary('-')); } /* - */
- /* TAA fix allowing (*) */
- LVAL xmul() { return (moreargs()?binary('*'):cvfixnum((FIXTYPE)1)); }
- LVAL xdiv() { return (binary('/')); } /* / */
- LVAL xmin() { return (binary('m')); } /* min */
- LVAL xmax() { return (binary('M')); } /* max */
- LVAL xlogand() { return (logbinary('&')); } /* logand */
- LVAL xlogior() { return (logbinary('|')); } /* logior */
- LVAL xlogxor() { return (logbinary('^')); } /* logxor */
-
-
- /* New by Tom Almy */
-
- LVAL xmod()
- {
- Number numer, div;
-
- readnumber(&numer);
- readnumber(&div);
- xllastarg();
-
- matchmodes(&numer, &div);
-
- switch (numer.mode) {
- case IN: checkizero(div.val);
- return(cvfixnum(numer.val -
- div.val*(FIXTYPE)floor(numer.val/(double)div.val)));
- case FL: checkfzero(div.fval);
- return(cvflonum((FLOTYPE)(numer.fval -
- div.fval*floor((double)(numer.fval/div.fval)))));
- #ifdef RATIOS
- case RT: checkizero(div.num);
- mult_ratios(&numer.num, &numer.denom, div.denom, div.num);
- numer.num = numer.num - numer.denom*
- (FIXTYPE)floor(numer.num/(double)numer.denom);
- mult_ratios(&numer.num, &numer.denom, div.num, div.denom);
- return (cvratio(numer.num, numer.denom));
- #endif
- }
- badcop();
- return NIL; /* fool compiler into not giving warning */
- }
-
- LVAL xexpt() /* modified for ratios by TAA */
- {
- LVAL base, power;
- int bsign, psign;
- FIXTYPE b, p, val;
- FLOTYPE fb, fp, fval;
-
- base = xlgetarg();
- power = xlgetarg();
- xllastarg();
-
- if (fixp(base) && fixp(power)) {
- b = getfixnum(base);
- p = getfixnum(power);
- if (p == 0) return(cvfixnum((FIXTYPE) 1));
- if (b == 0 && p > 0) return(cvfixnum((FIXTYPE) 0));
- checkizero(b);
- if ((bsign = (b < 0)) != 0) b = -b;
- if ((psign = (p < 0)) != 0) p = -p;
-
- fval = floor(pow((double) b, (double) p) + 0.1); /* to get integer right */
- if (bsign && (p & 1)) fval = -fval;
- if (!psign) {
- val = fval;
- if (val == fval) return(cvfixnum(val));
- else return(cvflonum((FLOTYPE) fval)); /* to handle precision for large results */
- }
- else {
- #ifdef RATIOS
- val = fval;
- if (val == fval) return (cvratio(1, val));
- else return (cvflonum((FLOTYPE) 1.0 / fval));
- #else
- checkfzero(fval);
- return(cvflonum((FLOTYPE) 1.0 / fval));
- #endif
- }
- }
- #ifdef RATIOS
- else if (ratiop(base) && fixp(power)) {
- FIXTYPE vald; /* integer of denominator result */
- FLOTYPE fvald; /* denominator result */
- b = getnumer(base); /* start with just the numerator */
- p = getfixnum(power);
- if (p == 0) return(cvfixnum((FIXTYPE) 1));
- if ((bsign = (b < 0)) != 0) b = -b;
- if ((psign = (p < 0)) != 0) p = -p;
-
- fval = floor(pow((double) b, (double) p) + 0.1); /* to get integer right */
- if (bsign && (p & 1)) fval = -fval;
-
- fvald = floor(pow((double) getdenom(base), (double) p) + 0.1);
-
- val = fval;
- vald = fvald;
-
- if (!psign) {
- if (val == fval && vald == fvald) /* will fit in ratio */
- return (cvratio(val, vald));
- else return (cvflonum(fval/fvald));
- }
- else {
- if (val == fval && vald == fvald) /* will fit in ratio */
- return (cvratio(vald, val));
- else return (cvflonum(fvald/fval));
- }
- }
- #endif
- else if (floatp(base) && fixp(power)) {
- fb = getflonum(base);
- p = getfixnum(power);
- if (p == 0) return(cvflonum((FLOTYPE) 1.0)); /* TAA MOD - used to return
- fixnum 1, but CL says should be flonum */
- if (fb == 0.0 && p > 0) return(cvflonum((FLOTYPE) 0.0));
- checkfzero(fb);
- if ((bsign = (fb < 0.0)) != 0) fb = -fb;
- if ((psign = (p < 0)) != 0) p = -p;
- fval = pow((double) fb, (double) p);
- if (bsign && (p & 1)) fval = -fval;
- if (!psign) return(cvflonum((FLOTYPE) fval));
- else {
- checkfzero(fval);
- return(cvflonum((FLOTYPE) 1.0 / fval));
- }
- }
- #ifdef RATIOS
- else if (numberp(base) && (ratiop(power) || floatp(power)))
- #else
- else if (numberp(base) && floatp(power))
- #endif
- {
- fb = makefloat(base);
- #ifdef RATIOS
- fp = ratiop(power) ?
- getnumer(power)/(FLOTYPE)getdenom(power) : getflonum(power);
- #else
- fp = getflonum(power);
- #endif
- if (fp == 0.0) return(cvflonum((FLOTYPE) 1.0));
- if (fb == 0.0 && fp > 0.0) return(cvflonum((FLOTYPE) 0.0));
- if (fb < 0.0)
- return(cvcomplex(cexpt(makecomplex(base), makecomplex(power))));
- if ((psign = (fp < 0.0)) != 0) fp = -fp;
- fval = pow((double) fb, (double) fp);
- if (!psign) return(cvflonum((FLOTYPE) fval));
- else {
- checkfzero(fval);
- return(cvflonum((FLOTYPE) 1.0 / fval));
- }
- }
- else if (complexp(base) || complexp(power))
- return(cvcomplex(cexpt(makecomplex(base), makecomplex(power))));
- else xlfail("bad argument type(s)");
- return NIL; /* avoid compiler warnings */
- }
-
- /* arc tangent -- Tom Almy */
- LVAL xatan()
- {
- Number numer, denom;
- LVAL lnum, ldenom;
- Complex cnum, cdenom;
-
- lnum = readnumber(&numer);
-
- if (moreargs()) {
- ldenom = readnumber(&denom);
- xllastarg();
- matchmodes(&numer, &denom);
-
- switch (numer.mode) {
- case IN:
- numer.fval = numer.val; denom.fval = denom.val;
- case FL:
- return (cvflonum((FLOTYPE)atan2(numer.fval, denom.fval)));
- #ifdef RATIOS
- case RT:
- return (cvflonum((FLOTYPE)atan2(numer.num/(FLOTYPE)numer.denom,
- denom.num/(FLOTYPE)denom.denom)));
- #endif
- default: /* complex */
- cnum = makecomplex(lnum);
- cdenom = makecomplex(ldenom);
- return (cvcomplex(catan2(cnum,cdenom)));
- }
- }
- else {
- switch (numer.mode) {
- case IN:
- numer.fval = numer.val;
- case FL:
- return (cvflonum((FLOTYPE)atan(numer.fval)));
- #ifdef RATIOS
- case RT:
- return (cvflonum((FLOTYPE)atan(numer.num/(FLOTYPE)numer.denom)));
- #endif
- default: /* complex */
- cnum = makecomplex(lnum);
- return (cvcomplex(catan(cnum)));
- }
- }
- }
-
-
-
- /* two argument logarithm */
- LOCAL double XNEAR logarithm(x, base, base_supplied)
- FLOTYPE x, base;
- int base_supplied;
- {
- double lbase;
- if (x <= 0.0) xlfail("logarithm of a nonpositive number");
- if (base_supplied) {
- if (base <= 0.0) xlfail("logarithm to a nonpositive base");
- else {
- lbase = log(base);
- if (lbase == 0.0) xlfail("logarith to a unit base");
- else return((log(x)/lbase));
- }
- }
- return (log(x));
- }
-
- LVAL xlog()
- {
- LVAL arg, base;
- int base_supplied = FALSE;
- double fx, fb;
-
- arg = xlgetarg();
- if (moreargs()) {
- base_supplied = TRUE;
- base = xlgetarg();
- }
- if (base_supplied) {
- if (numberp(arg) && numberp(base)) {
- fx = makefloat(arg);
- fb = makefloat(base);
- if (fx <= 0.0 || fb <= 0.0)
- return(cvcomplex(cdiv(clog(makecomplex(arg)), clog(makecomplex(base)))));
- else return(cvflonum((FLOTYPE) logarithm(fx, fb, TRUE)));
- }
- else if ((numberp(arg) && complexp(base))
- || (complexp(arg) && numberp(base))
- || (complexp(arg) && complexp(base)))
- return(cvcomplex(cdiv(clog(makecomplex(arg)), clog(makecomplex(base)))));
- else xlfail("bad argument type(s)");
- }
- else {
- if (numberp(arg)) {
- fx = makefloat(arg);
- if (fx <= 0.0) return(cvcomplex(clog(makecomplex(arg))));
- else return(cvflonum((FLOTYPE) logarithm(fx, 0.0, FALSE)));
- }
- else if (complexp(arg))
- return(cvcomplex(clog(makecomplex(arg))));
- else xlfail("bad argument type(s)");
- }
- return NIL; /* avoid compiler warnings */
- }
-
- /* TAA Mod to return FIXTYPE */
- LOCAL FIXTYPE XNEAR xget_gcd(n,m) /* euclid's algorith */
- FIXTYPE n, m;
- {
- FIXTYPE r;
-
- for (;;) {
- r = m % n;
- if (r == (FIXTYPE) 0)
- break;
- m = n;
- n = r;
- }
-
- return (n);
- }
-
- /* xgcd - greatest common divisor */
- LVAL xgcd()
- {
- FIXTYPE m,n;
- LVAL arg;
-
- if (!moreargs()) /* check for identity case */
- return (cvfixnum((FIXTYPE)0));
- arg = xlgafixnum();
- n = getfixnum(arg);
- if (n < (FIXTYPE)0) n = -n; /* absolute value */
- while (moreargs()) {
- arg = xlgafixnum();
- m = getfixnum(arg);
- if (m == 0 || n == 0) xlfail("zero argument");
- if (m < (FIXTYPE)0) m = -m; /* absolute value */
-
- n = xget_gcd(n,m);
- }
- return (cvfixnum(n));
- }
-
- LVAL xlcm() /* added by kcw */
- {
- LVAL arg;
- FIXTYPE n, m, t, g;
-
- arg = xlgafixnum();
- n = getfixnum(arg);
- if (!moreargs()) {
- if (n < (FIXTYPE) 0) n = -n;
- return (cvfixnum(n));
- }
-
- while (moreargs()) {
- arg = xlgafixnum();
- m = getfixnum(arg);
- if ((n == (FIXTYPE) 0) || (m == (FIXTYPE) 0))
- return(cvfixnum(0));
-
- t = n * m;
- g = xget_gcd(n,m);
-
- n = (FIXTYPE) t / g;
- }
-
- if (n < (FIXTYPE) 0) n = -n;
-
- return (cvfixnum(n));
- }
-
- #ifndef RANDOM
- LOCAL long rseed=1L;
- #endif
-
- /* unary - handle unary operations */
- LOCAL LVAL XNEAR unary(which)
- int which;
- {
- FLOTYPE fval;
- FIXTYPE ival;
- #ifdef RATIOS
- FIXTYPE numer, denom;
- #endif
- Complex cval;
- LVAL arg, real, imag;
- int mode;
-
- /* get the argument */
- arg = xlgetarg();
- if (which == 'F' && moreargs()) { /*TAA MOD to eliminate compiler warnings*/
- if (floatp(*xlargv)) xlargc--;
- else xlbadtype(*xlargv);
- }
- xllastarg();
-
- /* check its type */
- if (fixp(arg)) {
- ival = getfixnum(arg);
- mode = IN;
- }
- else if (floatp(arg)) {
- fval = getflonum(arg);
- mode = FL;
- }
- #ifdef RATIOS
- else if (ratiop(arg)) {
- numer = getnumer(arg);
- denom = getdenom(arg);
- mode = RT;
- }
- #endif
- else if (complexp(arg)) {
- cval = makecomplex(arg);
- real = realpart(arg);
- imag = imagpart(arg);
- if (fixp(realpart(arg))) mode = CI;
- else mode = CF;
- }
- else xlerror("not a number", arg);
-
- switch (which) {
- case '~':
- if (mode == IN) return(cvfixnum((FIXTYPE) ~ival));
- else badiop();
- break;
- case 'A':
- switch (mode) {
- case IN: return(cvfixnum((FIXTYPE) (ival < 0 ? -ival : ival)));
- case FL: return(cvflonum((FLOTYPE) (fval < 0.0 ? -fval : fval)));
- case CI:
- case CF: return(cvflonum((FLOTYPE) modulus(cval)));
- #ifdef RATIOS
- case RT: return(cvratio(numer<0?-numer:numer,denom));
- #endif
- }
- break;
- case '+':
- switch (mode) {
- case IN: return(cvfixnum((FIXTYPE) ival + 1));
- case FL: return(cvflonum((FLOTYPE) fval + 1.0));
- case CI: return(newicomplex(getfixnum(real) + 1, getfixnum(imag)));
- case CF: return(newdcomplex(getflonum(real) + 1.0, getflonum(imag)));
- #ifdef RATIOS
- case RT: return(cvratio(numer+denom, denom));
- #endif
- }
- break;
- case '-':
- switch (mode) {
- case IN: return(cvfixnum((FIXTYPE) ival - 1));
- case FL: return(cvflonum((FLOTYPE) fval - 1.0));
- case CI: return(newicomplex(getfixnum(real) - 1, getfixnum(imag)));
- case CF: return(newdcomplex(getflonum(real) - 1.0, getflonum(imag)));
- #ifdef RATIOS
- case RT: return(cvratio(numer-denom, denom));
- #endif
- }
- break;
- case 'S':
- switch (mode) {
- case IN: return(cvflonum((FLOTYPE) sin((double) ival)));
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom;
- #endif
- case FL: return(cvflonum((FLOTYPE) sin((double) fval)));
- case CI:
- case CF: return(cvcomplex(csin(cval)));
- }
- case 'C':
- switch (mode) {
- case IN: return(cvflonum((FLOTYPE) cos((double) ival)));
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom;
- #endif
- case FL: return(cvflonum((FLOTYPE) cos((double) fval)));
- case CI:
- case CF: return(cvcomplex(ccos(cval)));
- }
- case 'T':
- switch (mode) {
- case IN: return(cvflonum((FLOTYPE) tan((double) ival)));
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom;
- #endif
- case FL: return(cvflonum((FLOTYPE) tan((double) fval)));
- case CI:
- case CF: return(cvcomplex(ctan(cval)));
- }
- case 'E':
- switch (mode) {
- case IN: return(cvflonum((FLOTYPE) exp((double) ival)));
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom;
- #endif
- case FL: return(cvflonum((FLOTYPE) exp((double) fval)));
- case CI:
- case CF: return(cvcomplex(cexp(cval)));
- }
- break;
- case 'R':
- switch (mode) {
- case IN:
- if (ival < 0) return(cvcomplex(csqrt(makecomplex(arg))));
- else return(cvflonum((FLOTYPE) sqrt((double) ival)));
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom;
- #endif
- case FL:
- if (fval < 0) return(cvcomplex(csqrt(makecomplex(arg))));
- else return(cvflonum((FLOTYPE) sqrt(fval)));
- case CI:
- case CF: return(cvcomplex(csqrt(cval)));
- }
- break;
- case 'F':
- switch (mode) {
- case IN: return (cvflonum((FLOTYPE) ival));
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom;
- #endif
- case FL: return (cvflonum((FLOTYPE) fval));
- default: badcop();
- }
- break;
- #ifndef RANDOM
- case '?':
- switch (mode) {
- case IN: return (cvfixnum((FIXTYPE)(rseed=osrand(rseed)) % ival));
- case FL: badfop();
- default: badcop();
- }
- break;
- #endif
- case 's':
- switch (mode) {
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom; goto l1;
- #endif
- case IN:
- fval = ival;
- /* drop through */
- case FL:
- #ifdef RATIOS
- l1:
- #endif
- if (fval > 1.0 || fval < -1.0)
- return(cvcomplex(casin(makecomplex(arg))));
- else return(cvflonum((FLOTYPE) asin(fval)));
- case CI:
- case CF: return(cvcomplex(casin(cval)));
- }
- break;
- case 'c':
- switch (mode) {
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom; goto l2;
- #endif
- case IN:
- fval = ival;
- /* drop through */
- case FL:
- #ifdef RATIOS
- l2:
- #endif
- if (fval > 1.0 || fval < -1.0)
- return(cvcomplex(cacos(makecomplex(arg))));
- else return(cvflonum((FLOTYPE) acos(fval)));
- case CI:
- case CF: return(cvcomplex(cacos(cval)));
- }
- break;
- case 'P':
- switch (mode) {
- case IN: return(cvflonum((FLOTYPE) (ival >= 0) ? 0.0 : PI));
- #ifdef RATIOS
- case RT: fval = numer / (FLOTYPE) denom;
- #endif
- case FL: return(cvflonum((FLOTYPE) (fval >= 0.0) ? 0.0 : PI));
- case CI:
- case CF: return(cvflonum((FLOTYPE) phase(cval)));
- }
- break;
- default: xlfail("unsupported operation");
- }
- return NIL; /* avoid compiler warning */
- }
-
- LOCAL LVAL XNEAR unary2(which) /* handle truncate, floor, ceiling, and round */
- /* 1 or two arguments */
- /* By Tom Almy */
- int which;
- {
- Number numer, denom;
- LVAL lval;
-
- lval = readnumber(&numer);
-
- if (moreargs()) { /* two argument version */
- readnumber(&denom);
- xllastarg();
- matchmodes(&numer, &denom);
-
- switch (numer.mode) {
- case IN:
- checkizero(denom.val);
- numer.fval = numer.val / (double)denom.val;
- break;
- case FL:
- checkfzero(denom.fval);
- numer.fval /= denom.fval;
- break;
- #ifdef RATIOS
- case RT:
- checkizero(denom.num);
- numer.fval = ((FLOTYPE)numer.num * denom.denom) /
- ((FLOTYPE)numer.denom * denom.num);
- break;
- #endif
- default: badcop();
- }
- }
- else { /* single argument version */
- switch (numer.mode) {
- case IN: return lval; /* no-operation */
- case FL: break; /* continue */
- #ifdef RATIOS
- case RT: numer.fval = numer.num / (FLOTYPE) numer.denom;
- break;
- #endif
- default: badcop();
- }
- }
- switch (which) { /* now do it! */
- case 'I': modf(numer.fval,&numer.fval); break;
- case '_': numer.fval = floor(numer.fval); break;
- case '^': numer.fval = ceil(numer.fval); break;
- case 'r': numer.fval = floor(numer.fval + 0.5); break;
- }
- if (fabs(numer.fval) > (double)MAXFIX)
- return cvflonum((FLOTYPE)numer.fval);
- return cvfixnum((FIXTYPE)numer.fval);
- }
-
- /* unary functions */
- LVAL xlognot() { return (unary('~')); } /* lognot */
- LVAL xabs() { return (unary('A')); } /* abs */
- LVAL xadd1() { return (unary('+')); } /* 1+ */
- LVAL xsub1() { return (unary('-')); } /* 1- */
- LVAL xsin() { return (unary('S')); } /* sin */
- LVAL xcos() { return (unary('C')); } /* cos */
- LVAL xtan() { return (unary('T')); } /* tan */
- LVAL xexp() { return (unary('E')); } /* exp */
- LVAL xsqrt() { return (unary('R')); } /* sqrt */
- LVAL xfloat() { return (unary('F')); } /* float */
- #ifndef RANDOM
- LVAL xrand() { return (unary('?')); } /* random */
- #endif
- LVAL xasin() { return (unary('s')); } /* asin */
- LVAL xacos() { return (unary('c')); } /* acos */
- LVAL xphase() { return (unary('P')); } /* phase */
- LVAL xfix() { return (unary2('I')); } /* truncate */
- LVAL xfloor() { return (unary2('_')); } /* floor */
- LVAL xceil() { return (unary2('^')); } /* ceiling */
- LVAL xround() { return (unary2('r')); } /* round */
-
-
- /* predicate - handle a predicate function */
- LOCAL LVAL XNEAR predicate(fcn)
- int fcn;
- {
- FLOTYPE fval;
- FIXTYPE ival;
- LVAL arg;
-
- /* get the argument */
- arg = xlgetarg();
- xllastarg();
-
- /* check the argument type */
- if (fixp(arg)) {
- ival = getfixnum(arg);
- switch (fcn) {
- case '-': ival = (ival < 0); break;
- case 'Z': ival = (ival == 0); break;
- case '+': ival = (ival > 0); break;
- case 'E': ival = ((ival & 1) == 0); break;
- case 'O': ival = ((ival & 1) != 0); break;
- default: badiop();
- }
- }
- else if (floatp(arg)) {
- fval = getflonum(arg);
- switch (fcn) {
- case '-': ival = (fval < 0); break;
- case 'Z': ival = (fval == 0); break;
- case '+': ival = (fval > 0); break;
- default: badfop();
- }
- }
- #ifdef RATIOS
- else if (ratiop(arg)) {
- switch (fcn) {
- case '-': ival = (getnumer(arg) < 0); break;
- case 'Z': ival = FALSE; break; /* can't be zero! */
- case '+': ival = (getnumer(arg) > 0); break;
- default: badrop();
- }
- }
- #endif
- else
- xlerror("bad argument type",arg);
-
- /* return the result value */
- return (ival ? true : NIL);
- }
-
- /* unary predicates */
- LVAL xminusp() { return (predicate('-')); } /* minusp */
- LVAL xzerop() { return (predicate('Z')); } /* zerop */
- LVAL xplusp() { return (predicate('+')); } /* plusp */
- LVAL xevenp() { return (predicate('E')); } /* evenp */
- LVAL xoddp() { return (predicate('O')); } /* oddp */
-
-
- /* compare - common compare function */
- LOCAL LVAL XNEAR compare(fcn)
- int fcn;
- {
- FIXTYPE icmp,ival,iarg;
- FLOTYPE fcmp,fval,farg;
- LVAL arg;
- int mode;
-
- /* get the first argument */
- arg = xlgetarg();
-
- /* set the type of the first argument */
- if (fixp(arg)) {
- ival = getfixnum(arg);
- mode = 'I';
- }
- else if (floatp(arg)) {
- fval = getflonum(arg);
- mode = 'F';
- }
- #ifdef RATIOS
- else if (ratiop(arg)) {
- fval = getnumer(arg) / (FLOTYPE) getdenom(arg);
- mode = 'F';
- }
- #endif
- else
- xlerror("bad argument type",arg);
-
- /* handle each remaining argument */
- for (icmp = TRUE; icmp && moreargs(); ival = iarg, fval = farg) {
-
- /* get the next argument */
- arg = xlgetarg();
-
- /* check its type */
- if (fixp(arg)) {
- switch (mode) {
- case 'I':
- iarg = getfixnum(arg);
- break;
- case 'F':
- farg = (FLOTYPE)getfixnum(arg);
- break;
- }
- }
- else if (floatp(arg)) {
- switch (mode) {
- case 'I':
- fval = (FLOTYPE)ival;
- farg = getflonum(arg);
- mode = 'F';
- break;
- case 'F':
- farg = getflonum(arg);
- break;
- }
- }
- #ifdef RATIOS
- else if (ratiop(arg)) {
- switch (mode) {
- case 'I':
- fval = (FLOTYPE)ival;
- case 'F':
- farg = getnumer(arg) / (FLOTYPE) getdenom(arg);
- mode = 'F';
- break;
- }
- }
- #endif
- else
- xlerror("bad argument type",arg);
-
- /* compute result of the compare */
- switch (mode) {
- case 'I':
- icmp = ival - iarg;
- switch (fcn) {
- case '<': icmp = (icmp < 0); break;
- case 'L': icmp = (icmp <= 0); break;
- case '=': icmp = (icmp == 0); break;
- case '#': icmp = (icmp != 0); break;
- case 'G': icmp = (icmp >= 0); break;
- case '>': icmp = (icmp > 0); break;
- }
- break;
- case 'F':
- fcmp = fval - farg;
- switch (fcn) {
- case '<': icmp = (fcmp < 0.0); break;
- case 'L': icmp = (fcmp <= 0.0); break;
- case '=': icmp = (fcmp == 0.0); break;
- case '#': icmp = (fcmp != 0.0); break;
- case 'G': icmp = (fcmp >= 0.0); break;
- case '>': icmp = (fcmp > 0.0); break;
- }
- break;
- }
- }
-
- /* return the result */
- return (icmp ? true : NIL);
- }
-
- LOCAL LVAL XNEAR ccompare(which)
- int which;
- {
- Number val, arg;
- int icmp;
-
- switch (which) {
- case '=': icmp = TRUE; break;
- case '#': icmp = FALSE; break;
- }
- /*larg =*/ readnumber(&val);
- while (moreargs()) {
- /*larg =*/ readnumber(&arg);
- matchmodes(&val, &arg);
- switch (which) {
- case '=':
- switch (val.mode) {
- case IN: icmp = icmp && val.val == arg.val; break;
- case FL: icmp = icmp && val.fval == arg.fval; break;
- case CI: icmp = icmp && val.crval==arg.crval && val.cival==arg.cival;
- break;
- case CF: icmp = icmp && val.cfrval==arg.cfrval && val.cfival==arg.cfival;
- break;
- #ifdef RATIOS
- case RT: icmp = icmp && val.num == arg.num && val.denom == arg.denom;
- break;
- #endif
- }
- break;
- case '#':
- switch (val.mode) {
- case IN: icmp = icmp || val.val != arg.val; break;
- case FL: icmp = icmp || val.fval != arg.fval; break;
- case CI: icmp = icmp || val.crval!=arg.crval || val.cival!=arg.cival;
- break;
- case CF: icmp = icmp || val.cfrval!=arg.cfrval || val.cfival!=arg.cfival;
- break;
- #ifdef RATIOS
- case RT: icmp = icmp || val.num != arg.num || val.denom != arg.denom;
- break;
- #endif
- }
- break;
- }
- }
- return((icmp) ? true : NIL);
- }
-
- /* comparison functions */
- LVAL xlss() { return (compare('<')); } /* < */
- LVAL xleq() { return (compare('L')); } /* <= */
- LVAL xequ() { return (ccompare('=')); } /* = */
- LVAL xneq() { return (ccompare('#')); } /* /= */
- LVAL xgeq() { return (compare('G')); } /* >= */
- LVAL xgtr() { return (compare('>')); } /* > */
-
-
- /***********************************************************************/
- /** **/
- /** Complex Number Functions **/
- /** **/
- /***********************************************************************/
-
- LVAL xcomplex() /* TAA rewrite so (complex 12.0) => #c(12.0 0.0) as required
- by CL. */
- {
- LVAL real, imag;
-
- real = xlgetarg();
-
- if (moreargs()) {
- imag = xlgetarg();
- xllastarg();
- return (newcomplex(real, imag));
- }
- if (fixp(real)) return (real);
- return (newcomplex(real,cvflonum((FLOTYPE)0.0)));
- }
-
- LVAL xconjugate()
- {
- LVAL arg = xlgetarg();
-
- xllastarg();
- if (numberp(arg)) return(arg);
- if (!complexp(arg)) xlbadtype(arg);
- if (fixp(realpart(arg)) && fixp(imagpart(arg)))
- return(newicomplex(getfixnum(realpart(arg)), -getfixnum(imagpart(arg))));
- else
- return(newdcomplex(makefloat(realpart(arg)), -makefloat(imagpart(arg))));
- }
-
- LVAL xrealpart()
- {
- LVAL arg = xlgetarg();
-
- xllastarg();
- if (fixp(arg) || floatp(arg)) return(arg);
- if (!complexp(arg)) xlbadtype(arg);
- return(realpart(arg));
- }
-
- LVAL ximagpart()
- {
- LVAL arg = xlgetarg();
-
- xllastarg();
- if (fixp(arg)) return(cvfixnum((FIXTYPE) 0));
- if (floatp(arg)) return(cvflonum((FLOTYPE) 0.0));
- if (!complexp(arg)) xlbadtype(arg);
- return(imagpart(arg));
- }
-
- #endif
-