chiark / gitweb /
Merge branch 'arkkra' into shiny
[mup] / mup / mup / rational.c
CommitLineData
69695f33
MW
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__
167static void ratmsg(int code);
168static void add64_64(INT32B a[], INT32B x[], INT32B y[]);
169static void mul32_64(INT32B a[], INT32B x, INT32B y);
170static void divmod64(INT32B x[], INT32B y[], INT32B q[], INT32B r[]);
171static void red64_64(INT32B num[], INT32B den[]);
172#else
173static void ratmsg(), add64_64(), mul32_64(), divmod64(), red64_64();
174#endif
175
176
177int raterrno; /* set to error type upon return to user */
178void (*raterrfuncp)(); /* error handler functions to be called */
179
180static 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
201RATIONAL
202radd(x, y)
203
204RATIONAL 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
267RATIONAL
268rsub(x, y)
269
270RATIONAL 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
300RATIONAL
301rmul(x, y)
302
303RATIONAL 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
364RATIONAL
365rdiv(x, y)
366
367RATIONAL 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
397RATIONAL
398rneg(x)
399
400RATIONAL 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
426RATIONAL
427rinv(x)
428
429RATIONAL 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
474RATIONAL
475rrai(x, n)
476
477RATIONAL x;
478register 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
531void
532rred(ap)
533
534register 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
632char *
633ator(rp, s)
634
635register RATIONAL *rp;
636register 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
733char *
734rtoa(s, rp)
735
736register char s[];
737RATIONAL *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
793int
794gtrat(x, y)
795
796RATIONAL 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
834static void
835ratmsg(code)
836
837int 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
883static void
884add64_64(a, x, y)
885
886INT32B a[2];
887INT32B x[2];
888INT32B 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
927static void
928mul32_64(a, x, y)
929
930INT32B a[2];
931INT32B x;
932INT32B 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
994static void
995divmod64(x, y, q, r)
996
997INT32B x[2];
998INT32B y[2];
999INT32B q[2];
1000INT32B 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
1067static void
1068red64_64(num, den)
1069
1070INT32B num[2];
1071INT32B 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}