xref: /titanic_41/usr/src/lib/libmp/common/mdiv.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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
mp_mdiv(MINT * a,MINT * b,MINT * q,MINT * r)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
m_dsb(int qx,int n,short * a,short * b)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
m_trq(short v1,short v2,short u1,short u2,short u3)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
m_div(MINT * a,MINT * b,MINT * q,MINT * r)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