Little fix after the last commit (mostly a git fail)
[eigenmath-fx.git] / mmul.cpp
blob88ec5861ba6ce7a46d266636a9196950df783088
1 // Bignum multiplication and division
3 #include "stdafx.h"
4 #include "defs.h"
6 extern int ge(unsigned int *, unsigned int *, int);
8 static void mulf(unsigned int *, unsigned int *, int, unsigned int);
9 static void addf(unsigned int *, unsigned int *, int);
10 static void subf(unsigned int *, unsigned int *, int);
12 unsigned int *
13 mmul(unsigned int *a, unsigned int *b)
15 int alen, blen, i, n;
16 unsigned int *t, *x;
18 if (MZERO(a) || MZERO(b))
19 return mint(0);
21 if (MLENGTH(a) == 1 && a[0] == 1) {
22 t = mcopy(b);
23 MSIGN(t) *= MSIGN(a);
24 return t;
27 if (MLENGTH(b) == 1 && b[0] == 1) {
28 t = mcopy(a);
29 MSIGN(t) *= MSIGN(b);
30 return t;
33 alen = MLENGTH(a);
34 blen = MLENGTH(b);
36 n = alen + blen;
38 x = mnew(n);
40 t = mnew(alen + 1);
42 for (i = 0; i < n; i++)
43 x[i] = 0;
45 /* sum of partial products */
47 for (i = 0; i < blen; i++) {
48 mulf(t, a, alen, b[i]);
49 addf(x + i, t, alen + 1);
52 mfree(t);
54 /* length of product */
56 for (i = n - 1; i > 0; i--)
57 if (x[i])
58 break;
60 MLENGTH(x) = i + 1;
62 MSIGN(x) = MSIGN(a) * MSIGN(b);
64 return x;
67 unsigned int *
68 mdiv(unsigned int *a, unsigned int *b)
70 int alen, blen, i, n;
71 unsigned int c, *t, *x, *y;
72 unsigned long long jj, kk;
74 if (MZERO(b))
75 stop("divide by zero");
77 if (MZERO(a))
78 return mint(0);
80 alen = MLENGTH(a);
81 blen = MLENGTH(b);
83 n = alen - blen;
85 if (n < 0)
86 return mint(0);
88 x = mnew(alen + 1);
90 for (i = 0; i < alen; i++)
91 x[i] = a[i];
93 x[i] = 0;
95 y = mnew(n + 1);
97 t = mnew(blen + 1);
99 /* Add 1 here to round up in case the remaining words are non-zero. */
101 kk = (unsigned long long) b[blen - 1] + 1;
103 for (i = 0; i <= n; i++) {
105 y[n - i] = 0;
107 for (;;) {
109 /* estimate the partial quotient */
111 if (little_endian()) {
112 ((unsigned int *) &jj)[0] = x[alen - i - 1];
113 ((unsigned int *) &jj)[1] = x[alen - i - 0];
114 } else {
115 ((unsigned int *) &jj)[1] = x[alen - i - 1];
116 ((unsigned int *) &jj)[0] = x[alen - i - 0];
119 c = (unsigned int) (jj / kk);
121 if (c == 0) {
122 if (ge(x + n - i, b, blen)) { /* see note 1 */
123 y[n - i]++;
124 subf(x + n - i, b, blen);
126 break;
129 y[n - i] += c;
130 mulf(t, b, blen, c);
131 subf(x + n - i, t, blen + 1);
135 mfree(t);
137 mfree(x);
139 /* length of quotient */
141 for (i = n; i > 0; i--)
142 if (y[i])
143 break;
145 if (i == 0 && y[0] == 0) {
146 mfree(y);
147 y = mint(0);
148 } else {
149 MLENGTH(y) = i + 1;
150 MSIGN(y) = MSIGN(a) * MSIGN(b);
153 return y;
156 // a = a + b
158 static void
159 addf(unsigned int *a, unsigned int *b, int len)
161 int i;
162 long long t = 0; /* can be signed or unsigned */
163 for (i = 0; i < len; i++) {
164 t += (long long) a[i] + b[i];
165 a[i] = (unsigned int) t;
166 t >>= 32;
170 // a = a - b
172 static void
173 subf(unsigned int *a, unsigned int *b, int len)
175 int i;
176 long long t = 0; /* must be signed */
177 for (i = 0; i < len; i++) {
178 t += (long long) a[i] - b[i];
179 a[i] = (unsigned int) t;
180 t >>= 32;
184 // a = b * c
186 // 0xffffffff + 0xffffffff * 0xffffffff == 0xffffffff00000000
188 static void
189 mulf(unsigned int *a, unsigned int *b, int len, unsigned int c)
191 int i;
192 unsigned long long t = 0; /* must be unsigned */
193 for (i = 0; i < len; i++) {
194 t += (unsigned long long) b[i] * c;
195 a[i] = (unsigned int) t;
196 t >>= 32;
198 a[i] = (unsigned int) t;
201 unsigned int *
202 mmod(unsigned int *a, unsigned int *b)
204 int alen, blen, i, n;
205 unsigned int c, *t, *x, *y;
206 unsigned long long jj, kk;
208 if (MZERO(b))
209 stop("divide by zero");
211 if (MZERO(a))
212 return mint(0);
214 alen = MLENGTH(a);
215 blen = MLENGTH(b);
217 n = alen - blen;
219 if (n < 0)
220 return mcopy(a);
222 x = mnew(alen + 1);
224 for (i = 0; i < alen; i++)
225 x[i] = a[i];
227 x[i] = 0;
229 y = mnew(n + 1);
231 t = mnew(blen + 1);
233 kk = (unsigned long long) b[blen - 1] + 1;
235 for (i = 0; i <= n; i++) {
237 y[n - i] = 0;
239 for (;;) {
241 /* estimate the partial quotient */
243 if (little_endian()) {
244 ((unsigned int *) &jj)[0] = x[alen - i - 1];
245 ((unsigned int *) &jj)[1] = x[alen - i - 0];
246 } else {
247 ((unsigned int *) &jj)[1] = x[alen - i - 1];
248 ((unsigned int *) &jj)[0] = x[alen - i - 0];
251 c = (int) (jj / kk);
253 if (c == 0) {
254 if (ge(x + n - i, b, blen)) { /* see note 1 */
255 y[n - i]++;
256 subf(x + n - i, b, blen);
258 break;
261 y[n - i] += c;
262 mulf(t, b, blen, c);
263 subf(x + n - i, t, blen + 1);
267 mfree(t);
269 mfree(y);
271 /* length of remainder */
273 for (i = blen - 1; i > 0; i--)
274 if (x[i])
275 break;
277 if (i == 0 && x[0] == 0) {
278 mfree(x);
279 x = mint(0);
280 } else {
281 MLENGTH(x) = i + 1;
282 MSIGN(x) = MSIGN(a);
285 return x;
288 // return both quotient and remainder of a/b
290 void
291 mdivrem(unsigned int **q, unsigned int **r, unsigned int *a, unsigned int *b)
293 int alen, blen, i, n;
294 unsigned int c, *t, *x, *y;
295 unsigned long long jj, kk;
297 if (MZERO(b))
298 stop("divide by zero");
300 if (MZERO(a)) {
301 *q = mint(0);
302 *r = mint(0);
303 return;
306 alen = MLENGTH(a);
307 blen = MLENGTH(b);
309 n = alen - blen;
311 if (n < 0) {
312 *q = mint(0);
313 *r = mcopy(a);
314 return;
317 x = mnew(alen + 1);
319 for (i = 0; i < alen; i++)
320 x[i] = a[i];
322 x[i] = 0;
324 y = mnew(n + 1);
326 t = mnew(blen + 1);
328 kk = (unsigned long long) b[blen - 1] + 1;
330 for (i = 0; i <= n; i++) {
332 y[n - i] = 0;
334 for (;;) {
336 /* estimate the partial quotient */
338 if (little_endian()) {
339 ((unsigned int *) &jj)[0] = x[alen - i - 1];
340 ((unsigned int *) &jj)[1] = x[alen - i - 0];
341 } else {
342 ((unsigned int *) &jj)[1] = x[alen - i - 1];
343 ((unsigned int *) &jj)[0] = x[alen - i - 0];
346 c = (int) (jj / kk);
348 if (c == 0) {
349 if (ge(x + n - i, b, blen)) { /* see note 1 */
350 y[n - i]++;
351 subf(x + n - i, b, blen);
353 break;
356 y[n - i] += c;
357 mulf(t, b, blen, c);
358 subf(x + n - i, t, blen + 1);
362 mfree(t);
364 /* length of quotient */
366 for (i = n; i > 0; i--)
367 if (y[i])
368 break;
370 if (i == 0 && y[0] == 0) {
371 mfree(y);
372 y = mint(0);
373 } else {
374 MLENGTH(y) = i + 1;
375 MSIGN(y) = MSIGN(a) * MSIGN(b);
378 /* length of remainder */
380 for (i = blen - 1; i > 0; i--)
381 if (x[i])
382 break;
384 if (i == 0 && x[0] == 0) {
385 mfree(x);
386 x = mint(0);
387 } else {
388 MLENGTH(x) = i + 1;
389 MSIGN(x) = MSIGN(a);
392 *q = y;
393 *r = x;