1 // Bignum multiplication and division
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);
13 mmul(unsigned int *a
, unsigned int *b
)
18 if (MZERO(a
) || MZERO(b
))
21 if (MLENGTH(a
) == 1 && a
[0] == 1) {
27 if (MLENGTH(b
) == 1 && b
[0] == 1) {
42 for (i
= 0; i
< n
; i
++)
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);
54 /* length of product */
56 for (i
= n
- 1; i
> 0; i
--)
62 MSIGN(x
) = MSIGN(a
) * MSIGN(b
);
68 mdiv(unsigned int *a
, unsigned int *b
)
71 unsigned int c
, *t
, *x
, *y
;
72 unsigned long long jj
, kk
;
75 stop("divide by zero");
90 for (i
= 0; i
< alen
; i
++)
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
++) {
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];
115 ((unsigned int *) &jj
)[1] = x
[alen
- i
- 1];
116 ((unsigned int *) &jj
)[0] = x
[alen
- i
- 0];
119 c
= (unsigned int) (jj
/ kk
);
122 if (ge(x
+ n
- i
, b
, blen
)) { /* see note 1 */
124 subf(x
+ n
- i
, b
, blen
);
131 subf(x
+ n
- i
, t
, blen
+ 1);
139 /* length of quotient */
141 for (i
= n
; i
> 0; i
--)
145 if (i
== 0 && y
[0] == 0) {
150 MSIGN(y
) = MSIGN(a
) * MSIGN(b
);
159 addf(unsigned int *a
, unsigned int *b
, int len
)
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
;
173 subf(unsigned int *a
, unsigned int *b
, int len
)
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
;
186 // 0xffffffff + 0xffffffff * 0xffffffff == 0xffffffff00000000
189 mulf(unsigned int *a
, unsigned int *b
, int len
, unsigned int c
)
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
;
198 a
[i
] = (unsigned int) t
;
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
;
209 stop("divide by zero");
224 for (i
= 0; i
< alen
; i
++)
233 kk
= (unsigned long long) b
[blen
- 1] + 1;
235 for (i
= 0; i
<= n
; i
++) {
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];
247 ((unsigned int *) &jj
)[1] = x
[alen
- i
- 1];
248 ((unsigned int *) &jj
)[0] = x
[alen
- i
- 0];
254 if (ge(x
+ n
- i
, b
, blen
)) { /* see note 1 */
256 subf(x
+ n
- i
, b
, blen
);
263 subf(x
+ n
- i
, t
, blen
+ 1);
271 /* length of remainder */
273 for (i
= blen
- 1; i
> 0; i
--)
277 if (i
== 0 && x
[0] == 0) {
288 // return both quotient and remainder of a/b
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
;
298 stop("divide by zero");
319 for (i
= 0; i
< alen
; i
++)
328 kk
= (unsigned long long) b
[blen
- 1] + 1;
330 for (i
= 0; i
<= n
; i
++) {
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];
342 ((unsigned int *) &jj
)[1] = x
[alen
- i
- 1];
343 ((unsigned int *) &jj
)[0] = x
[alen
- i
- 0];
349 if (ge(x
+ n
- i
, b
, blen
)) { /* see note 1 */
351 subf(x
+ n
- i
, b
, blen
);
358 subf(x
+ n
- i
, t
, blen
+ 1);
364 /* length of quotient */
366 for (i
= n
; i
> 0; i
--)
370 if (i
== 0 && y
[0] == 0) {
375 MSIGN(y
) = MSIGN(a
) * MSIGN(b
);
378 /* length of remainder */
380 for (i
= blen
- 1; i
> 0; i
--)
384 if (i
== 0 && x
[0] == 0) {