• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * *****************************************************************************
3  *
4  * Copyright (c) 2018-2019 Gavin D. Howard and contributors.
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  *   list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright notice,
15  *   this list of conditions and the following disclaimer in the documentation
16  *   and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * *****************************************************************************
31  *
32  * Code for the number type.
33  *
34  */
35 
36 #include <assert.h>
37 #include <ctype.h>
38 #include <stdbool.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include <limits.h>
43 
44 #include <status.h>
45 #include <num.h>
46 #include <vm.h>
47 
48 static BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
49 
bc_num_neg(size_t n,bool neg)50 static ssize_t bc_num_neg(size_t n, bool neg) {
51 	return (((ssize_t) n) ^ -((ssize_t) neg)) + neg;
52 }
53 
bc_num_cmpZero(const BcNum * n)54 ssize_t bc_num_cmpZero(const BcNum *n) {
55 	return bc_num_neg((n)->len != 0, (n)->neg);
56 }
57 
bc_num_int(const BcNum * n)58 static size_t bc_num_int(const BcNum *n) {
59 	return n->len ? n->len - n->rdx : 0;
60 }
61 
bc_num_expand(BcNum * restrict n,size_t req)62 static void bc_num_expand(BcNum *restrict n, size_t req) {
63 	assert(n != NULL);
64 	req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
65 	if (req > n->cap) {
66 		n->num = bc_vm_realloc(n->num, BC_NUM_SIZE(req));
67 		n->cap = req;
68 	}
69 }
70 
bc_num_setToZero(BcNum * restrict n,size_t scale)71 static void bc_num_setToZero(BcNum *restrict n, size_t scale) {
72 	assert(n != NULL);
73 	n->scale = scale;
74 	n->len = n->rdx = 0;
75 	n->neg = false;
76 }
77 
bc_num_zero(BcNum * restrict n)78 static void bc_num_zero(BcNum *restrict n) {
79 	bc_num_setToZero(n, 0);
80 }
81 
bc_num_one(BcNum * restrict n)82 void bc_num_one(BcNum *restrict n) {
83 	bc_num_zero(n);
84 	n->len = 1;
85 	n->num[0] = 1;
86 }
87 
bc_num_clean(BcNum * restrict n)88 static void bc_num_clean(BcNum *restrict n) {
89 	while (BC_NUM_NONZERO(n) && !n->num[n->len - 1]) n->len -= 1;
90 	if (BC_NUM_ZERO(n)) {
91 		n->neg = false;
92 		n->rdx = 0;
93 	}
94 	else if (n->len < n->rdx) n->len = n->rdx;
95 }
96 
bc_num_log10(size_t i)97 static size_t bc_num_log10(size_t i) {
98 	size_t len;
99 	for (len = 1; i; i /= BC_BASE, ++len);
100 	assert(len - 1 <= BC_BASE_DIGS + 1);
101 	return len - 1;
102 }
103 
bc_num_zeroDigits(const BcDig * n)104 static size_t bc_num_zeroDigits(const BcDig *n) {
105 	return BC_BASE_DIGS - bc_num_log10((size_t) *n);
106 }
107 
bc_num_intDigits(const BcNum * n)108 static size_t bc_num_intDigits(const BcNum *n) {
109 	size_t digits = bc_num_int(n) * BC_BASE_DIGS;
110 	if (digits > 0) digits -= bc_num_zeroDigits(n->num + n->len - 1);
111 	return digits;
112 }
113 
bc_num_nonzeroLen(const BcNum * restrict n)114 static size_t bc_num_nonzeroLen(const BcNum *restrict n) {
115 	size_t i, len = n->len;
116 	assert(len == n->rdx);
117 	for (i = len - 1; i < len && !n->num[i]; --i);
118 	assert(i + 1 > 0);
119 	return i + 1;
120 }
121 
bc_num_addDigits(BcDig a,BcDig b,bool * carry)122 static BcDig bc_num_addDigits(BcDig a, BcDig b, bool *carry) {
123 
124 	assert(((BcBigDig) BC_BASE_POW) * 2 == ((BcDig) BC_BASE_POW) * 2);
125 	assert(a < BC_BASE_POW);
126 	assert(b < BC_BASE_POW);
127 
128 	a += b + *carry;
129 	*carry = (a >= BC_BASE_POW);
130 	if (*carry) a -= BC_BASE_POW;
131 
132 	assert(a >= 0);
133 	assert(a < BC_BASE_POW);
134 
135 	return a;
136 }
137 
bc_num_subDigits(BcDig a,BcDig b,bool * carry)138 static BcDig bc_num_subDigits(BcDig a, BcDig b, bool *carry) {
139 
140 	assert(a < BC_BASE_POW);
141 	assert(b < BC_BASE_POW);
142 
143 	b += *carry;
144 	*carry = (a < b);
145 	if (*carry) a += BC_BASE_POW;
146 
147 	assert(a - b >= 0);
148 	assert(a - b < BC_BASE_POW);
149 
150 	return a - b;
151 }
152 
bc_num_addArrays(BcDig * restrict a,const BcDig * restrict b,size_t len)153 static BcStatus bc_num_addArrays(BcDig *restrict a, const BcDig *restrict b,
154                                  size_t len)
155 {
156 	size_t i;
157 	bool carry = false;
158 
159 	for (i = 0; BC_NO_SIG && i < len; ++i)
160 		a[i] = bc_num_addDigits(a[i], b[i], &carry);
161 
162 	for (; BC_NO_SIG && carry; ++i)
163 		a[i] = bc_num_addDigits(a[i], 0, &carry);
164 
165 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
166 }
167 
bc_num_subArrays(BcDig * restrict a,const BcDig * restrict b,size_t len)168 static BcStatus bc_num_subArrays(BcDig *restrict a, const BcDig *restrict b,
169                                  size_t len)
170 {
171 	size_t i;
172 	bool carry = false;
173 
174 	for (i = 0; BC_NO_SIG && i < len; ++i)
175 		a[i] = bc_num_subDigits(a[i], b[i], &carry);
176 
177 	for (; BC_NO_SIG && carry; ++i)
178 		a[i] = bc_num_subDigits(a[i], 0, &carry);
179 
180 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
181 }
182 
bc_num_mulArray(const BcNum * restrict a,BcBigDig b,BcNum * restrict c)183 static BcStatus bc_num_mulArray(const BcNum *restrict a, BcBigDig b,
184                                 BcNum *restrict c)
185 {
186 	size_t i;
187 	BcBigDig carry = 0;
188 
189 	assert(b <= BC_BASE_POW);
190 
191 	if (a->len + 1 > c->cap) bc_num_expand(c, a->len + 1);
192 
193 	memset(c->num, 0, BC_NUM_SIZE(c->cap));
194 
195 	for (i = 0; BC_NO_SIG && i < a->len; ++i) {
196 		BcBigDig in = ((BcBigDig) a->num[i]) * b + carry;
197 		c->num[i] = in % BC_BASE_POW;
198 		carry = in / BC_BASE_POW;
199 	}
200 
201 	if (BC_NO_SIG) {
202 		assert(carry < BC_BASE_POW);
203 		c->num[i] = (BcDig) carry;
204 		c->len = a->len;
205 		c->len += (carry != 0);
206 	}
207 
208 	bc_num_clean(c);
209 
210 	assert(!c->neg || BC_NUM_NONZERO(c));
211 	assert(c->rdx <= c->len || !c->len || BC_SIG);
212 	assert(!c->len || c->num[c->len - 1] || c->rdx == c->len);
213 
214 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
215 }
216 
bc_num_divArray(const BcNum * restrict a,BcBigDig b,BcNum * restrict c,BcBigDig * rem)217 static BcStatus bc_num_divArray(const BcNum *restrict a, BcBigDig b,
218                                 BcNum *restrict c, BcBigDig *rem)
219 {
220 	size_t i;
221 	BcBigDig carry = 0;
222 
223 	assert(c->cap >= a->len);
224 
225 	for (i = a->len - 1; BC_NO_SIG && i < a->len; --i) {
226 		BcBigDig in = ((BcBigDig) a->num[i]) + carry * BC_BASE_POW;
227 		assert(in / b < BC_BASE_POW);
228 		c->num[i] = (BcDig) (in / b);
229 		carry = in % b;
230 	}
231 
232 	c->len = a->len;
233 	bc_num_clean(c);
234 	*rem = carry;
235 
236 	assert(!c->neg || BC_NUM_NONZERO(c));
237 	assert(c->rdx <= c->len || !c->len || BC_SIG);
238 	assert(!c->len || c->num[c->len - 1] || c->rdx == c->len);
239 
240 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
241 }
242 
bc_num_compare(const BcDig * restrict a,const BcDig * restrict b,size_t len)243 static ssize_t bc_num_compare(const BcDig *restrict a, const BcDig *restrict b,
244                               size_t len)
245 {
246 	size_t i;
247 	BcDig c = 0;
248 	for (i = len - 1; BC_NO_SIG && i < len && !(c = a[i] - b[i]); --i);
249 	return BC_SIG ? BC_NUM_CMP_SIGNAL_VAL : bc_num_neg(i + 1, c < 0);
250 }
251 
bc_num_cmp(const BcNum * a,const BcNum * b)252 ssize_t bc_num_cmp(const BcNum *a, const BcNum *b) {
253 
254 	size_t i, min, a_int, b_int, diff;
255 	BcDig *max_num, *min_num;
256 	bool a_max, neg = false;
257 	ssize_t cmp;
258 
259 	assert(a != NULL && b != NULL);
260 
261 	if (a == b) return 0;
262 	if (BC_NUM_ZERO(a)) return bc_num_neg(b->len != 0, !b->neg);
263 	if (BC_NUM_ZERO(b)) return bc_num_cmpZero(a);
264 	if (a->neg) {
265 		if (b->neg) neg = true;
266 		else return -1;
267 	}
268 	else if (b->neg) return 1;
269 
270 	a_int = bc_num_int(a);
271 	b_int = bc_num_int(b);
272 	a_int -= b_int;
273 	a_max = (a->rdx > b->rdx);
274 
275 	if (a_int) return neg ? -((ssize_t) a_int) : (ssize_t) a_int;
276 
277 	if (a_max) {
278 		min = b->rdx;
279 		diff = a->rdx - b->rdx;
280 		max_num = a->num + diff;
281 		min_num = b->num;
282 	}
283 	else {
284 		min = a->rdx;
285 		diff = b->rdx - a->rdx;
286 		max_num = b->num + diff;
287 		min_num = a->num;
288 	}
289 
290 	cmp = bc_num_compare(max_num, min_num, b_int + min);
291 
292 #if BC_ENABLE_SIGNALS
293 	if (BC_NUM_CMP_SIGNAL(cmp)) return cmp;
294 #endif // BC_ENABLE_SIGNALS
295 
296 	if (cmp) return bc_num_neg((size_t) cmp, !a_max == !neg);
297 
298 	for (max_num -= diff, i = diff - 1; BC_NO_SIG && i < diff; --i) {
299 		if (max_num[i]) return bc_num_neg(1, !a_max == !neg);
300 	}
301 
302 	return BC_SIG ? BC_NUM_CMP_SIGNAL_VAL : 0;
303 }
304 
bc_num_truncate(BcNum * restrict n,size_t places)305 void bc_num_truncate(BcNum *restrict n, size_t places) {
306 
307 	size_t places_rdx;
308 
309 	if (!places) return;
310 
311 	places_rdx = n->rdx ? n->rdx - BC_NUM_RDX(n->scale - places) : 0;
312 	assert(places <= n->scale && (BC_NUM_ZERO(n) || places_rdx <= n->len));
313 
314 	n->scale -= places;
315 	n->rdx -= places_rdx;
316 
317 	if (BC_NUM_NONZERO(n)) {
318 
319 		size_t pow;
320 
321 		pow = n->scale % BC_BASE_DIGS;
322 		pow = pow ? BC_BASE_DIGS - pow : 0;
323 		pow = bc_num_pow10[pow];
324 
325 		n->len -= places_rdx;
326 		memmove(n->num, n->num + places_rdx, BC_NUM_SIZE(n->len));
327 
328 		// Clear the lower part of the last digit.
329 		if (BC_NUM_NONZERO(n)) n->num[0] -= n->num[0] % (BcDig) pow;
330 
331 		bc_num_clean(n);
332 	}
333 }
334 
bc_num_extend(BcNum * restrict n,size_t places)335 static void bc_num_extend(BcNum *restrict n, size_t places) {
336 
337 	size_t places_rdx;
338 
339 	if (!places) return;
340 	if (BC_NUM_ZERO(n)) {
341 		n->scale += places;
342 		return;
343 	}
344 
345 	places_rdx = BC_NUM_RDX(places + n->scale) - n->rdx;
346 
347 	if (places_rdx) {
348 		bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));
349 		memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len));
350 		memset(n->num, 0, BC_NUM_SIZE(places_rdx));
351 	}
352 
353 	n->rdx += places_rdx;
354 	n->scale += places;
355 	n->len += places_rdx;
356 
357 	assert(n->rdx == BC_NUM_RDX(n->scale));
358 }
359 
bc_num_retireMul(BcNum * restrict n,size_t scale,bool neg1,bool neg2)360 static void bc_num_retireMul(BcNum *restrict n, size_t scale,
361                              bool neg1, bool neg2)
362 {
363 	if (n->scale < scale) bc_num_extend(n, scale - n->scale);
364 	else bc_num_truncate(n, n->scale - scale);
365 
366 	bc_num_clean(n);
367 	if (BC_NUM_NONZERO(n)) n->neg = (!neg1 != !neg2);
368 }
369 
bc_num_split(const BcNum * restrict n,size_t idx,BcNum * restrict a,BcNum * restrict b)370 static void bc_num_split(const BcNum *restrict n, size_t idx,
371                          BcNum *restrict a, BcNum *restrict b)
372 {
373 	assert(BC_NUM_ZERO(a));
374 	assert(BC_NUM_ZERO(b));
375 
376 	if (idx < n->len) {
377 
378 		b->len = n->len - idx;
379 		a->len = idx;
380 		a->scale = a->rdx = b->scale = b->rdx = 0;
381 
382 		assert(a->cap >= a->len);
383 		assert(b->cap >= b->len);
384 
385 		memcpy(b->num, n->num + idx, BC_NUM_SIZE(b->len));
386 		memcpy(a->num, n->num, BC_NUM_SIZE(idx));
387 
388 		bc_num_clean(b);
389 	}
390 	else bc_num_copy(a, n);
391 
392 	bc_num_clean(a);
393 }
394 
bc_num_shiftZero(BcNum * restrict n)395 static size_t bc_num_shiftZero(BcNum *restrict n) {
396 
397 	size_t i;
398 
399 	assert(!n->rdx || BC_NUM_ZERO(n));
400 
401 	for (i = 0; i < n->len && !n->num[i]; ++i);
402 
403 	n->len -= i;
404 	n->num += i;
405 
406 	return i;
407 }
408 
bc_num_unshiftZero(BcNum * restrict n,size_t places_rdx)409 static void bc_num_unshiftZero(BcNum *restrict n, size_t places_rdx) {
410 	n->len += places_rdx;
411 	n->num -= places_rdx;
412 }
413 
bc_num_shift(BcNum * restrict n,BcBigDig dig)414 static BcStatus bc_num_shift(BcNum *restrict n, BcBigDig dig) {
415 
416 	size_t i, len = n->len;
417 	BcBigDig carry = 0, pow;
418 	BcDig *ptr = n->num;
419 
420 	assert(dig < BC_BASE_DIGS);
421 
422 	pow = bc_num_pow10[dig];
423 	dig = bc_num_pow10[BC_BASE_DIGS - dig];
424 
425 	for (i = len - 1; BC_NO_SIG && i < len; --i) {
426 		BcBigDig in, temp;
427 		in = ((BcBigDig) ptr[i]);
428 		temp = carry * dig;
429 		carry = in % pow;
430 		ptr[i] = ((BcDig) (in / pow)) + (BcDig) temp;
431 	}
432 
433 	assert(!carry);
434 
435 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
436 }
437 
bc_num_shiftLeft(BcNum * restrict n,size_t places)438 static BcStatus bc_num_shiftLeft(BcNum *restrict n, size_t places) {
439 
440 	BcStatus s = BC_STATUS_SUCCESS;
441 	BcBigDig dig;
442 	size_t places_rdx;
443 	bool shift;
444 
445 	if (!places) return s;
446 	if (places > n->scale) {
447 		size_t size = bc_vm_growSize(BC_NUM_RDX(places - n->scale), n->len);
448 		if (size > SIZE_MAX - 1) return bc_vm_err(BC_ERROR_MATH_OVERFLOW);
449 	}
450 	if (BC_NUM_ZERO(n)) {
451 		if (n->scale >= places) n->scale -= places;
452 		else n->scale = 0;
453 		return s;
454 	}
455 
456 	dig = (BcBigDig) (places % BC_BASE_DIGS);
457 	shift = (dig != 0);
458 	places_rdx = BC_NUM_RDX(places);
459 
460 	if (n->scale) {
461 
462 		if (n->rdx >= places_rdx) {
463 
464 			size_t mod = n->scale % BC_BASE_DIGS, revdig;
465 
466 			mod = mod ? mod : BC_BASE_DIGS;
467 			revdig = dig ? BC_BASE_DIGS - dig : 0;
468 
469 			if (mod + revdig > BC_BASE_DIGS) places_rdx = 1;
470 			else places_rdx = 0;
471 		}
472 		else places_rdx -= n->rdx;
473 	}
474 
475 	if (places_rdx) {
476 		bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));
477 		memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len));
478 		memset(n->num, 0, BC_NUM_SIZE(places_rdx));
479 		n->len += places_rdx;
480 	}
481 
482 	if (places > n->scale) n->scale = n->rdx = 0;
483 	else {
484 		n->scale -= places;
485 		n->rdx = BC_NUM_RDX(n->scale);
486 	}
487 
488 	if (shift) s = bc_num_shift(n, BC_BASE_DIGS - dig);
489 
490 	bc_num_clean(n);
491 
492 	return BC_SIG && !s ? BC_STATUS_SIGNAL : s;
493 }
494 
bc_num_shiftRight(BcNum * restrict n,size_t places)495 static BcStatus bc_num_shiftRight(BcNum *restrict n, size_t places) {
496 
497 	BcStatus s = BC_STATUS_SUCCESS;
498 	BcBigDig dig;
499 	size_t places_rdx, scale, scale_mod, int_len, expand;
500 	bool shift;
501 
502 	if (!places) return s;
503 	if (BC_NUM_ZERO(n)) {
504 		n->scale += places;
505 		bc_num_expand(n, BC_NUM_RDX(n->scale));
506 		return s;
507 	}
508 
509 	dig = (BcBigDig) (places % BC_BASE_DIGS);
510 	shift = (dig != 0);
511 	scale = n->scale;
512 	scale_mod = scale % BC_BASE_DIGS;
513 	scale_mod = scale_mod ? scale_mod : BC_BASE_DIGS;
514 	int_len = bc_num_int(n);
515 	places_rdx = BC_NUM_RDX(places);
516 
517 	if (scale_mod + dig > BC_BASE_DIGS) {
518 		expand = places_rdx - 1;
519 		places_rdx = 1;
520 	}
521 	else {
522 		expand = places_rdx;
523 		places_rdx = 0;
524 	}
525 
526 	if (expand > int_len) expand -= int_len;
527 	else expand = 0;
528 
529 	bc_num_extend(n, places_rdx * BC_BASE_DIGS);
530 	bc_num_expand(n, bc_vm_growSize(expand, n->len));
531 	memset(n->num + n->len, 0, BC_NUM_SIZE(expand));
532 	n->len += expand;
533 	n->scale = n->rdx = 0;
534 
535 	if (shift) s = bc_num_shift(n, dig);
536 
537 	n->scale = scale + places;
538 	n->rdx = BC_NUM_RDX(n->scale);
539 
540 	bc_num_clean(n);
541 
542 	assert(n->rdx <= n->len && n->len <= n->cap);
543 	assert(n->rdx == BC_NUM_RDX(n->scale));
544 
545 	return BC_SIG && !s ? BC_STATUS_SIGNAL : s;
546 }
547 
bc_num_inv(BcNum * a,BcNum * b,size_t scale)548 static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale) {
549 
550 	BcNum one;
551 	BcDig num[2];
552 
553 	assert(BC_NUM_NONZERO(a));
554 
555 	bc_num_setup(&one, num, sizeof(num) / sizeof(BcDig));
556 	bc_num_one(&one);
557 
558 	return bc_num_div(&one, a, b, scale);
559 }
560 
561 #if BC_ENABLE_EXTRA_MATH
bc_num_intop(const BcNum * a,const BcNum * b,BcNum * restrict c,BcBigDig * v)562 static BcStatus bc_num_intop(const BcNum *a, const BcNum *b, BcNum *restrict c,
563                              BcBigDig *v)
564 {
565 	if (BC_ERR(b->rdx)) return bc_vm_err(BC_ERROR_MATH_NON_INTEGER);
566 	bc_num_copy(c, a);
567 	return bc_num_bigdig(b, v);
568 }
569 #endif // BC_ENABLE_EXTRA_MATH
570 
bc_num_as(BcNum * a,BcNum * b,BcNum * restrict c,size_t sub)571 static BcStatus bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) {
572 
573 	BcDig *ptr_c, *ptr_l, *ptr_r;
574 	size_t i, min_rdx, max_rdx, diff, a_int, b_int, min_len, max_len, max_int;
575 	size_t len_l, len_r;
576 	bool b_neg, do_sub, do_rev_sub, carry;
577 
578 	// Because this function doesn't need to use scale (per the bc spec),
579 	// I am hijacking it to say whether it's doing an add or a subtract.
580 	// Convert substraction to addition of negative second operand.
581 
582 	if (BC_NUM_ZERO(b)) {
583 		bc_num_copy(c, a);
584 		return BC_STATUS_SUCCESS;
585 	}
586 	if (BC_NUM_ZERO(a)) {
587 		bc_num_copy(c, b);
588 		c->neg = (b->neg != sub);
589 		return BC_STATUS_SUCCESS;
590 	}
591 
592 	b_neg = (b->neg != sub);
593 	do_sub = (a->neg != b_neg);
594 
595 	a_int = bc_num_int(a);
596 	b_int = bc_num_int(b);
597 	max_int = BC_MAX(a_int, b_int);
598 
599 	min_rdx = BC_MIN(a->rdx, b->rdx);
600 	max_rdx = BC_MAX(a->rdx, b->rdx);
601 	diff = max_rdx - min_rdx;
602 
603 	max_len = max_int + max_rdx;
604 
605 	if (do_sub) {
606 		if (a_int != b_int) do_rev_sub = (a_int < b_int);
607 		else if (a->rdx > b->rdx)
608 			do_rev_sub = (bc_num_compare(a->num + diff, b->num, b->len) < 0);
609 		else
610 			do_rev_sub = (bc_num_compare(a->num, b->num + diff, a->len) <= 0);
611 	}
612 	else {
613 		max_len += 1;
614 		do_rev_sub = false;
615 	}
616 
617 	assert(max_len <= c->cap);
618 
619 	if (do_rev_sub) {
620 		ptr_l = b->num;
621 		ptr_r = a->num;
622 		len_l = b->len;
623 		len_r = a->len;
624 	}
625 	else {
626 		ptr_l = a->num;
627 		ptr_r = b->num;
628 		len_l = a->len;
629 		len_r = b->len;
630 	}
631 
632 	ptr_c = c->num;
633 	carry = false;
634 
635 	if (diff) {
636 
637 		if ((a->rdx > b->rdx) != do_rev_sub) {
638 			memcpy(ptr_c, ptr_l, BC_NUM_SIZE(diff));
639 			ptr_l += diff;
640 			len_l -= diff;
641 		}
642 		else {
643 
644 			if (do_sub) {
645 
646 				for (i = 0; BC_NO_SIG && i < diff; i++)
647 					ptr_c[i] = bc_num_subDigits(0, ptr_r[i], &carry);
648 
649 				if (BC_SIG) return BC_STATUS_SIGNAL;
650 			}
651 			else memcpy(ptr_c, ptr_r, BC_NUM_SIZE(diff));
652 
653 			ptr_r += diff;
654 			len_r -= diff;
655 		}
656 
657 		ptr_c += diff;
658 	}
659 
660 	min_len = BC_MIN(len_l, len_r);
661 
662 	if (do_sub) {
663 		for (i = 0; BC_NO_SIG && i < min_len; ++i)
664 			ptr_c[i] = bc_num_subDigits(ptr_l[i], ptr_r[i], &carry);
665 		for (; BC_NO_SIG && i < len_l; ++i)
666 			ptr_c[i] = bc_num_subDigits(ptr_l[i], 0, &carry);
667 		for (; BC_NO_SIG && i < len_r; ++i)
668 			ptr_c[i] = bc_num_subDigits(0, ptr_r[i], &carry);
669 		for (; BC_NO_SIG && i < max_len - diff; ++i)
670 			ptr_c[i] = bc_num_subDigits(0, 0, &carry);
671 	}
672 	else {
673 		for (i = 0; BC_NO_SIG && i < min_len; ++i)
674 			ptr_c[i] = bc_num_addDigits(ptr_l[i], ptr_r[i], &carry);
675 		for (; BC_NO_SIG && i < len_l; ++i)
676 			ptr_c[i] = bc_num_addDigits(ptr_l[i], 0, &carry);
677 		for (; BC_NO_SIG && i < len_r; ++i)
678 			ptr_c[i] = bc_num_addDigits(0, ptr_r[i], &carry);
679 		for (; BC_NO_SIG && i < max_len - diff; ++i)
680 			ptr_c[i] = bc_num_addDigits(0, 0, &carry);
681 	}
682 
683 	if (BC_NO_SIG) {
684 
685 		assert(carry == false);
686 
687 		// The result has the same sign as a, unless the operation was a
688 		// reverse subtraction (b - a).
689 		c->neg = (a->neg != do_rev_sub);
690 		c->len = max_len;
691 		c->rdx = max_rdx;
692 		c->scale = BC_MAX(a->scale, b->scale);
693 
694 		bc_num_clean(c);
695 	}
696 
697 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
698 }
699 
bc_num_m_simp(const BcNum * a,const BcNum * b,BcNum * restrict c)700 static BcStatus bc_num_m_simp(const BcNum *a, const BcNum *b, BcNum *restrict c)
701 {
702 	size_t i, alen = a->len, blen = b->len, clen;
703 	BcDig *ptr_a = a->num, *ptr_b = b->num, *ptr_c;
704 	BcBigDig sum = 0, carry = 0;
705 
706 	assert(sizeof(sum) >= sizeof(BcDig) * 2);
707 	assert(!a->rdx && !b->rdx);
708 
709 	clen = bc_vm_growSize(alen, blen);
710 	bc_num_expand(c, bc_vm_growSize(clen, 1));
711 
712 	ptr_c = c->num;
713 	memset(ptr_c, 0, BC_NUM_SIZE(c->cap));
714 
715 	for (i = 0; BC_NO_SIG && i < clen; ++i) {
716 
717 		ssize_t sidx = (ssize_t) (i - blen + 1);
718 		size_t j = (size_t) BC_MAX(0, sidx), k = BC_MIN(i, blen - 1);
719 
720 		for (; BC_NO_SIG && j < alen && k < blen; ++j, --k) {
721 
722 			sum += ((BcBigDig) ptr_a[j]) * ((BcBigDig) ptr_b[k]);
723 
724 			if (sum >= ((BcBigDig) BC_BASE_POW) * BC_BASE_POW) {
725 				carry += sum / BC_BASE_POW;
726 				sum %= BC_BASE_POW;
727 			}
728 		}
729 
730 		if (sum >= BC_BASE_POW) {
731 			carry += sum / BC_BASE_POW;
732 			sum %= BC_BASE_POW;
733 		}
734 
735 		ptr_c[i] = (BcDig) sum;
736 		assert(ptr_c[i] < BC_BASE_POW);
737 		sum = carry;
738 		carry = 0;
739 	}
740 
741 	if (sum) {
742 		assert(sum < BC_BASE_POW);
743 		ptr_c[clen] = (BcDig) sum;
744 		clen += 1;
745 	}
746 
747 	c->len = clen;
748 
749 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
750 }
751 
bc_num_shiftAddSub(BcNum * restrict n,const BcNum * restrict a,size_t shift,BcNumShiftAddOp op)752 static BcStatus bc_num_shiftAddSub(BcNum *restrict n, const BcNum *restrict a,
753                                    size_t shift, BcNumShiftAddOp op)
754 {
755 	assert(n->len >= shift + a->len);
756 	assert(!n->rdx && !a->rdx);
757 	return op(n->num + shift, a->num, a->len);
758 }
759 
bc_num_k(BcNum * a,BcNum * b,BcNum * restrict c)760 static BcStatus bc_num_k(BcNum *a, BcNum *b, BcNum *restrict c) {
761 
762 	BcStatus s;
763 	size_t max, max2, total;
764 	BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
765 	BcDig *digs, *dig_ptr;
766 	BcNumShiftAddOp op;
767 	bool aone = BC_NUM_ONE(a);
768 
769 	assert(BC_NUM_ZERO(c));
770 
771 	// This is here because the function is recursive.
772 	if (BC_SIG) return BC_STATUS_SIGNAL;
773 	if (BC_NUM_ZERO(a) || BC_NUM_ZERO(b)) return BC_STATUS_SUCCESS;
774 	if (aone || BC_NUM_ONE(b)) {
775 		bc_num_copy(c, aone ? b : a);
776 		if ((aone && a->neg) || b->neg) c->neg = !c->neg;
777 		return BC_STATUS_SUCCESS;
778 	}
779 	if (a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN)
780 		return bc_num_m_simp(a, b, c);
781 
782 	max = BC_MAX(a->len, b->len);
783 	max = BC_MAX(max, BC_NUM_DEF_SIZE);
784 	max2 = (max + 1) / 2;
785 
786 	total = bc_vm_arraySize(BC_NUM_KARATSUBA_ALLOCS, max);
787 	digs = dig_ptr = bc_vm_malloc(BC_NUM_SIZE(total));
788 
789 	bc_num_setup(&l1, dig_ptr, max);
790 	dig_ptr += max;
791 	bc_num_setup(&h1, dig_ptr, max);
792 	dig_ptr += max;
793 	bc_num_setup(&l2, dig_ptr, max);
794 	dig_ptr += max;
795 	bc_num_setup(&h2, dig_ptr, max);
796 	dig_ptr += max;
797 	bc_num_setup(&m1, dig_ptr, max);
798 	dig_ptr += max;
799 	bc_num_setup(&m2, dig_ptr, max);
800 	max = bc_vm_growSize(max, 1);
801 	bc_num_init(&z0, max);
802 	bc_num_init(&z1, max);
803 	bc_num_init(&z2, max);
804 	max = bc_vm_growSize(max, max) + 1;
805 	bc_num_init(&temp, max);
806 
807 	bc_num_split(a, max2, &l1, &h1);
808 	bc_num_split(b, max2, &l2, &h2);
809 
810 	bc_num_expand(c, max);
811 	c->len = max;
812 	memset(c->num, 0, BC_NUM_SIZE(c->len));
813 
814 	s = bc_num_sub(&h1, &l1, &m1, 0);
815 	if (BC_ERR(s)) goto err;
816 	s = bc_num_sub(&l2, &h2, &m2, 0);
817 	if (BC_ERR(s)) goto err;
818 
819 	if (BC_NUM_NONZERO(&h1) && BC_NUM_NONZERO(&h2)) {
820 
821 		s = bc_num_m(&h1, &h2, &z2, 0);
822 		if (BC_ERR(s)) goto err;
823 		bc_num_clean(&z2);
824 
825 		s = bc_num_shiftAddSub(c, &z2, max2 * 2, bc_num_addArrays);
826 		if (BC_ERR(s)) goto err;
827 		s = bc_num_shiftAddSub(c, &z2, max2, bc_num_addArrays);
828 		if (BC_ERR(s)) goto err;
829 	}
830 
831 	if (BC_NUM_NONZERO(&l1) && BC_NUM_NONZERO(&l2)) {
832 
833 		s = bc_num_m(&l1, &l2, &z0, 0);
834 		if (BC_ERR(s)) goto err;
835 		bc_num_clean(&z0);
836 
837 		s = bc_num_shiftAddSub(c, &z0, max2, bc_num_addArrays);
838 		if (BC_ERR(s)) goto err;
839 		s = bc_num_shiftAddSub(c, &z0, 0, bc_num_addArrays);
840 		if (BC_ERR(s)) goto err;
841 	}
842 
843 	if (BC_NUM_NONZERO(&m1) && BC_NUM_NONZERO(&m2)) {
844 
845 		s = bc_num_m(&m1, &m2, &z1, 0);
846 		if (BC_ERR(s)) goto err;
847 		bc_num_clean(&z1);
848 
849 		op = (m1.neg != m2.neg) ? bc_num_subArrays : bc_num_addArrays;
850 		s = bc_num_shiftAddSub(c, &z1, max2, op);
851 		if (BC_ERR(s)) goto err;
852 	}
853 
854 err:
855 	free(digs);
856 	bc_num_free(&temp);
857 	bc_num_free(&z2);
858 	bc_num_free(&z1);
859 	bc_num_free(&z0);
860 	return s;
861 }
862 
bc_num_m(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)863 static BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
864 
865 	BcStatus s;
866 	BcNum cpa, cpb;
867 	size_t ascale, bscale, ardx, brdx, azero = 0, bzero = 0, zero, len, rscale;
868 
869 	bc_num_zero(c);
870 	ascale = a->scale;
871 	bscale = b->scale;
872 	scale = BC_MAX(scale, ascale);
873 	scale = BC_MAX(scale, bscale);
874 
875 	rscale = ascale + bscale;
876 	scale = BC_MIN(rscale, scale);
877 
878 	if ((a->len == 1 || b->len == 1) && !a->rdx && !b->rdx) {
879 
880 		BcNum *operand;
881 		BcBigDig dig;
882 
883 		if (a->len == 1) {
884 			dig = (BcBigDig) a->num[0];
885 			operand = b;
886 		}
887 		else {
888 			dig = (BcBigDig) b->num[0];
889 			operand = a;
890 		}
891 
892 		s = bc_num_mulArray(operand, dig, c);
893 		if (BC_ERROR_SIGNAL_ONLY(s)) return s;
894 
895 		if (BC_NUM_NONZERO(c)) c->neg = (a->neg != b->neg);
896 
897 		return s;
898 	}
899 
900 	bc_num_init(&cpa, a->len + a->rdx);
901 	bc_num_init(&cpb, b->len + b->rdx);
902 	bc_num_copy(&cpa, a);
903 	bc_num_copy(&cpb, b);
904 
905 	cpa.neg = cpb.neg = false;
906 
907 	ardx = cpa.rdx * BC_BASE_DIGS;
908 	s = bc_num_shiftLeft(&cpa, ardx);
909 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
910 	bc_num_clean(&cpa);
911 	azero = bc_num_shiftZero(&cpa);
912 
913 	brdx = cpb.rdx * BC_BASE_DIGS;
914 	s = bc_num_shiftLeft(&cpb, brdx);
915 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
916 	bzero = bc_num_shiftZero(&cpb);
917 	bc_num_clean(&cpb);
918 
919 	s = bc_num_k(&cpa, &cpb, c);
920 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
921 
922 	zero = bc_vm_growSize(azero, bzero);
923 	len = bc_vm_growSize(c->len, zero);
924 
925 	bc_num_expand(c, len);
926 	s = bc_num_shiftLeft(c, (len - c->len) * BC_BASE_DIGS);
927 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
928 	s = bc_num_shiftRight(c, ardx + brdx);
929 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
930 
931 	bc_num_retireMul(c, scale, a->neg, b->neg);
932 
933 err:
934 	bc_num_unshiftZero(&cpb, bzero);
935 	bc_num_free(&cpb);
936 	bc_num_unshiftZero(&cpa, azero);
937 	bc_num_free(&cpa);
938 	return s;
939 }
940 
bc_num_nonZeroDig(BcDig * restrict a,size_t len)941 static bool bc_num_nonZeroDig(BcDig *restrict a, size_t len) {
942 	size_t i;
943 	bool nonzero = false;
944 	for (i = len - 1; !nonzero && i < len; --i) nonzero = (a[i] != 0);
945 	return nonzero;
946 }
947 
bc_num_divCmp(const BcDig * a,const BcNum * b,size_t len)948 static ssize_t bc_num_divCmp(const BcDig *a, const BcNum *b, size_t len) {
949 
950 	ssize_t cmp;
951 
952 	if (b->len > len && a[len]) cmp = bc_num_compare(a, b->num, len + 1);
953 	else if (b->len <= len) {
954 		if (a[len]) cmp = 1;
955 		else cmp = bc_num_compare(a, b->num, len);
956 	}
957 	else cmp = -1;
958 
959 	return cmp;
960 }
961 
bc_num_divExtend(BcNum * restrict a,BcNum * restrict b,BcBigDig divisor)962 static BcStatus bc_num_divExtend(BcNum *restrict a, BcNum *restrict b,
963                                  BcBigDig divisor)
964 {
965 	BcStatus s;
966 	size_t pow;
967 
968 	pow = BC_BASE_DIGS - bc_num_log10((size_t) divisor);
969 
970 	s = bc_num_shiftLeft(a, pow);
971 	if (BC_ERROR_SIGNAL_ONLY(s)) return s;
972 
973 	return bc_num_shiftLeft(b, pow);
974 }
975 
bc_num_d_long(BcNum * restrict a,BcNum * restrict b,BcNum * restrict c,size_t scale)976 static BcStatus bc_num_d_long(BcNum *restrict a, BcNum *restrict b,
977                               BcNum *restrict c, size_t scale)
978 {
979 	BcStatus s = BC_STATUS_SUCCESS;
980 	BcBigDig divisor;
981 	size_t len, end, i, rdx;
982 	BcNum cpb;
983 	bool nonzero = false;
984 
985 	assert(b->len < a->len);
986 	len = b->len;
987 	end = a->len - len;
988 	assert(len >= 1);
989 
990 	bc_num_expand(c, a->len);
991 	memset(c->num, 0, c->cap * sizeof(BcDig));
992 
993 	c->rdx = a->rdx;
994 	c->scale = a->scale;
995 	c->len = a->len;
996 
997 	divisor = (BcBigDig) b->num[len - 1];
998 
999 	if (len > 1 && bc_num_nonZeroDig(b->num, len - 1)) {
1000 
1001 		nonzero = (divisor > 1 << ((10 * BC_BASE_DIGS) / 6 + 1));
1002 
1003 		if (!nonzero) {
1004 
1005 			s = bc_num_divExtend(a, b, divisor);
1006 			if (BC_ERROR_SIGNAL_ONLY(s)) return s;
1007 
1008 			len = BC_MAX(a->len, b->len);
1009 			bc_num_expand(a, len + 1);
1010 
1011 			if (len + 1 > a->len) a->len = len + 1;
1012 
1013 			len = b->len;
1014 			end = a->len - len;
1015 			divisor = (BcBigDig) b->num[len - 1];
1016 
1017 			nonzero = bc_num_nonZeroDig(b->num, len - 1);
1018 		}
1019 	}
1020 
1021 	divisor += nonzero;
1022 
1023 	bc_num_expand(c, a->len);
1024 	memset(c->num, 0, BC_NUM_SIZE(c->cap));
1025 
1026 	assert(c->scale >= scale);
1027 	rdx = c->rdx - BC_NUM_RDX(scale);
1028 
1029 	bc_num_init(&cpb, len + 1);
1030 
1031 	i = end - 1;
1032 
1033 	for (; BC_NO_SIG && i < end && i >= rdx && BC_NUM_NONZERO(a); --i) {
1034 
1035 		ssize_t cmp;
1036 		BcDig *n;
1037 		BcBigDig q, result;
1038 
1039 		n = a->num + i;
1040 		assert(n >= a->num);
1041 		result = q = 0;
1042 
1043 		cmp = bc_num_divCmp(n, b, len);
1044 
1045 #if BC_ENABLE_SIGNALS
1046 		if (BC_NUM_CMP_SIGNAL(cmp)) goto err;
1047 #endif // BC_ENABLE_SIGNALS
1048 
1049 		while (cmp >= 0) {
1050 
1051 			BcBigDig n1, dividend;
1052 
1053 			n1 = (BcBigDig) n[len];
1054 			dividend = n1 * BC_BASE_POW + (BcBigDig) n[len - 1];
1055 			q = (dividend / divisor);
1056 
1057 			if (q <= 1) {
1058 				q = 1;
1059 				s = bc_num_subArrays(n, b->num, len);
1060 				if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1061 			}
1062 			else {
1063 
1064 				assert(q <= BC_BASE_POW);
1065 
1066 				s = bc_num_mulArray(b, (BcBigDig) q, &cpb);
1067 				if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1068 
1069 				s = bc_num_subArrays(n, cpb.num, cpb.len);
1070 				if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1071 			}
1072 
1073 			result += q;
1074 			assert(result <= BC_BASE_POW);
1075 
1076 			if (nonzero) {
1077 				cmp = bc_num_divCmp(n, b, len);
1078 #if BC_ENABLE_SIGNALS
1079 				if (BC_NUM_CMP_SIGNAL(cmp)) goto err;
1080 #endif // BC_ENABLE_SIGNALS
1081 			}
1082 			else cmp = -1;
1083 		}
1084 
1085 		assert(result < BC_BASE_POW);
1086 
1087 		c->num[i] = (BcDig) result;
1088 	}
1089 
1090 err:
1091 	if (BC_NO_ERR(!s) && BC_SIG) s = BC_STATUS_SIGNAL;
1092 	bc_num_free(&cpb);
1093 	return s;
1094 }
1095 
bc_num_d(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)1096 static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1097 
1098 	BcStatus s = BC_STATUS_SUCCESS;
1099 	size_t len;
1100 	BcNum cpa, cpb;
1101 
1102 	if (BC_NUM_ZERO(b)) return bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
1103 	if (BC_NUM_ZERO(a)) {
1104 		bc_num_setToZero(c, scale);
1105 		return BC_STATUS_SUCCESS;
1106 	}
1107 	if (BC_NUM_ONE(b)) {
1108 		bc_num_copy(c, a);
1109 		bc_num_retireMul(c, scale, a->neg, b->neg);
1110 		return BC_STATUS_SUCCESS;
1111 	}
1112 	if (!a->rdx && !b->rdx && b->len == 1 && !scale) {
1113 		BcBigDig rem;
1114 		s = bc_num_divArray(a, (BcBigDig) b->num[0], c, &rem);
1115 		bc_num_retireMul(c, scale, a->neg, b->neg);
1116 		return s;
1117 	}
1118 
1119 	len = bc_num_mulReq(a, b, scale);
1120 	bc_num_init(&cpa, len);
1121 	bc_num_copy(&cpa, a);
1122 	bc_num_createCopy(&cpb, b);
1123 
1124 	len = b->len;
1125 
1126 	if (len > cpa.len) {
1127 		bc_num_expand(&cpa, bc_vm_growSize(len, 2));
1128 		bc_num_extend(&cpa, (len - cpa.len) * BC_BASE_DIGS);
1129 	}
1130 
1131 	cpa.scale = cpa.rdx * BC_BASE_DIGS;
1132 
1133 	bc_num_extend(&cpa, b->scale);
1134 	cpa.rdx -= BC_NUM_RDX(b->scale);
1135 	cpa.scale = cpa.rdx * BC_BASE_DIGS;
1136 
1137 	if (scale > cpa.scale) {
1138 		bc_num_extend(&cpa, scale);
1139 		cpa.scale = cpa.rdx * BC_BASE_DIGS;
1140 	}
1141 
1142 	if (cpa.cap == cpa.len) bc_num_expand(&cpa, bc_vm_growSize(cpa.len, 1));
1143 
1144 	// We want an extra zero in front to make things simpler.
1145 	cpa.num[cpa.len++] = 0;
1146 
1147 	if (cpa.rdx == cpa.len) cpa.len = bc_num_nonzeroLen(&cpa);
1148 	if (cpb.rdx == cpb.len) cpb.len = bc_num_nonzeroLen(&cpb);
1149 	cpb.scale = cpb.rdx = 0;
1150 
1151 	s = bc_num_d_long(&cpa, &cpb, c, scale);
1152 
1153 	if (BC_NO_ERR(!s)) {
1154 		if (BC_SIG) s = BC_STATUS_SIGNAL;
1155 		else bc_num_retireMul(c, scale, a->neg, b->neg);
1156 	}
1157 
1158 	bc_num_free(&cpb);
1159 	bc_num_free(&cpa);
1160 
1161 	return s;
1162 }
1163 
bc_num_r(BcNum * a,BcNum * b,BcNum * restrict c,BcNum * restrict d,size_t scale,size_t ts)1164 static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
1165                          BcNum *restrict d, size_t scale, size_t ts)
1166 {
1167 	BcStatus s;
1168 	BcNum temp;
1169 	bool neg;
1170 
1171 	if (BC_NUM_ZERO(b)) return bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
1172 	if (BC_NUM_ZERO(a)) {
1173 		bc_num_setToZero(c, ts);
1174 		bc_num_setToZero(d, ts);
1175 		return BC_STATUS_SUCCESS;
1176 	}
1177 
1178 	bc_num_init(&temp, d->cap);
1179 	s = bc_num_d(a, b, c, scale);
1180 	assert(!s || s == BC_STATUS_SIGNAL);
1181 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1182 
1183 	if (scale) scale = ts + 1;
1184 
1185 	s = bc_num_m(c, b, &temp, scale);
1186 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1187 	s = bc_num_sub(a, &temp, d, scale);
1188 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1189 
1190 	if (ts > d->scale && BC_NUM_NONZERO(d)) bc_num_extend(d, ts - d->scale);
1191 
1192 	neg = d->neg;
1193 	bc_num_retireMul(d, ts, a->neg, b->neg);
1194 	d->neg = BC_NUM_NONZERO(d) ? neg : false;
1195 
1196 err:
1197 	bc_num_free(&temp);
1198 	return s;
1199 }
1200 
bc_num_rem(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)1201 static BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1202 {
1203 	BcStatus s;
1204 	BcNum c1;
1205 	size_t ts;
1206 
1207 	ts = bc_vm_growSize(scale, b->scale);
1208 	ts = BC_MAX(ts, a->scale);
1209 
1210 	bc_num_init(&c1, bc_num_mulReq(a, b, ts));
1211 	s = bc_num_r(a, b, &c1, c, scale, ts);
1212 	bc_num_free(&c1);
1213 
1214 	return s;
1215 }
1216 
bc_num_p(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)1217 static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1218 
1219 	BcStatus s = BC_STATUS_SUCCESS;
1220 	BcNum copy;
1221 	BcBigDig pow = 0;
1222 	size_t i, powrdx, resrdx;
1223 	bool neg, zero;
1224 
1225 	if (BC_ERR(b->rdx)) return bc_vm_err(BC_ERROR_MATH_NON_INTEGER);
1226 
1227 	if (BC_NUM_ZERO(b)) {
1228 		bc_num_one(c);
1229 		return BC_STATUS_SUCCESS;
1230 	}
1231 	if (BC_NUM_ZERO(a)) {
1232 		if (b->neg) return bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
1233 		bc_num_setToZero(c, scale);
1234 		return BC_STATUS_SUCCESS;
1235 	}
1236 	if (BC_NUM_ONE(b)) {
1237 		if (!b->neg) bc_num_copy(c, a);
1238 		else s = bc_num_inv(a, c, scale);
1239 		return s;
1240 	}
1241 
1242 	neg = b->neg;
1243 	b->neg = false;
1244 	s = bc_num_bigdig(b, &pow);
1245 	b->neg = neg;
1246 	if (s) return s;
1247 
1248 	bc_num_createCopy(&copy, a);
1249 
1250 	if (!neg) {
1251 		size_t max = BC_MAX(scale, a->scale), scalepow = a->scale * pow;
1252 		scale = BC_MIN(scalepow, max);
1253 	}
1254 
1255 	for (powrdx = a->scale; BC_NO_SIG && !(pow & 1); pow >>= 1) {
1256 		powrdx <<= 1;
1257 		s = bc_num_mul(&copy, &copy, &copy, powrdx);
1258 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1259 	}
1260 
1261 	if (BC_SIG) goto sig_err;
1262 
1263 	bc_num_copy(c, &copy);
1264 	resrdx = powrdx;
1265 
1266 	while (BC_NO_SIG && (pow >>= 1)) {
1267 
1268 		powrdx <<= 1;
1269 		s = bc_num_mul(&copy, &copy, &copy, powrdx);
1270 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1271 
1272 		if (pow & 1) {
1273 			resrdx += powrdx;
1274 			s = bc_num_mul(c, &copy, c, resrdx);
1275 			if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1276 		}
1277 	}
1278 
1279 	if (BC_SIG) goto sig_err;
1280 	if (neg) {
1281 		s = bc_num_inv(c, c, scale);
1282 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1283 	}
1284 
1285 	if (c->scale > scale) bc_num_truncate(c, c->scale - scale);
1286 
1287 	// We can't use bc_num_clean() here.
1288 	for (zero = true, i = 0; zero && i < c->len; ++i) zero = !c->num[i];
1289 	if (zero) bc_num_setToZero(c, scale);
1290 
1291 sig_err:
1292 	if (BC_NO_ERR(!s) && BC_SIG) s = BC_STATUS_SIGNAL;
1293 err:
1294 	bc_num_free(&copy);
1295 	return s;
1296 }
1297 
1298 #if BC_ENABLE_EXTRA_MATH
bc_num_place(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)1299 static BcStatus bc_num_place(BcNum *a, BcNum *b, BcNum *restrict c,
1300                              size_t scale)
1301 {
1302 	BcStatus s = BC_STATUS_SUCCESS;
1303 	BcBigDig val = 0;
1304 
1305 	BC_UNUSED(scale);
1306 
1307 	s = bc_num_intop(a, b, c, &val);
1308 	if (BC_ERR(s)) return s;
1309 
1310 	if (val < c->scale) bc_num_truncate(c, c->scale - val);
1311 	else if (val > c->scale) bc_num_extend(c, val - c->scale);
1312 
1313 	return s;
1314 }
1315 
bc_num_left(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)1316 static BcStatus bc_num_left(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1317 {
1318 	BcStatus s = BC_STATUS_SUCCESS;
1319 	BcBigDig val = 0;
1320 
1321 	BC_UNUSED(scale);
1322 
1323 	s = bc_num_intop(a, b, c, &val);
1324 	if (BC_ERR(s)) return s;
1325 
1326 	return bc_num_shiftLeft(c, (size_t) val);
1327 }
1328 
bc_num_right(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)1329 static BcStatus bc_num_right(BcNum *a, BcNum *b, BcNum *restrict c,
1330                              size_t scale)
1331 {
1332 	BcStatus s = BC_STATUS_SUCCESS;
1333 	BcBigDig val = 0;
1334 
1335 	BC_UNUSED(scale);
1336 
1337 	s = bc_num_intop(a, b, c, &val);
1338 	if (BC_ERR(s)) return s;
1339 
1340 	if (BC_NUM_ZERO(c)) return s;
1341 
1342 	return bc_num_shiftRight(c, (size_t) val);
1343 }
1344 #endif // BC_ENABLE_EXTRA_MATH
1345 
bc_num_binary(BcNum * a,BcNum * b,BcNum * c,size_t scale,BcNumBinaryOp op,size_t req)1346 static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
1347                               BcNumBinaryOp op, size_t req)
1348 {
1349 	BcStatus s;
1350 	BcNum num2, *ptr_a, *ptr_b;
1351 	bool init = false;
1352 
1353 	assert(a != NULL && b != NULL && c != NULL && op != NULL);
1354 
1355 	if (c == a) {
1356 		ptr_a = &num2;
1357 		memcpy(ptr_a, c, sizeof(BcNum));
1358 		init = true;
1359 	}
1360 	else ptr_a = a;
1361 
1362 	if (c == b) {
1363 		ptr_b = &num2;
1364 		if (c != a) {
1365 			memcpy(ptr_b, c, sizeof(BcNum));
1366 			init = true;
1367 		}
1368 	}
1369 	else ptr_b = b;
1370 
1371 	if (init) bc_num_init(c, req);
1372 	else bc_num_expand(c, req);
1373 
1374 	s = op(ptr_a, ptr_b, c, scale);
1375 
1376 	assert(!c->neg || BC_NUM_NONZERO(c));
1377 	assert(c->rdx <= c->len || !c->len || s);
1378 	assert(!c->len || c->num[c->len - 1] || c->rdx == c->len);
1379 
1380 	if (init) bc_num_free(&num2);
1381 
1382 	return s;
1383 }
1384 
1385 #ifndef NDEBUG
bc_num_strValid(const char * val)1386 static bool bc_num_strValid(const char *val) {
1387 
1388 	bool radix = false;
1389 	size_t i, len = strlen(val);
1390 
1391 	if (!len) return true;
1392 
1393 	for (i = 0; i < len; ++i) {
1394 
1395 		BcDig c = val[i];
1396 
1397 		if (c == '.') {
1398 
1399 			if (radix) return false;
1400 
1401 			radix = true;
1402 			continue;
1403 		}
1404 
1405 		if (!(isdigit(c) || isupper(c))) return false;
1406 	}
1407 
1408 	return true;
1409 }
1410 #endif // NDEBUG
1411 
bc_num_parseChar(char c,size_t base_t)1412 static BcBigDig bc_num_parseChar(char c, size_t base_t) {
1413 
1414 	if (isupper(c)) {
1415 		c = BC_NUM_NUM_LETTER(c);
1416 		c = ((size_t) c) >= base_t ? (char) base_t - 1 : c;
1417 	}
1418 	else c -= '0';
1419 
1420 	return (BcBigDig) (uchar) c;
1421 }
1422 
bc_num_parseDecimal(BcNum * restrict n,const char * restrict val)1423 static void bc_num_parseDecimal(BcNum *restrict n, const char *restrict val) {
1424 
1425 	size_t len, i, temp, mod;
1426 	const char *ptr;
1427 	bool zero = true, rdx;
1428 
1429 	for (i = 0; val[i] == '0'; ++i);
1430 
1431 	val += i;
1432 	assert(!val[0] || isalnum(val[0]) || val[0] == '.');
1433 
1434 	// All 0's. We can just return, since this
1435 	// procedure expects a virgin (already 0) BcNum.
1436 	if (!val[0]) return;
1437 
1438 	len = strlen(val);
1439 
1440 	ptr = strchr(val, '.');
1441 	rdx = (ptr != NULL);
1442 
1443 	for (i = 0; i < len && (zero = (val[i] == '0' || val[i] == '.')); ++i);
1444 
1445 	n->scale = (size_t) (rdx * ((val + len) - (ptr + 1)));
1446 	n->rdx = BC_NUM_RDX(n->scale);
1447 
1448 	i = len - (ptr == val ? 0 : i) - rdx;
1449 	temp = BC_NUM_ROUND_POW(i);
1450 	mod = n->scale % BC_BASE_DIGS;
1451 	i = mod ? BC_BASE_DIGS - mod : 0;
1452 	n->len = ((temp + i) / BC_BASE_DIGS);
1453 
1454 	bc_num_expand(n, n->len);
1455 	memset(n->num, 0, BC_NUM_SIZE(n->len));
1456 
1457 	if (zero) n->len = n->rdx = 0;
1458 	else {
1459 
1460 		BcBigDig exp, pow;
1461 
1462 		assert(i <= BC_NUM_BIGDIG_MAX);
1463 
1464 		exp = (BcBigDig) i;
1465 		pow = bc_num_pow10[exp];
1466 
1467 		for (i = len - 1; i < len; --i, ++exp) {
1468 
1469 			char c = val[i];
1470 
1471 			if (c == '.') exp -= 1;
1472 			else {
1473 
1474 				size_t idx = exp / BC_BASE_DIGS;
1475 
1476 				if (isupper(c)) c = '9';
1477 				n->num[idx] += (((BcBigDig) c) - '0') * pow;
1478 
1479 				if ((exp + 1) % BC_BASE_DIGS == 0) pow = 1;
1480 				else pow *= BC_BASE;
1481 			}
1482 		}
1483 	}
1484 }
1485 
bc_num_parseBase(BcNum * restrict n,const char * restrict val,BcBigDig base)1486 static BcStatus bc_num_parseBase(BcNum *restrict n, const char *restrict val,
1487                                  BcBigDig base)
1488 {
1489 	BcStatus s = BC_STATUS_SUCCESS;
1490 	BcNum temp, mult1, mult2, result1, result2, *m1, *m2, *ptr;
1491 	char c = 0;
1492 	bool zero = true;
1493 	BcBigDig v;
1494 	size_t i, digs, len = strlen(val);
1495 
1496 	for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0');
1497 	if (zero) return BC_STATUS_SUCCESS;
1498 
1499 	bc_num_init(&temp, BC_NUM_BIGDIG_LOG10);
1500 	bc_num_init(&mult1, BC_NUM_BIGDIG_LOG10);
1501 
1502 	for (i = 0; i < len && (c = val[i]) && c != '.'; ++i) {
1503 
1504 		v = bc_num_parseChar(c, base);
1505 
1506 		s = bc_num_mulArray(n, base, &mult1);
1507 		if (BC_ERROR_SIGNAL_ONLY(s)) goto int_err;
1508 		bc_num_bigdig2num(&temp, v);
1509 		s = bc_num_add(&mult1, &temp, n, 0);
1510 		if (BC_ERROR_SIGNAL_ONLY(s)) goto int_err;
1511 	}
1512 
1513 	if (i == len && !(c = val[i])) goto int_err;
1514 
1515 	assert(c == '.');
1516 	bc_num_init(&mult2, BC_NUM_BIGDIG_LOG10);
1517 	bc_num_init(&result1, BC_NUM_DEF_SIZE);
1518 	bc_num_init(&result2, BC_NUM_DEF_SIZE);
1519 	bc_num_one(&mult1);
1520 
1521 	m1 = &mult1;
1522 	m2 = &mult2;
1523 
1524 	for (i += 1, digs = 0; BC_NO_SIG && i < len && (c = val[i]); ++i, ++digs) {
1525 
1526 		v = bc_num_parseChar(c, base);
1527 
1528 		s = bc_num_mulArray(&result1, base, &result2);
1529 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1530 
1531 		bc_num_bigdig2num(&temp, v);
1532 		s = bc_num_add(&result2, &temp, &result1, 0);
1533 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1534 		s = bc_num_mulArray(m1, base, m2);
1535 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1536 
1537 		if (m2->len < m2->rdx) m2->len = m2->rdx;
1538 
1539 		ptr = m1;
1540 		m1 = m2;
1541 		m2 = ptr;
1542 	}
1543 
1544 	if (BC_SIG) {
1545 		s = BC_STATUS_SIGNAL;
1546 		goto err;
1547 	}
1548 
1549 	// This one cannot be a divide by 0 because mult starts out at 1, then is
1550 	// multiplied by base, and base cannot be 0, so mult cannot be 0.
1551 	s = bc_num_div(&result1, m1, &result2, digs * 2);
1552 	assert(!s || s == BC_STATUS_SIGNAL);
1553 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1554 	bc_num_truncate(&result2, digs);
1555 	s = bc_num_add(n, &result2, n, digs);
1556 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1557 
1558 	if (BC_NUM_NONZERO(n)) {
1559 		if (n->scale < digs) bc_num_extend(n, digs - n->scale);
1560 	}
1561 	else bc_num_zero(n);
1562 
1563 err:
1564 	bc_num_free(&result2);
1565 	bc_num_free(&result1);
1566 	bc_num_free(&mult2);
1567 int_err:
1568 	bc_num_free(&mult1);
1569 	bc_num_free(&temp);
1570 	return s;
1571 }
1572 
bc_num_printNewline(void)1573 static void bc_num_printNewline(void) {
1574 	if (vm->nchars >= (size_t) (vm->line_len - 1)) {
1575 		bc_vm_putchar('\\');
1576 		bc_vm_putchar('\n');
1577 	}
1578 }
1579 
bc_num_putchar(int c)1580 static void bc_num_putchar(int c) {
1581 	if (c != '\n') bc_num_printNewline();
1582 	bc_vm_putchar(c);
1583 }
1584 
1585 #if DC_ENABLED
bc_num_printChar(size_t n,size_t len,bool rdx)1586 static void bc_num_printChar(size_t n, size_t len, bool rdx) {
1587 	BC_UNUSED(rdx);
1588 	BC_UNUSED(len);
1589 	assert(len == 1);
1590 	bc_vm_putchar((uchar) n);
1591 }
1592 #endif // DC_ENABLED
1593 
bc_num_printDigits(size_t n,size_t len,bool rdx)1594 static void bc_num_printDigits(size_t n, size_t len, bool rdx) {
1595 
1596 	size_t exp, pow;
1597 
1598 	bc_num_putchar(rdx ? '.' : ' ');
1599 
1600 	for (exp = 0, pow = 1; exp < len - 1; ++exp, pow *= BC_BASE);
1601 
1602 	for (exp = 0; exp < len; pow /= BC_BASE, ++exp) {
1603 		size_t dig = n / pow;
1604 		n -= dig * pow;
1605 		bc_num_putchar(((uchar) dig) + '0');
1606 	}
1607 }
1608 
bc_num_printHex(size_t n,size_t len,bool rdx)1609 static void bc_num_printHex(size_t n, size_t len, bool rdx) {
1610 
1611 	BC_UNUSED(len);
1612 
1613 	assert(len == 1);
1614 
1615 	if (rdx) bc_num_putchar('.');
1616 
1617 	bc_num_putchar(bc_num_hex_digits[n]);
1618 }
1619 
bc_num_printDecimal(const BcNum * restrict n)1620 static void bc_num_printDecimal(const BcNum *restrict n) {
1621 
1622 	size_t i, j, rdx = n->rdx;
1623 	bool zero = true;
1624 	size_t buffer[BC_BASE_DIGS];
1625 
1626 	if (n->neg) bc_num_putchar('-');
1627 
1628 	for (i = n->len - 1; i < n->len; --i) {
1629 
1630 		BcDig n9 = n->num[i];
1631 		size_t temp;
1632 		bool irdx = (i == rdx - 1);
1633 
1634 		zero = (zero & !irdx);
1635 		temp = n->scale % BC_BASE_DIGS;
1636 		temp = i || !temp ? 0 : BC_BASE_DIGS - temp;
1637 
1638 		memset(buffer, 0, BC_BASE_DIGS * sizeof(size_t));
1639 
1640 		for (j = 0; n9 && j < BC_BASE_DIGS; ++j) {
1641 			buffer[j] = n9 % BC_BASE;
1642 			n9 /= BC_BASE;
1643 		}
1644 
1645 		for (j = BC_BASE_DIGS - 1; j < BC_BASE_DIGS && j >= temp; --j) {
1646 			bool print_rdx = (irdx & (j == BC_BASE_DIGS - 1));
1647 			zero = (zero && buffer[j] == 0);
1648 			if (!zero) bc_num_printHex(buffer[j], 1, print_rdx);
1649 		}
1650 	}
1651 }
1652 
1653 #if BC_ENABLE_EXTRA_MATH
bc_num_printExponent(const BcNum * restrict n,bool eng)1654 static BcStatus bc_num_printExponent(const BcNum *restrict n, bool eng) {
1655 
1656 	BcStatus s = BC_STATUS_SUCCESS;
1657 	bool neg = (n->len <= n->rdx);
1658 	BcNum temp, exp;
1659 	size_t places, mod;
1660 	BcDig digs[BC_NUM_BIGDIG_LOG10];
1661 
1662 	bc_num_createCopy(&temp, n);
1663 
1664 	if (neg) {
1665 
1666 		size_t i, idx = bc_num_nonzeroLen(n) - 1;
1667 
1668 		places = 1;
1669 
1670 		for (i = BC_BASE_DIGS - 1; i < BC_BASE_DIGS; --i) {
1671 			if (bc_num_pow10[i] > (BcBigDig) n->num[idx]) places += 1;
1672 			else break;
1673 		}
1674 
1675 		places += (n->rdx - (idx + 1)) * BC_BASE_DIGS;
1676 		mod = places % 3;
1677 
1678 		if (eng && mod != 0) places += 3 - mod;
1679 		s = bc_num_shiftLeft(&temp, places);
1680 		if (BC_ERROR_SIGNAL_ONLY(s)) goto exit;
1681 	}
1682 	else {
1683 		places = bc_num_intDigits(n) - 1;
1684 		mod = places % 3;
1685 		if (eng && mod != 0) places -= 3 - (3 - mod);
1686 		s = bc_num_shiftRight(&temp, places);
1687 		if (BC_ERROR_SIGNAL_ONLY(s)) goto exit;
1688 	}
1689 
1690 	bc_num_printDecimal(&temp);
1691 	bc_num_putchar('e');
1692 
1693 	if (!places) {
1694 		bc_num_printHex(0, 1, false);
1695 		goto exit;
1696 	}
1697 
1698 	if (neg) bc_num_putchar('-');
1699 
1700 	bc_num_setup(&exp, digs, BC_NUM_BIGDIG_LOG10);
1701 	bc_num_bigdig2num(&exp, (BcBigDig) places);
1702 
1703 	bc_num_printDecimal(&exp);
1704 
1705 exit:
1706 	bc_num_free(&temp);
1707 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
1708 }
1709 #endif // BC_ENABLE_EXTRA_MATH
1710 
bc_num_printFixup(BcNum * restrict n,BcBigDig rem,BcBigDig pow,size_t idx)1711 static BcStatus bc_num_printFixup(BcNum *restrict n, BcBigDig rem,
1712                                   BcBigDig pow, size_t idx)
1713 {
1714 	size_t i, len = n->len - idx;
1715 	BcBigDig acc;
1716 	BcDig *a = n->num + idx;
1717 
1718 	if (len < 2) return BC_STATUS_SUCCESS;
1719 
1720 	for (i = len - 1; BC_NO_SIG && i > 0; --i) {
1721 
1722 		acc = ((BcBigDig) a[i]) * rem + ((BcBigDig) a[i - 1]);
1723 		a[i - 1] = (BcDig) (acc % pow);
1724 		acc /= pow;
1725 		acc += (BcBigDig) a[i];
1726 
1727 		if (acc >= BC_BASE_POW) {
1728 
1729 			if (i == len - 1) {
1730 				len = bc_vm_growSize(len, 1);
1731 				bc_num_expand(n, bc_vm_growSize(len, idx));
1732 				a = n->num + idx;
1733 				a[len - 1] = 0;
1734 			}
1735 
1736 			a[i + 1] += acc / BC_BASE_POW;
1737 			acc %= BC_BASE_POW;
1738 		}
1739 
1740 		assert(acc < BC_BASE_POW);
1741 		a[i] = (BcDig) acc;
1742 	}
1743 
1744 	n->len = len + idx;
1745 
1746 	return BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
1747 }
1748 
bc_num_printPrepare(BcNum * restrict n,BcBigDig rem,BcBigDig pow)1749 static BcStatus bc_num_printPrepare(BcNum *restrict n, BcBigDig rem,
1750                                     BcBigDig pow)
1751 {
1752 	BcStatus s = BC_STATUS_SUCCESS;
1753 	size_t i;
1754 
1755 	for (i = 0; BC_NO_SIG && BC_NO_ERR(!s) && i < n->len; ++i)
1756 		s = bc_num_printFixup(n, rem, pow, i);
1757 
1758 	if (BC_ERR(s)) return s;
1759 
1760 	for (i = 0; BC_NO_SIG && i < n->len; ++i) {
1761 
1762 		assert(pow == ((BcBigDig) ((BcDig) pow)));
1763 
1764 		if (n->num[i] >= (BcDig) pow) {
1765 
1766 			if (i + 1 == n->len) {
1767 				n->len = bc_vm_growSize(n->len, 1);
1768 				bc_num_expand(n, n->len);
1769 				n->num[i + 1] = 0;
1770 			}
1771 
1772 			assert(pow < BC_BASE_POW);
1773 			n->num[i + 1] += n->num[i] / ((BcDig) pow);
1774 			n->num[i] %= (BcDig) pow;
1775 		}
1776 	}
1777 
1778 	return BC_NO_ERR(!s) && BC_SIG ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
1779 }
1780 
bc_num_printNum(BcNum * restrict n,BcBigDig base,size_t len,BcNumDigitOp print)1781 static BcStatus bc_num_printNum(BcNum *restrict n, BcBigDig base,
1782                                 size_t len, BcNumDigitOp print)
1783 {
1784 	BcStatus s;
1785 	BcVec stack;
1786 	BcNum intp, fracp1, fracp2, digit, flen1, flen2, *n1, *n2, *temp;
1787 	BcBigDig dig = 0, *ptr, acc, exp;
1788 	size_t i, j;
1789 	bool radix;
1790 	BcDig digit_digs[BC_NUM_BIGDIG_LOG10 + 1];
1791 
1792 	assert(base > 1);
1793 
1794 	if (BC_NUM_ZERO(n)) {
1795 		print(0, len, false);
1796 		return BC_STATUS_SUCCESS;
1797 	}
1798 
1799 	// This function uses an algorithm that Stefan Esser <se@freebsd.org> came
1800 	// up with to print the integer part of a number. What it does is convert
1801 	// intp into a number of the specified base, but it does it directly,
1802 	// instead of just doing a series of divisions and printing the remainders
1803 	// in reverse order.
1804 	//
1805 	// Let me explain in a bit more detail:
1806 	//
1807 	// The algorithm takes the current least significant digit (after intp has
1808 	// been converted to an integer) and the next to least significant digit,
1809 	// and it converts the least significant digit into one of the specified
1810 	// base, putting any overflow into the next to least significant digit. It
1811 	// iterates through the whole number, from least significant to most
1812 	// significant, doing this conversion. At the end of that iteration, the
1813 	// least significant digit is converted, but the others are not, so it
1814 	// iterates again, starting at the next to least significant digit. It keeps
1815 	// doing that conversion, skipping one more digit than the last time, until
1816 	// all digits have been converted. Then it prints them in reverse order.
1817 	//
1818 	// That is the gist of the algorithm. It leaves out several things, such as
1819 	// the fact that digits are not always converted into the specified base,
1820 	// but into something close, basically a power of the specified base. In
1821 	// Stefan's words, "You could consider BcDigs to be of base 10^BC_BASE_DIGS
1822 	// in the normal case and obase^N for the largest value of N that satisfies
1823 	// obase^N <= 10^BC_BASE_DIGS. [This means that] the result is not in base
1824 	// "obase", but in base "obase^N", which happens to be printable as a number
1825 	// of base "obase" without consideration for neighbouring BcDigs." This fact
1826 	// is what necessitates the existence of the loop later in this function.
1827 	//
1828 	// The conversion happens in bc_num_printPrepare() where the outer loop
1829 	// happens and bc_num_printFixup() where the inner loop, or actual
1830 	// conversion, happens.
1831 
1832 	bc_vec_init(&stack, sizeof(BcBigDig), NULL);
1833 	bc_num_init(&fracp1, n->rdx);
1834 
1835 	bc_num_createCopy(&intp, n);
1836 	bc_num_truncate(&intp, intp.scale);
1837 
1838 	s = bc_num_sub(n, &intp, &fracp1, 0);
1839 	if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1840 
1841 	if (base != vm->last_base) {
1842 
1843 		vm->last_pow = 1;
1844 		vm->last_exp = 0;
1845 
1846 		while (vm->last_pow * base <= BC_BASE_POW) {
1847 			vm->last_pow *= base;
1848 			vm->last_exp += 1;
1849 		}
1850 
1851 		vm->last_rem = BC_BASE_POW - vm->last_pow;
1852 		vm->last_base = base;
1853 	}
1854 
1855 	exp = vm->last_exp;
1856 
1857 	if (vm->last_rem != 0) {
1858 		s = bc_num_printPrepare(&intp, vm->last_rem, vm->last_pow);
1859 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
1860 	}
1861 
1862 	for (i = 0; BC_NO_SIG && i < intp.len; ++i) {
1863 
1864 		acc = (BcBigDig) intp.num[i];
1865 
1866 		for (j = 0; BC_NO_SIG && j < exp && (i < intp.len - 1 || acc != 0); ++j)
1867 		{
1868 			if (j != exp - 1) {
1869 				dig = acc % base;
1870 				acc /= base;
1871 			}
1872 			else {
1873 				dig = acc;
1874 				acc = 0;
1875 			}
1876 
1877 			assert(dig < base);
1878 
1879 			bc_vec_push(&stack, &dig);
1880 		}
1881 
1882 		assert(acc == 0 || BC_SIG);
1883 	}
1884 
1885 	if (BC_SIG) goto sig_err;
1886 
1887 	for (i = 0; BC_NO_SIG && i < stack.len; ++i) {
1888 		ptr = bc_vec_item_rev(&stack, i);
1889 		assert(ptr != NULL);
1890 		print(*ptr, len, false);
1891 	}
1892 
1893 	if (BC_SIG) goto sig_err;
1894 	if (!n->scale) goto err;
1895 
1896 	bc_num_init(&fracp2, n->rdx);
1897 	bc_num_setup(&digit, digit_digs, sizeof(digit_digs) / sizeof(BcDig));
1898 	bc_num_init(&flen1, BC_NUM_BIGDIG_LOG10 + 1);
1899 	bc_num_init(&flen2, BC_NUM_BIGDIG_LOG10 + 1);
1900 	bc_num_one(&flen1);
1901 
1902 	radix = true;
1903 	n1 = &flen1;
1904 	n2 = &flen2;
1905 
1906 	fracp2.scale = n->scale;
1907 	fracp2.rdx = BC_NUM_RDX(fracp2.scale);
1908 
1909 	while (BC_NO_SIG && bc_num_intDigits(n1) < n->scale + 1) {
1910 
1911 		bc_num_expand(&fracp2, fracp1.len + 1);
1912 		s = bc_num_mulArray(&fracp1, base, &fracp2);
1913 		if (BC_ERROR_SIGNAL_ONLY(s)) goto frac_err;
1914 		if (fracp2.len < fracp2.rdx) fracp2.len = fracp2.rdx;
1915 
1916 		// Will never fail (except for signals) because fracp is
1917 		// guaranteed to be non-negative and small enough.
1918 		s = bc_num_bigdig(&fracp2, &dig);
1919 		if (BC_ERROR_SIGNAL_ONLY(s)) goto frac_err;
1920 
1921 		bc_num_bigdig2num(&digit, dig);
1922 		s = bc_num_sub(&fracp2, &digit, &fracp1, 0);
1923 		if (BC_ERROR_SIGNAL_ONLY(s)) goto frac_err;
1924 
1925 		print(dig, len, radix);
1926 		s = bc_num_mulArray(n1, base, n2);
1927 		if (BC_ERROR_SIGNAL_ONLY(s)) goto frac_err;
1928 
1929 		radix = false;
1930 		temp = n1;
1931 		n1 = n2;
1932 		n2 = temp;
1933 	}
1934 
1935 frac_err:
1936 	bc_num_free(&flen2);
1937 	bc_num_free(&flen1);
1938 	bc_num_free(&fracp2);
1939 sig_err:
1940 	if (BC_NO_ERR(!s) && BC_SIG) s = BC_STATUS_SIGNAL;
1941 err:
1942 	bc_num_free(&fracp1);
1943 	bc_num_free(&intp);
1944 	bc_vec_free(&stack);
1945 	return s;
1946 }
1947 
bc_num_printBase(BcNum * restrict n,BcBigDig base)1948 static BcStatus bc_num_printBase(BcNum *restrict n, BcBigDig base) {
1949 
1950 	BcStatus s;
1951 	size_t width;
1952 	BcNumDigitOp print;
1953 	bool neg = n->neg;
1954 
1955 	if (neg) bc_num_putchar('-');
1956 
1957 	n->neg = false;
1958 
1959 	if (base <= BC_NUM_MAX_POSIX_IBASE) {
1960 		width = 1;
1961 		print = bc_num_printHex;
1962 	}
1963 	else {
1964 		width = bc_num_log10(base - 1);
1965 		print = bc_num_printDigits;
1966 	}
1967 
1968 	s = bc_num_printNum(n, base, width, print);
1969 	n->neg = neg;
1970 
1971 	return s;
1972 }
1973 
1974 #if DC_ENABLED
bc_num_stream(BcNum * restrict n,BcBigDig base)1975 BcStatus bc_num_stream(BcNum *restrict n, BcBigDig base) {
1976 	return bc_num_printNum(n, base, 1, bc_num_printChar);
1977 }
1978 #endif // DC_ENABLED
1979 
bc_num_setup(BcNum * restrict n,BcDig * restrict num,size_t cap)1980 void bc_num_setup(BcNum *restrict n, BcDig *restrict num, size_t cap) {
1981 	assert(n != NULL);
1982 	n->num = num;
1983 	n->cap = cap;
1984 	bc_num_zero(n);
1985 }
1986 
bc_num_init(BcNum * restrict n,size_t req)1987 void bc_num_init(BcNum *restrict n, size_t req) {
1988 	assert(n != NULL);
1989 	req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
1990 	bc_num_setup(n, bc_vm_malloc(BC_NUM_SIZE(req)), req);
1991 }
1992 
bc_num_free(void * num)1993 void bc_num_free(void *num) {
1994 	assert(num != NULL);
1995 	free(((BcNum*) num)->num);
1996 }
1997 
bc_num_copy(BcNum * d,const BcNum * s)1998 void bc_num_copy(BcNum *d, const BcNum *s) {
1999 	assert(d != NULL && s != NULL);
2000 	if (d == s) return;
2001 	bc_num_expand(d, s->len);
2002 	d->len = s->len;
2003 	d->neg = s->neg;
2004 	d->rdx = s->rdx;
2005 	d->scale = s->scale;
2006 	memcpy(d->num, s->num, BC_NUM_SIZE(d->len));
2007 }
2008 
bc_num_createCopy(BcNum * d,const BcNum * s)2009 void bc_num_createCopy(BcNum *d, const BcNum *s) {
2010 	bc_num_init(d, s->len);
2011 	bc_num_copy(d, s);
2012 }
2013 
bc_num_createFromBigdig(BcNum * n,BcBigDig val)2014 void bc_num_createFromBigdig(BcNum *n, BcBigDig val) {
2015 	bc_num_init(n, (BC_NUM_BIGDIG_LOG10 - 1) / BC_BASE_DIGS + 1);
2016 	bc_num_bigdig2num(n, val);
2017 }
2018 
bc_num_scale(const BcNum * restrict n)2019 size_t bc_num_scale(const BcNum *restrict n) {
2020 	return n->scale;
2021 }
2022 
bc_num_len(const BcNum * restrict n)2023 size_t bc_num_len(const BcNum *restrict n) {
2024 
2025 	size_t len = n->len;
2026 
2027 	if (BC_NUM_ZERO(n)) return 0;
2028 
2029 	if (n->rdx == len) {
2030 
2031 		size_t zero, scale;
2032 
2033 		len = bc_num_nonzeroLen(n);
2034 
2035 		scale = n->scale % BC_BASE_DIGS;
2036 		scale = scale ? scale : BC_BASE_DIGS;
2037 
2038 		zero = bc_num_zeroDigits(n->num + len - 1);
2039 
2040 		len = len * BC_BASE_DIGS - zero - (BC_BASE_DIGS - scale);
2041 	}
2042 	else len = bc_num_intDigits(n) + n->scale;
2043 
2044 	return len;
2045 }
2046 
bc_num_parse(BcNum * restrict n,const char * restrict val,BcBigDig base,bool letter)2047 BcStatus bc_num_parse(BcNum *restrict n, const char *restrict val,
2048                       BcBigDig base, bool letter)
2049 {
2050 	BcStatus s = BC_STATUS_SUCCESS;
2051 
2052 	assert(n != NULL && val != NULL && base);
2053 	assert(base >= BC_NUM_MIN_BASE && base <= vm->maxes[BC_PROG_GLOBALS_IBASE]);
2054 	assert(bc_num_strValid(val));
2055 
2056 	if (letter) {
2057 		BcBigDig dig = bc_num_parseChar(val[0], BC_NUM_MAX_LBASE);
2058 		bc_num_bigdig2num(n, dig);
2059 	}
2060 	else if (base == BC_BASE) bc_num_parseDecimal(n, val);
2061 	else s = bc_num_parseBase(n, val, base);
2062 
2063 	return s;
2064 }
2065 
bc_num_print(BcNum * restrict n,BcBigDig base,bool newline)2066 BcStatus bc_num_print(BcNum *restrict n, BcBigDig base, bool newline) {
2067 
2068 	BcStatus s = BC_STATUS_SUCCESS;
2069 
2070 	assert(n != NULL);
2071 	assert(BC_ENABLE_EXTRA_MATH || base >= BC_NUM_MIN_BASE);
2072 
2073 	bc_num_printNewline();
2074 
2075 	if (BC_NUM_ZERO(n)) bc_num_printHex(0, 1, false);
2076 	else if (base == BC_BASE) bc_num_printDecimal(n);
2077 #if BC_ENABLE_EXTRA_MATH
2078 	else if (base == 0 || base == 1)
2079 		s = bc_num_printExponent(n, base != 0);
2080 #endif // BC_ENABLE_EXTRA_MATH
2081 	else s = bc_num_printBase(n, base);
2082 
2083 	if (BC_NO_ERR(!s) && newline) bc_num_putchar('\n');
2084 
2085 	return s;
2086 }
2087 
bc_num_bigdig(const BcNum * restrict n,BcBigDig * result)2088 BcStatus bc_num_bigdig(const BcNum *restrict n, BcBigDig *result) {
2089 
2090 	size_t i;
2091 	BcBigDig r;
2092 
2093 	assert(n != NULL && result != NULL);
2094 
2095 	if (BC_ERR(n->neg)) return bc_vm_err(BC_ERROR_MATH_NEGATIVE);
2096 
2097 	for (r = 0, i = n->len; i > n->rdx;) {
2098 
2099 		BcBigDig prev = r * BC_BASE_POW;
2100 
2101 		if (BC_ERR(prev / BC_BASE_POW != r))
2102 			return bc_vm_err(BC_ERROR_MATH_OVERFLOW);
2103 
2104 		r = prev + (BcBigDig) n->num[--i];
2105 
2106 		if (BC_ERR(r < prev)) return bc_vm_err(BC_ERROR_MATH_OVERFLOW);
2107 	}
2108 
2109 	*result = r;
2110 
2111 	return BC_STATUS_SUCCESS;
2112 }
2113 
bc_num_bigdig2num(BcNum * restrict n,BcBigDig val)2114 void bc_num_bigdig2num(BcNum *restrict n, BcBigDig val) {
2115 
2116 	BcDig *ptr;
2117 	size_t i;
2118 
2119 	assert(n != NULL);
2120 
2121 	bc_num_zero(n);
2122 
2123 	if (!val) return;
2124 
2125 	bc_num_expand(n, BC_NUM_BIGDIG_LOG10);
2126 
2127 	for (ptr = n->num, i = 0; val; ++i, val /= BC_BASE_POW)
2128 		ptr[i] = val % BC_BASE_POW;
2129 
2130 	n->len = i;
2131 }
2132 
bc_num_addReq(const BcNum * a,const BcNum * b,size_t scale)2133 size_t bc_num_addReq(const BcNum *a, const BcNum *b, size_t scale) {
2134 
2135 	size_t aint, bint, ardx, brdx;
2136 
2137 	BC_UNUSED(scale);
2138 
2139 	ardx = a->rdx;
2140 	aint = bc_num_int(a);
2141 	assert(aint <= a->len && ardx <= a->len);
2142 
2143 	brdx = b->rdx;
2144 	bint = bc_num_int(b);
2145 	assert(bint <= b->len && brdx <= b->len);
2146 
2147 	ardx = BC_MAX(ardx, brdx);
2148 	aint = BC_MAX(aint, bint);
2149 
2150 	return bc_vm_growSize(bc_vm_growSize(ardx, aint), 1);
2151 }
2152 
bc_num_mulReq(const BcNum * a,const BcNum * b,size_t scale)2153 size_t bc_num_mulReq(const BcNum *a, const BcNum *b, size_t scale) {
2154 	size_t max, rdx;
2155 	rdx = bc_vm_growSize(a->rdx, b->rdx);
2156 	max = BC_NUM_RDX(scale);
2157 	max = bc_vm_growSize(BC_MAX(max, rdx), 1);
2158 	rdx = bc_vm_growSize(bc_vm_growSize(bc_num_int(a), bc_num_int(b)), max);
2159 	return rdx;
2160 }
2161 
bc_num_powReq(const BcNum * a,const BcNum * b,size_t scale)2162 size_t bc_num_powReq(const BcNum *a, const BcNum *b, size_t scale) {
2163 	BC_UNUSED(scale);
2164 	return bc_vm_growSize(bc_vm_growSize(a->len, b->len), 1);
2165 }
2166 
2167 #if BC_ENABLE_EXTRA_MATH
bc_num_placesReq(const BcNum * a,const BcNum * b,size_t scale)2168 size_t bc_num_placesReq(const BcNum *a, const BcNum *b, size_t scale) {
2169 	BC_UNUSED(scale);
2170 	return a->len + b->len - a->rdx - b->rdx;
2171 }
2172 #endif // BC_ENABLE_EXTRA_MATH
2173 
bc_num_add(BcNum * a,BcNum * b,BcNum * c,size_t scale)2174 BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2175 	return bc_num_binary(a, b, c, false, bc_num_as, bc_num_addReq(a, b, scale));
2176 }
2177 
bc_num_sub(BcNum * a,BcNum * b,BcNum * c,size_t scale)2178 BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2179 	return bc_num_binary(a, b, c, true, bc_num_as, bc_num_addReq(a, b, scale));
2180 }
2181 
bc_num_mul(BcNum * a,BcNum * b,BcNum * c,size_t scale)2182 BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2183 	return bc_num_binary(a, b, c, scale, bc_num_m, bc_num_mulReq(a, b, scale));
2184 }
2185 
bc_num_div(BcNum * a,BcNum * b,BcNum * c,size_t scale)2186 BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2187 	return bc_num_binary(a, b, c, scale, bc_num_d, bc_num_mulReq(a, b, scale));
2188 }
2189 
bc_num_mod(BcNum * a,BcNum * b,BcNum * c,size_t scale)2190 BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2191 	size_t req = bc_num_mulReq(a, b, scale);
2192 	return bc_num_binary(a, b, c, scale, bc_num_rem, req);
2193 }
2194 
bc_num_pow(BcNum * a,BcNum * b,BcNum * c,size_t scale)2195 BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2196 	return bc_num_binary(a, b, c, scale, bc_num_p, bc_num_powReq(a, b, scale));
2197 }
2198 
2199 #if BC_ENABLE_EXTRA_MATH
bc_num_places(BcNum * a,BcNum * b,BcNum * c,size_t scale)2200 BcStatus bc_num_places(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2201 	size_t req = bc_num_placesReq(a, b, scale);
2202 	return bc_num_binary(a, b, c, scale, bc_num_place, req);
2203 }
2204 
bc_num_lshift(BcNum * a,BcNum * b,BcNum * c,size_t scale)2205 BcStatus bc_num_lshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2206 	size_t req = bc_num_placesReq(a, b, scale);
2207 	return bc_num_binary(a, b, c, scale, bc_num_left, req);
2208 }
2209 
bc_num_rshift(BcNum * a,BcNum * b,BcNum * c,size_t scale)2210 BcStatus bc_num_rshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2211 	size_t req = bc_num_placesReq(a, b, scale);
2212 	return bc_num_binary(a, b, c, scale, bc_num_right, req);
2213 }
2214 #endif // BC_ENABLE_EXTRA_MATH
2215 
bc_num_sqrt(BcNum * restrict a,BcNum * restrict b,size_t scale)2216 BcStatus bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
2217 
2218 	BcStatus s = BC_STATUS_SUCCESS;
2219 	BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
2220 	size_t pow, len, rdx, req, digs, digs1, digs2, resscale;
2221 	BcDig half_digs[1];
2222 
2223 	assert(a != NULL && b != NULL && a != b);
2224 
2225 	if (BC_ERR(a->neg)) return bc_vm_err(BC_ERROR_MATH_NEGATIVE);
2226 
2227 	if (a->scale > scale) scale = a->scale;
2228 	len = bc_vm_growSize(bc_num_intDigits(a), 1);
2229 	rdx = BC_NUM_RDX(scale);
2230 	req = bc_vm_growSize(BC_MAX(rdx, a->rdx), len >> 1);
2231 	bc_num_init(b, bc_vm_growSize(req, 1));
2232 
2233 	if (BC_NUM_ZERO(a)) {
2234 		bc_num_setToZero(b, scale);
2235 		return BC_STATUS_SUCCESS;
2236 	}
2237 	if (BC_NUM_ONE(a)) {
2238 		bc_num_one(b);
2239 		bc_num_extend(b, scale);
2240 		return BC_STATUS_SUCCESS;
2241 	}
2242 
2243 	rdx = BC_NUM_RDX(scale);
2244 	rdx = BC_MAX(rdx, a->rdx);
2245 	len = bc_vm_growSize(a->len, rdx);
2246 
2247 	bc_num_init(&num1, len);
2248 	bc_num_init(&num2, len);
2249 	bc_num_setup(&half, half_digs, sizeof(half_digs) / sizeof(BcDig));
2250 
2251 	bc_num_one(&half);
2252 	half.num[0] = BC_BASE_POW / 2;
2253 	half.len = 1;
2254 	half.rdx = 1;
2255 	half.scale = 1;
2256 
2257 	bc_num_init(&f, len);
2258 	bc_num_init(&fprime, len);
2259 
2260 	x0 = &num1;
2261 	x1 = &num2;
2262 
2263 	bc_num_one(x0);
2264 	pow = bc_num_intDigits(a);
2265 
2266 	if (pow) {
2267 
2268 		if (pow & 1) x0->num[0] = 2;
2269 		else x0->num[0] = 6;
2270 
2271 		pow -= 2 - (pow & 1);
2272 		s = bc_num_shiftLeft(x0, pow / 2);
2273 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2274 	}
2275 
2276 	x0->scale = x0->rdx = digs = digs1 = digs2 = 0;
2277 	resscale = (scale + BC_BASE_DIGS) + 2;
2278 
2279 	while (BC_NO_SIG && bc_num_cmp(x1, x0)) {
2280 
2281 		assert(BC_NUM_NONZERO(x0));
2282 
2283 		s = bc_num_div(a, x0, &f, resscale);
2284 		assert(!s || s == BC_STATUS_SIGNAL);
2285 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2286 		s = bc_num_add(x0, &f, &fprime, resscale);
2287 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2288 		s = bc_num_mul(&fprime, &half, x1, resscale);
2289 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2290 
2291 		temp = x0;
2292 		x0 = x1;
2293 		x1 = temp;
2294 	}
2295 
2296 	if (BC_SIG) {
2297 		s = BC_STATUS_SIGNAL;
2298 		goto err;
2299 	}
2300 
2301 	bc_num_copy(b, x0);
2302 	if (b->scale > scale) bc_num_truncate(b, b->scale - scale);
2303 
2304 	assert(!b->neg || BC_NUM_NONZERO(b));
2305 	assert(b->rdx <= b->len || !b->len);
2306 	assert(!b->len || b->num[b->len - 1] || b->rdx == b->len);
2307 
2308 err:
2309 	if (BC_ERR(s)) bc_num_free(b);
2310 	bc_num_free(&fprime);
2311 	bc_num_free(&f);
2312 	bc_num_free(&num2);
2313 	bc_num_free(&num1);
2314 	return s;
2315 }
2316 
bc_num_divmod(BcNum * a,BcNum * b,BcNum * c,BcNum * d,size_t scale)2317 BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) {
2318 
2319 	BcStatus s;
2320 	BcNum num2, *ptr_a;
2321 	bool init = false;
2322 	size_t ts, len;
2323 
2324 	ts = BC_MAX(scale + b->scale, a->scale);
2325 	len = bc_num_mulReq(a, b, ts);
2326 
2327 	assert(a != NULL && b != NULL && c != NULL && d != NULL);
2328 	assert(c != d && a != d && b != d && b != c);
2329 
2330 	if (c == a) {
2331 		memcpy(&num2, c, sizeof(BcNum));
2332 		ptr_a = &num2;
2333 		bc_num_init(c, len);
2334 		init = true;
2335 	}
2336 	else {
2337 		ptr_a = a;
2338 		bc_num_expand(c, len);
2339 	}
2340 
2341 	if (BC_NUM_NONZERO(a) && !a->rdx && !b->rdx && b->len == 1 && !scale) {
2342 
2343 		BcBigDig rem;
2344 
2345 		s = bc_num_divArray(ptr_a, (BcBigDig) b->num[0], c, &rem);
2346 
2347 		assert(rem < BC_BASE_POW);
2348 
2349 		d->num[0] = (BcDig) rem;
2350 		d->len = (rem != 0);
2351 	}
2352 	else s = bc_num_r(ptr_a, b, c, d, scale, ts);
2353 
2354 	assert(!c->neg || BC_NUM_NONZERO(c));
2355 	assert(c->rdx <= c->len || !c->len);
2356 	assert(!c->len || c->num[c->len - 1] || c->rdx == c->len);
2357 	assert(!d->neg || BC_NUM_NONZERO(d));
2358 	assert(d->rdx <= d->len || !d->len);
2359 	assert(!d->len || d->num[d->len - 1] || d->rdx == d->len);
2360 
2361 	if (init) bc_num_free(&num2);
2362 
2363 	return s;
2364 }
2365 
2366 #if DC_ENABLED
bc_num_modexp(BcNum * a,BcNum * b,BcNum * c,BcNum * restrict d)2367 BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) {
2368 
2369 	BcStatus s;
2370 	BcNum base, exp, two, temp;
2371 	BcDig two_digs[2];
2372 
2373 	assert(a != NULL && b != NULL && c != NULL && d != NULL);
2374 	assert(a != d && b != d && c != d);
2375 
2376 	if (BC_ERR(BC_NUM_ZERO(c)))
2377 		return bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
2378 	if (BC_ERR(b->neg)) return bc_vm_err(BC_ERROR_MATH_NEGATIVE);
2379 	if (BC_ERR(a->rdx || b->rdx || c->rdx))
2380 		return bc_vm_err(BC_ERROR_MATH_NON_INTEGER);
2381 
2382 	bc_num_expand(d, c->len);
2383 	bc_num_init(&base, c->len);
2384 	bc_num_setup(&two, two_digs, sizeof(two_digs) / sizeof(BcDig));
2385 	bc_num_init(&temp, b->len + 1);
2386 
2387 	bc_num_one(&two);
2388 	two.num[0] = 2;
2389 	bc_num_one(d);
2390 
2391 	// We already checked for 0.
2392 	s = bc_num_rem(a, c, &base, 0);
2393 	assert(!s || s == BC_STATUS_SIGNAL);
2394 	if (BC_ERROR_SIGNAL_ONLY(s)) goto rem_err;
2395 	bc_num_createCopy(&exp, b);
2396 
2397 	while (BC_NO_SIG && BC_NUM_NONZERO(&exp)) {
2398 
2399 		// Num two cannot be 0, so no errors.
2400 		s = bc_num_divmod(&exp, &two, &exp, &temp, 0);
2401 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2402 
2403 		if (BC_NUM_ONE(&temp) && !temp.neg) {
2404 
2405 			s = bc_num_mul(d, &base, &temp, 0);
2406 			if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2407 
2408 			// We already checked for 0.
2409 			s = bc_num_rem(&temp, c, d, 0);
2410 			assert(!s || s == BC_STATUS_SIGNAL);
2411 			if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2412 		}
2413 
2414 		s = bc_num_mul(&base, &base, &temp, 0);
2415 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2416 
2417 		// We already checked for 0.
2418 		s = bc_num_rem(&temp, c, &base, 0);
2419 		assert(!s || s == BC_STATUS_SIGNAL);
2420 		if (BC_ERROR_SIGNAL_ONLY(s)) goto err;
2421 	}
2422 
2423 	if (BC_NO_ERR(!s) && BC_SIG) s = BC_STATUS_SIGNAL;
2424 
2425 err:
2426 	bc_num_free(&exp);
2427 rem_err:
2428 	bc_num_free(&temp);
2429 	bc_num_free(&base);
2430 	assert(!d->neg || d->len);
2431 	assert(!d->len || d->num[d->len - 1] || d->rdx == d->len);
2432 	return s;
2433 }
2434 #endif // DC_ENABLED
2435 
2436 #if BC_DEBUG_CODE
bc_num_printDebug(const BcNum * n,const char * name,bool emptyline)2437 void bc_num_printDebug(const BcNum *n, const char *name, bool emptyline) {
2438 	printf("%s: ", name);
2439 	bc_num_printDecimal(n);
2440 	printf("\n");
2441 	if (emptyline) printf("\n");
2442 	vm->nchars = 0;
2443 }
2444 
bc_num_printDigs(const BcDig * n,size_t len,bool emptyline)2445 void bc_num_printDigs(const BcDig *n, size_t len, bool emptyline) {
2446 
2447 	size_t i;
2448 
2449 	for (i = len - 1; i < len; --i) printf(" %0*d", BC_BASE_DIGS, n[i]);
2450 
2451 	printf("\n");
2452 	if (emptyline) printf("\n");
2453 	vm->nchars = 0;
2454 }
2455 
bc_num_printWithDigs(const BcNum * n,const char * name,bool emptyline)2456 void bc_num_printWithDigs(const BcNum *n, const char *name, bool emptyline) {
2457 	printf("%s len: %zu, rdx: %zu, scale: %zu\n",
2458 	       name, n->len, n->rdx, n->scale);
2459 	bc_num_printDigs(n->num, n->len, emptyline);
2460 }
2461 
bc_num_dump(const char * varname,const BcNum * n)2462 void bc_num_dump(const char *varname, const BcNum *n) {
2463 
2464 	ulong i, scale = n->scale;
2465 
2466 	fprintf(stderr, "\n%s = %s", varname, n->len ? (n->neg ? "-" : "+") : "0 ");
2467 
2468 	for (i = n->len - 1; i < n->len; --i) {
2469 
2470 		if (i + 1 == n->rdx) fprintf(stderr, ". ");
2471 
2472 		if (scale / BC_BASE_DIGS != n->rdx - i - 1)
2473 			fprintf(stderr, "%0*d ", BC_BASE_DIGS, n->num[i]);
2474 		else {
2475 
2476 			int mod = scale % BC_BASE_DIGS;
2477 			int d = BC_BASE_DIGS - mod;
2478 			BcDig div;
2479 
2480 			if (mod != 0) {
2481 				div = n->num[i] / ((BcDig) bc_num_pow10[(ulong) d]);
2482 				fprintf(stderr, "%0*d", (int) mod, div);
2483 			}
2484 
2485 			div = n->num[i] % ((BcDig) bc_num_pow10[(ulong) d]);
2486 			fprintf(stderr, " ' %0*d ", d, div);
2487 		}
2488 	}
2489 
2490 	fprintf(stderr, "(%zu | %zu.%zu / %zu) %p\n",
2491 	        n->scale, n->len, n->rdx, n->cap, (void*) n->num);
2492 }
2493 #endif // BC_DEBUG_CODE
2494