xref: /freebsd/contrib/bc/src/num.c (revision d43fa8ef534ac87a16843d45264f56cf11e0fcbc)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
610328f8bSStefan Eßer  * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
7252884aeSStefan Eßer  *
8252884aeSStefan Eßer  * Redistribution and use in source and binary forms, with or without
9252884aeSStefan Eßer  * modification, are permitted provided that the following conditions are met:
10252884aeSStefan Eßer  *
11252884aeSStefan Eßer  * * Redistributions of source code must retain the above copyright notice, this
12252884aeSStefan Eßer  *   list of conditions and the following disclaimer.
13252884aeSStefan Eßer  *
14252884aeSStefan Eßer  * * Redistributions in binary form must reproduce the above copyright notice,
15252884aeSStefan Eßer  *   this list of conditions and the following disclaimer in the documentation
16252884aeSStefan Eßer  *   and/or other materials provided with the distribution.
17252884aeSStefan Eßer  *
18252884aeSStefan Eßer  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19252884aeSStefan Eßer  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20252884aeSStefan Eßer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21252884aeSStefan Eßer  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22252884aeSStefan Eßer  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23252884aeSStefan Eßer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24252884aeSStefan Eßer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25252884aeSStefan Eßer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26252884aeSStefan Eßer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27252884aeSStefan Eßer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28252884aeSStefan Eßer  * POSSIBILITY OF SUCH DAMAGE.
29252884aeSStefan Eßer  *
30252884aeSStefan Eßer  * *****************************************************************************
31252884aeSStefan Eßer  *
32252884aeSStefan Eßer  * Code for the number type.
33252884aeSStefan Eßer  *
34252884aeSStefan Eßer  */
35252884aeSStefan Eßer 
36252884aeSStefan Eßer #include <assert.h>
37252884aeSStefan Eßer #include <ctype.h>
38252884aeSStefan Eßer #include <stdbool.h>
39252884aeSStefan Eßer #include <stdlib.h>
40252884aeSStefan Eßer #include <string.h>
41252884aeSStefan Eßer #include <setjmp.h>
42252884aeSStefan Eßer #include <limits.h>
43252884aeSStefan Eßer 
44252884aeSStefan Eßer #include <num.h>
45252884aeSStefan Eßer #include <rand.h>
46252884aeSStefan Eßer #include <vm.h>
47252884aeSStefan Eßer 
4844d4804dSStefan Eßer // Before you try to understand this code, see the development manual
4944d4804dSStefan Eßer // (manuals/development.md#numbers).
5044d4804dSStefan Eßer 
51252884aeSStefan Eßer static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
52252884aeSStefan Eßer 
5344d4804dSStefan Eßer /**
5444d4804dSStefan Eßer  * Multiply two numbers and throw a math error if they overflow.
5544d4804dSStefan Eßer  * @param a  The first operand.
5644d4804dSStefan Eßer  * @param b  The second operand.
5744d4804dSStefan Eßer  * @return   The product of the two operands.
5844d4804dSStefan Eßer  */
5944d4804dSStefan Eßer static inline size_t bc_num_mulOverflow(size_t a, size_t b) {
6044d4804dSStefan Eßer 	size_t res = a * b;
6144d4804dSStefan Eßer 	if (BC_ERR(BC_VM_MUL_OVERFLOW(a, b, res))) bc_err(BC_ERR_MATH_OVERFLOW);
6244d4804dSStefan Eßer 	return res;
6344d4804dSStefan Eßer }
6444d4804dSStefan Eßer 
6544d4804dSStefan Eßer /**
6644d4804dSStefan Eßer  * Conditionally negate @a n based on @a neg. Algorithm taken from
6744d4804dSStefan Eßer  * https://graphics.stanford.edu/~seander/bithacks.html#ConditionalNegate .
6844d4804dSStefan Eßer  * @param n    The value to turn into a signed value and negate.
6944d4804dSStefan Eßer  * @param neg  The condition to negate or not.
7044d4804dSStefan Eßer  */
71252884aeSStefan Eßer static inline ssize_t bc_num_neg(size_t n, bool neg) {
72252884aeSStefan Eßer 	return (((ssize_t) n) ^ -((ssize_t) neg)) + neg;
73252884aeSStefan Eßer }
74252884aeSStefan Eßer 
7544d4804dSStefan Eßer /**
7644d4804dSStefan Eßer  * Compare a BcNum against zero.
7744d4804dSStefan Eßer  * @param n  The number to compare.
7844d4804dSStefan Eßer  * @return   -1 if the number is less than 0, 1 if greater, and 0 if equal.
7944d4804dSStefan Eßer  */
80252884aeSStefan Eßer ssize_t bc_num_cmpZero(const BcNum *n) {
8150696a6eSStefan Eßer 	return bc_num_neg((n)->len != 0, BC_NUM_NEG(n));
82252884aeSStefan Eßer }
83252884aeSStefan Eßer 
8444d4804dSStefan Eßer /**
8544d4804dSStefan Eßer  * Return the number of integer limbs in a BcNum. This is the opposite of rdx.
8644d4804dSStefan Eßer  * @param n  The number to return the amount of integer limbs for.
8744d4804dSStefan Eßer  * @return   The amount of integer limbs in @a n.
8844d4804dSStefan Eßer  */
89252884aeSStefan Eßer static inline size_t bc_num_int(const BcNum *n) {
9050696a6eSStefan Eßer 	return n->len ? n->len - BC_NUM_RDX_VAL(n) : 0;
91252884aeSStefan Eßer }
92252884aeSStefan Eßer 
9344d4804dSStefan Eßer /**
9444d4804dSStefan Eßer  * Expand a number's allocation capacity to at least req limbs.
9544d4804dSStefan Eßer  * @param n    The number to expand.
9644d4804dSStefan Eßer  * @param req  The number limbs to expand the allocation capacity to.
9744d4804dSStefan Eßer  */
98252884aeSStefan Eßer static void bc_num_expand(BcNum *restrict n, size_t req) {
99252884aeSStefan Eßer 
100252884aeSStefan Eßer 	assert(n != NULL);
101252884aeSStefan Eßer 
102252884aeSStefan Eßer 	req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
103252884aeSStefan Eßer 
104252884aeSStefan Eßer 	if (req > n->cap) {
105252884aeSStefan Eßer 
106252884aeSStefan Eßer 		BC_SIG_LOCK;
107252884aeSStefan Eßer 
108252884aeSStefan Eßer 		n->num = bc_vm_realloc(n->num, BC_NUM_SIZE(req));
109252884aeSStefan Eßer 		n->cap = req;
110252884aeSStefan Eßer 
111252884aeSStefan Eßer 		BC_SIG_UNLOCK;
112252884aeSStefan Eßer 	}
113252884aeSStefan Eßer }
114252884aeSStefan Eßer 
11544d4804dSStefan Eßer /**
11644d4804dSStefan Eßer  * Set a number to 0 with the specified scale.
11744d4804dSStefan Eßer  * @param n      The number to set to zero.
11844d4804dSStefan Eßer  * @param scale  The scale to set the number to.
11944d4804dSStefan Eßer  */
120252884aeSStefan Eßer static void bc_num_setToZero(BcNum *restrict n, size_t scale) {
121252884aeSStefan Eßer 	assert(n != NULL);
122252884aeSStefan Eßer 	n->scale = scale;
123252884aeSStefan Eßer 	n->len = n->rdx = 0;
124252884aeSStefan Eßer }
125252884aeSStefan Eßer 
12650696a6eSStefan Eßer void bc_num_zero(BcNum *restrict n) {
127252884aeSStefan Eßer 	bc_num_setToZero(n, 0);
128252884aeSStefan Eßer }
129252884aeSStefan Eßer 
130252884aeSStefan Eßer void bc_num_one(BcNum *restrict n) {
131252884aeSStefan Eßer 	bc_num_zero(n);
132252884aeSStefan Eßer 	n->len = 1;
133252884aeSStefan Eßer 	n->num[0] = 1;
134252884aeSStefan Eßer }
135252884aeSStefan Eßer 
13644d4804dSStefan Eßer /**
13744d4804dSStefan Eßer  * "Cleans" a number, which means reducing the length if the most significant
13844d4804dSStefan Eßer  * limbs are zero.
13944d4804dSStefan Eßer  * @param n  The number to clean.
14044d4804dSStefan Eßer  */
141252884aeSStefan Eßer static void bc_num_clean(BcNum *restrict n) {
142252884aeSStefan Eßer 
14344d4804dSStefan Eßer 	// Reduce the length.
144252884aeSStefan Eßer 	while (BC_NUM_NONZERO(n) && !n->num[n->len - 1]) n->len -= 1;
145252884aeSStefan Eßer 
14644d4804dSStefan Eßer 	// Special cases.
14750696a6eSStefan Eßer 	if (BC_NUM_ZERO(n)) n->rdx = 0;
14850696a6eSStefan Eßer 	else {
14944d4804dSStefan Eßer 
15044d4804dSStefan Eßer 		// len must be at least as much as rdx.
15150696a6eSStefan Eßer 		size_t rdx = BC_NUM_RDX_VAL(n);
15250696a6eSStefan Eßer 		if (n->len < rdx) n->len = rdx;
153252884aeSStefan Eßer 	}
154252884aeSStefan Eßer }
155252884aeSStefan Eßer 
15644d4804dSStefan Eßer /**
15744d4804dSStefan Eßer  * Returns the log base 10 of @a i. I could have done this with floating-point
15844d4804dSStefan Eßer  * math, and in fact, I originally did. However, that was the only
15944d4804dSStefan Eßer  * floating-point code in the entire codebase, and I decided I didn't want any.
16044d4804dSStefan Eßer  * This is fast enough. Also, it might handle larger numbers better.
16144d4804dSStefan Eßer  * @param i  The number to return the log base 10 of.
16244d4804dSStefan Eßer  * @return   The log base 10 of @a i.
16344d4804dSStefan Eßer  */
164252884aeSStefan Eßer static size_t bc_num_log10(size_t i) {
165252884aeSStefan Eßer 	size_t len;
166252884aeSStefan Eßer 	for (len = 1; i; i /= BC_BASE, ++len);
167252884aeSStefan Eßer 	assert(len - 1 <= BC_BASE_DIGS + 1);
168252884aeSStefan Eßer 	return len - 1;
169252884aeSStefan Eßer }
170252884aeSStefan Eßer 
17144d4804dSStefan Eßer /**
17244d4804dSStefan Eßer  * Returns the number of decimal digits in a limb that are zero starting at the
17344d4804dSStefan Eßer  * most significant digits. This basically returns how much of the limb is used.
17444d4804dSStefan Eßer  * @param n  The number.
17544d4804dSStefan Eßer  * @return   The number of decimal digits that are 0 starting at the most
17644d4804dSStefan Eßer  *           significant digits.
17744d4804dSStefan Eßer  */
178252884aeSStefan Eßer static inline size_t bc_num_zeroDigits(const BcDig *n) {
179252884aeSStefan Eßer 	assert(*n >= 0);
180252884aeSStefan Eßer 	assert(((size_t) *n) < BC_BASE_POW);
181252884aeSStefan Eßer 	return BC_BASE_DIGS - bc_num_log10((size_t) *n);
182252884aeSStefan Eßer }
183252884aeSStefan Eßer 
18444d4804dSStefan Eßer /**
18544d4804dSStefan Eßer  * Return the total number of integer digits in a number. This is the opposite
18644d4804dSStefan Eßer  * of scale, like bc_num_int() is the opposite of rdx.
18744d4804dSStefan Eßer  * @param n  The number.
18844d4804dSStefan Eßer  * @return   The number of integer digits in @a n.
18944d4804dSStefan Eßer  */
190252884aeSStefan Eßer static size_t bc_num_intDigits(const BcNum *n) {
191252884aeSStefan Eßer 	size_t digits = bc_num_int(n) * BC_BASE_DIGS;
192252884aeSStefan Eßer 	if (digits > 0) digits -= bc_num_zeroDigits(n->num + n->len - 1);
193252884aeSStefan Eßer 	return digits;
194252884aeSStefan Eßer }
195252884aeSStefan Eßer 
19644d4804dSStefan Eßer /**
19744d4804dSStefan Eßer  * Returns the number of limbs of a number that are non-zero starting at the
19844d4804dSStefan Eßer  * most significant limbs. This expects that there are *no* integer limbs in the
19944d4804dSStefan Eßer  * number because it is specifically to figure out how many zero limbs after the
20044d4804dSStefan Eßer  * decimal place to ignore. If there are zero limbs after non-zero limbs, they
20144d4804dSStefan Eßer  * are counted as non-zero limbs.
20244d4804dSStefan Eßer  * @param n  The number.
20344d4804dSStefan Eßer  * @return   The number of non-zero limbs after the decimal point.
20444d4804dSStefan Eßer  */
20544d4804dSStefan Eßer static size_t bc_num_nonZeroLen(const BcNum *restrict n) {
206252884aeSStefan Eßer 	size_t i, len = n->len;
20750696a6eSStefan Eßer 	assert(len == BC_NUM_RDX_VAL(n));
208252884aeSStefan Eßer 	for (i = len - 1; i < len && !n->num[i]; --i);
209252884aeSStefan Eßer 	assert(i + 1 > 0);
210252884aeSStefan Eßer 	return i + 1;
211252884aeSStefan Eßer }
212252884aeSStefan Eßer 
21344d4804dSStefan Eßer /**
21444d4804dSStefan Eßer  * Performs a one-limb add with a carry.
21544d4804dSStefan Eßer  * @param a      The first limb.
21644d4804dSStefan Eßer  * @param b      The second limb.
21744d4804dSStefan Eßer  * @param carry  An in/out parameter; the carry in from the previous add and the
21844d4804dSStefan Eßer  *               carry out from this add.
21944d4804dSStefan Eßer  * @return       The resulting limb sum.
22044d4804dSStefan Eßer  */
221252884aeSStefan Eßer static BcDig bc_num_addDigits(BcDig a, BcDig b, bool *carry) {
222252884aeSStefan Eßer 
223252884aeSStefan Eßer 	assert(((BcBigDig) BC_BASE_POW) * 2 == ((BcDig) BC_BASE_POW) * 2);
224252884aeSStefan Eßer 	assert(a < BC_BASE_POW);
225252884aeSStefan Eßer 	assert(b < BC_BASE_POW);
226252884aeSStefan Eßer 
227252884aeSStefan Eßer 	a += b + *carry;
228252884aeSStefan Eßer 	*carry = (a >= BC_BASE_POW);
229252884aeSStefan Eßer 	if (*carry) a -= BC_BASE_POW;
230252884aeSStefan Eßer 
231252884aeSStefan Eßer 	assert(a >= 0);
232252884aeSStefan Eßer 	assert(a < BC_BASE_POW);
233252884aeSStefan Eßer 
234252884aeSStefan Eßer 	return a;
235252884aeSStefan Eßer }
236252884aeSStefan Eßer 
23744d4804dSStefan Eßer /**
23844d4804dSStefan Eßer  * Performs a one-limb subtract with a carry.
23944d4804dSStefan Eßer  * @param a      The first limb.
24044d4804dSStefan Eßer  * @param b      The second limb.
24144d4804dSStefan Eßer  * @param carry  An in/out parameter; the carry in from the previous subtract
24244d4804dSStefan Eßer  *               and the carry out from this subtract.
24344d4804dSStefan Eßer  * @return       The resulting limb difference.
24444d4804dSStefan Eßer  */
245252884aeSStefan Eßer static BcDig bc_num_subDigits(BcDig a, BcDig b, bool *carry) {
246252884aeSStefan Eßer 
247252884aeSStefan Eßer 	assert(a < BC_BASE_POW);
248252884aeSStefan Eßer 	assert(b < BC_BASE_POW);
249252884aeSStefan Eßer 
250252884aeSStefan Eßer 	b += *carry;
251252884aeSStefan Eßer 	*carry = (a < b);
252252884aeSStefan Eßer 	if (*carry) a += BC_BASE_POW;
253252884aeSStefan Eßer 
254252884aeSStefan Eßer 	assert(a - b >= 0);
255252884aeSStefan Eßer 	assert(a - b < BC_BASE_POW);
256252884aeSStefan Eßer 
257252884aeSStefan Eßer 	return a - b;
258252884aeSStefan Eßer }
259252884aeSStefan Eßer 
26044d4804dSStefan Eßer /**
26144d4804dSStefan Eßer  * Add two BcDig arrays and store the result in the first array.
26244d4804dSStefan Eßer  * @param a    The first operand and out array.
26344d4804dSStefan Eßer  * @param b    The second operand.
26444d4804dSStefan Eßer  * @param len  The length of @a b.
26544d4804dSStefan Eßer  */
266252884aeSStefan Eßer static void bc_num_addArrays(BcDig *restrict a, const BcDig *restrict b,
267252884aeSStefan Eßer                              size_t len)
268252884aeSStefan Eßer {
269252884aeSStefan Eßer 	size_t i;
270252884aeSStefan Eßer 	bool carry = false;
271252884aeSStefan Eßer 
272252884aeSStefan Eßer 	for (i = 0; i < len; ++i) a[i] = bc_num_addDigits(a[i], b[i], &carry);
273252884aeSStefan Eßer 
27444d4804dSStefan Eßer 	// Take care of the extra limbs in the bigger array.
275252884aeSStefan Eßer 	for (; carry; ++i) a[i] = bc_num_addDigits(a[i], 0, &carry);
276252884aeSStefan Eßer }
277252884aeSStefan Eßer 
27844d4804dSStefan Eßer /**
27944d4804dSStefan Eßer  * Subtract two BcDig arrays and store the result in the first array.
28044d4804dSStefan Eßer  * @param a    The first operand and out array.
28144d4804dSStefan Eßer  * @param b    The second operand.
28244d4804dSStefan Eßer  * @param len  The length of @a b.
28344d4804dSStefan Eßer  */
284252884aeSStefan Eßer static void bc_num_subArrays(BcDig *restrict a, const BcDig *restrict b,
285252884aeSStefan Eßer                              size_t len)
286252884aeSStefan Eßer {
287252884aeSStefan Eßer 	size_t i;
288252884aeSStefan Eßer 	bool carry = false;
289252884aeSStefan Eßer 
290252884aeSStefan Eßer 	for (i = 0; i < len; ++i) a[i] = bc_num_subDigits(a[i], b[i], &carry);
291252884aeSStefan Eßer 
29244d4804dSStefan Eßer 	// Take care of the extra limbs in the bigger array.
293252884aeSStefan Eßer 	for (; carry; ++i) a[i] = bc_num_subDigits(a[i], 0, &carry);
294252884aeSStefan Eßer }
295252884aeSStefan Eßer 
29644d4804dSStefan Eßer /**
29744d4804dSStefan Eßer  * Multiply a BcNum array by a one-limb number. This is a faster version of
29844d4804dSStefan Eßer  * multiplication for when we can use it.
29944d4804dSStefan Eßer  * @param a  The BcNum to multiply by the one-limb number.
30044d4804dSStefan Eßer  * @param b  The one limb of the one-limb number.
30144d4804dSStefan Eßer  * @param c  The return parameter.
30244d4804dSStefan Eßer  */
303252884aeSStefan Eßer static void bc_num_mulArray(const BcNum *restrict a, BcBigDig b,
304252884aeSStefan Eßer                             BcNum *restrict c)
305252884aeSStefan Eßer {
306252884aeSStefan Eßer 	size_t i;
307252884aeSStefan Eßer 	BcBigDig carry = 0;
308252884aeSStefan Eßer 
309252884aeSStefan Eßer 	assert(b <= BC_BASE_POW);
310252884aeSStefan Eßer 
31144d4804dSStefan Eßer 	// Make sure the return parameter is big enough.
312252884aeSStefan Eßer 	if (a->len + 1 > c->cap) bc_num_expand(c, a->len + 1);
313252884aeSStefan Eßer 
31444d4804dSStefan Eßer 	// We want the entire return parameter to be zero for cleaning later.
315252884aeSStefan Eßer 	memset(c->num, 0, BC_NUM_SIZE(c->cap));
316252884aeSStefan Eßer 
31744d4804dSStefan Eßer 	// Actual multiplication loop.
318252884aeSStefan Eßer 	for (i = 0; i < a->len; ++i) {
319252884aeSStefan Eßer 		BcBigDig in = ((BcBigDig) a->num[i]) * b + carry;
320252884aeSStefan Eßer 		c->num[i] = in % BC_BASE_POW;
321252884aeSStefan Eßer 		carry = in / BC_BASE_POW;
322252884aeSStefan Eßer 	}
323252884aeSStefan Eßer 
324252884aeSStefan Eßer 	assert(carry < BC_BASE_POW);
32544d4804dSStefan Eßer 
32644d4804dSStefan Eßer 	// Finishing touches.
327252884aeSStefan Eßer 	c->num[i] = (BcDig) carry;
328252884aeSStefan Eßer 	c->len = a->len;
329252884aeSStefan Eßer 	c->len += (carry != 0);
330252884aeSStefan Eßer 
331252884aeSStefan Eßer 	bc_num_clean(c);
332252884aeSStefan Eßer 
33344d4804dSStefan Eßer 	// Postconditions.
33450696a6eSStefan Eßer 	assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
33550696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
33650696a6eSStefan Eßer 	assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
337252884aeSStefan Eßer }
338252884aeSStefan Eßer 
33944d4804dSStefan Eßer /**
34044d4804dSStefan Eßer  * Divide a BcNum array by a one-limb number. This is a faster version of divide
34144d4804dSStefan Eßer  * for when we can use it.
34244d4804dSStefan Eßer  * @param a    The BcNum to multiply by the one-limb number.
34344d4804dSStefan Eßer  * @param b    The one limb of the one-limb number.
34444d4804dSStefan Eßer  * @param c    The return parameter for the quotient.
34544d4804dSStefan Eßer  * @param rem  The return parameter for the remainder.
34644d4804dSStefan Eßer  */
347252884aeSStefan Eßer static void bc_num_divArray(const BcNum *restrict a, BcBigDig b,
348252884aeSStefan Eßer                             BcNum *restrict c, BcBigDig *rem)
349252884aeSStefan Eßer {
350252884aeSStefan Eßer 	size_t i;
351252884aeSStefan Eßer 	BcBigDig carry = 0;
352252884aeSStefan Eßer 
353252884aeSStefan Eßer 	assert(c->cap >= a->len);
354252884aeSStefan Eßer 
35544d4804dSStefan Eßer 	// Actual division loop.
356252884aeSStefan Eßer 	for (i = a->len - 1; i < a->len; --i) {
357252884aeSStefan Eßer 		BcBigDig in = ((BcBigDig) a->num[i]) + carry * BC_BASE_POW;
358252884aeSStefan Eßer 		assert(in / b < BC_BASE_POW);
359252884aeSStefan Eßer 		c->num[i] = (BcDig) (in / b);
360252884aeSStefan Eßer 		carry = in % b;
361252884aeSStefan Eßer 	}
362252884aeSStefan Eßer 
36344d4804dSStefan Eßer 	// Finishing touches.
364252884aeSStefan Eßer 	c->len = a->len;
365252884aeSStefan Eßer 	bc_num_clean(c);
366252884aeSStefan Eßer 	*rem = carry;
367252884aeSStefan Eßer 
36844d4804dSStefan Eßer 	// Postconditions.
36950696a6eSStefan Eßer 	assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
37050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
37150696a6eSStefan Eßer 	assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
372252884aeSStefan Eßer }
373252884aeSStefan Eßer 
37444d4804dSStefan Eßer /**
37544d4804dSStefan Eßer  * Compare two BcDig arrays and return >0 if @a b is greater, <0 if @a b is
37644d4804dSStefan Eßer  * less, and 0 if equal. Both @a a and @a b must have the same length.
37744d4804dSStefan Eßer  * @param a    The first array.
37844d4804dSStefan Eßer  * @param b    The second array.
37944d4804dSStefan Eßer  * @param len  The minimum length of the arrays.
38044d4804dSStefan Eßer  */
381252884aeSStefan Eßer static ssize_t bc_num_compare(const BcDig *restrict a, const BcDig *restrict b,
382252884aeSStefan Eßer                               size_t len)
383252884aeSStefan Eßer {
384252884aeSStefan Eßer 	size_t i;
385252884aeSStefan Eßer 	BcDig c = 0;
386252884aeSStefan Eßer 	for (i = len - 1; i < len && !(c = a[i] - b[i]); --i);
387252884aeSStefan Eßer 	return bc_num_neg(i + 1, c < 0);
388252884aeSStefan Eßer }
389252884aeSStefan Eßer 
390252884aeSStefan Eßer ssize_t bc_num_cmp(const BcNum *a, const BcNum *b) {
391252884aeSStefan Eßer 
39250696a6eSStefan Eßer 	size_t i, min, a_int, b_int, diff, ardx, brdx;
393252884aeSStefan Eßer 	BcDig *max_num, *min_num;
394252884aeSStefan Eßer 	bool a_max, neg = false;
395252884aeSStefan Eßer 	ssize_t cmp;
396252884aeSStefan Eßer 
397252884aeSStefan Eßer 	assert(a != NULL && b != NULL);
398252884aeSStefan Eßer 
39944d4804dSStefan Eßer 	// Same num? Equal.
400252884aeSStefan Eßer 	if (a == b) return 0;
40144d4804dSStefan Eßer 
40244d4804dSStefan Eßer 	// Easy cases.
40350696a6eSStefan Eßer 	if (BC_NUM_ZERO(a)) return bc_num_neg(b->len != 0, !BC_NUM_NEG(b));
404252884aeSStefan Eßer 	if (BC_NUM_ZERO(b)) return bc_num_cmpZero(a);
40550696a6eSStefan Eßer 	if (BC_NUM_NEG(a)) {
40650696a6eSStefan Eßer 		if (BC_NUM_NEG(b)) neg = true;
407252884aeSStefan Eßer 		else return -1;
408252884aeSStefan Eßer 	}
40950696a6eSStefan Eßer 	else if (BC_NUM_NEG(b)) return 1;
410252884aeSStefan Eßer 
41144d4804dSStefan Eßer 	// Get the number of int limbs in each number and get the difference.
412252884aeSStefan Eßer 	a_int = bc_num_int(a);
413252884aeSStefan Eßer 	b_int = bc_num_int(b);
414252884aeSStefan Eßer 	a_int -= b_int;
415252884aeSStefan Eßer 
41644d4804dSStefan Eßer 	// If there's a difference, then just return the comparison.
417252884aeSStefan Eßer 	if (a_int) return neg ? -((ssize_t) a_int) : (ssize_t) a_int;
418252884aeSStefan Eßer 
41944d4804dSStefan Eßer 	// Get the rdx's and figure out the max.
42050696a6eSStefan Eßer 	ardx = BC_NUM_RDX_VAL(a);
42150696a6eSStefan Eßer 	brdx = BC_NUM_RDX_VAL(b);
42250696a6eSStefan Eßer 	a_max = (ardx > brdx);
423252884aeSStefan Eßer 
42444d4804dSStefan Eßer 	// Set variables based on the above.
425252884aeSStefan Eßer 	if (a_max) {
42650696a6eSStefan Eßer 		min = brdx;
42750696a6eSStefan Eßer 		diff = ardx - brdx;
428252884aeSStefan Eßer 		max_num = a->num + diff;
429252884aeSStefan Eßer 		min_num = b->num;
430252884aeSStefan Eßer 	}
431252884aeSStefan Eßer 	else {
43250696a6eSStefan Eßer 		min = ardx;
43350696a6eSStefan Eßer 		diff = brdx - ardx;
434252884aeSStefan Eßer 		max_num = b->num + diff;
435252884aeSStefan Eßer 		min_num = a->num;
436252884aeSStefan Eßer 	}
437252884aeSStefan Eßer 
43844d4804dSStefan Eßer 	// Do a full limb-by-limb comparison.
439252884aeSStefan Eßer 	cmp = bc_num_compare(max_num, min_num, b_int + min);
440252884aeSStefan Eßer 
44144d4804dSStefan Eßer 	// If we found a difference, return it based on state.
442252884aeSStefan Eßer 	if (cmp) return bc_num_neg((size_t) cmp, !a_max == !neg);
443252884aeSStefan Eßer 
44444d4804dSStefan Eßer 	// If there was no difference, then the final step is to check which number
44544d4804dSStefan Eßer 	// has greater or lesser limbs beyond the other's.
446252884aeSStefan Eßer 	for (max_num -= diff, i = diff - 1; i < diff; --i) {
447252884aeSStefan Eßer 		if (max_num[i]) return bc_num_neg(1, !a_max == !neg);
448252884aeSStefan Eßer 	}
449252884aeSStefan Eßer 
450252884aeSStefan Eßer 	return 0;
451252884aeSStefan Eßer }
452252884aeSStefan Eßer 
453252884aeSStefan Eßer void bc_num_truncate(BcNum *restrict n, size_t places) {
454252884aeSStefan Eßer 
45550696a6eSStefan Eßer 	size_t nrdx, places_rdx;
456252884aeSStefan Eßer 
457252884aeSStefan Eßer 	if (!places) return;
458252884aeSStefan Eßer 
45944d4804dSStefan Eßer 	// Grab these needed values; places_rdx is the rdx equivalent to places like
46044d4804dSStefan Eßer 	// rdx is to scale.
46150696a6eSStefan Eßer 	nrdx = BC_NUM_RDX_VAL(n);
46250696a6eSStefan Eßer 	places_rdx = nrdx ? nrdx - BC_NUM_RDX(n->scale - places) : 0;
46344d4804dSStefan Eßer 
46444d4804dSStefan Eßer 	// We cannot truncate more places than we have.
465252884aeSStefan Eßer 	assert(places <= n->scale && (BC_NUM_ZERO(n) || places_rdx <= n->len));
466252884aeSStefan Eßer 
467252884aeSStefan Eßer 	n->scale -= places;
46850696a6eSStefan Eßer 	BC_NUM_RDX_SET(n, nrdx - places_rdx);
469252884aeSStefan Eßer 
47044d4804dSStefan Eßer 	// Only when the number is nonzero do we need to do the hard stuff.
471252884aeSStefan Eßer 	if (BC_NUM_NONZERO(n)) {
472252884aeSStefan Eßer 
473252884aeSStefan Eßer 		size_t pow;
474252884aeSStefan Eßer 
47544d4804dSStefan Eßer 		// This calculates how many decimal digits are in the least significant
47644d4804dSStefan Eßer 		// limb.
477252884aeSStefan Eßer 		pow = n->scale % BC_BASE_DIGS;
478252884aeSStefan Eßer 		pow = pow ? BC_BASE_DIGS - pow : 0;
479252884aeSStefan Eßer 		pow = bc_num_pow10[pow];
480252884aeSStefan Eßer 
481252884aeSStefan Eßer 		n->len -= places_rdx;
48244d4804dSStefan Eßer 
48344d4804dSStefan Eßer 		// We have to move limbs to maintain invariants. The limbs must begin at
48444d4804dSStefan Eßer 		// the beginning of the BcNum array.
485252884aeSStefan Eßer 		memmove(n->num, n->num + places_rdx, BC_NUM_SIZE(n->len));
486252884aeSStefan Eßer 
487252884aeSStefan Eßer 		// Clear the lower part of the last digit.
488252884aeSStefan Eßer 		if (BC_NUM_NONZERO(n)) n->num[0] -= n->num[0] % (BcDig) pow;
489252884aeSStefan Eßer 
490252884aeSStefan Eßer 		bc_num_clean(n);
491252884aeSStefan Eßer 	}
492252884aeSStefan Eßer }
493252884aeSStefan Eßer 
49450696a6eSStefan Eßer void bc_num_extend(BcNum *restrict n, size_t places) {
495252884aeSStefan Eßer 
49650696a6eSStefan Eßer 	size_t nrdx, places_rdx;
497252884aeSStefan Eßer 
498252884aeSStefan Eßer 	if (!places) return;
49944d4804dSStefan Eßer 
50044d4804dSStefan Eßer 	// Easy case with zero; set the scale.
501252884aeSStefan Eßer 	if (BC_NUM_ZERO(n)) {
502252884aeSStefan Eßer 		n->scale += places;
503252884aeSStefan Eßer 		return;
504252884aeSStefan Eßer 	}
505252884aeSStefan Eßer 
50644d4804dSStefan Eßer 	// Grab these needed values; places_rdx is the rdx equivalent to places like
50744d4804dSStefan Eßer 	// rdx is to scale.
50850696a6eSStefan Eßer 	nrdx = BC_NUM_RDX_VAL(n);
50950696a6eSStefan Eßer 	places_rdx = BC_NUM_RDX(places + n->scale) - nrdx;
510252884aeSStefan Eßer 
51144d4804dSStefan Eßer 	// This is the hard case. We need to expand the number, move the limbs, and
51244d4804dSStefan Eßer 	// set the limbs that were just cleared.
513252884aeSStefan Eßer 	if (places_rdx) {
514252884aeSStefan Eßer 		bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));
515252884aeSStefan Eßer 		memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len));
516252884aeSStefan Eßer 		memset(n->num, 0, BC_NUM_SIZE(places_rdx));
517252884aeSStefan Eßer 	}
518252884aeSStefan Eßer 
51944d4804dSStefan Eßer 	// Finally, set scale and rdx.
52050696a6eSStefan Eßer 	BC_NUM_RDX_SET(n, nrdx + places_rdx);
521252884aeSStefan Eßer 	n->scale += places;
522252884aeSStefan Eßer 	n->len += places_rdx;
523252884aeSStefan Eßer 
52450696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale));
525252884aeSStefan Eßer }
526252884aeSStefan Eßer 
52744d4804dSStefan Eßer /**
52844d4804dSStefan Eßer  * Retires (finishes) a multiplication or division operation.
52944d4804dSStefan Eßer  */
530252884aeSStefan Eßer static void bc_num_retireMul(BcNum *restrict n, size_t scale,
531252884aeSStefan Eßer                              bool neg1, bool neg2)
532252884aeSStefan Eßer {
53344d4804dSStefan Eßer 	// Make sure scale is correct.
534252884aeSStefan Eßer 	if (n->scale < scale) bc_num_extend(n, scale - n->scale);
535252884aeSStefan Eßer 	else bc_num_truncate(n, n->scale - scale);
536252884aeSStefan Eßer 
537252884aeSStefan Eßer 	bc_num_clean(n);
53844d4804dSStefan Eßer 
53944d4804dSStefan Eßer 	// We need to ensure rdx is correct.
54050696a6eSStefan Eßer 	if (BC_NUM_NONZERO(n)) n->rdx = BC_NUM_NEG_VAL(n, !neg1 != !neg2);
541252884aeSStefan Eßer }
542252884aeSStefan Eßer 
54344d4804dSStefan Eßer /**
54444d4804dSStefan Eßer  * Splits a number into two BcNum's. This is used in Karatsuba.
54544d4804dSStefan Eßer  * @param n    The number to split.
54644d4804dSStefan Eßer  * @param idx  The index to split at.
54744d4804dSStefan Eßer  * @param a    An out parameter; the low part of @a n.
54844d4804dSStefan Eßer  * @param b    An out parameter; the high part of @a n.
54944d4804dSStefan Eßer  */
550252884aeSStefan Eßer static void bc_num_split(const BcNum *restrict n, size_t idx,
551252884aeSStefan Eßer                          BcNum *restrict a, BcNum *restrict b)
552252884aeSStefan Eßer {
55344d4804dSStefan Eßer 	// We want a and b to be clear.
554252884aeSStefan Eßer 	assert(BC_NUM_ZERO(a));
555252884aeSStefan Eßer 	assert(BC_NUM_ZERO(b));
556252884aeSStefan Eßer 
55744d4804dSStefan Eßer 	// The usual case.
558252884aeSStefan Eßer 	if (idx < n->len) {
559252884aeSStefan Eßer 
56044d4804dSStefan Eßer 		// Set the fields first.
561252884aeSStefan Eßer 		b->len = n->len - idx;
562252884aeSStefan Eßer 		a->len = idx;
56350696a6eSStefan Eßer 		a->scale = b->scale = 0;
56450696a6eSStefan Eßer 		BC_NUM_RDX_SET(a, 0);
56550696a6eSStefan Eßer 		BC_NUM_RDX_SET(b, 0);
566252884aeSStefan Eßer 
567252884aeSStefan Eßer 		assert(a->cap >= a->len);
568252884aeSStefan Eßer 		assert(b->cap >= b->len);
569252884aeSStefan Eßer 
57044d4804dSStefan Eßer 		// Copy the arrays. This is not necessary for safety, but it is faster,
57144d4804dSStefan Eßer 		// for some reason.
572252884aeSStefan Eßer 		memcpy(b->num, n->num + idx, BC_NUM_SIZE(b->len));
573252884aeSStefan Eßer 		memcpy(a->num, n->num, BC_NUM_SIZE(idx));
574252884aeSStefan Eßer 
575252884aeSStefan Eßer 		bc_num_clean(b);
576252884aeSStefan Eßer 	}
57744d4804dSStefan Eßer 	// If the index is weird, just skip the split.
578252884aeSStefan Eßer 	else bc_num_copy(a, n);
579252884aeSStefan Eßer 
580252884aeSStefan Eßer 	bc_num_clean(a);
581252884aeSStefan Eßer }
582252884aeSStefan Eßer 
58344d4804dSStefan Eßer /**
58444d4804dSStefan Eßer  * Copies a number into another, but shifts the rdx so that the result number
58544d4804dSStefan Eßer  * only sees the integer part of the source number.
58644d4804dSStefan Eßer  * @param n  The number to copy.
58744d4804dSStefan Eßer  * @param r  The result number with a shifted rdx, len, and num.
58844d4804dSStefan Eßer  */
58944d4804dSStefan Eßer static void bc_num_shiftRdx(const BcNum *restrict n, BcNum *restrict r) {
59044d4804dSStefan Eßer 
59144d4804dSStefan Eßer 	size_t rdx = BC_NUM_RDX_VAL(n);
59244d4804dSStefan Eßer 
59344d4804dSStefan Eßer 	r->len = n->len - rdx;
59444d4804dSStefan Eßer 	r->cap = n->cap - rdx;
59544d4804dSStefan Eßer 	r->num = n->num + rdx;
59644d4804dSStefan Eßer 
59744d4804dSStefan Eßer 	BC_NUM_RDX_SET_NEG(r, 0, BC_NUM_NEG(n));
59844d4804dSStefan Eßer 	r->scale = 0;
59944d4804dSStefan Eßer }
60044d4804dSStefan Eßer 
60144d4804dSStefan Eßer /**
60244d4804dSStefan Eßer  * Shifts a number so that all of the least significant limbs of the number are
60344d4804dSStefan Eßer  * skipped. This must be undone by bc_num_unshiftZero().
60444d4804dSStefan Eßer  * @param n  The number to shift.
60544d4804dSStefan Eßer  */
606252884aeSStefan Eßer static size_t bc_num_shiftZero(BcNum *restrict n) {
607252884aeSStefan Eßer 
608252884aeSStefan Eßer 	size_t i;
609252884aeSStefan Eßer 
61044d4804dSStefan Eßer 	// If we don't have an integer, that is a problem, but it's also a bug
61144d4804dSStefan Eßer 	// because the caller should have set everything up right.
61250696a6eSStefan Eßer 	assert(!BC_NUM_RDX_VAL(n) || BC_NUM_ZERO(n));
613252884aeSStefan Eßer 
614252884aeSStefan Eßer 	for (i = 0; i < n->len && !n->num[i]; ++i);
615252884aeSStefan Eßer 
616252884aeSStefan Eßer 	n->len -= i;
617252884aeSStefan Eßer 	n->num += i;
618252884aeSStefan Eßer 
619252884aeSStefan Eßer 	return i;
620252884aeSStefan Eßer }
621252884aeSStefan Eßer 
62244d4804dSStefan Eßer /**
62344d4804dSStefan Eßer  * Undo the damage done by bc_num_unshiftZero(). This must be called like all
62444d4804dSStefan Eßer  * cleanup functions: after a label used by setjmp() and longjmp().
62544d4804dSStefan Eßer  * @param n           The number to unshift.
62644d4804dSStefan Eßer  * @param places_rdx  The amount the number was originally shift.
62744d4804dSStefan Eßer  */
628252884aeSStefan Eßer static void bc_num_unshiftZero(BcNum *restrict n, size_t places_rdx) {
629252884aeSStefan Eßer 	n->len += places_rdx;
630252884aeSStefan Eßer 	n->num -= places_rdx;
631252884aeSStefan Eßer }
632252884aeSStefan Eßer 
63344d4804dSStefan Eßer /**
63444d4804dSStefan Eßer  * Shifts the digits right within a number by no more than BC_BASE_DIGS - 1.
63544d4804dSStefan Eßer  * This is the final step on shifting numbers with the shift operators. It
63644d4804dSStefan Eßer  * depends on the caller to shift the limbs properly because all it does is
63744d4804dSStefan Eßer  * ensure that the rdx point is realigned to be between limbs.
63844d4804dSStefan Eßer  * @param n    The number to shift digits in.
63944d4804dSStefan Eßer  * @param dig  The number of places to shift right.
64044d4804dSStefan Eßer  */
641252884aeSStefan Eßer static void bc_num_shift(BcNum *restrict n, BcBigDig dig) {
642252884aeSStefan Eßer 
643252884aeSStefan Eßer 	size_t i, len = n->len;
644252884aeSStefan Eßer 	BcBigDig carry = 0, pow;
645252884aeSStefan Eßer 	BcDig *ptr = n->num;
646252884aeSStefan Eßer 
647252884aeSStefan Eßer 	assert(dig < BC_BASE_DIGS);
648252884aeSStefan Eßer 
64944d4804dSStefan Eßer 	// Figure out the parameters for division.
650252884aeSStefan Eßer 	pow = bc_num_pow10[dig];
651252884aeSStefan Eßer 	dig = bc_num_pow10[BC_BASE_DIGS - dig];
652252884aeSStefan Eßer 
65344d4804dSStefan Eßer 	// Run a series of divisions and mods with carries across the entire number
65444d4804dSStefan Eßer 	// array. This effectively shifts everything over.
655252884aeSStefan Eßer 	for (i = len - 1; i < len; --i) {
656252884aeSStefan Eßer 		BcBigDig in, temp;
657252884aeSStefan Eßer 		in = ((BcBigDig) ptr[i]);
658252884aeSStefan Eßer 		temp = carry * dig;
659252884aeSStefan Eßer 		carry = in % pow;
660252884aeSStefan Eßer 		ptr[i] = ((BcDig) (in / pow)) + (BcDig) temp;
661252884aeSStefan Eßer 	}
662252884aeSStefan Eßer 
663252884aeSStefan Eßer 	assert(!carry);
664252884aeSStefan Eßer }
665252884aeSStefan Eßer 
66644d4804dSStefan Eßer /**
66744d4804dSStefan Eßer  * Shift a number left by a certain number of places. This is the workhorse of
66844d4804dSStefan Eßer  * the left shift operator.
66944d4804dSStefan Eßer  * @param n       The number to shift left.
67044d4804dSStefan Eßer  * @param places  The amount of places to shift @a n left by.
67144d4804dSStefan Eßer  */
672252884aeSStefan Eßer static void bc_num_shiftLeft(BcNum *restrict n, size_t places) {
673252884aeSStefan Eßer 
674252884aeSStefan Eßer 	BcBigDig dig;
675252884aeSStefan Eßer 	size_t places_rdx;
676252884aeSStefan Eßer 	bool shift;
677252884aeSStefan Eßer 
678252884aeSStefan Eßer 	if (!places) return;
67944d4804dSStefan Eßer 
68044d4804dSStefan Eßer 	// Make sure to grow the number if necessary.
681252884aeSStefan Eßer 	if (places > n->scale) {
682252884aeSStefan Eßer 		size_t size = bc_vm_growSize(BC_NUM_RDX(places - n->scale), n->len);
68344d4804dSStefan Eßer 		if (size > SIZE_MAX - 1) bc_err(BC_ERR_MATH_OVERFLOW);
684252884aeSStefan Eßer 	}
68544d4804dSStefan Eßer 
68644d4804dSStefan Eßer 	// If zero, we can just set the scale and bail.
687252884aeSStefan Eßer 	if (BC_NUM_ZERO(n)) {
688252884aeSStefan Eßer 		if (n->scale >= places) n->scale -= places;
689252884aeSStefan Eßer 		else n->scale = 0;
690252884aeSStefan Eßer 		return;
691252884aeSStefan Eßer 	}
692252884aeSStefan Eßer 
69344d4804dSStefan Eßer 	// When I changed bc to have multiple digits per limb, this was the hardest
69444d4804dSStefan Eßer 	// code to change. This and shift right. Make sure you understand this
69544d4804dSStefan Eßer 	// before attempting anything.
69644d4804dSStefan Eßer 
69744d4804dSStefan Eßer 	// This is how many limbs we will shift.
698252884aeSStefan Eßer 	dig = (BcBigDig) (places % BC_BASE_DIGS);
699252884aeSStefan Eßer 	shift = (dig != 0);
70044d4804dSStefan Eßer 
70144d4804dSStefan Eßer 	// Convert places to a rdx value.
702252884aeSStefan Eßer 	places_rdx = BC_NUM_RDX(places);
703252884aeSStefan Eßer 
70444d4804dSStefan Eßer 	// If the number is not an integer, we need special care. The reason an
70544d4804dSStefan Eßer 	// integer doesn't is because left shift would only extend the integer,
70644d4804dSStefan Eßer 	// whereas a non-integer might have its fractional part eliminated or only
70744d4804dSStefan Eßer 	// partially eliminated.
708252884aeSStefan Eßer 	if (n->scale) {
709252884aeSStefan Eßer 
71050696a6eSStefan Eßer 		size_t nrdx = BC_NUM_RDX_VAL(n);
71150696a6eSStefan Eßer 
71244d4804dSStefan Eßer 		// If the number's rdx is bigger, that's the hard case.
71350696a6eSStefan Eßer 		if (nrdx >= places_rdx) {
714252884aeSStefan Eßer 
715252884aeSStefan Eßer 			size_t mod = n->scale % BC_BASE_DIGS, revdig;
716252884aeSStefan Eßer 
71744d4804dSStefan Eßer 			// We want mod to be in the range [1, BC_BASE_DIGS], not
71844d4804dSStefan Eßer 			// [0, BC_BASE_DIGS).
719252884aeSStefan Eßer 			mod = mod ? mod : BC_BASE_DIGS;
72044d4804dSStefan Eßer 
72144d4804dSStefan Eßer 			// We need to reverse dig to get the actual number of digits.
722252884aeSStefan Eßer 			revdig = dig ? BC_BASE_DIGS - dig : 0;
723252884aeSStefan Eßer 
72444d4804dSStefan Eßer 			// If the two overflow BC_BASE_DIGS, we need to move an extra place.
725252884aeSStefan Eßer 			if (mod + revdig > BC_BASE_DIGS) places_rdx = 1;
726252884aeSStefan Eßer 			else places_rdx = 0;
727252884aeSStefan Eßer 		}
72850696a6eSStefan Eßer 		else places_rdx -= nrdx;
729252884aeSStefan Eßer 	}
730252884aeSStefan Eßer 
73144d4804dSStefan Eßer 	// If this is non-zero, we need an extra place, so expand, move, and set.
732252884aeSStefan Eßer 	if (places_rdx) {
733252884aeSStefan Eßer 		bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));
734252884aeSStefan Eßer 		memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len));
735252884aeSStefan Eßer 		memset(n->num, 0, BC_NUM_SIZE(places_rdx));
736252884aeSStefan Eßer 		n->len += places_rdx;
737252884aeSStefan Eßer 	}
738252884aeSStefan Eßer 
73944d4804dSStefan Eßer 	// Set the scale appropriately.
74050696a6eSStefan Eßer 	if (places > n->scale) {
74150696a6eSStefan Eßer 		n->scale = 0;
74250696a6eSStefan Eßer 		BC_NUM_RDX_SET(n, 0);
74350696a6eSStefan Eßer 	}
744252884aeSStefan Eßer 	else {
745252884aeSStefan Eßer 		n->scale -= places;
74650696a6eSStefan Eßer 		BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
747252884aeSStefan Eßer 	}
748252884aeSStefan Eßer 
74944d4804dSStefan Eßer 	// Finally, shift within limbs.
750252884aeSStefan Eßer 	if (shift) bc_num_shift(n, BC_BASE_DIGS - dig);
751252884aeSStefan Eßer 
752252884aeSStefan Eßer 	bc_num_clean(n);
753252884aeSStefan Eßer }
754252884aeSStefan Eßer 
75550696a6eSStefan Eßer void bc_num_shiftRight(BcNum *restrict n, size_t places) {
756252884aeSStefan Eßer 
757252884aeSStefan Eßer 	BcBigDig dig;
758252884aeSStefan Eßer 	size_t places_rdx, scale, scale_mod, int_len, expand;
759252884aeSStefan Eßer 	bool shift;
760252884aeSStefan Eßer 
761252884aeSStefan Eßer 	if (!places) return;
76244d4804dSStefan Eßer 
76344d4804dSStefan Eßer 	// If zero, we can just set the scale and bail.
764252884aeSStefan Eßer 	if (BC_NUM_ZERO(n)) {
765252884aeSStefan Eßer 		n->scale += places;
766252884aeSStefan Eßer 		bc_num_expand(n, BC_NUM_RDX(n->scale));
767252884aeSStefan Eßer 		return;
768252884aeSStefan Eßer 	}
769252884aeSStefan Eßer 
77044d4804dSStefan Eßer 	// Amount within a limb we have to shift by.
771252884aeSStefan Eßer 	dig = (BcBigDig) (places % BC_BASE_DIGS);
772252884aeSStefan Eßer 	shift = (dig != 0);
77344d4804dSStefan Eßer 
774252884aeSStefan Eßer 	scale = n->scale;
77544d4804dSStefan Eßer 
77644d4804dSStefan Eßer 	// Figure out how the scale is affected.
777252884aeSStefan Eßer 	scale_mod = scale % BC_BASE_DIGS;
778252884aeSStefan Eßer 	scale_mod = scale_mod ? scale_mod : BC_BASE_DIGS;
77944d4804dSStefan Eßer 
78044d4804dSStefan Eßer 	// We need to know the int length and rdx for places.
781252884aeSStefan Eßer 	int_len = bc_num_int(n);
782252884aeSStefan Eßer 	places_rdx = BC_NUM_RDX(places);
783252884aeSStefan Eßer 
78444d4804dSStefan Eßer 	// If we are going to shift past a limb boundary or not, set accordingly.
785252884aeSStefan Eßer 	if (scale_mod + dig > BC_BASE_DIGS) {
786252884aeSStefan Eßer 		expand = places_rdx - 1;
787252884aeSStefan Eßer 		places_rdx = 1;
788252884aeSStefan Eßer 	}
789252884aeSStefan Eßer 	else {
790252884aeSStefan Eßer 		expand = places_rdx;
791252884aeSStefan Eßer 		places_rdx = 0;
792252884aeSStefan Eßer 	}
793252884aeSStefan Eßer 
79444d4804dSStefan Eßer 	// Clamp expanding.
795252884aeSStefan Eßer 	if (expand > int_len) expand -= int_len;
796252884aeSStefan Eßer 	else expand = 0;
797252884aeSStefan Eßer 
79844d4804dSStefan Eßer 	// Extend, expand, and zero.
799252884aeSStefan Eßer 	bc_num_extend(n, places_rdx * BC_BASE_DIGS);
800252884aeSStefan Eßer 	bc_num_expand(n, bc_vm_growSize(expand, n->len));
801252884aeSStefan Eßer 	memset(n->num + n->len, 0, BC_NUM_SIZE(expand));
80244d4804dSStefan Eßer 
80344d4804dSStefan Eßer 	// Set the fields.
804252884aeSStefan Eßer 	n->len += expand;
80550696a6eSStefan Eßer 	n->scale = 0;
80650696a6eSStefan Eßer 	BC_NUM_RDX_SET(n, 0);
807252884aeSStefan Eßer 
80844d4804dSStefan Eßer 	// Finally, shift within limbs.
809252884aeSStefan Eßer 	if (shift) bc_num_shift(n, dig);
810252884aeSStefan Eßer 
811252884aeSStefan Eßer 	n->scale = scale + places;
81250696a6eSStefan Eßer 	BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
813252884aeSStefan Eßer 
814252884aeSStefan Eßer 	bc_num_clean(n);
815252884aeSStefan Eßer 
81650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(n) <= n->len && n->len <= n->cap);
81750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale));
818252884aeSStefan Eßer }
819252884aeSStefan Eßer 
82044d4804dSStefan Eßer /**
82144d4804dSStefan Eßer  * Invert @a into @a b at the current scale.
82244d4804dSStefan Eßer  * @param a      The number to invert.
82344d4804dSStefan Eßer  * @param b      The return parameter. This must be preallocated.
82444d4804dSStefan Eßer  * @param scale  The current scale.
82544d4804dSStefan Eßer  */
82644d4804dSStefan Eßer static inline void bc_num_inv(BcNum *a, BcNum *b, size_t scale) {
827252884aeSStefan Eßer 	assert(BC_NUM_NONZERO(a));
82844d4804dSStefan Eßer 	bc_num_div(&vm.one, a, b, scale);
82944d4804dSStefan Eßer }
830252884aeSStefan Eßer 
83144d4804dSStefan Eßer /**
83244d4804dSStefan Eßer  * Tests if a number is a integer with scale or not. Returns true if the number
83344d4804dSStefan Eßer  * is not an integer. If it is, its integer shifted form is copied into the
83444d4804dSStefan Eßer  * result parameter for use where only integers are allowed.
83544d4804dSStefan Eßer  * @param n  The integer to test and shift.
83644d4804dSStefan Eßer  * @param r  The number to store the shifted result into. This number should
83744d4804dSStefan Eßer  *           *not* be allocated.
83844d4804dSStefan Eßer  * @return   True if the number is a non-integer, false otherwise.
83944d4804dSStefan Eßer  */
84044d4804dSStefan Eßer static bool bc_num_nonInt(const BcNum *restrict n, BcNum *restrict r) {
841252884aeSStefan Eßer 
84244d4804dSStefan Eßer 	bool zero;
84344d4804dSStefan Eßer 	size_t i, rdx = BC_NUM_RDX_VAL(n);
84444d4804dSStefan Eßer 
84544d4804dSStefan Eßer 	if (!rdx) {
84644d4804dSStefan Eßer 		memcpy(r, n, sizeof(BcNum));
84744d4804dSStefan Eßer 		return false;
84844d4804dSStefan Eßer 	}
84944d4804dSStefan Eßer 
85044d4804dSStefan Eßer 	zero = true;
85144d4804dSStefan Eßer 
85244d4804dSStefan Eßer 	for (i = 0; zero && i < rdx; ++i) zero = (n->num[i] == 0);
85344d4804dSStefan Eßer 
85444d4804dSStefan Eßer 	if (BC_ERR(!zero)) return true;
85544d4804dSStefan Eßer 
85644d4804dSStefan Eßer 	bc_num_shiftRdx(n, r);
85744d4804dSStefan Eßer 
85844d4804dSStefan Eßer 	return false;
859252884aeSStefan Eßer }
860252884aeSStefan Eßer 
861252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
86244d4804dSStefan Eßer 
86344d4804dSStefan Eßer /**
86444d4804dSStefan Eßer  * Execute common code for an operater that needs an integer for the second
86544d4804dSStefan Eßer  * operand and return the integer operand as a BcBigDig.
86644d4804dSStefan Eßer  * @param a  The first operand.
86744d4804dSStefan Eßer  * @param b  The second operand.
86844d4804dSStefan Eßer  * @param c  The result operand.
86944d4804dSStefan Eßer  * @return   The second operand as a hardware integer.
87044d4804dSStefan Eßer  */
87144d4804dSStefan Eßer static BcBigDig bc_num_intop(const BcNum *a, const BcNum *b, BcNum *restrict c)
872252884aeSStefan Eßer {
87344d4804dSStefan Eßer 	BcNum temp;
87444d4804dSStefan Eßer 
87544d4804dSStefan Eßer 	if (BC_ERR(bc_num_nonInt(b, &temp))) bc_err(BC_ERR_MATH_NON_INTEGER);
87644d4804dSStefan Eßer 
877252884aeSStefan Eßer 	bc_num_copy(c, a);
87844d4804dSStefan Eßer 
87944d4804dSStefan Eßer 	return bc_num_bigdig(&temp);
880252884aeSStefan Eßer }
881252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
882252884aeSStefan Eßer 
88344d4804dSStefan Eßer /**
88444d4804dSStefan Eßer  * This is the actual implementation of add *and* subtract. Since this function
88544d4804dSStefan Eßer  * doesn't need to use scale (per the bc spec), I am hijacking it to say whether
88644d4804dSStefan Eßer  * it's doing an add or a subtract. And then I convert substraction to addition
88744d4804dSStefan Eßer  * of negative second operand. This is a BcNumBinOp function.
88844d4804dSStefan Eßer  * @param a    The first operand.
88944d4804dSStefan Eßer  * @param b    The second operand.
89044d4804dSStefan Eßer  * @param c    The return parameter.
89144d4804dSStefan Eßer  * @param sub  Non-zero for a subtract, zero for an add.
89244d4804dSStefan Eßer  */
893252884aeSStefan Eßer static void bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) {
894252884aeSStefan Eßer 
895252884aeSStefan Eßer 	BcDig *ptr_c, *ptr_l, *ptr_r;
896252884aeSStefan Eßer 	size_t i, min_rdx, max_rdx, diff, a_int, b_int, min_len, max_len, max_int;
89750696a6eSStefan Eßer 	size_t len_l, len_r, ardx, brdx;
89850696a6eSStefan Eßer 	bool b_neg, do_sub, do_rev_sub, carry, c_neg;
899252884aeSStefan Eßer 
900252884aeSStefan Eßer 	if (BC_NUM_ZERO(b)) {
901252884aeSStefan Eßer 		bc_num_copy(c, a);
902252884aeSStefan Eßer 		return;
903252884aeSStefan Eßer 	}
90444d4804dSStefan Eßer 
905252884aeSStefan Eßer 	if (BC_NUM_ZERO(a)) {
906252884aeSStefan Eßer 		bc_num_copy(c, b);
90750696a6eSStefan Eßer 		c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(b) != sub);
908252884aeSStefan Eßer 		return;
909252884aeSStefan Eßer 	}
910252884aeSStefan Eßer 
911252884aeSStefan Eßer 	// Invert sign of b if it is to be subtracted. This operation must
91244d4804dSStefan Eßer 	// precede the tests for any of the operands being zero.
91350696a6eSStefan Eßer 	b_neg = (BC_NUM_NEG(b) != sub);
914252884aeSStefan Eßer 
91544d4804dSStefan Eßer 	// Figure out if we will actually add the numbers if their signs are equal
91644d4804dSStefan Eßer 	// or subtract.
91750696a6eSStefan Eßer 	do_sub = (BC_NUM_NEG(a) != b_neg);
918252884aeSStefan Eßer 
919252884aeSStefan Eßer 	a_int = bc_num_int(a);
920252884aeSStefan Eßer 	b_int = bc_num_int(b);
921252884aeSStefan Eßer 	max_int = BC_MAX(a_int, b_int);
922252884aeSStefan Eßer 
92344d4804dSStefan Eßer 	// Figure out which number will have its last limbs copied (for addition) or
92444d4804dSStefan Eßer 	// subtracted (for subtraction).
92550696a6eSStefan Eßer 	ardx = BC_NUM_RDX_VAL(a);
92650696a6eSStefan Eßer 	brdx = BC_NUM_RDX_VAL(b);
92750696a6eSStefan Eßer 	min_rdx = BC_MIN(ardx, brdx);
92850696a6eSStefan Eßer 	max_rdx = BC_MAX(ardx, brdx);
929252884aeSStefan Eßer 	diff = max_rdx - min_rdx;
930252884aeSStefan Eßer 
931252884aeSStefan Eßer 	max_len = max_int + max_rdx;
932252884aeSStefan Eßer 
933252884aeSStefan Eßer 	if (do_sub) {
934252884aeSStefan Eßer 
935252884aeSStefan Eßer 		// Check whether b has to be subtracted from a or a from b.
936252884aeSStefan Eßer 		if (a_int != b_int) do_rev_sub = (a_int < b_int);
93750696a6eSStefan Eßer 		else if (ardx > brdx)
938252884aeSStefan Eßer 			do_rev_sub = (bc_num_compare(a->num + diff, b->num, b->len) < 0);
939252884aeSStefan Eßer 		else
940252884aeSStefan Eßer 			do_rev_sub = (bc_num_compare(a->num, b->num + diff, a->len) <= 0);
941252884aeSStefan Eßer 	}
942252884aeSStefan Eßer 	else {
943252884aeSStefan Eßer 
944252884aeSStefan Eßer 		// The result array of the addition might come out one element
945252884aeSStefan Eßer 		// longer than the bigger of the operand arrays.
946252884aeSStefan Eßer 		max_len += 1;
947252884aeSStefan Eßer 		do_rev_sub = (a_int < b_int);
948252884aeSStefan Eßer 	}
949252884aeSStefan Eßer 
950252884aeSStefan Eßer 	assert(max_len <= c->cap);
951252884aeSStefan Eßer 
95244d4804dSStefan Eßer 	// Cache values for simple code later.
953252884aeSStefan Eßer 	if (do_rev_sub) {
954252884aeSStefan Eßer 		ptr_l = b->num;
955252884aeSStefan Eßer 		ptr_r = a->num;
956252884aeSStefan Eßer 		len_l = b->len;
957252884aeSStefan Eßer 		len_r = a->len;
958252884aeSStefan Eßer 	}
959252884aeSStefan Eßer 	else {
960252884aeSStefan Eßer 		ptr_l = a->num;
961252884aeSStefan Eßer 		ptr_r = b->num;
962252884aeSStefan Eßer 		len_l = a->len;
963252884aeSStefan Eßer 		len_r = b->len;
964252884aeSStefan Eßer 	}
965252884aeSStefan Eßer 
966252884aeSStefan Eßer 	ptr_c = c->num;
967252884aeSStefan Eßer 	carry = false;
968252884aeSStefan Eßer 
96944d4804dSStefan Eßer 	// This is true if the numbers have a different number of limbs after the
97044d4804dSStefan Eßer 	// decimal point.
971252884aeSStefan Eßer 	if (diff) {
972252884aeSStefan Eßer 
973252884aeSStefan Eßer 		// If the rdx values of the operands do not match, the result will
974252884aeSStefan Eßer 		// have low end elements that are the positive or negative trailing
975252884aeSStefan Eßer 		// elements of the operand with higher rdx value.
97650696a6eSStefan Eßer 		if ((ardx > brdx) != do_rev_sub) {
977252884aeSStefan Eßer 
97850696a6eSStefan Eßer 			// !do_rev_sub && ardx > brdx || do_rev_sub && brdx > ardx
979252884aeSStefan Eßer 			// The left operand has BcDig values that need to be copied,
980252884aeSStefan Eßer 			// either from a or from b (in case of a reversed subtraction).
981252884aeSStefan Eßer 			memcpy(ptr_c, ptr_l, BC_NUM_SIZE(diff));
982252884aeSStefan Eßer 			ptr_l += diff;
983252884aeSStefan Eßer 			len_l -= diff;
984252884aeSStefan Eßer 		}
985252884aeSStefan Eßer 		else {
986252884aeSStefan Eßer 
987252884aeSStefan Eßer 			// The right operand has BcDig values that need to be copied
988252884aeSStefan Eßer 			// or subtracted from zero (in case of a subtraction).
989252884aeSStefan Eßer 			if (do_sub) {
990252884aeSStefan Eßer 
99150696a6eSStefan Eßer 				// do_sub (do_rev_sub && ardx > brdx ||
99250696a6eSStefan Eßer 				// !do_rev_sub && brdx > ardx)
993252884aeSStefan Eßer 				for (i = 0; i < diff; i++)
994252884aeSStefan Eßer 					ptr_c[i] = bc_num_subDigits(0, ptr_r[i], &carry);
995252884aeSStefan Eßer 			}
996252884aeSStefan Eßer 			else {
997252884aeSStefan Eßer 
99850696a6eSStefan Eßer 				// !do_sub && brdx > ardx
999252884aeSStefan Eßer 				memcpy(ptr_c, ptr_r, BC_NUM_SIZE(diff));
1000252884aeSStefan Eßer 			}
1001252884aeSStefan Eßer 
100244d4804dSStefan Eßer 			// Future code needs to ignore the limbs we just did.
1003252884aeSStefan Eßer 			ptr_r += diff;
1004252884aeSStefan Eßer 			len_r -= diff;
1005252884aeSStefan Eßer 		}
1006252884aeSStefan Eßer 
100744d4804dSStefan Eßer 		// The return value pointer needs to ignore what we just did.
1008252884aeSStefan Eßer 		ptr_c += diff;
1009252884aeSStefan Eßer 	}
1010252884aeSStefan Eßer 
101144d4804dSStefan Eßer 	// This is the length that can be directly added/subtracted.
1012252884aeSStefan Eßer 	min_len = BC_MIN(len_l, len_r);
1013252884aeSStefan Eßer 
1014252884aeSStefan Eßer 	// After dealing with possible low array elements that depend on only one
101544d4804dSStefan Eßer 	// operand above, the actual add or subtract can be performed as if the rdx
101644d4804dSStefan Eßer 	// of both operands was the same.
101744d4804dSStefan Eßer 	//
1018252884aeSStefan Eßer 	// Inlining takes care of eliminating constant zero arguments to
1019252884aeSStefan Eßer 	// addDigit/subDigit (checked in disassembly of resulting bc binary
1020252884aeSStefan Eßer 	// compiled with gcc and clang).
1021252884aeSStefan Eßer 	if (do_sub) {
102244d4804dSStefan Eßer 
102344d4804dSStefan Eßer 		// Actual subtraction.
1024252884aeSStefan Eßer 		for (i = 0; i < min_len; ++i)
1025252884aeSStefan Eßer 			ptr_c[i] = bc_num_subDigits(ptr_l[i], ptr_r[i], &carry);
102644d4804dSStefan Eßer 
102744d4804dSStefan Eßer 		// Finishing the limbs beyond the direct subtraction.
1028252884aeSStefan Eßer 		for (; i < len_l; ++i) ptr_c[i] = bc_num_subDigits(ptr_l[i], 0, &carry);
1029252884aeSStefan Eßer 	}
1030252884aeSStefan Eßer 	else {
103144d4804dSStefan Eßer 
103244d4804dSStefan Eßer 		// Actual addition.
1033252884aeSStefan Eßer 		for (i = 0; i < min_len; ++i)
1034252884aeSStefan Eßer 			ptr_c[i] = bc_num_addDigits(ptr_l[i], ptr_r[i], &carry);
103544d4804dSStefan Eßer 
103644d4804dSStefan Eßer 		// Finishing the limbs beyond the direct addition.
1037252884aeSStefan Eßer 		for (; i < len_l; ++i) ptr_c[i] = bc_num_addDigits(ptr_l[i], 0, &carry);
103844d4804dSStefan Eßer 
103944d4804dSStefan Eßer 		// Addition can create an extra limb. We take care of that here.
1040252884aeSStefan Eßer 		ptr_c[i] = bc_num_addDigits(0, 0, &carry);
1041252884aeSStefan Eßer 	}
1042252884aeSStefan Eßer 
1043252884aeSStefan Eßer 	assert(carry == false);
1044252884aeSStefan Eßer 
1045252884aeSStefan Eßer 	// The result has the same sign as a, unless the operation was a
1046252884aeSStefan Eßer 	// reverse subtraction (b - a).
104750696a6eSStefan Eßer 	c_neg = BC_NUM_NEG(a) != (do_sub && do_rev_sub);
104850696a6eSStefan Eßer 	BC_NUM_RDX_SET_NEG(c, max_rdx, c_neg);
1049252884aeSStefan Eßer 	c->len = max_len;
1050252884aeSStefan Eßer 	c->scale = BC_MAX(a->scale, b->scale);
1051252884aeSStefan Eßer 
1052252884aeSStefan Eßer 	bc_num_clean(c);
1053252884aeSStefan Eßer }
1054252884aeSStefan Eßer 
105544d4804dSStefan Eßer /**
105644d4804dSStefan Eßer  * The simple multiplication that karatsuba dishes out to when the length of the
105744d4804dSStefan Eßer  * numbers gets low enough. This doesn't use scale because it treats the
105844d4804dSStefan Eßer  * operands as though they are integers.
105944d4804dSStefan Eßer  * @param a  The first operand.
106044d4804dSStefan Eßer  * @param b  The second operand.
106144d4804dSStefan Eßer  * @param c  The return parameter.
106244d4804dSStefan Eßer  */
106344d4804dSStefan Eßer static void bc_num_m_simp(const BcNum *a, const BcNum *b, BcNum *restrict c) {
106444d4804dSStefan Eßer 
1065252884aeSStefan Eßer 	size_t i, alen = a->len, blen = b->len, clen;
1066252884aeSStefan Eßer 	BcDig *ptr_a = a->num, *ptr_b = b->num, *ptr_c;
1067252884aeSStefan Eßer 	BcBigDig sum = 0, carry = 0;
1068252884aeSStefan Eßer 
1069252884aeSStefan Eßer 	assert(sizeof(sum) >= sizeof(BcDig) * 2);
107050696a6eSStefan Eßer 	assert(!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b));
1071252884aeSStefan Eßer 
107244d4804dSStefan Eßer 	// Make sure c is big enough.
1073252884aeSStefan Eßer 	clen = bc_vm_growSize(alen, blen);
1074252884aeSStefan Eßer 	bc_num_expand(c, bc_vm_growSize(clen, 1));
1075252884aeSStefan Eßer 
107644d4804dSStefan Eßer 	// If we don't memset, then we might have uninitialized data use later.
1077252884aeSStefan Eßer 	ptr_c = c->num;
1078252884aeSStefan Eßer 	memset(ptr_c, 0, BC_NUM_SIZE(c->cap));
1079252884aeSStefan Eßer 
108044d4804dSStefan Eßer 	// This is the actual multiplication loop. It uses the lattice form of long
108144d4804dSStefan Eßer 	// multiplication (see the explanation on the web page at
108244d4804dSStefan Eßer 	// https://knilt.arcc.albany.edu/What_is_Lattice_Multiplication or the
108344d4804dSStefan Eßer 	// explanation at Wikipedia).
1084252884aeSStefan Eßer 	for (i = 0; i < clen; ++i) {
1085252884aeSStefan Eßer 
1086252884aeSStefan Eßer 		ssize_t sidx = (ssize_t) (i - blen + 1);
108744d4804dSStefan Eßer 		size_t j, k;
1088252884aeSStefan Eßer 
108944d4804dSStefan Eßer 		// These are the start indices.
109044d4804dSStefan Eßer 		j = (size_t) BC_MAX(0, sidx);
109144d4804dSStefan Eßer 		k = BC_MIN(i, blen - 1);
109244d4804dSStefan Eßer 
109344d4804dSStefan Eßer 		// On every iteration of this loop, a multiplication happens, then the
109444d4804dSStefan Eßer 		// sum is automatically calculated.
1095252884aeSStefan Eßer 		for (; j < alen && k < blen; ++j, --k) {
1096252884aeSStefan Eßer 
1097252884aeSStefan Eßer 			sum += ((BcBigDig) ptr_a[j]) * ((BcBigDig) ptr_b[k]);
1098252884aeSStefan Eßer 
1099252884aeSStefan Eßer 			if (sum >= ((BcBigDig) BC_BASE_POW) * BC_BASE_POW) {
1100252884aeSStefan Eßer 				carry += sum / BC_BASE_POW;
1101252884aeSStefan Eßer 				sum %= BC_BASE_POW;
1102252884aeSStefan Eßer 			}
1103252884aeSStefan Eßer 		}
1104252884aeSStefan Eßer 
110544d4804dSStefan Eßer 		// Calculate the carry.
1106252884aeSStefan Eßer 		if (sum >= BC_BASE_POW) {
1107252884aeSStefan Eßer 			carry += sum / BC_BASE_POW;
1108252884aeSStefan Eßer 			sum %= BC_BASE_POW;
1109252884aeSStefan Eßer 		}
1110252884aeSStefan Eßer 
111144d4804dSStefan Eßer 		// Store and set up for next iteration.
1112252884aeSStefan Eßer 		ptr_c[i] = (BcDig) sum;
1113252884aeSStefan Eßer 		assert(ptr_c[i] < BC_BASE_POW);
1114252884aeSStefan Eßer 		sum = carry;
1115252884aeSStefan Eßer 		carry = 0;
1116252884aeSStefan Eßer 	}
1117252884aeSStefan Eßer 
1118252884aeSStefan Eßer 	// This should always be true because there should be no carry on the last
1119252884aeSStefan Eßer 	// digit; multiplication never goes above the sum of both lengths.
1120252884aeSStefan Eßer 	assert(!sum);
1121252884aeSStefan Eßer 
1122252884aeSStefan Eßer 	c->len = clen;
1123252884aeSStefan Eßer }
1124252884aeSStefan Eßer 
112544d4804dSStefan Eßer /**
112644d4804dSStefan Eßer  * Does a shifted add or subtract for Karatsuba below. This calls either
112744d4804dSStefan Eßer  * bc_num_addArrays() or bc_num_subArrays().
112844d4804dSStefan Eßer  * @param n      An in/out parameter; the first operand and return parameter.
112944d4804dSStefan Eßer  * @param a      The second operand.
113044d4804dSStefan Eßer  * @param shift  The amount to shift @a n by when adding/subtracting.
113144d4804dSStefan Eßer  * @param op     The function to call, either bc_num_addArrays() or
113244d4804dSStefan Eßer  *               bc_num_subArrays().
113344d4804dSStefan Eßer  */
1134252884aeSStefan Eßer static void bc_num_shiftAddSub(BcNum *restrict n, const BcNum *restrict a,
1135252884aeSStefan Eßer                                size_t shift, BcNumShiftAddOp op)
1136252884aeSStefan Eßer {
1137252884aeSStefan Eßer 	assert(n->len >= shift + a->len);
113850696a6eSStefan Eßer 	assert(!BC_NUM_RDX_VAL(n) && !BC_NUM_RDX_VAL(a));
1139252884aeSStefan Eßer 	op(n->num + shift, a->num, a->len);
1140252884aeSStefan Eßer }
1141252884aeSStefan Eßer 
114244d4804dSStefan Eßer /**
114344d4804dSStefan Eßer  * Implements the Karatsuba algorithm.
114444d4804dSStefan Eßer  */
114544d4804dSStefan Eßer static void bc_num_k(const BcNum *a, const BcNum *b, BcNum *restrict c) {
1146252884aeSStefan Eßer 
1147252884aeSStefan Eßer 	size_t max, max2, total;
1148252884aeSStefan Eßer 	BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
1149252884aeSStefan Eßer 	BcDig *digs, *dig_ptr;
1150252884aeSStefan Eßer 	BcNumShiftAddOp op;
1151252884aeSStefan Eßer 	bool aone = BC_NUM_ONE(a);
1152252884aeSStefan Eßer 
1153252884aeSStefan Eßer 	assert(BC_NUM_ZERO(c));
1154252884aeSStefan Eßer 
1155252884aeSStefan Eßer 	if (BC_NUM_ZERO(a) || BC_NUM_ZERO(b)) return;
115644d4804dSStefan Eßer 
1157252884aeSStefan Eßer 	if (aone || BC_NUM_ONE(b)) {
1158252884aeSStefan Eßer 		bc_num_copy(c, aone ? b : a);
115950696a6eSStefan Eßer 		if ((aone && BC_NUM_NEG(a)) || BC_NUM_NEG(b)) BC_NUM_NEG_TGL(c);
1160252884aeSStefan Eßer 		return;
1161252884aeSStefan Eßer 	}
116244d4804dSStefan Eßer 
116344d4804dSStefan Eßer 	// Shell out to the simple algorithm with certain conditions.
1164252884aeSStefan Eßer 	if (a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN) {
1165252884aeSStefan Eßer 		bc_num_m_simp(a, b, c);
1166252884aeSStefan Eßer 		return;
1167252884aeSStefan Eßer 	}
1168252884aeSStefan Eßer 
116944d4804dSStefan Eßer 	// We need to calculate the max size of the numbers that can result from the
117044d4804dSStefan Eßer 	// operations.
1171252884aeSStefan Eßer 	max = BC_MAX(a->len, b->len);
1172252884aeSStefan Eßer 	max = BC_MAX(max, BC_NUM_DEF_SIZE);
1173252884aeSStefan Eßer 	max2 = (max + 1) / 2;
1174252884aeSStefan Eßer 
117544d4804dSStefan Eßer 	// Calculate the space needed for all of the temporary allocations. We do
117644d4804dSStefan Eßer 	// this to just allocate once.
1177252884aeSStefan Eßer 	total = bc_vm_arraySize(BC_NUM_KARATSUBA_ALLOCS, max);
1178252884aeSStefan Eßer 
1179252884aeSStefan Eßer 	BC_SIG_LOCK;
1180252884aeSStefan Eßer 
118144d4804dSStefan Eßer 	// Allocate space for all of the temporaries.
1182252884aeSStefan Eßer 	digs = dig_ptr = bc_vm_malloc(BC_NUM_SIZE(total));
1183252884aeSStefan Eßer 
118444d4804dSStefan Eßer 	// Set up the temporaries.
1185252884aeSStefan Eßer 	bc_num_setup(&l1, dig_ptr, max);
1186252884aeSStefan Eßer 	dig_ptr += max;
1187252884aeSStefan Eßer 	bc_num_setup(&h1, dig_ptr, max);
1188252884aeSStefan Eßer 	dig_ptr += max;
1189252884aeSStefan Eßer 	bc_num_setup(&l2, dig_ptr, max);
1190252884aeSStefan Eßer 	dig_ptr += max;
1191252884aeSStefan Eßer 	bc_num_setup(&h2, dig_ptr, max);
1192252884aeSStefan Eßer 	dig_ptr += max;
1193252884aeSStefan Eßer 	bc_num_setup(&m1, dig_ptr, max);
1194252884aeSStefan Eßer 	dig_ptr += max;
1195252884aeSStefan Eßer 	bc_num_setup(&m2, dig_ptr, max);
119644d4804dSStefan Eßer 
119744d4804dSStefan Eßer 	// Some temporaries need the ability to grow, so we allocate them
119844d4804dSStefan Eßer 	// separately.
1199252884aeSStefan Eßer 	max = bc_vm_growSize(max, 1);
1200252884aeSStefan Eßer 	bc_num_init(&z0, max);
1201252884aeSStefan Eßer 	bc_num_init(&z1, max);
1202252884aeSStefan Eßer 	bc_num_init(&z2, max);
1203252884aeSStefan Eßer 	max = bc_vm_growSize(max, max) + 1;
1204252884aeSStefan Eßer 	bc_num_init(&temp, max);
1205252884aeSStefan Eßer 
1206252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
1207252884aeSStefan Eßer 
1208252884aeSStefan Eßer 	BC_SIG_UNLOCK;
1209252884aeSStefan Eßer 
121044d4804dSStefan Eßer 	// First, set up c.
1211252884aeSStefan Eßer 	bc_num_expand(c, max);
1212252884aeSStefan Eßer 	c->len = max;
1213252884aeSStefan Eßer 	memset(c->num, 0, BC_NUM_SIZE(c->len));
1214252884aeSStefan Eßer 
121544d4804dSStefan Eßer 	// Split the parameters.
121644d4804dSStefan Eßer 	bc_num_split(a, max2, &l1, &h1);
121744d4804dSStefan Eßer 	bc_num_split(b, max2, &l2, &h2);
121844d4804dSStefan Eßer 
121944d4804dSStefan Eßer 	// Do the subtraction.
1220252884aeSStefan Eßer 	bc_num_sub(&h1, &l1, &m1, 0);
1221252884aeSStefan Eßer 	bc_num_sub(&l2, &h2, &m2, 0);
1222252884aeSStefan Eßer 
122344d4804dSStefan Eßer 	// The if statements below are there for efficiency reasons. The best way to
122444d4804dSStefan Eßer 	// understand them is to understand the Karatsuba algorithm because now that
122544d4804dSStefan Eßer 	// the ollocations and splits are done, the algorithm is pretty
122644d4804dSStefan Eßer 	// straightforward.
122744d4804dSStefan Eßer 
1228252884aeSStefan Eßer 	if (BC_NUM_NONZERO(&h1) && BC_NUM_NONZERO(&h2)) {
1229252884aeSStefan Eßer 
123050696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(h1));
123150696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(h2));
123250696a6eSStefan Eßer 
1233252884aeSStefan Eßer 		bc_num_m(&h1, &h2, &z2, 0);
1234252884aeSStefan Eßer 		bc_num_clean(&z2);
1235252884aeSStefan Eßer 
1236252884aeSStefan Eßer 		bc_num_shiftAddSub(c, &z2, max2 * 2, bc_num_addArrays);
1237252884aeSStefan Eßer 		bc_num_shiftAddSub(c, &z2, max2, bc_num_addArrays);
1238252884aeSStefan Eßer 	}
1239252884aeSStefan Eßer 
1240252884aeSStefan Eßer 	if (BC_NUM_NONZERO(&l1) && BC_NUM_NONZERO(&l2)) {
1241252884aeSStefan Eßer 
124250696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(l1));
124350696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(l2));
124450696a6eSStefan Eßer 
1245252884aeSStefan Eßer 		bc_num_m(&l1, &l2, &z0, 0);
1246252884aeSStefan Eßer 		bc_num_clean(&z0);
1247252884aeSStefan Eßer 
1248252884aeSStefan Eßer 		bc_num_shiftAddSub(c, &z0, max2, bc_num_addArrays);
1249252884aeSStefan Eßer 		bc_num_shiftAddSub(c, &z0, 0, bc_num_addArrays);
1250252884aeSStefan Eßer 	}
1251252884aeSStefan Eßer 
1252252884aeSStefan Eßer 	if (BC_NUM_NONZERO(&m1) && BC_NUM_NONZERO(&m2)) {
1253252884aeSStefan Eßer 
125450696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(m1));
125550696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(m1));
125650696a6eSStefan Eßer 
1257252884aeSStefan Eßer 		bc_num_m(&m1, &m2, &z1, 0);
1258252884aeSStefan Eßer 		bc_num_clean(&z1);
1259252884aeSStefan Eßer 
126050696a6eSStefan Eßer 		op = (BC_NUM_NEG_NP(m1) != BC_NUM_NEG_NP(m2)) ?
126150696a6eSStefan Eßer 		     bc_num_subArrays : bc_num_addArrays;
1262252884aeSStefan Eßer 		bc_num_shiftAddSub(c, &z1, max2, op);
1263252884aeSStefan Eßer 	}
1264252884aeSStefan Eßer 
1265252884aeSStefan Eßer err:
1266252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
1267252884aeSStefan Eßer 	free(digs);
1268252884aeSStefan Eßer 	bc_num_free(&temp);
1269252884aeSStefan Eßer 	bc_num_free(&z2);
1270252884aeSStefan Eßer 	bc_num_free(&z1);
1271252884aeSStefan Eßer 	bc_num_free(&z0);
1272252884aeSStefan Eßer 	BC_LONGJMP_CONT;
1273252884aeSStefan Eßer }
1274252884aeSStefan Eßer 
127544d4804dSStefan Eßer /**
127644d4804dSStefan Eßer  * Does checks for Karatsuba. It also changes things to ensure that the
127744d4804dSStefan Eßer  * Karatsuba and simple multiplication can treat the numbers as integers. This
127844d4804dSStefan Eßer  * is a BcNumBinOp function.
127944d4804dSStefan Eßer  * @param a      The first operand.
128044d4804dSStefan Eßer  * @param b      The second operand.
128144d4804dSStefan Eßer  * @param c      The return parameter.
128244d4804dSStefan Eßer  * @param scale  The current scale.
128344d4804dSStefan Eßer  */
1284252884aeSStefan Eßer static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1285252884aeSStefan Eßer 
1286252884aeSStefan Eßer 	BcNum cpa, cpb;
1287252884aeSStefan Eßer 	size_t ascale, bscale, ardx, brdx, azero = 0, bzero = 0, zero, len, rscale;
1288252884aeSStefan Eßer 
128950696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
129050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
129150696a6eSStefan Eßer 
1292252884aeSStefan Eßer 	bc_num_zero(c);
129344d4804dSStefan Eßer 
1294252884aeSStefan Eßer 	ascale = a->scale;
1295252884aeSStefan Eßer 	bscale = b->scale;
129644d4804dSStefan Eßer 
129744d4804dSStefan Eßer 	// This sets the final scale according to the bc spec.
1298252884aeSStefan Eßer 	scale = BC_MAX(scale, ascale);
1299252884aeSStefan Eßer 	scale = BC_MAX(scale, bscale);
1300252884aeSStefan Eßer 	rscale = ascale + bscale;
1301252884aeSStefan Eßer 	scale = BC_MIN(rscale, scale);
1302252884aeSStefan Eßer 
130344d4804dSStefan Eßer 	// If this condition is true, we can use bc_num_mulArray(), which would be
130444d4804dSStefan Eßer 	// much faster.
1305252884aeSStefan Eßer 	if ((a->len == 1 || b->len == 1) && !a->rdx && !b->rdx) {
1306252884aeSStefan Eßer 
1307252884aeSStefan Eßer 		BcNum *operand;
1308252884aeSStefan Eßer 		BcBigDig dig;
1309252884aeSStefan Eßer 
131044d4804dSStefan Eßer 		// Set the correct operands.
1311252884aeSStefan Eßer 		if (a->len == 1) {
1312252884aeSStefan Eßer 			dig = (BcBigDig) a->num[0];
1313252884aeSStefan Eßer 			operand = b;
1314252884aeSStefan Eßer 		}
1315252884aeSStefan Eßer 		else {
1316252884aeSStefan Eßer 			dig = (BcBigDig) b->num[0];
1317252884aeSStefan Eßer 			operand = a;
1318252884aeSStefan Eßer 		}
1319252884aeSStefan Eßer 
1320252884aeSStefan Eßer 		bc_num_mulArray(operand, dig, c);
1321252884aeSStefan Eßer 
132244d4804dSStefan Eßer 		// Need to make sure the sign is correct.
132350696a6eSStefan Eßer 		if (BC_NUM_NONZERO(c))
132450696a6eSStefan Eßer 			c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(a) != BC_NUM_NEG(b));
1325252884aeSStefan Eßer 
1326252884aeSStefan Eßer 		return;
1327252884aeSStefan Eßer 	}
1328252884aeSStefan Eßer 
132950696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
133050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
133150696a6eSStefan Eßer 
1332252884aeSStefan Eßer 	BC_SIG_LOCK;
1333252884aeSStefan Eßer 
133444d4804dSStefan Eßer 	// We need copies because of all of the mutation needed to make Karatsuba
133544d4804dSStefan Eßer 	// think the numbers are integers.
133650696a6eSStefan Eßer 	bc_num_init(&cpa, a->len + BC_NUM_RDX_VAL(a));
133750696a6eSStefan Eßer 	bc_num_init(&cpb, b->len + BC_NUM_RDX_VAL(b));
1338252884aeSStefan Eßer 
1339252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
1340252884aeSStefan Eßer 
1341252884aeSStefan Eßer 	BC_SIG_UNLOCK;
1342252884aeSStefan Eßer 
1343252884aeSStefan Eßer 	bc_num_copy(&cpa, a);
1344252884aeSStefan Eßer 	bc_num_copy(&cpb, b);
1345252884aeSStefan Eßer 
134650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(cpa));
134750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(cpb));
1348252884aeSStefan Eßer 
134950696a6eSStefan Eßer 	BC_NUM_NEG_CLR_NP(cpa);
135050696a6eSStefan Eßer 	BC_NUM_NEG_CLR_NP(cpb);
135150696a6eSStefan Eßer 
135250696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(cpa));
135350696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(cpb));
135450696a6eSStefan Eßer 
135544d4804dSStefan Eßer 	// These are what makes them appear like integers.
135650696a6eSStefan Eßer 	ardx = BC_NUM_RDX_VAL_NP(cpa) * BC_BASE_DIGS;
1357252884aeSStefan Eßer 	bc_num_shiftLeft(&cpa, ardx);
1358252884aeSStefan Eßer 
135950696a6eSStefan Eßer 	brdx = BC_NUM_RDX_VAL_NP(cpb) * BC_BASE_DIGS;
1360252884aeSStefan Eßer 	bc_num_shiftLeft(&cpb, brdx);
1361252884aeSStefan Eßer 
1362252884aeSStefan Eßer 	// We need to reset the jump here because azero and bzero are used in the
1363252884aeSStefan Eßer 	// cleanup, and local variables are not guaranteed to be the same after a
1364252884aeSStefan Eßer 	// jump.
1365252884aeSStefan Eßer 	BC_SIG_LOCK;
1366252884aeSStefan Eßer 
1367252884aeSStefan Eßer 	BC_UNSETJMP;
1368252884aeSStefan Eßer 
136944d4804dSStefan Eßer 	// We want to ignore zero limbs.
1370252884aeSStefan Eßer 	azero = bc_num_shiftZero(&cpa);
1371252884aeSStefan Eßer 	bzero = bc_num_shiftZero(&cpb);
1372252884aeSStefan Eßer 
1373252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
1374252884aeSStefan Eßer 
1375252884aeSStefan Eßer 	BC_SIG_UNLOCK;
1376252884aeSStefan Eßer 
1377252884aeSStefan Eßer 	bc_num_clean(&cpa);
1378252884aeSStefan Eßer 	bc_num_clean(&cpb);
1379252884aeSStefan Eßer 
1380252884aeSStefan Eßer 	bc_num_k(&cpa, &cpb, c);
1381252884aeSStefan Eßer 
138244d4804dSStefan Eßer 	// The return parameter needs to have its scale set. This is the start. It
138344d4804dSStefan Eßer 	// also needs to be shifted by the same amount as a and b have limbs after
138444d4804dSStefan Eßer 	// the decimal point.
1385252884aeSStefan Eßer 	zero = bc_vm_growSize(azero, bzero);
1386252884aeSStefan Eßer 	len = bc_vm_growSize(c->len, zero);
1387252884aeSStefan Eßer 
1388252884aeSStefan Eßer 	bc_num_expand(c, len);
138944d4804dSStefan Eßer 
139044d4804dSStefan Eßer 	// Shift c based on the limbs after the decimal point in a and b.
1391252884aeSStefan Eßer 	bc_num_shiftLeft(c, (len - c->len) * BC_BASE_DIGS);
1392252884aeSStefan Eßer 	bc_num_shiftRight(c, ardx + brdx);
1393252884aeSStefan Eßer 
139450696a6eSStefan Eßer 	bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
1395252884aeSStefan Eßer 
1396252884aeSStefan Eßer err:
1397252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
1398252884aeSStefan Eßer 	bc_num_unshiftZero(&cpb, bzero);
1399252884aeSStefan Eßer 	bc_num_free(&cpb);
1400252884aeSStefan Eßer 	bc_num_unshiftZero(&cpa, azero);
1401252884aeSStefan Eßer 	bc_num_free(&cpa);
1402252884aeSStefan Eßer 	BC_LONGJMP_CONT;
1403252884aeSStefan Eßer }
1404252884aeSStefan Eßer 
140544d4804dSStefan Eßer /**
140644d4804dSStefan Eßer  * Returns true if the BcDig array has non-zero limbs, false otherwise.
140744d4804dSStefan Eßer  * @param a    The array to test.
140844d4804dSStefan Eßer  * @param len  The length of the array.
140944d4804dSStefan Eßer  * @return     True if @a has any non-zero limbs, false otherwise.
141044d4804dSStefan Eßer  */
1411252884aeSStefan Eßer static bool bc_num_nonZeroDig(BcDig *restrict a, size_t len) {
1412252884aeSStefan Eßer 	size_t i;
1413252884aeSStefan Eßer 	bool nonzero = false;
1414252884aeSStefan Eßer 	for (i = len - 1; !nonzero && i < len; --i) nonzero = (a[i] != 0);
1415252884aeSStefan Eßer 	return nonzero;
1416252884aeSStefan Eßer }
1417252884aeSStefan Eßer 
141844d4804dSStefan Eßer /**
141944d4804dSStefan Eßer  * Compares a BcDig array against a BcNum. This is especially suited for
142044d4804dSStefan Eßer  * division. Returns >0 if @a a is greater than @a b, <0 if it is less, and =0
142144d4804dSStefan Eßer  * if they are equal.
142244d4804dSStefan Eßer  * @param a    The array.
142344d4804dSStefan Eßer  * @param b    The number.
142444d4804dSStefan Eßer  * @param len  The length to assume the arrays are. This is always less than the
142544d4804dSStefan Eßer  *             actual length because of how this is implemented.
142644d4804dSStefan Eßer  */
1427252884aeSStefan Eßer static ssize_t bc_num_divCmp(const BcDig *a, const BcNum *b, size_t len) {
1428252884aeSStefan Eßer 
1429252884aeSStefan Eßer 	ssize_t cmp;
1430252884aeSStefan Eßer 
1431252884aeSStefan Eßer 	if (b->len > len && a[len]) cmp = bc_num_compare(a, b->num, len + 1);
1432252884aeSStefan Eßer 	else if (b->len <= len) {
1433252884aeSStefan Eßer 		if (a[len]) cmp = 1;
1434252884aeSStefan Eßer 		else cmp = bc_num_compare(a, b->num, len);
1435252884aeSStefan Eßer 	}
1436252884aeSStefan Eßer 	else cmp = -1;
1437252884aeSStefan Eßer 
1438252884aeSStefan Eßer 	return cmp;
1439252884aeSStefan Eßer }
1440252884aeSStefan Eßer 
144144d4804dSStefan Eßer /**
144244d4804dSStefan Eßer  * Extends the two operands of a division by BC_BASE_DIGS minus the number of
144344d4804dSStefan Eßer  * digits in the divisor estimate. In other words, it is shifting the numbers in
144444d4804dSStefan Eßer  * order to force the divisor estimate to fill the limb.
144544d4804dSStefan Eßer  * @param a        The first operand.
144644d4804dSStefan Eßer  * @param b        The second operand.
144744d4804dSStefan Eßer  * @param divisor  The divisor estimate.
144844d4804dSStefan Eßer  */
1449252884aeSStefan Eßer static void bc_num_divExtend(BcNum *restrict a, BcNum *restrict b,
1450252884aeSStefan Eßer                              BcBigDig divisor)
1451252884aeSStefan Eßer {
1452252884aeSStefan Eßer 	size_t pow;
1453252884aeSStefan Eßer 
1454252884aeSStefan Eßer 	assert(divisor < BC_BASE_POW);
1455252884aeSStefan Eßer 
1456252884aeSStefan Eßer 	pow = BC_BASE_DIGS - bc_num_log10((size_t) divisor);
1457252884aeSStefan Eßer 
1458252884aeSStefan Eßer 	bc_num_shiftLeft(a, pow);
1459252884aeSStefan Eßer 	bc_num_shiftLeft(b, pow);
1460252884aeSStefan Eßer }
1461252884aeSStefan Eßer 
146244d4804dSStefan Eßer /**
146344d4804dSStefan Eßer  * Actually does division. This is a rewrite of my original code by Stefan Esser
146444d4804dSStefan Eßer  * from FreeBSD.
146544d4804dSStefan Eßer  * @param a      The first operand.
146644d4804dSStefan Eßer  * @param b      The second operand.
146744d4804dSStefan Eßer  * @param c      The return parameter.
146844d4804dSStefan Eßer  * @param scale  The current scale.
146944d4804dSStefan Eßer  */
1470252884aeSStefan Eßer static void bc_num_d_long(BcNum *restrict a, BcNum *restrict b,
1471252884aeSStefan Eßer                           BcNum *restrict c, size_t scale)
1472252884aeSStefan Eßer {
1473252884aeSStefan Eßer 	BcBigDig divisor;
1474252884aeSStefan Eßer 	size_t len, end, i, rdx;
1475252884aeSStefan Eßer 	BcNum cpb;
1476252884aeSStefan Eßer 	bool nonzero = false;
1477252884aeSStefan Eßer 
1478252884aeSStefan Eßer 	assert(b->len < a->len);
147944d4804dSStefan Eßer 
1480252884aeSStefan Eßer 	len = b->len;
1481252884aeSStefan Eßer 	end = a->len - len;
148244d4804dSStefan Eßer 
1483252884aeSStefan Eßer 	assert(len >= 1);
1484252884aeSStefan Eßer 
148544d4804dSStefan Eßer 	// This is a final time to make sure c is big enough and that its array is
148644d4804dSStefan Eßer 	// properly zeroed.
1487252884aeSStefan Eßer 	bc_num_expand(c, a->len);
1488252884aeSStefan Eßer 	memset(c->num, 0, c->cap * sizeof(BcDig));
1489252884aeSStefan Eßer 
149044d4804dSStefan Eßer 	// Setup.
149150696a6eSStefan Eßer 	BC_NUM_RDX_SET(c, BC_NUM_RDX_VAL(a));
1492252884aeSStefan Eßer 	c->scale = a->scale;
1493252884aeSStefan Eßer 	c->len = a->len;
1494252884aeSStefan Eßer 
149544d4804dSStefan Eßer 	// This is pulling the most significant limb of b in order to establish a
149644d4804dSStefan Eßer 	// good "estimate" for the actual divisor.
1497252884aeSStefan Eßer 	divisor = (BcBigDig) b->num[len - 1];
1498252884aeSStefan Eßer 
149944d4804dSStefan Eßer 	// The entire bit of code in this if statement is to tighten the estimate of
150044d4804dSStefan Eßer 	// the divisor. The condition asks if b has any other non-zero limbs.
1501252884aeSStefan Eßer 	if (len > 1 && bc_num_nonZeroDig(b->num, len - 1)) {
1502252884aeSStefan Eßer 
150344d4804dSStefan Eßer 		// This takes a little bit of understanding. The "10*BC_BASE_DIGS/6+1"
150444d4804dSStefan Eßer 		// results in either 16 for 64-bit 9-digit limbs or 7 for 32-bit 4-digit
150544d4804dSStefan Eßer 		// limbs. Then it shifts a 1 by that many, which in both cases, puts the
150644d4804dSStefan Eßer 		// result above *half* of the max value a limb can store. Basically,
150744d4804dSStefan Eßer 		// this quickly calculates if the divisor is greater than half the max
150844d4804dSStefan Eßer 		// of a limb.
1509252884aeSStefan Eßer 		nonzero = (divisor > 1 << ((10 * BC_BASE_DIGS) / 6 + 1));
1510252884aeSStefan Eßer 
151144d4804dSStefan Eßer 		// If the divisor is *not* greater than half the limb...
1512252884aeSStefan Eßer 		if (!nonzero) {
1513252884aeSStefan Eßer 
151444d4804dSStefan Eßer 			// Extend the parameters by the number of missing digits in the
151544d4804dSStefan Eßer 			// divisor.
1516252884aeSStefan Eßer 			bc_num_divExtend(a, b, divisor);
1517252884aeSStefan Eßer 
151844d4804dSStefan Eßer 			// Check bc_num_d(). In there, we grow a again and again. We do it
151944d4804dSStefan Eßer 			// again here; we *always* want to be sure it is big enough.
1520252884aeSStefan Eßer 			len = BC_MAX(a->len, b->len);
1521252884aeSStefan Eßer 			bc_num_expand(a, len + 1);
1522252884aeSStefan Eßer 
152344d4804dSStefan Eßer 			// Make a have a zero most significant limb to match the len.
1524252884aeSStefan Eßer 			if (len + 1 > a->len) a->len = len + 1;
1525252884aeSStefan Eßer 
152644d4804dSStefan Eßer 			// Grab the new divisor estimate, new because the shift has made it
152744d4804dSStefan Eßer 			// different.
1528252884aeSStefan Eßer 			len = b->len;
1529252884aeSStefan Eßer 			end = a->len - len;
1530252884aeSStefan Eßer 			divisor = (BcBigDig) b->num[len - 1];
1531252884aeSStefan Eßer 
1532252884aeSStefan Eßer 			nonzero = bc_num_nonZeroDig(b->num, len - 1);
1533252884aeSStefan Eßer 		}
1534252884aeSStefan Eßer 	}
1535252884aeSStefan Eßer 
153644d4804dSStefan Eßer 	// If b has other nonzero limbs, we want the divisor to be one higher, so
153744d4804dSStefan Eßer 	// that it is an upper bound.
1538252884aeSStefan Eßer 	divisor += nonzero;
1539252884aeSStefan Eßer 
154044d4804dSStefan Eßer 	// Make sure c can fit the new length.
1541252884aeSStefan Eßer 	bc_num_expand(c, a->len);
1542252884aeSStefan Eßer 	memset(c->num, 0, BC_NUM_SIZE(c->cap));
1543252884aeSStefan Eßer 
1544252884aeSStefan Eßer 	assert(c->scale >= scale);
154550696a6eSStefan Eßer 	rdx = BC_NUM_RDX_VAL(c) - BC_NUM_RDX(scale);
1546252884aeSStefan Eßer 
1547252884aeSStefan Eßer 	BC_SIG_LOCK;
1548252884aeSStefan Eßer 
1549252884aeSStefan Eßer 	bc_num_init(&cpb, len + 1);
1550252884aeSStefan Eßer 
1551252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
1552252884aeSStefan Eßer 
1553252884aeSStefan Eßer 	BC_SIG_UNLOCK;
1554252884aeSStefan Eßer 
155544d4804dSStefan Eßer 	// This is the actual division loop.
155644d4804dSStefan Eßer 	for (i = end - 1; i < end && i >= rdx && BC_NUM_NONZERO(a); --i) {
1557252884aeSStefan Eßer 
1558252884aeSStefan Eßer 		ssize_t cmp;
1559252884aeSStefan Eßer 		BcDig *n;
1560252884aeSStefan Eßer 		BcBigDig result;
1561252884aeSStefan Eßer 
1562252884aeSStefan Eßer 		n = a->num + i;
1563252884aeSStefan Eßer 		assert(n >= a->num);
1564252884aeSStefan Eßer 		result = 0;
1565252884aeSStefan Eßer 
1566252884aeSStefan Eßer 		cmp = bc_num_divCmp(n, b, len);
1567252884aeSStefan Eßer 
156844d4804dSStefan Eßer 		// This is true if n is greater than b, which means that division can
156944d4804dSStefan Eßer 		// proceed, so this inner loop is the part that implements one instance
157044d4804dSStefan Eßer 		// of the division.
1571252884aeSStefan Eßer 		while (cmp >= 0) {
1572252884aeSStefan Eßer 
157344d4804dSStefan Eßer 			BcBigDig n1, dividend, quotient;
1574252884aeSStefan Eßer 
157544d4804dSStefan Eßer 			// These should be named obviously enough. Just imagine that it's a
157644d4804dSStefan Eßer 			// division of one limb. Because that's what it is.
1577252884aeSStefan Eßer 			n1 = (BcBigDig) n[len];
1578252884aeSStefan Eßer 			dividend = n1 * BC_BASE_POW + (BcBigDig) n[len - 1];
157944d4804dSStefan Eßer 			quotient = (dividend / divisor);
1580252884aeSStefan Eßer 
158144d4804dSStefan Eßer 			// If this is true, then we can just subtract. Remember: setting
158244d4804dSStefan Eßer 			// quotient to 1 is not bad because we already know that n is
158344d4804dSStefan Eßer 			// greater than b.
158444d4804dSStefan Eßer 			if (quotient <= 1) {
158544d4804dSStefan Eßer 				quotient = 1;
1586252884aeSStefan Eßer 				bc_num_subArrays(n, b->num, len);
1587252884aeSStefan Eßer 			}
1588252884aeSStefan Eßer 			else {
1589252884aeSStefan Eßer 
159044d4804dSStefan Eßer 				assert(quotient <= BC_BASE_POW);
1591252884aeSStefan Eßer 
159244d4804dSStefan Eßer 				// We need to multiply and subtract for a quotient above 1.
159344d4804dSStefan Eßer 				bc_num_mulArray(b, (BcBigDig) quotient, &cpb);
1594252884aeSStefan Eßer 				bc_num_subArrays(n, cpb.num, cpb.len);
1595252884aeSStefan Eßer 			}
1596252884aeSStefan Eßer 
159744d4804dSStefan Eßer 			// The result is the *real* quotient, by the way, but it might take
159844d4804dSStefan Eßer 			// multiple trips around this loop to get it.
159944d4804dSStefan Eßer 			result += quotient;
1600252884aeSStefan Eßer 			assert(result <= BC_BASE_POW);
1601252884aeSStefan Eßer 
160244d4804dSStefan Eßer 			// And here's why it might take multiple trips: n might *still* be
160344d4804dSStefan Eßer 			// greater than b. So we have to loop again. That's what this is
160444d4804dSStefan Eßer 			// setting up for: the condition of the while loop.
1605252884aeSStefan Eßer 			if (nonzero) cmp = bc_num_divCmp(n, b, len);
1606252884aeSStefan Eßer 			else cmp = -1;
1607252884aeSStefan Eßer 		}
1608252884aeSStefan Eßer 
1609252884aeSStefan Eßer 		assert(result < BC_BASE_POW);
1610252884aeSStefan Eßer 
161144d4804dSStefan Eßer 		// Store the actual limb quotient.
1612252884aeSStefan Eßer 		c->num[i] = (BcDig) result;
1613252884aeSStefan Eßer 	}
1614252884aeSStefan Eßer 
1615252884aeSStefan Eßer err:
1616252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
1617252884aeSStefan Eßer 	bc_num_free(&cpb);
1618252884aeSStefan Eßer 	BC_LONGJMP_CONT;
1619252884aeSStefan Eßer }
1620252884aeSStefan Eßer 
162144d4804dSStefan Eßer /**
162244d4804dSStefan Eßer  * Implements division. This is a BcNumBinOp function.
162344d4804dSStefan Eßer  * @param a      The first operand.
162444d4804dSStefan Eßer  * @param b      The second operand.
162544d4804dSStefan Eßer  * @param c      The return parameter.
162644d4804dSStefan Eßer  * @param scale  The current scale.
162744d4804dSStefan Eßer  */
1628252884aeSStefan Eßer static void bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1629252884aeSStefan Eßer 
163050696a6eSStefan Eßer 	size_t len, cpardx;
1631252884aeSStefan Eßer 	BcNum cpa, cpb;
1632252884aeSStefan Eßer 
163344d4804dSStefan Eßer 	if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
163444d4804dSStefan Eßer 
1635252884aeSStefan Eßer 	if (BC_NUM_ZERO(a)) {
1636252884aeSStefan Eßer 		bc_num_setToZero(c, scale);
1637252884aeSStefan Eßer 		return;
1638252884aeSStefan Eßer 	}
163944d4804dSStefan Eßer 
1640252884aeSStefan Eßer 	if (BC_NUM_ONE(b)) {
1641252884aeSStefan Eßer 		bc_num_copy(c, a);
164250696a6eSStefan Eßer 		bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
1643252884aeSStefan Eßer 		return;
1644252884aeSStefan Eßer 	}
164544d4804dSStefan Eßer 
164644d4804dSStefan Eßer 	// If this is true, we can use bc_num_divArray(), which would be faster.
164750696a6eSStefan Eßer 	if (!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale) {
1648252884aeSStefan Eßer 		BcBigDig rem;
1649252884aeSStefan Eßer 		bc_num_divArray(a, (BcBigDig) b->num[0], c, &rem);
165050696a6eSStefan Eßer 		bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
1651252884aeSStefan Eßer 		return;
1652252884aeSStefan Eßer 	}
1653252884aeSStefan Eßer 
165450696a6eSStefan Eßer 	len = bc_num_divReq(a, b, scale);
1655252884aeSStefan Eßer 
1656252884aeSStefan Eßer 	BC_SIG_LOCK;
1657252884aeSStefan Eßer 
165844d4804dSStefan Eßer 	// Initialize copies of the parameters. We want the length of the first
165944d4804dSStefan Eßer 	// operand copy to be as big as the result because of the way the division
166044d4804dSStefan Eßer 	// is implemented.
1661252884aeSStefan Eßer 	bc_num_init(&cpa, len);
1662252884aeSStefan Eßer 	bc_num_copy(&cpa, a);
1663252884aeSStefan Eßer 	bc_num_createCopy(&cpb, b);
1664252884aeSStefan Eßer 
1665252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
1666252884aeSStefan Eßer 
1667252884aeSStefan Eßer 	BC_SIG_UNLOCK;
1668252884aeSStefan Eßer 
1669252884aeSStefan Eßer 	len = b->len;
1670252884aeSStefan Eßer 
167144d4804dSStefan Eßer 	// Like the above comment, we want the copy of the first parameter to be
167244d4804dSStefan Eßer 	// larger than the second parameter.
1673252884aeSStefan Eßer 	if (len > cpa.len) {
1674252884aeSStefan Eßer 		bc_num_expand(&cpa, bc_vm_growSize(len, 2));
1675252884aeSStefan Eßer 		bc_num_extend(&cpa, (len - cpa.len) * BC_BASE_DIGS);
1676252884aeSStefan Eßer 	}
1677252884aeSStefan Eßer 
167850696a6eSStefan Eßer 	cpardx = BC_NUM_RDX_VAL_NP(cpa);
167950696a6eSStefan Eßer 	cpa.scale = cpardx * BC_BASE_DIGS;
1680252884aeSStefan Eßer 
168144d4804dSStefan Eßer 	// This is just setting up the scale in preparation for the division.
1682252884aeSStefan Eßer 	bc_num_extend(&cpa, b->scale);
168350696a6eSStefan Eßer 	cpardx = BC_NUM_RDX_VAL_NP(cpa) - BC_NUM_RDX(b->scale);
168450696a6eSStefan Eßer 	BC_NUM_RDX_SET_NP(cpa, cpardx);
168550696a6eSStefan Eßer 	cpa.scale = cpardx * BC_BASE_DIGS;
1686252884aeSStefan Eßer 
168744d4804dSStefan Eßer 	// Once again, just setting things up, this time to match scale.
1688252884aeSStefan Eßer 	if (scale > cpa.scale) {
1689252884aeSStefan Eßer 		bc_num_extend(&cpa, scale);
169050696a6eSStefan Eßer 		cpardx = BC_NUM_RDX_VAL_NP(cpa);
169150696a6eSStefan Eßer 		cpa.scale = cpardx * BC_BASE_DIGS;
1692252884aeSStefan Eßer 	}
1693252884aeSStefan Eßer 
169444d4804dSStefan Eßer 	// Grow if necessary.
1695252884aeSStefan Eßer 	if (cpa.cap == cpa.len) bc_num_expand(&cpa, bc_vm_growSize(cpa.len, 1));
1696252884aeSStefan Eßer 
1697252884aeSStefan Eßer 	// We want an extra zero in front to make things simpler.
1698252884aeSStefan Eßer 	cpa.num[cpa.len++] = 0;
1699252884aeSStefan Eßer 
170044d4804dSStefan Eßer 	// Still setting things up. Why all of these things are needed is not
170144d4804dSStefan Eßer 	// something that can be easily explained, but it has to do with making the
170244d4804dSStefan Eßer 	// actual algorithm easier to understand because it can assume a lot of
170344d4804dSStefan Eßer 	// things. Thus, you should view all of this setup code as establishing
170444d4804dSStefan Eßer 	// assumptions for bc_num_d_long(), where the actual division happens.
170544d4804dSStefan Eßer 	if (cpardx == cpa.len) cpa.len = bc_num_nonZeroLen(&cpa);
170644d4804dSStefan Eßer 	if (BC_NUM_RDX_VAL_NP(cpb) == cpb.len) cpb.len = bc_num_nonZeroLen(&cpb);
170750696a6eSStefan Eßer 	cpb.scale = 0;
170850696a6eSStefan Eßer 	BC_NUM_RDX_SET_NP(cpb, 0);
1709252884aeSStefan Eßer 
1710252884aeSStefan Eßer 	bc_num_d_long(&cpa, &cpb, c, scale);
1711252884aeSStefan Eßer 
171250696a6eSStefan Eßer 	bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
1713252884aeSStefan Eßer 
1714252884aeSStefan Eßer err:
1715252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
1716252884aeSStefan Eßer 	bc_num_free(&cpb);
1717252884aeSStefan Eßer 	bc_num_free(&cpa);
1718252884aeSStefan Eßer 	BC_LONGJMP_CONT;
1719252884aeSStefan Eßer }
1720252884aeSStefan Eßer 
172144d4804dSStefan Eßer /**
172244d4804dSStefan Eßer  * Implements divmod. This is the actual modulus function; since modulus
172344d4804dSStefan Eßer  * requires a division anyway, this returns the quotient and modulus. Either can
172444d4804dSStefan Eßer  * be thrown out as desired.
172544d4804dSStefan Eßer  * @param a      The first operand.
172644d4804dSStefan Eßer  * @param b      The second operand.
172744d4804dSStefan Eßer  * @param c      The return parameter for the quotient.
172844d4804dSStefan Eßer  * @param d      The return parameter for the modulus.
172944d4804dSStefan Eßer  * @param scale  The current scale.
173044d4804dSStefan Eßer  * @param ts     The scale that the operation should be done to. Yes, it's not
173144d4804dSStefan Eßer  *               necessarily the same as scale, per the bc spec.
173244d4804dSStefan Eßer  */
1733252884aeSStefan Eßer static void bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
1734252884aeSStefan Eßer                      BcNum *restrict d, size_t scale, size_t ts)
1735252884aeSStefan Eßer {
1736252884aeSStefan Eßer 	BcNum temp;
1737252884aeSStefan Eßer 	bool neg;
1738252884aeSStefan Eßer 
173944d4804dSStefan Eßer 	if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
174044d4804dSStefan Eßer 
1741252884aeSStefan Eßer 	if (BC_NUM_ZERO(a)) {
1742252884aeSStefan Eßer 		bc_num_setToZero(c, ts);
1743252884aeSStefan Eßer 		bc_num_setToZero(d, ts);
1744252884aeSStefan Eßer 		return;
1745252884aeSStefan Eßer 	}
1746252884aeSStefan Eßer 
1747252884aeSStefan Eßer 	BC_SIG_LOCK;
1748252884aeSStefan Eßer 
1749252884aeSStefan Eßer 	bc_num_init(&temp, d->cap);
1750252884aeSStefan Eßer 
1751252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
1752252884aeSStefan Eßer 
1753252884aeSStefan Eßer 	BC_SIG_UNLOCK;
1754252884aeSStefan Eßer 
175544d4804dSStefan Eßer 	// Division.
1756252884aeSStefan Eßer 	bc_num_d(a, b, c, scale);
1757252884aeSStefan Eßer 
175844d4804dSStefan Eßer 	// We want an extra digit so we can safely truncate.
1759252884aeSStefan Eßer 	if (scale) scale = ts + 1;
1760252884aeSStefan Eßer 
176150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(c));
176250696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
176350696a6eSStefan Eßer 
176444d4804dSStefan Eßer 	// Implement the rest of the (a - (a / b) * b) formula.
1765252884aeSStefan Eßer 	bc_num_m(c, b, &temp, scale);
1766252884aeSStefan Eßer 	bc_num_sub(a, &temp, d, scale);
1767252884aeSStefan Eßer 
176844d4804dSStefan Eßer 	// Extend if necessary.
1769252884aeSStefan Eßer 	if (ts > d->scale && BC_NUM_NONZERO(d)) bc_num_extend(d, ts - d->scale);
1770252884aeSStefan Eßer 
177150696a6eSStefan Eßer 	neg = BC_NUM_NEG(d);
177250696a6eSStefan Eßer 	bc_num_retireMul(d, ts, BC_NUM_NEG(a), BC_NUM_NEG(b));
177350696a6eSStefan Eßer 	d->rdx = BC_NUM_NEG_VAL(d, BC_NUM_NONZERO(d) ? neg : false);
1774252884aeSStefan Eßer 
1775252884aeSStefan Eßer err:
1776252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
1777252884aeSStefan Eßer 	bc_num_free(&temp);
1778252884aeSStefan Eßer 	BC_LONGJMP_CONT;
1779252884aeSStefan Eßer }
1780252884aeSStefan Eßer 
178144d4804dSStefan Eßer /**
178244d4804dSStefan Eßer  * Implements modulus/remainder. (Yes, I know they are different, but not in the
178344d4804dSStefan Eßer  * context of bc.) This is a BcNumBinOp function.
178444d4804dSStefan Eßer  * @param a      The first operand.
178544d4804dSStefan Eßer  * @param b      The second operand.
178644d4804dSStefan Eßer  * @param c      The return parameter.
178744d4804dSStefan Eßer  * @param scale  The current scale.
178844d4804dSStefan Eßer  */
1789252884aeSStefan Eßer static void bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1790252884aeSStefan Eßer 
1791252884aeSStefan Eßer 	BcNum c1;
1792252884aeSStefan Eßer 	size_t ts;
1793252884aeSStefan Eßer 
1794252884aeSStefan Eßer 	ts = bc_vm_growSize(scale, b->scale);
1795252884aeSStefan Eßer 	ts = BC_MAX(ts, a->scale);
1796252884aeSStefan Eßer 
1797252884aeSStefan Eßer 	BC_SIG_LOCK;
1798252884aeSStefan Eßer 
179944d4804dSStefan Eßer 	// Need a temp for the quotient.
1800252884aeSStefan Eßer 	bc_num_init(&c1, bc_num_mulReq(a, b, ts));
1801252884aeSStefan Eßer 
1802252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
1803252884aeSStefan Eßer 
1804252884aeSStefan Eßer 	BC_SIG_UNLOCK;
1805252884aeSStefan Eßer 
1806252884aeSStefan Eßer 	bc_num_r(a, b, &c1, c, scale, ts);
1807252884aeSStefan Eßer 
1808252884aeSStefan Eßer err:
1809252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
1810252884aeSStefan Eßer 	bc_num_free(&c1);
1811252884aeSStefan Eßer 	BC_LONGJMP_CONT;
1812252884aeSStefan Eßer }
1813252884aeSStefan Eßer 
181444d4804dSStefan Eßer /**
181544d4804dSStefan Eßer  * Implements power (exponentiation). This is a BcNumBinOp function.
181644d4804dSStefan Eßer  * @param a      The first operand.
181744d4804dSStefan Eßer  * @param b      The second operand.
181844d4804dSStefan Eßer  * @param c      The return parameter.
181944d4804dSStefan Eßer  * @param scale  The current scale.
182044d4804dSStefan Eßer  */
1821252884aeSStefan Eßer static void bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1822252884aeSStefan Eßer 
182344d4804dSStefan Eßer 	BcNum copy, btemp;
182444d4804dSStefan Eßer 	BcBigDig exp;
182544d4804dSStefan Eßer 	size_t powrdx, resrdx;
182644d4804dSStefan Eßer 	bool neg;
1827252884aeSStefan Eßer 
182844d4804dSStefan Eßer 	if (BC_ERR(bc_num_nonInt(b, &btemp))) bc_err(BC_ERR_MATH_NON_INTEGER);
1829252884aeSStefan Eßer 
183044d4804dSStefan Eßer 	if (BC_NUM_ZERO(&btemp)) {
1831252884aeSStefan Eßer 		bc_num_one(c);
1832252884aeSStefan Eßer 		return;
1833252884aeSStefan Eßer 	}
183444d4804dSStefan Eßer 
1835252884aeSStefan Eßer 	if (BC_NUM_ZERO(a)) {
183644d4804dSStefan Eßer 		if (BC_NUM_NEG_NP(btemp)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
1837252884aeSStefan Eßer 		bc_num_setToZero(c, scale);
1838252884aeSStefan Eßer 		return;
1839252884aeSStefan Eßer 	}
184044d4804dSStefan Eßer 
184144d4804dSStefan Eßer 	if (BC_NUM_ONE(&btemp)) {
184244d4804dSStefan Eßer 		if (!BC_NUM_NEG_NP(btemp)) bc_num_copy(c, a);
1843252884aeSStefan Eßer 		else bc_num_inv(a, c, scale);
1844252884aeSStefan Eßer 		return;
1845252884aeSStefan Eßer 	}
1846252884aeSStefan Eßer 
184744d4804dSStefan Eßer 	neg = BC_NUM_NEG_NP(btemp);
184844d4804dSStefan Eßer 	BC_NUM_NEG_CLR_NP(btemp);
1849252884aeSStefan Eßer 
185044d4804dSStefan Eßer 	exp = bc_num_bigdig(&btemp);
185144d4804dSStefan Eßer 
185244d4804dSStefan Eßer 	BC_SIG_LOCK;
1853252884aeSStefan Eßer 
1854252884aeSStefan Eßer 	bc_num_createCopy(&copy, a);
1855252884aeSStefan Eßer 
1856252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
1857252884aeSStefan Eßer 
1858252884aeSStefan Eßer 	BC_SIG_UNLOCK;
1859252884aeSStefan Eßer 
186044d4804dSStefan Eßer 	// If this is true, then we do not have to do a division, and we need to
186144d4804dSStefan Eßer 	// set scale accordingly.
1862252884aeSStefan Eßer 	if (!neg) {
186344d4804dSStefan Eßer 		size_t max = BC_MAX(scale, a->scale), scalepow;
186444d4804dSStefan Eßer 		scalepow = bc_num_mulOverflow(a->scale, exp);
1865252884aeSStefan Eßer 		scale = BC_MIN(scalepow, max);
1866252884aeSStefan Eßer 	}
1867252884aeSStefan Eßer 
186844d4804dSStefan Eßer 	// This is only implementing the first exponentiation by squaring, until it
186944d4804dSStefan Eßer 	// reaches the first time where the square is actually used.
187044d4804dSStefan Eßer 	for (powrdx = a->scale; !(exp & 1); exp >>= 1) {
1871252884aeSStefan Eßer 		powrdx <<= 1;
187250696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(copy));
1873252884aeSStefan Eßer 		bc_num_mul(&copy, &copy, &copy, powrdx);
1874252884aeSStefan Eßer 	}
1875252884aeSStefan Eßer 
187644d4804dSStefan Eßer 	// Make c a copy of copy for the purpose of saving the squares that should
187744d4804dSStefan Eßer 	// be saved.
1878252884aeSStefan Eßer 	bc_num_copy(c, &copy);
1879252884aeSStefan Eßer 	resrdx = powrdx;
1880252884aeSStefan Eßer 
188144d4804dSStefan Eßer 	// Now finish the exponentiation by squaring, this time saving the squares
188244d4804dSStefan Eßer 	// as necessary.
188344d4804dSStefan Eßer 	while (exp >>= 1) {
1884252884aeSStefan Eßer 
1885252884aeSStefan Eßer 		powrdx <<= 1;
188650696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(copy));
1887252884aeSStefan Eßer 		bc_num_mul(&copy, &copy, &copy, powrdx);
1888252884aeSStefan Eßer 
188944d4804dSStefan Eßer 		// If this is true, we want to save that particular square. This does
189044d4804dSStefan Eßer 		// that by multiplying c with copy.
189144d4804dSStefan Eßer 		if (exp & 1) {
1892252884aeSStefan Eßer 			resrdx += powrdx;
189350696a6eSStefan Eßer 			assert(BC_NUM_RDX_VALID(c));
189450696a6eSStefan Eßer 			assert(BC_NUM_RDX_VALID_NP(copy));
1895252884aeSStefan Eßer 			bc_num_mul(c, &copy, c, resrdx);
1896252884aeSStefan Eßer 		}
1897252884aeSStefan Eßer 	}
1898252884aeSStefan Eßer 
189944d4804dSStefan Eßer 	// Invert if necessary.
1900252884aeSStefan Eßer 	if (neg) bc_num_inv(c, c, scale);
1901252884aeSStefan Eßer 
190244d4804dSStefan Eßer 	// Truncate if necessary.
1903252884aeSStefan Eßer 	if (c->scale > scale) bc_num_truncate(c, c->scale - scale);
1904252884aeSStefan Eßer 
190544d4804dSStefan Eßer 	bc_num_clean(c);
1906252884aeSStefan Eßer 
1907252884aeSStefan Eßer err:
1908252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
1909252884aeSStefan Eßer 	bc_num_free(&copy);
1910252884aeSStefan Eßer 	BC_LONGJMP_CONT;
1911252884aeSStefan Eßer }
1912252884aeSStefan Eßer 
1913252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
191444d4804dSStefan Eßer /**
191544d4804dSStefan Eßer  * Implements the places operator. This is a BcNumBinOp function.
191644d4804dSStefan Eßer  * @param a      The first operand.
191744d4804dSStefan Eßer  * @param b      The second operand.
191844d4804dSStefan Eßer  * @param c      The return parameter.
191944d4804dSStefan Eßer  * @param scale  The current scale.
192044d4804dSStefan Eßer  */
1921252884aeSStefan Eßer static void bc_num_place(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1922252884aeSStefan Eßer 
192344d4804dSStefan Eßer 	BcBigDig val;
1924252884aeSStefan Eßer 
1925252884aeSStefan Eßer 	BC_UNUSED(scale);
1926252884aeSStefan Eßer 
192744d4804dSStefan Eßer 	val = bc_num_intop(a, b, c);
1928252884aeSStefan Eßer 
192944d4804dSStefan Eßer 	// Just truncate or extend as appropriate.
1930252884aeSStefan Eßer 	if (val < c->scale) bc_num_truncate(c, c->scale - val);
1931252884aeSStefan Eßer 	else if (val > c->scale) bc_num_extend(c, val - c->scale);
1932252884aeSStefan Eßer }
1933252884aeSStefan Eßer 
193444d4804dSStefan Eßer /**
193544d4804dSStefan Eßer  * Implements the left shift operator. This is a BcNumBinOp function.
193644d4804dSStefan Eßer  */
1937252884aeSStefan Eßer static void bc_num_left(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1938252884aeSStefan Eßer 
193944d4804dSStefan Eßer 	BcBigDig val;
1940252884aeSStefan Eßer 
1941252884aeSStefan Eßer 	BC_UNUSED(scale);
1942252884aeSStefan Eßer 
194344d4804dSStefan Eßer 	val = bc_num_intop(a, b, c);
1944252884aeSStefan Eßer 
1945252884aeSStefan Eßer 	bc_num_shiftLeft(c, (size_t) val);
1946252884aeSStefan Eßer }
1947252884aeSStefan Eßer 
194844d4804dSStefan Eßer /**
194944d4804dSStefan Eßer  * Implements the right shift operator. This is a BcNumBinOp function.
195044d4804dSStefan Eßer  */
1951252884aeSStefan Eßer static void bc_num_right(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1952252884aeSStefan Eßer 
195344d4804dSStefan Eßer 	BcBigDig val;
1954252884aeSStefan Eßer 
1955252884aeSStefan Eßer 	BC_UNUSED(scale);
1956252884aeSStefan Eßer 
195744d4804dSStefan Eßer 	val = bc_num_intop(a, b, c);
1958252884aeSStefan Eßer 
1959252884aeSStefan Eßer 	if (BC_NUM_ZERO(c)) return;
1960252884aeSStefan Eßer 
1961252884aeSStefan Eßer 	bc_num_shiftRight(c, (size_t) val);
1962252884aeSStefan Eßer }
1963252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
1964252884aeSStefan Eßer 
196544d4804dSStefan Eßer /**
196644d4804dSStefan Eßer  * Prepares for, and calls, a binary operator function. This is probably the
196744d4804dSStefan Eßer  * most important function in the entire file because it establishes assumptions
196844d4804dSStefan Eßer  * that make the rest of the code so easy. Those assumptions include:
196944d4804dSStefan Eßer  *
197044d4804dSStefan Eßer  * - a is not the same pointer as c.
197144d4804dSStefan Eßer  * - b is not the same pointer as c.
197244d4804dSStefan Eßer  * - there is enough room in c for the result.
197344d4804dSStefan Eßer  *
197444d4804dSStefan Eßer  * Without these, this whole function would basically have to be duplicated for
197544d4804dSStefan Eßer  * *all* binary operators.
197644d4804dSStefan Eßer  *
197744d4804dSStefan Eßer  * @param a      The first operand.
197844d4804dSStefan Eßer  * @param b      The second operand.
197944d4804dSStefan Eßer  * @param c      The return parameter.
198044d4804dSStefan Eßer  * @param scale  The current scale.
198144d4804dSStefan Eßer  * @param req    The number of limbs needed to fit the result.
198244d4804dSStefan Eßer  */
1983252884aeSStefan Eßer static void bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
19847e5c51e5SStefan Eßer                           BcNumBinOp op, size_t req)
1985252884aeSStefan Eßer {
198650696a6eSStefan Eßer 	BcNum *ptr_a, *ptr_b, num2;
1987252884aeSStefan Eßer 	bool init = false;
1988252884aeSStefan Eßer 
1989252884aeSStefan Eßer 	assert(a != NULL && b != NULL && c != NULL && op != NULL);
1990252884aeSStefan Eßer 
199150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
199250696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
199350696a6eSStefan Eßer 
1994252884aeSStefan Eßer 	BC_SIG_LOCK;
1995252884aeSStefan Eßer 
199644d4804dSStefan Eßer 	// Reallocate if c == a.
1997252884aeSStefan Eßer 	if (c == a) {
1998252884aeSStefan Eßer 
1999252884aeSStefan Eßer 		ptr_a = &num2;
2000252884aeSStefan Eßer 
2001252884aeSStefan Eßer 		memcpy(ptr_a, c, sizeof(BcNum));
2002252884aeSStefan Eßer 		init = true;
2003252884aeSStefan Eßer 	}
200450696a6eSStefan Eßer 	else {
200550696a6eSStefan Eßer 		ptr_a = a;
200650696a6eSStefan Eßer 	}
2007252884aeSStefan Eßer 
200844d4804dSStefan Eßer 	// Also reallocate if c == b.
2009252884aeSStefan Eßer 	if (c == b) {
2010252884aeSStefan Eßer 
2011252884aeSStefan Eßer 		ptr_b = &num2;
2012252884aeSStefan Eßer 
2013252884aeSStefan Eßer 		if (c != a) {
2014252884aeSStefan Eßer 			memcpy(ptr_b, c, sizeof(BcNum));
2015252884aeSStefan Eßer 			init = true;
2016252884aeSStefan Eßer 		}
2017252884aeSStefan Eßer 	}
201850696a6eSStefan Eßer 	else {
201950696a6eSStefan Eßer 		ptr_b = b;
202050696a6eSStefan Eßer 	}
2021252884aeSStefan Eßer 
202244d4804dSStefan Eßer 	// Actually reallocate. If we don't reallocate, we want to expand at the
202344d4804dSStefan Eßer 	// very least.
2024252884aeSStefan Eßer 	if (init) {
2025252884aeSStefan Eßer 
2026252884aeSStefan Eßer 		bc_num_init(c, req);
2027252884aeSStefan Eßer 
202844d4804dSStefan Eßer 		// Must prepare for cleanup. We want this here so that locals that got
202944d4804dSStefan Eßer 		// set stay set since a longjmp() is not guaranteed to preserve locals.
2030252884aeSStefan Eßer 		BC_SETJMP_LOCKED(err);
2031252884aeSStefan Eßer 		BC_SIG_UNLOCK;
2032252884aeSStefan Eßer 	}
2033252884aeSStefan Eßer 	else {
2034252884aeSStefan Eßer 		BC_SIG_UNLOCK;
2035252884aeSStefan Eßer 		bc_num_expand(c, req);
2036252884aeSStefan Eßer 	}
2037252884aeSStefan Eßer 
203844d4804dSStefan Eßer 	// It is okay for a and b to be the same. If a binary operator function does
203944d4804dSStefan Eßer 	// need them to be different, the binary operator function is responsible
204044d4804dSStefan Eßer 	// for that.
204144d4804dSStefan Eßer 
204244d4804dSStefan Eßer 	// Call the actual binary operator function.
2043252884aeSStefan Eßer 	op(ptr_a, ptr_b, c, scale);
2044252884aeSStefan Eßer 
204550696a6eSStefan Eßer 	assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
204650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
204750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(c));
204850696a6eSStefan Eßer 	assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
2049252884aeSStefan Eßer 
2050252884aeSStefan Eßer err:
205144d4804dSStefan Eßer 	// Cleanup only needed if we initialized c to a new number.
2052252884aeSStefan Eßer 	if (init) {
2053252884aeSStefan Eßer 		BC_SIG_MAYLOCK;
2054252884aeSStefan Eßer 		bc_num_free(&num2);
2055252884aeSStefan Eßer 		BC_LONGJMP_CONT;
2056252884aeSStefan Eßer 	}
2057252884aeSStefan Eßer }
2058252884aeSStefan Eßer 
205950696a6eSStefan Eßer #if !defined(NDEBUG) || BC_ENABLE_LIBRARY
206044d4804dSStefan Eßer 
206144d4804dSStefan Eßer /**
206244d4804dSStefan Eßer  * Tests a number string for validity. This function has a history; I originally
206344d4804dSStefan Eßer  * wrote it because I did not trust my parser. Over time, however, I came to
206444d4804dSStefan Eßer  * trust it, so I was able to relegate this function to debug builds only, and I
206544d4804dSStefan Eßer  * used it in assert()'s. But then I created the library, and well, I can't
206644d4804dSStefan Eßer  * trust users, so I reused this for yelling at users.
206744d4804dSStefan Eßer  * @param val  The string to check to see if it's a valid number string.
206844d4804dSStefan Eßer  * @return     True if the string is a valid number string, false otherwise.
206944d4804dSStefan Eßer  */
207050696a6eSStefan Eßer bool bc_num_strValid(const char *restrict val) {
2071252884aeSStefan Eßer 
2072252884aeSStefan Eßer 	bool radix = false;
2073252884aeSStefan Eßer 	size_t i, len = strlen(val);
2074252884aeSStefan Eßer 
207544d4804dSStefan Eßer 	// Notice that I don't check if there is a negative sign. That is not part
207644d4804dSStefan Eßer 	// of a valid number, except in the library. The library-specific code takes
207744d4804dSStefan Eßer 	// care of that part.
207844d4804dSStefan Eßer 
207944d4804dSStefan Eßer 	// Nothing in the string is okay.
2080252884aeSStefan Eßer 	if (!len) return true;
2081252884aeSStefan Eßer 
208244d4804dSStefan Eßer 	// Loop through the characters.
2083252884aeSStefan Eßer 	for (i = 0; i < len; ++i) {
2084252884aeSStefan Eßer 
2085252884aeSStefan Eßer 		BcDig c = val[i];
2086252884aeSStefan Eßer 
208744d4804dSStefan Eßer 		// If we have found a radix point...
2088252884aeSStefan Eßer 		if (c == '.') {
2089252884aeSStefan Eßer 
209044d4804dSStefan Eßer 			// We don't allow two radices.
2091252884aeSStefan Eßer 			if (radix) return false;
2092252884aeSStefan Eßer 
2093252884aeSStefan Eßer 			radix = true;
2094252884aeSStefan Eßer 			continue;
2095252884aeSStefan Eßer 		}
2096252884aeSStefan Eßer 
209744d4804dSStefan Eßer 		// We only allow digits and uppercase letters.
2098252884aeSStefan Eßer 		if (!(isdigit(c) || isupper(c))) return false;
2099252884aeSStefan Eßer 	}
2100252884aeSStefan Eßer 
2101252884aeSStefan Eßer 	return true;
2102252884aeSStefan Eßer }
210350696a6eSStefan Eßer #endif // !defined(NDEBUG) || BC_ENABLE_LIBRARY
2104252884aeSStefan Eßer 
210544d4804dSStefan Eßer /**
210644d4804dSStefan Eßer  * Parses one character and returns the digit that corresponds to that
210744d4804dSStefan Eßer  * character according to the base.
210844d4804dSStefan Eßer  * @param c     The character to parse.
210944d4804dSStefan Eßer  * @param base  The base.
211044d4804dSStefan Eßer  * @return      The character as a digit.
211144d4804dSStefan Eßer  */
211244d4804dSStefan Eßer static BcBigDig bc_num_parseChar(char c, size_t base) {
2113252884aeSStefan Eßer 
211444d4804dSStefan Eßer 	assert(isupper(c) || isdigit(c));
211544d4804dSStefan Eßer 
211644d4804dSStefan Eßer 	// If a letter...
2117252884aeSStefan Eßer 	if (isupper(c)) {
211844d4804dSStefan Eßer 
211944d4804dSStefan Eßer 		// This returns the digit that directly corresponds with the letter.
2120252884aeSStefan Eßer 		c = BC_NUM_NUM_LETTER(c);
212144d4804dSStefan Eßer 
212244d4804dSStefan Eßer 		// If the digit is greater than the base, we clamp.
212344d4804dSStefan Eßer 		c = ((size_t) c) >= base ? (char) base - 1 : c;
2124252884aeSStefan Eßer 	}
212544d4804dSStefan Eßer 	// Straight convert the digit to a number.
2126252884aeSStefan Eßer 	else c -= '0';
2127252884aeSStefan Eßer 
2128252884aeSStefan Eßer 	return (BcBigDig) (uchar) c;
2129252884aeSStefan Eßer }
2130252884aeSStefan Eßer 
213144d4804dSStefan Eßer /**
213244d4804dSStefan Eßer  * Parses a string as a decimal number. This is separate because it's going to
213344d4804dSStefan Eßer  * be the most used, and it can be heavily optimized for decimal only.
213444d4804dSStefan Eßer  * @param n    The number to parse into and return. Must be preallocated.
213544d4804dSStefan Eßer  * @param val  The string to parse.
213644d4804dSStefan Eßer  */
2137252884aeSStefan Eßer static void bc_num_parseDecimal(BcNum *restrict n, const char *restrict val) {
2138252884aeSStefan Eßer 
2139252884aeSStefan Eßer 	size_t len, i, temp, mod;
2140252884aeSStefan Eßer 	const char *ptr;
2141252884aeSStefan Eßer 	bool zero = true, rdx;
2142252884aeSStefan Eßer 
214344d4804dSStefan Eßer 	// Eat leading zeroes.
2144252884aeSStefan Eßer 	for (i = 0; val[i] == '0'; ++i);
2145252884aeSStefan Eßer 
2146252884aeSStefan Eßer 	val += i;
2147252884aeSStefan Eßer 	assert(!val[0] || isalnum(val[0]) || val[0] == '.');
2148252884aeSStefan Eßer 
214944d4804dSStefan Eßer 	// All 0's. We can just return, since this procedure expects a virgin
215044d4804dSStefan Eßer 	// (already 0) BcNum.
2151252884aeSStefan Eßer 	if (!val[0]) return;
2152252884aeSStefan Eßer 
215344d4804dSStefan Eßer 	// The length of the string is the length of the number, except it might be
215444d4804dSStefan Eßer 	// one bigger because of a decimal point.
2155252884aeSStefan Eßer 	len = strlen(val);
2156252884aeSStefan Eßer 
215744d4804dSStefan Eßer 	// Find the location of the decimal point.
2158252884aeSStefan Eßer 	ptr = strchr(val, '.');
2159252884aeSStefan Eßer 	rdx = (ptr != NULL);
2160252884aeSStefan Eßer 
216144d4804dSStefan Eßer 	// We eat leading zeroes again. These leading zeroes are different because
216244d4804dSStefan Eßer 	// they will come after the decimal point if they exist, and since that's
216344d4804dSStefan Eßer 	// the case, they must be preserved.
2164252884aeSStefan Eßer 	for (i = 0; i < len && (zero = (val[i] == '0' || val[i] == '.')); ++i);
2165252884aeSStefan Eßer 
216644d4804dSStefan Eßer 	// Set the scale of the number based on the location of the decimal point.
216744d4804dSStefan Eßer 	// The casts to uintptr_t is to ensure that bc does not hit undefined
216844d4804dSStefan Eßer 	// behavior when doing math on the values.
2169d213476dSStefan Eßer 	n->scale = (size_t) (rdx * (((uintptr_t) (val + len)) -
2170d213476dSStefan Eßer 	                            (((uintptr_t) ptr) + 1)));
2171252884aeSStefan Eßer 
217244d4804dSStefan Eßer 	// Set rdx.
217350696a6eSStefan Eßer 	BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
217444d4804dSStefan Eßer 
217544d4804dSStefan Eßer 	// Calculate length. First, the length of the integer, then the number of
217644d4804dSStefan Eßer 	// digits in the last limb, then the length.
2177252884aeSStefan Eßer 	i = len - (ptr == val ? 0 : i) - rdx;
2178252884aeSStefan Eßer 	temp = BC_NUM_ROUND_POW(i);
2179252884aeSStefan Eßer 	mod = n->scale % BC_BASE_DIGS;
2180252884aeSStefan Eßer 	i = mod ? BC_BASE_DIGS - mod : 0;
2181252884aeSStefan Eßer 	n->len = ((temp + i) / BC_BASE_DIGS);
2182252884aeSStefan Eßer 
218344d4804dSStefan Eßer 	// Expand and zero.
2184252884aeSStefan Eßer 	bc_num_expand(n, n->len);
2185252884aeSStefan Eßer 	memset(n->num, 0, BC_NUM_SIZE(n->len));
2186252884aeSStefan Eßer 
218750696a6eSStefan Eßer 	if (zero) {
218850696a6eSStefan Eßer 		// I think I can set rdx directly to zero here because n should be a
218950696a6eSStefan Eßer 		// new number with sign set to false.
219050696a6eSStefan Eßer 		n->len = n->rdx = 0;
219150696a6eSStefan Eßer 	}
2192252884aeSStefan Eßer 	else {
2193252884aeSStefan Eßer 
219444d4804dSStefan Eßer 		// There is actually stuff to parse if we make it here. Yay...
2195252884aeSStefan Eßer 		BcBigDig exp, pow;
2196252884aeSStefan Eßer 
2197252884aeSStefan Eßer 		assert(i <= BC_NUM_BIGDIG_MAX);
2198252884aeSStefan Eßer 
219944d4804dSStefan Eßer 		// The exponent and power.
2200252884aeSStefan Eßer 		exp = (BcBigDig) i;
2201252884aeSStefan Eßer 		pow = bc_num_pow10[exp];
2202252884aeSStefan Eßer 
220344d4804dSStefan Eßer 		// Parse loop. We parse backwards because numbers are stored little
220444d4804dSStefan Eßer 		// endian.
2205252884aeSStefan Eßer 		for (i = len - 1; i < len; --i, ++exp) {
2206252884aeSStefan Eßer 
2207252884aeSStefan Eßer 			char c = val[i];
2208252884aeSStefan Eßer 
220944d4804dSStefan Eßer 			// Skip the decimal point.
2210252884aeSStefan Eßer 			if (c == '.') exp -= 1;
2211252884aeSStefan Eßer 			else {
2212252884aeSStefan Eßer 
221344d4804dSStefan Eßer 				// The index of the limb.
2214252884aeSStefan Eßer 				size_t idx = exp / BC_BASE_DIGS;
2215252884aeSStefan Eßer 
221644d4804dSStefan Eßer 				// Clamp for the base.
2217252884aeSStefan Eßer 				if (isupper(c)) c = '9';
221844d4804dSStefan Eßer 
221944d4804dSStefan Eßer 				// Add the digit to the limb.
2220252884aeSStefan Eßer 				n->num[idx] += (((BcBigDig) c) - '0') * pow;
2221252884aeSStefan Eßer 
222244d4804dSStefan Eßer 				// Adjust the power and exponent.
2223252884aeSStefan Eßer 				if ((exp + 1) % BC_BASE_DIGS == 0) pow = 1;
2224252884aeSStefan Eßer 				else pow *= BC_BASE;
2225252884aeSStefan Eßer 			}
2226252884aeSStefan Eßer 		}
2227252884aeSStefan Eßer 	}
2228252884aeSStefan Eßer }
2229252884aeSStefan Eßer 
223044d4804dSStefan Eßer /**
223144d4804dSStefan Eßer  * Parse a number in any base (besides decimal).
223244d4804dSStefan Eßer  * @param n     The number to parse into and return. Must be preallocated.
223344d4804dSStefan Eßer  * @param val   The string to parse.
223444d4804dSStefan Eßer  * @param base  The base to parse as.
223544d4804dSStefan Eßer  */
2236252884aeSStefan Eßer static void bc_num_parseBase(BcNum *restrict n, const char *restrict val,
2237252884aeSStefan Eßer                              BcBigDig base)
2238252884aeSStefan Eßer {
2239252884aeSStefan Eßer 	BcNum temp, mult1, mult2, result1, result2, *m1, *m2, *ptr;
2240252884aeSStefan Eßer 	char c = 0;
2241252884aeSStefan Eßer 	bool zero = true;
2242252884aeSStefan Eßer 	BcBigDig v;
2243252884aeSStefan Eßer 	size_t i, digs, len = strlen(val);
2244252884aeSStefan Eßer 
224544d4804dSStefan Eßer 	// If zero, just return because the number should be virgin (already 0).
2246252884aeSStefan Eßer 	for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0');
2247252884aeSStefan Eßer 	if (zero) return;
2248252884aeSStefan Eßer 
2249252884aeSStefan Eßer 	BC_SIG_LOCK;
2250252884aeSStefan Eßer 
2251252884aeSStefan Eßer 	bc_num_init(&temp, BC_NUM_BIGDIG_LOG10);
2252252884aeSStefan Eßer 	bc_num_init(&mult1, BC_NUM_BIGDIG_LOG10);
2253252884aeSStefan Eßer 
2254252884aeSStefan Eßer 	BC_SETJMP_LOCKED(int_err);
2255252884aeSStefan Eßer 
2256252884aeSStefan Eßer 	BC_SIG_UNLOCK;
2257252884aeSStefan Eßer 
225844d4804dSStefan Eßer 	// We split parsing into parsing the integer and parsing the fractional
225944d4804dSStefan Eßer 	// part.
226044d4804dSStefan Eßer 
226144d4804dSStefan Eßer 	// Parse the integer part. This is the easy part because we just multiply
226244d4804dSStefan Eßer 	// the number by the base, then add the digit.
2263252884aeSStefan Eßer 	for (i = 0; i < len && (c = val[i]) && c != '.'; ++i) {
2264252884aeSStefan Eßer 
226544d4804dSStefan Eßer 		// Convert the character to a digit.
2266252884aeSStefan Eßer 		v = bc_num_parseChar(c, base);
2267252884aeSStefan Eßer 
226844d4804dSStefan Eßer 		// Multiply the number.
2269252884aeSStefan Eßer 		bc_num_mulArray(n, base, &mult1);
227044d4804dSStefan Eßer 
227144d4804dSStefan Eßer 		// Convert the digit to a number and add.
2272252884aeSStefan Eßer 		bc_num_bigdig2num(&temp, v);
2273252884aeSStefan Eßer 		bc_num_add(&mult1, &temp, n, 0);
2274252884aeSStefan Eßer 	}
2275252884aeSStefan Eßer 
227644d4804dSStefan Eßer 	// If this condition is true, then we are done. We still need to do cleanup
227744d4804dSStefan Eßer 	// though.
227810328f8bSStefan Eßer 	if (i == len && !val[i]) goto int_err;
2279252884aeSStefan Eßer 
228044d4804dSStefan Eßer 	// If we get here, we *must* be at the radix point.
228110328f8bSStefan Eßer 	assert(val[i] == '.');
2282252884aeSStefan Eßer 
2283252884aeSStefan Eßer 	BC_SIG_LOCK;
2284252884aeSStefan Eßer 
228544d4804dSStefan Eßer 	// Unset the jump to reset in for these new initializations.
2286252884aeSStefan Eßer 	BC_UNSETJMP;
2287252884aeSStefan Eßer 
2288252884aeSStefan Eßer 	bc_num_init(&mult2, BC_NUM_BIGDIG_LOG10);
2289252884aeSStefan Eßer 	bc_num_init(&result1, BC_NUM_DEF_SIZE);
2290252884aeSStefan Eßer 	bc_num_init(&result2, BC_NUM_DEF_SIZE);
2291252884aeSStefan Eßer 	bc_num_one(&mult1);
2292252884aeSStefan Eßer 
2293252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
2294252884aeSStefan Eßer 
2295252884aeSStefan Eßer 	BC_SIG_UNLOCK;
2296252884aeSStefan Eßer 
229744d4804dSStefan Eßer 	// Pointers for easy switching.
2298252884aeSStefan Eßer 	m1 = &mult1;
2299252884aeSStefan Eßer 	m2 = &mult2;
2300252884aeSStefan Eßer 
230144d4804dSStefan Eßer 	// Parse the fractional part. This is the hard part.
2302252884aeSStefan Eßer 	for (i += 1, digs = 0; i < len && (c = val[i]); ++i, ++digs) {
2303252884aeSStefan Eßer 
230450696a6eSStefan Eßer 		size_t rdx;
230550696a6eSStefan Eßer 
230644d4804dSStefan Eßer 		// Convert the character to a digit.
2307252884aeSStefan Eßer 		v = bc_num_parseChar(c, base);
2308252884aeSStefan Eßer 
230944d4804dSStefan Eßer 		// We keep growing result2 according to the base because the more digits
231044d4804dSStefan Eßer 		// after the radix, the more significant the digits close to the radix
231144d4804dSStefan Eßer 		// should be.
2312252884aeSStefan Eßer 		bc_num_mulArray(&result1, base, &result2);
2313252884aeSStefan Eßer 
231444d4804dSStefan Eßer 		// Convert the digit to a number.
2315252884aeSStefan Eßer 		bc_num_bigdig2num(&temp, v);
231644d4804dSStefan Eßer 
231744d4804dSStefan Eßer 		// Add the digit into the fraction part.
2318252884aeSStefan Eßer 		bc_num_add(&result2, &temp, &result1, 0);
231944d4804dSStefan Eßer 
232044d4804dSStefan Eßer 		// Keep growing m1 and m2 for use after the loop.
2321252884aeSStefan Eßer 		bc_num_mulArray(m1, base, m2);
2322252884aeSStefan Eßer 
232350696a6eSStefan Eßer 		rdx = BC_NUM_RDX_VAL(m2);
232450696a6eSStefan Eßer 
232550696a6eSStefan Eßer 		if (m2->len < rdx) m2->len = rdx;
2326252884aeSStefan Eßer 
232744d4804dSStefan Eßer 		// Switch.
2328252884aeSStefan Eßer 		ptr = m1;
2329252884aeSStefan Eßer 		m1 = m2;
2330252884aeSStefan Eßer 		m2 = ptr;
2331252884aeSStefan Eßer 	}
2332252884aeSStefan Eßer 
2333252884aeSStefan Eßer 	// This one cannot be a divide by 0 because mult starts out at 1, then is
233444d4804dSStefan Eßer 	// multiplied by base, and base cannot be 0, so mult cannot be 0. And this
233544d4804dSStefan Eßer 	// is the reason we keep growing m1 and m2; this division is what converts
233644d4804dSStefan Eßer 	// the parsed fractional part from an integer to a fractional part.
2337252884aeSStefan Eßer 	bc_num_div(&result1, m1, &result2, digs * 2);
233844d4804dSStefan Eßer 
233944d4804dSStefan Eßer 	// Pretruncate.
2340252884aeSStefan Eßer 	bc_num_truncate(&result2, digs);
234144d4804dSStefan Eßer 
234244d4804dSStefan Eßer 	// The final add of the integer part to the fractional part.
2343252884aeSStefan Eßer 	bc_num_add(n, &result2, n, digs);
2344252884aeSStefan Eßer 
234544d4804dSStefan Eßer 	// Basic cleanup.
2346252884aeSStefan Eßer 	if (BC_NUM_NONZERO(n)) {
2347252884aeSStefan Eßer 		if (n->scale < digs) bc_num_extend(n, digs - n->scale);
2348252884aeSStefan Eßer 	}
2349252884aeSStefan Eßer 	else bc_num_zero(n);
2350252884aeSStefan Eßer 
2351252884aeSStefan Eßer err:
2352252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
2353252884aeSStefan Eßer 	bc_num_free(&result2);
2354252884aeSStefan Eßer 	bc_num_free(&result1);
2355252884aeSStefan Eßer 	bc_num_free(&mult2);
2356252884aeSStefan Eßer int_err:
2357252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
2358252884aeSStefan Eßer 	bc_num_free(&mult1);
2359252884aeSStefan Eßer 	bc_num_free(&temp);
2360252884aeSStefan Eßer 	BC_LONGJMP_CONT;
2361252884aeSStefan Eßer }
2362252884aeSStefan Eßer 
236344d4804dSStefan Eßer /**
236444d4804dSStefan Eßer  * Prints a backslash+newline combo if the number of characters needs it. This
236544d4804dSStefan Eßer  * is really a convenience function.
236644d4804dSStefan Eßer  */
236750696a6eSStefan Eßer static inline void bc_num_printNewline(void) {
236850696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
2369*d43fa8efSStefan Eßer 	if (vm.nchars >= vm.line_len - 1 && vm.line_len) {
23707e5c51e5SStefan Eßer 		bc_vm_putchar('\\', bc_flush_none);
23717e5c51e5SStefan Eßer 		bc_vm_putchar('\n', bc_flush_err);
2372252884aeSStefan Eßer 	}
237350696a6eSStefan Eßer #endif // !BC_ENABLE_LIBRARY
2374252884aeSStefan Eßer }
2375252884aeSStefan Eßer 
237644d4804dSStefan Eßer /**
237744d4804dSStefan Eßer  * Prints a character after a backslash+newline, if needed.
237844d4804dSStefan Eßer  * @param c       The character to print.
237944d4804dSStefan Eßer  * @param bslash  Whether to print a backslash+newline.
238044d4804dSStefan Eßer  */
238144d4804dSStefan Eßer static void bc_num_putchar(int c, bool bslash) {
238244d4804dSStefan Eßer 	if (c != '\n' && bslash) bc_num_printNewline();
23837e5c51e5SStefan Eßer 	bc_vm_putchar(c, bc_flush_save);
2384252884aeSStefan Eßer }
2385252884aeSStefan Eßer 
238644d4804dSStefan Eßer #if !BC_ENABLE_LIBRARY
238744d4804dSStefan Eßer 
238844d4804dSStefan Eßer /**
238944d4804dSStefan Eßer  * Prints a character for a number's digit. This is for printing for dc's P
239044d4804dSStefan Eßer  * command. This function does not need to worry about radix points. This is a
239144d4804dSStefan Eßer  * BcNumDigitOp.
239244d4804dSStefan Eßer  * @param n       The "digit" to print.
239344d4804dSStefan Eßer  * @param len     The "length" of the digit, or number of characters that will
239444d4804dSStefan Eßer  *                need to be printed for the digit.
239544d4804dSStefan Eßer  * @param rdx     True if a decimal (radix) point should be printed.
239644d4804dSStefan Eßer  * @param bslash  True if a backslash+newline should be printed if the character
239744d4804dSStefan Eßer  *                limit for the line is reached, false otherwise.
239844d4804dSStefan Eßer  */
239944d4804dSStefan Eßer static void bc_num_printChar(size_t n, size_t len, bool rdx, bool bslash) {
2400252884aeSStefan Eßer 	BC_UNUSED(rdx);
2401252884aeSStefan Eßer 	BC_UNUSED(len);
240244d4804dSStefan Eßer 	BC_UNUSED(bslash);
2403252884aeSStefan Eßer 	assert(len == 1);
24047e5c51e5SStefan Eßer 	bc_vm_putchar((uchar) n, bc_flush_save);
2405252884aeSStefan Eßer }
2406252884aeSStefan Eßer 
240744d4804dSStefan Eßer #endif // !BC_ENABLE_LIBRARY
240844d4804dSStefan Eßer 
240944d4804dSStefan Eßer /**
241044d4804dSStefan Eßer  * Prints a series of characters for large bases. This is for printing in bases
241144d4804dSStefan Eßer  * above hexadecimal. This is a BcNumDigitOp.
241244d4804dSStefan Eßer  * @param n       The "digit" to print.
241344d4804dSStefan Eßer  * @param len     The "length" of the digit, or number of characters that will
241444d4804dSStefan Eßer  *                need to be printed for the digit.
241544d4804dSStefan Eßer  * @param rdx     True if a decimal (radix) point should be printed.
241644d4804dSStefan Eßer  * @param bslash  True if a backslash+newline should be printed if the character
241744d4804dSStefan Eßer  *                limit for the line is reached, false otherwise.
241844d4804dSStefan Eßer  */
241944d4804dSStefan Eßer static void bc_num_printDigits(size_t n, size_t len, bool rdx, bool bslash) {
2420252884aeSStefan Eßer 
2421252884aeSStefan Eßer 	size_t exp, pow;
2422252884aeSStefan Eßer 
242344d4804dSStefan Eßer 	// If needed, print the radix; otherwise, print a space to separate digits.
242444d4804dSStefan Eßer 	bc_num_putchar(rdx ? '.' : ' ', true);
2425252884aeSStefan Eßer 
242644d4804dSStefan Eßer 	// Calculate the exponent and power.
2427252884aeSStefan Eßer 	for (exp = 0, pow = 1; exp < len - 1; ++exp, pow *= BC_BASE);
2428252884aeSStefan Eßer 
242944d4804dSStefan Eßer 	// Print each character individually.
2430252884aeSStefan Eßer 	for (exp = 0; exp < len; pow /= BC_BASE, ++exp) {
243144d4804dSStefan Eßer 
243244d4804dSStefan Eßer 		// The individual subdigit.
2433252884aeSStefan Eßer 		size_t dig = n / pow;
243444d4804dSStefan Eßer 
243544d4804dSStefan Eßer 		// Take the subdigit away.
2436252884aeSStefan Eßer 		n -= dig * pow;
243744d4804dSStefan Eßer 
243844d4804dSStefan Eßer 		// Print the subdigit.
243944d4804dSStefan Eßer 		bc_num_putchar(((uchar) dig) + '0', bslash || exp != len - 1);
2440252884aeSStefan Eßer 	}
2441252884aeSStefan Eßer }
2442252884aeSStefan Eßer 
244344d4804dSStefan Eßer /**
244444d4804dSStefan Eßer  * Prints a character for a number's digit. This is for printing in bases for
244544d4804dSStefan Eßer  * hexadecimal and below because they always print only one character at a time.
244644d4804dSStefan Eßer  * This is a BcNumDigitOp.
244744d4804dSStefan Eßer  * @param n       The "digit" to print.
244844d4804dSStefan Eßer  * @param len     The "length" of the digit, or number of characters that will
244944d4804dSStefan Eßer  *                need to be printed for the digit.
245044d4804dSStefan Eßer  * @param rdx     True if a decimal (radix) point should be printed.
245144d4804dSStefan Eßer  * @param bslash  True if a backslash+newline should be printed if the character
245244d4804dSStefan Eßer  *                limit for the line is reached, false otherwise.
245344d4804dSStefan Eßer  */
245444d4804dSStefan Eßer static void bc_num_printHex(size_t n, size_t len, bool rdx, bool bslash) {
2455252884aeSStefan Eßer 
2456252884aeSStefan Eßer 	BC_UNUSED(len);
245744d4804dSStefan Eßer 	BC_UNUSED(bslash);
2458252884aeSStefan Eßer 
2459252884aeSStefan Eßer 	assert(len == 1);
2460252884aeSStefan Eßer 
246144d4804dSStefan Eßer 	if (rdx) bc_num_putchar('.', true);
2462252884aeSStefan Eßer 
246344d4804dSStefan Eßer 	bc_num_putchar(bc_num_hex_digits[n], bslash);
2464252884aeSStefan Eßer }
2465252884aeSStefan Eßer 
246644d4804dSStefan Eßer /**
246744d4804dSStefan Eßer  * Prints a decimal number. This is specially written for optimization since
246844d4804dSStefan Eßer  * this will be used the most and because bc's numbers are already in decimal.
246944d4804dSStefan Eßer  * @param n        The number to print.
247044d4804dSStefan Eßer  * @param newline  Whether to print backslash+newlines on long enough lines.
247144d4804dSStefan Eßer  */
247244d4804dSStefan Eßer static void bc_num_printDecimal(const BcNum *restrict n, bool newline) {
2473252884aeSStefan Eßer 
247450696a6eSStefan Eßer 	size_t i, j, rdx = BC_NUM_RDX_VAL(n);
2475252884aeSStefan Eßer 	bool zero = true;
2476252884aeSStefan Eßer 	size_t buffer[BC_BASE_DIGS];
2477252884aeSStefan Eßer 
247844d4804dSStefan Eßer 	// Print loop.
2479252884aeSStefan Eßer 	for (i = n->len - 1; i < n->len; --i) {
2480252884aeSStefan Eßer 
2481252884aeSStefan Eßer 		BcDig n9 = n->num[i];
2482252884aeSStefan Eßer 		size_t temp;
2483252884aeSStefan Eßer 		bool irdx = (i == rdx - 1);
2484252884aeSStefan Eßer 
248544d4804dSStefan Eßer 		// Calculate the number of digits in the limb.
2486252884aeSStefan Eßer 		zero = (zero & !irdx);
2487252884aeSStefan Eßer 		temp = n->scale % BC_BASE_DIGS;
2488252884aeSStefan Eßer 		temp = i || !temp ? 0 : BC_BASE_DIGS - temp;
2489252884aeSStefan Eßer 
2490252884aeSStefan Eßer 		memset(buffer, 0, BC_BASE_DIGS * sizeof(size_t));
2491252884aeSStefan Eßer 
249244d4804dSStefan Eßer 		// Fill the buffer with individual digits.
2493252884aeSStefan Eßer 		for (j = 0; n9 && j < BC_BASE_DIGS; ++j) {
2494d213476dSStefan Eßer 			buffer[j] = ((size_t) n9) % BC_BASE;
2495252884aeSStefan Eßer 			n9 /= BC_BASE;
2496252884aeSStefan Eßer 		}
2497252884aeSStefan Eßer 
249844d4804dSStefan Eßer 		// Print the digits in the buffer.
2499252884aeSStefan Eßer 		for (j = BC_BASE_DIGS - 1; j < BC_BASE_DIGS && j >= temp; --j) {
250044d4804dSStefan Eßer 
250144d4804dSStefan Eßer 			// Figure out whether to print the decimal point.
2502252884aeSStefan Eßer 			bool print_rdx = (irdx & (j == BC_BASE_DIGS - 1));
250344d4804dSStefan Eßer 
250444d4804dSStefan Eßer 			// The zero variable helps us skip leading zero digits in the limb.
2505252884aeSStefan Eßer 			zero = (zero && buffer[j] == 0);
250644d4804dSStefan Eßer 
250744d4804dSStefan Eßer 			if (!zero) {
250844d4804dSStefan Eßer 
250944d4804dSStefan Eßer 				// While the first three arguments should be self-explanatory,
251044d4804dSStefan Eßer 				// the last needs explaining. I don't want to print a newline
251144d4804dSStefan Eßer 				// when the last digit to be printed could take the place of the
251244d4804dSStefan Eßer 				// backslash rather than being pushed, as a single character, to
251344d4804dSStefan Eßer 				// the next line. That's what that last argument does for bc.
251444d4804dSStefan Eßer 				bc_num_printHex(buffer[j], 1, print_rdx,
251544d4804dSStefan Eßer 				                !newline || (j > temp || i != 0));
251644d4804dSStefan Eßer 			}
2517252884aeSStefan Eßer 		}
2518252884aeSStefan Eßer 	}
2519252884aeSStefan Eßer }
2520252884aeSStefan Eßer 
2521252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
2522252884aeSStefan Eßer 
252344d4804dSStefan Eßer /**
252444d4804dSStefan Eßer  * Prints a number in scientific or engineering format. When doing this, we are
252544d4804dSStefan Eßer  * always printing in decimal.
252644d4804dSStefan Eßer  * @param n        The number to print.
252744d4804dSStefan Eßer  * @param eng      True if we are in engineering mode.
252844d4804dSStefan Eßer  * @param newline  Whether to print backslash+newlines on long enough lines.
252944d4804dSStefan Eßer  */
253044d4804dSStefan Eßer static void bc_num_printExponent(const BcNum *restrict n,
253144d4804dSStefan Eßer                                  bool eng, bool newline)
253244d4804dSStefan Eßer {
253350696a6eSStefan Eßer 	size_t places, mod, nrdx = BC_NUM_RDX_VAL(n);
253450696a6eSStefan Eßer 	bool neg = (n->len <= nrdx);
2535252884aeSStefan Eßer 	BcNum temp, exp;
2536252884aeSStefan Eßer 	BcDig digs[BC_NUM_BIGDIG_LOG10];
2537252884aeSStefan Eßer 
2538252884aeSStefan Eßer 	BC_SIG_LOCK;
2539252884aeSStefan Eßer 
2540252884aeSStefan Eßer 	bc_num_createCopy(&temp, n);
2541252884aeSStefan Eßer 
2542252884aeSStefan Eßer 	BC_SETJMP_LOCKED(exit);
2543252884aeSStefan Eßer 
2544252884aeSStefan Eßer 	BC_SIG_UNLOCK;
2545252884aeSStefan Eßer 
254644d4804dSStefan Eßer 	// We need to calculate the exponents, and they change based on whether the
254744d4804dSStefan Eßer 	// number is all fractional or not, obviously.
2548252884aeSStefan Eßer 	if (neg) {
2549252884aeSStefan Eßer 
255044d4804dSStefan Eßer 		// Figure out how many limbs after the decimal point is zero.
255144d4804dSStefan Eßer 		size_t i, idx = bc_num_nonZeroLen(n) - 1;
2552252884aeSStefan Eßer 
2553252884aeSStefan Eßer 		places = 1;
2554252884aeSStefan Eßer 
255544d4804dSStefan Eßer 		// Figure out how much in the last limb is zero.
2556252884aeSStefan Eßer 		for (i = BC_BASE_DIGS - 1; i < BC_BASE_DIGS; --i) {
2557252884aeSStefan Eßer 			if (bc_num_pow10[i] > (BcBigDig) n->num[idx]) places += 1;
2558252884aeSStefan Eßer 			else break;
2559252884aeSStefan Eßer 		}
2560252884aeSStefan Eßer 
256144d4804dSStefan Eßer 		// Calculate the combination of zero limbs and zero digits in the last
256244d4804dSStefan Eßer 		// limb.
256350696a6eSStefan Eßer 		places += (nrdx - (idx + 1)) * BC_BASE_DIGS;
2564252884aeSStefan Eßer 		mod = places % 3;
2565252884aeSStefan Eßer 
256644d4804dSStefan Eßer 		// Calculate places if we are in engineering mode.
2567252884aeSStefan Eßer 		if (eng && mod != 0) places += 3 - mod;
256844d4804dSStefan Eßer 
256944d4804dSStefan Eßer 		// Shift the temp to the right place.
2570252884aeSStefan Eßer 		bc_num_shiftLeft(&temp, places);
2571252884aeSStefan Eßer 	}
2572252884aeSStefan Eßer 	else {
257344d4804dSStefan Eßer 
257444d4804dSStefan Eßer 		// This is the number of digits that we are supposed to put behind the
257544d4804dSStefan Eßer 		// decimal point.
2576252884aeSStefan Eßer 		places = bc_num_intDigits(n) - 1;
257744d4804dSStefan Eßer 
257844d4804dSStefan Eßer 		// Calculate the true number based on whether engineering mode is
257944d4804dSStefan Eßer 		// activated.
2580252884aeSStefan Eßer 		mod = places % 3;
2581252884aeSStefan Eßer 		if (eng && mod != 0) places -= 3 - (3 - mod);
258244d4804dSStefan Eßer 
258344d4804dSStefan Eßer 		// Shift the temp to the right place.
2584252884aeSStefan Eßer 		bc_num_shiftRight(&temp, places);
2585252884aeSStefan Eßer 	}
2586252884aeSStefan Eßer 
258744d4804dSStefan Eßer 	// Print the shifted number.
258844d4804dSStefan Eßer 	bc_num_printDecimal(&temp, newline);
2589252884aeSStefan Eßer 
259044d4804dSStefan Eßer 	// Print the e.
259144d4804dSStefan Eßer 	bc_num_putchar('e', !newline);
259244d4804dSStefan Eßer 
259344d4804dSStefan Eßer 	// Need to explicitly print a zero exponent.
2594252884aeSStefan Eßer 	if (!places) {
259544d4804dSStefan Eßer 		bc_num_printHex(0, 1, false, !newline);
2596252884aeSStefan Eßer 		goto exit;
2597252884aeSStefan Eßer 	}
2598252884aeSStefan Eßer 
259944d4804dSStefan Eßer 	// Need to print sign for the exponent.
260044d4804dSStefan Eßer 	if (neg) bc_num_putchar('-', true);
2601252884aeSStefan Eßer 
260244d4804dSStefan Eßer 	// Create a temporary for the exponent...
2603252884aeSStefan Eßer 	bc_num_setup(&exp, digs, BC_NUM_BIGDIG_LOG10);
2604252884aeSStefan Eßer 	bc_num_bigdig2num(&exp, (BcBigDig) places);
2605252884aeSStefan Eßer 
260644d4804dSStefan Eßer 	/// ..and print it.
260744d4804dSStefan Eßer 	bc_num_printDecimal(&exp, newline);
2608252884aeSStefan Eßer 
2609252884aeSStefan Eßer exit:
2610252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
2611252884aeSStefan Eßer 	bc_num_free(&temp);
2612252884aeSStefan Eßer 	BC_LONGJMP_CONT;
2613252884aeSStefan Eßer }
2614252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
2615252884aeSStefan Eßer 
261644d4804dSStefan Eßer /**
261744d4804dSStefan Eßer  * Converts a number from limbs with base BC_BASE_POW to base @a pow, where
261844d4804dSStefan Eßer  * @a pow is obase^N.
261944d4804dSStefan Eßer  * @param n    The number to convert.
262044d4804dSStefan Eßer  * @param rem  BC_BASE_POW - @a pow.
262144d4804dSStefan Eßer  * @param pow  The power of obase we will convert the number to.
262244d4804dSStefan Eßer  * @param idx  The index of the number to start converting at. Doing the
262344d4804dSStefan Eßer  *             conversion is O(n^2); we have to sweep through starting at the
262444d4804dSStefan Eßer  *             least significant limb
262544d4804dSStefan Eßer  */
2626252884aeSStefan Eßer static void bc_num_printFixup(BcNum *restrict n, BcBigDig rem,
2627252884aeSStefan Eßer                               BcBigDig pow, size_t idx)
2628252884aeSStefan Eßer {
2629252884aeSStefan Eßer 	size_t i, len = n->len - idx;
2630252884aeSStefan Eßer 	BcBigDig acc;
2631252884aeSStefan Eßer 	BcDig *a = n->num + idx;
2632252884aeSStefan Eßer 
263344d4804dSStefan Eßer 	// Ignore if there's just one limb left. This is the part that requires the
263444d4804dSStefan Eßer 	// extra loop after the one calling this function in bc_num_printPrepare().
2635252884aeSStefan Eßer 	if (len < 2) return;
2636252884aeSStefan Eßer 
263744d4804dSStefan Eßer 	// Loop through the remaining limbs and convert. We start at the second limb
263844d4804dSStefan Eßer 	// because we pull the value from the previous one as well.
2639252884aeSStefan Eßer 	for (i = len - 1; i > 0; --i) {
2640252884aeSStefan Eßer 
264144d4804dSStefan Eßer 		// Get the limb and add it to the previous, along with multiplying by
264244d4804dSStefan Eßer 		// the remainder because that's the proper overflow. "acc" means
264344d4804dSStefan Eßer 		// "accumulator," by the way.
2644252884aeSStefan Eßer 		acc = ((BcBigDig) a[i]) * rem + ((BcBigDig) a[i - 1]);
264544d4804dSStefan Eßer 
264644d4804dSStefan Eßer 		// Store a value in base pow in the previous limb.
2647252884aeSStefan Eßer 		a[i - 1] = (BcDig) (acc % pow);
264844d4804dSStefan Eßer 
264944d4804dSStefan Eßer 		// Divide by the base and accumulate the remaining value in the limb.
2650252884aeSStefan Eßer 		acc /= pow;
2651252884aeSStefan Eßer 		acc += (BcBigDig) a[i];
2652252884aeSStefan Eßer 
265344d4804dSStefan Eßer 		// If the accumulator is greater than the base...
2654252884aeSStefan Eßer 		if (acc >= BC_BASE_POW) {
2655252884aeSStefan Eßer 
265644d4804dSStefan Eßer 			// Do we need to grow?
2657252884aeSStefan Eßer 			if (i == len - 1) {
265844d4804dSStefan Eßer 
265944d4804dSStefan Eßer 				// Grow.
2660252884aeSStefan Eßer 				len = bc_vm_growSize(len, 1);
2661252884aeSStefan Eßer 				bc_num_expand(n, bc_vm_growSize(len, idx));
266244d4804dSStefan Eßer 
266344d4804dSStefan Eßer 				// Update the pointer because it may have moved.
2664252884aeSStefan Eßer 				a = n->num + idx;
266544d4804dSStefan Eßer 
266644d4804dSStefan Eßer 				// Zero out the last limb.
2667252884aeSStefan Eßer 				a[len - 1] = 0;
2668252884aeSStefan Eßer 			}
2669252884aeSStefan Eßer 
267044d4804dSStefan Eßer 			// Overflow into the next limb since we are over the base.
2671252884aeSStefan Eßer 			a[i + 1] += acc / BC_BASE_POW;
2672252884aeSStefan Eßer 			acc %= BC_BASE_POW;
2673252884aeSStefan Eßer 		}
2674252884aeSStefan Eßer 
2675252884aeSStefan Eßer 		assert(acc < BC_BASE_POW);
267644d4804dSStefan Eßer 
267744d4804dSStefan Eßer 		// Set the limb.
2678252884aeSStefan Eßer 		a[i] = (BcDig) acc;
2679252884aeSStefan Eßer 	}
2680252884aeSStefan Eßer 
268144d4804dSStefan Eßer 	// We may have grown the number, so adjust the length.
2682252884aeSStefan Eßer 	n->len = len + idx;
2683252884aeSStefan Eßer }
2684252884aeSStefan Eßer 
268544d4804dSStefan Eßer /**
268644d4804dSStefan Eßer  * Prepares a number for printing in a base that is not a divisor of
268744d4804dSStefan Eßer  * BC_BASE_POW. This basically converts the number from having limbs of base
268844d4804dSStefan Eßer  * BC_BASE_POW to limbs of pow, where pow is obase^N.
268944d4804dSStefan Eßer  * @param n    The number to prepare for printing.
269044d4804dSStefan Eßer  * @param rem  The remainder of BC_BASE_POW when divided by a power of the base.
269144d4804dSStefan Eßer  * @param pow  The power of the base.
269244d4804dSStefan Eßer  */
269344d4804dSStefan Eßer static void bc_num_printPrepare(BcNum *restrict n, BcBigDig rem, BcBigDig pow) {
269444d4804dSStefan Eßer 
2695252884aeSStefan Eßer 	size_t i;
2696252884aeSStefan Eßer 
269744d4804dSStefan Eßer 	// Loop from the least significant limb to the most significant limb and
269844d4804dSStefan Eßer 	// convert limbs in each pass.
2699252884aeSStefan Eßer 	for (i = 0; i < n->len; ++i) bc_num_printFixup(n, rem, pow, i);
2700252884aeSStefan Eßer 
270144d4804dSStefan Eßer 	// bc_num_printFixup() does not do everything it is supposed to, so we do
270244d4804dSStefan Eßer 	// the last bit of cleanup here. That cleanup is to ensure that each limb
270344d4804dSStefan Eßer 	// is less than pow and to expand the number to fit new limbs as necessary.
2704252884aeSStefan Eßer 	for (i = 0; i < n->len; ++i) {
2705252884aeSStefan Eßer 
2706252884aeSStefan Eßer 		assert(pow == ((BcBigDig) ((BcDig) pow)));
2707252884aeSStefan Eßer 
270844d4804dSStefan Eßer 		// If the limb needs fixing...
2709252884aeSStefan Eßer 		if (n->num[i] >= (BcDig) pow) {
2710252884aeSStefan Eßer 
271144d4804dSStefan Eßer 			// Do we need to grow?
2712252884aeSStefan Eßer 			if (i + 1 == n->len) {
271344d4804dSStefan Eßer 
271444d4804dSStefan Eßer 				// Grow the number.
2715252884aeSStefan Eßer 				n->len = bc_vm_growSize(n->len, 1);
2716252884aeSStefan Eßer 				bc_num_expand(n, n->len);
271744d4804dSStefan Eßer 
271844d4804dSStefan Eßer 				// Without this, we might use uninitialized data.
2719252884aeSStefan Eßer 				n->num[i + 1] = 0;
2720252884aeSStefan Eßer 			}
2721252884aeSStefan Eßer 
2722252884aeSStefan Eßer 			assert(pow < BC_BASE_POW);
272344d4804dSStefan Eßer 
272444d4804dSStefan Eßer 			// Overflow into the next limb.
2725252884aeSStefan Eßer 			n->num[i + 1] += n->num[i] / ((BcDig) pow);
2726252884aeSStefan Eßer 			n->num[i] %= (BcDig) pow;
2727252884aeSStefan Eßer 		}
2728252884aeSStefan Eßer 	}
2729252884aeSStefan Eßer }
2730252884aeSStefan Eßer 
273144d4804dSStefan Eßer static void bc_num_printNum(BcNum *restrict n, BcBigDig base, size_t len,
273244d4804dSStefan Eßer                             BcNumDigitOp print, bool newline)
2733252884aeSStefan Eßer {
2734252884aeSStefan Eßer 	BcVec stack;
2735252884aeSStefan Eßer 	BcNum intp, fracp1, fracp2, digit, flen1, flen2, *n1, *n2, *temp;
2736252884aeSStefan Eßer 	BcBigDig dig = 0, *ptr, acc, exp;
273744d4804dSStefan Eßer 	size_t i, j, nrdx, idigits;
2738252884aeSStefan Eßer 	bool radix;
2739252884aeSStefan Eßer 	BcDig digit_digs[BC_NUM_BIGDIG_LOG10 + 1];
2740252884aeSStefan Eßer 
2741252884aeSStefan Eßer 	assert(base > 1);
2742252884aeSStefan Eßer 
274344d4804dSStefan Eßer 	// Easy case. Even with scale, we just print this.
2744252884aeSStefan Eßer 	if (BC_NUM_ZERO(n)) {
274544d4804dSStefan Eßer 		print(0, len, false, !newline);
2746252884aeSStefan Eßer 		return;
2747252884aeSStefan Eßer 	}
2748252884aeSStefan Eßer 
2749252884aeSStefan Eßer 	// This function uses an algorithm that Stefan Esser <se@freebsd.org> came
2750252884aeSStefan Eßer 	// up with to print the integer part of a number. What it does is convert
2751252884aeSStefan Eßer 	// intp into a number of the specified base, but it does it directly,
2752252884aeSStefan Eßer 	// instead of just doing a series of divisions and printing the remainders
2753252884aeSStefan Eßer 	// in reverse order.
2754252884aeSStefan Eßer 	//
2755252884aeSStefan Eßer 	// Let me explain in a bit more detail:
2756252884aeSStefan Eßer 	//
275744d4804dSStefan Eßer 	// The algorithm takes the current least significant limb (after intp has
275844d4804dSStefan Eßer 	// been converted to an integer) and the next to least significant limb, and
275944d4804dSStefan Eßer 	// it converts the least significant limb into one of the specified base,
276044d4804dSStefan Eßer 	// putting any overflow into the next to least significant limb. It iterates
276144d4804dSStefan Eßer 	// through the whole number, from least significant to most significant,
276244d4804dSStefan Eßer 	// doing this conversion. At the end of that iteration, the least
276344d4804dSStefan Eßer 	// significant limb is converted, but the others are not, so it iterates
276444d4804dSStefan Eßer 	// again, starting at the next to least significant limb. It keeps doing
276544d4804dSStefan Eßer 	// that conversion, skipping one more limb than the last time, until all
276644d4804dSStefan Eßer 	// limbs have been converted. Then it prints them in reverse order.
2767252884aeSStefan Eßer 	//
2768252884aeSStefan Eßer 	// That is the gist of the algorithm. It leaves out several things, such as
276944d4804dSStefan Eßer 	// the fact that limbs are not always converted into the specified base, but
277044d4804dSStefan Eßer 	// into something close, basically a power of the specified base. In
2771252884aeSStefan Eßer 	// Stefan's words, "You could consider BcDigs to be of base 10^BC_BASE_DIGS
2772252884aeSStefan Eßer 	// in the normal case and obase^N for the largest value of N that satisfies
2773252884aeSStefan Eßer 	// obase^N <= 10^BC_BASE_DIGS. [This means that] the result is not in base
2774252884aeSStefan Eßer 	// "obase", but in base "obase^N", which happens to be printable as a number
2775252884aeSStefan Eßer 	// of base "obase" without consideration for neighbouring BcDigs." This fact
2776252884aeSStefan Eßer 	// is what necessitates the existence of the loop later in this function.
2777252884aeSStefan Eßer 	//
2778252884aeSStefan Eßer 	// The conversion happens in bc_num_printPrepare() where the outer loop
2779252884aeSStefan Eßer 	// happens and bc_num_printFixup() where the inner loop, or actual
278044d4804dSStefan Eßer 	// conversion, happens. In other words, bc_num_printPrepare() is where the
278144d4804dSStefan Eßer 	// loop that starts at the least significant limb and goes to the most
278244d4804dSStefan Eßer 	// significant limb. Then, on every iteration of its loop, it calls
278344d4804dSStefan Eßer 	// bc_num_printFixup(), which has the inner loop of actually converting
278444d4804dSStefan Eßer 	// the limbs it passes into limbs of base obase^N rather than base
278544d4804dSStefan Eßer 	// BC_BASE_POW.
2786252884aeSStefan Eßer 
278750696a6eSStefan Eßer 	nrdx = BC_NUM_RDX_VAL(n);
278850696a6eSStefan Eßer 
2789252884aeSStefan Eßer 	BC_SIG_LOCK;
2790252884aeSStefan Eßer 
279144d4804dSStefan Eßer 	// The stack is what allows us to reverse the digits for printing.
279244d4804dSStefan Eßer 	bc_vec_init(&stack, sizeof(BcBigDig), BC_DTOR_NONE);
279350696a6eSStefan Eßer 	bc_num_init(&fracp1, nrdx);
2794252884aeSStefan Eßer 
279544d4804dSStefan Eßer 	// intp will be the "integer part" of the number, so copy it.
2796252884aeSStefan Eßer 	bc_num_createCopy(&intp, n);
2797252884aeSStefan Eßer 
2798252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
2799252884aeSStefan Eßer 
2800252884aeSStefan Eßer 	BC_SIG_UNLOCK;
2801252884aeSStefan Eßer 
280244d4804dSStefan Eßer 	// Make intp an integer.
2803252884aeSStefan Eßer 	bc_num_truncate(&intp, intp.scale);
2804252884aeSStefan Eßer 
280544d4804dSStefan Eßer 	// Get the fractional part out.
2806252884aeSStefan Eßer 	bc_num_sub(n, &intp, &fracp1, 0);
2807252884aeSStefan Eßer 
280844d4804dSStefan Eßer 	// If the base is not the same as the last base used for printing, we need
280944d4804dSStefan Eßer 	// to update the cached exponent and power. Yes, we cache the values of the
281044d4804dSStefan Eßer 	// exponent and power. That is to prevent us from calculating them every
281144d4804dSStefan Eßer 	// time because printing will probably happen multiple times on the same
281244d4804dSStefan Eßer 	// base.
2813252884aeSStefan Eßer 	if (base != vm.last_base) {
2814252884aeSStefan Eßer 
2815252884aeSStefan Eßer 		vm.last_pow = 1;
2816252884aeSStefan Eßer 		vm.last_exp = 0;
2817252884aeSStefan Eßer 
281844d4804dSStefan Eßer 		// Calculate the exponent and power.
2819252884aeSStefan Eßer 		while (vm.last_pow * base <= BC_BASE_POW) {
2820252884aeSStefan Eßer 			vm.last_pow *= base;
2821252884aeSStefan Eßer 			vm.last_exp += 1;
2822252884aeSStefan Eßer 		}
2823252884aeSStefan Eßer 
282444d4804dSStefan Eßer 		// Also, the remainder and base itself.
2825252884aeSStefan Eßer 		vm.last_rem = BC_BASE_POW - vm.last_pow;
2826252884aeSStefan Eßer 		vm.last_base = base;
2827252884aeSStefan Eßer 	}
2828252884aeSStefan Eßer 
2829252884aeSStefan Eßer 	exp = vm.last_exp;
2830252884aeSStefan Eßer 
283144d4804dSStefan Eßer 	// If vm.last_rem is 0, then the base we are printing in is a divisor of
283244d4804dSStefan Eßer 	// BC_BASE_POW, which is the easy case because it means that BC_BASE_POW is
283344d4804dSStefan Eßer 	// a power of obase, and no conversion is needed. If it *is* 0, then we have
283444d4804dSStefan Eßer 	// the hard case, and we have to prepare the number for the base.
2835252884aeSStefan Eßer 	if (vm.last_rem != 0) bc_num_printPrepare(&intp, vm.last_rem, vm.last_pow);
2836252884aeSStefan Eßer 
283744d4804dSStefan Eßer 	// After the conversion comes the surprisingly easy part. From here on out,
283844d4804dSStefan Eßer 	// this is basically naive code that I wrote, adjusted for the larger bases.
283944d4804dSStefan Eßer 
284044d4804dSStefan Eßer 	// Fill the stack of digits for the integer part.
2841252884aeSStefan Eßer 	for (i = 0; i < intp.len; ++i) {
2842252884aeSStefan Eßer 
284344d4804dSStefan Eßer 		// Get the limb.
2844252884aeSStefan Eßer 		acc = (BcBigDig) intp.num[i];
2845252884aeSStefan Eßer 
284644d4804dSStefan Eßer 		// Turn the limb into digits of base obase.
2847252884aeSStefan Eßer 		for (j = 0; j < exp && (i < intp.len - 1 || acc != 0); ++j)
2848252884aeSStefan Eßer 		{
284944d4804dSStefan Eßer 			// This condition is true if we are not at the last digit.
2850252884aeSStefan Eßer 			if (j != exp - 1) {
2851252884aeSStefan Eßer 				dig = acc % base;
2852252884aeSStefan Eßer 				acc /= base;
2853252884aeSStefan Eßer 			}
2854252884aeSStefan Eßer 			else {
2855252884aeSStefan Eßer 				dig = acc;
2856252884aeSStefan Eßer 				acc = 0;
2857252884aeSStefan Eßer 			}
2858252884aeSStefan Eßer 
2859252884aeSStefan Eßer 			assert(dig < base);
2860252884aeSStefan Eßer 
286144d4804dSStefan Eßer 			// Push the digit onto the stack.
2862252884aeSStefan Eßer 			bc_vec_push(&stack, &dig);
2863252884aeSStefan Eßer 		}
2864252884aeSStefan Eßer 
2865252884aeSStefan Eßer 		assert(acc == 0);
2866252884aeSStefan Eßer 	}
2867252884aeSStefan Eßer 
286844d4804dSStefan Eßer 	// Go through the stack backwards and print each digit.
2869252884aeSStefan Eßer 	for (i = 0; i < stack.len; ++i) {
287044d4804dSStefan Eßer 
2871252884aeSStefan Eßer 		ptr = bc_vec_item_rev(&stack, i);
287244d4804dSStefan Eßer 
2873252884aeSStefan Eßer 		assert(ptr != NULL);
287444d4804dSStefan Eßer 
287544d4804dSStefan Eßer 		// While the first three arguments should be self-explanatory, the last
287644d4804dSStefan Eßer 		// needs explaining. I don't want to print a newline when the last digit
287744d4804dSStefan Eßer 		// to be printed could take the place of the backslash rather than being
287844d4804dSStefan Eßer 		// pushed, as a single character, to the next line. That's what that
287944d4804dSStefan Eßer 		// last argument does for bc.
288044d4804dSStefan Eßer 		print(*ptr, len, false, !newline ||
288144d4804dSStefan Eßer 		      (n->scale != 0 || i == stack.len - 1));
2882252884aeSStefan Eßer 	}
2883252884aeSStefan Eßer 
288444d4804dSStefan Eßer 	// We are done if there is no fractional part.
2885252884aeSStefan Eßer 	if (!n->scale) goto err;
2886252884aeSStefan Eßer 
2887252884aeSStefan Eßer 	BC_SIG_LOCK;
2888252884aeSStefan Eßer 
288944d4804dSStefan Eßer 	// Reset the jump because some locals are changing.
2890252884aeSStefan Eßer 	BC_UNSETJMP;
2891252884aeSStefan Eßer 
289250696a6eSStefan Eßer 	bc_num_init(&fracp2, nrdx);
2893252884aeSStefan Eßer 	bc_num_setup(&digit, digit_digs, sizeof(digit_digs) / sizeof(BcDig));
2894252884aeSStefan Eßer 	bc_num_init(&flen1, BC_NUM_BIGDIG_LOG10);
2895252884aeSStefan Eßer 	bc_num_init(&flen2, BC_NUM_BIGDIG_LOG10);
2896252884aeSStefan Eßer 
2897252884aeSStefan Eßer 	BC_SETJMP_LOCKED(frac_err);
2898252884aeSStefan Eßer 
2899252884aeSStefan Eßer 	BC_SIG_UNLOCK;
2900252884aeSStefan Eßer 
2901252884aeSStefan Eßer 	bc_num_one(&flen1);
2902252884aeSStefan Eßer 
2903252884aeSStefan Eßer 	radix = true;
290444d4804dSStefan Eßer 
290544d4804dSStefan Eßer 	// Pointers for easy switching.
2906252884aeSStefan Eßer 	n1 = &flen1;
2907252884aeSStefan Eßer 	n2 = &flen2;
2908252884aeSStefan Eßer 
2909252884aeSStefan Eßer 	fracp2.scale = n->scale;
291050696a6eSStefan Eßer 	BC_NUM_RDX_SET_NP(fracp2, BC_NUM_RDX(fracp2.scale));
2911252884aeSStefan Eßer 
291244d4804dSStefan Eßer 	// As long as we have not reached the scale of the number, keep printing.
291344d4804dSStefan Eßer 	while ((idigits = bc_num_intDigits(n1)) <= n->scale) {
2914252884aeSStefan Eßer 
291544d4804dSStefan Eßer 		// These numbers will keep growing.
2916252884aeSStefan Eßer 		bc_num_expand(&fracp2, fracp1.len + 1);
2917252884aeSStefan Eßer 		bc_num_mulArray(&fracp1, base, &fracp2);
291850696a6eSStefan Eßer 
291950696a6eSStefan Eßer 		nrdx = BC_NUM_RDX_VAL_NP(fracp2);
292050696a6eSStefan Eßer 
292144d4804dSStefan Eßer 		// Ensure an invariant.
292250696a6eSStefan Eßer 		if (fracp2.len < nrdx) fracp2.len = nrdx;
2923252884aeSStefan Eßer 
2924252884aeSStefan Eßer 		// fracp is guaranteed to be non-negative and small enough.
292544d4804dSStefan Eßer 		dig = bc_num_bigdig2(&fracp2);
2926252884aeSStefan Eßer 
292744d4804dSStefan Eßer 		// Convert the digit to a number and subtract it from the number.
2928252884aeSStefan Eßer 		bc_num_bigdig2num(&digit, dig);
2929252884aeSStefan Eßer 		bc_num_sub(&fracp2, &digit, &fracp1, 0);
2930252884aeSStefan Eßer 
293144d4804dSStefan Eßer 		// While the first three arguments should be self-explanatory, the last
293244d4804dSStefan Eßer 		// needs explaining. I don't want to print a newline when the last digit
293344d4804dSStefan Eßer 		// to be printed could take the place of the backslash rather than being
293444d4804dSStefan Eßer 		// pushed, as a single character, to the next line. That's what that
293544d4804dSStefan Eßer 		// last argument does for bc.
293644d4804dSStefan Eßer 		print(dig, len, radix, !newline || idigits != n->scale);
293744d4804dSStefan Eßer 
293844d4804dSStefan Eßer 		// Update the multipliers.
2939252884aeSStefan Eßer 		bc_num_mulArray(n1, base, n2);
2940252884aeSStefan Eßer 
2941252884aeSStefan Eßer 		radix = false;
294244d4804dSStefan Eßer 
294344d4804dSStefan Eßer 		// Switch.
2944252884aeSStefan Eßer 		temp = n1;
2945252884aeSStefan Eßer 		n1 = n2;
2946252884aeSStefan Eßer 		n2 = temp;
2947252884aeSStefan Eßer 	}
2948252884aeSStefan Eßer 
2949252884aeSStefan Eßer frac_err:
2950252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
2951252884aeSStefan Eßer 	bc_num_free(&flen2);
2952252884aeSStefan Eßer 	bc_num_free(&flen1);
2953252884aeSStefan Eßer 	bc_num_free(&fracp2);
2954252884aeSStefan Eßer err:
2955252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
2956252884aeSStefan Eßer 	bc_num_free(&fracp1);
2957252884aeSStefan Eßer 	bc_num_free(&intp);
2958252884aeSStefan Eßer 	bc_vec_free(&stack);
2959252884aeSStefan Eßer 	BC_LONGJMP_CONT;
2960252884aeSStefan Eßer }
2961252884aeSStefan Eßer 
296244d4804dSStefan Eßer /**
296344d4804dSStefan Eßer  * Prints a number in the specified base, or rather, figures out which function
296444d4804dSStefan Eßer  * to call to print the number in the specified base and calls it.
296544d4804dSStefan Eßer  * @param n        The number to print.
296644d4804dSStefan Eßer  * @param base     The base to print in.
296744d4804dSStefan Eßer  * @param newline  Whether to print backslash+newlines on long enough lines.
296844d4804dSStefan Eßer  */
296944d4804dSStefan Eßer static void bc_num_printBase(BcNum *restrict n, BcBigDig base, bool newline) {
2970252884aeSStefan Eßer 
2971252884aeSStefan Eßer 	size_t width;
2972252884aeSStefan Eßer 	BcNumDigitOp print;
297350696a6eSStefan Eßer 	bool neg = BC_NUM_NEG(n);
2974252884aeSStefan Eßer 
297544d4804dSStefan Eßer 	// Clear the sign because it makes the actual printing easier when we have
297644d4804dSStefan Eßer 	// to do math.
297750696a6eSStefan Eßer 	BC_NUM_NEG_CLR(n);
2978252884aeSStefan Eßer 
297944d4804dSStefan Eßer 	// Bases at hexadecimal and below are printed as one character, larger bases
298044d4804dSStefan Eßer 	// are printed as a series of digits separated by spaces.
2981252884aeSStefan Eßer 	if (base <= BC_NUM_MAX_POSIX_IBASE) {
2982252884aeSStefan Eßer 		width = 1;
2983252884aeSStefan Eßer 		print = bc_num_printHex;
2984252884aeSStefan Eßer 	}
2985252884aeSStefan Eßer 	else {
2986252884aeSStefan Eßer 		assert(base <= BC_BASE_POW);
2987252884aeSStefan Eßer 		width = bc_num_log10(base - 1);
2988252884aeSStefan Eßer 		print = bc_num_printDigits;
2989252884aeSStefan Eßer 	}
2990252884aeSStefan Eßer 
299144d4804dSStefan Eßer 	// Print.
299244d4804dSStefan Eßer 	bc_num_printNum(n, base, width, print, newline);
299344d4804dSStefan Eßer 
299444d4804dSStefan Eßer 	// Reset the sign.
299550696a6eSStefan Eßer 	n->rdx = BC_NUM_NEG_VAL(n, neg);
2996252884aeSStefan Eßer }
2997252884aeSStefan Eßer 
299844d4804dSStefan Eßer #if !BC_ENABLE_LIBRARY
299944d4804dSStefan Eßer 
300044d4804dSStefan Eßer void bc_num_stream(BcNum *restrict n) {
300144d4804dSStefan Eßer 	bc_num_printNum(n, BC_NUM_STREAM_BASE, 1, bc_num_printChar, false);
3002252884aeSStefan Eßer }
300344d4804dSStefan Eßer 
300444d4804dSStefan Eßer #endif // !BC_ENABLE_LIBRARY
3005252884aeSStefan Eßer 
3006252884aeSStefan Eßer void bc_num_setup(BcNum *restrict n, BcDig *restrict num, size_t cap) {
3007252884aeSStefan Eßer 	assert(n != NULL);
3008252884aeSStefan Eßer 	n->num = num;
3009252884aeSStefan Eßer 	n->cap = cap;
3010252884aeSStefan Eßer 	bc_num_zero(n);
3011252884aeSStefan Eßer }
3012252884aeSStefan Eßer 
3013252884aeSStefan Eßer void bc_num_init(BcNum *restrict n, size_t req) {
3014252884aeSStefan Eßer 
3015252884aeSStefan Eßer 	BcDig *num;
3016252884aeSStefan Eßer 
3017252884aeSStefan Eßer 	BC_SIG_ASSERT_LOCKED;
3018252884aeSStefan Eßer 
3019252884aeSStefan Eßer 	assert(n != NULL);
3020252884aeSStefan Eßer 
302144d4804dSStefan Eßer 	// BC_NUM_DEF_SIZE is set to be about the smallest allocation size that
302244d4804dSStefan Eßer 	// malloc() returns in practice, so just use it.
3023252884aeSStefan Eßer 	req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
3024252884aeSStefan Eßer 
302544d4804dSStefan Eßer 	// If we can't use a temp, allocate.
302644d4804dSStefan Eßer 	if (req != BC_NUM_DEF_SIZE || (num = bc_vm_takeTemp()) == NULL)
302744d4804dSStefan Eßer 		num = bc_vm_malloc(BC_NUM_SIZE(req));
3028252884aeSStefan Eßer 
3029252884aeSStefan Eßer 	bc_num_setup(n, num, req);
3030252884aeSStefan Eßer }
3031252884aeSStefan Eßer 
3032252884aeSStefan Eßer void bc_num_clear(BcNum *restrict n) {
3033252884aeSStefan Eßer 	n->num = NULL;
3034252884aeSStefan Eßer 	n->cap = 0;
3035252884aeSStefan Eßer }
3036252884aeSStefan Eßer 
3037252884aeSStefan Eßer void bc_num_free(void *num) {
3038252884aeSStefan Eßer 
3039252884aeSStefan Eßer 	BcNum *n = (BcNum*) num;
3040252884aeSStefan Eßer 
3041252884aeSStefan Eßer 	BC_SIG_ASSERT_LOCKED;
3042252884aeSStefan Eßer 
3043252884aeSStefan Eßer 	assert(n != NULL);
3044252884aeSStefan Eßer 
304544d4804dSStefan Eßer 	if (n->cap == BC_NUM_DEF_SIZE) bc_vm_addTemp(n->num);
3046252884aeSStefan Eßer 	else free(n->num);
3047252884aeSStefan Eßer }
3048252884aeSStefan Eßer 
3049252884aeSStefan Eßer void bc_num_copy(BcNum *d, const BcNum *s) {
305044d4804dSStefan Eßer 
3051252884aeSStefan Eßer 	assert(d != NULL && s != NULL);
305244d4804dSStefan Eßer 
3053252884aeSStefan Eßer 	if (d == s) return;
305444d4804dSStefan Eßer 
3055252884aeSStefan Eßer 	bc_num_expand(d, s->len);
3056252884aeSStefan Eßer 	d->len = s->len;
305744d4804dSStefan Eßer 
305844d4804dSStefan Eßer 	// I can just copy directly here because the sign *and* rdx will be
305944d4804dSStefan Eßer 	// properly preserved.
3060252884aeSStefan Eßer 	d->rdx = s->rdx;
3061252884aeSStefan Eßer 	d->scale = s->scale;
3062252884aeSStefan Eßer 	memcpy(d->num, s->num, BC_NUM_SIZE(d->len));
3063252884aeSStefan Eßer }
3064252884aeSStefan Eßer 
3065252884aeSStefan Eßer void bc_num_createCopy(BcNum *d, const BcNum *s) {
3066252884aeSStefan Eßer 	BC_SIG_ASSERT_LOCKED;
3067252884aeSStefan Eßer 	bc_num_init(d, s->len);
3068252884aeSStefan Eßer 	bc_num_copy(d, s);
3069252884aeSStefan Eßer }
3070252884aeSStefan Eßer 
307144d4804dSStefan Eßer void bc_num_createFromBigdig(BcNum *restrict n, BcBigDig val) {
3072252884aeSStefan Eßer 	BC_SIG_ASSERT_LOCKED;
307350696a6eSStefan Eßer 	bc_num_init(n, BC_NUM_BIGDIG_LOG10);
3074252884aeSStefan Eßer 	bc_num_bigdig2num(n, val);
3075252884aeSStefan Eßer }
3076252884aeSStefan Eßer 
3077252884aeSStefan Eßer size_t bc_num_scale(const BcNum *restrict n) {
3078252884aeSStefan Eßer 	return n->scale;
3079252884aeSStefan Eßer }
3080252884aeSStefan Eßer 
3081252884aeSStefan Eßer size_t bc_num_len(const BcNum *restrict n) {
3082252884aeSStefan Eßer 
3083252884aeSStefan Eßer 	size_t len = n->len;
3084252884aeSStefan Eßer 
308544d4804dSStefan Eßer 	// Always return at least 1.
3086028616d0SStefan Eßer 	if (BC_NUM_ZERO(n)) return n->scale ? n->scale : 1;
3087252884aeSStefan Eßer 
308844d4804dSStefan Eßer 	// If this is true, there is no integer portion of the number.
308950696a6eSStefan Eßer 	if (BC_NUM_RDX_VAL(n) == len) {
3090252884aeSStefan Eßer 
309144d4804dSStefan Eßer 		// We have to take into account the fact that some of the digits right
309244d4804dSStefan Eßer 		// after the decimal could be zero. If that is the case, we need to
309344d4804dSStefan Eßer 		// ignore them until we hit the first non-zero digit.
309444d4804dSStefan Eßer 
3095252884aeSStefan Eßer 		size_t zero, scale;
3096252884aeSStefan Eßer 
309744d4804dSStefan Eßer 		// The number of limbs with non-zero digits.
309844d4804dSStefan Eßer 		len = bc_num_nonZeroLen(n);
3099252884aeSStefan Eßer 
310044d4804dSStefan Eßer 		// Get the number of digits in the last limb.
3101252884aeSStefan Eßer 		scale = n->scale % BC_BASE_DIGS;
3102252884aeSStefan Eßer 		scale = scale ? scale : BC_BASE_DIGS;
3103252884aeSStefan Eßer 
310444d4804dSStefan Eßer 		// Get the number of zero digits.
3105252884aeSStefan Eßer 		zero = bc_num_zeroDigits(n->num + len - 1);
3106252884aeSStefan Eßer 
310744d4804dSStefan Eßer 		// Calculate the true length.
3108252884aeSStefan Eßer 		len = len * BC_BASE_DIGS - zero - (BC_BASE_DIGS - scale);
3109252884aeSStefan Eßer 	}
311044d4804dSStefan Eßer 	// Otherwise, count the number of int digits and return that plus the scale.
3111252884aeSStefan Eßer 	else len = bc_num_intDigits(n) + n->scale;
3112252884aeSStefan Eßer 
3113252884aeSStefan Eßer 	return len;
3114252884aeSStefan Eßer }
3115252884aeSStefan Eßer 
311650696a6eSStefan Eßer void bc_num_parse(BcNum *restrict n, const char *restrict val, BcBigDig base) {
311750696a6eSStefan Eßer 
3118252884aeSStefan Eßer 	assert(n != NULL && val != NULL && base);
3119252884aeSStefan Eßer 	assert(base >= BC_NUM_MIN_BASE && base <= vm.maxes[BC_PROG_GLOBALS_IBASE]);
3120252884aeSStefan Eßer 	assert(bc_num_strValid(val));
3121252884aeSStefan Eßer 
312244d4804dSStefan Eßer 	// A one character number is *always* parsed as though the base was the
312344d4804dSStefan Eßer 	// maximum allowed ibase, per the bc spec.
312450696a6eSStefan Eßer 	if (!val[1]) {
3125252884aeSStefan Eßer 		BcBigDig dig = bc_num_parseChar(val[0], BC_NUM_MAX_LBASE);
3126252884aeSStefan Eßer 		bc_num_bigdig2num(n, dig);
3127252884aeSStefan Eßer 	}
3128252884aeSStefan Eßer 	else if (base == BC_BASE) bc_num_parseDecimal(n, val);
3129252884aeSStefan Eßer 	else bc_num_parseBase(n, val, base);
313050696a6eSStefan Eßer 
313150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(n));
3132252884aeSStefan Eßer }
3133252884aeSStefan Eßer 
3134252884aeSStefan Eßer void bc_num_print(BcNum *restrict n, BcBigDig base, bool newline) {
3135252884aeSStefan Eßer 
3136252884aeSStefan Eßer 	assert(n != NULL);
3137252884aeSStefan Eßer 	assert(BC_ENABLE_EXTRA_MATH || base >= BC_NUM_MIN_BASE);
3138252884aeSStefan Eßer 
313944d4804dSStefan Eßer 	// We may need a newline, just to start.
3140252884aeSStefan Eßer 	bc_num_printNewline();
3141252884aeSStefan Eßer 
3142*d43fa8efSStefan Eßer 	if (BC_NUM_NONZERO(n)) {
3143*d43fa8efSStefan Eßer 
3144*d43fa8efSStefan Eßer 		// Print the sign.
3145*d43fa8efSStefan Eßer 		if (BC_NUM_NEG(n)) bc_num_putchar('-', true);
3146*d43fa8efSStefan Eßer 
3147*d43fa8efSStefan Eßer 		// Print the leading zero if necessary.
3148*d43fa8efSStefan Eßer 		if (BC_Z && BC_NUM_RDX_VAL(n) == n->len)
3149*d43fa8efSStefan Eßer 			bc_num_printHex(0, 1, false, !newline);
3150*d43fa8efSStefan Eßer 	}
3151*d43fa8efSStefan Eßer 
315244d4804dSStefan Eßer 	// Short-circuit 0.
315344d4804dSStefan Eßer 	if (BC_NUM_ZERO(n)) bc_num_printHex(0, 1, false, !newline);
315444d4804dSStefan Eßer 	else if (base == BC_BASE) bc_num_printDecimal(n, newline);
3155252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
315644d4804dSStefan Eßer 	else if (base == 0 || base == 1)
315744d4804dSStefan Eßer 		bc_num_printExponent(n, base != 0, newline);
3158252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
315944d4804dSStefan Eßer 	else bc_num_printBase(n, base, newline);
3160252884aeSStefan Eßer 
316144d4804dSStefan Eßer 	if (newline) bc_num_putchar('\n', false);
3162252884aeSStefan Eßer }
3163252884aeSStefan Eßer 
316444d4804dSStefan Eßer BcBigDig bc_num_bigdig2(const BcNum *restrict n) {
3165252884aeSStefan Eßer 
3166252884aeSStefan Eßer 	// This function returns no errors because it's guaranteed to succeed if
316744d4804dSStefan Eßer 	// its preconditions are met. Those preconditions include both n needs to
316844d4804dSStefan Eßer 	// be non-NULL, n being non-negative, and n being less than vm.max. If all
316944d4804dSStefan Eßer 	// of that is true, then we can just convert without worrying about negative
317044d4804dSStefan Eßer 	// errors or overflow.
3171252884aeSStefan Eßer 
3172252884aeSStefan Eßer 	BcBigDig r = 0;
317350696a6eSStefan Eßer 	size_t nrdx = BC_NUM_RDX_VAL(n);
3174252884aeSStefan Eßer 
317544d4804dSStefan Eßer 	assert(n != NULL);
317650696a6eSStefan Eßer 	assert(!BC_NUM_NEG(n));
3177252884aeSStefan Eßer 	assert(bc_num_cmp(n, &vm.max) < 0);
317850696a6eSStefan Eßer 	assert(n->len - nrdx <= 3);
3179252884aeSStefan Eßer 
3180252884aeSStefan Eßer 	// There is a small speed win from unrolling the loop here, and since it
3181252884aeSStefan Eßer 	// only adds 53 bytes, I decided that it was worth it.
318250696a6eSStefan Eßer 	switch (n->len - nrdx) {
318350696a6eSStefan Eßer 
3184252884aeSStefan Eßer 		case 3:
318550696a6eSStefan Eßer 		{
318650696a6eSStefan Eßer 			r = (BcBigDig) n->num[nrdx + 2];
318750696a6eSStefan Eßer 		}
3188252884aeSStefan Eßer 		// Fallthrough.
318950696a6eSStefan Eßer 		BC_FALLTHROUGH
319050696a6eSStefan Eßer 
3191252884aeSStefan Eßer 		case 2:
319250696a6eSStefan Eßer 		{
319350696a6eSStefan Eßer 			r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx + 1];
319450696a6eSStefan Eßer 		}
3195252884aeSStefan Eßer 		// Fallthrough.
319650696a6eSStefan Eßer 		BC_FALLTHROUGH
319750696a6eSStefan Eßer 
3198252884aeSStefan Eßer 		case 1:
319950696a6eSStefan Eßer 		{
320050696a6eSStefan Eßer 			r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx];
320150696a6eSStefan Eßer 		}
3202252884aeSStefan Eßer 	}
3203252884aeSStefan Eßer 
320444d4804dSStefan Eßer 	return r;
3205252884aeSStefan Eßer }
3206252884aeSStefan Eßer 
320744d4804dSStefan Eßer BcBigDig bc_num_bigdig(const BcNum *restrict n) {
3208252884aeSStefan Eßer 
320944d4804dSStefan Eßer 	assert(n != NULL);
3210252884aeSStefan Eßer 
321144d4804dSStefan Eßer 	// This error checking is extremely important, and if you do not have a
321244d4804dSStefan Eßer 	// guarantee that converting a number will always succeed in a particular
321344d4804dSStefan Eßer 	// case, you *must* call this function to get these error checks. This
321444d4804dSStefan Eßer 	// includes all instances of numbers inputted by the user or calculated by
321544d4804dSStefan Eßer 	// the user. Otherwise, you can call the faster bc_num_bigdig2().
321644d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_NEG(n))) bc_err(BC_ERR_MATH_NEGATIVE);
321744d4804dSStefan Eßer 	if (BC_ERR(bc_num_cmp(n, &vm.max) >= 0)) bc_err(BC_ERR_MATH_OVERFLOW);
3218252884aeSStefan Eßer 
321944d4804dSStefan Eßer 	return bc_num_bigdig2(n);
3220252884aeSStefan Eßer }
3221252884aeSStefan Eßer 
3222252884aeSStefan Eßer void bc_num_bigdig2num(BcNum *restrict n, BcBigDig val) {
3223252884aeSStefan Eßer 
3224252884aeSStefan Eßer 	BcDig *ptr;
3225252884aeSStefan Eßer 	size_t i;
3226252884aeSStefan Eßer 
3227252884aeSStefan Eßer 	assert(n != NULL);
3228252884aeSStefan Eßer 
3229252884aeSStefan Eßer 	bc_num_zero(n);
3230252884aeSStefan Eßer 
323144d4804dSStefan Eßer 	// Already 0.
3232252884aeSStefan Eßer 	if (!val) return;
3233252884aeSStefan Eßer 
323444d4804dSStefan Eßer 	// Expand first. This is the only way this function can fail, and it's a
323544d4804dSStefan Eßer 	// fatal error.
3236252884aeSStefan Eßer 	bc_num_expand(n, BC_NUM_BIGDIG_LOG10);
3237252884aeSStefan Eßer 
323844d4804dSStefan Eßer 	// The conversion is easy because numbers are laid out in little-endian
323944d4804dSStefan Eßer 	// order.
3240252884aeSStefan Eßer 	for (ptr = n->num, i = 0; val; ++i, val /= BC_BASE_POW)
3241252884aeSStefan Eßer 		ptr[i] = val % BC_BASE_POW;
3242252884aeSStefan Eßer 
3243252884aeSStefan Eßer 	n->len = i;
3244252884aeSStefan Eßer }
3245252884aeSStefan Eßer 
324644d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH
324744d4804dSStefan Eßer 
3248252884aeSStefan Eßer void bc_num_rng(const BcNum *restrict n, BcRNG *rng) {
3249252884aeSStefan Eßer 
325050696a6eSStefan Eßer 	BcNum temp, temp2, intn, frac;
3251252884aeSStefan Eßer 	BcRand state1, state2, inc1, inc2;
325250696a6eSStefan Eßer 	size_t nrdx = BC_NUM_RDX_VAL(n);
3253252884aeSStefan Eßer 
325444d4804dSStefan Eßer 	// This function holds the secret of how I interpret a seed number for the
325544d4804dSStefan Eßer 	// PRNG. Well, it's actually in the development manual
325644d4804dSStefan Eßer 	// (manuals/development.md#pseudo-random-number-generator), so look there
325744d4804dSStefan Eßer 	// before you try to understand this.
325844d4804dSStefan Eßer 
3259252884aeSStefan Eßer 	BC_SIG_LOCK;
3260252884aeSStefan Eßer 
3261252884aeSStefan Eßer 	bc_num_init(&temp, n->len);
3262252884aeSStefan Eßer 	bc_num_init(&temp2, n->len);
326350696a6eSStefan Eßer 	bc_num_init(&frac, nrdx);
3264252884aeSStefan Eßer 	bc_num_init(&intn, bc_num_int(n));
3265252884aeSStefan Eßer 
3266252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
3267252884aeSStefan Eßer 
3268252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3269252884aeSStefan Eßer 
327050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(vm.max));
3271252884aeSStefan Eßer 
327250696a6eSStefan Eßer 	memcpy(frac.num, n->num, BC_NUM_SIZE(nrdx));
327350696a6eSStefan Eßer 	frac.len = nrdx;
327450696a6eSStefan Eßer 	BC_NUM_RDX_SET_NP(frac, nrdx);
3275252884aeSStefan Eßer 	frac.scale = n->scale;
3276252884aeSStefan Eßer 
327750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(frac));
327850696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(vm.max2));
327950696a6eSStefan Eßer 
328044d4804dSStefan Eßer 	// Multiply the fraction and truncate so that it's an integer. The
328144d4804dSStefan Eßer 	// truncation is what clamps it, by the way.
328250696a6eSStefan Eßer 	bc_num_mul(&frac, &vm.max2, &temp, 0);
3283252884aeSStefan Eßer 	bc_num_truncate(&temp, temp.scale);
3284252884aeSStefan Eßer 	bc_num_copy(&frac, &temp);
3285252884aeSStefan Eßer 
328644d4804dSStefan Eßer 	// Get the integer.
328750696a6eSStefan Eßer 	memcpy(intn.num, n->num + nrdx, BC_NUM_SIZE(bc_num_int(n)));
3288252884aeSStefan Eßer 	intn.len = bc_num_int(n);
3289252884aeSStefan Eßer 
3290252884aeSStefan Eßer 	// This assert is here because it has to be true. It is also here to justify
329144d4804dSStefan Eßer 	// some optimizations.
3292252884aeSStefan Eßer 	assert(BC_NUM_NONZERO(&vm.max));
3293252884aeSStefan Eßer 
329444d4804dSStefan Eßer 	// If there *was* a fractional part...
3295252884aeSStefan Eßer 	if (BC_NUM_NONZERO(&frac)) {
3296252884aeSStefan Eßer 
329744d4804dSStefan Eßer 		// This divmod splits frac into the two state parts.
3298252884aeSStefan Eßer 		bc_num_divmod(&frac, &vm.max, &temp, &temp2, 0);
3299252884aeSStefan Eßer 
3300252884aeSStefan Eßer 		// frac is guaranteed to be smaller than vm.max * vm.max (pow).
3301252884aeSStefan Eßer 		// This means that when dividing frac by vm.max, as above, the
3302252884aeSStefan Eßer 		// quotient and remainder are both guaranteed to be less than vm.max,
3303252884aeSStefan Eßer 		// which means we can use bc_num_bigdig2() here and not worry about
3304252884aeSStefan Eßer 		// overflow.
330544d4804dSStefan Eßer 		state1 = (BcRand) bc_num_bigdig2(&temp2);
330644d4804dSStefan Eßer 		state2 = (BcRand) bc_num_bigdig2(&temp);
3307252884aeSStefan Eßer 	}
3308252884aeSStefan Eßer 	else state1 = state2 = 0;
3309252884aeSStefan Eßer 
331044d4804dSStefan Eßer 	// If there *was* an integer part...
3311252884aeSStefan Eßer 	if (BC_NUM_NONZERO(&intn)) {
3312252884aeSStefan Eßer 
331344d4804dSStefan Eßer 		// This divmod splits intn into the two inc parts.
3314252884aeSStefan Eßer 		bc_num_divmod(&intn, &vm.max, &temp, &temp2, 0);
3315252884aeSStefan Eßer 
3316252884aeSStefan Eßer 		// Because temp2 is the mod of vm.max, from above, it is guaranteed
3317252884aeSStefan Eßer 		// to be small enough to use bc_num_bigdig2().
331844d4804dSStefan Eßer 		inc1 = (BcRand) bc_num_bigdig2(&temp2);
3319252884aeSStefan Eßer 
332044d4804dSStefan Eßer 		// Clamp the second inc part.
3321252884aeSStefan Eßer 		if (bc_num_cmp(&temp, &vm.max) >= 0) {
3322252884aeSStefan Eßer 			bc_num_copy(&temp2, &temp);
3323252884aeSStefan Eßer 			bc_num_mod(&temp2, &vm.max, &temp, 0);
3324252884aeSStefan Eßer 		}
3325252884aeSStefan Eßer 
3326252884aeSStefan Eßer 		// The if statement above ensures that temp is less than vm.max, which
3327252884aeSStefan Eßer 		// means that we can use bc_num_bigdig2() here.
332844d4804dSStefan Eßer 		inc2 = (BcRand) bc_num_bigdig2(&temp);
3329252884aeSStefan Eßer 	}
3330252884aeSStefan Eßer 	else inc1 = inc2 = 0;
3331252884aeSStefan Eßer 
3332252884aeSStefan Eßer 	bc_rand_seed(rng, state1, state2, inc1, inc2);
3333252884aeSStefan Eßer 
3334252884aeSStefan Eßer err:
3335252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
3336252884aeSStefan Eßer 	bc_num_free(&intn);
3337252884aeSStefan Eßer 	bc_num_free(&frac);
3338252884aeSStefan Eßer 	bc_num_free(&temp2);
3339252884aeSStefan Eßer 	bc_num_free(&temp);
3340252884aeSStefan Eßer 	BC_LONGJMP_CONT;
3341252884aeSStefan Eßer }
3342252884aeSStefan Eßer 
3343252884aeSStefan Eßer void bc_num_createFromRNG(BcNum *restrict n, BcRNG *rng) {
3344252884aeSStefan Eßer 
3345252884aeSStefan Eßer 	BcRand s1, s2, i1, i2;
334650696a6eSStefan Eßer 	BcNum conv, temp1, temp2, temp3;
3347252884aeSStefan Eßer 	BcDig temp1_num[BC_RAND_NUM_SIZE], temp2_num[BC_RAND_NUM_SIZE];
3348252884aeSStefan Eßer 	BcDig conv_num[BC_NUM_BIGDIG_LOG10];
3349252884aeSStefan Eßer 
3350252884aeSStefan Eßer 	BC_SIG_LOCK;
3351252884aeSStefan Eßer 
3352252884aeSStefan Eßer 	bc_num_init(&temp3, 2 * BC_RAND_NUM_SIZE);
3353252884aeSStefan Eßer 
3354252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
3355252884aeSStefan Eßer 
3356252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3357252884aeSStefan Eßer 
3358252884aeSStefan Eßer 	bc_num_setup(&temp1, temp1_num, sizeof(temp1_num) / sizeof(BcDig));
3359252884aeSStefan Eßer 	bc_num_setup(&temp2, temp2_num, sizeof(temp2_num) / sizeof(BcDig));
3360252884aeSStefan Eßer 	bc_num_setup(&conv, conv_num, sizeof(conv_num) / sizeof(BcDig));
3361252884aeSStefan Eßer 
3362252884aeSStefan Eßer 	// This assert is here because it has to be true. It is also here to justify
336344d4804dSStefan Eßer 	// the assumption that vm.max is not zero.
3364252884aeSStefan Eßer 	assert(BC_NUM_NONZERO(&vm.max));
3365252884aeSStefan Eßer 
336644d4804dSStefan Eßer 	// Because this is true, we can just ignore math errors that would happen
336744d4804dSStefan Eßer 	// otherwise.
336850696a6eSStefan Eßer 	assert(BC_NUM_NONZERO(&vm.max2));
3369252884aeSStefan Eßer 
3370252884aeSStefan Eßer 	bc_rand_getRands(rng, &s1, &s2, &i1, &i2);
3371252884aeSStefan Eßer 
337244d4804dSStefan Eßer 	// Put the second piece of state into a number.
3373252884aeSStefan Eßer 	bc_num_bigdig2num(&conv, (BcBigDig) s2);
3374252884aeSStefan Eßer 
337550696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(conv));
337650696a6eSStefan Eßer 
337744d4804dSStefan Eßer 	// Multiply by max to make room for the first piece of state.
3378252884aeSStefan Eßer 	bc_num_mul(&conv, &vm.max, &temp1, 0);
3379252884aeSStefan Eßer 
338044d4804dSStefan Eßer 	// Add in the first piece of state.
3381252884aeSStefan Eßer 	bc_num_bigdig2num(&conv, (BcBigDig) s1);
3382252884aeSStefan Eßer 	bc_num_add(&conv, &temp1, &temp2, 0);
3383252884aeSStefan Eßer 
338444d4804dSStefan Eßer 	// Divide to make it an entirely fractional part.
338550696a6eSStefan Eßer 	bc_num_div(&temp2, &vm.max2, &temp3, BC_RAND_STATE_BITS);
3386252884aeSStefan Eßer 
338744d4804dSStefan Eßer 	// Now start on the increment parts. It's the same process without the
338844d4804dSStefan Eßer 	// divide, so put the second piece of increment into a number.
3389252884aeSStefan Eßer 	bc_num_bigdig2num(&conv, (BcBigDig) i2);
3390252884aeSStefan Eßer 
339150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(conv));
339250696a6eSStefan Eßer 
339344d4804dSStefan Eßer 	// Multiply by max to make room for the first piece of increment.
3394252884aeSStefan Eßer 	bc_num_mul(&conv, &vm.max, &temp1, 0);
3395252884aeSStefan Eßer 
339644d4804dSStefan Eßer 	// Add in the first piece of increment.
3397252884aeSStefan Eßer 	bc_num_bigdig2num(&conv, (BcBigDig) i1);
3398252884aeSStefan Eßer 	bc_num_add(&conv, &temp1, &temp2, 0);
3399252884aeSStefan Eßer 
340044d4804dSStefan Eßer 	// Now add the two together.
3401252884aeSStefan Eßer 	bc_num_add(&temp2, &temp3, n, 0);
3402252884aeSStefan Eßer 
340350696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(n));
340450696a6eSStefan Eßer 
3405252884aeSStefan Eßer err:
3406252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
3407252884aeSStefan Eßer 	bc_num_free(&temp3);
3408252884aeSStefan Eßer 	BC_LONGJMP_CONT;
3409252884aeSStefan Eßer }
3410252884aeSStefan Eßer 
341144d4804dSStefan Eßer void bc_num_irand(BcNum *restrict a, BcNum *restrict b, BcRNG *restrict rng) {
341244d4804dSStefan Eßer 
341344d4804dSStefan Eßer 	BcNum atemp;
341444d4804dSStefan Eßer 	size_t i, len;
3415252884aeSStefan Eßer 
3416252884aeSStefan Eßer 	assert(a != b);
3417252884aeSStefan Eßer 
341844d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_NEG(a))) bc_err(BC_ERR_MATH_NEGATIVE);
341944d4804dSStefan Eßer 
342044d4804dSStefan Eßer 	// If either of these are true, then the numbers are integers.
3421252884aeSStefan Eßer 	if (BC_NUM_ZERO(a) || BC_NUM_ONE(a)) return;
3422252884aeSStefan Eßer 
342344d4804dSStefan Eßer 	if (BC_ERR(bc_num_nonInt(a, &atemp))) bc_err(BC_ERR_MATH_NON_INTEGER);
3424252884aeSStefan Eßer 
342544d4804dSStefan Eßer 	assert(atemp.len);
3426252884aeSStefan Eßer 
342744d4804dSStefan Eßer 	len = atemp.len - 1;
3428252884aeSStefan Eßer 
342944d4804dSStefan Eßer 	// Just generate a random number for each limb.
343044d4804dSStefan Eßer 	for (i = 0; i < len; ++i)
343144d4804dSStefan Eßer 		b->num[i] = (BcDig) bc_rand_bounded(rng, BC_BASE_POW);
3432252884aeSStefan Eßer 
343344d4804dSStefan Eßer 	// Do the last digit explicitly because the bound must be right. But only
343444d4804dSStefan Eßer 	// do it if the limb does not equal 1. If it does, we have already hit the
343544d4804dSStefan Eßer 	// limit.
343644d4804dSStefan Eßer 	if (atemp.num[i] != 1) {
343744d4804dSStefan Eßer 		b->num[i] = (BcDig) bc_rand_bounded(rng, (BcRand) atemp.num[i]);
343844d4804dSStefan Eßer 		b->len = atemp.len;
3439252884aeSStefan Eßer 	}
344044d4804dSStefan Eßer 	// We want 1 less len in the case where we skip the last limb.
344144d4804dSStefan Eßer 	else b->len = len;
3442252884aeSStefan Eßer 
3443252884aeSStefan Eßer 	bc_num_clean(b);
3444252884aeSStefan Eßer 
344550696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3446252884aeSStefan Eßer }
344744d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
3448252884aeSStefan Eßer 
3449252884aeSStefan Eßer size_t bc_num_addReq(const BcNum *a, const BcNum *b, size_t scale) {
3450252884aeSStefan Eßer 
3451252884aeSStefan Eßer 	size_t aint, bint, ardx, brdx;
3452252884aeSStefan Eßer 
345344d4804dSStefan Eßer 	// Addition and subtraction require the max of the length of the two numbers
345444d4804dSStefan Eßer 	// plus 1.
345544d4804dSStefan Eßer 
3456252884aeSStefan Eßer 	BC_UNUSED(scale);
3457252884aeSStefan Eßer 
345850696a6eSStefan Eßer 	ardx = BC_NUM_RDX_VAL(a);
3459252884aeSStefan Eßer 	aint = bc_num_int(a);
3460252884aeSStefan Eßer 	assert(aint <= a->len && ardx <= a->len);
3461252884aeSStefan Eßer 
346250696a6eSStefan Eßer 	brdx = BC_NUM_RDX_VAL(b);
3463252884aeSStefan Eßer 	bint = bc_num_int(b);
3464252884aeSStefan Eßer 	assert(bint <= b->len && brdx <= b->len);
3465252884aeSStefan Eßer 
3466252884aeSStefan Eßer 	ardx = BC_MAX(ardx, brdx);
3467252884aeSStefan Eßer 	aint = BC_MAX(aint, bint);
3468252884aeSStefan Eßer 
3469252884aeSStefan Eßer 	return bc_vm_growSize(bc_vm_growSize(ardx, aint), 1);
3470252884aeSStefan Eßer }
3471252884aeSStefan Eßer 
3472252884aeSStefan Eßer size_t bc_num_mulReq(const BcNum *a, const BcNum *b, size_t scale) {
347344d4804dSStefan Eßer 
3474252884aeSStefan Eßer 	size_t max, rdx;
347544d4804dSStefan Eßer 
347644d4804dSStefan Eßer 	// Multiplication requires the sum of the lengths of the numbers.
347744d4804dSStefan Eßer 
347850696a6eSStefan Eßer 	rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));
347944d4804dSStefan Eßer 
3480252884aeSStefan Eßer 	max = BC_NUM_RDX(scale);
348144d4804dSStefan Eßer 
3482252884aeSStefan Eßer 	max = bc_vm_growSize(BC_MAX(max, rdx), 1);
3483252884aeSStefan Eßer 	rdx = bc_vm_growSize(bc_vm_growSize(bc_num_int(a), bc_num_int(b)), max);
348444d4804dSStefan Eßer 
3485252884aeSStefan Eßer 	return rdx;
3486252884aeSStefan Eßer }
3487252884aeSStefan Eßer 
348850696a6eSStefan Eßer size_t bc_num_divReq(const BcNum *a, const BcNum *b, size_t scale) {
348944d4804dSStefan Eßer 
349050696a6eSStefan Eßer 	size_t max, rdx;
349144d4804dSStefan Eßer 
349244d4804dSStefan Eßer 	// Division requires the length of the dividend plus the scale.
349344d4804dSStefan Eßer 
349450696a6eSStefan Eßer 	rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));
349544d4804dSStefan Eßer 
349650696a6eSStefan Eßer 	max = BC_NUM_RDX(scale);
349744d4804dSStefan Eßer 
349850696a6eSStefan Eßer 	max = bc_vm_growSize(BC_MAX(max, rdx), 1);
349950696a6eSStefan Eßer 	rdx = bc_vm_growSize(bc_num_int(a), max);
350044d4804dSStefan Eßer 
350150696a6eSStefan Eßer 	return rdx;
350250696a6eSStefan Eßer }
350350696a6eSStefan Eßer 
3504252884aeSStefan Eßer size_t bc_num_powReq(const BcNum *a, const BcNum *b, size_t scale) {
3505252884aeSStefan Eßer 	BC_UNUSED(scale);
3506252884aeSStefan Eßer 	return bc_vm_growSize(bc_vm_growSize(a->len, b->len), 1);
3507252884aeSStefan Eßer }
3508252884aeSStefan Eßer 
3509252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
3510252884aeSStefan Eßer size_t bc_num_placesReq(const BcNum *a, const BcNum *b, size_t scale) {
3511252884aeSStefan Eßer 	BC_UNUSED(scale);
351250696a6eSStefan Eßer 	return a->len + b->len - BC_NUM_RDX_VAL(a) - BC_NUM_RDX_VAL(b);
3513252884aeSStefan Eßer }
3514252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
3515252884aeSStefan Eßer 
3516252884aeSStefan Eßer void bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
351750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
351850696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3519252884aeSStefan Eßer 	bc_num_binary(a, b, c, false, bc_num_as, bc_num_addReq(a, b, scale));
3520252884aeSStefan Eßer }
3521252884aeSStefan Eßer 
3522252884aeSStefan Eßer void bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
352350696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
352450696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3525252884aeSStefan Eßer 	bc_num_binary(a, b, c, true, bc_num_as, bc_num_addReq(a, b, scale));
3526252884aeSStefan Eßer }
3527252884aeSStefan Eßer 
3528252884aeSStefan Eßer void bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
352950696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
353050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3531252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_m, bc_num_mulReq(a, b, scale));
3532252884aeSStefan Eßer }
3533252884aeSStefan Eßer 
3534252884aeSStefan Eßer void bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
353550696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
353650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
353750696a6eSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_d, bc_num_divReq(a, b, scale));
3538252884aeSStefan Eßer }
3539252884aeSStefan Eßer 
3540252884aeSStefan Eßer void bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
354150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
354250696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
354350696a6eSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_rem, bc_num_divReq(a, b, scale));
3544252884aeSStefan Eßer }
3545252884aeSStefan Eßer 
3546252884aeSStefan Eßer void bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
354750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
354850696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3549252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_p, bc_num_powReq(a, b, scale));
3550252884aeSStefan Eßer }
3551252884aeSStefan Eßer 
3552252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
3553252884aeSStefan Eßer void bc_num_places(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
355450696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
355550696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3556252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_place, bc_num_placesReq(a, b, scale));
3557252884aeSStefan Eßer }
3558252884aeSStefan Eßer 
3559252884aeSStefan Eßer void bc_num_lshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
356050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
356150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3562252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_left, bc_num_placesReq(a, b, scale));
3563252884aeSStefan Eßer }
3564252884aeSStefan Eßer 
3565252884aeSStefan Eßer void bc_num_rshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
356650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
356750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3568252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_right, bc_num_placesReq(a, b, scale));
3569252884aeSStefan Eßer }
3570252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
3571252884aeSStefan Eßer 
3572252884aeSStefan Eßer void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
3573252884aeSStefan Eßer 
3574252884aeSStefan Eßer 	BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
357510328f8bSStefan Eßer 	size_t pow, len, rdx, req, resscale;
3576252884aeSStefan Eßer 	BcDig half_digs[1];
3577252884aeSStefan Eßer 
3578252884aeSStefan Eßer 	assert(a != NULL && b != NULL && a != b);
3579252884aeSStefan Eßer 
358044d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_NEG(a))) bc_err(BC_ERR_MATH_NEGATIVE);
3581252884aeSStefan Eßer 
358244d4804dSStefan Eßer 	// We want to calculate to a's scale if it is bigger so that the result will
358344d4804dSStefan Eßer 	// truncate properly.
3584252884aeSStefan Eßer 	if (a->scale > scale) scale = a->scale;
3585252884aeSStefan Eßer 
358644d4804dSStefan Eßer 	// Set parameters for the result.
3587252884aeSStefan Eßer 	len = bc_vm_growSize(bc_num_intDigits(a), 1);
3588252884aeSStefan Eßer 	rdx = BC_NUM_RDX(scale);
358944d4804dSStefan Eßer 
359044d4804dSStefan Eßer 	// Square root needs half of the length of the parameter.
359150696a6eSStefan Eßer 	req = bc_vm_growSize(BC_MAX(rdx, BC_NUM_RDX_VAL(a)), len >> 1);
3592252884aeSStefan Eßer 
3593252884aeSStefan Eßer 	BC_SIG_LOCK;
3594252884aeSStefan Eßer 
359544d4804dSStefan Eßer 	// Unlike the binary operators, this function is the only single parameter
359644d4804dSStefan Eßer 	// function and is expected to initialize the result. This means that it
359744d4804dSStefan Eßer 	// expects that b is *NOT* preallocated. We allocate it here.
3598252884aeSStefan Eßer 	bc_num_init(b, bc_vm_growSize(req, 1));
3599252884aeSStefan Eßer 
3600252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3601252884aeSStefan Eßer 
360250696a6eSStefan Eßer 	assert(a != NULL && b != NULL && a != b);
360350696a6eSStefan Eßer 	assert(a->num != NULL && b->num != NULL);
360450696a6eSStefan Eßer 
360544d4804dSStefan Eßer 	// Easy case.
3606252884aeSStefan Eßer 	if (BC_NUM_ZERO(a)) {
3607252884aeSStefan Eßer 		bc_num_setToZero(b, scale);
3608252884aeSStefan Eßer 		return;
3609252884aeSStefan Eßer 	}
361044d4804dSStefan Eßer 
361144d4804dSStefan Eßer 	// Another easy case.
3612252884aeSStefan Eßer 	if (BC_NUM_ONE(a)) {
3613252884aeSStefan Eßer 		bc_num_one(b);
3614252884aeSStefan Eßer 		bc_num_extend(b, scale);
3615252884aeSStefan Eßer 		return;
3616252884aeSStefan Eßer 	}
3617252884aeSStefan Eßer 
361844d4804dSStefan Eßer 	// Set the parameters again.
3619252884aeSStefan Eßer 	rdx = BC_NUM_RDX(scale);
362050696a6eSStefan Eßer 	rdx = BC_MAX(rdx, BC_NUM_RDX_VAL(a));
3621252884aeSStefan Eßer 	len = bc_vm_growSize(a->len, rdx);
3622252884aeSStefan Eßer 
3623252884aeSStefan Eßer 	BC_SIG_LOCK;
3624252884aeSStefan Eßer 
3625252884aeSStefan Eßer 	bc_num_init(&num1, len);
3626252884aeSStefan Eßer 	bc_num_init(&num2, len);
3627252884aeSStefan Eßer 	bc_num_setup(&half, half_digs, sizeof(half_digs) / sizeof(BcDig));
3628252884aeSStefan Eßer 
362944d4804dSStefan Eßer 	// There is a division by two in the formula. We setup a number that's 1/2
363044d4804dSStefan Eßer 	// so that we can use multiplication instead of heavy division.
3631252884aeSStefan Eßer 	bc_num_one(&half);
3632252884aeSStefan Eßer 	half.num[0] = BC_BASE_POW / 2;
3633252884aeSStefan Eßer 	half.len = 1;
363450696a6eSStefan Eßer 	BC_NUM_RDX_SET_NP(half, 1);
3635252884aeSStefan Eßer 	half.scale = 1;
3636252884aeSStefan Eßer 
3637252884aeSStefan Eßer 	bc_num_init(&f, len);
3638252884aeSStefan Eßer 	bc_num_init(&fprime, len);
3639252884aeSStefan Eßer 
3640252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
3641252884aeSStefan Eßer 
3642252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3643252884aeSStefan Eßer 
364444d4804dSStefan Eßer 	// Pointers for easy switching.
3645252884aeSStefan Eßer 	x0 = &num1;
3646252884aeSStefan Eßer 	x1 = &num2;
3647252884aeSStefan Eßer 
364844d4804dSStefan Eßer 	// Start with 1.
3649252884aeSStefan Eßer 	bc_num_one(x0);
365044d4804dSStefan Eßer 
365144d4804dSStefan Eßer 	// The power of the operand is needed for the estimate.
3652252884aeSStefan Eßer 	pow = bc_num_intDigits(a);
3653252884aeSStefan Eßer 
365444d4804dSStefan Eßer 	// The code in this if statement calculates the initial estimate. First, if
365544d4804dSStefan Eßer 	// a is less than 0, then 0 is a good estimate. Otherwise, we want something
365644d4804dSStefan Eßer 	// in the same ballpark. That ballpark is pow.
3657252884aeSStefan Eßer 	if (pow) {
3658252884aeSStefan Eßer 
365944d4804dSStefan Eßer 		// An odd number is served by starting with 2^((pow-1)/2), and an even
366044d4804dSStefan Eßer 		// number is served by starting with 6^((pow-2)/2). Why? Because math.
3661252884aeSStefan Eßer 		if (pow & 1) x0->num[0] = 2;
3662252884aeSStefan Eßer 		else x0->num[0] = 6;
3663252884aeSStefan Eßer 
3664252884aeSStefan Eßer 		pow -= 2 - (pow & 1);
3665252884aeSStefan Eßer 		bc_num_shiftLeft(x0, pow / 2);
3666252884aeSStefan Eßer 	}
3667252884aeSStefan Eßer 
366850696a6eSStefan Eßer 	// I can set the rdx here directly because neg should be false.
366910328f8bSStefan Eßer 	x0->scale = x0->rdx = 0;
3670252884aeSStefan Eßer 	resscale = (scale + BC_BASE_DIGS) + 2;
3671252884aeSStefan Eßer 
367244d4804dSStefan Eßer 	// This is the calculation loop. This compare goes to 0 eventually as the
367344d4804dSStefan Eßer 	// difference between the two numbers gets smaller than resscale.
3674252884aeSStefan Eßer 	while (bc_num_cmp(x1, x0)) {
3675252884aeSStefan Eßer 
3676252884aeSStefan Eßer 		assert(BC_NUM_NONZERO(x0));
3677252884aeSStefan Eßer 
367844d4804dSStefan Eßer 		// This loop directly corresponds to the iteration in Newton's method.
367944d4804dSStefan Eßer 		// If you know the formula, this loop makes sense. Go study the formula.
368044d4804dSStefan Eßer 
3681252884aeSStefan Eßer 		bc_num_div(a, x0, &f, resscale);
3682252884aeSStefan Eßer 		bc_num_add(x0, &f, &fprime, resscale);
368350696a6eSStefan Eßer 
368450696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(fprime));
368550696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(half));
368650696a6eSStefan Eßer 
3687252884aeSStefan Eßer 		bc_num_mul(&fprime, &half, x1, resscale);
3688252884aeSStefan Eßer 
368944d4804dSStefan Eßer 		// Switch.
3690252884aeSStefan Eßer 		temp = x0;
3691252884aeSStefan Eßer 		x0 = x1;
3692252884aeSStefan Eßer 		x1 = temp;
3693252884aeSStefan Eßer 	}
3694252884aeSStefan Eßer 
369544d4804dSStefan Eßer 	// Copy to the result and truncate.
3696252884aeSStefan Eßer 	bc_num_copy(b, x0);
3697252884aeSStefan Eßer 	if (b->scale > scale) bc_num_truncate(b, b->scale - scale);
3698252884aeSStefan Eßer 
369950696a6eSStefan Eßer 	assert(!BC_NUM_NEG(b) || BC_NUM_NONZERO(b));
370050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
370150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(b) <= b->len || !b->len);
370250696a6eSStefan Eßer 	assert(!b->len || b->num[b->len - 1] || BC_NUM_RDX_VAL(b) == b->len);
3703252884aeSStefan Eßer 
3704252884aeSStefan Eßer err:
3705252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
3706252884aeSStefan Eßer 	bc_num_free(&fprime);
3707252884aeSStefan Eßer 	bc_num_free(&f);
3708252884aeSStefan Eßer 	bc_num_free(&num2);
3709252884aeSStefan Eßer 	bc_num_free(&num1);
3710252884aeSStefan Eßer 	BC_LONGJMP_CONT;
3711252884aeSStefan Eßer }
3712252884aeSStefan Eßer 
3713252884aeSStefan Eßer void bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) {
3714252884aeSStefan Eßer 
3715252884aeSStefan Eßer 	size_t ts, len;
371650696a6eSStefan Eßer 	BcNum *ptr_a, num2;
371750696a6eSStefan Eßer 	bool init = false;
3718252884aeSStefan Eßer 
371944d4804dSStefan Eßer 	// The bulk of this function is just doing what bc_num_binary() does for the
372044d4804dSStefan Eßer 	// binary operators. However, it assumes that only c and a can be equal.
372144d4804dSStefan Eßer 
372244d4804dSStefan Eßer 	// Set up the parameters.
3723252884aeSStefan Eßer 	ts = BC_MAX(scale + b->scale, a->scale);
3724252884aeSStefan Eßer 	len = bc_num_mulReq(a, b, ts);
3725252884aeSStefan Eßer 
3726252884aeSStefan Eßer 	assert(a != NULL && b != NULL && c != NULL && d != NULL);
3727252884aeSStefan Eßer 	assert(c != d && a != d && b != d && b != c);
3728252884aeSStefan Eßer 
372944d4804dSStefan Eßer 	// Initialize or expand as necessary.
3730252884aeSStefan Eßer 	if (c == a) {
3731252884aeSStefan Eßer 
3732252884aeSStefan Eßer 		memcpy(&num2, c, sizeof(BcNum));
3733252884aeSStefan Eßer 		ptr_a = &num2;
3734252884aeSStefan Eßer 
3735252884aeSStefan Eßer 		BC_SIG_LOCK;
3736252884aeSStefan Eßer 
3737252884aeSStefan Eßer 		bc_num_init(c, len);
3738252884aeSStefan Eßer 
3739252884aeSStefan Eßer 		init = true;
3740252884aeSStefan Eßer 
3741252884aeSStefan Eßer 		BC_SETJMP_LOCKED(err);
3742252884aeSStefan Eßer 
3743252884aeSStefan Eßer 		BC_SIG_UNLOCK;
3744252884aeSStefan Eßer 	}
3745252884aeSStefan Eßer 	else {
3746252884aeSStefan Eßer 		ptr_a = a;
3747252884aeSStefan Eßer 		bc_num_expand(c, len);
3748252884aeSStefan Eßer 	}
3749252884aeSStefan Eßer 
375044d4804dSStefan Eßer 	// Do the quick version if possible.
375150696a6eSStefan Eßer 	if (BC_NUM_NONZERO(a) && !BC_NUM_RDX_VAL(a) &&
375250696a6eSStefan Eßer 	    !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale)
375350696a6eSStefan Eßer 	{
3754252884aeSStefan Eßer 		BcBigDig rem;
3755252884aeSStefan Eßer 
3756252884aeSStefan Eßer 		bc_num_divArray(ptr_a, (BcBigDig) b->num[0], c, &rem);
3757252884aeSStefan Eßer 
3758252884aeSStefan Eßer 		assert(rem < BC_BASE_POW);
3759252884aeSStefan Eßer 
3760252884aeSStefan Eßer 		d->num[0] = (BcDig) rem;
3761252884aeSStefan Eßer 		d->len = (rem != 0);
3762252884aeSStefan Eßer 	}
376344d4804dSStefan Eßer 	// Do the slow method.
3764252884aeSStefan Eßer 	else bc_num_r(ptr_a, b, c, d, scale, ts);
3765252884aeSStefan Eßer 
376650696a6eSStefan Eßer 	assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
376750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(c));
376850696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
376950696a6eSStefan Eßer 	assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
377050696a6eSStefan Eßer 	assert(!BC_NUM_NEG(d) || BC_NUM_NONZERO(d));
377150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(d));
377250696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(d) <= d->len || !d->len);
377350696a6eSStefan Eßer 	assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
3774252884aeSStefan Eßer 
3775252884aeSStefan Eßer err:
377644d4804dSStefan Eßer 	// Only cleanup if we initialized.
3777252884aeSStefan Eßer 	if (init) {
3778252884aeSStefan Eßer 		BC_SIG_MAYLOCK;
3779252884aeSStefan Eßer 		bc_num_free(&num2);
3780252884aeSStefan Eßer 		BC_LONGJMP_CONT;
3781252884aeSStefan Eßer 	}
3782252884aeSStefan Eßer }
3783252884aeSStefan Eßer 
3784252884aeSStefan Eßer void bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) {
3785252884aeSStefan Eßer 
378644d4804dSStefan Eßer 	BcNum base, exp, two, temp, atemp, btemp, ctemp;
3787252884aeSStefan Eßer 	BcDig two_digs[2];
3788252884aeSStefan Eßer 
3789252884aeSStefan Eßer 	assert(a != NULL && b != NULL && c != NULL && d != NULL);
3790252884aeSStefan Eßer 	assert(a != d && b != d && c != d);
3791252884aeSStefan Eßer 
379244d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_ZERO(c))) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
3793252884aeSStefan Eßer 
379444d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_NEG(b))) bc_err(BC_ERR_MATH_NEGATIVE);
379544d4804dSStefan Eßer 
379644d4804dSStefan Eßer #ifndef NDEBUG
379744d4804dSStefan Eßer 	// This is entirely for quieting a useless scan-build error.
379844d4804dSStefan Eßer 	btemp.len = 0;
379944d4804dSStefan Eßer 	ctemp.len = 0;
380044d4804dSStefan Eßer #endif // NDEBUG
380144d4804dSStefan Eßer 
380244d4804dSStefan Eßer 	// Eliminate fractional parts that are zero or error if they are not zero.
380344d4804dSStefan Eßer 	if (BC_ERR(bc_num_nonInt(a, &atemp) || bc_num_nonInt(b, &btemp) ||
380444d4804dSStefan Eßer 	           bc_num_nonInt(c, &ctemp)))
380544d4804dSStefan Eßer 	{
380644d4804dSStefan Eßer 		bc_err(BC_ERR_MATH_NON_INTEGER);
380744d4804dSStefan Eßer 	}
380844d4804dSStefan Eßer 
380944d4804dSStefan Eßer 	bc_num_expand(d, ctemp.len);
3810252884aeSStefan Eßer 
3811252884aeSStefan Eßer 	BC_SIG_LOCK;
3812252884aeSStefan Eßer 
381344d4804dSStefan Eßer 	bc_num_init(&base, ctemp.len);
3814252884aeSStefan Eßer 	bc_num_setup(&two, two_digs, sizeof(two_digs) / sizeof(BcDig));
381544d4804dSStefan Eßer 	bc_num_init(&temp, btemp.len + 1);
381644d4804dSStefan Eßer 	bc_num_createCopy(&exp, &btemp);
3817252884aeSStefan Eßer 
3818252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
3819252884aeSStefan Eßer 
3820252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3821252884aeSStefan Eßer 
3822252884aeSStefan Eßer 	bc_num_one(&two);
3823252884aeSStefan Eßer 	two.num[0] = 2;
3824252884aeSStefan Eßer 	bc_num_one(d);
3825252884aeSStefan Eßer 
3826252884aeSStefan Eßer 	// We already checked for 0.
382744d4804dSStefan Eßer 	bc_num_rem(&atemp, &ctemp, &base, 0);
3828252884aeSStefan Eßer 
382944d4804dSStefan Eßer 	// If you know the algorithm I used, the memory-efficient method, then this
383044d4804dSStefan Eßer 	// loop should be self-explanatory because it is the calculation loop.
3831252884aeSStefan Eßer 	while (BC_NUM_NONZERO(&exp)) {
3832252884aeSStefan Eßer 
3833252884aeSStefan Eßer 		// Num two cannot be 0, so no errors.
3834252884aeSStefan Eßer 		bc_num_divmod(&exp, &two, &exp, &temp, 0);
3835252884aeSStefan Eßer 
383650696a6eSStefan Eßer 		if (BC_NUM_ONE(&temp) && !BC_NUM_NEG_NP(temp)) {
383750696a6eSStefan Eßer 
383850696a6eSStefan Eßer 			assert(BC_NUM_RDX_VALID(d));
383950696a6eSStefan Eßer 			assert(BC_NUM_RDX_VALID_NP(base));
3840252884aeSStefan Eßer 
3841252884aeSStefan Eßer 			bc_num_mul(d, &base, &temp, 0);
3842252884aeSStefan Eßer 
3843252884aeSStefan Eßer 			// We already checked for 0.
384444d4804dSStefan Eßer 			bc_num_rem(&temp, &ctemp, d, 0);
3845252884aeSStefan Eßer 		}
3846252884aeSStefan Eßer 
384750696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(base));
384850696a6eSStefan Eßer 
3849252884aeSStefan Eßer 		bc_num_mul(&base, &base, &temp, 0);
3850252884aeSStefan Eßer 
3851252884aeSStefan Eßer 		// We already checked for 0.
385244d4804dSStefan Eßer 		bc_num_rem(&temp, &ctemp, &base, 0);
3853252884aeSStefan Eßer 	}
3854252884aeSStefan Eßer 
3855252884aeSStefan Eßer err:
3856252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
3857252884aeSStefan Eßer 	bc_num_free(&exp);
3858252884aeSStefan Eßer 	bc_num_free(&temp);
3859252884aeSStefan Eßer 	bc_num_free(&base);
3860252884aeSStefan Eßer 	BC_LONGJMP_CONT;
386150696a6eSStefan Eßer 	assert(!BC_NUM_NEG(d) || d->len);
386250696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(d));
386350696a6eSStefan Eßer 	assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
3864252884aeSStefan Eßer }
3865252884aeSStefan Eßer 
3866252884aeSStefan Eßer #if BC_DEBUG_CODE
3867252884aeSStefan Eßer void bc_num_printDebug(const BcNum *n, const char *name, bool emptyline) {
38687e5c51e5SStefan Eßer 	bc_file_puts(&vm.fout, bc_flush_none, name);
38697e5c51e5SStefan Eßer 	bc_file_puts(&vm.fout, bc_flush_none, ": ");
387044d4804dSStefan Eßer 	bc_num_printDecimal(n, true);
38717e5c51e5SStefan Eßer 	bc_file_putchar(&vm.fout, bc_flush_err, '\n');
38727e5c51e5SStefan Eßer 	if (emptyline) bc_file_putchar(&vm.fout, bc_flush_err, '\n');
3873252884aeSStefan Eßer 	vm.nchars = 0;
3874252884aeSStefan Eßer }
3875252884aeSStefan Eßer 
3876252884aeSStefan Eßer void bc_num_printDigs(const BcDig *n, size_t len, bool emptyline) {
3877252884aeSStefan Eßer 
3878252884aeSStefan Eßer 	size_t i;
3879252884aeSStefan Eßer 
3880252884aeSStefan Eßer 	for (i = len - 1; i < len; --i)
3881252884aeSStefan Eßer 		bc_file_printf(&vm.fout, " %lu", (unsigned long) n[i]);
3882252884aeSStefan Eßer 
38837e5c51e5SStefan Eßer 	bc_file_putchar(&vm.fout, bc_flush_err, '\n');
38847e5c51e5SStefan Eßer 	if (emptyline) bc_file_putchar(&vm.fout, bc_flush_err, '\n');
3885252884aeSStefan Eßer 	vm.nchars = 0;
3886252884aeSStefan Eßer }
3887252884aeSStefan Eßer 
3888252884aeSStefan Eßer void bc_num_printWithDigs(const BcNum *n, const char *name, bool emptyline) {
38897e5c51e5SStefan Eßer 	bc_file_puts(&vm.fout, bc_flush_none, name);
3890252884aeSStefan Eßer 	bc_file_printf(&vm.fout, " len: %zu, rdx: %zu, scale: %zu\n",
389150696a6eSStefan Eßer 	               name, n->len, BC_NUM_RDX_VAL(n), n->scale);
3892252884aeSStefan Eßer 	bc_num_printDigs(n->num, n->len, emptyline);
3893252884aeSStefan Eßer }
3894252884aeSStefan Eßer 
3895252884aeSStefan Eßer void bc_num_dump(const char *varname, const BcNum *n) {
3896252884aeSStefan Eßer 
3897252884aeSStefan Eßer 	ulong i, scale = n->scale;
3898252884aeSStefan Eßer 
3899252884aeSStefan Eßer 	bc_file_printf(&vm.ferr, "\n%s = %s", varname,
390050696a6eSStefan Eßer 	               n->len ? (BC_NUM_NEG(n) ? "-" : "+") : "0 ");
3901252884aeSStefan Eßer 
3902252884aeSStefan Eßer 	for (i = n->len - 1; i < n->len; --i) {
3903252884aeSStefan Eßer 
39047e5c51e5SStefan Eßer 		if (i + 1 == BC_NUM_RDX_VAL(n))
39057e5c51e5SStefan Eßer 			bc_file_puts(&vm.ferr, bc_flush_none, ". ");
3906252884aeSStefan Eßer 
390750696a6eSStefan Eßer 		if (scale / BC_BASE_DIGS != BC_NUM_RDX_VAL(n) - i - 1)
3908252884aeSStefan Eßer 			bc_file_printf(&vm.ferr, "%lu ", (unsigned long) n->num[i]);
3909252884aeSStefan Eßer 		else {
3910252884aeSStefan Eßer 
3911252884aeSStefan Eßer 			int mod = scale % BC_BASE_DIGS;
3912252884aeSStefan Eßer 			int d = BC_BASE_DIGS - mod;
3913252884aeSStefan Eßer 			BcDig div;
3914252884aeSStefan Eßer 
3915252884aeSStefan Eßer 			if (mod != 0) {
3916252884aeSStefan Eßer 				div = n->num[i] / ((BcDig) bc_num_pow10[(ulong) d]);
3917252884aeSStefan Eßer 				bc_file_printf(&vm.ferr, "%lu", (unsigned long) div);
3918252884aeSStefan Eßer 			}
3919252884aeSStefan Eßer 
3920252884aeSStefan Eßer 			div = n->num[i] % ((BcDig) bc_num_pow10[(ulong) d]);
3921252884aeSStefan Eßer 			bc_file_printf(&vm.ferr, " ' %lu ", (unsigned long) div);
3922252884aeSStefan Eßer 		}
3923252884aeSStefan Eßer 	}
3924252884aeSStefan Eßer 
3925252884aeSStefan Eßer 	bc_file_printf(&vm.ferr, "(%zu | %zu.%zu / %zu) %lu\n",
392650696a6eSStefan Eßer 	               n->scale, n->len, BC_NUM_RDX_VAL(n), n->cap,
3927252884aeSStefan Eßer 	               (unsigned long) (void*) n->num);
39287e5c51e5SStefan Eßer 
39297e5c51e5SStefan Eßer 	bc_file_flush(&vm.ferr, bc_flush_err);
3930252884aeSStefan Eßer }
3931252884aeSStefan Eßer #endif // BC_DEBUG_CODE
3932