Commit | Line | Data |
---|---|---|
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__ | |
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 | } |