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