1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
   2: 
   3: /*
   4:   $Header: b1nuR.c,v 1.4 85/08/22 16:51:49 timo Exp $
   5: */
   6: 
   7: /* Rational arithmetic */
   8: 
   9: #include "b.h"
  10: #include "b0con.h"
  11: #include "b1obj.h"
  12: #include "b1num.h"
  13: #include "b3err.h"
  14: 
  15: /* Length calculations used for fraction sizes: */
  16: #define Maxlen(u, v) \
  17:     (Roundsize(u) > Roundsize(v) ? Roundsize(u) : Roundsize(v))
  18: #define Sumlen(u, v) (Roundsize(u)+Roundsize(v))
  19: #define Difflen(u, v) (Roundsize(u)-Roundsize(v))
  20: 
  21: /* To shut off lint and other warnings: */
  22: #undef Copy
  23: #define Copy(x) ((integer)copy((value)(x)))
  24: 
  25: /* Globally used constants */
  26: 
  27: rational rat_zero;
  28: rational rat_half;
  29: 
  30: /* Make a normalized rational from two integers */
  31: 
  32: Visible rational mk_rat(x, y, len) integer x, y; int len; {
  33:     rational a;
  34:     integer u,v;
  35: 
  36:     if (y == int_0) {
  37:         if (interrupted)
  38:             return rat_zero;
  39:         syserr(MESS(1200, "mk_rat(x, y) with y=0"));
  40:     }
  41: 
  42:     if (x == int_0 && len <= 0) return (rational) Copy(rat_zero);
  43: 
  44:     if (Msd(y) < 0) {   /* interchange signs */
  45:         u = int_neg(x);
  46:         v = int_neg(y);
  47:     } else {
  48:         u = Copy(x);
  49:         v = Copy(y);
  50:     }
  51: 
  52:     a = (rational) grab_rat();
  53:     if (len > 0 && len+2 <= Maxintlet) Length(a) = -2 - len;
  54: 
  55:     if (u == int_0 || v == int_1) {
  56:         /* No simplification possible */
  57:         Numerator(a) = Copy(u);
  58:         Denominator(a) = int_1;
  59:     } else {
  60:         integer g, abs_u;
  61: 
  62:         if (Msd(u) < 0) abs_u = int_neg(u);
  63:         else abs_u = Copy(u);
  64:         g = int_gcd(abs_u, v);
  65:         release((value) abs_u);
  66: 
  67:         if (g != int_1) {
  68:             Numerator(a) = int_quot(u, g);
  69:             Denominator(a) = int_quot(v, g);
  70:         } else {
  71:             Numerator(a) = Copy(u);
  72:             Denominator(a) = Copy(v);
  73:         }
  74:         release((value) g);
  75:     }
  76: 
  77:     release((value) u); release((value) v);
  78: 
  79:     return a;
  80: }
  81: 
  82: 
  83: /* Arithmetic on rational numbers */
  84: 
  85: /* Shorthands: */
  86: #define N(u) Numerator(u)
  87: #define D(u) Denominator(u)
  88: 
  89: Visible rational rat_sum(u, v) register rational u, v; {
  90:     integer t1, t2, t3, t4;
  91:     rational a;
  92: 
  93:     t2= int_prod(N(u), D(v));
  94:     t3= int_prod(N(v), D(u));
  95:     t1= int_sum(t2, t3);
  96:     t4= int_prod(D(u), D(v));
  97:     a= mk_rat(t1, t4, Maxlen(u, v));
  98:     release((value) t1); release((value) t2);
  99:     release((value) t3); release((value) t4);
 100: 
 101:     return a;
 102: }
 103: 
 104: 
 105: Visible rational rat_diff(u, v) register rational u, v; {
 106:     integer t1, t2, t3, t4;
 107:     rational a;
 108: 
 109:     t2= int_prod(N(u), D(v));
 110:     t3= int_prod(N(v), D(u));
 111:     t1= int_diff(t2, t3);
 112:     t4= int_prod(D(u), D(v));
 113:     a= mk_rat(t1, t4, Maxlen(u, v));
 114:     release((value) t1); release((value) t2);
 115:     release((value) t3); release((value) t4);
 116: 
 117:     return a;
 118: }
 119: 
 120: 
 121: Visible rational rat_prod(u, v) register rational u, v; {
 122:     integer t1, t2;
 123:     rational a;
 124: 
 125:     t1= int_prod(N(u), N(v));
 126:     t2= int_prod(D(u), D(v));
 127:     a= mk_rat(t1, t2, Sumlen(u, v));
 128:     release((value) t1); release((value) t2);
 129: 
 130:     return a;
 131: }
 132: 
 133: 
 134: Visible rational rat_quot(u, v) register rational u, v; {
 135:     integer t1, t2;
 136:     rational a;
 137: 
 138:     if (Numerator(v) == int_0) {
 139:         error(MESS(1201, "in u/v, v is zero"));
 140:         return (rational) Copy(rat_zero);
 141:     }
 142: 
 143:     t1= int_prod(N(u), D(v));
 144:     t2= int_prod(D(u), N(v));
 145:     a= mk_rat(t1, t2, Difflen(u, v));
 146:     release((value) t1); release((value) t2);
 147: 
 148:     return a;
 149: }
 150: 
 151: 
 152: Visible rational rat_neg(u) register rational u; {
 153:     register rational a;
 154: 
 155:     /* Avoid a real subtraction from zero */
 156: 
 157:     if (Numerator(u) == int_0) return (rational) Copy(u);
 158: 
 159:     a = (rational) grab_rat();
 160:     N(a) = int_neg(N(u));
 161:     D(a) = Copy(D(u));
 162:     Length(a) = Length(u);
 163: 
 164:     return a;
 165: }
 166: 
 167: 
 168: /* Rational number to the integral power */
 169: 
 170: Visible rational rat_power(a, n) rational a; integer n; {
 171:     integer u, v, tu, tv, temp;
 172: 
 173:     if (n == int_0) return mk_rat(int_1, int_1, 0);
 174: 
 175:     if (Msd(n) < 0) {
 176:         if (Numerator(a) == int_0) {
 177:             error(MESS(1202, "in 0**n, n is negative"));
 178:             return (rational) Copy(a);
 179:         }
 180:         if (Msd(Numerator(a)) < 0) {
 181:             u= int_neg(Denominator(a));
 182:             v = int_neg(Numerator(a));
 183:         }
 184:         else {
 185:             u = Copy(Denominator(a));
 186:             v = Copy(Numerator(a));
 187:         }
 188:         n = int_neg(n);
 189:     } else {
 190:         if (Numerator(a) == int_0) return (rational) Copy(a);
 191:             /* To avoid necessary simplification later on */
 192:         u = Copy(Numerator(a));
 193:         v = Copy(Denominator(a));
 194:         n = Copy(n);
 195:     }
 196: 
 197:     tu = int_1;
 198:     tv = int_1;
 199: 
 200:     while (n != int_0 && !interrupted) {
 201:         if (Odd(Lsd(n))) {
 202:             if (u != int_1) {
 203:                 temp = tu;
 204:                 tu = int_prod(u, tu);
 205:                 release((value) temp);
 206:             }
 207:             if (v != int_1) {
 208:                 temp = tv;
 209:                 tv = int_prod(v, tv);
 210:                 release((value) temp);
 211:             }
 212:             if (n == int_1)
 213:                 break; /* Avoid useless last squaring */
 214:         }
 215: 
 216:         /* Square u, v */
 217: 
 218:         if (u != int_1) {
 219:             temp = u;
 220:             u = int_prod(u, u);
 221:             release((value) temp);
 222:         }
 223:         if (v != int_1) {
 224:             temp = v;
 225:             v = int_prod(v, v);
 226:             release((value) temp);
 227:         }
 228: 
 229:         n = int_half(n);
 230:     } /* while (n!=0) */
 231: 
 232:     release((value) n);
 233:     release((value) u);
 234:     release((value) v);
 235:     a = (rational) grab_rat();
 236:     Numerator(a) = tu;
 237:     Denominator(a) = tv;
 238: 
 239:     return a;
 240: }
 241: 
 242: 
 243: /* Compare two rational numbers */
 244: 
 245: Visible relation rat_comp(u, v) register rational u, v; {
 246:     int sd, su, sv;
 247:     integer nu, nv;
 248: 
 249:     /* 1. Compare pointers */
 250:     if (u == v || N(u) == N(v) && D(u) == D(v)) return 0;
 251: 
 252:     /* 2. Either zero? */
 253:     if (N(u) == int_0) return int_comp(int_0, N(v));
 254:     if (N(v) == int_0) return int_comp(N(u), int_0);
 255: 
 256:     /* 3. Compare signs */
 257:     su = Msd(N(u));
 258:     sv = Msd(N(v));
 259:     su = (su>0) - (su<0);
 260:     sv = (sv>0) - (sv<0);
 261:     if (su != sv) return su > sv ? 1 : -1;
 262: 
 263:     /* 4. Compute numerator of difference and return sign */
 264:     nu= int_prod(N(u), D(v));
 265:     nv= int_prod(N(v), D(u));
 266:     sd= int_comp(nu, nv);
 267:     release((value) nu); release((value) nv);
 268:     return sd;
 269: }
 270: 
 271: Visible Procedure rat_init() {
 272:     rat_zero = (rational) grab_rat();
 273:     Numerator(rat_zero) = int_0;
 274:     Denominator(rat_zero) = int_1;
 275: 
 276:     rat_half = (rational) grab_rat();
 277:     Numerator(rat_half) = int_1;
 278:     Denominator(rat_half) = int_2;
 279: }
 280: 
 281: Visible Procedure endrat() {
 282:     release((value) rat_zero);
 283:     release((value) rat_half);
 284: }

Defined functions

endrat defined in line 281; used 1 times
rat_comp defined in line 245; used 3 times
rat_diff defined in line 105; used 1 times
rat_init defined in line 271; used 1 times
rat_prod defined in line 121; used 1 times
rat_quot defined in line 134; used 1 times
rat_sum defined in line 89; used 1 times

Defined macros

Copy defined in line 23; used 18 times
D defined in line 87; used 18 times
Difflen defined in line 19; used 1 times
Maxlen defined in line 16; used 2 times
N defined in line 86; used 20 times
Sumlen defined in line 18; used 1 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2849
Valid CSS Valid XHTML 1.0 Strict