Newsgroups: comp.sources.unix From: dbell@canb.auug.org.au (David I. Bell) Subject: v27i135: calc-2.9.0 - arbitrary precision C-like programmable calculator, Part08/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 135 Archive-Name: calc-2.9.0/part08 #!/bin/sh # this is part 8 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file calc2.9.0/opcodes.c continued # CurArch=8 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/opcodes.c" sed 's/^X//' << 'SHAR_EOF' >> calc2.9.0/opcodes.c X#endif X vsprintf(buf, fmt, ap); X va_end(ap); X fprintf(stderr, "%s\n", buf); X funcname = NULL; X longjmp(jmpbuf, 1); X} X X/* END CODE */ SHAR_EOF echo "File calc2.9.0/opcodes.c is complete" chmod 0644 calc2.9.0/opcodes.c || echo "restore of calc2.9.0/opcodes.c fails" set `wc -c calc2.9.0/opcodes.c`;Sum=$1 if test "$Sum" != "52101" then echo original size 52101, current size $Sum;fi echo "x - extracting calc2.9.0/opcodes.h (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/opcodes.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 X#ifndef OPCODES_H X#define OPCODES_H X X X/* X * Opcodes X */ X#define OP_NOP 0L /* no operation */ X#define OP_LOCALADDR 1L /* load address of local variable */ X#define OP_GLOBALADDR 2L /* load address of global variable */ X#define OP_PARAMADDR 3L /* load address of paramater variable */ X#define OP_LOCALVALUE 4L /* load value of local variable */ X#define OP_GLOBALVALUE 5L /* load value of global variable */ X#define OP_PARAMVALUE 6L /* load value of paramater variable */ X#define OP_NUMBER 7L /* load constant real numeric value */ X#define OP_INDEXADDR 8L /* load array index address */ X#define OP_PRINTRESULT 9L /* print result of top-level expression */ X#define OP_ASSIGN 10L /* assign value to variable */ X#define OP_ADD 11L /* add top two values */ X#define OP_SUB 12L /* subtract top two values */ X#define OP_MUL 13L /* multiply top two values */ X#define OP_DIV 14L /* divide top two values */ X#define OP_MOD 15L /* take mod of top two values */ X#define OP_SAVE 16L /* save value for later use */ X#define OP_NEGATE 17L /* negate top value */ X#define OP_INVERT 18L /* invert top value */ X#define OP_INT 19L /* take integer part of top value */ X#define OP_FRAC 20L /* take fraction part of top value */ X#define OP_NUMERATOR 21L /* take numerator of top value */ X#define OP_DENOMINATOR 22L /* take denominator of top value */ X#define OP_DUPLICATE 23L /* duplicate top value on stack */ X#define OP_POP 24L /* pop top value from stack */ X#define OP_RETURN 25L /* return value of function */ X#define OP_JUMPEQ 26L /* jump if top value is zero */ X#define OP_JUMPNE 27L /* jump if top value is nonzero */ X#define OP_JUMP 28L /* jump unconditionally */ X#define OP_USERCALL 29L /* call a user-defined function */ X#define OP_GETVALUE 30L /* convert address to value */ X#define OP_EQ 31L /* test top two elements for equality */ X#define OP_NE 32L /* test top two elements for inequality */ X#define OP_LE 33L /* test top two elements for <= */ X#define OP_GE 34L /* test top two elements for >= */ X#define OP_LT 35L /* test top two elements for < */ X#define OP_GT 36L /* test top two elements for > */ X#define OP_PREINC 37L /* add one to variable (++x) */ X#define OP_PREDEC 38L /* subtract one from variable (--x) */ X#define OP_POSTINC 39L /* add one to variable (x++) */ X#define OP_POSTDEC 40L /* subtract one from variable (x--) */ X#define OP_DEBUG 41L /* debugging point */ X#define OP_PRINT 42L /* print value */ X#define OP_ASSIGNPOP 43L /* assign to variable and remove it */ X#define OP_ZERO 44L /* put zero on the stack */ X#define OP_ONE 45L /* put one on the stack */ X#define OP_PRINTEOL 46L /* print end of line */ X#define OP_PRINTSPACE 47L /* print a space */ X#define OP_PRINTSTRING 48L /* print constant string */ X#define OP_DUPVALUE 49L /* duplicate value of top value */ X#define OP_OLDVALUE 50L /* old calculation value */ X#define OP_QUO 51L /* integer quotient of top two values */ X#define OP_POWER 52L /* number raised to a power */ X#define OP_QUIT 53L /* quit program */ X#define OP_CALL 54L /* call built-in routine */ X#define OP_GETEPSILON 55L /* get allowed error for calculations */ X#define OP_AND 56L /* arithmetic and */ X#define OP_OR 57L /* arithmetic or */ X#define OP_NOT 58L /* logical not */ X#define OP_ABS 59L /* absolute value */ X#define OP_SGN 60L /* sign of number */ X#define OP_ISINT 61L /* whether top value is integer */ X#define OP_CONDORJUMP 62L /* conditional or jump */ X#define OP_CONDANDJUMP 63L /* conditional and jump */ X#define OP_SQUARE 64L /* square top value */ X#define OP_STRING 65L /* load constant string value */ X#define OP_ISNUM 66L /* whether top value is a number */ X#define OP_UNDEF 67L /* load undefined value on stack */ X#define OP_ISNULL 68L /* whether variable is the null value */ X#define OP_ARGVALUE 69L /* load value of argument (parameter) n */ X#define OP_MATCREATE 70L /* create matrix */ X#define OP_ISMAT 71L /* whether variable is a matrix */ X#define OP_ISSTR 72L /* whether variable is a string */ X#define OP_GETCONFIG 73L /* get value of configuration parameter */ X#define OP_LEFTSHIFT 74L /* left shift of integer */ X#define OP_RIGHTSHIFT 75L /* right shift of integer */ X#define OP_CASEJUMP 76L /* test case and jump if not matched */ X#define OP_ISODD 77L /* whether value is an odd integer */ X#define OP_ISEVEN 78L /* whether value is even integer */ X#define OP_FIADDR 79L /* 'fast index' matrix value address */ X#define OP_FIVALUE 80L /* 'fast index' matrix value */ X#define OP_ISREAL 81L /* test value for real number */ X#define OP_IMAGINARY 82L /* load imaginary numeric constant */ X#define OP_RE 83L /* real part of complex number */ X#define OP_IM 84L /* imaginary part of complex number */ X#define OP_CONJUGATE 85L /* complex conjugate of complex number */ X#define OP_OBJCREATE 86L /* create object */ X#define OP_ISOBJ 87L /* whether value is an object */ X#define OP_NORM 88L /* norm of value (square of abs) */ X#define OP_ELEMADDR 89L /* address of element of object */ X#define OP_ELEMVALUE 90L /* value of element of object */ X#define OP_ISTYPE 91L /* whether two values are the same type */ X#define OP_SCALE 92L /* scale value by a power of two */ X#define OP_ISLIST 93L /* whether value is a list */ X#define OP_SWAP 94L /* swap values of two variables */ X#define OP_ISSIMPLE 95L /* whether value is a simple type */ X#define OP_CMP 96L /* compare values returning -1, 0, or 1 */ X#define OP_QUOMOD 97L /* calculate quotient and remainder */ X#define OP_SETCONFIG 98L /* set configuration parameter */ X#define OP_SETEPSILON 99L /* set allowed error for calculations */ X#define OP_ISFILE 100L /* whether value is a file */ X#define OP_ISASSOC 101L /* whether value is an association */ X#define OP_INITSTATIC 102L /* once only code for static initialization */ X#define OP_ELEMINIT 103L /* assign element of matrix or object */ X#define MAX_OPCODE 103L /* highest legal opcode */ X X#endif X X/* END CODE */ SHAR_EOF chmod 0644 calc2.9.0/opcodes.h || echo "restore of calc2.9.0/opcodes.h fails" set `wc -c calc2.9.0/opcodes.h`;Sum=$1 if test "$Sum" != "6052" then echo original size 6052, current size $Sum;fi echo "x - extracting calc2.9.0/qfunc.c (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/qfunc.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 rational arithmetic non-primitive functions X */ X X#include "qmath.h" X X XNUMBER *_epsilon_; /* default precision for real functions */ Xlong _epsilonprec_; /* bits of precision for epsilon */ X X X/* X * Set the default precision for real calculations. X * The precision must be between zero and one. X */ Xvoid Xsetepsilon(q) X NUMBER *q; /* number to be set as the new epsilon */ X{ X NUMBER *old; X X if (qisneg(q) || qiszero(q) || (qreli(q, 1L) >= 0)) X math_error("Epsilon value must be between zero and one"); X old = _epsilon_; X _epsilonprec_ = qprecision(q); X _epsilon_ = qlink(q); X if (old) X qfree(old); X} X X X/* X * Return the inverse of one number modulo another. X * That is, find x such that: X * Ax = 1 (mod B) X * Returns zero if the numbers are not relatively prime (temporary hack). X */ XNUMBER * Xqminv(q1, q2) X NUMBER *q1, *q2; X{ X NUMBER *r; X X if (qisfrac(q1) || qisfrac(q2)) X math_error("Non-integers for minv"); X r = qalloc(); X if (zmodinv(q1->num, q2->num, &r->num)) { X qfree(r); X return qlink(&_qzero_); X } X return r; X} X X X/* X * Return the modulo of one number raised to another. X * Here q1 is the number to be raised, q2 is the power to raise it to, X * and q3 is the number to take the modulo with the result. X * The second and third numbers are assumed nonnegative. X * Returned answer is non-negative. X * q4 = qpowermod(q1, q2, q3); X */ XNUMBER * Xqpowermod(q1, q2, q3) X NUMBER *q1, *q2, *q3; X{ X NUMBER *r; X X if (qisfrac(q1) || qisfrac(q2) || qisfrac(q3)) X math_error("Non-integers for powermod"); X r = qalloc(); X zpowermod(q1->num, q2->num, q3->num, &r->num); X return r; X} X X X/* X * Return the power function of one number with another. X * The power must be integral. X * q3 = qpowi(q1, q2); X */ XNUMBER * Xqpowi(q1, q2) X NUMBER *q1, *q2; X{ X register NUMBER *r; X BOOL invert, sign; X ZVALUE num, den, z2; X X if (qisfrac(q2)) X math_error("Raising number to fractional power"); X num = q1->num; X den = q1->den; X z2 = q2->num; X sign = (num.sign && zisodd(z2)); X invert = z2.sign; X num.sign = 0; X z2.sign = 0; X /* X * Check for trivial cases first. X */ X if (ziszero(num)) { /* zero raised to a power */ X if (invert || ziszero(z2)) X math_error("Zero raised to non-positive power"); X return qlink(&_qzero_); X } X if (zisunit(num) && zisunit(den)) { /* 1 or -1 raised to a power */ X r = (sign ? q1 : &_qone_); X r->links++; X return r; X } X if (ziszero(z2)) /* raising to zeroth power */ X return qlink(&_qone_); X if (zisunit(z2)) { /* raising to power 1 or -1 */ X if (invert) X return qinv(q1); X return qlink(q1); X } X /* X * Not a trivial case. Do the real work. X */ X r = qalloc(); X if (!zisunit(num)) X zpowi(num, z2, &r->num); X if (!zisunit(den)) X zpowi(den, z2, &r->den); X if (invert) { X z2 = r->num; X r->num = r->den; X r->den = z2; X } X r->num.sign = sign; X return r; X} X X X/* X * Given the legs of a right triangle, compute its hypothenuse within X * the specified error. This is sqrt(a^2 + b^2). X */ XNUMBER * Xqhypot(q1, q2, epsilon) X NUMBER *q1, *q2, *epsilon; X{ X NUMBER *tmp1, *tmp2, *tmp3; X X if (qisneg(epsilon) || qiszero(epsilon)) X math_error("Bad epsilon value for hypot"); X if (qiszero(q1)) X return qabs(q2); X if (qiszero(q2)) X return qabs(q1); X tmp1 = qsquare(q1); X tmp2 = qsquare(q2); X tmp3 = qadd(tmp1, tmp2); X qfree(tmp1); X qfree(tmp2); X tmp1 = qsqrt(tmp3, epsilon); X qfree(tmp3); X return tmp1; X} X X X/* X * Given one leg of a right triangle with unit hypothenuse, calculate X * the other leg within the specified error. This is sqrt(1 - a^2). X * If the wantneg flag is nonzero, then negative square root is returned. X */ XNUMBER * Xqlegtoleg(q, epsilon, wantneg) X NUMBER *q, *epsilon; X BOOL wantneg; X{ X NUMBER *qt, *res, qtmp; X ZVALUE num, ztmp1, ztmp2; X X if (qisneg(epsilon) || qiszero(epsilon)) X math_error("Bad epsilon value for legtoleg"); X if (qisunit(q)) X return qlink(&_qzero_); X if (qiszero(q)) { X if (wantneg) X return qlink(&_qnegone_); X return qlink(&_qone_); X } X num = q->num; X num.sign = 0; X if (zrel(num, q->den) >= 0) X math_error("Leg too large in legtoleg"); X zsquare(q->den, &ztmp1); X zsquare(num, &ztmp2); X zsub(ztmp1, ztmp2, &qtmp.num); X zfree(ztmp1); X zfree(ztmp2); X qtmp.den = _one_; X qt = qsqrt(&qtmp, epsilon); X zfree(qtmp.num); X qtmp.num = q->den; X res = qdiv(qt, &qtmp); X qfree(qt); X qt = qbappr(res, epsilon); X qfree(res); X if (wantneg) { X res = qneg(qt); X qfree(qt); X qt = res; X } X return qt; X} X X X/* X * Compute the square root of a number to within the specified error. X * If the number is an exact square, the exact result is returned. X * q3 = qsqrt(q1, q2); X */ XNUMBER * Xqsqrt(q1, epsilon) X register NUMBER *q1, *epsilon; X{ X long bits, bits2; /* number of bits of precision */ X int exact; X NUMBER *r; X ZVALUE t1, t2; X X if (qisneg(q1)) X math_error("Square root of negative number"); X if (qisneg(epsilon) || qiszero(epsilon)) X math_error("Bad epsilon value for sqrt"); X if (qiszero(q1)) X return qlink(&_qzero_); X if (qisunit(q1)) X return qlink(&_qone_); X if (qiszero(epsilon) && qisint(q1) && zistiny(q1->num) && (*q1->num.v <= 3)) X return qlink(&_qone_); X bits = zhighbit(epsilon->den) - zhighbit(epsilon->num) + 1; X if (bits < 0) X bits = 0; X bits2 = zhighbit(q1->num) - zhighbit(q1->den) + 1; X if (bits2 > 0) X bits += bits2; X r = qalloc(); X zshift(q1->num, bits * 2, &t2); X zmul(q1->den, t2, &t1); X zfree(t2); X exact = zsqrt(t1, &t2); X zfree(t1); X if (exact) { X zshift(q1->den, bits, &t1); X zreduce(t2, t1, &r->num, &r->den); X } else { X zquo(t2, q1->den, &t1); X zfree(t2); X zbitvalue(bits, &t2); X zreduce(t1, t2, &r->num, &r->den); X } X zfree(t1); X zfree(t2); X if (qiszero(r)) { X qfree(r); X r = qlink(&_qzero_); X } X return r; X} X X X/* X * Calculate the integral part of the square root of a number. X * Example: qisqrt(13) = 3. X */ XNUMBER * Xqisqrt(q) X NUMBER *q; X{ X NUMBER *r; X ZVALUE tmp; X X if (qisneg(q)) X math_error("Square root of negative number"); X if (qiszero(q)) X return qlink(&_qzero_); X if (qisint(q) && zistiny(q->num) && (z1tol(q->num) < 4)) X return qlink(&_qone_); X r = qalloc(); X if (qisint(q)) { X (void) zsqrt(q->num, &r->num); X return r; X } X zquo(q->num, q->den, &tmp); X (void) zsqrt(tmp, &r->num); X zfree(tmp); X return r; X} X X X/* X * Return whether or not a number is an exact square. X */ XBOOL Xqissquare(q) X NUMBER *q; X{ X BOOL flag; X X flag = zissquare(q->num); X if (qisint(q) || !flag) X return flag; X return zissquare(q->den); X} X X X/* X * Compute the greatest integer of the Kth root of a number. X * Example: qiroot(85, 3) = 4. X */ XNUMBER * Xqiroot(q1, q2) X register NUMBER *q1, *q2; X{ X NUMBER *r; X ZVALUE tmp; X X if (qisneg(q2) || qiszero(q2) || qisfrac(q2)) X math_error("Taking number to bad root value"); X if (qiszero(q1)) X return qlink(&_qzero_); X if (qisone(q1) || qisone(q2)) X return qlink(q1); X if (qistwo(q2)) X return qisqrt(q1); X r = qalloc(); X if (qisint(q1)) { X zroot(q1->num, q2->num, &r->num); X return r; X } X zquo(q1->num, q1->den, &tmp); X zroot(tmp, q2->num, &r->num); X zfree(tmp); X return r; X} X X X/* X * Return the greatest integer of the base 2 log of a number. X * This is the number such that 1 <= x / log2(x) < 2. X * Examples: qilog2(8) = 3, qilog2(1.3) = 1, qilog2(1/7) = -3. X */ Xlong Xqilog2(q) X NUMBER *q; /* number to take log of */ X{ X long n; /* power of two */ X int c; /* result of comparison */ X ZVALUE tmp; /* temporary value */ X X if (qisneg(q) || qiszero(q)) X math_error("Non-positive number for log2"); X if (qisint(q)) X return zhighbit(q->num); X n = zhighbit(q->num) - zhighbit(q->den); X if (n == 0) X c = zrel(q->num, q->den); X else if (n > 0) { X zshift(q->den, n, &tmp); X c = zrel(q->num, tmp); X } else { X zshift(q->num, n, &tmp); X c = zrel(tmp, q->den); X } X if (n) X zfree(tmp); X if (c < 0) X n--; X return n; X} X X X/* X * Return the greatest integer of the base 10 log of a number. X * This is the number such that 1 <= x / log10(x) < 10. X * Examples: qilog10(100) = 2, qilog10(12.3) = 1, qilog10(.023) = -2. X */ Xlong Xqilog10(q) X NUMBER *q; /* number to take log of */ X{ X long n; /* log value */ X ZVALUE temp; /* temporary value */ X X if (qisneg(q) || qiszero(q)) X math_error("Non-positive number for log10"); X if (qisint(q)) X return zlog10(q->num); X /* X * The number is not an integer. X * Compute the result if the number is greater than one. X */ X if ((q->num.len > q->den.len) || X ((q->num.len == q->den.len) && (zrel(q->num, q->den) > 0))) { X zquo(q->num, q->den, &temp); X n = zlog10(temp); X zfree(temp); X return n; X } X /* X * Here if the number is less than one. X * If the number is the inverse of a power of ten, then the obvious answer X * will be off by one. Subtracting one if the number is the inverse of an X * integer will fix it. X */ X if (zisunit(q->num)) X zsub(q->den, _one_, &temp); X else X zquo(q->den, q->num, &temp); X n = -zlog10(temp) - 1; X zfree(temp); X return n; X} X X X/* X * Return the number of digits in a number, ignoring the sign. X * For fractions, this is the number of digits of its greatest integer. X * Examples: qdigits(3456) = 4, qdigits(-23.45) = 2, qdigits(.0120) = 1. X */ Xlong Xqdigits(q) X NUMBER *q; /* number to count digits of */ X{ X long n; /* number of digits */ X ZVALUE temp; /* temporary value */ X X if (qisint(q)) X return zdigits(q->num); X zquo(q->num, q->den, &temp); X n = zdigits(temp); X zfree(temp); X return n; X} X X X/* X * Return the digit at the specified decimal place of a number represented X * in floating point. The lowest digit of the integral part of a number X * is the zeroth decimal place. Negative decimal places indicate digits X * to the right of the decimal point. Examples: qdigit(1234.5678, 1) = 3, X * qdigit(1234.5678, -3) = 7. X */ XFLAG Xqdigit(q, n) X NUMBER *q; X long n; X{ X ZVALUE tenpow, tmp1, tmp2; X FLAG res; X X /* X * Zero number or negative decimal place of integer is trivial. X */ X if (qiszero(q) || (qisint(q) && (n < 0))) X return 0; X /* X * For non-negative decimal places, answer is easy. X */ X if (n >= 0) { X if (qisint(q)) X return zdigit(q->num, n); X zquo(q->num, q->den, &tmp1); X res = zdigit(tmp1, n); X zfree(tmp1); X return res; X } X /* X * Fractional value and want negative digit, must work harder. X */ X ztenpow(-n, &tenpow); X zmul(q->num, tenpow, &tmp1); X zfree(tenpow); X zquo(tmp1, q->den, &tmp2); X res = zmodi(tmp2, 10L); X zfree(tmp1); X zfree(tmp2); X return res; X} X X X/* X * Return whether or not a bit is set at the specified bit position in a X * number. The lowest bit of the integral part of a number is the zeroth X * bit position. Negative bit positions indicate bits to the right of the X * binary decimal point. Examples: qdigit(17.1, 0) = 1, qdigit(17.1, -1) = 0. X */ XBOOL Xqisset(q, n) X NUMBER *q; X long n; X{ X NUMBER *qtmp1, *qtmp2; X ZVALUE ztmp; X BOOL res; X X /* X * Zero number or negative bit position place of integer is trivial. X */ X if (qiszero(q) || (qisint(q) && (n < 0))) X return FALSE; X /* X * For non-negative bit positions, answer is easy. X */ X if (n >= 0) { X if (qisint(q)) X return zisset(q->num, n); X zquo(q->num, q->den, &ztmp); X res = zisset(ztmp, n); X zfree(ztmp); X return res; X } X /* X * Fractional value and want negative bit position, must work harder. X */ X qtmp1 = qscale(q, -n); X qtmp2 = qint(qtmp1); X qfree(qtmp1); X res = ((qtmp2->num.v[0] & 0x01) != 0); X qfree(qtmp2); X return res; X} X X X/* X * Compute the factorial of an integer. X * q2 = qfact(q1); X */ XNUMBER * Xqfact(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (qisfrac(q)) X math_error("Non-integral factorial"); X if (qiszero(q) || zisone(q->num)) X return qlink(&_qone_); X r = qalloc(); X zfact(q->num, &r->num); X return r; X} X X X/* X * Compute the product of the primes less than or equal to a number. X * q2 = qpfact(q1); X */ XNUMBER * Xqpfact(q) X register NUMBER *q; X{ X NUMBER *r; X X if (qisfrac(q)) X math_error("Non-integral factorial"); X r = qalloc(); X zpfact(q->num, &r->num); X return r; X} X X X/* X * Compute the lcm of all the numbers less than or equal to a number. X * q2 = qlcmfact(q1); X */ XNUMBER * Xqlcmfact(q) X register NUMBER *q; X{ X NUMBER *r; X X if (qisfrac(q)) X math_error("Non-integral lcmfact"); X r = qalloc(); X zlcmfact(q->num, &r->num); X return r; X} X X X/* X * Compute the permutation function M! / (M - N)!. X */ XNUMBER * Xqperm(q1, q2) X register NUMBER *q1, *q2; X{ X register NUMBER *r; X X if (qisfrac(q1) || qisfrac(q2)) X math_error("Non-integral arguments for permutation"); X r = qalloc(); X zperm(q1->num, q2->num, &r->num); X return r; X} X X X/* X * Compute the combinatorial function M! / (N! * (M - N)!). X */ XNUMBER * Xqcomb(q1, q2) X register NUMBER *q1, *q2; X{ X register NUMBER *r; X X if (qisfrac(q1) || qisfrac(q2)) X math_error("Non-integral arguments for combinatorial"); X r = qalloc(); X zcomb(q1->num, q2->num, &r->num); X return r; X} X X X/* X * Compute the Jacobi function (a / b). X * -1 => a is not quadratic residue mod b X * 1 => b is composite, or a is quad residue of b X * 0 => b is even or b < 0 X */ XNUMBER * Xqjacobi(q1, q2) X register NUMBER *q1, *q2; X{ X if (qisfrac(q1) || qisfrac(q2)) X math_error("Non-integral arguments for jacobi"); X return itoq((long) zjacobi(q1->num, q2->num)); X} X X X/* X * Compute the Fibonacci number F(n). X */ XNUMBER * Xqfib(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (qisfrac(q)) X math_error("Non-integral Fibonacci number"); X r = qalloc(); X zfib(q->num, &r->num); X return r; X} X X X/* X * Truncate a number to the specified number of decimal places. X * Specifying zero places makes the result identical to qint. X * Example: qtrunc(2/3, 3) = .666 X */ XNUMBER * Xqtrunc(q1, q2) X NUMBER *q1, *q2; X{ X long places; X NUMBER *r; X ZVALUE tenpow, tmp1, tmp2; X X if (qisfrac(q2) || qisneg(q2) || !zistiny(q2->num)) X math_error("Bad number of places for qtrunc"); X if (qisint(q1)) X return qlink(q1); X r = qalloc(); X places = z1tol(q2->num); X /* X * Ok, produce the result. X * First see if we want no places, in which case just take integer part. X */ X if (places == 0) { X zquo(q1->num, q1->den, &r->num); X return r; X } X ztenpow(places, &tenpow); X zmul(q1->num, tenpow, &tmp1); X zquo(tmp1, q1->den, &tmp2); X zfree(tmp1); X if (ziszero(tmp2)) { X zfree(tmp2); X return qlink(&_qzero_); X } X /* X * Now reduce the result to the lowest common denominator. X */ X zgcd(tmp2, tenpow, &tmp1); X if (zisunit(tmp1)) { X zfree(tmp1); X r->num = tmp2; X r->den = tenpow; X return r; X } X zquo(tmp2, tmp1, &r->num); X zquo(tenpow, tmp1, &r->den); X zfree(tmp1); X zfree(tmp2); X zfree(tenpow); X return r; X} X X X/* X * Round a number to the specified number of decimal places. X * Zero decimal places means round to the nearest integer. X * Example: qround(2/3, 3) = .667 X */ XNUMBER * Xqround(q, places) X NUMBER *q; /* number to be rounded */ X long places; /* number of decimal places to round to */ X{ X NUMBER *r; X ZVALUE tenpow, roundval, tmp1, tmp2; X X if (places < 0) X math_error("Negative places for qround"); X if (qisint(q)) X return qlink(q); X /* X * Calculate one half of the denominator, ignoring fractional results. X * This is the value we will add in order to cause rounding. X */ X zshift(q->den, -1L, &roundval); X roundval.sign = q->num.sign; X /* X * Ok, now do the actual work to produce the result. X */ X r = qalloc(); X ztenpow(places, &tenpow); X zmul(q->num, tenpow, &tmp2); X zadd(tmp2, roundval, &tmp1); X zfree(tmp2); X zfree(roundval); X zquo(tmp1, q->den, &tmp2); X zfree(tmp1); X if (ziszero(tmp2)) { X zfree(tmp2); X return qlink(&_qzero_); X } X /* X * Now reduce the result to the lowest common denominator. X */ X zgcd(tmp2, tenpow, &tmp1); X if (zisunit(tmp1)) { X zfree(tmp1); X r->num = tmp2; X r->den = tenpow; X return r; X } X zquo(tmp2, tmp1, &r->num); X zquo(tenpow, tmp1, &r->den); X zfree(tmp1); X zfree(tmp2); X zfree(tenpow); X return r; X} X X X/* X * Truncate a number to the specified number of binary places. X * Specifying zero places makes the result identical to qint. X */ XNUMBER * Xqbtrunc(q1, q2) X NUMBER *q1, *q2; X{ X long places, twopow; X NUMBER *r; X ZVALUE tmp1, tmp2; X X if (qisfrac(q2) || qisneg(q2) || !zistiny(q2->num)) X math_error("Bad number of places for qtrunc"); X if (qisint(q1)) X return qlink(q1); X r = qalloc(); X places = z1tol(q2->num); X /* X * Ok, produce the result. X * First see if we want no places, in which case just take integer part. X */ X if (places == 0) { X zquo(q1->num, q1->den, &r->num); X return r; X } X zshift(q1->num, places, &tmp1); X zquo(tmp1, q1->den, &tmp2); X zfree(tmp1); X if (ziszero(tmp2)) { X zfree(tmp2); X return qlink(&_qzero_); X } X /* X * Now reduce the result to the lowest common denominator. X */ X if (zisodd(tmp2)) { X r->num = tmp2; X zbitvalue(places, &r->den); X return r; X } X twopow = zlowbit(tmp2); X if (twopow > places) X twopow = places; X places -= twopow; X zshift(tmp2, -twopow, &r->num); X zfree(tmp2); X zbitvalue(places, &r->den); X return r; X} X X X/* X * Round a number to the specified number of binary places. X * Zero binary places means round to the nearest integer. X */ XNUMBER * Xqbround(q, places) X NUMBER *q; /* number to be rounded */ X long places; /* number of binary places to round to */ X{ X long twopow; X NUMBER *r; X ZVALUE roundval, tmp1, tmp2; X X if (places < 0) X math_error("Negative places for qbround"); X if (qisint(q)) X return qlink(q); X r = qalloc(); X /* X * Calculate one half of the denominator, ignoring fractional results. X * This is the value we will add in order to cause rounding. X */ X zshift(q->den, -1L, &roundval); X roundval.sign = q->num.sign; X /* X * Ok, produce the result. X */ X zshift(q->num, places, &tmp1); X zadd(tmp1, roundval, &tmp2); X zfree(roundval); X zfree(tmp1); X zquo(tmp2, q->den, &tmp1); X zfree(tmp2); X if (ziszero(tmp1)) { X zfree(tmp1); X return qlink(&_qzero_); X } X /* X * Now reduce the result to the lowest common denominator. X */ X if (zisodd(tmp1)) { X r->num = tmp1; X zbitvalue(places, &r->den); X return r; X } X twopow = zlowbit(tmp1); X if (twopow > places) X twopow = places; X places -= twopow; X zshift(tmp1, -twopow, &r->num); X zfree(tmp1); X zbitvalue(places, &r->den); X return r; X} X X X/* X * Approximate a number by using binary rounding with the minimum number X * of binary places so that the resulting number is within the specified X * epsilon of the original number. X */ XNUMBER * Xqbappr(q, e) X NUMBER *q, *e; X{ X long bits; X X if (qisneg(e) || qiszero(e)) X math_error("Bad epsilon value for qbappr"); X if (e == _epsilon_) X bits = _epsilonprec_ + 1; X else X bits = qprecision(e) + 1; X return qbround(q, bits); X} X X X/* X * Approximate a number using continued fractions until the approximation X * error is less than the specified value. If a NULL pointer is given X * for the error value, then the closest simpler fraction is returned. X */ XNUMBER * Xqcfappr(q, e) X NUMBER *q, *e; X{ X NUMBER qtest, *qtmp; X ZVALUE u1, u2, u3, v1, v2, v3, t1, t2, t3, qq, tt; X int i; X BOOL haveeps; X X haveeps = TRUE; X if (e == NULL) { X haveeps = FALSE; X e = &_qzero_; X } X if (qisneg(e)) X math_error("Negative epsilon for cfappr"); X if (qisint(q) || zisunit(q->num) || (haveeps && qiszero(e))) X return qlink(q); X u1 = _one_; X u2 = _zero_; X u3 = q->num; X u3.sign = 0; X v1 = _zero_; X v2 = _one_; X v3 = q->den; X while (!ziszero(v3)) { X if (!ziszero(u2) && !ziszero(u1)) { X qtest.num = u2; X qtest.den = u1; X qtest.den.sign = 0; X qtest.num.sign = q->num.sign; X qtmp = qsub(q, &qtest); X qtest = *qtmp; X qtest.num.sign = 0; X i = qrel(&qtest, e); X qfree(qtmp); X if (i <= 0) X break; X } X zquo(u3, v3, &qq); X zmul(qq, v1, &tt); zsub(u1, tt, &t1); zfree(tt); X zmul(qq, v2, &tt); zsub(u2, tt, &t2); zfree(tt); X zmul(qq, v3, &tt); zsub(u3, tt, &t3); zfree(tt); X zfree(qq); zfree(u1); zfree(u2); X if ((u3.v != q->num.v) && (u3.v != q->den.v)) X zfree(u3); X u1 = v1; u2 = v2; u3 = v3; X v1 = t1; v2 = t2; v3 = t3; X } X if (u3.v != q->den.v) X zfree(u3); X zfree(v1); X zfree(v2); X i = ziszero(v3); X zfree(v3); X if (i && haveeps) { X zfree(u1); X zfree(u2); X return qlink(q); X } X qtest.num = u2; X qtest.den = u1; X qtest.den.sign = 0; X qtest.num.sign = q->num.sign; X qtmp = qcopy(&qtest); X zfree(u1); X zfree(u2); X return qtmp; X} X X X/* X * Return an indication on whether or not two fractions are approximately X * equal within the specified epsilon. Returns negative if the absolute value X * of the difference between the two numbers is less than epsilon, zero if X * the difference is equal to epsilon, and positive if the difference is X * greater than epsilon. X */ XFLAG Xqnear(q1, q2, epsilon) X NUMBER *q1, *q2, *epsilon; X{ X int res; X NUMBER qtemp, *qq; X X if (qisneg(epsilon)) X math_error("Negative epsilon for near"); X if (q1 == q2) { X if (qiszero(epsilon)) X return 0; X return -1; X } X if (qiszero(epsilon)) X return qcmp(q1, q2); X if (qiszero(q2)) { X qtemp = *q1; X qtemp.num.sign = 0; X return qrel(&qtemp, epsilon); X } X if (qiszero(q1)) { X qtemp = *q2; X qtemp.num.sign = 0; X return qrel(&qtemp, epsilon); X } X qq = qsub(q1, q2); X qtemp = *qq; X qtemp.num.sign = 0; X res = qrel(&qtemp, epsilon); X qfree(qq); X return res; X} X X X/* X * Compute the gcd (greatest common divisor) of two numbers. X * q3 = qgcd(q1, q2); X */ XNUMBER * Xqgcd(q1, q2) X register NUMBER *q1, *q2; X{ X ZVALUE z; X NUMBER *q; X X if (q1 == q2) X return qabs(q1); X if (qisfrac(q1) || qisfrac(q2)) { X q = qalloc(); X zgcd(q1->num, q2->num, &q->num); X zlcm(q1->den, q2->den, &q->den); X return q; X } X if (qiszero(q1)) X return qabs(q2); X if (qiszero(q2)) X return qabs(q1); X if (qisunit(q1) || qisunit(q2)) X return qlink(&_qone_); X zgcd(q1->num, q2->num, &z); X if (zisunit(z)) { X zfree(z); X return qlink(&_qone_); X } X q = qalloc(); X q->num = z; X return q; X} X X X/* X * Compute the lcm (least common multiple) of two numbers. X * q3 = qlcm(q1, q2); X */ XNUMBER * Xqlcm(q1, q2) X register NUMBER *q1, *q2; X{ X NUMBER *q; X X if (qiszero(q1) || qiszero(q2)) X return qlink(&_qzero_); X if (q1 == q2) X return qabs(q1); X if (qisunit(q1)) X return qabs(q2); X if (qisunit(q2)) X return qabs(q1); X q = qalloc(); X zlcm(q1->num, q2->num, &q->num); X if (qisfrac(q1) || qisfrac(q2)) X zgcd(q1->den, q2->den, &q->den); X return q; X} X X X/* X * Remove all occurances of the specified factor from a number. X * Returned number is always positive. X */ XNUMBER * Xqfacrem(q1, q2) X NUMBER *q1, *q2; X{ X long count; X ZVALUE tmp; X NUMBER *r; X X if (qisfrac(q1) || qisfrac(q2)) X math_error("Non-integers for factor removal"); X count = zfacrem(q1->num, q2->num, &tmp); X if (zisunit(tmp)) { X zfree(tmp); X return qlink(&_qone_); X } X if (count == 0) { X zfree(tmp); X return qlink(q1); X } X r = qalloc(); X r->num = tmp; X return r; X} X X X/* X * Divide one number by the gcd of it with another number repeatedly until X * the number is relatively prime. X */ XNUMBER * Xqgcdrem(q1, q2) X NUMBER *q1, *q2; X{ X ZVALUE tmp; X NUMBER *r; X X if (qisfrac(q1) || qisfrac(q2)) X math_error("Non-integers for gcdrem"); X zgcdrem(q1->num, q2->num, &tmp); X if (zisunit(tmp)) { X zfree(tmp); X return qlink(&_qone_); X } X if (zcmp(q1->num, tmp) == 0) { X zfree(tmp); X return qlink(q1); X } X r = qalloc(); X r->num = tmp; X return r; X} X X X/* X * Return the lowest prime factor of a number. X * Search is conducted for the specified number of primes. X * Returns one if no factor was found. X */ XNUMBER * Xqlowfactor(q1, q2) X NUMBER *q1, *q2; X{ X if (qisfrac(q1) || qisfrac(q2)) X math_error("Non-integers for lowfactor"); X return itoq(zlowfactor(q1->num, ztoi(q2->num))); X} X X X/* X * Return the number of places after the decimal point needed to exactly X * represent the specified number as a real number. Integers return zero, X * and non-terminating decimals return minus one. Examples: X * qplaces(1/7)=-1, qplaces(3/10)= 1, qplaces(1/8)=3, qplaces(4)=0. X */ Xlong Xqplaces(q) X NUMBER *q; X{ X long twopow, fivepow; X HALF fiveval[2]; X ZVALUE five; X ZVALUE tmp; X X if (qisint(q)) /* no decimal places if number is integer */ X return 0; X /* X * The number of decimal places of a fraction in lowest terms is finite X * if an only if the denominator is of the form 2^A * 5^B, and then the X * number of decimal places is equal to MAX(A, B). X */ X five.sign = 0; X five.len = 1; X five.v = fiveval; X fiveval[0] = 5; X fivepow = zfacrem(q->den, five, &tmp); X if (!zisonebit(tmp)) { X zfree(tmp); X return -1; X } X twopow = zlowbit(tmp); X zfree(tmp); X if (twopow < fivepow) X twopow = fivepow; X return twopow; X} X X X/* X * Perform a probabilistic primality test (algorithm P in Knuth). X * Returns FALSE if definitely not prime, or TRUE if probably prime. X * Second arg determines how many times to check for primality. X */ XBOOL Xqprimetest(q1, q2) X NUMBER *q1, *q2; X{ X if (qisfrac(q1) || qisfrac(q2) || qisneg(q2)) X math_error("Bad arguments for qprimetest"); X return zprimetest(q1->num, qtoi(q2)); X} X X X/* X * Return a trivial hash value for a number. X */ XHASH Xqhash(q) X NUMBER *q; X{ X HASH hash; X X hash = zhash(q->num); X if (qisfrac(q)) X hash += zhash(q->den) * 2000003; X return hash; X} X X/* END CODE */ SHAR_EOF chmod 0644 calc2.9.0/qfunc.c || echo "restore of calc2.9.0/qfunc.c fails" set `wc -c calc2.9.0/qfunc.c`;Sum=$1 if test "$Sum" != "24730" then echo original size 24730, current size $Sum;fi echo "x - extracting calc2.9.0/qio.c (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/qio.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 rational numbers X */ X X#include "stdarg.h" X#include "qmath.h" X 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 X#if 0 Xstatic long etoalen; Xstatic char *etoabuf = NULL; X#endif X Xstatic long scalefactor; Xstatic ZVALUE scalenumber = { 0, 0, 0 }; X X X/* X * Print a formatted string containing arbitrary numbers, similar to printf. X * ALL numeric arguments to this routine are rational NUMBERs. X * Various forms of printing such numbers are supplied, in addition X * to strings and characters. Output can actually be to any FILE X * stream or a string. X */ X#ifdef VARARGS X# define VA_ALIST1 fmt, va_alist X# define VA_DCL1 char *fmt; va_dcl X#else X# ifdef __STDC__ X# define VA_ALIST1 char *fmt, ... X# define VA_DCL1 X# else X# define VA_ALIST1 fmt X# define VA_DCL1 char *fmt; X# endif X#endif X/*VARARGS*/ Xvoid Xqprintf(VA_ALIST1) X VA_DCL1 X{ X va_list ap; X NUMBER *q; X int ch, sign; X long width, precision; X X#ifdef VARARGS X va_start(ap); X#else X va_start(ap, fmt); X#endif X while ((ch = *fmt++) != '\0') { X if (ch == '\\') { X ch = *fmt++; X switch (ch) { X case 'n': ch = '\n'; break; X case 'r': ch = '\r'; break; X case 't': ch = '\t'; break; X case 'f': ch = '\f'; break; X case 'v': ch = '\v'; break; X case 'b': ch = '\b'; break; X case 0: X va_end(ap); X return; X } X PUTCHAR(ch); X continue; X } X if (ch != '%') { X PUTCHAR(ch); X continue; X } X ch = *fmt++; X width = 0; precision = 8; sign = 1; Xpercent: ; X switch (ch) { X case 'd': X q = va_arg(ap, NUMBER *); X qprintfd(q, width); X break; X case 'f': X q = va_arg(ap, NUMBER *); X qprintff(q, width, precision); X break; X case 'e': X q = va_arg(ap, NUMBER *); X qprintfe(q, width, precision); X break; X case 'r': X case 'R': X q = va_arg(ap, NUMBER *); X qprintfr(q, width, (BOOL) (ch == 'R')); X break; X case 'N': X q = va_arg(ap, NUMBER *); X zprintval(q->num, 0L, width); X break; X case 'D': X q = va_arg(ap, NUMBER *); X zprintval(q->den, 0L, width); X break; X case 'o': X q = va_arg(ap, NUMBER *); X qprintfo(q, width); X break; X case 'x': X q = va_arg(ap, NUMBER *); X qprintfx(q, width); X break; X case 'b': X q = va_arg(ap, NUMBER *); X qprintfb(q, width); X break; X case 's': X PUTSTR(va_arg(ap, char *)); X break; X case 'c': X PUTCHAR(va_arg(ap, int)); X break; X case 0: X va_end(ap); X return; X case '-': X sign = -1; X ch = *fmt++; X default: X if (('0' <= ch && ch <= '9') || ch == '.' || ch == '*') { X if (ch == '*') { X q = va_arg(ap, NUMBER *); X width = sign * qtoi(q); X ch = *fmt++; X } else if (ch != '.') { X width = ch - '0'; X while ('0' <= (ch = *fmt++) && ch <= '9') X width = width * 10 + ch - '0'; X width *= sign; X } X if (ch == '.') { X if ((ch = *fmt++) == '*') { X q = va_arg(ap, NUMBER *); X precision = qtoi(q); X ch = *fmt++; X } else { X precision = 0; X while ('0' <= (ch = *fmt++) && ch <= '9') X precision = precision * 10 + ch - '0'; X } X } X goto percent; X } X } X } X va_end(ap); X} X X X#if 0 X/* X * Read a number from the specified FILE stream (NULL means stdin). X * The number can be an integer, a fraction, a real number, an X * exponential number, or a hex, octal or binary number. Leading blanks X * are skipped. Illegal numbers return NULL. Unrecognized characters X * remain to be read on the line. X * q = qreadval(fp); X */ XNUMBER * Xqreadval(fp) X FILE *fp; /* file stream to read from (or NULL) */ X{ X NUMBER *r; /* returned number */ X char *cp; /* current buffer location */ X long savecc; /* characters saved in buffer */ X long scancc; /* characters parsed correctly */ X int ch; /* current character */ X X if (fp == NULL) X fp = stdin; X if (etoabuf == NULL) { X etoabuf = (char *)malloc(OUTBUFSIZE + 2); X if (etoabuf == NULL) X return NULL; X etoalen = OUTBUFSIZE; X } X cp = etoabuf; X ch = fgetc(fp); X while ((ch == ' ') || (ch == '\t')) X ch = fgetc(fp); X savecc = 0; X for (;;) { X if (ch == EOF) X return NULL; X if (savecc >= etoalen) X { X cp = (char *)realloc(etoabuf, etoalen + OUTBUFSIZE + 2); X if (cp == NULL) X return NULL; X etoabuf = cp; X etoalen += OUTBUFSIZE; X cp += savecc; X } X *cp++ = (char)ch; X *cp = '\0'; X scancc = qparse(etoabuf, QPF_SLASH); X if (scancc != ++savecc) X break; X ch = fgetc(fp); X } X ungetc(ch, fp); X if (scancc < 0) X return NULL; X r = atoq(etoabuf); X if (ziszero(r->den)) { X qfree(r); X r = NULL; X } X return r; X} X#endif X X X/* X * Print a number in the specified output mode. X * If MODE_DEFAULT is given, then the default output mode is used. X * Any approximate output is flagged with a leading tilde. X * Integers are always printed as themselves. X */ Xvoid Xqprintnum(q, outmode) X NUMBER *q; X{ X NUMBER tmpval; X long prec, exp; X X if (outmode == MODE_DEFAULT) X outmode = _outmode_; X if ((outmode == MODE_FRAC) || ((outmode == MODE_REAL) && qisint(q))) { X qprintfr(q, 0L, FALSE); X return; X } X switch (outmode) { X case MODE_INT: X if (qisfrac(q)) X PUTCHAR('~'); X qprintfd(q, 0L); X break; X X case MODE_REAL: X prec = qplaces(q); X if ((prec < 0) || (prec > _outdigits_)) { X prec = _outdigits_; X PUTCHAR('~'); X } X qprintff(q, 0L, prec); X break; X X case MODE_EXP: X if (qiszero(q)) { X PUTCHAR('0'); X return; X } X tmpval = *q; X tmpval.num.sign = 0; X exp = qilog10(&tmpval); X if (exp == 0) { /* in range to output as real */ X qprintnum(q, MODE_REAL); X return; X } X tmpval.num = _one_; X tmpval.den = _one_; X if (exp > 0) X ztenpow(exp, &tmpval.den); X else X ztenpow(-exp, &tmpval.num); X q = qmul(q, &tmpval); X zfree(tmpval.num); X zfree(tmpval.den); X qprintnum(q, MODE_REAL); X qfree(q); X PRINTF1("e%ld", exp); X break; X X case MODE_HEX: X qprintfx(q, 0L); X break; X X case MODE_OCTAL: X qprintfo(q, 0L); X break; X X case MODE_BINARY: X qprintfb(q, 0L); X break; X X default: X math_error("Bad mode for print"); X } X} X X X/* X * Print a number in floating point representation. X * Example: 193.784 X */ Xvoid Xqprintff(q, width, precision) X NUMBER *q; X long width; X long precision; X{ X ZVALUE z, z1; X X if (precision != scalefactor) { X if (scalenumber.v) X zfree(scalenumber); X ztenpow(precision, &scalenumber); X scalefactor = precision; X } X if (scalenumber.v) X zmul(q->num, scalenumber, &z); X else X z = q->num; X if (qisfrac(q)) { X zquo(z, q->den, &z1); X if (z.v != q->num.v) X zfree(z); X z = z1; X } X if (qisneg(q) && ziszero(z)) X PUTCHAR('-'); X zprintval(z, precision, width); X if (z.v != q->num.v) X zfree(z); X} X X X/* X * Print a number in exponential notation. X * Example: 4.1856e34 X */ X/*ARGSUSED*/ Xvoid Xqprintfe(q, width, precision) X register NUMBER *q; X long width; X long precision; X{ X long exponent; X NUMBER q2; X ZVALUE num, den, tenpow, tmp; X X if (qiszero(q)) { X PUTSTR("0.0"); X return; X } X num = q->num; X den = q->den; X num.sign = 0; X exponent = zdigits(num) - zdigits(den); X if (exponent > 0) { X ztenpow(exponent, &tenpow); X zmul(den, tenpow, &tmp); X zfree(tenpow); X den = tmp; X } X if (exponent < 0) { X ztenpow(-exponent, &tenpow); X zmul(num, tenpow, &tmp); X zfree(tenpow); X num = tmp; X } X if (zrel(num, den) < 0) { X zmuli(num, 10L, &tmp); X if (num.v != q->num.v) X zfree(num); X num = tmp; X exponent--; X } X q2.num = num; X q2.den = den; X q2.num.sign = q->num.sign; X qprintff(&q2, 0L, precision); X if (exponent) X PRINTF1("e%ld", exponent); X if (num.v != q->num.v) X zfree(num); X if (den.v != q->den.v) X zfree(den); X} X X X/* X * Print a number in rational representation. X * Example: 397/37 X */ Xvoid Xqprintfr(q, width, force) X NUMBER *q; X long width; X BOOL force; X{ X zprintval(q->num, 0L, width); X if (force || qisfrac(q)) { X PUTCHAR('/'); X zprintval(q->den, 0L, width); X } X} X X X/* X * Print a number as an integer (truncating fractional part). X * Example: 958421 X */ Xvoid Xqprintfd(q, width) X NUMBER *q; X long width; X{ X ZVALUE z; X X if (qisfrac(q)) { X zquo(q->num, q->den, &z); X zprintval(z, 0L, width); X zfree(z); X } else X zprintval(q->num, 0L, width); X} X X X/* X * Print a number in hex. X * This prints the numerator and denominator in hex. X */ Xvoid Xqprintfx(q, width) X NUMBER *q; X long width; X{ X zprintx(q->num, width); X if (qisfrac(q)) { X PUTCHAR('/'); X zprintx(q->den, 0L); X } X} X X X/* X * Print a number in binary. X * This prints the numerator and denominator in binary. X */ Xvoid Xqprintfb(q, width) X NUMBER *q; X long width; X{ X zprintb(q->num, width); X if (qisfrac(q)) { X PUTCHAR('/'); X zprintb(q->den, 0L); X } X} X X X/* X * Print a number in octal. X * This prints the numerator and denominator in octal. X */ Xvoid Xqprintfo(q, width) X NUMBER *q; X long width; X{ X zprinto(q->num, width); X if (qisfrac(q)) { X PUTCHAR('/'); X zprinto(q->den, 0L); X } X} X X X/* X * Convert a string to a number in rational, floating point, X * exponential notation, hex, or octal. X * q = atoq(string); X */ XNUMBER * Xatoq(s) X register char *s; X{ X register NUMBER *q; X register char *t; X ZVALUE div, newnum, newden, tmp; X long decimals, exp; X BOOL hex, negexp; X X q = qalloc(); X decimals = 0; X exp = 0; X negexp = FALSE; X hex = FALSE; X t = s; X if ((*t == '+') || (*t == '-')) X t++; X if ((*t == '0') && ((t[1] == 'x') || (t[1] == 'X'))) { X hex = TRUE; X t += 2; X } X while (((*t >= '0') && (*t <= '9')) || (hex && X (((*t >= 'a') && (*t <= 'f')) || ((*t >= 'A') && (*t <= 'F'))))) X t++; X if (*t == '/') { X t++; X atoz(t, &q->den); X } else if ((*t == '.') || (*t == 'e') || (*t == 'E')) { X if (*t == '.') { X t++; X while ((*t >= '0') && (*t <= '9')) { X t++; X decimals++; X } X } X /* X * Parse exponent if any X */ X if ((*t == 'e') || (*t == 'E')) { X t++; X if (*t == '+') X t++; X else if (*t == '-') { X negexp = TRUE; X t++; X } X while ((*t >= '0') && (*t <= '9')) { X exp = (exp * 10) + *t++ - '0'; X if (exp > 1000000) X math_error("Exponent too large"); X } X } X ztenpow(decimals, &q->den); X } X atoz(s, &q->num); X if (qiszero(q)) { X qfree(q); X return qlink(&_qzero_); X } X /* X * Apply the exponential if any X */ X if (exp) { X ztenpow(exp, &tmp); X if (negexp) { X zmul(q->den, tmp, &newden); X zfree(q->den); X q->den = newden; X } else { X zmul(q->num, tmp, &newnum); X zfree(q->num); X q->num = newnum; X } X zfree(tmp); X } X /* X * Reduce the fraction to lowest terms X */ X if (zisunit(q->num) || zisunit(q->den)) X return q; X zgcd(q->num, q->den, &div); X if (zisunit(div)) X return q; X zquo(q->num, div, &newnum); X zfree(q->num); X zquo(q->den, div, &newden); X zfree(q->den); X q->num = newnum; X q->den = newden; X return q; X} X X X/* X * Parse a number in any of the various legal forms, and return the count X * of characters that are part of a legal number. Numbers can be either a X * decimal integer, possibly two decimal integers separated with a slash, a X * floating point or exponential number, a hex number beginning with "0x", X * a binary number beginning with "0b", or an octal number beginning with "0". X * The flags argument modifies the end of number testing for ease in handling X * fractions or complex numbers. Minus one is returned if the number format X * is definitely illegal. X */ Xlong Xqparse(cp, flags) X register char *cp; X{ X char *oldcp; X X oldcp = cp; X if ((*cp == '+') || (*cp == '-')) X cp++; X if ((*cp == '+') || (*cp == '-')) X return -1; X if ((*cp == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { /* hex */ X cp += 2; X while (((*cp >= '0') && (*cp <= '9')) || X ((*cp >= 'a') && (*cp <= 'f')) || X ((*cp >= 'A') && (*cp <= 'F'))) X cp++; X goto done; X } X if ((*cp == '0') && ((cp[1] == 'b') || (cp[1] == 'B'))) { /* binary */ X cp += 2; X while ((*cp == '0') || (*cp == '1')) X cp++; X goto done; X } X if ((*cp == '0') && (cp[1] >= '0') && (cp[1] <= '9')) { /* octal */ X while ((*cp >= '0') && (*cp <= '7')) X cp++; X goto done; X } X /* X * Number is decimal, but can still be a fraction or real or exponential. X */ X while ((*cp >= '0') && (*cp <= '9')) X cp++; X if (*cp == '/' && flags & QPF_SLASH) { /* fraction */ X cp++; X while ((*cp >= '0') && (*cp <= '9')) X cp++; X goto done; X } X if (*cp == '.') { /* floating point */ X cp++; X while ((*cp >= '0') && (*cp <= '9')) X cp++; X } X if ((*cp == 'e') || (*cp == 'E')) { /* exponential */ X cp++; X if ((*cp == '+') || (*cp == '-')) X cp++; X if ((*cp == '+') || (*cp == '-')) X return -1; X while ((*cp >= '0') && (*cp <= '9')) X cp++; X } X Xdone: X if (((*cp == 'i') || (*cp == 'I')) && (flags & QPF_IMAG)) X cp++; X if ((*cp == '.') || ((*cp == '/') && (flags & QPF_SLASH)) || X ((*cp >= '0') && (*cp <= '9')) || X ((*cp >= 'a') && (*cp <= 'z')) || X ((*cp >= 'A') && (*cp <= 'Z'))) X return -1; X return (cp - oldcp); X} X X/* END CODE */ SHAR_EOF chmod 0644 calc2.9.0/qio.c || echo "restore of calc2.9.0/qio.c fails" set `wc -c calc2.9.0/qio.c`;Sum=$1 if test "$Sum" != "12895" then echo original size 12895, current size $Sum;fi echo "x - extracting calc2.9.0/qmath.c (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/qmath.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 rational arithmetic primitive routines X */ X X#include "qmath.h" X X XNUMBER _qzero_ = { { _zeroval_, 1, 0 }, { _oneval_, 1, 0 }, 1 }; XNUMBER _qone_ = { { _oneval_, 1, 0 }, { _oneval_, 1, 0 }, 1 }; Xstatic NUMBER _qtwo_ = { { _twoval_, 1, 0 }, { _oneval_, 1, 0 }, 1 }; Xstatic NUMBER _qten_ = { { _tenval_, 1, 0 }, { _oneval_, 1, 0 }, 1 }; XNUMBER _qnegone_ = { { _oneval_, 1, 1 }, { _oneval_, 1, 0 }, 1 }; XNUMBER _qonehalf_ = { { _oneval_, 1, 0 }, { _twoval_, 1, 0 }, 1 }; X X X/* X * Create another copy of a number. X * q2 = qcopy(q1); X */ XNUMBER * Xqcopy(q) X register NUMBER *q; X{ X register NUMBER *r; X X r = qalloc(); X r->num.sign = q->num.sign; X if (!zisunit(q->num)) { X r->num.len = q->num.len; X r->num.v = alloc(r->num.len); X zcopyval(q->num, r->num); X } X if (!zisunit(q->den)) { X r->den.len = q->den.len; X r->den.v = alloc(r->den.len); X zcopyval(q->den, r->den); X } X return r; X} X X X/* X * Convert a number to a normal integer. X * i = qtoi(q); X */ Xlong Xqtoi(q) X register NUMBER *q; X{ X long i; X ZVALUE res; X X if (qisint(q)) X return ztoi(q->num); X zquo(q->num, q->den, &res); X i = ztoi(res); X zfree(res); X return i; X} X X X/* X * Convert a normal integer into a number. X * q = itoq(i); X */ XNUMBER * Xitoq(i) X long i; X{ X register NUMBER *q; X X if ((i >= -1) && (i <= 10)) { X switch ((int) i) { X case 0: q = &_qzero_; break; X case 1: q = &_qone_; break; X case 2: q = &_qtwo_; break; X case 10: q = &_qten_; break; X case -1: q = &_qnegone_; break; X default: q = NULL; X } X if (q) X return qlink(q); X } X q = qalloc(); X itoz(i, &q->num); X return q; X} X X X/* X * Create a number from the given integral numerator and denominator. X * q = iitoq(inum, iden); X */ XNUMBER * Xiitoq(inum, iden) X long inum, iden; X{ X register NUMBER *q; X long d; X BOOL sign; X X if (iden == 0) X math_error("Division by zero"); X if (inum == 0) X return qlink(&_qzero_); X sign = 0; X if (inum < 0) { X sign = 1; X inum = -inum; X } X if (iden < 0) { X sign = 1 - sign; X iden = -iden; X } X d = iigcd(inum, iden); X inum /= d; X iden /= d; X if (iden == 1) X return itoq(sign ? -inum : inum); X q = qalloc(); X if (inum != 1) X itoz(inum, &q->num); X itoz(iden, &q->den); X q->num.sign = sign; X return q; X} X X X/* X * Add two numbers to each other. X * q3 = qadd(q1, q2); X */ XNUMBER * Xqadd(q1, q2) X register NUMBER *q1, *q2; X{ X NUMBER *r; X ZVALUE t1, t2, temp, d1, d2, vpd1, upd1; X X if (qiszero(q1)) X return qlink(q2); X if (qiszero(q2)) X return qlink(q1); X r = qalloc(); X /* X * If either number is an integer, then the result is easy. X */ X if (qisint(q1) && qisint(q2)) { X zadd(q1->num, q2->num, &r->num); X return r; X } X if (qisint(q2)) { X zmul(q1->den, q2->num, &temp); X zadd(q1->num, temp, &r->num); X zfree(temp); X zcopy(q1->den, &r->den); X return r; X } X if (qisint(q1)) { X zmul(q2->den, q1->num, &temp); X zadd(q2->num, temp, &r->num); X zfree(temp); X zcopy(q2->den, &r->den); X return r; X } X /* X * Both arguments are true fractions, so we need more work. X * If the denominators are relatively prime, then the answer is the X * straightforward cross product result with no need for reduction. X */ X zgcd(q1->den, q2->den, &d1); X if (zisunit(d1)) { X zfree(d1); X zmul(q1->num, q2->den, &t1); X zmul(q1->den, q2->num, &t2); X zadd(t1, t2, &r->num); X zfree(t1); X zfree(t2); X zmul(q1->den, q2->den, &r->den); X return r; X } X /* X * The calculation is now more complicated. X * See Knuth Vol 2 for details. X */ X zquo(q2->den, d1, &vpd1); X zquo(q1->den, d1, &upd1); X zmul(q1->num, vpd1, &t1); X zmul(q2->num, upd1, &t2); X zadd(t1, t2, &temp); X zfree(t1); X zfree(t2); X zfree(vpd1); X zgcd(temp, d1, &d2); X zfree(d1); X if (zisunit(d2)) { X zfree(d2); X r->num = temp; X zmul(upd1, q2->den, &r->den); X zfree(upd1); X return r; X } X zquo(temp, d2, &r->num); X zfree(temp); X zquo(q2->den, d2, &temp); X zfree(d2); X zmul(temp, upd1, &r->den); X zfree(temp); X zfree(upd1); X return r; X} X X X/* X * Subtract one number from another. X * q3 = qsub(q1, q2); X */ XNUMBER * Xqsub(q1, q2) X register NUMBER *q1, *q2; X{ X NUMBER t, *r; X X if (q1 == q2) X return qlink(&_qzero_); X if (qiszero(q2)) X return qlink(q1); X if (qisint(q1) && qisint(q2)) { X r = qalloc(); X zsub(q1->num, q2->num, &r->num); X return r; X } X t = *q2; X t.num.sign = !t.num.sign; X return qadd(q1, &t); X} X X X/* X * Increment a number by one. X */ XNUMBER * Xqinc(q) X NUMBER *q; X{ X NUMBER *r; X X r = qalloc(); X if (qisint(q)) { X zadd(q->num, _one_, &r->num); X return r; X } X zadd(q->num, q->den, &r->num); X zcopy(q->den, &r->den); X return r; X} X X X/* X * Decrement a number by one. X */ XNUMBER * Xqdec(q) X NUMBER *q; X{ X NUMBER *r; X X r = qalloc(); X if (qisint(q)) { X zsub(q->num, _one_, &r->num); X return r; X } X zsub(q->num, q->den, &r->num); X zcopy(q->den, &r->den); X return r; X} X X X/* X * Add a normal small integer value to an arbitrary number. X */ XNUMBER * Xqaddi(q1, n) X NUMBER *q1; X long n; X{ X NUMBER addnum; /* temporary number */ X HALF addval[2]; /* value of small number */ X BOOL neg; /* TRUE if number is neg */ X X if (n == 0) X return qlink(q1); X if (n == 1) X return qinc(q1); X if (n == -1) X return qdec(q1); X if (qiszero(q1)) X return itoq(n); X addnum.num.sign = 0; X addnum.num.len = 1; X addnum.num.v = addval; X addnum.den = _one_; X neg = (n < 0); X if (neg) X n = -n; X addval[0] = (HALF) n; X n = (((FULL) n) >> BASEB); X if (n) { X addval[1] = (HALF) n; X addnum.num.len = 2; X } X if (neg) X return qsub(q1, &addnum); X else X return qadd(q1, &addnum); X} X X X/* X * Multiply two numbers. X * q3 = qmul(q1, q2); X */ XNUMBER * Xqmul(q1, q2) X register NUMBER *q1, *q2; X{ X NUMBER *r; /* returned value */ X ZVALUE n1, n2, d1, d2; /* numerators and denominators */ X ZVALUE tmp; X X if (qiszero(q1) || qiszero(q2)) X return qlink(&_qzero_); X if (qisone(q1)) X return qlink(q2); X if (qisone(q2)) X return qlink(q1); X if (qisint(q1) && qisint(q2)) { /* easy results if integers */ X r = qalloc(); X zmul(q1->num, q2->num, &r->num); X return r; X } X n1 = q1->num; X n2 = q2->num; X d1 = q1->den; X d2 = q2->den; X if (ziszero(d1) || ziszero(d2)) X math_error("Division by zero"); X if (ziszero(n1) || ziszero(n2)) X return qlink(&_qzero_); X if (!zisunit(n1) && !zisunit(d2)) { /* possibly reduce */ X zgcd(n1, d2, &tmp); X if (!zisunit(tmp)) { X zquo(q1->num, tmp, &n1); X zquo(q2->den, tmp, &d2); X } X zfree(tmp); X } X if (!zisunit(n2) && !zisunit(d1)) { /* again possibly reduce */ X zgcd(n2, d1, &tmp); X if (!zisunit(tmp)) { X zquo(q2->num, tmp, &n2); X zquo(q1->den, tmp, &d1); X } X zfree(tmp); X } X r = qalloc(); X zmul(n1, n2, &r->num); X zmul(d1, d2, &r->den); X if (q1->num.v != n1.v) X zfree(n1); X if (q1->den.v != d1.v) X zfree(d1); X if (q2->num.v != n2.v) X zfree(n2); X if (q2->den.v != d2.v) X zfree(d2); X return r; X} X X X/* X * Multiply a number by a small integer. X * q2 = qmuli(q1, n); X */ XNUMBER * Xqmuli(q, n) X NUMBER *q; X long n; X{ X NUMBER *r; X long d; /* gcd of multiplier and denominator */ X int sign; X X if ((n == 0) || qiszero(q)) X return qlink(&_qzero_); X if (n == 1) X return qlink(q); X r = qalloc(); X if (qisint(q)) { X zmuli(q->num, n, &r->num); X return r; X } X sign = 1; X if (n < 0) { X n = -n; X sign = -1; X } X d = zmodi(q->den, n); X d = iigcd(d, n); X zmuli(q->num, (n * sign) / d, &r->num); X (void) zdivi(q->den, d, &r->den); X return r; X} X X X/* X * Divide two numbers (as fractions). X * q3 = qdiv(q1, q2); X */ XNUMBER * Xqdiv(q1, q2) X register NUMBER *q1, *q2; X{ X NUMBER temp; X X if (qiszero(q2)) X math_error("Division by zero"); X if ((q1 == q2) || !qcmp(q1, q2)) X return qlink(&_qone_); X if (qisone(q1)) X return qinv(q2); X temp.num = q2->den; X temp.den = q2->num; X temp.num.sign = temp.den.sign; X temp.den.sign = 0; X temp.links = 1; X return qmul(q1, &temp); X} X X X/* X * Divide a number by a small integer. X * q2 = qdivi(q1, n); X */ XNUMBER * Xqdivi(q, n) X NUMBER *q; X long n; X{ X NUMBER *r; X long d; /* gcd of divisor and numerator */ X int sign; X X if (n == 0) X math_error("Division by zero"); X if ((n == 1) || qiszero(q)) X return qlink(q); X sign = 1; X if (n < 0) { X n = -n; X sign = -1; X } X r = qalloc(); X d = zmodi(q->num, n); X d = iigcd(d, n); X (void) zdivi(q->num, d * sign, &r->num); X zmuli(q->den, n / d, &r->den); X return r; X} X X X/* X * Return the quotient when one number is divided by another. X * This works for fractional values also, and in all cases: X * qquo(q1, q2) = int(q1 / q2). X */ XNUMBER * Xqquo(q1, q2) X register NUMBER *q1, *q2; X{ X ZVALUE num, den, res; X NUMBER *q; X X if (zisunit(q1->num)) X num = q2->den; X else if (zisunit(q2->den)) X num = q1->num; X else X zmul(q1->num, q2->den, &num); X if (zisunit(q1->den)) X den = q2->num; X else if (zisunit(q2->num)) X den = q1->den; X else X zmul(q1->den, q2->num, &den); X zquo(num, den, &res); X if ((num.v != q2->den.v) && (num.v != q1->num.v)) X zfree(num); X if ((den.v != q2->num.v) && (den.v != q1->den.v)) X zfree(den); X if (ziszero(res)) { X zfree(res); X return qlink(&_qzero_); X } X res.sign = (q1->num.sign != q2->num.sign); X if (zisunit(res)) { X q = (res.sign ? &_qnegone_ : &_qone_); X zfree(res); X return qlink(q); X } X q = qalloc(); X q->num = res; X return q; X} X X X/* X * Return the absolute value of a number. X * q2 = qabs(q1); X */ XNUMBER * Xqabs(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (q->num.sign == 0) X return qlink(q); X r = qalloc(); X if (!zisunit(q->num)) X zcopy(q->num, &r->num); X if (!zisunit(q->den)) X zcopy(q->den, &r->den); X r->num.sign = 0; X return r; X} X X X/* X * Negate a number. X * q2 = qneg(q1); X */ XNUMBER * Xqneg(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (qiszero(q)) X return qlink(&_qzero_); X r = qalloc(); X if (!zisunit(q->num)) X zcopy(q->num, &r->num); X if (!zisunit(q->den)) X zcopy(q->den, &r->den); X r->num.sign = !q->num.sign; X return r; X} X X X/* X * Return the sign of a number (-1, 0 or 1) X */ XNUMBER * Xqsign(q) X NUMBER *q; X{ X if (qiszero(q)) X return qlink(&_qzero_); X if (qisneg(q)) X return qlink(&_qnegone_); X return qlink(&_qone_); X} X X X/* X * Invert a number. X * q2 = qinv(q1); X */ XNUMBER * Xqinv(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (qisunit(q)) { X r = (qisneg(q) ? &_qnegone_ : &_qone_); X return qlink(r); X } X if (qiszero(q)) X math_error("Division by zero"); X r = qalloc(); X if (!zisunit(q->num)) X zcopy(q->num, &r->den); X if (!zisunit(q->den)) X zcopy(q->den, &r->num); X r->num.sign = q->num.sign; X r->den.sign = 0; X return r; X} X X X/* X * Return just the numerator of a number. X * q2 = qnum(q1); X */ XNUMBER * Xqnum(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (qisint(q)) X return qlink(q); X if (zisunit(q->num)) { X r = (qisneg(q) ? &_qnegone_ : &_qone_); X return qlink(r); X } X r = qalloc(); X zcopy(q->num, &r->num); X return r; X} X X X/* X * Return just the denominator of a number. X * q2 = qden(q1); X */ XNUMBER * Xqden(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (qisint(q)) X return qlink(&_qone_); X r = qalloc(); X zcopy(q->den, &r->num); X return r; X} X X X/* X * Return the fractional part of a number. X * q2 = qfrac(q1); X */ XNUMBER * Xqfrac(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (qisint(q)) X return qlink(&_qzero_); X if ((q->num.len < q->den.len) || ((q->num.len == q->den.len) && X (q->num.v[q->num.len - 1] < q->den.v[q->num.len - 1]))) X return qlink(q); X r = qalloc(); X zmod(q->num, q->den, &r->num); X zcopy(q->den, &r->den); X r->num.sign = q->num.sign; X return r; X} X X X/* X * Return the integral part of a number. X * q2 = qint(q1); X */ XNUMBER * Xqint(q) X register NUMBER *q; X{ X register NUMBER *r; X X if (qisint(q)) X return qlink(q); X if ((q->num.len < q->den.len) || ((q->num.len == q->den.len) && X (q->num.v[q->num.len - 1] < q->den.v[q->num.len - 1]))) SHAR_EOF echo "End of part 8" echo "File calc2.9.0/qmath.c is continued in part 9" echo "9" > s2_seq_.tmp exit 0