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 /scl.c | |
| download | scm-5ca6e8e6a4e5c022a6fb5d28f30219c22c99eda8.tar.gz scm-5ca6e8e6a4e5c022a6fb5d28f30219c22c99eda8.zip  | |
Import Upstream version 4e6upstream/4e6
Diffstat (limited to 'scl.c')
| -rw-r--r-- | scl.c | 2393 | 
1 files changed, 2393 insertions, 0 deletions
@@ -0,0 +1,2393 @@ +/* Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 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.   + */ + +/* "scl.c" non-IEEE utility functions and non-integer arithmetic. +   Authors: Jerry D. Hedden and Aubrey Jaffer */ + +#include "scm.h" + +#ifdef FLOATS +# include <math.h> + +static char s_makrect[] = "make-rectangular", s_makpolar[] = "make-polar", +	    s_magnitude[] = "magnitude", s_angle[] = "angle", +	    s_real_part[] = "real-part", s_imag_part[] = "imag-part", +	    s_in2ex[] = "inexact->exact"; +static char s_expt[] = "$expt", s_atan2[] = "$atan2"; +static char s_memv[] = "memv", s_assv[] = "assv"; +#endif + +SCM sys_protects[NUM_PROTECTS]; +sizet num_protects = NUM_PROTECTS; + +char		s_inexactp[] = "inexact?"; +static char     s_zerop[] = "zero?", +		s_positivep[] = "positive?", s_negativep[] = "negative?"; +static char     s_eqp[] = "=", s_lessp[] = "<", s_grp[] = ">"; +static char     s_leqp[] = "<=", s_greqp[] = ">="; +static char     s_max[] = "max", s_min[] = "min"; +char		s_sum[] = "+", s_difference[] = "-", s_product[] = "*", +		s_divide[] = "/"; +static char     s_number2string[] = "number->string", +		s_str2number[] = "string->number"; + +static char s_list_tail[] = "list-tail"; +static char s_str2list[] = "string->list"; +static char s_st_copy[] = "string-copy", s_st_fill[] = "string-fill!"; +static char s_vect2list[] = "vector->list", s_ve_fill[] = "vector-fill!"; + +/*** NUMBERS -> STRINGS ***/ +#ifdef FLOATS +int dblprec; +static double fx[] = {0.0, 5e-1, 5e-2, 5e-3, 5e-4, 5e-5, +			   5e-6, 5e-7, 5e-8, 5e-9, 5e-10, +			   5e-11,5e-12,5e-13,5e-14,5e-15, +			   5e-16,5e-17,5e-18,5e-19,5e-20}; + +static sizet idbl2str(f, a) +     double f; +char *a; +{ +  int efmt, dpt, d, i, wp = dblprec; +  sizet ch = 0; +  int exp = 0; + +  if (f==0.0) goto zero;	/*{a[0]='0'; a[1]='.'; a[2]='0'; return 3;}*/ +  if (f < 0.0) {f = -f;a[ch++]='-';} +  else if (f > 0.0) ; +  else goto funny; +  if IS_INF(f) { +    if (ch==0) a[ch++]='+'; +  funny: a[ch++]='#'; a[ch++]='.'; a[ch++]='#'; return ch; +  } +# ifdef DBL_MIN_10_EXP		/* Prevent unnormalized values, as from +			make-uniform-vector, from causing infinite loops. */ +  while (f < 1.0) {f *= 10.0;  if (exp-- < DBL_MIN_10_EXP) goto funny;} +  while (f > 10.0) {f *= 0.10; if (exp++ > DBL_MAX_10_EXP) goto funny;} +# else +  while (f < 1.0) {f *= 10.0; exp--;} +  while (f > 10.0) {f /= 10.0; exp++;} +# endif +  if (f+fx[wp] >= 10.0) {f = 1.0; exp++;} + zero: +# ifdef ENGNOT +  dpt = (exp+9999)%3; +  exp -= dpt++; +  efmt = 1; +# else +  efmt = (exp < -3) || (exp > wp+2); +  if (!efmt) +    if (exp < 0) { +      a[ch++] = '0'; +      a[ch++] = '.'; +      dpt = exp; +      while (++dpt)  a[ch++] = '0'; +    } else +      dpt = exp+1; +  else +    dpt = 1; +# endif + +  do { +    d = f; +    f -= d; +    a[ch++] = d+'0'; +    if (f < fx[wp])  break; +    if (f+fx[wp] >= 1.0) { +      a[ch-1]++; +      break; +    } +    f *= 10.0; +    if (!(--dpt))  a[ch++] = '.'; +  } while (wp--); + +  if (dpt > 0) +# ifndef ENGNOT +    if ((dpt > 4) && (exp > 6)) { +      d = (a[0]=='-'?2:1); +      for (i = ch++; i > d; i--) +	a[i] = a[i-1]; +      a[d] = '.'; +      efmt = 1; +    } else +# endif +      { +	while (--dpt)  a[ch++] = '0'; +	a[ch++] = '.'; +      } +  if (a[ch-1]=='.')  a[ch++]='0'; /* trailing zero */ +  if (efmt && exp) { +    a[ch++] = 'e'; +    if (exp < 0) { +      exp = -exp; +      a[ch++] = '-'; +    } +    for (i = 10; i <= exp; i *= 10); +    for (i /= 10; i; i /= 10) { +      a[ch++] = exp/i + '0'; +      exp %= i; +    } +  } +  return ch; +} + +static sizet iflo2str(flt, str) +     SCM flt; +     char *str; +{ +  sizet i; +# ifdef SINGLES +  if SINGP(flt) i = idbl2str(FLO(flt), str); +  else +# endif +    i = idbl2str(REAL(flt), str); +  if CPLXP(flt) { +              if(0 <= IMAG(flt)) /* jeh */ +                str[i++] = '+'; /* jeh */ +    i += idbl2str(IMAG(flt), &str[i]); +    str[i++] = 'i'; +  } +  return i; +} +#endif				/* FLOATS */ + +sizet iint2str(num, rad, p) +     long num; +     int rad; +     char *p; +{ +  sizet j; +  register int i = 1, d; +  register long n = num; +  if (n < 0) {n = -n; i++;} +  for (n /= rad;n > 0;n /= rad) i++; +  j = i; +  n = num; +  if (n < 0) {n = -n; *p++ = '-'; i--;} +  while (i--) { +    d = n % rad; +    n /= rad; +    p[i] = d + ((d < 10) ? '0' : 'a' - 10); +  } +  return j; +} +#ifdef BIGDIG +static SCM big2str(b, radix) +     SCM b; +     register unsigned int radix; +{ +  SCM t = copybig(b, 0);	/* sign of temp doesn't matter */ +  register BIGDIG *ds = BDIGITS(t); +  sizet i = NUMDIGS(t); +  sizet j = radix==16 ? (BITSPERDIG*i)/4+2 +    : radix >= 10 ? (BITSPERDIG*i*241L)/800+2 +      : (BITSPERDIG*i)+2; +  sizet k = 0; +  sizet radct = 0; +      sizet ch; /* jeh */ +  BIGDIG radpow = 1, radmod = 0; +  SCM ss = makstr((long)j); +  char *s = CHARS(ss), c; +  while ((long) radpow * radix < BIGRAD) { +    radpow *= radix; +    radct++; +  } +  s[0] = tc16_bigneg==TYP16(b) ? '-' : '+'; +  while ((i || radmod) && j) { +    if (k==0) { +      radmod = (BIGDIG)divbigdig(ds, i, radpow); +      k = radct; +      if (!ds[i-1]) i--; +    } +    c = radmod % radix; radmod /= radix; k--; +    s[--j] = c < 10 ? c + '0' : c + 'a' - 10; +  } +      ch = s[0]=='-' ? 1 : 0; /* jeh */ +  if (ch < j) { /* jeh */ +    for(i = j;j < LENGTH(ss);j++) s[ch+j-i] = s[j]; /* jeh */ +    resizuve(ss, (SCM)MAKINUM(ch+LENGTH(ss)-i)); /* jeh */ +  } +  return ss; +} +#endif +SCM number2string(x, radix) +     SCM x, radix; +{ +  if UNBNDP(radix) radix=MAKINUM(10L); +  else ASSERT(INUMP(radix), radix, ARG2, s_number2string); +#ifdef FLOATS +  if NINUMP(x) { +    char num_buf[FLOBUFLEN]; +# ifdef BIGDIG +    ASRTGO(NIMP(x), badx); +    if BIGP(x) return big2str(x, (unsigned int)INUM(radix)); +#  ifndef RECKLESS +    if (!(INEXP(x))) +    badx: wta(x, (char *)ARG1, s_number2string); +#  endif +# else +    ASSERT(NIMP(x) && INEXP(x), x, ARG1, s_number2string); +# endif +    return makfromstr(num_buf, iflo2str(x, num_buf)); +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_number2string); +    return big2str(x, (unsigned int)INUM(radix)); +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_number2string); +# endif +#endif +  { +    char num_buf[INTBUFLEN]; +    return makfromstr(num_buf, iint2str(INUM(x), (int)INUM(radix), num_buf)); +  } +} +/* These print routines are stubbed here so that repl.c doesn't need +   FLOATS or BIGDIGs conditionals */ +int floprint(sexp, port, writing) +     SCM sexp; +     SCM port; +     int writing; +{ +#ifdef FLOATS +  char num_buf[FLOBUFLEN]; +  lfwrite(num_buf, (sizet)sizeof(char), iflo2str(sexp, num_buf), port); +#else +  ipruk("float", sexp, port); +#endif +  return !0; +} +int bigprint(exp, port, writing) +     SCM exp; +     SCM port; +     int writing; +{ +#ifdef BIGDIG +  exp = big2str(exp, (unsigned int)10); +  lfwrite(CHARS(exp), (sizet)sizeof(char), (sizet)LENGTH(exp), port); +#else +  ipruk("bignum", exp, port); +#endif +  return !0; +} +/*** END nums->strs ***/ + +/*** STRINGS -> NUMBERS ***/ +#ifdef BIGDIG +SCM istr2int(str, len, radix) +     char *str; +     long len; +     register long radix; +{ +  sizet j; +  register sizet k, blen = 1; +  sizet i = 0; +  int c; +  SCM res; +  register BIGDIG *ds; +  register unsigned long t2; + +  if (0 >= len) return BOOL_F;	/* zero length */ +  if (10==radix) j = 1+(84*len)/(BITSPERDIG*25); +  else j = (8 < radix) ? 1+(4*len)/BITSPERDIG : 1+(3*len)/BITSPERDIG; +  switch (str[0]) {		/* leading sign */ +  case '-': +  case '+': if (++i==len) return BOOL_F; /* bad if lone `+' or `-' */ +  } +  res = mkbig(j, '-'==str[0]); +  ds = BDIGITS(res); +  for (k = j;k--;) ds[k] = 0; +  do { +    switch (c = str[i++]) { +    case DIGITS: +      c = c - '0'; +      goto accumulate; +    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': +      c = c-'A'+10; +      goto accumulate; +    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': +      c = c-'a'+10; +    accumulate: +      if (c >= radix) return BOOL_F; /* bad digit for radix */ +      k = 0; +      t2 = c; +    moretodo: +      while(k < blen) { +/*	printf("k = %d, blen = %d, t2 = %ld, ds[k] = %d\n", k, blen, t2, ds[k]);*/ +	t2 += ds[k]*radix; +	ds[k++] = BIGLO(t2); +	t2 = BIGDN(t2); +      } +      ASSERT(blen <= j, (SCM)MAKINUM(blen), OVFLOW, "bignum"); +      if (t2) {blen++; goto moretodo;} +      break; +    default: +      return BOOL_F;		/* not a digit */ +    } +  } while (i < len); +  if (blen * BITSPERDIG/CHAR_BIT <= sizeof(SCM)) +    if INUMP(res = big2inum(res, blen)) return res; +  if (j==blen) return res; +  return adjbig(res, blen); +} +#else +SCM istr2int(str, len, radix) +     register char *str; +     long len; +     register long radix; +{ +  register long n = 0, ln; +  register int c; +  register int i = 0; +  int lead_neg = 0; +  if (0 >= len) return BOOL_F;	/* zero length */ +  switch (*str) {		/* leading sign */ +  case '-': lead_neg = 1; +  case '+': if (++i==len) return BOOL_F; /* bad if lone `+' or `-' */ +  } + +  do { +    switch (c = str[i++]) { +    case DIGITS: +      c = c - '0'; +      goto accumulate; +    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': +      c = c-'A'+10; +      goto accumulate; +    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': +      c = c-'a'+10; +    accumulate: +      if (c >= radix) return BOOL_F; /* bad digit for radix */ +      ln = n; +      n = n * radix - c; +      /* Negation is a workaround for HP700 cc bug */ +      if (n > ln || (-n > -MOST_NEGATIVE_FIXNUM)) goto ovfl; +      break; +    default: +      return BOOL_F;		/* not a digit */ +    } +  } while (i < len); +  if (!lead_neg) if ((n = -n) > MOST_POSITIVE_FIXNUM) goto ovfl; +  return MAKINUM(n); + ovfl:				/* overflow scheme integer */ +  return BOOL_F; +} +#endif + +#ifdef FLOATS +SCM istr2flo(str, len, radix) +     register char *str; +     register long len; +     register long radix; +{ +  register int c, i = 0; +  double lead_sgn; +  double res = 0.0, tmp = 0.0; +  int flg = 0; +  int point = 0; +  SCM second; + +  if (i >= len) return BOOL_F;	/* zero length */ + +  switch (*str) {		/* leading sign */ +  case '-': lead_sgn = -1.0; i++; break; +  case '+': lead_sgn = 1.0; i++; break; +    default : lead_sgn = 0.0; +  } +  if (i==len) return BOOL_F;	/* bad if lone `+' or `-' */ + +  if (str[i]=='i' || str[i]=='I') { /* handle `+i' and `-i'   */ +    if (lead_sgn==0.0) return BOOL_F; /* must have leading sign */ +    if (++i < len) return BOOL_F; /* `i' not last character */ +    return makdbl(0.0, lead_sgn); +  } +  do {				/* check initial digits */ +    switch (c = str[i]) { +    case DIGITS: +      c = c - '0'; +      goto accum1; +    case 'D': case 'E': case 'F': +      if (radix==10) goto out1; /* must be exponent */ +    case 'A': case 'B': case 'C': +      c = c-'A'+10; +      goto accum1; +    case 'd': case 'e': case 'f': +      if (radix==10) goto out1; +    case 'a': case 'b': case 'c': +      c = c-'a'+10; +    accum1: +      if (c >= radix) return BOOL_F; /* bad digit for radix */ +      res = res * radix + c; +      flg = 1;			/* res is valid */ +      break; +    default: +      goto out1; +    } +  } while (++i < len); + out1: + +  /* if true, then we did see a digit above, and res is valid */ +  if (i==len) goto done; + +  /* By here, must have seen a digit, +     or must have next char be a `.' with radix==10 */ +  if (!flg) +    if (!(str[i]=='.' && radix==10)) +      return BOOL_F; + +  while (str[i]=='#') {		/* optional sharps */ +    res *= radix; +    if (++i==len) goto done; +  } + +  if (str[i]=='/') { +    while (++i < len) { +      switch (c = str[i]) { +      case DIGITS: +	c = c - '0'; +	goto accum2; +      case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': +	c = c-'A'+10; +	goto accum2; +      case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': +	c = c-'a'+10; +      accum2: +	if (c >= radix) return BOOL_F; +	tmp = tmp * radix + c; +	break; +      default: +	goto out2; +      } +    } +  out2: +    if (tmp==0.0) return BOOL_F; /* `slash zero' not allowed */ +    if (i < len) +      while (str[i]=='#') {	/* optional sharps */ +	tmp *= radix; +	if (++i==len) break; +      } +    res /= tmp; +    goto done; +  } + +  if (str[i]=='.') {		/* decimal point notation */ +    if (radix != 10) return BOOL_F; /* must be radix 10 */ +    while (++i < len) { +      switch (c = str[i]) { +      case DIGITS: +	point--; +	res = res*10.0 + c-'0'; +	flg = 1; +	break; +      default: +	goto out3; +      } +    } +  out3: +    if (!flg) return BOOL_F;	/* no digits before or after decimal point */ +    if (i==len) goto adjust; +    while (str[i]=='#') {	/* ignore remaining sharps */ +      if (++i==len) goto adjust; +    } +  } + +  switch (str[i]) {		/* exponent */ +  case 'd': case 'D': +  case 'e': case 'E': +  case 'f': case 'F': +  case 'l': case 'L': +  case 's': case 'S': { +    int expsgn = 1, expon = 0; +    if (radix != 10) return BOOL_F; /* only in radix 10 */ +    if (++i==len) return BOOL_F; /* bad exponent */ +    switch (str[i]) { +    case '-':  expsgn=(-1); +    case '+':  if (++i==len) return BOOL_F; /* bad exponent */ +    } +    if (str[i] < '0' || str[i] > '9') return BOOL_F; /* bad exponent */ +    do { +      switch (c = str[i]) { +      case DIGITS: +	expon = expon*10 + c-'0'; +	if (expon > MAXEXP)  return BOOL_F; /* exponent too large */ +	break; +      default: +	goto out4; +      } +    } while (++i < len); +  out4: +    point += expsgn*expon; +  } +  } + + adjust: +  if (point >= 0) +    while (point--)  res *= 10.0; +  else +# ifdef _UNICOS +    while (point++)  res *= 0.1; +# else +    while (point++)  res /= 10.0; +# endif + + done: +  /* at this point, we have a legitimate floating point result */ +  if (lead_sgn==-1.0)  res = -res; +  if (i==len) return makdbl(res, 0.0); + +  if (str[i]=='i' || str[i]=='I') { /* pure imaginary number  */ +    if (lead_sgn==0.0) return BOOL_F; /* must have leading sign */ +    if (++i < len) return BOOL_F; /* `i' not last character */ +    return makdbl(0.0, res); +  } + +  switch (str[i++]) { +  case '-':  lead_sgn = -1.0; break; +  case '+':  lead_sgn = 1.0;  break; +  case '@': {			/* polar input for complex number */ +    /* get a `real' for angle */ +    second = istr2flo(&str[i], (long)(len-i), radix); +    if (!(INEXP(second))) return BOOL_F; /* not `real' */ +    if (CPLXP(second))    return BOOL_F; /* not `real' */ +    tmp = REALPART(second); +    return makdbl(res*cos(tmp), res*sin(tmp)); +  } +  default: return BOOL_F; +  } + +  /* at this point, last char must be `i' */ +  if (str[len-1] != 'i' && str[len-1] != 'I') return BOOL_F; +  /* handles `x+i' and `x-i' */ +  if (i==(len-1))  return makdbl(res, lead_sgn); +  /* get a `ureal' for complex part */ +  second = istr2flo(&str[i], (long)((len-i)-1), radix); +  if (!(INEXP(second))) return BOOL_F; /* not `ureal' */ +  if (CPLXP(second))    return BOOL_F; /* not `ureal' */ +  tmp = REALPART(second); +  if (tmp < 0.0)	return BOOL_F; /* not `ureal' */ +  return makdbl(res, (lead_sgn*tmp)); +} +#endif				/* FLOATS */ + + +SCM istring2number(str, len, radix) +     char *str; +     long len; +     long radix; +{ +  int i = 0; +  char ex = 0; +  char ex_p = 0, rx_p = 0;	/* Only allow 1 exactness and 1 radix prefix */ +  SCM res; +  if (len==1) +    if (*str=='+' || *str=='-') /* Catches lone `+' and `-' for speed */ +      return BOOL_F; + +  while ((len-i) >= 2  &&  str[i]=='#' && ++i) +    switch (str[i++]) { +    case 'b': case 'B':  if (rx_p++) return BOOL_F; radix = 2;  break; +    case 'o': case 'O':  if (rx_p++) return BOOL_F; radix = 8;  break; +    case 'd': case 'D':  if (rx_p++) return BOOL_F; radix = 10; break; +    case 'x': case 'X':  if (rx_p++) return BOOL_F; radix = 16; break; +    case 'i': case 'I':  if (ex_p++) return BOOL_F; ex = 2;     break; +    case 'e': case 'E':  if (ex_p++) return BOOL_F; ex = 1;     break; +    default:  return BOOL_F; +    } + +  switch (ex) { +  case 1: +    return istr2int(&str[i], len-i, radix); +  case 0: +    res = istr2int(&str[i], len-i, radix); +    if NFALSEP(res) return res; +#ifdef FLOATS +  case 2: return istr2flo(&str[i], len-i, radix); +#endif +  } +  return BOOL_F; +} + + +SCM string2number(str, radix) +     SCM str, radix; +{ +  if UNBNDP(radix) radix=MAKINUM(10L); +  else ASSERT(INUMP(radix), radix, ARG2, s_str2number); +  ASSERT(NIMP(str) && STRINGP(str), str, ARG1, s_str2number); +  return istring2number(CHARS(str), LENGTH(str), INUM(radix)); +} +/*** END strs->nums ***/ + +#ifdef FLOATS +SCM makdbl (x, y) +     double x, y; +{ +  SCM z; +  if ((y==0.0) && (x==0.0)) return flo0; +  NEWCELL(z); +  DEFER_INTS; +  if (y==0.0) { +# ifdef SINGLES +    float fx; +#  ifndef SINGLESONLY +    if ((-FLTMAX < x) && (x < FLTMAX) && ((fx=x)==x)) +#  endif +      { +	CAR(z) = tc_flo; +	FLO(z) = x; +	ALLOW_INTS; +	return z; +      } +# endif				/* def SINGLES */ +    CDR(z) = (SCM)must_malloc(1L*sizeof(double), "real"); +    CAR(z) = tc_dblr; +  } +  else { +    CDR(z) = (SCM)must_malloc(2L*sizeof(double), "complex"); +    CAR(z) = tc_dblc; +    IMAG(z) = y; +  } +  REAL(z) = x; +  ALLOW_INTS; +  return z; +} + +SCM eqv(x, y) +     SCM x, y; +{ +  if (x==y) return BOOL_T; +  if IMP(x) return BOOL_F; +  if IMP(y) return BOOL_F; +  /* this ensures that types and length are the same. */ +  if (CAR(x) != CAR(y)) return BOOL_F; +  if NUMP(x) { +# ifdef BIGDIG +    if BIGP(x) return (0==bigcomp(x, y)) ? BOOL_T : BOOL_F; +# endif +    if (REALPART(x) != REALPART(y)) return BOOL_F; +    if (CPLXP(x) && (IMAG(x) != IMAG(y))) return BOOL_F; +    return BOOL_T; +  } +  return BOOL_F; +} +SCM memv(x, lst)			/* m.borza  12.2.91 */ +SCM x, lst; +{ +  for(;NIMP(lst);lst = CDR(lst)) { +    ASRTGO(CONSP(lst), badlst); +    if NFALSEP(eqv(CAR(lst), x)) return lst; +  } +# ifndef RECKLESS +  if (!(NULLP(lst))) +    badlst: wta(lst, (char *)ARG2, s_memv); +# endif +  return BOOL_F; +} +SCM assv(x, alist)		/* m.borza  12.2.91 */ +SCM x, alist; +{ +  SCM tmp; +  for(;NIMP(alist);alist = CDR(alist)) { +    ASRTGO(CONSP(alist), badlst); +    tmp = CAR(alist); +    ASRTGO(NIMP(tmp) && CONSP(tmp), badlst); +    if NFALSEP(eqv(CAR(tmp), x)) return tmp; +  } +# ifndef RECKLESS +  if (!(NULLP(alist))) +    badlst: wta(alist, (char *)ARG2, s_assv); +# endif +  return BOOL_F; +} +#endif				/* FLOATS */ + +SCM list_tail(lst, k) +     SCM lst, k; +{ +  register long i; +  ASSERT(INUMP(k), k, ARG2, s_list_tail); +  i = INUM(k); +  while (i-- > 0) { +    ASSERT(NIMP(lst) && CONSP(lst), lst, ARG1, s_list_tail); +    lst = CDR(lst); +  } +  return lst; +} + +SCM string2list(str) +     SCM str; +{ +  long i; +  SCM res = EOL; +  unsigned char *src; +  ASSERT(NIMP(str) && STRINGP(str), str, ARG1, s_str2list); +  src = UCHARS(str); +  for(i = LENGTH(str)-1;i >= 0;i--) res = cons((SCM)MAKICHR(src[i]), res); +  return res; +} +SCM string_copy(str) +     SCM str; +{ +  ASSERT(NIMP(str) && STRINGP(str), str, ARG1, s_st_copy); +  return makfromstr(CHARS(str), (sizet)LENGTH(str)); +} +SCM string_fill(str, chr) +     SCM str, chr; +{ +  register char *dst, c; +  register long k; +  ASSERT(NIMP(str) && STRINGP(str), str, ARG1, s_st_fill); +  ASSERT(ICHRP(chr), chr, ARG2, s_st_fill); +  c = ICHR(chr); +  dst = CHARS(str); +  for(k = LENGTH(str)-1;k >= 0;k--) dst[k] = c; +  return UNSPECIFIED; +} +SCM vector2list(v) +     SCM v; +{ +  SCM res = EOL; +  long i; +  SCM *data; +  ASSERT(NIMP(v) && VECTORP(v), v, ARG1, s_vect2list); +  data = VELTS(v); +  for(i = LENGTH(v)-1;i >= 0;i--) res = cons(data[i], res); +  return res; +} +SCM vector_fill(v, fill) +     SCM v, fill; +{ +  register long i; +  register SCM *data; +  ASSERT(NIMP(v) && VECTORP(v), v, ARG1, s_ve_fill); +  data = VELTS(v); +  for(i = LENGTH(v)-1;i >= 0;i--) data[i] = fill; +  return UNSPECIFIED; +} +static SCM vector_equal(x, y) +     SCM x, y; +{ +  long i; +  for(i = LENGTH(x)-1;i >= 0;i--) +    if FALSEP(equal(VELTS(x)[i], VELTS(y)[i])) return BOOL_F; +  return BOOL_T; +} +SCM bigequal(x, y) +     SCM x, y; +{ +#ifdef BIGDIG +  if (0==bigcomp(x, y)) return BOOL_T; +#endif +  return BOOL_F; +} +SCM floequal(x, y) +     SCM x, y; +{ +#ifdef FLOATS +  if (REALPART(x) != REALPART(y)) return BOOL_F; +  if (!(CPLXP(x) && (IMAG(x) != IMAG(y)))) return BOOL_T; +#endif +  return BOOL_F; +} +SCM equal(x, y) +     SCM x, y; +{ +  CHECK_STACK; + tailrecurse: POLL; +	if (x==y) return BOOL_T; +	if IMP(x) return BOOL_F; +	if IMP(y) return BOOL_F; +	if (CONSP(x) && CONSP(y)) { +		if FALSEP(equal(CAR(x), CAR(y))) return BOOL_F; +		x = CDR(x); +		y = CDR(y); +		goto tailrecurse; +	} +	/* this ensures that types and length are the same. */ +	if (CAR(x) != CAR(y)) return BOOL_F; +	switch (TYP7(x)) { +        default: return BOOL_F; +	case tc7_string: return st_equal(x, y); +	case tc7_vector: return vector_equal(x, y); +	case tc7_smob: { +	        int i = SMOBNUM(x); +	        if (!(i < numsmob)) return BOOL_F; +	        if (smobs[i].equalp) return (smobs[i].equalp)(x, y); +		else return BOOL_F; +	      } +	case tc7_bvect: case tc7_uvect: case tc7_ivect: +	case tc7_fvect:	case tc7_cvect: case tc7_dvect: { +	        SCM (*pred)() = smobs[0x0ff & (tc16_array>>8)].equalp; +	        if (pred) return (*pred)(x, y); +		else return BOOL_F; +	      } +	} +	return BOOL_F; +} + +SCM numberp(x) +     SCM x; +{ +  if INUMP(x) return BOOL_T; +#ifdef FLOATS +  if (NIMP(x) && NUMP(x)) return BOOL_T; +#else +# ifdef BIGDIG +  if (NIMP(x) && NUMP(x)) return BOOL_T; +# endif +#endif +  return BOOL_F; +} +#ifdef FLOATS +SCM realp(x) +     SCM x; +{ +  if INUMP(x) return BOOL_T; +  if IMP(x) return BOOL_F; +  if REALP(x) return BOOL_T; +# ifdef BIGDIG +  if BIGP(x) return BOOL_T; +# endif +  return BOOL_F; +} +SCM intp(x) +     SCM x; +{ +  double r; +  if INUMP(x) return BOOL_T; +  if IMP(x) return BOOL_F; +# ifdef BIGDIG +  if BIGP(x) return BOOL_T; +# endif +  if (!INEXP(x)) return BOOL_F; +  if CPLXP(x) return BOOL_F; +  r = REALPART(x); +  if (r==floor(r)) return BOOL_T; +  return BOOL_F; +} +#endif				/* FLOATS */ + +SCM inexactp(x) +     SCM x; +{ +#ifdef FLOATS +  if (NIMP(x) && INEXP(x)) return BOOL_T; +#endif +  return BOOL_F; +} +SCM eqp(x, y) +     SCM x, y; +{ +#ifdef FLOATS +  SCM t; +  if NINUMP(x) { +# ifdef BIGDIG +#  ifndef RECKLESS +    if (!(NIMP(x))) +    badx: wta(x, (char *)ARG1, s_eqp); +#  endif +    if BIGP(x) { +      if INUMP(y) return BOOL_F; +      ASRTGO(NIMP(y), bady); +      if BIGP(y) return (0==bigcomp(x, y)) ? BOOL_T : BOOL_F; +      ASRTGO(INEXP(y), bady); +    bigreal: +      return (REALP(y) && (big2dbl(x)==REALPART(y))) ? BOOL_T : BOOL_F; +    } +    ASRTGO(INEXP(x), badx); +# else +    ASSERT(NIMP(x) && INEXP(x), x, ARG1, s_eqp); +# endif +    if INUMP(y) {t = x; x = y; y = t; goto realint;} +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) {t = x; x = y; y = t; goto bigreal;} +    ASRTGO(INEXP(y), bady); +# else +    ASRTGO(NIMP(y) && INEXP(y), bady); +# endif +    if (REALPART(x) != REALPART(y)) return BOOL_F; +    if CPLXP(x) +      return (CPLXP(y) && (IMAG(x)==IMAG(y))) ? BOOL_T : BOOL_F; +    return CPLXP(y) ? BOOL_F : BOOL_T; +  } +  if NINUMP(y) { +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) return BOOL_F; +#  ifndef RECKLESS +    if (!(INEXP(y))) +    bady: wta(y, (char *)ARG2, s_eqp); +#  endif +# else +#  ifndef RECKLESS +    if (!(NIMP(y) && INEXP(y))) +    bady: wta(y, (char *)ARG2, s_eqp); +#  endif +# endif +  realint: +    return (REALP(y) && (((double)INUM(x))==REALPART(y))) ? BOOL_T : BOOL_F; +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_eqp); +    if INUMP(y) return BOOL_F; +    ASRTGO(NIMP(y) && BIGP(y), bady); +    return (0==bigcomp(x, y)) ? BOOL_T : BOOL_F; +  } +  if NINUMP(y) { +#  ifndef RECKLESS +    if (!(NIMP(y) && BIGP(y))) +    bady: wta(y, (char *)ARG2, s_eqp); +#  endif +    return BOOL_F; +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_eqp); +  ASSERT(INUMP(y), y, ARG2, s_eqp); +# endif +#endif +  return ((long)x==(long)y) ? BOOL_T : BOOL_F; +} +SCM lessp(x, y) +     SCM x, y; +{ +#ifdef FLOATS +  if NINUMP(x) { +# ifdef BIGDIG +#  ifndef RECKLESS +    if (!(NIMP(x))) +    badx: wta(x, (char *)ARG1, s_lessp); +#  endif +    if BIGP(x) { +      if INUMP(y) return BIGSIGN(x) ? BOOL_T : BOOL_F; +      ASRTGO(NIMP(y), bady); +      if BIGP(y) return (1==bigcomp(x, y)) ? BOOL_T : BOOL_F; +      ASRTGO(REALP(y), bady); +      return (big2dbl(x) < REALPART(y)) ? BOOL_T : BOOL_F; +    } +    ASRTGO(REALP(x), badx); +# else +    ASSERT(NIMP(x) && REALP(x), x, ARG1, s_lessp); +# endif +    if INUMP(y) return (REALPART(x) < ((double)INUM(y))) ? BOOL_T : BOOL_F; +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) return (REALPART(x) < big2dbl(y)) ? BOOL_T : BOOL_F; +    ASRTGO(REALP(y), bady); +# else +    ASRTGO(NIMP(y) && REALP(y), bady); +# endif +    return (REALPART(x) < REALPART(y)) ? BOOL_T : BOOL_F; +  } +  if NINUMP(y) { +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) return BIGSIGN(y) ? BOOL_F : BOOL_T; +#  ifndef RECKLESS +    if (!(REALP(y))) +    bady: wta(y, (char *)ARG2, s_lessp); +#  endif +# else +#  ifndef RECKLESS +    if (!(NIMP(y) && REALP(y))) +    bady: wta(y, (char *)ARG2, s_lessp); +#  endif +# endif +    return (((double)INUM(x)) < REALPART(y)) ? BOOL_T : BOOL_F; +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_lessp); +    if INUMP(y) return BIGSIGN(x) ? BOOL_T : BOOL_F; +    ASRTGO(NIMP(y) && BIGP(y), bady); +    return (1==bigcomp(x, y)) ? BOOL_T : BOOL_F; +  } +  if NINUMP(y) { +#  ifndef RECKLESS +    if (!(NIMP(y) && BIGP(y))) +    bady: wta(y, (char *)ARG2, s_lessp); +#  endif +    return BIGSIGN(y) ? BOOL_F : BOOL_T; +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_lessp); +  ASSERT(INUMP(y), y, ARG2, s_lessp); +# endif +#endif +  return ((long)x < (long)y) ? BOOL_T : BOOL_F; +} +SCM greaterp(x, y) +     SCM x, y; +{ +  return lessp(y, x); +} +SCM leqp(x, y) +     SCM x, y; +{ +  return BOOL_NOT(lessp(y, x)); +} +SCM greqp(x, y) +     SCM x, y; +{ +  return BOOL_NOT(lessp(x, y)); +} +SCM zerop(z) +     SCM z; +{ +#ifdef FLOATS +  if NINUMP(z) { +# ifdef BIGDIG +    ASRTGO(NIMP(z), badz); +    if BIGP(z) return BOOL_F; +#  ifndef RECKLESS +    if (!(INEXP(z))) +      badz: wta(z, (char *)ARG1, s_zerop); +#  endif +# else +    ASSERT(NIMP(z) && INEXP(z), z, ARG1, s_zerop); +# endif +    return (z==flo0) ? BOOL_T : BOOL_F; +  } +#else +# ifdef BIGDIG +  if NINUMP(z) { +    ASSERT(NIMP(z) && BIGP(z), z, ARG1, s_zerop); +    return BOOL_F; +  } +# else +  ASSERT(INUMP(z), z, ARG1, s_zerop); +# endif +#endif +  return (z==INUM0) ? BOOL_T: BOOL_F; +} +SCM positivep(x) +     SCM x; +{ +#ifdef FLOATS +  if NINUMP(x) { +# ifdef BIGDIG +    ASRTGO(NIMP(x), badx); +    if BIGP(x) return TYP16(x)==tc16_bigpos ? BOOL_T : BOOL_F; +#  ifndef RECKLESS +    if (!(REALP(x))) +      badx: wta(x, (char *)ARG1, s_positivep); +#  endif +# else +    ASSERT(NIMP(x) && REALP(x), x, ARG1, s_positivep); +# endif +    return (REALPART(x) > 0.0) ? BOOL_T : BOOL_F; +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_positivep); +    return TYP16(x)==tc16_bigpos ? BOOL_T : BOOL_F; +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_positivep); +# endif +#endif +  return (x > INUM0) ? BOOL_T : BOOL_F; +} +SCM negativep(x) +     SCM x; +{ +#ifdef FLOATS +  if NINUMP(x) { +# ifdef BIGDIG +    ASRTGO(NIMP(x), badx); +    if BIGP(x) return TYP16(x)==tc16_bigpos ? BOOL_F : BOOL_T; +#  ifndef RECKLESS +    if (!(REALP(x))) +      badx: wta(x, (char *)ARG1, s_negativep); +#  endif +# else +    ASSERT(NIMP(x) && REALP(x), x, ARG1, s_negativep); +# endif +    return (REALPART(x) < 0.0) ? BOOL_T : BOOL_F; +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_negativep); +    return (TYP16(x)==tc16_bigneg) ? BOOL_T : BOOL_F; +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_negativep); +# endif +#endif +  return (x < INUM0) ? BOOL_T : BOOL_F; +} + +SCM lmax(x, y) +     SCM x, y; +{ +#ifdef FLOATS +  double z; +#endif +  if UNBNDP(y) { +#ifndef RECKLESS +    if (!(NUMBERP(x))) +    badx: wta(x, (char *)ARG1, s_max); +#endif +    return x; +  } +#ifdef FLOATS +  if NINUMP(x) { +# ifdef BIGDIG +    ASRTGO(NIMP(x), badx); +    if BIGP(x) { +      if INUMP(y) return BIGSIGN(x) ? y : x; +      ASRTGO(NIMP(y), bady); +      if BIGP(y) return (1==bigcomp(x, y)) ? y : x; +      ASRTGO(REALP(y), bady); +      z = big2dbl(x); +      return (z < REALPART(y)) ? y : makdbl(z, 0.0); +    } +    ASRTGO(REALP(x), badx); +# else +    ASSERT(NIMP(x) && REALP(x), x, ARG1, s_max); +# endif +    if INUMP(y) return (REALPART(x) < (z = INUM(y))) ? makdbl(z, 0.0) : x; +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) return (REALPART(x) < (z = big2dbl(y))) ? makdbl(z, 0.0) : x; +    ASRTGO(REALP(y), bady); +# else +    ASRTGO(NIMP(y) && REALP(y), bady); +# endif +    return (REALPART(x) < REALPART(y)) ? y : x; +  } +  if NINUMP(y) { +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) return BIGSIGN(y) ? x : y; +#  ifndef RECKLESS +    if (!(REALP(y))) +    bady: wta(y, (char *)ARG2, s_max); +#  endif +# else +#  ifndef RECKLESS +    if (!(NIMP(y) && REALP(y))) +    bady: wta(y, (char *)ARG2, s_max); +#  endif +# endif +    return ((z = INUM(x)) < REALPART(y)) ? y : makdbl(z, 0.0); +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_max); +    if INUMP(y) return BIGSIGN(x) ? y : x; +    ASRTGO(NIMP(y) && BIGP(y), bady); +    return (1==bigcomp(x, y)) ? y : x; +  } +  if NINUMP(y) { +#  ifndef RECKLESS +    if (!(NIMP(y) && BIGP(y))) +    bady: wta(y, (char *)ARG2, s_max); +#  endif +    return BIGSIGN(y) ? x : y; +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_max); +  ASSERT(INUMP(y), y, ARG2, s_max); +# endif +#endif +  return ((long)x < (long)y) ? y : x; +} + +SCM lmin(x, y) +     SCM x, y; +{ +#ifdef FLOATS +  double z; +#endif +  if UNBNDP(y) { +#ifndef RECKLESS +    if (!(NUMBERP(x))) +    badx: wta(x, (char *)ARG1, s_min); +#endif +    return x; +  } +#ifdef FLOATS +  if NINUMP(x) { +# ifdef BIGDIG +    ASRTGO(NIMP(x), badx); +    if BIGP(x) { +      if INUMP(y) return BIGSIGN(x) ? x : y; +      ASRTGO(NIMP(y), bady); +      if BIGP(y) return (-1==bigcomp(x, y)) ? y : x; +      ASRTGO(REALP(y), bady); +      z = big2dbl(x); +      return (z > REALPART(y)) ? y : makdbl(z, 0.0); +    } +    ASRTGO(REALP(x), badx); +# else +    ASSERT(NIMP(x) && REALP(x), x, ARG1, s_min); +# endif +    if INUMP(y) return (REALPART(x) > (z = INUM(y))) ? makdbl(z, 0.0) : x; +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) return (REALPART(x) > (z = big2dbl(y))) ? makdbl(z, 0.0) : x; +    ASRTGO(REALP(y), bady); +# else +    ASRTGO(NIMP(y) && REALP(y), bady); +# endif +    return (REALPART(x) > REALPART(y)) ? y : x; +  } +  if NINUMP(y) { +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) return BIGSIGN(y) ? y : x; +#  ifndef RECKLESS +    if (!(REALP(y))) +    bady: wta(y, (char *)ARG2, s_min); +#  endif +# else +#  ifndef RECKLESS +    if (!(NIMP(y) && REALP(y))) +    bady: wta(y, (char *)ARG2, s_min); +#  endif +# endif +    return ((z = INUM(x)) > REALPART(y)) ? y : makdbl(z, 0.0); +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_min); +    if INUMP(y) return BIGSIGN(x) ? x : y; +    ASRTGO(NIMP(y) && BIGP(y), bady); +    return (-1==bigcomp(x, y)) ? y : x; +  } +  if NINUMP(y) { +#  ifndef RECKLESS +    if (!(NIMP(y) && BIGP(y))) +    bady: wta(y, (char *)ARG2, s_min); +#  endif +    return BIGSIGN(y) ? y : x; +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_min); +  ASSERT(INUMP(y), y, ARG2, s_min); +# endif +#endif +  return ((long)x > (long)y) ? y : x; +} + +SCM sum(x, y) +     SCM x, y; +{ +  if UNBNDP(y) { +    if UNBNDP(x) return INUM0; +#ifndef RECKLESS +    if (!(NUMBERP(x))) +    badx: wta(x, (char *)ARG1, s_sum); +#endif +    return x; +  } +#ifdef FLOATS +  if NINUMP(x) { +    SCM t; +# ifdef BIGDIG +    ASRTGO(NIMP(x), badx); +    if BIGP(x) { +      if INUMP(y) {t = x; x = y; y = t; goto intbig;} +      ASRTGO(NIMP(y), bady); +      if BIGP(y) { +	if (NUMDIGS(x) > NUMDIGS(y)) {t = x; x = y; y = t;} +	return addbig(BDIGITS(x), NUMDIGS(x), BIGSIGN(x), y, 0); +      } +      ASRTGO(INEXP(y), bady); +    bigreal: return makdbl(big2dbl(x)+REALPART(y), CPLXP(y)?IMAG(y):0.0); +    } +    ASRTGO(INEXP(x), badx); +# else +    ASRTGO(NIMP(x) && INEXP(x), badx); +# endif +    if INUMP(y) {t = x; x = y; y = t; goto intreal;} +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) {t = x; x = y; y = t; goto bigreal;} +#  ifndef RECKLESS +    else if (!(INEXP(y))) +    bady: wta(y, (char *)ARG2, s_sum); +#  endif +# else +#  ifndef RECKLESS +    if (!(NIMP(y) && INEXP(y))) +    bady: wta(y, (char *)ARG2, s_sum); +#  endif +# endif +    { double i = 0.0; +      if CPLXP(x) i = IMAG(x); +      if CPLXP(y) i += IMAG(y); +      return makdbl(REALPART(x)+REALPART(y), i); } +  } +  if NINUMP(y) { +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) +    intbig: { +#  ifndef DIGSTOOBIG +      long z = pseudolong(INUM(x)); +      return addbig((BIGDIG *)&z, DIGSPERLONG, (x < 0) ? 0x0100 : 0, y, 0); +#  else +      BIGDIG zdigs[DIGSPERLONG]; +      longdigs(INUM(x), zdigs); +      return addbig(zdigs, DIGSPERLONG, (x < 0) ? 0x0100 : 0, y, 0); +#  endif +    } +    ASRTGO(INEXP(y), bady); +# else +    ASRTGO(NIMP(y) && INEXP(y), bady); +# endif +  intreal: return makdbl(INUM(x)+REALPART(y), CPLXP(y)?IMAG(y):0.0); +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    SCM t; +    ASRTGO(NIMP(x) && BIGP(x), badx); +    if INUMP(y) {t = x; x = y; y = t; goto intbig;} +    ASRTGO(NIMP(y) && BIGP(y), bady); +    if (NUMDIGS(x) > NUMDIGS(y)) {t = x; x = y; y = t;} +    return addbig(BDIGITS(x), NUMDIGS(x), BIGSIGN(x), y, 0); +  } +  if NINUMP(y) { +#  ifndef RECKLESS +    if (!(NIMP(y) && BIGP(y))) +    bady: wta(y, (char *)ARG2, s_sum); +#  endif +    intbig: { +#  ifndef DIGSTOOBIG +      long z = pseudolong(INUM(x)); +      return addbig(&z, DIGSPERLONG, (x < 0) ? 0x0100 : 0, y, 0); +#  else +      BIGDIG zdigs[DIGSPERLONG]; +      longdigs(INUM(x), zdigs); +      return addbig(zdigs, DIGSPERLONG, (x < 0) ? 0x0100 : 0, y, 0); +#  endif +    } +  } +# else +  ASRTGO(INUMP(x), badx); +  ASSERT(INUMP(y), y, ARG2, s_sum); +# endif +#endif +  x = INUM(x)+INUM(y); +  if FIXABLE(x) return MAKINUM(x); +#ifdef BIGDIG +  return long2big(x); +#else +# ifdef FLOATS +  return makdbl((double)x, 0.0); +# else +  wta(y, (char *)OVFLOW, s_sum); +# endif +#endif +} + +SCM difference(x, y) +     SCM x, y; +{ +#ifdef FLOATS +  if NINUMP(x) { +# ifndef RECKLESS +    if (!(NIMP(x))) +    badx: wta(x, (char *)ARG1, s_difference); +# endif +    if UNBNDP(y) { +# ifdef BIGDIG +      if BIGP(x) { +	x = copybig(x, !BIGSIGN(x)); +	return NUMDIGS(x) * BITSPERDIG/CHAR_BIT <= sizeof(SCM) ? +	  big2inum(x, NUMDIGS(x)) : x; +      } +# endif +      ASRTGO(INEXP(x), badx); +      return makdbl(-REALPART(x), CPLXP(x)?-IMAG(x):0.0); +    } +    if INUMP(y) return sum(x, MAKINUM(-INUM(y))); +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(x) { +      if BIGP(y) return (NUMDIGS(x) < NUMDIGS(y)) ? +		   addbig(BDIGITS(x), NUMDIGS(x), BIGSIGN(x), y, 0x0100) : +		   addbig(BDIGITS(y), NUMDIGS(y), BIGSIGN(y) ^ 0x0100, x, 0); +      ASRTGO(INEXP(y), bady); +      return makdbl(big2dbl(x)-REALPART(y), CPLXP(y)?-IMAG(y):0.0); +    } +    ASRTGO(INEXP(x), badx); +    if BIGP(y) return makdbl(REALPART(x)-big2dbl(y), CPLXP(x)?IMAG(x):0.0); +    ASRTGO(INEXP(y), bady); +# else +    ASRTGO(INEXP(x), badx); +    ASRTGO(NIMP(y) && INEXP(y), bady); +# endif +    if CPLXP(x) +      if CPLXP(y) +	return makdbl(REAL(x)-REAL(y), IMAG(x)-IMAG(y)); +      else +	return makdbl(REAL(x)-REALPART(y), IMAG(x)); +    return makdbl(REALPART(x)-REALPART(y), CPLXP(y)?-IMAG(y):0.0); +  } +  if UNBNDP(y) {x = -INUM(x); goto checkx;} +  if NINUMP(y) { +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) { +#  ifndef DIGSTOOBIG +      long z = pseudolong(INUM(x)); +      return addbig((BIGDIG *)&z, DIGSPERLONG, (x < 0) ? 0x0100 : 0, y, 0x0100); +#  else +      BIGDIG zdigs[DIGSPERLONG]; +      longdigs(INUM(x), zdigs); +      return addbig(zdigs, DIGSPERLONG, (x < 0) ? 0x0100 : 0, y, 0x0100); +#  endif +    } +#  ifndef RECKLESS +    if (!(INEXP(y))) +    bady: wta(y, (char *)ARG2, s_difference); +#  endif +# else +#  ifndef RECKLESS +    if (!(NIMP(y) && INEXP(y))) +    bady: wta(y, (char *)ARG2, s_difference); +#  endif +# endif +    return makdbl(INUM(x)-REALPART(y), CPLXP(y)?-IMAG(y):0.0); +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_difference); +    if UNBNDP(y) { +      x = copybig(x, !BIGSIGN(x)); +      return NUMDIGS(x) * BITSPERDIG/CHAR_BIT <= sizeof(SCM) ? +		big2inum(x, NUMDIGS(x)) : x; +    } +    if INUMP(y) { +#  ifndef DIGSTOOBIG +      long z = pseudolong(INUM(y)); +      return addbig(&z, DIGSPERLONG, (y < 0) ? 0 : 0x0100, x, 0); +#  else +      BIGDIG zdigs[DIGSPERLONG]; +      longdigs(INUM(x), zdigs); +      return addbig(zdigs, DIGSPERLONG, (y < 0) ? 0 : 0x0100, x, 0); +#  endif +    } +    ASRTGO(NIMP(y) && BIGP(y), bady); +    return (NUMDIGS(x) < NUMDIGS(y)) ? +		   addbig(BDIGITS(x), NUMDIGS(x), BIGSIGN(x), y, 0x0100) : +		   addbig(BDIGITS(y), NUMDIGS(y), BIGSIGN(y) ^ 0x0100, x, 0); +  } +  if UNBNDP(y) {x = -INUM(x); goto checkx;} +  if NINUMP(y) { +#  ifndef RECKLESS +    if (!(NIMP(y) && BIGP(y))) +    bady: wta(y, (char *)ARG2, s_difference); +#  endif +    { +#  ifndef DIGSTOOBIG +      long z = pseudolong(INUM(x)); +      return addbig(&z, DIGSPERLONG, (x < 0) ? 0x0100 : 0, y, 0x0100); +#  else +      BIGDIG zdigs[DIGSPERLONG]; +      longdigs(INUM(x), zdigs); +      return addbig(zdigs, DIGSPERLONG, (x < 0) ? 0x0100 : 0, y, 0x0100); +#  endif +    } +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_difference); +  if UNBNDP(y) {x = -INUM(x); goto checkx;} +  ASSERT(INUMP(y), y, ARG2, s_difference); +# endif +#endif +  x = INUM(x)-INUM(y); + checkx: +  if FIXABLE(x) return MAKINUM(x); +#ifdef BIGDIG +  return long2big(x); +#else +# ifdef FLOATS +  return makdbl((double)x, 0.0); +# else +  wta(y, (char *)OVFLOW, s_difference); +# endif +#endif +} + +SCM product(x, y) +     SCM x, y; +{ +  if UNBNDP(y) { +    if UNBNDP(x) return MAKINUM(1L); +#ifndef RECKLESS +    if (!(NUMBERP(x))) +    badx: wta(x, (char *)ARG1, s_product); +#endif +    return x; +  } +#ifdef FLOATS +  if NINUMP(x) { +    SCM t; +# ifdef BIGDIG +    ASRTGO(NIMP(x), badx); +    if BIGP(x) { +      if INUMP(y) {t = x; x = y; y = t; goto intbig;} +      ASRTGO(NIMP(y), bady); +      if BIGP(y) return mulbig(BDIGITS(x), NUMDIGS(x), BDIGITS(y), NUMDIGS(y), +			       BIGSIGN(x) ^ BIGSIGN(y)); +      ASRTGO(INEXP(y), bady); +    bigreal: { +      double bg = big2dbl(x); +      return makdbl(bg*REALPART(y), CPLXP(y)?bg*IMAG(y):0.0); } +    } +    ASRTGO(INEXP(x), badx); +# else +    ASRTGO(NIMP(x) && INEXP(x), badx); +# endif +    if INUMP(y) {t = x; x = y; y = t; goto intreal;} +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) {t = x; x = y; y = t; goto bigreal;} +#  ifndef RECKLESS +    else if (!(INEXP(y))) +    bady: wta(y, (char *)ARG2, s_product); +#  endif +# else +#  ifndef RECKLESS +    if (!(NIMP(y) && INEXP(y))) +    bady: wta(y, (char *)ARG2, s_product); +#  endif +# endif +    if CPLXP(x) +      if CPLXP(y) +	return makdbl(REAL(x)*REAL(y)-IMAG(x)*IMAG(y), +		      REAL(x)*IMAG(y)+IMAG(x)*REAL(y)); +      else +	return makdbl(REAL(x)*REALPART(y), IMAG(x)*REALPART(y)); +    return makdbl(REALPART(x)*REALPART(y), +		  CPLXP(y)?REALPART(x)*IMAG(y):0.0); +  } +  if NINUMP(y) { +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) { +    intbig: if (INUM0==x) return x; if (MAKINUM(1L)==x) return y; +      { +#  ifndef DIGSTOOBIG +	long z = pseudolong(INUM(x)); +	return mulbig((BIGDIG *)&z, DIGSPERLONG, BDIGITS(y), NUMDIGS(y), +		      BIGSIGN(y) ? (x>0) : (x<0)); +#  else +	BIGDIG zdigs[DIGSPERLONG]; +	longdigs(INUM(x), zdigs); +	return mulbig(zdigs, DIGSPERLONG, BDIGITS(y), NUMDIGS(y), +		      BIGSIGN(y) ? (x>0) : (x<0)); +#  endif +      } +    } +    ASRTGO(INEXP(y), bady); +# else +    ASRTGO(NIMP(y) && INEXP(y), bady); +# endif +  intreal: return makdbl(INUM(x)*REALPART(y), CPLXP(y)?INUM(x)*IMAG(y):0.0); +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    ASRTGO(NIMP(x) && BIGP(x), badx); +    if INUMP(y) {SCM t = x; x = y; y = t; goto intbig;} +    ASRTGO(NIMP(y) && BIGP(y), bady); +    return mulbig(BDIGITS(x), NUMDIGS(x), BDIGITS(y), NUMDIGS(y), +		  BIGSIGN(x) ^ BIGSIGN(y)); +  } +  if NINUMP(y) { +#  ifndef RECKLESS +    if (!(NIMP(y) && BIGP(y))) +    bady: wta(y, (char *)ARG2, s_product); +#  endif +  intbig: if (INUM0==x) return x; if (MAKINUM(1L)==x) return y; +    { +#  ifndef DIGSTOOBIG +      long z = pseudolong(INUM(x)); +      return mulbig(&z, DIGSPERLONG, BDIGITS(y), NUMDIGS(y), +		    BIGSIGN(y) ? (x>0) : (x<0)); +#  else +      BIGDIG zdigs[DIGSPERLONG]; +      longdigs(INUM(x), zdigs); +      return mulbig(zdigs, DIGSPERLONG, BDIGITS(y), NUMDIGS(y), +		    BIGSIGN(y) ? (x>0) : (x<0)); +#  endif +    } +  } +# else +  ASRTGO(INUMP(x), badx); +  ASSERT(INUMP(y), y, ARG2, s_product); +# endif +#endif +  { +    long i, j, k; +    i = INUM(x); +    if (0==i) return x; +    j = INUM(y); +    k = i * j; +    y = MAKINUM(k); +    if (k != INUM(y) || k/i != j) +#ifdef BIGDIG +      { int sgn = (i < 0) ^ (j < 0); +# ifndef DIGSTOOBIG +	i = pseudolong(i); +	j = pseudolong(j); +	return mulbig((BIGDIG *)&i, DIGSPERLONG, +		      (BIGDIG *)&j, DIGSPERLONG, sgn); +# else /* DIGSTOOBIG */ +	BIGDIG idigs[DIGSPERLONG]; +	BIGDIG jdigs[DIGSPERLONG]; +	longdigs(i, idigs); +	longdigs(j, jdigs); +	return mulbig(idigs, DIGSPERLONG, jdigs, DIGSPERLONG, sgn); +# endif +      } +#else +# ifdef FLOATS +    return makdbl(((double)i)*((double)j), 0.0); +# else +    wta(y, (char *)OVFLOW, s_product); +# endif +#endif +    return y; +  } +} + +SCM divide(x, y) +     SCM x, y; +{ +#ifdef FLOATS +  double d, r, i, a; +  if NINUMP(x) { +# ifndef RECKLESS +    if (!(NIMP(x))) +    badx: wta(x, (char *)ARG1, s_divide); +# endif +    if UNBNDP(y) { +# ifdef BIGDIG +      if BIGP(x) return makdbl(1.0/big2dbl(x), 0.0); +# endif +      ASRTGO(INEXP(x), badx); +      if REALP(x) return makdbl(1.0/REALPART(x), 0.0); +      r = REAL(x);  i = IMAG(x);  d = r*r+i*i; +      return makdbl(r/d, -i/d); +    } +# ifdef BIGDIG +    if BIGP(x) { +      SCM z; +      if INUMP(y) { +        z = INUM(y); +        ASSERT(z, y, OVFLOW, s_divide); +	if (1==z) return x; +        if (z < 0) z = -z; +        if (z < BIGRAD) { +          SCM w = copybig(x, BIGSIGN(x) ? (y>0) : (y<0)); +          return divbigdig(BDIGITS(w), NUMDIGS(w), (BIGDIG)z) ? +	    makdbl(big2dbl(x)/INUM(y), 0.0) : normbig(w); +	} +#  ifndef DIGSTOOBIG +        z = pseudolong(z); +        z = divbigbig(BDIGITS(x), NUMDIGS(x), (BIGDIG *)&z, DIGSPERLONG, +                      BIGSIGN(x) ? (y>0) : (y<0), 3); +#  else +	{ BIGDIG zdigs[DIGSPERLONG]; +	  longdigs(z, zdigs); +	  z = divbigbig(BDIGITS(x), NUMDIGS(x), zdigs, DIGSPERLONG, +			BIGSIGN(x) ? (y>0) : (y<0), 3);} +#  endif +        return z ? z : makdbl(big2dbl(x)/INUM(y), 0.0); +      } +      ASRTGO(NIMP(y), bady); +      if BIGP(y) { +	z = divbigbig(BDIGITS(x), NUMDIGS(x), BDIGITS(y), NUMDIGS(y), +		      BIGSIGN(x) ^ BIGSIGN(y), 3); +	return z ? z : makdbl(big2dbl(x)/big2dbl(y), 0.0); +      } +      ASRTGO(INEXP(y), bady); +      if REALP(y) return makdbl(big2dbl(x)/REALPART(y), 0.0); +      a = big2dbl(x); +      goto complex_div; +    } +# endif +    ASRTGO(INEXP(x), badx); +    if INUMP(y) {d = INUM(y); goto basic_div;} +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) {d = big2dbl(y); goto basic_div;} +    ASRTGO(INEXP(y), bady); +# else +    ASRTGO(NIMP(y) && INEXP(y), bady); +# endif +    if REALP(y) { +      d = REALPART(y); +    basic_div: return makdbl(REALPART(x)/d, CPLXP(x)?IMAG(x)/d:0.0); +    } +    a = REALPART(x); +    if REALP(x) goto complex_div; +    r = REAL(y);  i = IMAG(y);  d = r*r+i*i; +    return makdbl((a*r+IMAG(x)*i)/d, (IMAG(x)*r-a*i)/d); +  } +  if UNBNDP(y) { +    if ((MAKINUM(1L)==x) || (MAKINUM(-1L)==x)) return x; +    return makdbl(1.0/((double)INUM(x)), 0.0); +  } +  if NINUMP(y) { +# ifdef BIGDIG +    ASRTGO(NIMP(y), bady); +    if BIGP(y) return makdbl(INUM(x)/big2dbl(y), 0.0); +#  ifndef RECKLESS +    if (!(INEXP(y))) +    bady: wta(y, (char *)ARG2, s_divide); +#  endif +# else +#  ifndef RECKLESS +    if (!(NIMP(y) && INEXP(y))) +    bady: wta(y, (char *)ARG2, s_divide); +#  endif +# endif +    if REALP(y) return makdbl(INUM(x)/REALPART(y), 0.0); +    a = INUM(x); +  complex_div: +    r = REAL(y);  i = IMAG(y);  d = r*r+i*i; +    return makdbl((a*r)/d, (-a*i)/d); +  } +#else +# ifdef BIGDIG +  if NINUMP(x) { +    SCM z; +    ASSERT(NIMP(x) && BIGP(x), x, ARG1, s_divide); +    if UNBNDP(y) goto ov; +    if INUMP(y) { +      z = INUM(y); +      if (!z) goto ov; +      if (1==z) return x; +      if (z < 0) z = -z; +      if (z < BIGRAD) { +        SCM w = copybig(x, BIGSIGN(x) ? (y>0) : (y<0)); +        if (divbigdig(BDIGITS(w), NUMDIGS(w), (BIGDIG)z)) goto ov; +        return w; +      } +#  ifndef DIGSTOOBIG +      z = pseudolong(z); +      z = divbigbig(BDIGITS(x), NUMDIGS(x), &z, DIGSPERLONG, +		    BIGSIGN(x) ? (y>0) : (y<0), 3); +#  else +      { BIGDIG zdigs[DIGSPERLONG]; +	longdigs(z, zdigs); +	z = divbigbig(BDIGITS(x), NUMDIGS(x), zdigs, DIGSPERLONG, +		      BIGSIGN(x) ? (y>0) : (y<0), 3);} +#  endif +    } else { +      ASRTGO(NIMP(y) && BIGP(y), bady); +      z = divbigbig(BDIGITS(x), NUMDIGS(x), BDIGITS(y), NUMDIGS(y), +		    BIGSIGN(x) ^ BIGSIGN(y), 3); +    } +    if (!z) goto ov; +    return z; +  } +  if UNBNDP(y) { +    if ((MAKINUM(1L)==x) || (MAKINUM(-1L)==x)) return x; +    goto ov; +  } +  if NINUMP(y) { +#  ifndef RECKLESS +    if (!(NIMP(y) && BIGP(y))) +    bady: wta(y, (char *)ARG2, s_divide); +#  endif +    goto ov; +  } +# else +  ASSERT(INUMP(x), x, ARG1, s_divide); +  if UNBNDP(y) { +    if ((MAKINUM(1L)==x) || (MAKINUM(-1L)==x)) return x; +    goto ov; +  } +  ASSERT(INUMP(y), y, ARG2, s_divide); +# endif +#endif +  { +    long z = INUM(y); +    if ((0==z) || INUM(x)%z) goto ov; +    z = INUM(x)/z; +    if FIXABLE(z) return MAKINUM(z); +#ifdef BIGDIG +    return long2big(z); +#endif +#ifdef FLOATS +  ov: return makdbl(((double)INUM(x))/((double)INUM(y)), 0.0); +#else +  ov: wta(x, (char *)OVFLOW, s_divide); +#endif +  } +} + +#ifdef FLOATS +double lasinh(x) +     double x; +{ +  return log(x+sqrt(x*x+1)); +} + +double lacosh(x) +     double x; +{ +  return log(x+sqrt(x*x-1)); +} + +double latanh(x) +     double x; +{ +  return 0.5*log((1+x)/(1-x)); +} + +double ltrunc(x) +     double x; +{ +  if (x < 0.0) return -floor(-x); +  return floor(x); +} +double round(x) +     double x; +{ +  double plus_half = x + 0.5; +  double result = floor(plus_half); +  /* Adjust so that the round is towards even.  */ +  return (plus_half==result && plus_half / 2 != floor(plus_half / 2)) +    ? result - 1 : result; +} + +struct dpair {double x, y;}; + +void two_doubles(z1, z2, sstring, xy) +     SCM z1, z2; +     char *sstring; +     struct dpair *xy; +{ +  if INUMP(z1) xy->x = INUM(z1); +  else { +# ifdef BIGDIG +    ASRTGO(NIMP(z1), badz1); +    if BIGP(z1) xy->x = big2dbl(z1); +    else { +#  ifndef RECKLESS +      if (!(REALP(z1))) +      badz1: wta(z1, (char *)ARG1, sstring); +#  endif +      xy->x = REALPART(z1);} +# else +    {ASSERT(NIMP(z1) && REALP(z1), z1, ARG1, sstring); +     xy->x = REALPART(z1);} +# endif +  } +  if INUMP(z2) xy->y = INUM(z2); +  else { +# ifdef BIGDIG +    ASRTGO(NIMP(z2), badz2); +    if BIGP(z2) xy->y = big2dbl(z2); +    else { +#  ifndef RECKLESS +      if (!(REALP(z2))) +      badz2: wta(z2, (char *)ARG2, sstring); +#  endif +      xy->y = REALPART(z2);} +# else +    {ASSERT(NIMP(z2) && REALP(z2), z2, ARG2, sstring); +     xy->y = REALPART(z2);} +# endif +  } +} + +SCM expt(z1, z2) +     SCM z1, z2; +{ +  struct dpair xy; +  two_doubles(z1, z2, s_expt, &xy); +  return makdbl(pow(xy.x, xy.y), 0.0); +} +SCM latan2(z1, z2) +     SCM z1, z2; +{ +  struct dpair xy; +  two_doubles(z1, z2, s_atan2, &xy); +  return makdbl(atan2(xy.x, xy.y), 0.0); +} +SCM makrect(z1, z2) +     SCM z1, z2; +{ +  struct dpair xy; +  two_doubles(z1, z2, s_makrect, &xy); +  return makdbl(xy.x, xy.y); +} +SCM makpolar(z1, z2) +     SCM z1, z2; +{ +  struct dpair xy; +  two_doubles(z1, z2, s_makpolar, &xy); +  return makdbl(xy.x*cos(xy.y), xy.x*sin(xy.y)); +} + +SCM real_part(z) +     SCM z; +{ +  if NINUMP(z) { +# ifdef BIGDIG +    ASRTGO(NIMP(z), badz); +    if BIGP(z) return z; +#  ifndef RECKLESS +    if (!(INEXP(z))) +    badz: wta(z, (char *)ARG1, s_real_part); +#  endif +# else +    ASSERT(NIMP(z) && INEXP(z), z, ARG1, s_real_part); +# endif +    if CPLXP(z) return makdbl(REAL(z), 0.0); +  } +  return z; +} +SCM imag_part(z) +     SCM z; +{ +  if INUMP(z) return INUM0; +# ifdef BIGDIG +  ASRTGO(NIMP(z), badz); +  if BIGP(z) return INUM0; +#  ifndef RECKLESS +  if (!(INEXP(z))) +  badz: wta(z, (char *)ARG1, s_imag_part); +#  endif +# else +  ASSERT(NIMP(z) && INEXP(z), z, ARG1, s_imag_part); +# endif +  if CPLXP(z) return makdbl(IMAG(z), 0.0); +  return flo0; +} +SCM magnitude(z) +     SCM z; +{ +  if INUMP(z) return absval(z); +# ifdef BIGDIG +  ASRTGO(NIMP(z), badz); +  if BIGP(z) return absval(z); +#  ifndef RECKLESS +  if (!(INEXP(z))) +  badz: wta(z, (char *)ARG1, s_magnitude); +#  endif +# else +  ASSERT(NIMP(z) && INEXP(z), z, ARG1, s_magnitude); +# endif +  if CPLXP(z) +    { +      double i = IMAG(z), r = REAL(z); +      return makdbl(sqrt(i*i+r*r), 0.0); +    } +  return makdbl(fabs(REALPART(z)), 0.0); +} + +SCM angle(z) +     SCM z; +{ +  double x, y = 0.0; +  if INUMP(z) {x = (z>=INUM0) ? 1.0 : -1.0; goto do_angle;} +# ifdef BIGDIG +  ASRTGO(NIMP(z), badz); +  if BIGP(z) {x = (TYP16(z)==tc16_bigpos) ? 1.0 : -1.0; goto do_angle;} +#  ifndef RECKLESS +  if (!(INEXP(z))) { +    badz: wta(z, (char *)ARG1, s_angle);} +#  endif +# else +  ASSERT(NIMP(z) && INEXP(z), z, ARG1, s_angle); +# endif +  if REALP(z) {x = REALPART(z); goto do_angle;} +  x = REAL(z); y = IMAG(z); +do_angle: +  return makdbl(atan2(y, x), 0.0); +} + +double floident(z) +     double z; +{ +  return z; +} +SCM in2ex(z) +     SCM z; +{ +  if INUMP(z) return z; +# ifdef BIGDIG +  ASRTGO(NIMP(z), badz); +  if BIGP(z) return z; +#  ifndef RECKLESS +  if (!(REALP(z))) +    badz: wta(z, (char *)ARG1, s_in2ex); +#  endif +# else +  ASSERT(NIMP(z) && REALP(z), z, ARG1, s_in2ex); +# endif +# ifdef BIGDIG +  { +    double u = floor(REALPART(z)+0.5); +    if ((u <= MOST_POSITIVE_FIXNUM) && (-u <= -MOST_NEGATIVE_FIXNUM)) { +      /* Negation is a workaround for HP700 cc bug */ +      SCM ans = MAKINUM((long)u); +      if (INUM(ans)==(long)u) return ans; +    } +    ASRTGO(!IS_INF(u), badz);	/* problem? */ +    return dbl2big(u); +  } +# else +  return MAKINUM((long)floor(REALPART(z)+0.5)); +# endif +} +#else				/* ~FLOATS */ +static char s_trunc[] = "truncate"; +SCM numident(x) +     SCM x; +{ +  ASSERT(INUMP(x), x, ARG1, s_trunc); +  return x; +} +#endif				/* FLOATS */ + +#ifdef BIGDIG +# ifdef FLOATS +SCM dbl2big(d) +     double d;			/* must be integer */ +{ +  sizet i = 0; +  long c; +  BIGDIG *digits; +  SCM ans; +  double u = (d < 0)?-d:d; +  while (0 != floor(u)) {u /= BIGRAD;i++;} +  ans = mkbig(i, d < 0); +  digits = BDIGITS(ans); +  while (i--) { +    u *= BIGRAD; +    c = floor(u); +    u -= c; +    digits[i] = c; +  } +  ASSERT(0==u, INUM0, OVFLOW, "dbl2big"); +  return ans; +} +double big2dbl(b) +     SCM b; +{ +  double ans = 0.0; +  sizet i = NUMDIGS(b); +  BIGDIG *digits = BDIGITS(b); +  while (i--) ans = digits[i] + BIGRAD*ans; +  if (tc16_bigneg==TYP16(b)) return -ans; +  return ans; +} +# endif +#endif + +unsigned long hasher(obj, n, d) +     SCM obj; +     unsigned long n; +     sizet d; +{ +  switch (7 & (int) obj) { +  case 2: case 6:		/* INUMP(obj) */ +    return INUM(obj) % n; +  case 4: +    if ICHRP(obj) +      return (unsigned)(downcase[ICHR(obj)]) % n; +    switch ((int) obj) { +#ifndef SICP +    case (int) EOL: d = 256; break; +#endif +    case (int) BOOL_T: d = 257; break; +    case (int) BOOL_F: d = 258; break; +    case (int) EOF_VAL: d = 259; break; +    default: d = 263;		/* perhaps should be error */ +    } +    return d % n; +  default: return 263 % n;	/* perhaps should be error */ +  case 0: +    switch TYP7(obj) { +    default: return 263 % n; +    case tc7_smob: +      switch TYP16(obj) { +      case tcs_bignums: +      bighash: return INUM(modulo(obj, MAKINUM(n))); +      default: return 263 % n; +#ifdef FLOATS +      case tc16_flo: +	if REALP(obj) { +	  double r = REALPART(obj); +	  if (floor(r)==r) { +	    obj = in2ex(obj); +	    if IMP(obj) return INUM(obj) % n; +	    goto bighash; +	  } +	} +	obj = number2string(obj, MAKINUM(10)); +#endif +      } +    case tcs_symbols: case tc7_string: +      return strhash(UCHARS(obj), (sizet) LENGTH(obj), n); +    case tc7_vector: { +      sizet len = LENGTH(obj); +      SCM *data = VELTS(obj); +      if (len>5) { +	sizet i = d/2; +	unsigned long h = 1; +	while (i--) h = ((h<<8) + (hasher(data[h % len], n, 2))) % n; +	return h; +      } +      else { +	sizet i = len; +	unsigned long h = (n)-1; +	while (i--) h = ((h<<8) + (hasher(data[i], n, d/len))) % n; +	return h; +      } +    } +    case tcs_cons_imcar: case tcs_cons_nimcar: +      if (d) return (hasher(CAR(obj), n, d/2)+hasher(CDR(obj), n, d/2)) % n; +      else return 1; +    case tc7_port: +      return ((RDNG & CAR(obj)) ? 260 : 261) % n; +    case tcs_closures: case tc7_contin: case tcs_subrs: +      return 262 % n; +    } +  } +} + +static char s_hashv[] = "hashv", s_hashq[] = "hashq"; +extern char s_obunhash[]; +#define s_hash (&s_obunhash[9]) + +SCM hash(obj, n) +     SCM obj; +     SCM n; +{ +  ASSERT(INUMP(n) && 0 <= n, n, ARG2, s_hash); +  return MAKINUM(hasher(obj, INUM(n), 10)); +} + +SCM hashv(obj, n) +     SCM obj; +     SCM n; +{ +  ASSERT(INUMP(n) && 0 <= n, n, ARG2, s_hashv); +  if ICHRP(obj) return MAKINUM((unsigned)(downcase[ICHR(obj)]) % INUM(n)); +  if (NIMP(obj) && NUMP(obj)) return MAKINUM(hasher(obj, INUM(n), 10)); +  else return MAKINUM(obj % INUM(n)); +} + +SCM hashq(obj, n) +     SCM obj; +     SCM n; +{ +  ASSERT(INUMP(n) && 0 <= n, n, ARG2, s_hashq); +  return MAKINUM((((unsigned) obj) >> 1) % INUM(n)); +} + +static iproc subr1s[] = { +	{"number?", numberp}, +	{"complex?", numberp}, +	{s_inexactp, inexactp}, +#ifdef FLOATS +	{"real?", realp}, +	{"rational?", realp}, +	{"integer?", intp}, +	{s_real_part, real_part}, +	{s_imag_part, imag_part}, +	{s_magnitude, magnitude}, +	{s_angle, angle}, +	{s_in2ex, in2ex}, +#else +	{"real?", numberp}, +	{"rational?", numberp}, +	{"integer?", exactp}, +	{"floor", numident}, +	{"ceiling", numident}, +	{s_trunc, numident}, +	{"round", numident}, +#endif +	{s_zerop, zerop}, +	{s_positivep, positivep}, +	{s_negativep, negativep}, +	{s_str2list, string2list}, +	{"list->string", string}, +	{s_st_copy, string_copy}, +	{"list->vector", vector}, +	{s_vect2list, vector2list}, +	{0, 0}}; + +static iproc asubrs[] = { +	{s_difference, difference}, +	{s_divide, divide}, +	{s_max, lmax}, +	{s_min, lmin}, +	{s_sum, sum}, +	{s_product, product}, +	{0, 0}}; + +static iproc subr2s[] = { +#ifdef FLOATS +	{s_makrect, makrect}, +	{s_makpolar, makpolar}, +	{s_memv, memv}, +	{s_assv, assv}, +	{s_atan2, latan2}, +	{s_expt, expt}, +#else +	{"memv", memq}, +	{"assv", assq}, +#endif +	{s_list_tail, list_tail}, +	{s_ve_fill, vector_fill}, +	{s_st_fill, string_fill}, +	{s_hash, hash}, +	{s_hashv, hashv}, +	{s_hashq, hashq}, +	{0, 0}}; + +static iproc subr2os[] = { +	{s_str2number, string2number}, +	{s_number2string, number2string}, +	{0, 0}}; + +static iproc rpsubrs[] = { +#ifdef FLOATS +	{"eqv?", eqv}, +#else +	{"eqv?", eq}, +#endif +	{s_eqp, eqp}, +	{s_lessp, lessp}, +	{s_grp, greaterp}, +	{s_leqp, leqp}, +	{s_greqp, greqp}, +	{0, 0}}; + +#ifdef FLOATS +static dblproc cxrs[] = { +	{"floor", floor}, +	{"ceiling", ceil}, +	{"truncate", ltrunc}, +	{"round", round}, +	{"$sqrt", sqrt}, +	{"$abs", fabs}, +	{"$exp", exp}, +	{"$log", log}, +	{"$sin", sin}, +	{"$cos", cos}, +	{"$tan", tan}, +	{"$asin", asin}, +	{"$acos", acos}, +	{"$atan", atan}, +	{"$sinh", sinh}, +	{"$cosh", cosh}, +	{"$tanh", tanh}, +	{"$asinh", lasinh}, +	{"$acosh", lacosh}, +	{"$atanh", latanh}, +	{"exact->inexact", floident}, +	{0, 0}}; +#endif + +#ifdef FLOATS +# ifndef DBL_DIG +static void add1(f, fsum) +     double f, *fsum; +{ +  *fsum = f + 1.0; +} +# endif +#endif + +void init_scl() +{ +  init_iprocs(subr1s, tc7_subr_1); +  init_iprocs(subr2os, tc7_subr_2o); +  init_iprocs(subr2s, tc7_subr_2); +  init_iprocs(asubrs, tc7_asubr); +  init_iprocs(rpsubrs, tc7_rpsubr); +#ifdef SICP +  add_feature("sicp"); +#endif +#ifdef FLOATS +  init_iprocs((iproc *)cxrs, tc7_cxr); +  NEWCELL(flo0); +# ifdef SINGLES +  CAR(flo0) = tc_flo; +  FLO(flo0) = 0.0; +# else +  CDR(flo0) = (SCM)must_malloc(1L*sizeof(double), "real"); +  REAL(flo0) = 0.0; +  CAR(flo0) = tc_dblr; +# endif +# ifdef DBL_DIG +  dblprec = (DBL_DIG > 20) ? 20 : DBL_DIG; +# else +  {				/* determine floating point precision */ +    double f = 0.1; +    double fsum = 1.0+f; +    while (fsum != 1.0) { +      f /= 10.0; +      if (++dblprec > 20) break; +      add1(f, &fsum); +    } +    dblprec = dblprec-1; +  } +# endif /* DBL_DIG */ +#endif +}  | 
