|
|
1.1 ! root 1: #include "mprec.h" ! 2: #include <assert.h> ! 3: #include <sys/mdata.h> ! 4: ! 5: ! 6: /* ! 7: * Mdiv sets the mints pointed to by "q" and "r" to the quotient ! 8: * and remainder (respectively) of dividing "a" by "b". If "b" ! 9: * is zero, then it calls mperr with the appropriate message. ! 10: * The division is performed such that the following two properties ! 11: * hold : ! 12: * 1. "r" + "q" * "b" = "a". ! 13: * 2. The sign of "r" = the sign of "q". ! 14: * 3. The abs. value of "r" < abs. value of "b". ! 15: * Note that no assumption is made as to the distinctness of "a", ! 16: * "b", "q" and "r". ! 17: */ ! 18: ! 19: void ! 20: mdiv(a, b, q, r) ! 21: register mint *a, *b, *q, *r; ! 22: { ! 23: int apos, bpos; ! 24: mint al, bl; ! 25: int ispos(); ! 26: void shortd(), longd(); ! 27: ! 28: /* take care of small denominators */ ! 29: if (b->len <= 2 && ( ! 30: b->len == 1 /* 0 to BASE - 2 */ ! 31: || b->val[1] == NEFL /* -BASE to -2 */ ! 32: || b->val[1] == 0 /* BASE - 1 */ ! 33: || (b->val[1] == 1 && b->val[0] == 0) /* BASE */ ! 34: ) ! 35: ) { ! 36: shortd(a, b, q, r); ! 37: return; ! 38: } ! 39: ! 40: /* make denominator negative */ ! 41: if (bpos = ispos(b)) { ! 42: minit(&bl); ! 43: mneg(b, &bl); ! 44: b = &bl; ! 45: } ! 46: assert(b->len > 2); ! 47: ! 48: /* copy numerator, makeing it positive */ ! 49: minit(&al); ! 50: if (apos = ispos(a)) ! 51: mcopy(a, &al); ! 52: else ! 53: mneg(a, &al); ! 54: a = &al; ! 55: ! 56: /* ! 57: * BASE ^ (a->len - 1) <= a < BASE ^ a->len ! 58: * BASE ^ (b->len - 2) < -b <= BASE ^ (b->len - 1) ! 59: * ! 60: * do divide. ! 61: */ ! 62: ! 63: if (a->len <= b->len - 2) ! 64: mcopy(mzero, q); ! 65: else ! 66: longd(a, b, q); ! 67: ! 68: /* adjust signs */ ! 69: if (apos ? !bpos : bpos) { ! 70: mneg(q, q); ! 71: mneg(a, r); ! 72: } else ! 73: mcopy(a, r); ! 74: ! 75: /* throw away garbage */ ! 76: mpfree(al.val); ! 77: if (bpos) ! 78: mpfree(bl.val); ! 79: } ! 80: ! 81: ! 82: /* ! 83: * Shortd divides the mints pointed to by "a" and "b". ! 84: * It sets the mints pointed to by "q" and "r" to the quotient ! 85: * and remainder respectively. It assumes that "b" is between ! 86: * -BASE and BASE. ! 87: */ ! 88: ! 89: static void ! 90: shortd(a, b, q, r) ! 91: register mint *a, *b, *q, *r; ! 92: { ! 93: int rem; ! 94: int denom; ! 95: ! 96: assert(b->len <= 2); ! 97: if (ispos(b)) { ! 98: denom = b->val[0]; ! 99: if (b->len != 1 && denom == 0) ! 100: denom = BASE; ! 101: } else ! 102: denom = b->val[0] - BASE; ! 103: assert(-BASE <= denom && denom <= BASE); ! 104: sdiv(a, denom, q, &rem); ! 105: mitom(rem, r); ! 106: } ! 107: ! 108: ! 109: /* ! 110: * Longd does the actual long divide. It sets "q" and "a" to ! 111: * the quotient and remainder (respectively) of "a" / (- "b"). ! 112: * It assumes the following: ! 113: * 1. "b" is negative ! 114: * 2. "a" is positive ! 115: * 3. "a" is a destroyable copy ! 116: * 4. ("a"->len + 2) > ("b"->len) >= 3 ! 117: */ ! 118: ! 119: static void ! 120: longd(a, b, q) ! 121: register mint *a, *b; ! 122: mint *q; ! 123: { ! 124: register char *rp; ! 125: unsigned shift; ! 126: int tden; ! 127: unsigned tbias; ! 128: mint res; ! 129: ! 130: ! 131: /* ! 132: * For "a" we have the range ! 133: * (BASE - 1) * BASE ^ (a->len - 1) > a ! 134: * a >= (BASE - 1) * BASE ^ (a->len - 2) ! 135: * and for "b" we want ! 136: * tden * BASE ^ tbias >= -b > (tden - 1) * BASE ^ tbias ! 137: */ ! 138: ! 139: tden = est(b); ! 140: tbias = b->len - 3; ! 141: ! 142: assert(a->len >= tbias + 2); ! 143: res.len = a->len - tbias; ! 144: res.val = (char *)mpalc(res.len); ! 145: rp = &res.val[res.len - 1]; ! 146: *rp-- = 0; ! 147: shift = a->len - (tbias + 2); ! 148: ! 149: do { ! 150: *rp = guess(tden, tbias + shift, a); ! 151: msma(b, *rp, shift, a); ! 152: if (snc(b, shift, a)) { ! 153: ++*rp; ! 154: msma(b, 1, shift, a); ! 155: } ! 156: --rp; ! 157: } while (shift-- != 0); ! 158: norm(a); ! 159: norm(&res); ! 160: mpfree(q->val); ! 161: *q = res; ! 162: } ! 163: ! 164: ! 165: ! 166: ! 167: /* ! 168: * Est estimates the mint pointed to by "a". Its result ! 169: * satisfies the following: ! 170: * 1. result * BASE ^ (a->len - 3) >= -a ! 171: * && -a > (result - 1) * BASE ^ (a->len - 3) ! 172: * 2. BASE ^ 2 >= mant > BASE ! 173: * Note that "a" is assumed to be negative and have length atleast ! 174: * three. ! 175: */ ! 176: static int ! 177: est(a) ! 178: register mint *a; ! 179: { ! 180: register int result; ! 181: ! 182: assert(!ispos(a) && a->len >= 3); ! 183: result = (NEFL - a->val[a->len - 2]) << L2BASE; ! 184: result += NEFL - a->val[a->len - 3] + 1; ! 185: assert(BASE * BASE >= result && result > BASE); ! 186: return (result); ! 187: } ! 188: ! 189: ! 190: /* ! 191: * Guess returns an integer which is the integral part of ! 192: * "a" / ("den" * BASE ^ "shift") ! 193: * Note that it is assumed that the following hold: ! 194: * 1. "a" is positive. ! 195: * 2. BASE ^ 2 >= "den" > BASE ! 196: * 3. the quotient is a single "digit" (ie. NEFL > quotient >= 0) ! 197: */ ! 198: ! 199: static int ! 200: guess(den, shift, a) ! 201: int den; ! 202: unsigned shift; ! 203: mint *a; ! 204: { ! 205: register char *ap = &a->val[a->len - 1]; ! 206: long result; ! 207: ! 208: if (*ap == 0) ! 209: --ap; ! 210: assert(ap + 1 - a->val <= shift + 3); ! 211: if (ap + 1 - a->val < shift + 2) ! 212: return (0); ! 213: result = (ap[0] << L2BASE) + ap[-1]; ! 214: if (ap + 1 - a->val == shift + 3) ! 215: result = (result << L2BASE) + ap[-2]; ! 216: assert(result < den * (long)BASE); ! 217: return (result / den); ! 218: } ! 219: ! 220: ! 221: /* ! 222: * Snc does a shift-negate-compare. Specifically, it assumes that ! 223: * "b" is negative, "a" is positive and it returns wether or not ! 224: * a >= -b * BASE ^ shift ! 225: * (ie. a + b * BASE ^ shift is positive (ie. >= 0).) ! 226: */ ! 227: ! 228: static ! 229: snc(b, shift, a) ! 230: mint *a, *b; ! 231: unsigned shift; ! 232: { ! 233: register char *ap; ! 234: register char *bp; ! 235: register char *limit; ! 236: int aleng, bleng; ! 237: int temp; ! 238: ! 239: /* ! 240: * correct length of a ! 241: */ ! 242: limit = a->val; ! 243: for (ap = &limit[a->len - 1]; *ap == 0 && ap > limit; --ap) ! 244: ; ! 245: a->len = ap - limit + 1; ! 246: if (*ap == NEFL) ! 247: ++a->len; ! 248: aleng = ap - limit + 1; ! 249: bleng = b->len + shift - 1; ! 250: ! 251: /* ! 252: * BASE ^ aleng > a >= BASE ^ (aleng - 1) ! 253: * BASE ^ (b->len - 1) >= -b > BASE ^ (b->len - 2) ! 254: * so multiplying by BASE ^ shift gives ! 255: * BASE ^ bleng >= -b * BASE ^ shift > BASE ^ (bleng - 1) ! 256: * This means that ! 257: * IF bleng > aleng ! 258: * THEN bleng - 1 >= aleng ! 259: * SO -b * BASE ^ shift > BASE ^ (bleng - 1) ! 260: * >= BASE ^ aleng ! 261: * > a ! 262: * and thus we return FALSE. ! 263: * Also we have ! 264: * IF aleng > bleng ! 265: * THEN aleng - 1 >= bleng ! 266: * SO a >= BASE ^ (aleng - 1) ! 267: * >= BASE ^ bleng ! 268: * >= -b * BASE ^ shift ! 269: * and thus we return TRUE. ! 270: * Finally ! 271: * If aleng = bleng then the two numbers line up and ! 272: * it is just a matter of returning wether or not their ! 273: * sum would cause a carry. ! 274: */ ! 275: if (aleng != bleng) ! 276: return (aleng > bleng); ! 277: limit = b->val; ! 278: for (bp = &limit[b->len - 2]; bp >= limit; --bp, --ap) { ! 279: temp = *ap + *bp; ! 280: if (temp >= BASE) ! 281: return (TRUE); ! 282: if (temp < NEFL) ! 283: return (FALSE); ! 284: } ! 285: return (FALSE); ! 286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.