chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / rational.c
1 /* Copyright (c) 1995, 1996, 2001 by Arkkra Enterprises */
2 /* All rights reserved */
3 /*
4  *      rational.c      functions to do operations on rational numbers
5  *
6  *      Contents:
7  *
8  *              radd(), rsub(), rmul(), rdiv(), rneg(), rinv(), rrai(), rred(),
9  *              ator(), rtoa(); also gtrat(), called by macros GT,GE,LT,LE
10  *
11  *              ratmsg(), add64_64(), mul32_64(), divmod64(), red64_64()
12  *
13  *              The first group of functions are for the user.  The second
14  *              are for internal use only.
15  *
16  *      Description:
17  *              The functions in this file do operations on rational numbers.
18  *              The rational arguments to functions that the users can call
19  *              must be in standard form (lowest terms, with positive
20  *              denominator) except for rred().  There are checks for division
21  *              by zero and for overflow of numerators and denominators.
22  *              (The absolute values of each are limited to MAXLONG, defined
23  *              in rational.h.)  If there is an error, the external int
24  *              raterrno is set to RATDIV0 or RATOVER, as the case may be,
25  *              and *raterrfuncp is checked.  If nonzero, it is assumed to
26  *              point at the user's error handler, and it is called with a
27  *              parameter equal to raterrno.  Otherwise, a message is printed
28  *              to stderr.  In any case, the answer returned to the user is
29  *              0/1.  If there was no error, raterrno is set to RATNOERR.
30  *
31  *              In general, the functions assume they are being called with
32  *              valid parameters.  If they are not, results are not guaranteed
33  *              to be correct.  However, they are defensive enough so that
34  *              invalid parameters will not cause a crash in these routines.
35  *              They will not always detect invalid parameters, but if they
36  *              do, they will use the raterrno/raterrfuncp mechanism described
37  *              above, with the value RATPARM.
38  *
39  *              These routines depend on a INT32B being a 32-bit number,
40  *              stored in two's complement form, and UINT32B being the same
41  *              for unsigned.  See rational.h.  Numerators and denominators
42  *              are assumed to be INT32B.  Furthermore, the number 0x80000000
43  *              is not allowed.  The routines should work on any machine and
44  *              compiler where these requirements are met.
45  *
46  *              Internally, when 64-bit numbers are used, they are represented
47  *              by an array of two INT32B.  The 0 subscript contains the low
48  *              order bits and the 1 subscript contains the high order bits.
49  *              The numbers are usually used as two's complement signed
50  *              integers, so the high bit of the 1 subscript is a sign bit.
51  */
52
53 #ifndef stderr
54 #       include <stdio.h>
55 #endif
56
57 #ifndef isspace
58 #       include <ctype.h>
59 #endif
60
61 #ifndef _RATIONAL
62 #       include "rational.h"
63 #endif
64
65
66
67 /*
68  * Define SMALL to be a number that uses less than half as many bits as
69  * MAXLONG (15 as compared to 31).  Define a SMALLRAT as a rational number
70  * whose numerator (absolute value) and denominator are in that range.
71  * The denominator is assumed to be positive.
72  */
73 #define SMALL           0x7fff
74 #define SMALLRAT(q)     ((q).n <= SMALL && (q).n >= -SMALL && (q).d <= SMALL)
75
76
77 /*
78  * This macro checks whether a 64-bit integer is actually less than or
79  * equal to MAXLONG in absolute value, 0x7fffffff.
80  */
81 #define INT32(n)        ((n)[1] ==  0 && (n)[0] >= 0 ||         \
82                          (n)[1] == -1 && (n)[0] < 0 && (n)[0] != 0x80000000)
83
84
85 /*
86  * Return whether the first 64-bit number equals the second.
87  * To be equal, both words must be equal.
88  */
89 #define EQ64(x, y)      ( (x)[1] == (y)[1] && (x)[0] == (y)[0] )
90
91
92 /*
93  * Return whether the first 64-bit number is greater than the second.
94  * If the high order words are equal, use the low order words, unsigned;
95  * otherwise, just use the high order words.
96  */
97 #define GT64(x, y) (                                            \
98         (x)[1] == (y)[1] ?                                      \
99                 (UINT32B)(x)[0] > (UINT32B)(y)[0]               \
100         :                                                       \
101                 (x)[1] > (y)[1]                                 \
102 )
103
104
105 /*
106  * Return whether the first 64-bit number is less than the second.
107  * If the high order words are equal, use the low order words, unsigned;
108  * otherwise, just use the high order words.
109  */
110 #define LT64(x, y) (                                            \
111         (x)[1] == (y)[1] ?                                      \
112                 (UINT32B)(x)[0] < (UINT32B)(y)[0]               \
113         :                                                       \
114                 (x)[1] < (y)[1]                                 \
115 )
116
117
118 /*
119  * Return whether the first *unsigned* 64-bit number is less than or equal to
120  * the second.  If the high order words are equal, use the low order words;
121  * otherwise, just use the high order words.
122  */
123 #define LEU64(x, y) (                                           \
124         (x)[1] == (y)[1] ?                                      \
125                 (UINT32B)(x)[0] <= (UINT32B)(y)[0]              \
126         :                                                       \
127                 (UINT32B)(x)[1] <= (UINT32B)(y)[1]              \
128 )
129
130
131 /*
132  * Negate a 64-bit number.
133  */
134 #define NEG64(x)        {                                               \
135         (x)[1] = ~(x)[1];       /* one's complement */                  \
136         (x)[0] = -(x)[0];       /* two's complement */                  \
137         if ((x)[0] == 0)        /* if "carry" must inc high word */     \
138                 (x)[1]++;                                               \
139 }
140
141
142 /*
143  * Shift a 64-bit number left one bit as unsigned (not that it matters).
144  */
145 #define SHL1U64(x)      {                                               \
146         (x)[1] <<= 1;           /* shift high word */                   \
147         if ((x)[0] < 0)         /* if high bit of low word is set */    \
148                 (x)[1]++;       /* shift it into the high word */       \
149         (x)[0] <<= 1;           /* shift low word */                    \
150 }
151
152
153 /*
154  * Shift a 64-bit number right one bit as unsigned.
155  */
156 #define SHR1U64(x)      {                                               \
157         (x)[0] = (UINT32B)(x)[0] >> 1;  /* shift low word */            \
158         if ((x)[1] & 1)                 /* if low bit of high word set*/\
159                 (x)[0] |= 0x80000000;   /* shift it into low word */    \
160         (x)[1] = (UINT32B)(x)[1] >> 1;  /* shift low word */            \
161 }
162
163
164
165 /* declare as static the functions that are only used internally */
166 #ifdef __STDC__
167 static void ratmsg(int code);
168 static void add64_64(INT32B a[], INT32B x[], INT32B y[]);
169 static void mul32_64(INT32B a[], INT32B x, INT32B y);
170 static void divmod64(INT32B x[], INT32B y[], INT32B q[], INT32B r[]);
171 static void red64_64(INT32B num[], INT32B den[]);
172 #else
173 static void ratmsg(), add64_64(), mul32_64(), divmod64(), red64_64();
174 #endif
175
176
177 int raterrno;                   /* set to error type upon return to user */
178 void (*raterrfuncp)();          /* error handler functions to be called */
179
180 static RATIONAL zero = {0,1};
181 \f
182 /*
183  *      radd()          add two rational numbers
184  *
185  *      This function adds two rational numbers.  They must be in standard
186  *      form.
187  *
188  *      Parameters:     x       the first number
189  *                      y       the second number
190  *
191  *      Return value:   The sum (x + y), if it can be represented as a
192  *                      RATIONAL, else 0/1.
193  *
194  *      Side effects:   If radd() succeeds, it sets raterrno to RATNOERR.
195  *                      Otherwise, the numerator or denominator must have
196  *                      overflowed, so it sets raterrno to RATOVER and
197  *                      either prints a message or calls a user-supplied
198  *                      error handler.
199  */
200
201 RATIONAL
202 radd(x, y)
203
204 RATIONAL x, y;
205
206 {
207         RATIONAL a;                     /* the answer */
208         INT32B bign[2];                 /* 64-bit numerator */
209         INT32B bigd[2];                 /* 64-bit denominator */
210         INT32B bigt[2];                 /* temp storage */
211
212
213         raterrno = RATNOERR;            /* no error yet */
214
215         /*
216          * If the numbers are small enough, do it the easy way, since there is
217          * then no danger of overflow.
218          */
219         if (SMALLRAT(x) && SMALLRAT(y)) {
220                 a.n = x.n * y.d + x.d * y.n;
221                 a.d = x.d * y.d;
222                 rred(&a);               /* reduce to standard form */
223                 return(a);
224         }
225
226         /*
227          * To avoid overflow during the calculations, use two INT32B to
228          * hold numbers.
229          */
230         mul32_64(bign, x.n, y.d);       /* get first part of numerator */
231         mul32_64(bigt, x.d, y.n);       /* get second part of numerator */
232         add64_64(bign, bign, bigt);     /* add to get full numerator */
233         mul32_64(bigd, x.d, y.d);       /* get denominator */
234         red64_64(bign, bigd);           /* reduce */
235
236         /* overflow if the result can't fit in a RATIONAL */
237         if ( ! INT32(bign) || ! INT32(bigd) ) {
238                 ratmsg(RATOVER);        /* set raterrno, report error */
239                 return(zero);
240         }
241
242         a.n = bign[0];                  /* set answer */
243         a.d = bigd[0];
244
245         return(a);
246 }
247 \f
248 /*
249  *      rsub()          subtract two rational numbers
250  *
251  *      This function subtracts two rational numbers.  They must be in standard
252  *      form.
253  *
254  *      Parameters:     x       the first number
255  *                      y       the second number
256  *
257  *      Return value:   The difference (x - y), if it can be represented as a
258  *                      RATIONAL, else 0/1.
259  *
260  *      Side effects:   If rsub() succeeds, it sets raterrno to RATNOERR.
261  *                      Otherwise, the numerator or denominator must have
262  *                      overflowed, so it sets raterrno to RATOVER and
263  *                      either prints a message or calls a user-supplied
264  *                      error handler.
265  */
266
267 RATIONAL
268 rsub(x, y)
269
270 RATIONAL x, y;
271
272 {
273         /*
274          * Just negate the second operand and add.  We could call rneg() to
275          * negate y, but why waste the time?
276          */
277         y.n = -y.n;
278         return(radd(x, y));
279 }
280 \f
281 /*
282  *      rmul()          multiply two rational numbers
283  *
284  *      This function multiplies two rational numbers.  They must be in standard
285  *      form.
286  *
287  *      Parameters:     x       the first number
288  *                      y       the second number
289  *
290  *      Return value:   The product (x * y), if it can be represented as a
291  *                      RATIONAL, else 0/1.
292  *
293  *      Side effects:   If rsub() succeeds, it sets raterrno to RATNOERR.
294  *                      Otherwise, the numerator or denominator must have
295  *                      overflowed, so it sets raterrno to RATOVER and
296  *                      either prints a message or calls a user-supplied
297  *                      error handler.
298  */
299
300 RATIONAL
301 rmul(x, y)
302
303 RATIONAL x, y;
304
305 {
306         RATIONAL a;                     /* the answer */
307         INT32B bign[2];                 /* 64-bit numerator */
308         INT32B bigd[2];                 /* 64-bit denominator */
309
310
311         raterrno = RATNOERR;            /* no error yet */
312
313         /*
314          * If the numbers are small enough, do it the easy way, since there is
315          * then no danger of overflow.
316          */
317         if (SMALLRAT(x) && SMALLRAT(y)) {
318                 a.n = x.n * y.n;
319                 a.d = x.d * y.d;
320                 rred(&a);               /* reduce to standard form */
321                 return(a);
322         }
323
324         /*
325          * To avoid overflow during the calculations, use two INT32B to
326          * hold numbers.
327          */
328         mul32_64(bign, x.n, y.n);       /* get numerator */
329         mul32_64(bigd, x.d, y.d);       /* get denominator */
330         red64_64(bign, bigd);           /* reduce */
331
332         /* overflow if the result can't fit in a RATIONAL */
333         if ( ! INT32(bign) || ! INT32(bigd) ) {
334                 ratmsg(RATOVER);        /* set raterrno, report error */
335                 return(zero);
336         }
337
338         a.n = bign[0];                  /* set answer */
339         a.d = bigd[0];
340
341         return(a);
342 }
343 \f
344 /*
345  *      rdiv()          divide two rational numbers
346  *
347  *      This function divides two rational numbers.  They must be in standard
348  *      form.
349  *
350  *      Parameters:     x       the first number
351  *                      y       the second number
352  *
353  *      Return value:   The quotient (x / y), if it is defined and can be
354  *                      represented as a RATIONAL, else 0/1.
355  *
356  *      Side effects:   If rdiv() succeeds, it sets raterrno to RATNOERR.
357  *                      Otherwise, either the second number was zero or the
358  *                      numerator or denominator overflowed.  In this case,
359  *                      it sets raterrno to RATDIV0 or RATOVER, respectively,
360  *                      and either prints a message or calls a user-supplied
361  *                      error handler.
362  */
363
364 RATIONAL
365 rdiv(x, y)
366
367 RATIONAL x, y;
368
369 {
370         RATIONAL r;                     /* reciprocal of y */
371
372
373         r = rinv(y);                    /* first find 1/y */
374
375         if (raterrno != RATNOERR)       /* if y was 0, return failure now */
376                 return(zero);
377
378         /*
379          * Return  x * r.   Whether rmul() succeeds or fails, we still just want
380          * to leave raterrno the same and return what rmul() returns.
381          */
382         return(rmul(x, r));
383 }
384 \f
385 /*
386  *      rneg()          negate a rational number
387  *
388  *      This function negates a rational number.  It must be in standard form.
389  *
390  *      Parameters:     x       the number
391  *
392  *      Return value:   The negative (-x).
393  *
394  *      Side effects:   It sets raterrno to RATNOERR.
395  */
396
397 RATIONAL
398 rneg(x)
399
400 RATIONAL x;
401
402 {
403         raterrno = RATNOERR;            /* no errors are possible */
404
405         x.n = -x.n;
406
407         /* answer is already in standard form since x was */
408         return(x);
409 }
410 \f
411 /*
412  *      rinv()          invert a rational number
413  *
414  *      This function inverts a rational number.  It must be in standard form.
415  *
416  *      Parameters:     x       the number
417  *
418  *      Return value:   The reciprocal (1 / x), if it is defined, else 0/1.
419  *
420  *      Side effects:   If rinv() succeeds, it sets raterrno to RATNOERR.
421  *                      Otherwise, the second number must have been zero,
422  *                      so it sets raterrno to RATDIV0 and either prints a
423  *                      message or calls a user-supplied error handler.
424  */
425
426 RATIONAL
427 rinv(x)
428
429 RATIONAL x;
430
431 {
432         RATIONAL a;                     /* the answer */
433
434
435         /* check for division by 0 */
436         if (ZE(x)) {
437                 ratmsg(RATDIV0);        /* set raterrno, report error */
438                 return(zero);
439         }
440
441         raterrno = RATNOERR;            /* no errors from here on */
442
443         a.n = x.d;                      /* flip numerator and denominator */
444         a.d = x.n;
445
446         if (a.d < 0) {                  /* if x was negative, reverse signs */
447                 a.n = -a.n;
448                 a.d = -a.d;
449         }
450
451         return(a);
452 }
453 \f
454 /*
455  *      rrai()          raise a rational number to an integral power
456  *
457  *      This function raises a rational number to an integral power.  The
458  *      rational number must be in standard form.
459  *
460  *      Parameters:     x       the rational number
461  *                      n       the power, an integer
462  *
463  *      Return value:   The result (x to the nth power), if it is defined and
464  *                      can be represented as a RATIONAL, else 0/1.
465  *
466  *      Side effects:   If rrai() succeeds, it sets raterrno to RATNOERR.
467  *                      Otherwise, either zero is being raised to a non-
468  *                      positive power, or the numerator or denominator
469  *                      overflowed.  In this case, it sets raterrno to
470  *                      RATDIV0 or RATOVER, respectively, and either prints
471  *                      a message or calls a user-supplied error handler.
472  */
473
474 RATIONAL
475 rrai(x, n)
476
477 RATIONAL x;
478 register int n;
479
480 {
481         static RATIONAL one = {1,1};
482
483         RATIONAL a;                     /* the answer */
484         register int i;                 /* loop counter */
485
486
487         /* it is undefined to raise zero to a nonpositive power */
488         if (ZE(x) && n <= 0) {
489                 ratmsg(RATDIV0);        /* set raterrno, report error */
490                 return(zero);
491         }
492
493         raterrno = RATNOERR;            /* no error yet */
494
495         a = one;                        /* init to 1 */
496         if (n >= 0) {
497                 for (i = 0; i < n; i++) {
498                         a = rmul(a, x);         /* mul again by x */
499                         if (raterrno != RATNOERR)
500                                 return(zero);
501                 }
502         } else {
503                 for (i = 0; i > n; i--) {
504                         a = rdiv(a, x);         /* div again by x */
505                         if (raterrno != RATNOERR)
506                                 return(zero);
507                 }
508         }
509
510         return(a);
511 }
512 \f
513 /*
514  *      rred()          reduce a rational number to standard form
515  *
516  *      This function puts a rational number into standard form; that is,
517  *      numerator and denominator will be relatively prime and the denominator
518  *      will be positive.  On input, they may be any integers whose absolute
519  *      values do not exceed MAXLONG.
520  *
521  *      Parameters:     ap      pointer to the rational number
522  *
523  *      Return value:   None.
524  *
525  *      Side effects:   If ap->d is 0, the function sets raterrno to RATDIV0,
526  *                      either prints a message or calls a user-supplied
527  *                      error handler, and sets *ap to 0/1.  Otherwise, it
528  *                      sets raterrno to RATNOERR and puts *ap in standard form.
529  */
530
531 void
532 rred(ap)
533
534 register RATIONAL *ap;
535
536 {
537         register INT32B b, c, r; /* temp variables for Euclidean algorithm */
538         register int sign;      /* answer is pos (1) or neg (-1) */
539
540
541         /*
542          * Since the numerator and denominator can be anything <= MAXLONG,
543          * we must guard against division by 0.
544          */
545         if (ap->d == 0) {
546                 ratmsg(RATDIV0);        /* set raterrno, report error */
547                 *ap = zero;
548                 return;
549         }
550
551         raterrno = RATNOERR;            /* no errors possible from here on */
552
553         if (ap->n == 0) {               /* if so, answer is "0/1" */
554                 ap->d = 1;
555                 return;
556         }
557
558         /* now figure out sign of answer, and make n & d positive */
559         sign = 1;                       /* init to positive */
560         if (ap->n < 0) {                /* reverse if numerator neg */
561                 sign = -sign;
562                 ap->n = -(ap->n);
563         }
564         if (ap->d < 0) {                /* reverse if denominator neg */
565                 sign = -sign;
566                 ap->d = -(ap->d);
567         }
568
569         /* now check whether numerator or denominator are equal */
570         if (ap->n == ap->d) {           /* if so, answer is +1 or -1 */
571                 ap->n = sign;
572                 ap->d = 1;
573                 return;
574         }
575
576         if (ap->n < ap->d) {            /* set so that c > b */
577                 c = ap->d;
578                 b = ap->n;
579         } else {
580                 c = ap->n;
581                 b = ap->d;
582         }
583
584         /* use Euclidean Algorithm to find greatest common divisor of c & b */
585         do {
586                 r = c % b;
587                 c = b;
588                 b = r;
589         } while (r != 0);
590
591         /* now c is the greatest common divisor */
592
593         ap->n /= c;             /* divide out greatest common divisor */
594         ap->d /= c;             /* divide out greatest common divisor */
595
596         if (sign < 0)           /* put sign in if result should be negative */
597                 ap->n = -(ap->n);
598
599         return;
600 }
601 \f
602 /*
603  *      ator()          convert an ascii string to a rational number
604  *
605  *      This function takes an ascii string as input and interprets it as
606  *      a rational number.  White space may precede the number, but the
607  *      number may not contain white space.  The numerator may be preceded
608  *      by a minus sign.  The denomintor is optional, but if present, must
609  *      not contain a sign.  In short, the number must match one of the
610  *      following lex regular expressions, which starts where s points and
611  *      ends before the first character not matching the pattern:
612  *              [ \t\n]*-?[0-9]+
613  *              [ \t\n]*-?[0-9]+\/[0-9]+
614  *      Further restrictions are that the absolute values of numerator and
615  *      denominator cannot exceed MAXLONG, and the denominator cannot be 0.
616  *      If neither pattern is matched, or the further restrictions are
617  *      violated, the function sets *rp to 0/1 and returns NULL.  Otherwise,
618  *      it sets *rp to the result in standard form, and returns a pointer to
619  *      the first char after the number found.
620  *
621  *      Parameters:     rp      pointer to where the answer goes
622  *                      s       string containing ascii rational number
623  *
624  *      Return value:   If a valid rational number is found, the function
625  *                      returns a pointer to the next char in the string
626  *                      following the number.  Otherwise it returns NULL.
627  *
628  *      Side effects:   If ator() succeeds, it sets *rp to the result.
629  *                      Otherwise, it sets it to 0/1.
630  */
631
632 char *
633 ator(rp, s)
634
635 register RATIONAL *rp;
636 register char s[];
637
638 {
639         register char *p;       /* point somewhere in s[] */
640         int sign;               /* 1 means positive, -1 negative */
641
642
643         /* skip by white space */
644         for (p = s; isspace(*p); p++)
645                 ;
646
647         /* init sign to positive; then reverse it if a dash is found */
648         sign = 1;
649         if (p[0] == '-') {
650                 sign = -1;
651                 p++;
652         }
653
654         /* fail if there are no digits */
655         if ( ! isdigit(*p) ) {
656                 *rp = zero;
657                 return(NULL);
658         }
659
660         /*
661          * Collect the numerator digits, and defend against overflow.
662          */
663         rp->n = 0;
664         while ( isdigit(*p) ) {
665                 if (rp->n > MAXLONG / 10) {
666                         *rp = zero;
667                         return(NULL);
668                 }
669                 rp->n *= 10;
670                 if (rp->n > MAXLONG - (*p - '0')) {
671                         *rp = zero;
672                         return(NULL);
673                 }
674                 rp->n += *p++ - '0';
675         }
676
677         if (sign < 0)                   /* make negative if necessary */
678                 rp->n = -(rp->n);
679
680
681         /*
682          * If there is to be a denominator, collect its digits.  Otherwise,
683          * set it to 1.  Defend against overflow.
684          */
685         if (*p == '/') {
686                 p++;
687                 if ( ! isdigit(*p) ) {  /* must be digit (no '-' allowed) */
688                         *rp = zero;
689                         return(NULL);
690                 }
691                 rp->d = 0;
692                 while ( isdigit(*p) ) {
693                         if (rp->d > MAXLONG / 10) {
694                                 *rp = zero;
695                                 return(NULL);
696                         }
697                         rp->d *= 10;
698                         if (rp->d > MAXLONG - (*p - '0')) {
699                                 *rp = zero;
700                                 return(NULL);
701                         }
702                         rp->d += *p++ - '0';
703                 }
704                 if (rp->d == 0) {       /* zero denominator is a failure */
705                         *rp = zero;
706                         return(NULL);
707                 }
708         } else {
709                 rp->d = 1;              /* no denominator; assume 1 */
710         }
711
712         rred(rp);                       /* reduce the fraction */
713
714         return(p);                      /* first char after the number */
715 }
716 \f
717 /*
718  *      rtoa()          convert a rational number to an ascii string
719  *
720  *      This function takes a rational number as input converts it into
721  *      an ascii string.  If the denominator is 1, it will not be printed.
722  *      The number must be in standard form.
723  *
724  *      Parameters:     s       pointer to where the answer goes
725  *                      rp      pointer to the rational number
726  *
727  *      Return value:   The function returns a pointer to the next char in
728  *                      the string following the number.
729  *
730  *      Side effects:   The function sets s[] to the result.
731  */
732
733 char *
734 rtoa(s, rp)
735
736 register char s[];
737 RATIONAL *rp;
738
739 {
740         register INT32B num, den;       /* copy of num and den from *rp */
741         register int i;                 /* index into t[] */
742         char t[12];                     /* temp answer string */
743
744
745         num = rp->n;                    /* copy num and den for efficiency */
746         den = rp->d;
747
748         if (num < 0) {                  /* if num is negative */
749                 *s++ = '-';             /* output minus sign */
750                 num = -num;             /* and make num positive */
751         }
752
753         i = 0;
754         do {                            /* calc digits in reverse order */
755                 t[i++] = num % 10 + '0';
756                 num /= 10;
757         } while (num > 0);              /* always loop at least once so 0="0"*/
758
759         while (--i >= 0)                /* copy digits to answer string */
760                 *s++ = t[i];
761
762         if (den != 1) {                 /* if a denominator is needed */
763                 *s++ = '/';             /* fraction bar */
764                 i = 0;
765                 do {                    /* calc digits in reverse order */
766                         t[i++] = den % 10 + '0';
767                         den /= 10;
768                 } while (den > 0);
769
770                 while (--i >= 0)        /* copy digits to answer string */
771                         *s++ = t[i];
772         }
773
774         return(s);
775 }
776 \f
777 /*
778  *      gtrat()         decide whether one rational is greater than another
779  *
780  *      This function decides whether its first parameter is greater than
781  *      its second.  It is used by the macros GT, GE, LT, and LE.
782  *      The numbers must be in standard form.  (Actually, all that is
783  *      matters is that the denominators be positive.)
784  *
785  *      Parameters:     x       the first rational
786  *                      y       the second rational
787  *
788  *      Return value:   1 if x > y, otherwise 0
789  *
790  *      Side effects:   none
791  */
792
793 int
794 gtrat(x, y)
795
796 RATIONAL x, y;
797
798 {
799         INT32B a[2];            /* temp holding areas for 64-bit numbers */
800         INT32B b[2];
801
802
803         /* if no overflow possible, cross-multiply and return truth value */
804         /* note:  this depends on positive denominators */
805         if (SMALLRAT(x) && SMALLRAT(y))
806                 return(x.n * y.d > x.d * y.n);
807
808         /*
809          * The numbers are too big; we have to do it the hard way to avoid
810          * overflow.  Cross-multiply.  Note: this depends on positive
811          * denominators.
812          */
813         mul32_64(a, x.n, y.d);
814         mul32_64(b, x.d, y.n);
815
816         return(GT64(a, b));
817 }
818 \f
819 /*
820  *      ratmsg()        handle rational error of type "code"
821  *
822  *      This function sets raterrno.  Then calls the user's error handler,
823  *      if there is one, or else prints a message to standard error.
824  *
825  *      Parameters:     code    the error code
826  *
827  *      Return value:   None.
828  *
829  *      Side effects:   raterrno is set; then either a message is printed
830  *                      to standard error or the user's error handler is
831  *                      called.
832  */
833
834 static void
835 ratmsg(code)
836
837 int code;
838
839 {
840         raterrno = code;                /* set global error flag */
841
842         if (raterrfuncp == 0) {
843                 /* no user trap exists, so print message from here */
844                 switch (code) {
845                 case RATOVER:
846                         (void)fputs("rational overflow\n", stderr);
847                         break;
848
849                 case RATDIV0:
850                         (void)fputs("rational division by zero\n", stderr);
851                         break;
852
853                 case RATPARM:
854                         (void)fputs("invalid number passed to rational number routine\n", stderr);
855                         break;
856
857                 default:
858                         (void)fputs("error in rational routines\n", stderr);
859                         break;
860                 }
861         } else {
862                 /* call user trap function to handle the error */
863                 (*raterrfuncp)(code);
864         }
865 }
866 \f
867 /*
868  *      add64_64()      add 64-bit numbers to get a 64-bit number
869  *
870  *      This function adds two 64-bit signed numbers to get a 64-bit
871  *      signed number.  It is assumed that the result will not overflow.
872  *      Any of the inputs may be the same arrays.
873  *
874  *      Parameters:     a       answer goes here
875  *                      x       the first input
876  *                      y       the second input
877  *
878  *      Return value:   none
879  *
880  *      Side effects:   a is set to the result.
881  */
882
883 static void
884 add64_64(a, x, y)
885
886 INT32B a[2];
887 INT32B x[2];
888 INT32B y[2];
889
890 {
891         INT32B t[2];                    /* temp storage */
892
893
894         /* first add low and high parts separately */
895         /* use temp storage in case a[] is the same array as x[] or y[] */
896         t[0] = x[0] + y[0];
897         t[1] = x[1] + y[1];
898
899         /* figure out if the low part carries into the high part */
900         if (x[0] < 0 && y[0] < 0) {             /* both high order bits set */
901                 t[1]++;                         /* must be a carry */
902         } else if (x[0] < 0 || y[0] < 0) {      /* exactly one high bit set */
903                 if (t[0] >= 0)                  /* if result high bit clear */
904                         t[1]++;                 /* must be a carry */
905         }
906
907         a[0] = t[0];                    /* copy results */
908         a[1] = t[1];
909 }
910 \f
911 /*
912  *      mul32_64()      multiply 32-bit numbers to get a 64-bit number
913  *
914  *      This function multiplies two 32-bit signed numbers to get a 64-bit
915  *      signed number.  The numbers must not equal 0x80000000.  Overflow
916  *      cannot occur.
917  *
918  *      Parameters:     a       answer goes here
919  *                      x       the first 32-bit number
920  *                      y       the second 32-bit number
921  *
922  *      Return value:   none
923  *
924  *      Side effects:   a is set to the result.
925  */
926
927 static void
928 mul32_64(a, x, y)
929
930 INT32B a[2];
931 INT32B x;
932 INT32B y;
933
934 {
935         INT32B t[2];                    /* temp storage for inner terms */
936         INT32B xl, xh;                  /* low and high 16 bits of x */
937         INT32B yl, yh;                  /* low and high 16 bits of y */
938         int sign;                       /* sign of the result */
939
940
941         /* make both numbers positive and determine the sign of the result */
942         sign = 1;                               /* start at positive */
943         if (x < 0) {
944                 x = -x;
945                 sign = -sign;
946         }
947         if (y < 0) {
948                 y = -y;
949                 sign = -sign;
950         }
951
952         /* break x and y into high and low pieces */
953         xl = x & 0xffff;                /* 0 <= xl <= 0xffff */
954         xh = x >> 16;                   /* 0 <= xh <= 0x7fff */
955         yl = y & 0xffff;                /* 0 <= yl <= 0xffff */
956         yh = y >> 16;                   /* 0 <= yh <= 0x7fff */
957
958         /* multiply the outer parts */
959         a[0] = xl * yl;                 /* 0 <= a[0] <= 0xfffe0001 */
960         a[1] = xh * yh;                 /* 0 <= a[1] <= 0x3fff0001 */
961
962         /* multiply the inner parts and break the result in two pieces */
963         t[0] = xl * yh + xh * yl;       /* 0 <= t[0] <= 0xfffd0002 */
964         t[1] = (UINT32B)t[0] >> 16;             /* 0 <= t[1] <= 0x0000fffd */
965         t[0] <<= 16;                            /* 0 <= t[0] <= 0xffff0000 */
966
967         /* add the two partial products */
968         add64_64(a, a, t);              /* 0 <= a <= 0x3fffffff00000001 */
969
970         /* if the answer is supposed to be negative, negate it */
971         if (sign < 0)
972                 NEG64(a);
973 }
974 \f
975 /*
976  *      divmod64()      find quotient and remainder of two 64-bit numbers
977  *
978  *      This function takes two 64-bit numbers and divides the first by the
979  *      second, to get a quotient and remainder, both 64 bits.  It is assumed
980  *      that the first number is nonnegative and the second number is positive.
981  *      q and r must be different arrays.
982  *
983  *      Parameters:     x       first number (dividend)
984  *                      y       second number (divisor)
985  *                      q       quotient
986  *                      r       remainder
987  *
988  *      Return value:   none
989  *
990  *      Side effects:   q and r are altered to be the results
991  *                      x and y are not altered
992  */
993
994 static void
995 divmod64(x, y, q, r)
996
997 INT32B x[2];
998 INT32B y[2];
999 INT32B q[2];
1000 INT32B r[2];
1001
1002 {
1003         INT32B s[2];            /* temp storage for divisor */
1004         INT32B t[2];            /* temp storage for scratch */
1005         register int shift;     /* how far has y been shifted? */
1006
1007
1008         r[0] = x[0];            /* copy dividend to remainder place */
1009         r[1] = x[1];
1010         s[0] = y[0];            /* copy divisor to temp storage */
1011         s[1] = y[1];
1012
1013         /* shift divisor left until greater than dividend */
1014         /* compare as unsigned so no problem if it gets shifted into sign bit */
1015         for (shift = 0; LEU64(s, r); shift++)
1016                 SHL1U64(s);
1017
1018         SHR1U64(s);             /* shift it back right one, so <= dividend */
1019         shift--;
1020
1021         q[0] = 0;               /* start quotient at 0 */
1022         q[1] = 0;
1023
1024         /*
1025          * Loop once for each bit shifted.
1026          */
1027         for ( ; shift >= 0; shift--) {
1028                 /*
1029                  * If the current divisor does not exceed what's left of the
1030                  * dividend, subtract it from it, and record that by setting
1031                  * the low order bit of the current quotient.
1032                  */
1033                 if ( ! GT64(s, r) ) {
1034                         t[0] = s[0];
1035                         t[1] = s[1];
1036                         NEG64(t);
1037                         add64_64(r, r, t);
1038                         q[0] |= 1;
1039                 }
1040
1041                 /* shift quotient left and divisor right */
1042                 SHL1U64(q);
1043                 SHR1U64(s);
1044         }
1045
1046         SHR1U64(q);             /* shift quotient right */
1047 }
1048 \f
1049 /*
1050  *      red64_64()      reduce a 64 bit over 64 bit rational to lowest terms
1051  *
1052  *      This function takes two 64-bit numbers as numerator and denominator
1053  *      of a rational number, and reduces them to lowest terms, with the
1054  *      denominator positive.  If the user called this package correctly, the
1055  *      denominator cannot be zero, but to be defensive we check for that, and
1056  *      if it happens, set raterrno to RATPARM and either print a message or
1057  *      call a user-supplied error handler.
1058  *
1059  *      Parameters:     num     numerator
1060  *                      den     denominator
1061  *
1062  *      Return value:   none
1063  *
1064  *      Side effects:   num and den are altered to be the result
1065  */
1066
1067 static void
1068 red64_64(num, den)
1069
1070 INT32B num[2];
1071 INT32B den[2];
1072
1073 {
1074         INT32B b[2], c[2], r[2]; /* temp variables for Euclidean algorithm */
1075         INT32B junk[2];         /* placeholder for calling divmod64 */
1076         int sign;               /* answer is pos (1) or neg (-1) */
1077
1078
1079         if (den[1] == 0 && den[0] == 0) { /* if den == 0 */
1080                 /*
1081                  * This is an error.  The user must have called a routine with
1082                  * an invalid number for us to get here, in fact a number with
1083                  * a zero denominator, since "den" here always was created as
1084                  * the product of denominators.  Report the error and return
1085                  * zero.
1086                  */
1087                 num[1] = 0;             /* set num = 0 */
1088                 num[0] = 0;
1089                 den[1] = 0;             /* set den = 1 */
1090                 den[0] = 1;
1091                 ratmsg(RATPARM);        /* set raterrno, report error */
1092                 return;
1093         }
1094
1095         if (num[1] == 0 && num[0] == 0) { /* if num == 0 */
1096                 den[1] = 0;             /* set den = 1; answer is 0/1 */
1097                 den[0] = 1;
1098                 return;
1099         }
1100
1101         /* now figure out sign of answer, and make num & den positive */
1102         sign = 1;                       /* init to positive */
1103         if (num[1] < 0) {               /* if numerator neg */
1104                 sign = -sign;           /* reverse the sign */
1105                 NEG64(num);
1106         }
1107         if (den[1] < 0) {               /* if denominator neg */
1108                 sign = -sign;           /* reverse the sign */
1109                 NEG64(den);
1110         }
1111
1112         /* now check whether numerator or denominator is larger */
1113         if (EQ64(num, den)) {
1114                 num[0] = sign;          /* answer is +1 or -1 */
1115
1116                 if (sign < 0)           /* set high order word to sign bit */
1117                         num[1] = -1;
1118                 else
1119                         num[1] = 0;
1120
1121                 den[1] = 0;             /* set den to 1 */
1122                 den[0] = 1;
1123
1124                 return;
1125         }
1126
1127         /* set up c and b so that one is num, the other den, and c > b */
1128         if (LT64(num, den)) {                   /* if num < den */
1129                 c[0] = den[0];                  /* c = den */
1130                 c[1] = den[1];
1131                 b[0] = num[0];                  /* b = num */
1132                 b[1] = num[1];
1133         } else {
1134                 c[0] = num[0];                  /* c = num */
1135                 c[1] = num[1];
1136                 b[0] = den[0];                  /* b = den */
1137                 b[1] = den[1];
1138         }
1139
1140         /* use Euclidean Algorithm to find greatest common divisor of c & b */
1141         do {
1142                 divmod64(c, b, junk, r);        /* r = c % b */
1143                 c[0] = b[0];                    /* c = b */
1144                 c[1] = b[1];
1145                 b[0] = r[0];                    /* b = r */
1146                 b[1] = r[1];
1147         } while (r[0] != 0 || r[1] != 0);       /* while r != 0 */
1148
1149         /* now c is the greatest common divisor of num and den */
1150
1151         /* divide out the greatest common divisor and put the sign in */
1152         divmod64(num, c, num, junk);            /* num /= c */
1153         if (sign < 0)                           /* if should be negative */
1154                 NEG64(num);                     /* negate the numerator */
1155         divmod64(den, c, den, junk);            /* den /= c */
1156
1157         return;
1158 }