1*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 2*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 3*7c478bd9Sstevel@tonic-gate 4*7c478bd9Sstevel@tonic-gate 5*7c478bd9Sstevel@tonic-gate /* 6*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 7*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 8*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 9*7c478bd9Sstevel@tonic-gate */ 10*7c478bd9Sstevel@tonic-gate /* Portions Copyright(c) 1988, Sun Microsystems Inc. */ 11*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 12*7c478bd9Sstevel@tonic-gate 13*7c478bd9Sstevel@tonic-gate /* 14*7c478bd9Sstevel@tonic-gate * Copyright (c) 1997, by Sun Microsystems, Inc. 15*7c478bd9Sstevel@tonic-gate * All rights reserved. 16*7c478bd9Sstevel@tonic-gate */ 17*7c478bd9Sstevel@tonic-gate 18*7c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ 19*7c478bd9Sstevel@tonic-gate 20*7c478bd9Sstevel@tonic-gate /* LINTLIBRARY */ 21*7c478bd9Sstevel@tonic-gate 22*7c478bd9Sstevel@tonic-gate #include <mp.h> 23*7c478bd9Sstevel@tonic-gate #include <stdio.h> 24*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 25*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 26*7c478bd9Sstevel@tonic-gate #include "libmp.h" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate static void m_div(MINT *, MINT *, MINT *, MINT *); 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate void 31*7c478bd9Sstevel@tonic-gate mp_mdiv(MINT *a, MINT *b, MINT *q, MINT *r) 32*7c478bd9Sstevel@tonic-gate { 33*7c478bd9Sstevel@tonic-gate MINT x, y; 34*7c478bd9Sstevel@tonic-gate int sign; 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate sign = 1; 37*7c478bd9Sstevel@tonic-gate x.len = y.len = 0; 38*7c478bd9Sstevel@tonic-gate _mp_move(a, &x); 39*7c478bd9Sstevel@tonic-gate _mp_move(b, &y); 40*7c478bd9Sstevel@tonic-gate if (x.len < 0) { 41*7c478bd9Sstevel@tonic-gate sign = -1; 42*7c478bd9Sstevel@tonic-gate x.len = -x.len; 43*7c478bd9Sstevel@tonic-gate } 44*7c478bd9Sstevel@tonic-gate if (y.len < 0) { 45*7c478bd9Sstevel@tonic-gate sign = -sign; 46*7c478bd9Sstevel@tonic-gate y.len = -y.len; 47*7c478bd9Sstevel@tonic-gate } 48*7c478bd9Sstevel@tonic-gate _mp_xfree(q); 49*7c478bd9Sstevel@tonic-gate _mp_xfree(r); 50*7c478bd9Sstevel@tonic-gate m_div(&x, &y, q, r); 51*7c478bd9Sstevel@tonic-gate if (sign == -1) { 52*7c478bd9Sstevel@tonic-gate q->len = -q->len; 53*7c478bd9Sstevel@tonic-gate r->len = -r->len; 54*7c478bd9Sstevel@tonic-gate } 55*7c478bd9Sstevel@tonic-gate _mp_xfree(&x); 56*7c478bd9Sstevel@tonic-gate _mp_xfree(&y); 57*7c478bd9Sstevel@tonic-gate } 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate static int 60*7c478bd9Sstevel@tonic-gate m_dsb(int qx, int n, short *a, short *b) 61*7c478bd9Sstevel@tonic-gate { 62*7c478bd9Sstevel@tonic-gate int borrow; 63*7c478bd9Sstevel@tonic-gate int s3b2shit; 64*7c478bd9Sstevel@tonic-gate int j; 65*7c478bd9Sstevel@tonic-gate short fifteen = 15; 66*7c478bd9Sstevel@tonic-gate short *aptr, *bptr; 67*7c478bd9Sstevel@tonic-gate #ifdef DEBUGDSB 68*7c478bd9Sstevel@tonic-gate (void) printf("m_dsb %d %d %d %d\n", qx, n, *a, *b); 69*7c478bd9Sstevel@tonic-gate #endif 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate borrow = 0; 72*7c478bd9Sstevel@tonic-gate aptr = a; 73*7c478bd9Sstevel@tonic-gate bptr = b; 74*7c478bd9Sstevel@tonic-gate for (j = n; j > 0; j--) { 75*7c478bd9Sstevel@tonic-gate #ifdef DEBUGDSB 76*7c478bd9Sstevel@tonic-gate (void) printf("1 borrow=%x %d %d %d\n", borrow, (*aptr * qx), 77*7c478bd9Sstevel@tonic-gate *bptr, *aptr); 78*7c478bd9Sstevel@tonic-gate #endif 79*7c478bd9Sstevel@tonic-gate borrow -= (*aptr++) * qx - *bptr; 80*7c478bd9Sstevel@tonic-gate #ifdef DEBUGDSB 81*7c478bd9Sstevel@tonic-gate (void) printf("2 borrow=%x %d %d %d\n", borrow, (*aptr * qx), 82*7c478bd9Sstevel@tonic-gate *bptr, *aptr); 83*7c478bd9Sstevel@tonic-gate #endif 84*7c478bd9Sstevel@tonic-gate *bptr++ = (short)(borrow & 077777); 85*7c478bd9Sstevel@tonic-gate #ifdef DEBUGDSB 86*7c478bd9Sstevel@tonic-gate (void) printf("3 borrow=%x %d %d %d\n", borrow, (*aptr * qx), 87*7c478bd9Sstevel@tonic-gate *bptr, *aptr); 88*7c478bd9Sstevel@tonic-gate #endif 89*7c478bd9Sstevel@tonic-gate if (borrow >= 0) borrow >>= fifteen; /* 3b2 */ 90*7c478bd9Sstevel@tonic-gate else borrow = 0xfffe0000 | (borrow >> fifteen); 91*7c478bd9Sstevel@tonic-gate #ifdef DEBUGDSB 92*7c478bd9Sstevel@tonic-gate (void) printf("4 borrow=%x %d %d %d\n", borrow, (*aptr * qx), 93*7c478bd9Sstevel@tonic-gate *bptr, *aptr); 94*7c478bd9Sstevel@tonic-gate #endif 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate borrow += *bptr; 97*7c478bd9Sstevel@tonic-gate *bptr = (short)(borrow & 077777); 98*7c478bd9Sstevel@tonic-gate if (borrow >= 0) s3b2shit = borrow >> fifteen; /* 3b2 */ 99*7c478bd9Sstevel@tonic-gate else s3b2shit = 0xfffe0000 | (borrow >> fifteen); 100*7c478bd9Sstevel@tonic-gate if (s3b2shit == 0) { 101*7c478bd9Sstevel@tonic-gate #ifdef DEBUGDSB 102*7c478bd9Sstevel@tonic-gate (void) printf("mdsb 0\n"); 103*7c478bd9Sstevel@tonic-gate #endif 104*7c478bd9Sstevel@tonic-gate return (0); 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate borrow = 0; 107*7c478bd9Sstevel@tonic-gate aptr = a; 108*7c478bd9Sstevel@tonic-gate bptr = b; 109*7c478bd9Sstevel@tonic-gate for (j = n; j > 0; j--) { 110*7c478bd9Sstevel@tonic-gate borrow += *aptr++ + *bptr; 111*7c478bd9Sstevel@tonic-gate *bptr++ = (short)(borrow & 077777); 112*7c478bd9Sstevel@tonic-gate if (borrow >= 0) borrow >>= fifteen; /* 3b2 */ 113*7c478bd9Sstevel@tonic-gate else borrow = 0xfffe0000 | (borrow >>fifteen); 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate #ifdef DEBUGDSB 116*7c478bd9Sstevel@tonic-gate (void) printf("mdsb 1\n"); 117*7c478bd9Sstevel@tonic-gate #endif 118*7c478bd9Sstevel@tonic-gate return (1); 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate static int 122*7c478bd9Sstevel@tonic-gate m_trq(short v1, short v2, short u1, short u2, short u3) 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate short d; 125*7c478bd9Sstevel@tonic-gate int x1; 126*7c478bd9Sstevel@tonic-gate int c1; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate c1 = u1 * 0100000 + u2; 129*7c478bd9Sstevel@tonic-gate if (u1 == v1) { 130*7c478bd9Sstevel@tonic-gate d = 077777; 131*7c478bd9Sstevel@tonic-gate } else { 132*7c478bd9Sstevel@tonic-gate d = (short)(c1 / v1); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate do { 135*7c478bd9Sstevel@tonic-gate x1 = c1 - v1 * d; 136*7c478bd9Sstevel@tonic-gate x1 = x1 * 0100000 + u3 - v2 * d; 137*7c478bd9Sstevel@tonic-gate --d; 138*7c478bd9Sstevel@tonic-gate } while (x1 < 0); 139*7c478bd9Sstevel@tonic-gate #ifdef DEBUGMTRQ 140*7c478bd9Sstevel@tonic-gate (void) printf("mtrq %d %d %d %d %d %d\n", v1, v2, u1, u2, u3, (d+1)); 141*7c478bd9Sstevel@tonic-gate #endif 142*7c478bd9Sstevel@tonic-gate return ((int)d + 1); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate static void 146*7c478bd9Sstevel@tonic-gate m_div(MINT *a, MINT *b, MINT *q, MINT *r) 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate MINT u, v, x, w; 149*7c478bd9Sstevel@tonic-gate short d; 150*7c478bd9Sstevel@tonic-gate short *qval; 151*7c478bd9Sstevel@tonic-gate short *uval; 152*7c478bd9Sstevel@tonic-gate int j; 153*7c478bd9Sstevel@tonic-gate int qq; 154*7c478bd9Sstevel@tonic-gate int n; 155*7c478bd9Sstevel@tonic-gate short v1; 156*7c478bd9Sstevel@tonic-gate short v2; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate u.len = v.len = x.len = w.len = 0; 159*7c478bd9Sstevel@tonic-gate if (b->len == 0) { 160*7c478bd9Sstevel@tonic-gate _mp_fatal("mdiv divide by zero"); 161*7c478bd9Sstevel@tonic-gate return; 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate if (b->len == 1) { 164*7c478bd9Sstevel@tonic-gate r->val = _mp_xalloc(1, "m_div1"); 165*7c478bd9Sstevel@tonic-gate mp_sdiv(a, b->val[0], q, r->val); 166*7c478bd9Sstevel@tonic-gate if (r->val[0] == 0) { 167*7c478bd9Sstevel@tonic-gate free(r->val); 168*7c478bd9Sstevel@tonic-gate r->len = 0; 169*7c478bd9Sstevel@tonic-gate } else { 170*7c478bd9Sstevel@tonic-gate r->len = 1; 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate return; 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate if (a -> len < b -> len) { 175*7c478bd9Sstevel@tonic-gate q->len = 0; 176*7c478bd9Sstevel@tonic-gate r->len = a->len; 177*7c478bd9Sstevel@tonic-gate r->val = _mp_xalloc(r->len, "m_div2"); 178*7c478bd9Sstevel@tonic-gate for (qq = 0; qq < r->len; qq++) { 179*7c478bd9Sstevel@tonic-gate r->val[qq] = a->val[qq]; 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate return; 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate x.len = 1; 184*7c478bd9Sstevel@tonic-gate x.val = &d; 185*7c478bd9Sstevel@tonic-gate n = b->len; 186*7c478bd9Sstevel@tonic-gate d = 0100000 / (b->val[n - 1] + 1); 187*7c478bd9Sstevel@tonic-gate mp_mult(a, &x, &u); /* subtle: relies on mult allocing extra space */ 188*7c478bd9Sstevel@tonic-gate mp_mult(b, &x, &v); 189*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MDIV 190*7c478bd9Sstevel@tonic-gate (void) printf(" u=%s\n", mtox(&u)); 191*7c478bd9Sstevel@tonic-gate (void) printf(" v=%s\n", mtox(&v)); 192*7c478bd9Sstevel@tonic-gate #endif 193*7c478bd9Sstevel@tonic-gate v1 = v.val[n - 1]; 194*7c478bd9Sstevel@tonic-gate v2 = v.val[n - 2]; 195*7c478bd9Sstevel@tonic-gate qval = _mp_xalloc(a -> len - n + 1, "m_div3"); 196*7c478bd9Sstevel@tonic-gate uval = u.val; 197*7c478bd9Sstevel@tonic-gate for (j = a->len - n; j >= 0; j--) { 198*7c478bd9Sstevel@tonic-gate qq = m_trq(v1, v2, uval[j + n], uval[j + n - 1], 199*7c478bd9Sstevel@tonic-gate uval[j + n - 2]); 200*7c478bd9Sstevel@tonic-gate if (m_dsb(qq, n, v.val, uval + j)) 201*7c478bd9Sstevel@tonic-gate qq -= 1; 202*7c478bd9Sstevel@tonic-gate qval[j] = (short)qq; 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate x.len = n; 205*7c478bd9Sstevel@tonic-gate x.val = u.val; 206*7c478bd9Sstevel@tonic-gate _mp_mcan(&x); 207*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MDIV 208*7c478bd9Sstevel@tonic-gate (void) printf(" x=%s\n", mtox(&x)); 209*7c478bd9Sstevel@tonic-gate (void) printf(" d(in)=%d\n", (d)); 210*7c478bd9Sstevel@tonic-gate #endif 211*7c478bd9Sstevel@tonic-gate mp_sdiv(&x, d, &w, &d); 212*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MDIV 213*7c478bd9Sstevel@tonic-gate (void) printf(" w=%s\n", mtox(&w)); 214*7c478bd9Sstevel@tonic-gate (void) printf(" d(out)=%d\n", (d)); 215*7c478bd9Sstevel@tonic-gate #endif 216*7c478bd9Sstevel@tonic-gate r->len = w.len; 217*7c478bd9Sstevel@tonic-gate r->val = w.val; 218*7c478bd9Sstevel@tonic-gate q->val = qval; 219*7c478bd9Sstevel@tonic-gate qq = a->len - n + 1; 220*7c478bd9Sstevel@tonic-gate if (qq > 0 && qval[qq - 1] == 0) 221*7c478bd9Sstevel@tonic-gate qq -= 1; 222*7c478bd9Sstevel@tonic-gate q->len = qq; 223*7c478bd9Sstevel@tonic-gate if (qq == 0) 224*7c478bd9Sstevel@tonic-gate free(qval); 225*7c478bd9Sstevel@tonic-gate if (x.len != 0) 226*7c478bd9Sstevel@tonic-gate _mp_xfree(&u); 227*7c478bd9Sstevel@tonic-gate _mp_xfree(&v); 228*7c478bd9Sstevel@tonic-gate } 229