home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-07 | 59.4 KB | 2,783 lines |
- Newsgroups: comp.sources.unix
- From: dbell@canb.auug.org.au (David I. Bell)
- Subject: v27i139: calc-2.9.0 - arbitrary precision C-like programmable calculator, Part12/19
- References: <1.755316719.21314@gw.home.vix.com>
- Sender: unix-sources-moderator@gw.home.vix.com
- Approved: vixie@gw.home.vix.com
-
- Submitted-By: dbell@canb.auug.org.au (David I. Bell)
- Posting-Number: Volume 27, Issue 139
- Archive-Name: calc-2.9.0/part12
-
- #!/bin/sh
- # this is part 12 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file calc2.9.0/zfunc.c continued
- #
- CurArch=12
- if test ! -r s2_seq_.tmp
- then echo "Please unpack part 1 first!"
- exit 1; fi
- ( read Scheck
- if test "$Scheck" != $CurArch
- then echo "Please unpack part $Scheck next!"
- exit 1;
- else exit 0; fi
- ) < s2_seq_.tmp || exit 1
- echo "x - Continuing file calc2.9.0/zfunc.c"
- sed 's/^X//' << 'SHAR_EOF' >> calc2.9.0/zfunc.c
- X * is unimportant.
- X */
- X highbit = (highbit + k - 1) / k;
- X try.len = (highbit / BASEB) + 1;
- X try.v = alloc(try.len);
- X try.v[try.len-1] = ((HALF)1 << (highbit % BASEB));
- X try.sign = 0;
- X old.v = alloc(try.len);
- X old.len = 1;
- X *old.v = 0;
- X old.sign = 0;
- X /*
- X * Main divide and average loop
- X */
- X for (;;) {
- X zpowi(try, k1, &temp);
- X zquo(z1, temp, &quo);
- X zfree(temp);
- X i = zrel(try, quo);
- X if (i <= 0) {
- X /*
- X * Current try is less than or equal to the root since it is
- X * less than the quotient. If the quotient is equal to the try,
- X * we are all done. Also, if the try is equal to the old value,
- X * we are done since no improvement occurred.
- X * If not, save the improved value and loop some more.
- X */
- X if ((i == 0) || (zcmp(old, try) == 0)) {
- X zfree(quo);
- X zfree(old);
- X try.sign = (HALF)sign;
- X zquicktrim(try);
- X *dest = try;
- X return;
- X }
- X old.len = try.len;
- X zcopyval(try, old);
- X }
- X /* average current try and quotent for the new try */
- X zmul(try, k1, &temp);
- X zfree(try);
- X zadd(quo, temp, &temp2);
- X zfree(temp);
- X zfree(quo);
- X zquo(temp2, z2, &try);
- X zfree(temp2);
- X }
- X}
- X
- X
- X/*
- X * Test to see if a number is an exact square or not.
- X */
- XBOOL
- Xzissquare(z)
- X ZVALUE z; /* number to be tested */
- X{
- X long n, i;
- X ZVALUE tmp;
- X
- X if (z.sign) /* negative */
- X return FALSE;
- X while ((z.len > 1) && (*z.v == 0)) { /* ignore trailing zero words */
- X z.len--;
- X z.v++;
- X }
- X if (zisleone(z)) /* zero or one */
- X return TRUE;
- X n = *z.v & 0xf; /* check mod 16 values */
- X if ((n != 0) && (n != 1) && (n != 4) && (n != 9))
- X return FALSE;
- X n = *z.v & 0xff; /* check mod 256 values */
- X i = 0x80;
- X while (((i * i) & 0xff) != n)
- X if (--i <= 0)
- X return FALSE;
- X n = zsqrt(z, &tmp); /* must do full square root test now */
- X zfree(tmp);
- X return n;
- X}
- X
- X
- X/*
- X * Return a trivial hash value for an integer.
- X */
- XHASH
- Xzhash(z)
- X ZVALUE z;
- X{
- X HASH hash;
- X int i;
- X
- X hash = z.len * 1000003;
- X if (z.sign)
- X hash += 10000019;
- X for (i = z.len - 1; i >= 0; i--)
- X hash = hash * 79372817 + z.v[i] + 10000079;
- X return hash;
- X}
- X
- X/* END CODE */
- SHAR_EOF
- echo "File calc2.9.0/zfunc.c is complete"
- chmod 0644 calc2.9.0/zfunc.c || echo "restore of calc2.9.0/zfunc.c fails"
- set `wc -c calc2.9.0/zfunc.c`;Sum=$1
- if test "$Sum" != "34638"
- then echo original size 34638, current size $Sum;fi
- echo "x - extracting calc2.9.0/zio.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/zio.c &&
- X/*
- X * Copyright (c) 1993 David I. Bell
- X * Permission is granted to use, distribute, or modify this source,
- X * provided that this copyright notice remains intact.
- X *
- X * Scanf and printf routines for arbitrary precision integers.
- X */
- X
- X#include "stdarg.h"
- X#include "zmath.h"
- X
- X
- X#define OUTBUFSIZE 200 /* realloc size for output buffers */
- X
- X#define PUTCHAR(ch) math_chr(ch)
- X#define PUTSTR(str) math_str(str)
- X#define PRINTF1(fmt, a1) math_fmt(fmt, a1)
- X#define PRINTF2(fmt, a1, a2) math_fmt(fmt, a1, a2)
- X
- X
- Xlong _outdigits_ = 20; /* default digits for output */
- Xint _outmode_ = MODE_INITIAL; /* default output mode */
- X
- X
- X/*
- X * Output state that has been saved when diversions are done.
- X */
- Xtypedef struct iostate IOSTATE;
- Xstruct iostate {
- X IOSTATE *oldiostates; /* previous saved state */
- X long outdigits; /* digits for output */
- X int outmode; /* output mode */
- X FILE *outfp; /* file unit for output (if any) */
- X char *outbuf; /* output string buffer (if any) */
- X long outbufsize; /* current size of string buffer */
- X long outbufused; /* space used in string buffer */
- X BOOL outputisstring; /* TRUE if output is to string buffer */
- X};
- X
- X
- Xstatic IOSTATE *oldiostates = NULL; /* list of saved output states */
- Xstatic FILE *outfp = stdout; /* file unit for output */
- Xstatic char *outbuf = NULL; /* current diverted buffer */
- Xstatic BOOL outputisstring = FALSE;
- Xstatic long outbufsize;
- Xstatic long outbufused;
- X
- X
- X/*
- X * Routine to output a character either to a FILE
- X * handle or into a string.
- X */
- Xvoid
- Xmath_chr(ch)
- X{
- X char *cp;
- X
- X if (!outputisstring) {
- X fputc(ch, outfp);
- X return;
- X }
- X if (outbufused >= outbufsize) {
- X cp = (char *)realloc(outbuf, outbufsize + OUTBUFSIZE + 1);
- X if (cp == NULL)
- X math_error("Cannot realloc output string");
- X outbuf = cp;
- X outbufsize += OUTBUFSIZE;
- X }
- X outbuf[outbufused++] = (char)ch;
- X}
- X
- X
- X/*
- X * Routine to output a null-terminated string either
- X * to a FILE handle or into a string.
- X */
- Xvoid
- Xmath_str(str)
- X char *str;
- X{
- X char *cp;
- X int len;
- X
- X if (!outputisstring) {
- X fputs(str, outfp);
- X return;
- X }
- X len = strlen(str);
- X if ((outbufused + len) > outbufsize) {
- X cp = (char *)realloc(outbuf, outbufsize + len + OUTBUFSIZE + 1);
- X if (cp == NULL)
- X math_error("Cannot realloc output string");
- X outbuf = cp;
- X outbufsize += (len + OUTBUFSIZE);
- X }
- X memcpy(&outbuf[outbufused], str, len);
- X outbufused += len;
- X}
- X
- X
- X/*
- X * Output a null-terminated string either to a FILE handle or into a string,
- X * padded with spaces as needed so as to fit within the specified width.
- X * If width is positive, the spaces are added at the front of the string.
- X * If width is negative, the spaces are added at the end of the string.
- X * The complete string is always output, even if this overflows the width.
- X * No characters within the string are handled specially.
- X */
- Xvoid
- Xmath_fill(str, width)
- X char *str;
- X long width;
- X{
- X if (width > 0) {
- X width -= strlen(str);
- X while (width-- > 0)
- X PUTCHAR(' ');
- X PUTSTR(str);
- X } else {
- X width += strlen(str);
- X PUTSTR(str);
- X while (width++ < 0)
- X PUTCHAR(' ');
- X }
- X}
- X
- X
- X/*
- X * Routine to output a printf-style formatted string either
- X * to a FILE handle or into a string.
- X */
- X#ifdef VARARGS
- X# define VA_ALIST fmt, va_alist
- X# define VA_DCL char *fmt; va_dcl
- X#else
- X# ifdef __STDC__
- X# define VA_ALIST char *fmt, ...
- X# define VA_DCL
- X# else
- X# define VA_ALIST fmt
- X# define VA_DCL char *fmt;
- X# endif
- X#endif
- X/*VARARGS*/
- Xvoid
- Xmath_fmt(VA_ALIST)
- X VA_DCL
- X{
- X va_list ap;
- X char buf[200];
- X
- X#ifdef VARARGS
- X va_start(ap);
- X#else
- X va_start(ap, fmt);
- X#endif
- X vsprintf(buf, fmt, ap);
- X va_end(ap);
- X math_str(buf);
- X}
- X
- X
- X/*
- X * Flush the current output stream.
- X */
- Xvoid
- Xmath_flush()
- X{
- X if (!outputisstring)
- X fflush(outfp);
- X}
- X
- X
- X/*
- X * Divert further output so that it is saved into a string that will be
- X * returned later when the diversion is completed. The current state of
- X * output is remembered for later restoration. Diversions can be nested.
- X * Output diversion is only intended for saving output to "stdout".
- X */
- Xvoid
- Xmath_divertio()
- X{
- X register IOSTATE *sp;
- X
- X sp = (IOSTATE *) malloc(sizeof(IOSTATE));
- X if (sp == NULL)
- X math_error("No memory for diverting output");
- X sp->oldiostates = oldiostates;
- X sp->outdigits = _outdigits_;
- X sp->outmode = _outmode_;
- X sp->outfp = outfp;
- X sp->outbuf = outbuf;
- X sp->outbufsize = outbufsize;
- X sp->outbufused = outbufused;
- X sp->outputisstring = outputisstring;
- X
- X outbufused = 0;
- X outbufsize = 0;
- X outbuf = (char *) malloc(OUTBUFSIZE + 1);
- X if (outbuf == NULL)
- X math_error("Cannot allocate divert string");
- X outbufsize = OUTBUFSIZE;
- X outputisstring = TRUE;
- X oldiostates = sp;
- X}
- X
- X
- X/*
- X * Undivert output and return the saved output as a string. This also
- X * restores the output state to what it was before the diversion began.
- X * The string needs freeing by the caller when it is no longer needed.
- X */
- Xchar *
- Xmath_getdivertedio()
- X{
- X register IOSTATE *sp;
- X char *cp;
- X
- X sp = oldiostates;
- X if (sp == NULL)
- X math_error("No diverted state to restore");
- X cp = outbuf;
- X cp[outbufused] = '\0';
- X oldiostates = sp->oldiostates;
- X _outdigits_ = sp->outdigits;
- X _outmode_ = sp->outmode;
- X outfp = sp->outfp;
- X outbuf = sp->outbuf;
- X outbufsize = sp->outbufsize;
- X outbufused = sp->outbufused;
- X outbuf = sp->outbuf;
- X outputisstring = sp->outputisstring;
- X return cp;
- X}
- X
- X
- X/*
- X * Clear all diversions and set output back to the original destination.
- X * This is called when resetting the global state of the program.
- X */
- Xvoid
- Xmath_cleardiversions()
- X{
- X while (oldiostates)
- X free(math_getdivertedio());
- X}
- X
- X
- X/*
- X * Set the output routines to output to the specified FILE stream.
- X * This interacts with output diversion in the following manner.
- X * STDOUT diversion action
- X * ---- --------- ------
- X * yes yes set output to diversion string again.
- X * yes no set output to stdout.
- X * no yes set output to specified file.
- X * no no set output to specified file.
- X */
- Xvoid
- Xmath_setfp(newfp)
- X FILE *newfp;
- X{
- X outfp = newfp;
- X outputisstring = (oldiostates && (newfp == stdout));
- X}
- X
- X
- X/*
- X * Set the output mode for numeric output.
- X * This also returns the previous mode.
- X */
- Xint
- Xmath_setmode(newmode)
- X{
- X int oldmode;
- X
- X if ((newmode <= MODE_DEFAULT) || (newmode > MODE_MAX))
- X math_error("Setting illegal output mode");
- X oldmode = _outmode_;
- X _outmode_ = newmode;
- X return oldmode;
- X}
- X
- X
- X/*
- X * Set the number of digits for float or exponential output.
- X * This also returns the previous number of digits.
- X */
- Xlong
- Xmath_setdigits(newdigits)
- X long newdigits;
- X{
- X long olddigits;
- X
- X if (newdigits < 0)
- X math_error("Setting illegal number of digits");
- X olddigits = _outdigits_;
- X _outdigits_ = newdigits;
- X return olddigits;
- X}
- X
- X
- X/*
- X * Print an integer value as a hex number.
- X * Width is the number of columns to print the number in, including the
- X * sign if required. If zero, no extra output is done. If positive,
- X * leading spaces are typed if necessary. If negative, trailing spaces are
- X * typed if necessary. The special characters 0x appear to indicate the
- X * number is hex.
- X */
- X/*ARGSUSED*/
- Xvoid
- Xzprintx(z, width)
- X ZVALUE z;
- X long width;
- X{
- X register HALF *hp; /* current word to print */
- X int len; /* number of halfwords to type */
- X char *str;
- X
- X if (width) {
- X math_divertio();
- X zprintx(z, 0L);
- X str = math_getdivertedio();
- X math_fill(str, width);
- X free(str);
- X return;
- X }
- X len = z.len - 1;
- X if (zisneg(z))
- X PUTCHAR('-');
- X if ((len == 0) && (*z.v <= (FULL) 9)) {
- X len = '0' + *z.v;
- X PUTCHAR(len);
- X return;
- X }
- X hp = z.v + len;
- X PRINTF1("0x%x", (FULL) *hp--);
- X while (--len >= 0)
- X PRINTF1("%04x", (FULL) *hp--);
- X}
- X
- X
- X/*
- X * Print an integer value as a binary number.
- X * The special characters 0b appear to indicate the number is binary.
- X */
- X/*ARGSUSED*/
- Xvoid
- Xzprintb(z, width)
- X ZVALUE z;
- X long width;
- X{
- X register HALF *hp; /* current word to print */
- X int len; /* number of halfwords to type */
- X HALF val; /* current value */
- X HALF mask; /* current mask */
- X int didprint; /* nonzero if printed some digits */
- X int ch; /* current char */
- X char *str;
- X
- X if (width) {
- X math_divertio();
- X zprintb(z, 0L);
- X str = math_getdivertedio();
- X math_fill(str, width);
- X free(str);
- X return;
- X }
- X len = z.len - 1;
- X if (zisneg(z))
- X PUTCHAR('-');
- X if ((len == 0) && (*z.v <= (FULL) 1)) {
- X len = '0' + *z.v;
- X PUTCHAR(len);
- X return;
- X }
- X hp = z.v + len;
- X didprint = 0;
- X PUTSTR("0b");
- X while (len-- >= 0) {
- X val = *hp--;
- X mask = (1 << (BASEB - 1));
- X while (mask) {
- X ch = '0' + ((mask & val) != 0);
- X if (didprint || (ch != '0')) {
- X PUTCHAR(ch);
- X didprint = 1;
- X }
- X mask >>= 1;
- X }
- X }
- X}
- X
- X
- X/*
- X * Print an integer value as an octal number.
- X * The number begins with a leading 0 to indicate that it is octal.
- X */
- X/*ARGSUSED*/
- Xvoid
- Xzprinto(z, width)
- X ZVALUE z;
- X long width;
- X{
- X register HALF *hp; /* current word to print */
- X int len; /* number of halfwords to type */
- X int num1, num2; /* numbers to type */
- X int rem; /* remainder number of halfwords */
- X char *str;
- X
- X if (width) {
- X math_divertio();
- X zprinto(z, 0L);
- X str = math_getdivertedio();
- X math_fill(str, width);
- X free(str);
- X return;
- X }
- X if (zisneg(z))
- X PUTCHAR('-');
- X len = z.len;
- X if ((len == 1) && (*z.v <= (FULL) 7)) {
- X num1 = '0' + *z.v;
- X PUTCHAR(num1);
- X return;
- X }
- X hp = z.v + len - 1;
- X rem = len % 3;
- X switch (rem) { /* handle odd amounts first */
- X case 0:
- X num1 = (((FULL) hp[0]) << 8) + (((FULL) hp[-1]) >> 8);
- X num2 = (((FULL) (hp[-1] & 0xff)) << 16) + ((FULL) hp[-2]);
- X rem = 3;
- X break;
- X case 1:
- X num1 = 0;
- X num2 = (FULL) hp[0];
- X break;
- X case 2:
- X num1 = (((FULL) hp[0]) >> 8);
- X num2 = (((FULL) (hp[0] & 0xff)) << 16) + ((FULL) hp[-1]);
- X break;
- X }
- X if (num1)
- X PRINTF2("0%o%08o", num1, num2);
- X else
- X PRINTF1("0%o", num2);
- X len -= rem;
- X hp -= rem;
- X while (len > 0) { /* finish in groups of 3 halfwords */
- X num1 = (((FULL) hp[0]) << 8) + (((FULL) hp[-1]) >> 8);
- X num2 = (((FULL) (hp[-1] & 0xff)) << 16) + ((FULL) hp[-2]);
- X PRINTF2("%08o%08o", num1, num2);
- X hp -= 3;
- X len -= 3;
- X }
- X}
- X
- X
- X/*
- X * Print a decimal integer to the terminal.
- X * This works by dividing the number by 10^2^N for some N, and
- X * then doing this recursively on the quotient and remainder.
- X * Decimals supplies number of decimal places to print, with a decimal
- X * point at the right location, with zero meaning no decimal point.
- X * Width is the number of columns to print the number in, including the
- X * decimal point and sign if required. If zero, no extra output is done.
- X * If positive, leading spaces are typed if necessary. If negative, trailing
- X * spaces are typed if necessary. As examples of the effects of these values,
- X * (345,0,0) = "345", (345,2,0) = "3.45", (345,5,8) = " .00345".
- X */
- Xvoid
- Xzprintval(z, decimals, width)
- X ZVALUE z; /* number to be printed */
- X long decimals; /* number of decimal places */
- X long width; /* number of columns to print in */
- X{
- X int depth; /* maximum depth */
- X int n; /* current index into array */
- X int i; /* number to print */
- X long leadspaces; /* number of leading spaces to print */
- X long putpoint; /* digits until print decimal point */
- X long digits; /* number of digits of raw number */
- X BOOL output; /* TRUE if have output something */
- X BOOL neg; /* TRUE if negative */
- X ZVALUE quo, rem; /* quotient and remainder */
- X ZVALUE leftnums[32]; /* left parts of the number */
- X ZVALUE rightnums[32]; /* right parts of the number */
- X
- X if (decimals < 0)
- X decimals = 0;
- X if (width < 0)
- X width = 0;
- X neg = (z.sign != 0);
- X
- X leadspaces = width - neg - (decimals > 0);
- X z.sign = 0;
- X /*
- X * Find the 2^N power of ten which is greater than or equal
- X * to the number, calculating it the first time if necessary.
- X */
- X _tenpowers_[0] = _ten_;
- X depth = 0;
- X while ((_tenpowers_[depth].len < z.len) || (zrel(_tenpowers_[depth], z) <= 0)) {
- X depth++;
- X if (_tenpowers_[depth].len == 0)
- X zsquare(_tenpowers_[depth-1], &_tenpowers_[depth]);
- X }
- X /*
- X * Divide by smaller 2^N powers of ten until the parts are small
- X * enough to output. This algorithm walks through a binary tree
- X * where each node is a piece of the number to print, and such that
- X * we visit left nodes first. We do the needed recursion in line.
- X */
- X digits = 1;
- X output = FALSE;
- X n = 0;
- X putpoint = 0;
- X rightnums[0].len = 0;
- X leftnums[0] = z;
- X for (;;) {
- X while (n < depth) {
- X i = depth - n - 1;
- X zdiv(leftnums[n], _tenpowers_[i], &quo, &rem);
- X if (!ziszero(quo))
- X digits += (1L << i);
- X n++;
- X leftnums[n] = quo;
- X rightnums[n] = rem;
- X }
- X i = leftnums[n].v[0];
- X if (output || i || (n == 0)) {
- X if (!output) {
- X output = TRUE;
- X if (decimals > digits)
- X leadspaces -= decimals;
- X else
- X leadspaces -= digits;
- X while (--leadspaces >= 0)
- X PUTCHAR(' ');
- X if (neg)
- X PUTCHAR('-');
- X if (decimals) {
- X putpoint = (digits - decimals);
- X if (putpoint <= 0) {
- X PUTCHAR('.');
- X while (++putpoint <= 0)
- X PUTCHAR('0');
- X putpoint = 0;
- X }
- X }
- X }
- X i += '0';
- X PUTCHAR(i);
- X if (--putpoint == 0)
- X PUTCHAR('.');
- X }
- X while (rightnums[n].len == 0) {
- X if (n <= 0)
- X return;
- X if (leftnums[n].len)
- X zfree(leftnums[n]);
- X n--;
- X }
- X zfree(leftnums[n]);
- X leftnums[n] = rightnums[n];
- X rightnums[n].len = 0;
- X }
- X}
- X
- X
- X/*
- X * Read an integer value in decimal, hex, octal, or binary.
- X * Hex numbers are indicated by a leading "0x", binary with a leading "0b",
- X * and octal by a leading "0". Periods are skipped over, but any other
- X * extraneous character stops the scan.
- X */
- Xvoid
- Xatoz(s, res)
- X register char *s;
- X ZVALUE *res;
- X{
- X ZVALUE z, ztmp, digit;
- X HALF digval;
- X BOOL minus;
- X long shift;
- X
- X minus = FALSE;
- X shift = 0;
- X if (*s == '+')
- X s++;
- X else if (*s == '-') {
- X minus = TRUE;
- X s++;
- X }
- X if (*s == '0') { /* possibly hex, octal, or binary */
- X s++;
- X if ((*s >= '0') && (*s <= '7')) {
- X shift = 3;
- X } else if ((*s == 'x') || (*s == 'X')) {
- X shift = 4;
- X s++;
- X } else if ((*s == 'b') || (*s == 'B')) {
- X shift = 1;
- X s++;
- X }
- X }
- X digit.v = &digval;
- X digit.len = 1;
- X digit.sign = 0;
- X z = _zero_;
- X while (*s) {
- X digval = *s++;
- X if ((digval >= '0') && (digval <= '9'))
- X digval -= '0';
- X else if ((digval >= 'a') && (digval <= 'f') && shift)
- X digval -= ('a' - 10);
- X else if ((digval >= 'A') && (digval <= 'F') && shift)
- X digval -= ('A' - 10);
- X else if (digval == '.')
- X continue;
- X else
- X break;
- X if (shift)
- X zshift(z, shift, &ztmp);
- X else
- X zmuli(z, 10L, &ztmp);
- X zfree(z);
- X zadd(ztmp, digit, &z);
- X zfree(ztmp);
- X }
- X ztrim(&z);
- X if (minus && !ziszero(z))
- X z.sign = 1;
- X *res = z;
- X}
- X
- X/* END CODE */
- SHAR_EOF
- chmod 0644 calc2.9.0/zio.c || echo "restore of calc2.9.0/zio.c fails"
- set `wc -c calc2.9.0/zio.c`;Sum=$1
- if test "$Sum" != "14342"
- then echo original size 14342, current size $Sum;fi
- echo "x - extracting calc2.9.0/zmath.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/zmath.c &&
- X/*
- X * Copyright (c) 1993 David I. Bell
- X * Permission is granted to use, distribute, or modify this source,
- X * provided that this copyright notice remains intact.
- X *
- X * Extended precision integral arithmetic primitives
- X */
- X
- X#include "zmath.h"
- X
- X
- XHALF _twoval_[] = { 2 };
- XHALF _zeroval_[] = { 0 };
- XHALF _oneval_[] = { 1 };
- XHALF _tenval_[] = { 10 };
- X
- XZVALUE _zero_ = { _zeroval_, 1, 0};
- XZVALUE _one_ = { _oneval_, 1, 0 };
- XZVALUE _ten_ = { _tenval_, 1, 0 };
- X
- X
- X/*
- X * mask of given bits, rotated thru all bit positions twice
- X *
- X * bitmask[i] (1 << (i-1)), for -BASEB*4<=i<=BASEB*4
- X * rotmask[j][k] (1 << ((j+k-1)%BASEB)), for -BASEB*2<=j,k<=BASEB*2
- X */
- Xstatic HALF *bmask; /* actual rotation thru 8 cycles */
- Xstatic HALF **rmask; /* actual rotation pointers thru 2 cycles */
- XHALF *bitmask; /* bit rotation, norm 0 */
- X#if 0
- Xstatic HALF **rotmask; /* pointers to bit rotations, norm index */
- X#endif
- X
- XBOOL _math_abort_; /* nonzero to abort calculations */
- X
- X
- Xstatic void dadd MATH_PROTO((ZVALUE z1, ZVALUE z2, long y, long n));
- Xstatic BOOL dsub MATH_PROTO((ZVALUE z1, ZVALUE z2, long y, long n));
- Xstatic void dmul MATH_PROTO((ZVALUE z, FULL x, ZVALUE *dest));
- X
- X
- X#ifdef ALLOCTEST
- Xstatic long nalloc = 0;
- Xstatic long nfree = 0;
- X#endif
- X
- X
- XHALF *
- Xalloc(len)
- X long len;
- X{
- X HALF *hp;
- X
- X if (_math_abort_)
- X math_error("Calculation aborted");
- X hp = (HALF *) malloc(len * sizeof(HALF) + 2);
- X if (hp == 0)
- X math_error("Not enough memory");
- X#ifdef ALLOCTEST
- X ++nalloc;
- X#endif
- X return hp;
- X}
- X
- X
- X#ifdef ALLOCTEST
- Xvoid
- Xfreeh(h)
- X HALF *h;
- X{
- X if ((h != _zeroval_) && (h != _oneval_)) {
- X free(h);
- X ++nfree;
- X }
- X}
- X
- X
- Xvoid
- XallocStat()
- X{
- X fprintf(stderr, "nalloc: %ld nfree: %ld kept: %ld\n",
- X nalloc, nfree, nalloc - nfree);
- X}
- X#endif
- X
- X
- X/*
- X * Convert a normal integer to a number.
- X */
- Xvoid
- Xitoz(i, res)
- X long i;
- X ZVALUE *res;
- X{
- X long diddle, len;
- X
- X res->len = 1;
- X res->sign = 0;
- X diddle = 0;
- X if (i == 0) {
- X res->v = _zeroval_;
- X return;
- X }
- X if (i < 0) {
- X res->sign = 1;
- X i = -i;
- X if (i < 0) { /* fix most negative number */
- X diddle = 1;
- X i--;
- X }
- X }
- X if (i == 1) {
- X res->v = _oneval_;
- X return;
- X }
- X len = 1 + (((FULL) i) >= BASE);
- X res->len = len;
- X res->v = alloc(len);
- X res->v[0] = (HALF) (i + diddle);
- X if (len == 2)
- X res->v[1] = (HALF) (i / BASE);
- X}
- X
- X
- X/*
- X * Convert a number to a normal integer, as far as possible.
- X * If the number is out of range, the largest number is returned.
- X */
- Xlong
- Xztoi(z)
- X ZVALUE z;
- X{
- X long i;
- X
- X if (zisbig(z)) {
- X i = MAXFULL;
- X return (z.sign ? -i : i);
- X }
- X i = (zistiny(z) ? z1tol(z) : z2tol(z));
- X return (z.sign ? -i : i);
- X}
- X
- X
- X/*
- X * Make a copy of an integer value
- X */
- Xvoid
- Xzcopy(z, res)
- X ZVALUE z, *res;
- X{
- X res->sign = z.sign;
- X res->len = z.len;
- X if (zisleone(z)) { /* zero or plus or minus one are easy */
- X res->v = (z.v[0] ? _oneval_ : _zeroval_);
- X return;
- X }
- X res->v = alloc(z.len);
- X zcopyval(z, *res);
- X}
- X
- X
- X/*
- X * Add together two integers.
- X */
- Xvoid
- Xzadd(z1, z2, res)
- X ZVALUE z1, z2, *res;
- X{
- X ZVALUE dest;
- X HALF *p1, *p2, *pd;
- X long len;
- X FULL carry;
- X SIUNION sival;
- X
- X if (z1.sign && !z2.sign) {
- X z1.sign = 0;
- X zsub(z2, z1, res);
- X return;
- X }
- X if (z2.sign && !z1.sign) {
- X z2.sign = 0;
- X zsub(z1, z2, res);
- X return;
- X }
- X if (z2.len > z1.len) {
- X pd = z1.v; z1.v = z2.v; z2.v = pd;
- X len = z1.len; z1.len = z2.len; z2.len = len;
- X }
- X dest.len = z1.len + 1;
- X dest.v = alloc(dest.len);
- X dest.sign = z1.sign;
- X carry = 0;
- X pd = dest.v;
- X p1 = z1.v;
- X p2 = z2.v;
- X len = z2.len;
- X while (len--) {
- X sival.ivalue = ((FULL) *p1++) + ((FULL) *p2++) + carry;
- X *pd++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X len = z1.len - z2.len;
- X while (len--) {
- X sival.ivalue = ((FULL) *p1++) + carry;
- X *pd++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X *pd = (HALF)carry;
- X zquicktrim(dest);
- X *res = dest;
- X}
- X
- X
- X/*
- X * Subtract two integers.
- X */
- Xvoid
- Xzsub(z1, z2, res)
- X ZVALUE z1, z2, *res;
- X{
- X register HALF *h1, *h2, *hd;
- X long len1, len2;
- X FULL carry;
- X SIUNION sival;
- X ZVALUE dest;
- X
- X if (z1.sign != z2.sign) {
- X z2.sign = z1.sign;
- X zadd(z1, z2, res);
- X return;
- X }
- X len1 = z1.len;
- X len2 = z2.len;
- X if (len1 == len2) {
- X h1 = z1.v + len1 - 1;
- X h2 = z2.v + len2 - 1;
- X while ((len1 > 0) && ((FULL)*h1 == (FULL)*h2)) {
- X len1--;
- X h1--;
- X h2--;
- X }
- X if (len1 == 0) {
- X *res = _zero_;
- X return;
- X }
- X len2 = len1;
- X }
- X dest.sign = z1.sign;
- X carry = ((len1 < len2) || ((len1 == len2) && ((FULL)*h1 < (FULL)*h2)));
- X h1 = z1.v;
- X h2 = z2.v;
- X if (carry) {
- X carry = len1;
- X len1 = len2;
- X len2 = carry;
- X h1 = z2.v;
- X h2 = z1.v;
- X dest.sign = !dest.sign;
- X }
- X hd = alloc(len1);
- X dest.v = hd;
- X dest.len = len1;
- X len1 -= len2;
- X carry = 0;
- X while (--len2 >= 0) {
- X sival.ivalue = (BASE1 - ((FULL) *h1++)) + *h2++ + carry;
- X *hd++ = BASE1 - sival.silow;
- X carry = sival.sihigh;
- X }
- X while (--len1 >= 0) {
- X sival.ivalue = (BASE1 - ((FULL) *h1++)) + carry;
- X *hd++ = BASE1 - sival.silow;
- X carry = sival.sihigh;
- X }
- X if (hd[-1] == 0)
- X ztrim(&dest);
- X *res = dest;
- X}
- X
- X
- X#if 0
- X/*
- X * Multiply two integers together.
- X */
- Xvoid
- Xzmul(z1, z2, res)
- X ZVALUE z1, z2, *res;
- X{
- X register HALF *s1, *s2, *sd, *h1;
- X FULL mul, carry;
- X long len1, len2;
- X SIUNION sival;
- X ZVALUE dest;
- X
- X if (ziszero(z1) || ziszero(z2)) {
- X *res = _zero_;
- X return;
- X }
- X if (zisone(z1)) {
- X zcopy(z2, res);
- X return;
- X }
- X if (zisone(z2)) {
- X zcopy(z1, res);
- X return;
- X }
- X dest.len = z1.len + z2.len;
- X dest.v = alloc(dest.len);
- X dest.sign = (z1.sign != z2.sign);
- X zclearval(dest);
- X /*
- X * Swap the numbers if necessary to make the second one smaller.
- X */
- X if (z1.len < z2.len) {
- X len1 = z1.len;
- X z1.len = z2.len;
- X z2.len = len1;
- X s1 = z1.v;
- X z1.v = z2.v;
- X z2.v = s1;
- X }
- X /*
- X * Multiply the first number by each 'digit' of the second number
- X * and add the result to the total.
- X */
- X sd = dest.v;
- X s2 = z2.v;
- X for (len2 = z2.len; len2--; sd++) {
- X mul = (FULL) *s2++;
- X if (mul == 0)
- X continue;
- X h1 = sd;
- X s1 = z1.v;
- X carry = 0;
- X len1 = z1.len;
- X while (len1 >= 4) { /* expand the loop some */
- X len1 -= 4;
- X sival.ivalue = (mul * ((FULL) *s1++)) + ((FULL) *h1) + carry;
- X *h1++ = sival.silow;
- X sival.ivalue = (mul * ((FULL) *s1++)) + ((FULL) *h1) + ((FULL) sival.sihigh);
- X *h1++ = sival.silow;
- X sival.ivalue = (mul * ((FULL) *s1++)) + ((FULL) *h1) + ((FULL) sival.sihigh);
- X *h1++ = sival.silow;
- X sival.ivalue = (mul * ((FULL) *s1++)) + ((FULL) *h1) + ((FULL) sival.sihigh);
- X *h1++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X while (--len1 >= 0) {
- X sival.ivalue = (mul * ((FULL) *s1++)) + ((FULL) *h1) + carry;
- X *h1++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X while (carry) {
- X sival.ivalue = ((FULL) *h1) + carry;
- X *h1++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X }
- X ztrim(&dest);
- X *res = dest;
- X}
- X#endif
- X
- X
- X/*
- X * Multiply an integer by a small number.
- X */
- Xvoid
- Xzmuli(z, n, res)
- X ZVALUE z;
- X long n;
- X ZVALUE *res;
- X{
- X register HALF *h1, *sd;
- X FULL low;
- X FULL high;
- X FULL carry;
- X long len;
- X SIUNION sival;
- X ZVALUE dest;
- X
- X if ((n == 0) || ziszero(z)) {
- X *res = _zero_;
- X return;
- X }
- X if (n < 0) {
- X n = -n;
- X z.sign = !z.sign;
- X }
- X if (n == 1) {
- X zcopy(z, res);
- X return;
- X }
- X low = ((FULL) n) & BASE1;
- X high = ((FULL) n) >> BASEB;
- X dest.len = z.len + 2;
- X dest.v = alloc(dest.len);
- X dest.sign = z.sign;
- X /*
- X * Multiply by the low digit.
- X */
- X h1 = z.v;
- X sd = dest.v;
- X len = z.len;
- X carry = 0;
- X while (len--) {
- X sival.ivalue = ((FULL) *h1++) * low + carry;
- X *sd++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X *sd = (HALF)carry;
- X /*
- X * If there was only one digit, then we are all done except
- X * for trimming the number if there was no last carry.
- X */
- X if (high == 0) {
- X dest.len--;
- X if (carry == 0)
- X dest.len--;
- X *res = dest;
- X return;
- X }
- X /*
- X * Need to multiply by the high digit and add it into the
- X * previous value. Clear the final word of rubbish first.
- X */
- X *(++sd) = 0;
- X h1 = z.v;
- X sd = dest.v + 1;
- X len = z.len;
- X carry = 0;
- X while (len--) {
- X sival.ivalue = ((FULL) *h1++) * high + ((FULL) *sd) + carry;
- X *sd++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X *sd = (HALF)carry;
- X zquicktrim(dest);
- X *res = dest;
- X}
- X
- X
- X/*
- X * Divide two numbers by their greatest common divisor.
- X * This is useful for reducing the numerator and denominator of
- X * a fraction to its lowest terms.
- X */
- Xvoid
- Xzreduce(z1, z2, z1res, z2res)
- X ZVALUE z1, z2, *z1res, *z2res;
- X{
- X ZVALUE tmp;
- X
- X if (zisleone(z1) || zisleone(z2))
- X tmp = _one_;
- X else
- X zgcd(z1, z2, &tmp);
- X if (zisunit(tmp)) {
- X zcopy(z1, z1res);
- X zcopy(z2, z2res);
- X } else {
- X zquo(z1, tmp, z1res);
- X zquo(z2, tmp, z2res);
- X }
- X zfree(tmp);
- X}
- X
- X
- X/*
- X * Divide two numbers to obtain a quotient and remainder.
- X * This algorithm is taken from
- X * Knuth, The Art of Computer Programming, vol 2: Seminumerical Algorithms.
- X * Slight modifications were made to speed this mess up.
- X */
- Xvoid
- Xzdiv(z1, z2, res, rem)
- X ZVALUE z1, z2, *res, *rem;
- X{
- X long i, j, k;
- X register HALF *q, *pp;
- X SIUNION pair; /* pair of halfword values */
- X HALF h2, v2;
- X long y;
- X FULL x;
- X ZVALUE ztmp1, ztmp2, ztmp3, quo;
- X
- X if (ziszero(z2))
- X math_error("Division by zero");
- X if (ziszero(z1)) {
- X *res = _zero_;
- X *rem = _zero_;
- X return;
- X }
- X if (zisone(z2)) {
- X zcopy(z1, res);
- X *rem = _zero_;
- X return;
- X }
- X i = 32768;
- X j = 0;
- X k = (long) z2.v[z2.len - 1];
- X while (! (k & i)) {
- X j ++;
- X i >>= 1;
- X }
- X ztmp1.v = alloc(z1.len + 1);
- X ztmp1.len = z1.len + 1;
- X zcopyval(z1, ztmp1);
- X ztmp1.v[z1.len] = 0;
- X ztmp1.sign = 0;
- X ztmp2.v = alloc(z2.len);
- X ztmp2.len = z2.len;
- X ztmp2.sign = 0;
- X zcopyval(z2, ztmp2);
- X if (zrel(ztmp1, ztmp2) < 0) {
- X rem->v = ztmp1.v;
- X rem->sign = z1.sign;
- X rem->len = z1.len;
- X zfree(ztmp2);
- X *res = _zero_;
- X return;
- X }
- X quo.len = z1.len - z2.len + 1;
- X quo.v = alloc(quo.len);
- X quo.sign = z1.sign != z2.sign;
- X zclearval(quo);
- X
- X ztmp3.v = zalloctemp(z2.len + 1);
- X
- X /*
- X * Normalize z1 and z2
- X */
- X zshiftl(ztmp1, j);
- X zshiftl(ztmp2, j);
- X
- X k = ztmp1.len - ztmp2.len;
- X q = quo.v + quo.len;
- X y = ztmp1.len - 1;
- X h2 = ztmp2.v [ztmp2.len - 1];
- X v2 = 0;
- X if (ztmp2.len >= 2)
- X v2 = ztmp2.v [ztmp2.len - 2];
- X for (;k--; --y) {
- X pp = ztmp1.v + y - 1;
- X pair.silow = pp[0];
- X pair.sihigh = pp[1];
- X if (ztmp1.v[y] == h2)
- X x = BASE1;
- X else
- X x = pair.ivalue / h2;
- X if (x) {
- X while (pair.ivalue - x * h2 < BASE &&
- X v2 * x > (pair.ivalue - x * h2) * BASE + ztmp1.v [y-2]) {
- X --x;
- X }
- X dmul(ztmp2, x, &ztmp3);
- X#ifdef divblab
- X printf(" x: %ld\n", x);
- X printf("ztmp1: ");
- X printz(ztmp1);
- X printf("ztmp2: ");
- X printz(ztmp2);
- X printf("ztmp3: ");
- X printz(ztmp3);
- X#endif
- X if (dsub(ztmp1, ztmp3, y, ztmp2.len)) {
- X --x;
- X /*
- X printf("adding back\n");
- X */
- X dadd(ztmp1, ztmp2, y, ztmp2.len);
- X }
- X }
- X ztrim(&ztmp1);
- X *--q = (HALF)x;
- X }
- X zshiftr(ztmp1, j);
- X *rem = ztmp1;
- X ztrim(rem);
- X zfree(ztmp2);
- X ztrim(&quo);
- X *res = quo;
- X}
- X
- X
- X/*
- X * Return the quotient and remainder of an integer divided by a small
- X * number. A nonzero remainder is only meaningful when both numbers
- X * are positive.
- X */
- Xlong
- Xzdivi(z, n, res)
- X ZVALUE z, *res;
- X long n;
- X{
- X register HALF *h1, *sd;
- X FULL val;
- X HALF divval[2];
- X ZVALUE div;
- X ZVALUE dest;
- X long len;
- X
- X if (n == 0)
- X math_error("Division by zero");
- X if (ziszero(z)) {
- X *res = _zero_;
- X return 0;
- X }
- X if (n < 0) {
- X n = -n;
- X z.sign = !z.sign;
- X }
- X if (n == 1) {
- X zcopy(z, res);
- X return 0;
- X }
- X /*
- X * If the division is by a large number, then call the normal
- X * divide routine.
- X */
- X if (n & ~BASE1) {
- X div.sign = 0;
- X div.len = 2;
- X div.v = divval;
- X divval[0] = (HALF) n;
- X divval[1] = ((FULL) n) >> BASEB;
- X zdiv(z, div, res, &dest);
- X n = (zistiny(dest) ? z1tol(dest) : z2tol(dest));
- X zfree(dest);
- X return n;
- X }
- X /*
- X * Division is by a small number, so we can be quick about it.
- X */
- X len = z.len;
- X dest.sign = z.sign;
- X dest.len = len;
- X dest.v = alloc(len);
- X h1 = z.v + len - 1;
- X sd = dest.v + len - 1;
- X val = 0;
- X while (len--) {
- X val = ((val << BASEB) + ((FULL) *h1--));
- X *sd-- = val / n;
- X val %= n;
- X }
- X zquicktrim(dest);
- X *res = dest;
- X return val;
- X}
- X
- X
- X/*
- X * Return the quotient of two numbers.
- X * This works the same as zdiv, except that the remainer is not returned.
- X */
- Xvoid
- Xzquo(z1, z2, res)
- X ZVALUE z1, z2, *res;
- X{
- X long i, j, k;
- X register HALF *q, *pp;
- X SIUNION pair; /* pair of halfword values */
- X HALF h2, v2;
- X long y;
- X FULL x;
- X ZVALUE ztmp1, ztmp2, ztmp3, quo;
- X
- X if (ziszero(z2))
- X math_error("Division by zero");
- X if (ziszero(z1)) {
- X *res = _zero_;
- X return;
- X }
- X if (zisone(z2)) {
- X zcopy(z1, res);
- X return;
- X }
- X i = 32768;
- X j = 0;
- X k = (long) z2.v[z2.len - 1];
- X while (! (k & i)) {
- X j ++;
- X i >>= 1;
- X }
- X ztmp1.v = alloc(z1.len + 1);
- X ztmp1.len = z1.len + 1;
- X zcopyval(z1, ztmp1);
- X ztmp1.v[z1.len] = 0;
- X ztmp1.sign = 0;
- X ztmp2.v = alloc(z2.len);
- X ztmp2.len = z2.len;
- X ztmp2.sign = 0;
- X zcopyval(z2, ztmp2);
- X if (zrel(ztmp1, ztmp2) < 0) {
- X zfree(ztmp1);
- X zfree(ztmp2);
- X *res = _zero_;
- X return;
- X }
- X quo.len = z1.len - z2.len + 1;
- X quo.v = alloc(quo.len);
- X quo.sign = z1.sign != z2.sign;
- X zclearval(quo);
- X
- X ztmp3.v = zalloctemp(z2.len + 1);
- X
- X /*
- X * Normalize z1 and z2
- X */
- X zshiftl(ztmp1, j);
- X zshiftl(ztmp2, j);
- X
- X k = ztmp1.len - ztmp2.len;
- X q = quo.v + quo.len;
- X y = ztmp1.len - 1;
- X h2 = ztmp2.v [ztmp2.len - 1];
- X v2 = 0;
- X if (ztmp2.len >= 2)
- X v2 = ztmp2.v [ztmp2.len - 2];
- X for (;k--; --y) {
- X pp = ztmp1.v + y - 1;
- X pair.silow = pp[0];
- X pair.sihigh = pp[1];
- X if (ztmp1.v[y] == h2)
- X x = BASE1;
- X else
- X x = pair.ivalue / h2;
- X if (x) {
- X while (pair.ivalue - x * h2 < BASE &&
- X v2 * x > (pair.ivalue - x * h2) * BASE + ztmp1.v [y-2]) {
- X --x;
- X }
- X dmul(ztmp2, x, &ztmp3);
- X if (dsub(ztmp1, ztmp3, y, ztmp2.len)) {
- X --x;
- X dadd(ztmp1, ztmp2, y, ztmp2.len);
- X }
- X }
- X ztrim(&ztmp1);
- X *--q = (HALF)x;
- X }
- X zfree(ztmp1);
- X zfree(ztmp2);
- X ztrim(&quo);
- X *res = quo;
- X}
- X
- X
- X/*
- X * Compute the remainder after dividing one number by another.
- X * This is only defined for positive z2 values.
- X * The result is normalized to lie in the range 0 to z2-1.
- X */
- Xvoid
- Xzmod(z1, z2, rem)
- X ZVALUE z1, z2, *rem;
- X{
- X long i, j, k, neg;
- X register HALF *pp;
- X SIUNION pair; /* pair of halfword values */
- X HALF h2, v2;
- X long y;
- X FULL x;
- X ZVALUE ztmp1, ztmp2, ztmp3;
- X
- X if (ziszero(z2))
- X math_error("Division by zero");
- X if (zisneg(z2))
- X math_error("Non-positive modulus");
- X if (ziszero(z1) || zisunit(z2)) {
- X *rem = _zero_;
- X return;
- X }
- X if (zistwo(z2)) {
- X if (zisodd(z1))
- X *rem = _one_;
- X else
- X *rem = _zero_;
- X return;
- X }
- X neg = z1.sign;
- X z1.sign = 0;
- X
- X /*
- X * Do a quick check to see if the absolute value of the number
- X * is less than the modulus. If so, then the result is just a
- X * subtract or a copy.
- X */
- X h2 = z1.v[z1.len - 1];
- X v2 = z2.v[z2.len - 1];
- X if ((z1.len < z2.len) || ((z1.len == z2.len) && (h2 < v2))) {
- X if (neg)
- X zsub(z2, z1, rem);
- X else
- X zcopy(z1, rem);
- X return;
- X }
- X
- X /*
- X * Do another quick check to see if the number is positive and
- X * between the size of the modulus and twice the modulus.
- X * If so, then the answer is just another subtract.
- X */
- X if (!neg && (z1.len == z2.len) && (h2 > v2) &&
- X (((FULL) h2) < 2 * ((FULL) v2)))
- X {
- X zsub(z1, z2, rem);
- X return;
- X }
- X
- X /*
- X * If the modulus is an exact power of two, then the result
- X * can be obtained by ignoring the high bits of the number.
- X * This truncation assumes that the number of words for the
- X * number is at least as large as the number of words in the
- X * modulus, which is true at this point.
- X */
- X if (((v2 & -v2) == v2) && zisonebit(z2)) { /* ASSUMES 2'S COMP */
- X i = zhighbit(z2);
- X z1.len = (i + BASEB - 1) / BASEB;
- X zcopy(z1, &ztmp1);
- X i %= BASEB;
- X if (i)
- X ztmp1.v[ztmp1.len - 1] &= ((((HALF) 1) << i) - 1);
- X ztmp2.len = 0;
- X goto gotanswer;
- X }
- X
- X /*
- X * If the modulus is one less than an exact power of two, then
- X * the result can be simplified similarly to "casting out 9's".
- X * Only do this simplification for large enough modulos.
- X */
- X if ((z2.len > 1) && (z2.v[0] == BASE1) && zisallbits(z2)) {
- X i = -(zhighbit(z2) + 1);
- X zcopy(z1, &ztmp1);
- X z1 = ztmp1;
- X while ((k = zrel(z1, z2)) > 0) {
- X ztmp1 = _zero_;
- X while (!ziszero(z1)) {
- X zand(z1, z2, &ztmp2);
- X zadd(ztmp2, ztmp1, &ztmp3);
- X zfree(ztmp1);
- X zfree(ztmp2);
- X ztmp1 = ztmp3;
- X zshift(z1, i, &ztmp2);
- X zfree(z1);
- X z1 = ztmp2;
- X }
- X zfree(z1);
- X z1 = ztmp1;
- X }
- X if (k == 0) {
- X zfree(ztmp1);
- X *rem = _zero_;
- X return;
- X }
- X ztmp2.len = 0;
- X goto gotanswer;
- X }
- X
- X /*
- X * Must actually do the divide.
- X */
- X i = 32768;
- X j = 0;
- X k = (long) z2.v[z2.len - 1];
- X while (! (k & i)) {
- X j ++;
- X i >>= 1;
- X }
- X ztmp1.v = alloc(z1.len + 1);
- X ztmp1.len = z1.len + 1;
- X zcopyval(z1, ztmp1);
- X ztmp1.v[z1.len] = 0;
- X ztmp1.sign = 0;
- X ztmp2.v = alloc(z2.len);
- X ztmp2.len = z2.len;
- X ztmp2.sign = 0;
- X zcopyval(z2, ztmp2);
- X if (zrel(ztmp1, ztmp2) < 0)
- X goto gotanswer;
- X
- X ztmp3.v = zalloctemp(z2.len + 1);
- X
- X /*
- X * Normalize z1 and z2
- X */
- X zshiftl(ztmp1, j);
- X zshiftl(ztmp2, j);
- X
- X k = ztmp1.len - ztmp2.len;
- X y = ztmp1.len - 1;
- X h2 = ztmp2.v [ztmp2.len - 1];
- X v2 = 0;
- X if (ztmp2.len >= 2)
- X v2 = ztmp2.v [ztmp2.len - 2];
- X for (;k--; --y) {
- X pp = ztmp1.v + y - 1;
- X pair.silow = pp[0];
- X pair.sihigh = pp[1];
- X if (ztmp1.v[y] == h2)
- X x = BASE1;
- X else
- X x = pair.ivalue / h2;
- X if (x) {
- X while (pair.ivalue - x * h2 < BASE &&
- X v2 * x > (pair.ivalue - x * h2) * BASE + ztmp1.v [y-2]) {
- X --x;
- X }
- X dmul(ztmp2, x, &ztmp3);
- X if (dsub(ztmp1, ztmp3, y, ztmp2.len))
- X dadd(ztmp1, ztmp2, y, ztmp2.len);
- X }
- X ztrim(&ztmp1);
- X }
- X zshiftr(ztmp1, j);
- X
- Xgotanswer:
- X ztrim(&ztmp1);
- X if (ztmp2.len)
- X zfree(ztmp2);
- X if (neg && !ziszero(ztmp1)) {
- X zsub(z2, ztmp1, rem);
- X zfree(ztmp1);
- X } else
- X *rem = ztmp1;
- X}
- X
- X
- X/*
- X * Calculate the mod of an integer by a small number.
- X * This is only defined for positive moduli.
- X */
- Xlong
- Xzmodi(z, n)
- X ZVALUE z;
- X long n;
- X{
- X register HALF *h1;
- X FULL val;
- X HALF divval[2];
- X ZVALUE div;
- X ZVALUE temp;
- X long len;
- X
- X if (n == 0)
- X math_error("Division by zero");
- X if (n < 0)
- X math_error("Non-positive modulus");
- X if (ziszero(z) || (n == 1))
- X return 0;
- X if (zisone(z))
- X return 1;
- X /*
- X * If the modulus is by a large number, then call the normal
- X * modulo routine.
- X */
- X if (n & ~BASE1) {
- X div.sign = 0;
- X div.len = 2;
- X div.v = divval;
- X divval[0] = (HALF) n;
- X divval[1] = ((FULL) n) >> BASEB;
- X zmod(z, div, &temp);
- X n = (zistiny(temp) ? z1tol(temp) : z2tol(temp));
- X zfree(temp);
- X return n;
- X }
- X /*
- X * The modulus is by a small number, so we can do this quickly.
- X */
- X len = z.len;
- X h1 = z.v + len - 1;
- X val = 0;
- X while (len--)
- X val = ((val << BASEB) + ((FULL) *h1--)) % n;
- X if (z.sign)
- X val = n - val;
- X return val;
- X}
- X
- X
- X/*
- X * Return whether or not one number exactly divides another one.
- X * Returns TRUE if division occurs with no remainder.
- X * z1 is the number to be divided by z2.
- X */
- XBOOL
- Xzdivides(z1, z2)
- X ZVALUE z1, z2; /* numbers to test division into and by */
- X{
- X ZVALUE temp;
- X long cv;
- X
- X z1.sign = 0;
- X z2.sign = 0;
- X /*
- X * Take care of obvious cases first
- X */
- X if (zisleone(z2)) { /* division by zero or one */
- X if (*z2.v == 0)
- X math_error("Division by zero");
- X return TRUE;
- X }
- X if (ziszero(z1)) /* everything divides zero */
- X return TRUE;
- X if (z1.len < z2.len) /* quick size comparison */
- X return FALSE;
- X if ((z1.len == z2.len) && (z1.v[z1.len-1] < z2.v[z2.len-1])) /* more */
- X return FALSE;
- X if (zisodd(z1) && ziseven(z2)) /* can't divide odd by even */
- X return FALSE;
- X if (zlowbit(z1) < zlowbit(z2)) /* can't have smaller power of two */
- X return FALSE;
- X cv = zrel(z1, z2); /* can't divide smaller number */
- X if (cv <= 0)
- X return (cv == 0);
- X /*
- X * Now do the real work. Divisor divides dividend if the gcd of the
- X * two numbers equals the divisor.
- X */
- X zgcd(z1, z2, &temp);
- X cv = zcmp(z2, temp);
- X zfree(temp);
- X return (cv == 0);
- X}
- X
- X
- X/*
- X * Compute the logical OR of two numbers
- X */
- Xvoid
- Xzor(z1, z2, res)
- X ZVALUE z1, z2, *res;
- X{
- X register HALF *sp, *dp;
- X long len;
- X ZVALUE bz, lz, dest;
- X
- X if (z1.len >= z2.len) {
- X bz = z1;
- X lz = z2;
- X } else {
- X bz = z2;
- X lz = z1;
- X }
- X dest.len = bz.len;
- X dest.v = alloc(dest.len);
- X dest.sign = 0;
- X zcopyval(bz, dest);
- X len = lz.len;
- X sp = lz.v;
- X dp = dest.v;
- X while (len--)
- X *dp++ |= *sp++;
- X *res = dest;
- X}
- X
- X
- X/*
- X * Compute the logical AND of two numbers.
- X */
- Xvoid
- Xzand(z1, z2, res)
- X ZVALUE z1, z2, *res;
- X{
- X register HALF *h1, *h2, *hd;
- X register long len;
- X ZVALUE dest;
- X
- X len = ((z1.len <= z2.len) ? z1.len : z2.len);
- X h1 = &z1.v[len-1];
- X h2 = &z2.v[len-1];
- X while ((len > 1) && ((*h1 & *h2) == 0)) {
- X h1--;
- X h2--;
- X len--;
- X }
- X dest.len = len;
- X dest.v = alloc(len);
- X dest.sign = 0;
- X h1 = z1.v;
- X h2 = z2.v;
- X hd = dest.v;
- X while (len--)
- X *hd++ = (*h1++ & *h2++);
- X *res = dest;
- X}
- X
- X
- X/*
- X * Compute the logical XOR of two numbers.
- X */
- Xvoid
- Xzxor(z1, z2, res)
- X ZVALUE z1, z2, *res;
- X{
- X register HALF *sp, *dp;
- X long len;
- X ZVALUE bz, lz, dest;
- X
- X if (z1.len == z2.len) {
- X for (len = z1.len; ((len > 1) && (z1.v[len-1] == z2.v[len-1])); len--) ;
- X z1.len = len;
- X z2.len = len;
- X }
- X if (z1.len >= z2.len) {
- X bz = z1;
- X lz = z2;
- X } else {
- X bz = z2;
- X lz = z1;
- X }
- X dest.len = bz.len;
- X dest.v = alloc(dest.len);
- X dest.sign = 0;
- X zcopyval(bz, dest);
- X len = lz.len;
- X sp = lz.v;
- X dp = dest.v;
- X while (len--)
- X *dp++ ^= *sp++;
- X *res = dest;
- X}
- X
- X
- X/*
- X * Shift a number left (or right) by the specified number of bits.
- X * Positive shift means to the left. When shifting right, rightmost
- X * bits are lost. The sign of the number is preserved.
- X */
- Xvoid
- Xzshift(z, n, res)
- X ZVALUE z, *res;
- X long n;
- X{
- X ZVALUE ans;
- X long hc; /* number of halfwords shift is by */
- X
- X if (ziszero(z)) {
- X *res = _zero_;
- X return;
- X }
- X if (n == 0) {
- X zcopy(z, res);
- X return;
- X }
- X /*
- X * If shift value is negative, then shift right.
- X * Check for large shifts, and handle word-sized shifts quickly.
- X */
- X if (n < 0) {
- X n = -n;
- X if ((n < 0) || (n >= (z.len * BASEB))) {
- X *res = _zero_;
- X return;
- X }
- X hc = n / BASEB;
- X n %= BASEB;
- X z.v += hc;
- X z.len -= hc;
- X ans.len = z.len;
- X ans.v = alloc(ans.len);
- X ans.sign = z.sign;
- X zcopyval(z, ans);
- X if (n > 0) {
- X zshiftr(ans, n);
- X ztrim(&ans);
- X }
- X if (ziszero(ans)) {
- X zfree(ans);
- X ans = _zero_;
- X }
- X *res = ans;
- X return;
- X }
- X /*
- X * Shift value is positive, so shift leftwards.
- X * Check specially for a shift of the value 1, since this is common.
- X * Also handle word-sized shifts quickly.
- X */
- X if (zisunit(z)) {
- X zbitvalue(n, res);
- X res->sign = z.sign;
- X return;
- X }
- X hc = n / BASEB;
- X n %= BASEB;
- X ans.len = z.len + hc + 1;
- X ans.v = alloc(ans.len);
- X ans.sign = z.sign;
- X if (hc > 0)
- X memset((char *) ans.v, 0, hc * sizeof(HALF));
- X memcpy((char *) (ans.v + hc),
- X (char *) z.v, z.len * sizeof(HALF));
- X ans.v[ans.len - 1] = 0;
- X if (n > 0) {
- X ans.v += hc;
- X ans.len -= hc;
- X zshiftl(ans, n);
- X ans.v -= hc;
- X ans.len += hc;
- X }
- X ztrim(&ans);
- X *res = ans;
- X}
- X
- X
- X/*
- X * Return the position of the lowest bit which is set in the binary
- X * representation of a number (counting from zero). This is the highest
- X * power of two which evenly divides the number.
- X */
- Xlong
- Xzlowbit(z)
- X ZVALUE z;
- X{
- X register HALF *zp;
- X long n;
- X HALF dataval;
- X HALF *bitval;
- X
- X n = 0;
- X for (zp = z.v; *zp == 0; zp++)
- X if (++n >= z.len)
- X return 0;
- X dataval = *zp;
- X bitval = bitmask;
- X while ((*(bitval++) & dataval) == 0) {
- X }
- X return (n*BASEB)+(bitval-bitmask-1);
- X}
- X
- X
- X/*
- X * Return the position of the highest bit which is set in the binary
- X * representation of a number (counting from zero). This is the highest power
- X * of two which is less than or equal to the number (which is assumed nonzero).
- X */
- Xlong
- Xzhighbit(z)
- X ZVALUE z;
- X{
- X HALF dataval;
- X HALF *bitval;
- X
- X dataval = z.v[z.len-1];
- X if (dataval) {
- X bitval = bitmask+BASEB;
- X while ((*(--bitval) & dataval) == 0) {
- X }
- X }
- X return (z.len*BASEB)+(bitval-bitmask-BASEB);
- X}
- X
- X
- X#if 0
- X/*
- X * Reverse the bits of a particular range of bits of a number.
- X *
- X * This function returns an integer with bits a thru b swapped.
- X * That is, bit a is swapped with bit b, bit a+1 is swapped with b-1,
- X * and so on.
- X *
- X * As a special case, if the ending bit position is < 0, is it taken to
- X * mean the highest bit set. Thus zbitrev(0, -1, z, &res) will
- X * perform a complete bit reverse of the number 'z'.
- X *
- X * As a special case, if the starting bit position is < 0, is it taken to
- X * mean the lowest bit set. Thus zbitrev(-1, -1, z, &res) is the
- X * same as zbitrev(lowbit(z), highbit(z), z, &res).
- X *
- X * Note that the low order bit number is taken to be 0. Also, bitrev
- X * ignores the sign of the number.
- X *
- X * Bits beyond the highest bit are taken to be zero. Thus the calling
- X * bitrev(0, 100, _one_, &res) will result in a value of 2^100.
- X */
- Xvoid
- Xzbitrev(low, high, z, res)
- X long low; /* lowest bit to reverse, <0 => lowbit(z) */
- X long high; /* highest bit to reverse, <0 => highbit(z) */
- X ZVALUE z; /* value to bit reverse */
- X ZVALUE *res; /* resulting bit reverse number */
- X{
- X}
- X#endif
- X
- X
- X/*
- X * Return whether or not the specifed bit number is set in a number.
- X * Rightmost bit of a number is bit 0.
- X */
- XBOOL
- Xzisset(z, n)
- X ZVALUE z;
- X long n;
- X{
- X if ((n < 0) || ((n / BASEB) >= z.len))
- X return FALSE;
- X return ((z.v[n / BASEB] & (((HALF) 1) << (n % BASEB))) != 0);
- X}
- X
- X
- X/*
- X * Check whether or not a number has exactly one bit set, and
- X * thus is an exact power of two. Returns TRUE if so.
- X */
- XBOOL
- Xzisonebit(z)
- X ZVALUE z;
- X{
- X register HALF *hp;
- X register LEN len;
- X
- X if (ziszero(z) || zisneg(z))
- X return FALSE;
- X hp = z.v;
- X len = z.len;
- X while (len > 4) {
- X len -= 4;
- X if (*hp++ || *hp++ || *hp++ || *hp++)
- X return FALSE;
- X }
- X while (--len > 0) {
- X if (*hp++)
- X return FALSE;
- X }
- X return ((*hp & -*hp) == *hp); /* NEEDS 2'S COMPLEMENT */
- X}
- X
- X
- X/*
- X * Check whether or not a number has all of its bits set below some
- X * bit position, and thus is one less than an exact power of two.
- X * Returns TRUE if so.
- X */
- XBOOL
- Xzisallbits(z)
- X ZVALUE z;
- X{
- X register HALF *hp;
- X register LEN len;
- X HALF digit;
- X
- X if (ziszero(z) || zisneg(z))
- X return FALSE;
- X hp = z.v;
- X len = z.len;
- X while (len > 4) {
- X len -= 4;
- X if ((*hp++ != BASE1) || (*hp++ != BASE1) ||
- X (*hp++ != BASE1) || (*hp++ != BASE1))
- X return FALSE;
- X }
- X while (--len > 0) {
- X if (*hp++ != BASE1)
- X return FALSE;
- X }
- X digit = *hp + 1;
- X return ((digit & -digit) == digit); /* NEEDS 2'S COMPLEMENT */
- X}
- X
- X
- X/*
- X * Return the number whose binary representation contains only one bit which
- X * is in the specified position (counting from zero). This is equivilant
- X * to raising two to the given power.
- X */
- Xvoid
- Xzbitvalue(n, res)
- X long n;
- X ZVALUE *res;
- X{
- X ZVALUE z;
- X
- X if (n < 0) n = 0;
- X z.sign = 0;
- X z.len = (n / BASEB) + 1;
- X z.v = alloc(z.len);
- X zclearval(z);
- X z.v[z.len-1] = (((HALF) 1) << (n % BASEB));
- X *res = z;
- X}
- X
- X
- X/*
- X * Compare a number against zero.
- X * Returns the sgn function of the number (-1, 0, or 1).
- X */
- XFLAG
- Xztest(z)
- X ZVALUE z;
- X{
- X register int sign;
- X register HALF *h;
- X register long len;
- X
- X sign = 1;
- X if (z.sign)
- X sign = -sign;
- X h = z.v;
- X len = z.len;
- X while (len--)
- X if (*h++)
- X return sign;
- X return 0;
- X}
- X
- X
- X/*
- X * Compare two numbers to see which is larger.
- X * Returns -1 if first number is smaller, 0 if they are equal, and 1 if
- X * first number is larger. This is the same result as ztest(z2-z1).
- X */
- XFLAG
- Xzrel(z1, z2)
- X ZVALUE z1, z2;
- X{
- X register HALF *h1, *h2;
- X register long len1, len2;
- X int sign;
- X
- X sign = 1;
- X if (z1.sign < z2.sign)
- X return 1;
- X if (z2.sign < z1.sign)
- X return -1;
- X if (z2.sign)
- X sign = -1;
- X len1 = z1.len;
- X len2 = z2.len;
- X h1 = z1.v + z1.len - 1;
- X h2 = z2.v + z2.len - 1;
- X while (len1 > len2) {
- X if (*h1--)
- X return sign;
- X len1--;
- X }
- X while (len2 > len1) {
- X if (*h2--)
- X return -sign;
- X len2--;
- X }
- X while (len1--) {
- X if (*h1-- != *h2--)
- X break;
- X }
- X if ((len1 = *++h1) > (len2 = *++h2))
- X return sign;
- X if (len1 < len2)
- X return -sign;
- X return 0;
- X}
- X
- X
- X/*
- X * Compare two numbers to see if they are equal or not.
- X * Returns TRUE if they differ.
- X */
- XBOOL
- Xzcmp(z1, z2)
- X ZVALUE z1, z2;
- X{
- X register HALF *h1, *h2;
- X register long len;
- X
- X if ((z1.sign != z2.sign) || (z1.len != z2.len) || (*z1.v != *z2.v))
- X return TRUE;
- X len = z1.len;
- X h1 = z1.v;
- X h2 = z2.v;
- X while (len-- > 0) {
- X if (*h1++ != *h2++)
- X return TRUE;
- X }
- X return FALSE;
- X}
- X
- X
- X/*
- X * Internal utility subroutines
- X */
- Xstatic void
- Xdadd(z1, z2, y, n)
- X ZVALUE z1, z2;
- X long y, n;
- X{
- X HALF *s1, *s2;
- X short carry;
- X long sum;
- X
- X s1 = z1.v + y - n;
- X s2 = z2.v;
- X carry = 0;
- X while (n--) {
- X sum = (long)*s1 + (long)*s2 + carry;
- X carry = 0;
- X if (sum >= BASE) {
- X sum -= BASE;
- X carry = 1;
- X }
- X *s1 = (HALF)sum;
- X ++s1;
- X ++s2;
- X }
- X sum = (long)*s1 + carry;
- X *s1 = (HALF)sum;
- X}
- X
- X
- X/*
- X * Do subtract for divide, returning TRUE if subtraction went negative.
- X */
- Xstatic BOOL
- Xdsub(z1, z2, y, n)
- X ZVALUE z1, z2;
- X long y, n;
- X{
- X HALF *s1, *s2, *s3;
- X FULL i1;
- X BOOL neg;
- X
- X neg = FALSE;
- X s1 = z1.v + y - n;
- X s2 = z2.v;
- X if (++n > z2.len)
- X n = z2.len;
- X while (n--) {
- X i1 = (FULL) *s1;
- X if (i1 < (FULL) *s2) {
- X s3 = s1 + 1;
- X while (s3 < z1.v + z1.len && !(*s3)) {
- X *s3 = BASE1;
- X ++s3;
- X }
- X if (s3 >= z1.v + z1.len)
- X neg = TRUE;
- X else
- X --(*s3);
- X i1 += BASE;
- X }
- X *s1 = i1 - (FULL) *s2;
- X ++s1;
- X ++s2;
- X }
- X return neg;
- X}
- X
- X
- X/*
- X * Multiply a number by a single 'digit'.
- X * This is meant to be used only by the divide routine, and so the
- X * destination area must already be allocated and be large enough.
- X */
- Xstatic void
- Xdmul(z, mul, dest)
- X ZVALUE z;
- X FULL mul;
- X ZVALUE *dest;
- X{
- X register HALF *zp, *dp;
- X SIUNION sival;
- X FULL carry;
- X long len;
- X
- X dp = dest->v;
- X dest->sign = 0;
- X if (mul == 0) {
- X dest->len = 1;
- X *dp = 0;
- X return;
- X }
- X len = z.len;
- X zp = z.v + len - 1;
- X while ((*zp == 0) && (len > 1)) {
- X len--;
- X zp--;
- X }
- X dest->len = len;
- X zp = z.v;
- X carry = 0;
- X while (len >= 4) {
- X len -= 4;
- X sival.ivalue = (mul * ((FULL) *zp++)) + carry;
- X *dp++ = sival.silow;
- X sival.ivalue = (mul * ((FULL) *zp++)) + ((FULL) sival.sihigh);
- X *dp++ = sival.silow;
- X sival.ivalue = (mul * ((FULL) *zp++)) + ((FULL) sival.sihigh);
- X *dp++ = sival.silow;
- X sival.ivalue = (mul * ((FULL) *zp++)) + ((FULL) sival.sihigh);
- X *dp++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X while (--len >= 0) {
- X sival.ivalue = (mul * ((FULL) *zp++)) + carry;
- X *dp++ = sival.silow;
- X carry = sival.sihigh;
- X }
- X if (carry) {
- X *dp = (HALF)carry;
- X dest->len++;
- X }
- X}
- X
- X
- X/*
- X * Utility to calculate the gcd of two small integers.
- X */
- Xlong
- Xiigcd(i1, i2)
- X long i1, i2;
- X{
- X FULL f1, f2, temp;
- X
- X f1 = (FULL) ((i1 >= 0) ? i1 : -i1);
- X f2 = (FULL) ((i2 >= 0) ? i2 : -i2);
- X while (f1) {
- X temp = f2 % f1;
- X f2 = f1;
- X f1 = temp;
- X }
- X return (long) f2;
- X}
- X
- X
- Xvoid
- Xztrim(z)
- X ZVALUE *z;
- X{
- X register HALF *h;
- X register long len;
- X
- X h = z->v + z->len - 1;
- X len = z->len;
- X while (*h == 0 && len > 1) {
- X --h;
- X --len;
- X }
- X z->len = len;
- X}
- X
- X
- X/*
- X * Utility routine to shift right.
- X */
- Xvoid
- Xzshiftr(z, n)
- X ZVALUE z;
- X long n;
- X{
- X register HALF *h, *lim;
- X FULL mask, maskt;
- X long len;
- X
- X if (n >= BASEB) {
- X len = n / BASEB;
- X h = z.v;
- X lim = z.v + z.len - len;
- X while (h < lim) {
- X h[0] = h[len];
- X ++h;
- X }
- X n -= BASEB * len;
- X lim = z.v + z.len;
- X while (h < lim)
- X *h++ = 0;
- X }
- X if (n) {
- X len = z.len;
- X h = z.v + len - 1;
- X mask = 0;
- X while (len--) {
- X maskt = (((FULL) *h) << (BASEB - n)) & BASE1;
- X *h = (*h >> n) | mask;
- X mask = maskt;
- X --h;
- X }
- X }
- X}
- X
- X
- X/*
- X * Utility routine to shift left.
- X */
- Xvoid
- Xzshiftl(z, n)
- X ZVALUE z;
- X long n;
- X{
- X register HALF *h;
- X FULL mask, i;
- X long len;
- X
- X if (n >= BASEB) {
- X len = n / BASEB;
- X h = z.v + z.len - 1;
- X while (!*h)
- X --h;
- X while (h >= z.v) {
- X h[len] = h[0];
- X --h;
- X }
- X n -= BASEB * len;
- X while (len)
- X h[len--] = 0;
- X }
- X if (n > 0) {
- X len = z.len;
- X h = z.v;
- X mask = 0;
- X while (len--) {
- X i = (((FULL) *h) << n) | mask;
- X if (i > BASE1) {
- X mask = i >> BASEB;
- X i &= BASE1;
- X } else
- X mask = 0;
- X *h = (HALF) i;
- X ++h;
- X }
- X }
- X}
- X
- X/*
- X * initmasks - init the bitmask rotation arrays
- X *
- X * bitmask[i] (1 << (i-1)), for -BASEB*4<=i<=BASEB*4
- X * rotmask[j][k] (1 << ((j+k-1)%BASEB)), for -BASEB*2<=j,k<=BASEB*2
- X *
- X * The bmask array contains 8 cycles of rotations of a bit mask.
- X * We point bitmask and the rotmask pointers into the middle to
- X * ensure that we can have a complete two cycle swing forward
- X * and backward.
- X */
- Xvoid
- Xinitmasks()
- X{
- X int i;
- X
- X /*
- X * setup the bmask array
- X */
- X bmask = alloc((long)((8*BASEB)+1));
- X for (i=0; i < (8*BASEB)+1; ++i) {
- X bmask[i] = 1 << (i%BASEB);
- X }
- X
- X /*
- X * setup the rmask pointers
- X */
- X rmask = (HALF **)malloc(sizeof(HALF *)*((BASEB*4)+2));
- X for (i = 0; i <= (4*BASEB)+1; ++i) {
- X rmask[i] = &bmask[(2*BASEB)+i];
- X }
- X
- X#if 0
- X /*
- X * setup the rotmask array, allow for -2*BASEB thru 2*BASEB indexing
- X */
- X rotmask = &rmask[2*BASEB];
- X#endif
- X
- X /*
- X * setup the bitmask array to allow -4*BASEB thru 4*BASEB indexing
- X */
- X bitmask = &bmask[4*BASEB];
- X return;
- X}
- X
- X/* END CODE */
- SHAR_EOF
- chmod 0644 calc2.9.0/zmath.c || echo "restore of calc2.9.0/zmath.c fails"
- set `wc -c calc2.9.0/zmath.c`;Sum=$1
- if test "$Sum" != "32248"
- then echo original size 32248, current size $Sum;fi
- echo "x - extracting calc2.9.0/zmath.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/zmath.h &&
- X/*
- X * Copyright (c) 1993 David I. Bell
- X * Permission is granted to use, distribute, or modify this source,
- X * provided that this copyright notice remains intact.
- X *
- X * Data structure declarations for extended precision integer arithmetic.
- X * The assumption made is that a long is 32 bits and shorts are 16 bits,
- X * and longs must be addressible on word boundaries.
- X */
- X
- X#ifndef ZMATH_H
- X#define ZMATH_H
- X
- X#include <stdio.h>
- X#include "alloc.h"
- X#include "endian.h"
- X
- X#include "have_stdlib.h"
- X#ifdef HAVE_STDLIB_H
- X# include <stdlib.h>
- X#endif
- X
- X
- X#ifndef ALLOCTEST
- X# if defined(CALC_MALLOC)
- X# define freeh(p) (((void *)p == (void *)_zeroval_) || \
- X ((void *)p == (void *)_oneval_) || free((void *)p))
- X# else
- X# define freeh(p) { if (((void *)p != (void *)_zeroval_) && \
- X ((void *)p != (void *)_oneval_)) free((void *)p); }
- X# endif
- X#endif
- X
- X
- Xtypedef short FLAG; /* small value (e.g. comparison) */
- Xtypedef int BOOL; /* TRUE or FALSE value */
- Xtypedef unsigned long HASH; /* hash value */
- X
- X
- X#if !defined(TRUE)
- X#define TRUE ((BOOL) 1) /* booleans */
- X#endif
- X#if !defined(FALSE)
- X#define FALSE ((BOOL) 0)
- X#endif
- X
- X
- X/*
- X * NOTE: FULL must be twice the storage size of a HALF
- X * LEN storage size must be <= FULL storage size
- X */
- Xtypedef unsigned short HALF; /* unit of number storage */
- Xtypedef unsigned long FULL; /* double unit of number storage */
- Xtypedef long LEN; /* unit of length storage */
- X
- X#define BASE ((FULL) 65536) /* base for calculations (2^16) */
- X#define BASE1 ((FULL) (BASE - 1)) /* one less than base */
- X#define BASEB 16 /* number of bits in base */
- X#define BASEDIG 5 /* number of digits in base */
- X#define MAXHALF ((FULL) 0x7fff) /* largest positive half value */
- X#define MAXFULL ((FULL) 0x7fffffff) /* largest positive full value */
- X#define TOPHALF ((FULL) 0x8000) /* highest bit in half value */
- X#define TOPFULL ((FULL) 0x80000000) /* highest bit in full value */
- X#define MAXLEN ((LEN) 0x7fffffff) /* longest value allowed */
- X#define MAXREDC 5 /* number of entries in REDC cache */
- X#define SQ_ALG2 20 /* size for alternative squaring */
- X#define MUL_ALG2 20 /* size for alternative multiply */
- X#define POW_ALG2 40 /* size for using REDC for powers */
- X#define REDC_ALG2 50 /* size for using alternative REDC */
- X
- X
- X
- Xtypedef union {
- X FULL ivalue;
- X struct {
- X HALF Svalue1;
- X HALF Svalue2;
- X } sis;
- X} SIUNION;
- X
- X
- X#if !defined(BYTE_ORDER)
- X#include <machine/endian.h>
- X#endif
- X
- X#if !defined(LITTLE_ENDIAN)
- X#define LITTLE_ENDIAN 1234 /* Least Significant Byte first */
- X#endif
- X#if !defined(BIG_ENDIAN)
- X#define BIG_ENDIAN 4321 /* Most Significant Byte first */
- X#endif
- X/* PDP_ENDIAN - LSB in word, MSW in long is not supported */
- X
- X#if BYTE_ORDER == LITTLE_ENDIAN
- X# define silow sis.Svalue1 /* low order half of full value */
- X# define sihigh sis.Svalue2 /* high order half of full value */
- X#else
- X# if BYTE_ORDER == BIG_ENDIAN
- X# define silow sis.Svalue2 /* low order half of full value */
- X# define sihigh sis.Svalue1 /* high order half of full value */
- X# else
- X :@</*/>@: BYTE_ORDER must be BIG_ENDIAN or LITTLE_ENDIAN :@</*/>@:
- X# endif
- X#endif
- X
- X
- Xtypedef struct {
- X HALF *v; /* pointer to array of values */
- X LEN len; /* number of values in array */
- X BOOL sign; /* sign, nonzero is negative */
- X} ZVALUE;
- X
- X
- X
- X/*
- X * Function prototypes for integer math routines.
- X */
- X#if defined(__STDC__)
- X#define MATH_PROTO(a) a
- X#else
- X#define MATH_PROTO(a) ()
- X#endif
- X
- Xextern HALF * alloc MATH_PROTO((LEN len));
- X#ifdef ALLOCTEST
- Xextern void freeh MATH_PROTO((HALF *));
- X#endif
- X
- X
- X/*
- X * Input, output, and conversion routines.
- X */
- Xextern void zcopy MATH_PROTO((ZVALUE z, ZVALUE *res));
- Xextern void itoz MATH_PROTO((long i, ZVALUE *res));
- Xextern void atoz MATH_PROTO((char *s, ZVALUE *res));
- Xextern long ztoi MATH_PROTO((ZVALUE z));
- Xextern void zprintval MATH_PROTO((ZVALUE z, long decimals, long width));
- Xextern void zprintx MATH_PROTO((ZVALUE z, long width));
- Xextern void zprintb MATH_PROTO((ZVALUE z, long width));
- Xextern void zprinto MATH_PROTO((ZVALUE z, long width));
- X
- X
- X/*
- X * Basic numeric routines.
- X */
- Xextern void zmuli MATH_PROTO((ZVALUE z, long n, ZVALUE *res));
- Xextern long zdivi MATH_PROTO((ZVALUE z, long n, ZVALUE *res));
- Xextern long zmodi MATH_PROTO((ZVALUE z, long n));
- Xextern void zadd MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zsub MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zmul MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zdiv MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res, ZVALUE *rem));
- Xextern void zquo MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zmod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *rem));
- Xextern BOOL zdivides MATH_PROTO((ZVALUE z1, ZVALUE z2));
- Xextern void zor MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zand MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zxor MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zshift MATH_PROTO((ZVALUE z, long n, ZVALUE *res));
- Xextern void zsquare MATH_PROTO((ZVALUE z, ZVALUE *res));
- Xextern long zlowbit MATH_PROTO((ZVALUE z));
- Xextern long zhighbit MATH_PROTO((ZVALUE z));
- Xextern void zbitvalue MATH_PROTO((long n, ZVALUE *res));
- Xextern BOOL zisset MATH_PROTO((ZVALUE z, long n));
- Xextern BOOL zisonebit MATH_PROTO((ZVALUE z));
- Xextern BOOL zisallbits MATH_PROTO((ZVALUE z));
- Xextern FLAG ztest MATH_PROTO((ZVALUE z));
- Xextern FLAG zrel MATH_PROTO((ZVALUE z1, ZVALUE z2));
- Xextern BOOL zcmp MATH_PROTO((ZVALUE z1, ZVALUE z2));
- X
- X
- X/*
- X * More complicated numeric functions.
- X */
- Xextern long iigcd MATH_PROTO((long i1, long i2));
- Xextern void zgcd MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zlcm MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zreduce MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *z1res, ZVALUE *z2res));
- Xextern void zfact MATH_PROTO((ZVALUE z, ZVALUE *dest));
- Xextern void zpfact MATH_PROTO((ZVALUE z, ZVALUE *dest));
- Xextern void zlcmfact MATH_PROTO((ZVALUE z, ZVALUE *dest));
- Xextern void zperm MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zcomb MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern BOOL zprimetest MATH_PROTO((ZVALUE z, long count));
- Xextern FLAG zjacobi MATH_PROTO((ZVALUE z1, ZVALUE z2));
- Xextern void zfib MATH_PROTO((ZVALUE z, ZVALUE *res));
- Xextern void zpowi MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void ztenpow MATH_PROTO((long power, ZVALUE *res));
- Xextern void zpowermod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE z3, ZVALUE *res));
- Xextern BOOL zmodinv MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern BOOL zrelprime MATH_PROTO((ZVALUE z1, ZVALUE z2));
- Xextern long zlog MATH_PROTO((ZVALUE z1, ZVALUE z2));
- Xextern long zlog10 MATH_PROTO((ZVALUE z));
- Xextern long zdivcount MATH_PROTO((ZVALUE z1, ZVALUE z2));
- Xextern long zfacrem MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *rem));
- Xextern void zgcdrem MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern long zlowfactor MATH_PROTO((ZVALUE z, long count));
- Xextern long zdigits MATH_PROTO((ZVALUE z1));
- Xextern FLAG zdigit MATH_PROTO((ZVALUE z1, long n));
- Xextern BOOL zsqrt MATH_PROTO((ZVALUE z1, ZVALUE *dest));
- Xextern void zroot MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *dest));
- Xextern BOOL zissquare MATH_PROTO((ZVALUE z));
- Xextern HASH zhash MATH_PROTO((ZVALUE z));
- X
- X#if 0
- Xextern void zapprox MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res1, ZVALUE *res2));
- X#endif
- X
- X
- X#if 0
- Xextern void zmulmod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE z3, ZVALUE *res));
- Xextern void zsquaremod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE *res));
- Xextern void zsubmod MATH_PROTO((ZVALUE z1, ZVALUE z2, ZVALUE z3, ZVALUE *res));
- SHAR_EOF
- echo "End of part 12"
- echo "File calc2.9.0/zmath.h is continued in part 13"
- echo "13" > s2_seq_.tmp
- exit 0
-