xref: /freebsd/contrib/bc/src/num.c (revision 44d4804d1945435745518cd09eb8ae6ab22ecef4)
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 
48*44d4804dSStefan Eßer // Before you try to understand this code, see the development manual
49*44d4804dSStefan Eßer // (manuals/development.md#numbers).
50*44d4804dSStefan Eßer 
51252884aeSStefan Eßer static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
52252884aeSStefan Eßer 
53*44d4804dSStefan Eßer /**
54*44d4804dSStefan Eßer  * Multiply two numbers and throw a math error if they overflow.
55*44d4804dSStefan Eßer  * @param a  The first operand.
56*44d4804dSStefan Eßer  * @param b  The second operand.
57*44d4804dSStefan Eßer  * @return   The product of the two operands.
58*44d4804dSStefan Eßer  */
59*44d4804dSStefan Eßer static inline size_t bc_num_mulOverflow(size_t a, size_t b) {
60*44d4804dSStefan Eßer 	size_t res = a * b;
61*44d4804dSStefan Eßer 	if (BC_ERR(BC_VM_MUL_OVERFLOW(a, b, res))) bc_err(BC_ERR_MATH_OVERFLOW);
62*44d4804dSStefan Eßer 	return res;
63*44d4804dSStefan Eßer }
64*44d4804dSStefan Eßer 
65*44d4804dSStefan Eßer /**
66*44d4804dSStefan Eßer  * Conditionally negate @a n based on @a neg. Algorithm taken from
67*44d4804dSStefan Eßer  * https://graphics.stanford.edu/~seander/bithacks.html#ConditionalNegate .
68*44d4804dSStefan Eßer  * @param n    The value to turn into a signed value and negate.
69*44d4804dSStefan Eßer  * @param neg  The condition to negate or not.
70*44d4804dSStefan 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 
75*44d4804dSStefan Eßer /**
76*44d4804dSStefan Eßer  * Compare a BcNum against zero.
77*44d4804dSStefan Eßer  * @param n  The number to compare.
78*44d4804dSStefan Eßer  * @return   -1 if the number is less than 0, 1 if greater, and 0 if equal.
79*44d4804dSStefan 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 
84*44d4804dSStefan Eßer /**
85*44d4804dSStefan Eßer  * Return the number of integer limbs in a BcNum. This is the opposite of rdx.
86*44d4804dSStefan Eßer  * @param n  The number to return the amount of integer limbs for.
87*44d4804dSStefan Eßer  * @return   The amount of integer limbs in @a n.
88*44d4804dSStefan 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 
93*44d4804dSStefan Eßer /**
94*44d4804dSStefan Eßer  * Expand a number's allocation capacity to at least req limbs.
95*44d4804dSStefan Eßer  * @param n    The number to expand.
96*44d4804dSStefan Eßer  * @param req  The number limbs to expand the allocation capacity to.
97*44d4804dSStefan 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 
115*44d4804dSStefan Eßer /**
116*44d4804dSStefan Eßer  * Set a number to 0 with the specified scale.
117*44d4804dSStefan Eßer  * @param n      The number to set to zero.
118*44d4804dSStefan Eßer  * @param scale  The scale to set the number to.
119*44d4804dSStefan 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 
136*44d4804dSStefan Eßer /**
137*44d4804dSStefan Eßer  * "Cleans" a number, which means reducing the length if the most significant
138*44d4804dSStefan Eßer  * limbs are zero.
139*44d4804dSStefan Eßer  * @param n  The number to clean.
140*44d4804dSStefan Eßer  */
141252884aeSStefan Eßer static void bc_num_clean(BcNum *restrict n) {
142252884aeSStefan Eßer 
143*44d4804dSStefan Eßer 	// Reduce the length.
144252884aeSStefan Eßer 	while (BC_NUM_NONZERO(n) && !n->num[n->len - 1]) n->len -= 1;
145252884aeSStefan Eßer 
146*44d4804dSStefan Eßer 	// Special cases.
14750696a6eSStefan Eßer 	if (BC_NUM_ZERO(n)) n->rdx = 0;
14850696a6eSStefan Eßer 	else {
149*44d4804dSStefan Eßer 
150*44d4804dSStefan 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 
156*44d4804dSStefan Eßer /**
157*44d4804dSStefan Eßer  * Returns the log base 10 of @a i. I could have done this with floating-point
158*44d4804dSStefan Eßer  * math, and in fact, I originally did. However, that was the only
159*44d4804dSStefan Eßer  * floating-point code in the entire codebase, and I decided I didn't want any.
160*44d4804dSStefan Eßer  * This is fast enough. Also, it might handle larger numbers better.
161*44d4804dSStefan Eßer  * @param i  The number to return the log base 10 of.
162*44d4804dSStefan Eßer  * @return   The log base 10 of @a i.
163*44d4804dSStefan 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 
171*44d4804dSStefan Eßer /**
172*44d4804dSStefan Eßer  * Returns the number of decimal digits in a limb that are zero starting at the
173*44d4804dSStefan Eßer  * most significant digits. This basically returns how much of the limb is used.
174*44d4804dSStefan Eßer  * @param n  The number.
175*44d4804dSStefan Eßer  * @return   The number of decimal digits that are 0 starting at the most
176*44d4804dSStefan Eßer  *           significant digits.
177*44d4804dSStefan 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 
184*44d4804dSStefan Eßer /**
185*44d4804dSStefan Eßer  * Return the total number of integer digits in a number. This is the opposite
186*44d4804dSStefan Eßer  * of scale, like bc_num_int() is the opposite of rdx.
187*44d4804dSStefan Eßer  * @param n  The number.
188*44d4804dSStefan Eßer  * @return   The number of integer digits in @a n.
189*44d4804dSStefan 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 
196*44d4804dSStefan Eßer /**
197*44d4804dSStefan Eßer  * Returns the number of limbs of a number that are non-zero starting at the
198*44d4804dSStefan Eßer  * most significant limbs. This expects that there are *no* integer limbs in the
199*44d4804dSStefan Eßer  * number because it is specifically to figure out how many zero limbs after the
200*44d4804dSStefan Eßer  * decimal place to ignore. If there are zero limbs after non-zero limbs, they
201*44d4804dSStefan Eßer  * are counted as non-zero limbs.
202*44d4804dSStefan Eßer  * @param n  The number.
203*44d4804dSStefan Eßer  * @return   The number of non-zero limbs after the decimal point.
204*44d4804dSStefan Eßer  */
205*44d4804dSStefan 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 
213*44d4804dSStefan Eßer /**
214*44d4804dSStefan Eßer  * Performs a one-limb add with a carry.
215*44d4804dSStefan Eßer  * @param a      The first limb.
216*44d4804dSStefan Eßer  * @param b      The second limb.
217*44d4804dSStefan Eßer  * @param carry  An in/out parameter; the carry in from the previous add and the
218*44d4804dSStefan Eßer  *               carry out from this add.
219*44d4804dSStefan Eßer  * @return       The resulting limb sum.
220*44d4804dSStefan 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 
237*44d4804dSStefan Eßer /**
238*44d4804dSStefan Eßer  * Performs a one-limb subtract with a carry.
239*44d4804dSStefan Eßer  * @param a      The first limb.
240*44d4804dSStefan Eßer  * @param b      The second limb.
241*44d4804dSStefan Eßer  * @param carry  An in/out parameter; the carry in from the previous subtract
242*44d4804dSStefan Eßer  *               and the carry out from this subtract.
243*44d4804dSStefan Eßer  * @return       The resulting limb difference.
244*44d4804dSStefan 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 
260*44d4804dSStefan Eßer /**
261*44d4804dSStefan Eßer  * Add two BcDig arrays and store the result in the first array.
262*44d4804dSStefan Eßer  * @param a    The first operand and out array.
263*44d4804dSStefan Eßer  * @param b    The second operand.
264*44d4804dSStefan Eßer  * @param len  The length of @a b.
265*44d4804dSStefan 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 
274*44d4804dSStefan 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 
278*44d4804dSStefan Eßer /**
279*44d4804dSStefan Eßer  * Subtract two BcDig arrays and store the result in the first array.
280*44d4804dSStefan Eßer  * @param a    The first operand and out array.
281*44d4804dSStefan Eßer  * @param b    The second operand.
282*44d4804dSStefan Eßer  * @param len  The length of @a b.
283*44d4804dSStefan 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 
292*44d4804dSStefan 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 
296*44d4804dSStefan Eßer /**
297*44d4804dSStefan Eßer  * Multiply a BcNum array by a one-limb number. This is a faster version of
298*44d4804dSStefan Eßer  * multiplication for when we can use it.
299*44d4804dSStefan Eßer  * @param a  The BcNum to multiply by the one-limb number.
300*44d4804dSStefan Eßer  * @param b  The one limb of the one-limb number.
301*44d4804dSStefan Eßer  * @param c  The return parameter.
302*44d4804dSStefan 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 
311*44d4804dSStefan 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 
314*44d4804dSStefan 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 
317*44d4804dSStefan 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);
325*44d4804dSStefan Eßer 
326*44d4804dSStefan 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 
333*44d4804dSStefan 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 
339*44d4804dSStefan Eßer /**
340*44d4804dSStefan Eßer  * Divide a BcNum array by a one-limb number. This is a faster version of divide
341*44d4804dSStefan Eßer  * for when we can use it.
342*44d4804dSStefan Eßer  * @param a    The BcNum to multiply by the one-limb number.
343*44d4804dSStefan Eßer  * @param b    The one limb of the one-limb number.
344*44d4804dSStefan Eßer  * @param c    The return parameter for the quotient.
345*44d4804dSStefan Eßer  * @param rem  The return parameter for the remainder.
346*44d4804dSStefan 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 
355*44d4804dSStefan 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 
363*44d4804dSStefan 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 
368*44d4804dSStefan 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 
374*44d4804dSStefan Eßer /**
375*44d4804dSStefan Eßer  * Compare two BcDig arrays and return >0 if @a b is greater, <0 if @a b is
376*44d4804dSStefan Eßer  * less, and 0 if equal. Both @a a and @a b must have the same length.
377*44d4804dSStefan Eßer  * @param a    The first array.
378*44d4804dSStefan Eßer  * @param b    The second array.
379*44d4804dSStefan Eßer  * @param len  The minimum length of the arrays.
380*44d4804dSStefan 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 
399*44d4804dSStefan Eßer 	// Same num? Equal.
400252884aeSStefan Eßer 	if (a == b) return 0;
401*44d4804dSStefan Eßer 
402*44d4804dSStefan 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 
411*44d4804dSStefan 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 
416*44d4804dSStefan 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 
419*44d4804dSStefan 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 
424*44d4804dSStefan 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 
438*44d4804dSStefan 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 
441*44d4804dSStefan 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 
444*44d4804dSStefan Eßer 	// If there was no difference, then the final step is to check which number
445*44d4804dSStefan 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 
459*44d4804dSStefan Eßer 	// Grab these needed values; places_rdx is the rdx equivalent to places like
460*44d4804dSStefan 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;
463*44d4804dSStefan Eßer 
464*44d4804dSStefan 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 
470*44d4804dSStefan 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 
475*44d4804dSStefan Eßer 		// This calculates how many decimal digits are in the least significant
476*44d4804dSStefan 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;
482*44d4804dSStefan Eßer 
483*44d4804dSStefan Eßer 		// We have to move limbs to maintain invariants. The limbs must begin at
484*44d4804dSStefan 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;
499*44d4804dSStefan Eßer 
500*44d4804dSStefan 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 
506*44d4804dSStefan Eßer 	// Grab these needed values; places_rdx is the rdx equivalent to places like
507*44d4804dSStefan 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 
511*44d4804dSStefan Eßer 	// This is the hard case. We need to expand the number, move the limbs, and
512*44d4804dSStefan 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 
519*44d4804dSStefan 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 
527*44d4804dSStefan Eßer /**
528*44d4804dSStefan Eßer  * Retires (finishes) a multiplication or division operation.
529*44d4804dSStefan 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 {
533*44d4804dSStefan 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);
538*44d4804dSStefan Eßer 
539*44d4804dSStefan 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 
543*44d4804dSStefan Eßer /**
544*44d4804dSStefan Eßer  * Splits a number into two BcNum's. This is used in Karatsuba.
545*44d4804dSStefan Eßer  * @param n    The number to split.
546*44d4804dSStefan Eßer  * @param idx  The index to split at.
547*44d4804dSStefan Eßer  * @param a    An out parameter; the low part of @a n.
548*44d4804dSStefan Eßer  * @param b    An out parameter; the high part of @a n.
549*44d4804dSStefan 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 {
553*44d4804dSStefan 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 
557*44d4804dSStefan Eßer 	// The usual case.
558252884aeSStefan Eßer 	if (idx < n->len) {
559252884aeSStefan Eßer 
560*44d4804dSStefan 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 
570*44d4804dSStefan Eßer 		// Copy the arrays. This is not necessary for safety, but it is faster,
571*44d4804dSStefan 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 	}
577*44d4804dSStefan 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 
583*44d4804dSStefan Eßer /**
584*44d4804dSStefan Eßer  * Copies a number into another, but shifts the rdx so that the result number
585*44d4804dSStefan Eßer  * only sees the integer part of the source number.
586*44d4804dSStefan Eßer  * @param n  The number to copy.
587*44d4804dSStefan Eßer  * @param r  The result number with a shifted rdx, len, and num.
588*44d4804dSStefan Eßer  */
589*44d4804dSStefan Eßer static void bc_num_shiftRdx(const BcNum *restrict n, BcNum *restrict r) {
590*44d4804dSStefan Eßer 
591*44d4804dSStefan Eßer 	size_t rdx = BC_NUM_RDX_VAL(n);
592*44d4804dSStefan Eßer 
593*44d4804dSStefan Eßer 	r->len = n->len - rdx;
594*44d4804dSStefan Eßer 	r->cap = n->cap - rdx;
595*44d4804dSStefan Eßer 	r->num = n->num + rdx;
596*44d4804dSStefan Eßer 
597*44d4804dSStefan Eßer 	BC_NUM_RDX_SET_NEG(r, 0, BC_NUM_NEG(n));
598*44d4804dSStefan Eßer 	r->scale = 0;
599*44d4804dSStefan Eßer }
600*44d4804dSStefan Eßer 
601*44d4804dSStefan Eßer /**
602*44d4804dSStefan Eßer  * Shifts a number so that all of the least significant limbs of the number are
603*44d4804dSStefan Eßer  * skipped. This must be undone by bc_num_unshiftZero().
604*44d4804dSStefan Eßer  * @param n  The number to shift.
605*44d4804dSStefan 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 
610*44d4804dSStefan Eßer 	// If we don't have an integer, that is a problem, but it's also a bug
611*44d4804dSStefan 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 
622*44d4804dSStefan Eßer /**
623*44d4804dSStefan Eßer  * Undo the damage done by bc_num_unshiftZero(). This must be called like all
624*44d4804dSStefan Eßer  * cleanup functions: after a label used by setjmp() and longjmp().
625*44d4804dSStefan Eßer  * @param n           The number to unshift.
626*44d4804dSStefan Eßer  * @param places_rdx  The amount the number was originally shift.
627*44d4804dSStefan 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 
633*44d4804dSStefan Eßer /**
634*44d4804dSStefan Eßer  * Shifts the digits right within a number by no more than BC_BASE_DIGS - 1.
635*44d4804dSStefan Eßer  * This is the final step on shifting numbers with the shift operators. It
636*44d4804dSStefan Eßer  * depends on the caller to shift the limbs properly because all it does is
637*44d4804dSStefan Eßer  * ensure that the rdx point is realigned to be between limbs.
638*44d4804dSStefan Eßer  * @param n    The number to shift digits in.
639*44d4804dSStefan Eßer  * @param dig  The number of places to shift right.
640*44d4804dSStefan 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 
649*44d4804dSStefan 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 
653*44d4804dSStefan Eßer 	// Run a series of divisions and mods with carries across the entire number
654*44d4804dSStefan 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 
666*44d4804dSStefan Eßer /**
667*44d4804dSStefan Eßer  * Shift a number left by a certain number of places. This is the workhorse of
668*44d4804dSStefan Eßer  * the left shift operator.
669*44d4804dSStefan Eßer  * @param n       The number to shift left.
670*44d4804dSStefan Eßer  * @param places  The amount of places to shift @a n left by.
671*44d4804dSStefan 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;
679*44d4804dSStefan Eßer 
680*44d4804dSStefan 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);
683*44d4804dSStefan Eßer 		if (size > SIZE_MAX - 1) bc_err(BC_ERR_MATH_OVERFLOW);
684252884aeSStefan Eßer 	}
685*44d4804dSStefan Eßer 
686*44d4804dSStefan 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 
693*44d4804dSStefan Eßer 	// When I changed bc to have multiple digits per limb, this was the hardest
694*44d4804dSStefan Eßer 	// code to change. This and shift right. Make sure you understand this
695*44d4804dSStefan Eßer 	// before attempting anything.
696*44d4804dSStefan Eßer 
697*44d4804dSStefan 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);
700*44d4804dSStefan Eßer 
701*44d4804dSStefan Eßer 	// Convert places to a rdx value.
702252884aeSStefan Eßer 	places_rdx = BC_NUM_RDX(places);
703252884aeSStefan Eßer 
704*44d4804dSStefan Eßer 	// If the number is not an integer, we need special care. The reason an
705*44d4804dSStefan Eßer 	// integer doesn't is because left shift would only extend the integer,
706*44d4804dSStefan Eßer 	// whereas a non-integer might have its fractional part eliminated or only
707*44d4804dSStefan 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 
712*44d4804dSStefan 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 
717*44d4804dSStefan Eßer 			// We want mod to be in the range [1, BC_BASE_DIGS], not
718*44d4804dSStefan Eßer 			// [0, BC_BASE_DIGS).
719252884aeSStefan Eßer 			mod = mod ? mod : BC_BASE_DIGS;
720*44d4804dSStefan Eßer 
721*44d4804dSStefan 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 
724*44d4804dSStefan 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 
731*44d4804dSStefan 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 
739*44d4804dSStefan 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 
749*44d4804dSStefan 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;
762*44d4804dSStefan Eßer 
763*44d4804dSStefan 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 
770*44d4804dSStefan 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);
773*44d4804dSStefan Eßer 
774252884aeSStefan Eßer 	scale = n->scale;
775*44d4804dSStefan Eßer 
776*44d4804dSStefan 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;
779*44d4804dSStefan Eßer 
780*44d4804dSStefan 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 
784*44d4804dSStefan 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 
794*44d4804dSStefan Eßer 	// Clamp expanding.
795252884aeSStefan Eßer 	if (expand > int_len) expand -= int_len;
796252884aeSStefan Eßer 	else expand = 0;
797252884aeSStefan Eßer 
798*44d4804dSStefan 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));
802*44d4804dSStefan Eßer 
803*44d4804dSStefan 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 
808*44d4804dSStefan 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 
820*44d4804dSStefan Eßer /**
821*44d4804dSStefan Eßer  * Invert @a into @a b at the current scale.
822*44d4804dSStefan Eßer  * @param a      The number to invert.
823*44d4804dSStefan Eßer  * @param b      The return parameter. This must be preallocated.
824*44d4804dSStefan Eßer  * @param scale  The current scale.
825*44d4804dSStefan Eßer  */
826*44d4804dSStefan Eßer static inline void bc_num_inv(BcNum *a, BcNum *b, size_t scale) {
827252884aeSStefan Eßer 	assert(BC_NUM_NONZERO(a));
828*44d4804dSStefan Eßer 	bc_num_div(&vm.one, a, b, scale);
829*44d4804dSStefan Eßer }
830252884aeSStefan Eßer 
831*44d4804dSStefan Eßer /**
832*44d4804dSStefan Eßer  * Tests if a number is a integer with scale or not. Returns true if the number
833*44d4804dSStefan Eßer  * is not an integer. If it is, its integer shifted form is copied into the
834*44d4804dSStefan Eßer  * result parameter for use where only integers are allowed.
835*44d4804dSStefan Eßer  * @param n  The integer to test and shift.
836*44d4804dSStefan Eßer  * @param r  The number to store the shifted result into. This number should
837*44d4804dSStefan Eßer  *           *not* be allocated.
838*44d4804dSStefan Eßer  * @return   True if the number is a non-integer, false otherwise.
839*44d4804dSStefan Eßer  */
840*44d4804dSStefan Eßer static bool bc_num_nonInt(const BcNum *restrict n, BcNum *restrict r) {
841252884aeSStefan Eßer 
842*44d4804dSStefan Eßer 	bool zero;
843*44d4804dSStefan Eßer 	size_t i, rdx = BC_NUM_RDX_VAL(n);
844*44d4804dSStefan Eßer 
845*44d4804dSStefan Eßer 	if (!rdx) {
846*44d4804dSStefan Eßer 		memcpy(r, n, sizeof(BcNum));
847*44d4804dSStefan Eßer 		return false;
848*44d4804dSStefan Eßer 	}
849*44d4804dSStefan Eßer 
850*44d4804dSStefan Eßer 	zero = true;
851*44d4804dSStefan Eßer 
852*44d4804dSStefan Eßer 	for (i = 0; zero && i < rdx; ++i) zero = (n->num[i] == 0);
853*44d4804dSStefan Eßer 
854*44d4804dSStefan Eßer 	if (BC_ERR(!zero)) return true;
855*44d4804dSStefan Eßer 
856*44d4804dSStefan Eßer 	bc_num_shiftRdx(n, r);
857*44d4804dSStefan Eßer 
858*44d4804dSStefan Eßer 	return false;
859252884aeSStefan Eßer }
860252884aeSStefan Eßer 
861252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
862*44d4804dSStefan Eßer 
863*44d4804dSStefan Eßer /**
864*44d4804dSStefan Eßer  * Execute common code for an operater that needs an integer for the second
865*44d4804dSStefan Eßer  * operand and return the integer operand as a BcBigDig.
866*44d4804dSStefan Eßer  * @param a  The first operand.
867*44d4804dSStefan Eßer  * @param b  The second operand.
868*44d4804dSStefan Eßer  * @param c  The result operand.
869*44d4804dSStefan Eßer  * @return   The second operand as a hardware integer.
870*44d4804dSStefan Eßer  */
871*44d4804dSStefan Eßer static BcBigDig bc_num_intop(const BcNum *a, const BcNum *b, BcNum *restrict c)
872252884aeSStefan Eßer {
873*44d4804dSStefan Eßer 	BcNum temp;
874*44d4804dSStefan Eßer 
875*44d4804dSStefan Eßer 	if (BC_ERR(bc_num_nonInt(b, &temp))) bc_err(BC_ERR_MATH_NON_INTEGER);
876*44d4804dSStefan Eßer 
877252884aeSStefan Eßer 	bc_num_copy(c, a);
878*44d4804dSStefan Eßer 
879*44d4804dSStefan Eßer 	return bc_num_bigdig(&temp);
880252884aeSStefan Eßer }
881252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
882252884aeSStefan Eßer 
883*44d4804dSStefan Eßer /**
884*44d4804dSStefan Eßer  * This is the actual implementation of add *and* subtract. Since this function
885*44d4804dSStefan Eßer  * doesn't need to use scale (per the bc spec), I am hijacking it to say whether
886*44d4804dSStefan Eßer  * it's doing an add or a subtract. And then I convert substraction to addition
887*44d4804dSStefan Eßer  * of negative second operand. This is a BcNumBinOp function.
888*44d4804dSStefan Eßer  * @param a    The first operand.
889*44d4804dSStefan Eßer  * @param b    The second operand.
890*44d4804dSStefan Eßer  * @param c    The return parameter.
891*44d4804dSStefan Eßer  * @param sub  Non-zero for a subtract, zero for an add.
892*44d4804dSStefan 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 	}
904*44d4804dSStefan 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
912*44d4804dSStefan 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 
915*44d4804dSStefan Eßer 	// Figure out if we will actually add the numbers if their signs are equal
916*44d4804dSStefan 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 
923*44d4804dSStefan Eßer 	// Figure out which number will have its last limbs copied (for addition) or
924*44d4804dSStefan 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 
952*44d4804dSStefan 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 
969*44d4804dSStefan Eßer 	// This is true if the numbers have a different number of limbs after the
970*44d4804dSStefan 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 
1002*44d4804dSStefan 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 
1007*44d4804dSStefan 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 
1011*44d4804dSStefan 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
1015*44d4804dSStefan Eßer 	// operand above, the actual add or subtract can be performed as if the rdx
1016*44d4804dSStefan Eßer 	// of both operands was the same.
1017*44d4804dSStefan 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) {
1022*44d4804dSStefan Eßer 
1023*44d4804dSStefan 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);
1026*44d4804dSStefan Eßer 
1027*44d4804dSStefan 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 {
1031*44d4804dSStefan Eßer 
1032*44d4804dSStefan 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);
1035*44d4804dSStefan Eßer 
1036*44d4804dSStefan 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);
1038*44d4804dSStefan Eßer 
1039*44d4804dSStefan 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 
1055*44d4804dSStefan Eßer /**
1056*44d4804dSStefan Eßer  * The simple multiplication that karatsuba dishes out to when the length of the
1057*44d4804dSStefan Eßer  * numbers gets low enough. This doesn't use scale because it treats the
1058*44d4804dSStefan Eßer  * operands as though they are integers.
1059*44d4804dSStefan Eßer  * @param a  The first operand.
1060*44d4804dSStefan Eßer  * @param b  The second operand.
1061*44d4804dSStefan Eßer  * @param c  The return parameter.
1062*44d4804dSStefan Eßer  */
1063*44d4804dSStefan Eßer static void bc_num_m_simp(const BcNum *a, const BcNum *b, BcNum *restrict c) {
1064*44d4804dSStefan 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 
1072*44d4804dSStefan 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 
1076*44d4804dSStefan 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 
1080*44d4804dSStefan Eßer 	// This is the actual multiplication loop. It uses the lattice form of long
1081*44d4804dSStefan Eßer 	// multiplication (see the explanation on the web page at
1082*44d4804dSStefan Eßer 	// https://knilt.arcc.albany.edu/What_is_Lattice_Multiplication or the
1083*44d4804dSStefan 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);
1087*44d4804dSStefan Eßer 		size_t j, k;
1088252884aeSStefan Eßer 
1089*44d4804dSStefan Eßer 		// These are the start indices.
1090*44d4804dSStefan Eßer 		j = (size_t) BC_MAX(0, sidx);
1091*44d4804dSStefan Eßer 		k = BC_MIN(i, blen - 1);
1092*44d4804dSStefan Eßer 
1093*44d4804dSStefan Eßer 		// On every iteration of this loop, a multiplication happens, then the
1094*44d4804dSStefan 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 
1105*44d4804dSStefan 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 
1111*44d4804dSStefan 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 
1125*44d4804dSStefan Eßer /**
1126*44d4804dSStefan Eßer  * Does a shifted add or subtract for Karatsuba below. This calls either
1127*44d4804dSStefan Eßer  * bc_num_addArrays() or bc_num_subArrays().
1128*44d4804dSStefan Eßer  * @param n      An in/out parameter; the first operand and return parameter.
1129*44d4804dSStefan Eßer  * @param a      The second operand.
1130*44d4804dSStefan Eßer  * @param shift  The amount to shift @a n by when adding/subtracting.
1131*44d4804dSStefan Eßer  * @param op     The function to call, either bc_num_addArrays() or
1132*44d4804dSStefan Eßer  *               bc_num_subArrays().
1133*44d4804dSStefan 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 
1142*44d4804dSStefan Eßer /**
1143*44d4804dSStefan Eßer  * Implements the Karatsuba algorithm.
1144*44d4804dSStefan Eßer  */
1145*44d4804dSStefan 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;
1156*44d4804dSStefan 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 	}
1162*44d4804dSStefan Eßer 
1163*44d4804dSStefan 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 
1169*44d4804dSStefan Eßer 	// We need to calculate the max size of the numbers that can result from the
1170*44d4804dSStefan 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 
1175*44d4804dSStefan Eßer 	// Calculate the space needed for all of the temporary allocations. We do
1176*44d4804dSStefan 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 
1181*44d4804dSStefan 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 
1184*44d4804dSStefan 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);
1196*44d4804dSStefan Eßer 
1197*44d4804dSStefan Eßer 	// Some temporaries need the ability to grow, so we allocate them
1198*44d4804dSStefan 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 
1210*44d4804dSStefan 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 
1215*44d4804dSStefan Eßer 	// Split the parameters.
1216*44d4804dSStefan Eßer 	bc_num_split(a, max2, &l1, &h1);
1217*44d4804dSStefan Eßer 	bc_num_split(b, max2, &l2, &h2);
1218*44d4804dSStefan Eßer 
1219*44d4804dSStefan 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 
1223*44d4804dSStefan Eßer 	// The if statements below are there for efficiency reasons. The best way to
1224*44d4804dSStefan Eßer 	// understand them is to understand the Karatsuba algorithm because now that
1225*44d4804dSStefan Eßer 	// the ollocations and splits are done, the algorithm is pretty
1226*44d4804dSStefan Eßer 	// straightforward.
1227*44d4804dSStefan 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 
1275*44d4804dSStefan Eßer /**
1276*44d4804dSStefan Eßer  * Does checks for Karatsuba. It also changes things to ensure that the
1277*44d4804dSStefan Eßer  * Karatsuba and simple multiplication can treat the numbers as integers. This
1278*44d4804dSStefan Eßer  * is a BcNumBinOp function.
1279*44d4804dSStefan Eßer  * @param a      The first operand.
1280*44d4804dSStefan Eßer  * @param b      The second operand.
1281*44d4804dSStefan Eßer  * @param c      The return parameter.
1282*44d4804dSStefan Eßer  * @param scale  The current scale.
1283*44d4804dSStefan 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);
1293*44d4804dSStefan Eßer 
1294252884aeSStefan Eßer 	ascale = a->scale;
1295252884aeSStefan Eßer 	bscale = b->scale;
1296*44d4804dSStefan Eßer 
1297*44d4804dSStefan 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 
1303*44d4804dSStefan Eßer 	// If this condition is true, we can use bc_num_mulArray(), which would be
1304*44d4804dSStefan 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 
1310*44d4804dSStefan 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 
1322*44d4804dSStefan 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 
1334*44d4804dSStefan Eßer 	// We need copies because of all of the mutation needed to make Karatsuba
1335*44d4804dSStefan 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 
1355*44d4804dSStefan 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 
1369*44d4804dSStefan 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 
1382*44d4804dSStefan Eßer 	// The return parameter needs to have its scale set. This is the start. It
1383*44d4804dSStefan Eßer 	// also needs to be shifted by the same amount as a and b have limbs after
1384*44d4804dSStefan 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);
1389*44d4804dSStefan Eßer 
1390*44d4804dSStefan 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 
1405*44d4804dSStefan Eßer /**
1406*44d4804dSStefan Eßer  * Returns true if the BcDig array has non-zero limbs, false otherwise.
1407*44d4804dSStefan Eßer  * @param a    The array to test.
1408*44d4804dSStefan Eßer  * @param len  The length of the array.
1409*44d4804dSStefan Eßer  * @return     True if @a has any non-zero limbs, false otherwise.
1410*44d4804dSStefan 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 
1418*44d4804dSStefan Eßer /**
1419*44d4804dSStefan Eßer  * Compares a BcDig array against a BcNum. This is especially suited for
1420*44d4804dSStefan Eßer  * division. Returns >0 if @a a is greater than @a b, <0 if it is less, and =0
1421*44d4804dSStefan Eßer  * if they are equal.
1422*44d4804dSStefan Eßer  * @param a    The array.
1423*44d4804dSStefan Eßer  * @param b    The number.
1424*44d4804dSStefan Eßer  * @param len  The length to assume the arrays are. This is always less than the
1425*44d4804dSStefan Eßer  *             actual length because of how this is implemented.
1426*44d4804dSStefan 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 
1441*44d4804dSStefan Eßer /**
1442*44d4804dSStefan Eßer  * Extends the two operands of a division by BC_BASE_DIGS minus the number of
1443*44d4804dSStefan Eßer  * digits in the divisor estimate. In other words, it is shifting the numbers in
1444*44d4804dSStefan Eßer  * order to force the divisor estimate to fill the limb.
1445*44d4804dSStefan Eßer  * @param a        The first operand.
1446*44d4804dSStefan Eßer  * @param b        The second operand.
1447*44d4804dSStefan Eßer  * @param divisor  The divisor estimate.
1448*44d4804dSStefan 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 
1462*44d4804dSStefan Eßer /**
1463*44d4804dSStefan Eßer  * Actually does division. This is a rewrite of my original code by Stefan Esser
1464*44d4804dSStefan Eßer  * from FreeBSD.
1465*44d4804dSStefan Eßer  * @param a      The first operand.
1466*44d4804dSStefan Eßer  * @param b      The second operand.
1467*44d4804dSStefan Eßer  * @param c      The return parameter.
1468*44d4804dSStefan Eßer  * @param scale  The current scale.
1469*44d4804dSStefan 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);
1479*44d4804dSStefan Eßer 
1480252884aeSStefan Eßer 	len = b->len;
1481252884aeSStefan Eßer 	end = a->len - len;
1482*44d4804dSStefan Eßer 
1483252884aeSStefan Eßer 	assert(len >= 1);
1484252884aeSStefan Eßer 
1485*44d4804dSStefan Eßer 	// This is a final time to make sure c is big enough and that its array is
1486*44d4804dSStefan 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 
1490*44d4804dSStefan 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 
1495*44d4804dSStefan Eßer 	// This is pulling the most significant limb of b in order to establish a
1496*44d4804dSStefan Eßer 	// good "estimate" for the actual divisor.
1497252884aeSStefan Eßer 	divisor = (BcBigDig) b->num[len - 1];
1498252884aeSStefan Eßer 
1499*44d4804dSStefan Eßer 	// The entire bit of code in this if statement is to tighten the estimate of
1500*44d4804dSStefan 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 
1503*44d4804dSStefan Eßer 		// This takes a little bit of understanding. The "10*BC_BASE_DIGS/6+1"
1504*44d4804dSStefan Eßer 		// results in either 16 for 64-bit 9-digit limbs or 7 for 32-bit 4-digit
1505*44d4804dSStefan Eßer 		// limbs. Then it shifts a 1 by that many, which in both cases, puts the
1506*44d4804dSStefan Eßer 		// result above *half* of the max value a limb can store. Basically,
1507*44d4804dSStefan Eßer 		// this quickly calculates if the divisor is greater than half the max
1508*44d4804dSStefan Eßer 		// of a limb.
1509252884aeSStefan Eßer 		nonzero = (divisor > 1 << ((10 * BC_BASE_DIGS) / 6 + 1));
1510252884aeSStefan Eßer 
1511*44d4804dSStefan Eßer 		// If the divisor is *not* greater than half the limb...
1512252884aeSStefan Eßer 		if (!nonzero) {
1513252884aeSStefan Eßer 
1514*44d4804dSStefan Eßer 			// Extend the parameters by the number of missing digits in the
1515*44d4804dSStefan Eßer 			// divisor.
1516252884aeSStefan Eßer 			bc_num_divExtend(a, b, divisor);
1517252884aeSStefan Eßer 
1518*44d4804dSStefan Eßer 			// Check bc_num_d(). In there, we grow a again and again. We do it
1519*44d4804dSStefan 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 
1523*44d4804dSStefan 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 
1526*44d4804dSStefan Eßer 			// Grab the new divisor estimate, new because the shift has made it
1527*44d4804dSStefan 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 
1536*44d4804dSStefan Eßer 	// If b has other nonzero limbs, we want the divisor to be one higher, so
1537*44d4804dSStefan Eßer 	// that it is an upper bound.
1538252884aeSStefan Eßer 	divisor += nonzero;
1539252884aeSStefan Eßer 
1540*44d4804dSStefan 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 
1555*44d4804dSStefan Eßer 	// This is the actual division loop.
1556*44d4804dSStefan 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 
1568*44d4804dSStefan Eßer 		// This is true if n is greater than b, which means that division can
1569*44d4804dSStefan Eßer 		// proceed, so this inner loop is the part that implements one instance
1570*44d4804dSStefan Eßer 		// of the division.
1571252884aeSStefan Eßer 		while (cmp >= 0) {
1572252884aeSStefan Eßer 
1573*44d4804dSStefan Eßer 			BcBigDig n1, dividend, quotient;
1574252884aeSStefan Eßer 
1575*44d4804dSStefan Eßer 			// These should be named obviously enough. Just imagine that it's a
1576*44d4804dSStefan 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];
1579*44d4804dSStefan Eßer 			quotient = (dividend / divisor);
1580252884aeSStefan Eßer 
1581*44d4804dSStefan Eßer 			// If this is true, then we can just subtract. Remember: setting
1582*44d4804dSStefan Eßer 			// quotient to 1 is not bad because we already know that n is
1583*44d4804dSStefan Eßer 			// greater than b.
1584*44d4804dSStefan Eßer 			if (quotient <= 1) {
1585*44d4804dSStefan Eßer 				quotient = 1;
1586252884aeSStefan Eßer 				bc_num_subArrays(n, b->num, len);
1587252884aeSStefan Eßer 			}
1588252884aeSStefan Eßer 			else {
1589252884aeSStefan Eßer 
1590*44d4804dSStefan Eßer 				assert(quotient <= BC_BASE_POW);
1591252884aeSStefan Eßer 
1592*44d4804dSStefan Eßer 				// We need to multiply and subtract for a quotient above 1.
1593*44d4804dSStefan 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 
1597*44d4804dSStefan Eßer 			// The result is the *real* quotient, by the way, but it might take
1598*44d4804dSStefan Eßer 			// multiple trips around this loop to get it.
1599*44d4804dSStefan Eßer 			result += quotient;
1600252884aeSStefan Eßer 			assert(result <= BC_BASE_POW);
1601252884aeSStefan Eßer 
1602*44d4804dSStefan Eßer 			// And here's why it might take multiple trips: n might *still* be
1603*44d4804dSStefan Eßer 			// greater than b. So we have to loop again. That's what this is
1604*44d4804dSStefan 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 
1611*44d4804dSStefan 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 
1621*44d4804dSStefan Eßer /**
1622*44d4804dSStefan Eßer  * Implements division. This is a BcNumBinOp function.
1623*44d4804dSStefan Eßer  * @param a      The first operand.
1624*44d4804dSStefan Eßer  * @param b      The second operand.
1625*44d4804dSStefan Eßer  * @param c      The return parameter.
1626*44d4804dSStefan Eßer  * @param scale  The current scale.
1627*44d4804dSStefan 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 
1633*44d4804dSStefan Eßer 	if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
1634*44d4804dSStefan 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 	}
1639*44d4804dSStefan 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 	}
1645*44d4804dSStefan Eßer 
1646*44d4804dSStefan 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 
1658*44d4804dSStefan Eßer 	// Initialize copies of the parameters. We want the length of the first
1659*44d4804dSStefan Eßer 	// operand copy to be as big as the result because of the way the division
1660*44d4804dSStefan 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 
1671*44d4804dSStefan Eßer 	// Like the above comment, we want the copy of the first parameter to be
1672*44d4804dSStefan 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 
1681*44d4804dSStefan 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 
1687*44d4804dSStefan 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 
1694*44d4804dSStefan 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 
1700*44d4804dSStefan Eßer 	// Still setting things up. Why all of these things are needed is not
1701*44d4804dSStefan Eßer 	// something that can be easily explained, but it has to do with making the
1702*44d4804dSStefan Eßer 	// actual algorithm easier to understand because it can assume a lot of
1703*44d4804dSStefan Eßer 	// things. Thus, you should view all of this setup code as establishing
1704*44d4804dSStefan Eßer 	// assumptions for bc_num_d_long(), where the actual division happens.
1705*44d4804dSStefan Eßer 	if (cpardx == cpa.len) cpa.len = bc_num_nonZeroLen(&cpa);
1706*44d4804dSStefan 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 
1721*44d4804dSStefan Eßer /**
1722*44d4804dSStefan Eßer  * Implements divmod. This is the actual modulus function; since modulus
1723*44d4804dSStefan Eßer  * requires a division anyway, this returns the quotient and modulus. Either can
1724*44d4804dSStefan Eßer  * be thrown out as desired.
1725*44d4804dSStefan Eßer  * @param a      The first operand.
1726*44d4804dSStefan Eßer  * @param b      The second operand.
1727*44d4804dSStefan Eßer  * @param c      The return parameter for the quotient.
1728*44d4804dSStefan Eßer  * @param d      The return parameter for the modulus.
1729*44d4804dSStefan Eßer  * @param scale  The current scale.
1730*44d4804dSStefan Eßer  * @param ts     The scale that the operation should be done to. Yes, it's not
1731*44d4804dSStefan Eßer  *               necessarily the same as scale, per the bc spec.
1732*44d4804dSStefan 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 
1739*44d4804dSStefan Eßer 	if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
1740*44d4804dSStefan 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 
1755*44d4804dSStefan Eßer 	// Division.
1756252884aeSStefan Eßer 	bc_num_d(a, b, c, scale);
1757252884aeSStefan Eßer 
1758*44d4804dSStefan 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 
1764*44d4804dSStefan 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 
1768*44d4804dSStefan 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 
1781*44d4804dSStefan Eßer /**
1782*44d4804dSStefan Eßer  * Implements modulus/remainder. (Yes, I know they are different, but not in the
1783*44d4804dSStefan Eßer  * context of bc.) This is a BcNumBinOp function.
1784*44d4804dSStefan Eßer  * @param a      The first operand.
1785*44d4804dSStefan Eßer  * @param b      The second operand.
1786*44d4804dSStefan Eßer  * @param c      The return parameter.
1787*44d4804dSStefan Eßer  * @param scale  The current scale.
1788*44d4804dSStefan 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 
1799*44d4804dSStefan 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 
1814*44d4804dSStefan Eßer /**
1815*44d4804dSStefan Eßer  * Implements power (exponentiation). This is a BcNumBinOp function.
1816*44d4804dSStefan Eßer  * @param a      The first operand.
1817*44d4804dSStefan Eßer  * @param b      The second operand.
1818*44d4804dSStefan Eßer  * @param c      The return parameter.
1819*44d4804dSStefan Eßer  * @param scale  The current scale.
1820*44d4804dSStefan Eßer  */
1821252884aeSStefan Eßer static void bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1822252884aeSStefan Eßer 
1823*44d4804dSStefan Eßer 	BcNum copy, btemp;
1824*44d4804dSStefan Eßer 	BcBigDig exp;
1825*44d4804dSStefan Eßer 	size_t powrdx, resrdx;
1826*44d4804dSStefan Eßer 	bool neg;
1827252884aeSStefan Eßer 
1828*44d4804dSStefan Eßer 	if (BC_ERR(bc_num_nonInt(b, &btemp))) bc_err(BC_ERR_MATH_NON_INTEGER);
1829252884aeSStefan Eßer 
1830*44d4804dSStefan Eßer 	if (BC_NUM_ZERO(&btemp)) {
1831252884aeSStefan Eßer 		bc_num_one(c);
1832252884aeSStefan Eßer 		return;
1833252884aeSStefan Eßer 	}
1834*44d4804dSStefan Eßer 
1835252884aeSStefan Eßer 	if (BC_NUM_ZERO(a)) {
1836*44d4804dSStefan 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 	}
1840*44d4804dSStefan Eßer 
1841*44d4804dSStefan Eßer 	if (BC_NUM_ONE(&btemp)) {
1842*44d4804dSStefan 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 
1847*44d4804dSStefan Eßer 	neg = BC_NUM_NEG_NP(btemp);
1848*44d4804dSStefan Eßer 	BC_NUM_NEG_CLR_NP(btemp);
1849252884aeSStefan Eßer 
1850*44d4804dSStefan Eßer 	exp = bc_num_bigdig(&btemp);
1851*44d4804dSStefan Eßer 
1852*44d4804dSStefan 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 
1860*44d4804dSStefan Eßer 	// If this is true, then we do not have to do a division, and we need to
1861*44d4804dSStefan Eßer 	// set scale accordingly.
1862252884aeSStefan Eßer 	if (!neg) {
1863*44d4804dSStefan Eßer 		size_t max = BC_MAX(scale, a->scale), scalepow;
1864*44d4804dSStefan Eßer 		scalepow = bc_num_mulOverflow(a->scale, exp);
1865252884aeSStefan Eßer 		scale = BC_MIN(scalepow, max);
1866252884aeSStefan Eßer 	}
1867252884aeSStefan Eßer 
1868*44d4804dSStefan Eßer 	// This is only implementing the first exponentiation by squaring, until it
1869*44d4804dSStefan Eßer 	// reaches the first time where the square is actually used.
1870*44d4804dSStefan 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 
1876*44d4804dSStefan Eßer 	// Make c a copy of copy for the purpose of saving the squares that should
1877*44d4804dSStefan Eßer 	// be saved.
1878252884aeSStefan Eßer 	bc_num_copy(c, &copy);
1879252884aeSStefan Eßer 	resrdx = powrdx;
1880252884aeSStefan Eßer 
1881*44d4804dSStefan Eßer 	// Now finish the exponentiation by squaring, this time saving the squares
1882*44d4804dSStefan Eßer 	// as necessary.
1883*44d4804dSStefan 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 
1889*44d4804dSStefan Eßer 		// If this is true, we want to save that particular square. This does
1890*44d4804dSStefan Eßer 		// that by multiplying c with copy.
1891*44d4804dSStefan 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 
1899*44d4804dSStefan Eßer 	// Invert if necessary.
1900252884aeSStefan Eßer 	if (neg) bc_num_inv(c, c, scale);
1901252884aeSStefan Eßer 
1902*44d4804dSStefan Eßer 	// Truncate if necessary.
1903252884aeSStefan Eßer 	if (c->scale > scale) bc_num_truncate(c, c->scale - scale);
1904252884aeSStefan Eßer 
1905*44d4804dSStefan 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
1914*44d4804dSStefan Eßer /**
1915*44d4804dSStefan Eßer  * Implements the places operator. This is a BcNumBinOp function.
1916*44d4804dSStefan Eßer  * @param a      The first operand.
1917*44d4804dSStefan Eßer  * @param b      The second operand.
1918*44d4804dSStefan Eßer  * @param c      The return parameter.
1919*44d4804dSStefan Eßer  * @param scale  The current scale.
1920*44d4804dSStefan Eßer  */
1921252884aeSStefan Eßer static void bc_num_place(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1922252884aeSStefan Eßer 
1923*44d4804dSStefan Eßer 	BcBigDig val;
1924252884aeSStefan Eßer 
1925252884aeSStefan Eßer 	BC_UNUSED(scale);
1926252884aeSStefan Eßer 
1927*44d4804dSStefan Eßer 	val = bc_num_intop(a, b, c);
1928252884aeSStefan Eßer 
1929*44d4804dSStefan 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 
1934*44d4804dSStefan Eßer /**
1935*44d4804dSStefan Eßer  * Implements the left shift operator. This is a BcNumBinOp function.
1936*44d4804dSStefan Eßer  */
1937252884aeSStefan Eßer static void bc_num_left(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1938252884aeSStefan Eßer 
1939*44d4804dSStefan Eßer 	BcBigDig val;
1940252884aeSStefan Eßer 
1941252884aeSStefan Eßer 	BC_UNUSED(scale);
1942252884aeSStefan Eßer 
1943*44d4804dSStefan 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 
1948*44d4804dSStefan Eßer /**
1949*44d4804dSStefan Eßer  * Implements the right shift operator. This is a BcNumBinOp function.
1950*44d4804dSStefan Eßer  */
1951252884aeSStefan Eßer static void bc_num_right(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
1952252884aeSStefan Eßer 
1953*44d4804dSStefan Eßer 	BcBigDig val;
1954252884aeSStefan Eßer 
1955252884aeSStefan Eßer 	BC_UNUSED(scale);
1956252884aeSStefan Eßer 
1957*44d4804dSStefan 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 
1965*44d4804dSStefan Eßer /**
1966*44d4804dSStefan Eßer  * Prepares for, and calls, a binary operator function. This is probably the
1967*44d4804dSStefan Eßer  * most important function in the entire file because it establishes assumptions
1968*44d4804dSStefan Eßer  * that make the rest of the code so easy. Those assumptions include:
1969*44d4804dSStefan Eßer  *
1970*44d4804dSStefan Eßer  * - a is not the same pointer as c.
1971*44d4804dSStefan Eßer  * - b is not the same pointer as c.
1972*44d4804dSStefan Eßer  * - there is enough room in c for the result.
1973*44d4804dSStefan Eßer  *
1974*44d4804dSStefan Eßer  * Without these, this whole function would basically have to be duplicated for
1975*44d4804dSStefan Eßer  * *all* binary operators.
1976*44d4804dSStefan Eßer  *
1977*44d4804dSStefan Eßer  * @param a      The first operand.
1978*44d4804dSStefan Eßer  * @param b      The second operand.
1979*44d4804dSStefan Eßer  * @param c      The return parameter.
1980*44d4804dSStefan Eßer  * @param scale  The current scale.
1981*44d4804dSStefan Eßer  * @param req    The number of limbs needed to fit the result.
1982*44d4804dSStefan 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 
1996*44d4804dSStefan 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 
2008*44d4804dSStefan 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 
2022*44d4804dSStefan Eßer 	// Actually reallocate. If we don't reallocate, we want to expand at the
2023*44d4804dSStefan Eßer 	// very least.
2024252884aeSStefan Eßer 	if (init) {
2025252884aeSStefan Eßer 
2026252884aeSStefan Eßer 		bc_num_init(c, req);
2027252884aeSStefan Eßer 
2028*44d4804dSStefan Eßer 		// Must prepare for cleanup. We want this here so that locals that got
2029*44d4804dSStefan 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 
2038*44d4804dSStefan Eßer 	// It is okay for a and b to be the same. If a binary operator function does
2039*44d4804dSStefan Eßer 	// need them to be different, the binary operator function is responsible
2040*44d4804dSStefan Eßer 	// for that.
2041*44d4804dSStefan Eßer 
2042*44d4804dSStefan 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:
2051*44d4804dSStefan 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
2060*44d4804dSStefan Eßer 
2061*44d4804dSStefan Eßer /**
2062*44d4804dSStefan Eßer  * Tests a number string for validity. This function has a history; I originally
2063*44d4804dSStefan Eßer  * wrote it because I did not trust my parser. Over time, however, I came to
2064*44d4804dSStefan Eßer  * trust it, so I was able to relegate this function to debug builds only, and I
2065*44d4804dSStefan Eßer  * used it in assert()'s. But then I created the library, and well, I can't
2066*44d4804dSStefan Eßer  * trust users, so I reused this for yelling at users.
2067*44d4804dSStefan Eßer  * @param val  The string to check to see if it's a valid number string.
2068*44d4804dSStefan Eßer  * @return     True if the string is a valid number string, false otherwise.
2069*44d4804dSStefan 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 
2075*44d4804dSStefan Eßer 	// Notice that I don't check if there is a negative sign. That is not part
2076*44d4804dSStefan Eßer 	// of a valid number, except in the library. The library-specific code takes
2077*44d4804dSStefan Eßer 	// care of that part.
2078*44d4804dSStefan Eßer 
2079*44d4804dSStefan Eßer 	// Nothing in the string is okay.
2080252884aeSStefan Eßer 	if (!len) return true;
2081252884aeSStefan Eßer 
2082*44d4804dSStefan 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 
2087*44d4804dSStefan Eßer 		// If we have found a radix point...
2088252884aeSStefan Eßer 		if (c == '.') {
2089252884aeSStefan Eßer 
2090*44d4804dSStefan 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 
2097*44d4804dSStefan 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 
2105*44d4804dSStefan Eßer /**
2106*44d4804dSStefan Eßer  * Parses one character and returns the digit that corresponds to that
2107*44d4804dSStefan Eßer  * character according to the base.
2108*44d4804dSStefan Eßer  * @param c     The character to parse.
2109*44d4804dSStefan Eßer  * @param base  The base.
2110*44d4804dSStefan Eßer  * @return      The character as a digit.
2111*44d4804dSStefan Eßer  */
2112*44d4804dSStefan Eßer static BcBigDig bc_num_parseChar(char c, size_t base) {
2113252884aeSStefan Eßer 
2114*44d4804dSStefan Eßer 	assert(isupper(c) || isdigit(c));
2115*44d4804dSStefan Eßer 
2116*44d4804dSStefan Eßer 	// If a letter...
2117252884aeSStefan Eßer 	if (isupper(c)) {
2118*44d4804dSStefan Eßer 
2119*44d4804dSStefan Eßer 		// This returns the digit that directly corresponds with the letter.
2120252884aeSStefan Eßer 		c = BC_NUM_NUM_LETTER(c);
2121*44d4804dSStefan Eßer 
2122*44d4804dSStefan Eßer 		// If the digit is greater than the base, we clamp.
2123*44d4804dSStefan Eßer 		c = ((size_t) c) >= base ? (char) base - 1 : c;
2124252884aeSStefan Eßer 	}
2125*44d4804dSStefan 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 
2131*44d4804dSStefan Eßer /**
2132*44d4804dSStefan Eßer  * Parses a string as a decimal number. This is separate because it's going to
2133*44d4804dSStefan Eßer  * be the most used, and it can be heavily optimized for decimal only.
2134*44d4804dSStefan Eßer  * @param n    The number to parse into and return. Must be preallocated.
2135*44d4804dSStefan Eßer  * @param val  The string to parse.
2136*44d4804dSStefan 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 
2143*44d4804dSStefan 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 
2149*44d4804dSStefan Eßer 	// All 0's. We can just return, since this procedure expects a virgin
2150*44d4804dSStefan Eßer 	// (already 0) BcNum.
2151252884aeSStefan Eßer 	if (!val[0]) return;
2152252884aeSStefan Eßer 
2153*44d4804dSStefan Eßer 	// The length of the string is the length of the number, except it might be
2154*44d4804dSStefan Eßer 	// one bigger because of a decimal point.
2155252884aeSStefan Eßer 	len = strlen(val);
2156252884aeSStefan Eßer 
2157*44d4804dSStefan Eßer 	// Find the location of the decimal point.
2158252884aeSStefan Eßer 	ptr = strchr(val, '.');
2159252884aeSStefan Eßer 	rdx = (ptr != NULL);
2160252884aeSStefan Eßer 
2161*44d4804dSStefan Eßer 	// We eat leading zeroes again. These leading zeroes are different because
2162*44d4804dSStefan Eßer 	// they will come after the decimal point if they exist, and since that's
2163*44d4804dSStefan 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 
2166*44d4804dSStefan Eßer 	// Set the scale of the number based on the location of the decimal point.
2167*44d4804dSStefan Eßer 	// The casts to uintptr_t is to ensure that bc does not hit undefined
2168*44d4804dSStefan 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 
2172*44d4804dSStefan Eßer 	// Set rdx.
217350696a6eSStefan Eßer 	BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
2174*44d4804dSStefan Eßer 
2175*44d4804dSStefan Eßer 	// Calculate length. First, the length of the integer, then the number of
2176*44d4804dSStefan 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 
2183*44d4804dSStefan 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 
2194*44d4804dSStefan 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 
2199*44d4804dSStefan Eßer 		// The exponent and power.
2200252884aeSStefan Eßer 		exp = (BcBigDig) i;
2201252884aeSStefan Eßer 		pow = bc_num_pow10[exp];
2202252884aeSStefan Eßer 
2203*44d4804dSStefan Eßer 		// Parse loop. We parse backwards because numbers are stored little
2204*44d4804dSStefan 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 
2209*44d4804dSStefan Eßer 			// Skip the decimal point.
2210252884aeSStefan Eßer 			if (c == '.') exp -= 1;
2211252884aeSStefan Eßer 			else {
2212252884aeSStefan Eßer 
2213*44d4804dSStefan Eßer 				// The index of the limb.
2214252884aeSStefan Eßer 				size_t idx = exp / BC_BASE_DIGS;
2215252884aeSStefan Eßer 
2216*44d4804dSStefan Eßer 				// Clamp for the base.
2217252884aeSStefan Eßer 				if (isupper(c)) c = '9';
2218*44d4804dSStefan Eßer 
2219*44d4804dSStefan Eßer 				// Add the digit to the limb.
2220252884aeSStefan Eßer 				n->num[idx] += (((BcBigDig) c) - '0') * pow;
2221252884aeSStefan Eßer 
2222*44d4804dSStefan 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 
2230*44d4804dSStefan Eßer /**
2231*44d4804dSStefan Eßer  * Parse a number in any base (besides decimal).
2232*44d4804dSStefan Eßer  * @param n     The number to parse into and return. Must be preallocated.
2233*44d4804dSStefan Eßer  * @param val   The string to parse.
2234*44d4804dSStefan Eßer  * @param base  The base to parse as.
2235*44d4804dSStefan 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 
2245*44d4804dSStefan 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 
2258*44d4804dSStefan Eßer 	// We split parsing into parsing the integer and parsing the fractional
2259*44d4804dSStefan Eßer 	// part.
2260*44d4804dSStefan Eßer 
2261*44d4804dSStefan Eßer 	// Parse the integer part. This is the easy part because we just multiply
2262*44d4804dSStefan 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 
2265*44d4804dSStefan Eßer 		// Convert the character to a digit.
2266252884aeSStefan Eßer 		v = bc_num_parseChar(c, base);
2267252884aeSStefan Eßer 
2268*44d4804dSStefan Eßer 		// Multiply the number.
2269252884aeSStefan Eßer 		bc_num_mulArray(n, base, &mult1);
2270*44d4804dSStefan Eßer 
2271*44d4804dSStefan 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 
2276*44d4804dSStefan Eßer 	// If this condition is true, then we are done. We still need to do cleanup
2277*44d4804dSStefan Eßer 	// though.
227810328f8bSStefan Eßer 	if (i == len && !val[i]) goto int_err;
2279252884aeSStefan Eßer 
2280*44d4804dSStefan 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 
2285*44d4804dSStefan 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 
2297*44d4804dSStefan Eßer 	// Pointers for easy switching.
2298252884aeSStefan Eßer 	m1 = &mult1;
2299252884aeSStefan Eßer 	m2 = &mult2;
2300252884aeSStefan Eßer 
2301*44d4804dSStefan 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 
2306*44d4804dSStefan Eßer 		// Convert the character to a digit.
2307252884aeSStefan Eßer 		v = bc_num_parseChar(c, base);
2308252884aeSStefan Eßer 
2309*44d4804dSStefan Eßer 		// We keep growing result2 according to the base because the more digits
2310*44d4804dSStefan Eßer 		// after the radix, the more significant the digits close to the radix
2311*44d4804dSStefan Eßer 		// should be.
2312252884aeSStefan Eßer 		bc_num_mulArray(&result1, base, &result2);
2313252884aeSStefan Eßer 
2314*44d4804dSStefan Eßer 		// Convert the digit to a number.
2315252884aeSStefan Eßer 		bc_num_bigdig2num(&temp, v);
2316*44d4804dSStefan Eßer 
2317*44d4804dSStefan Eßer 		// Add the digit into the fraction part.
2318252884aeSStefan Eßer 		bc_num_add(&result2, &temp, &result1, 0);
2319*44d4804dSStefan Eßer 
2320*44d4804dSStefan 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 
2327*44d4804dSStefan 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
2334*44d4804dSStefan Eßer 	// multiplied by base, and base cannot be 0, so mult cannot be 0. And this
2335*44d4804dSStefan Eßer 	// is the reason we keep growing m1 and m2; this division is what converts
2336*44d4804dSStefan Eßer 	// the parsed fractional part from an integer to a fractional part.
2337252884aeSStefan Eßer 	bc_num_div(&result1, m1, &result2, digs * 2);
2338*44d4804dSStefan Eßer 
2339*44d4804dSStefan Eßer 	// Pretruncate.
2340252884aeSStefan Eßer 	bc_num_truncate(&result2, digs);
2341*44d4804dSStefan Eßer 
2342*44d4804dSStefan 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 
2345*44d4804dSStefan 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 
2363*44d4804dSStefan Eßer /**
2364*44d4804dSStefan Eßer  * Prints a backslash+newline combo if the number of characters needs it. This
2365*44d4804dSStefan Eßer  * is really a convenience function.
2366*44d4804dSStefan Eßer  */
236750696a6eSStefan Eßer static inline void bc_num_printNewline(void) {
236850696a6eSStefan Eßer #if !BC_ENABLE_LIBRARY
2369252884aeSStefan Eßer 	if (vm.nchars >= vm.line_len - 1) {
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 
2376*44d4804dSStefan Eßer /**
2377*44d4804dSStefan Eßer  * Prints a character after a backslash+newline, if needed.
2378*44d4804dSStefan Eßer  * @param c       The character to print.
2379*44d4804dSStefan Eßer  * @param bslash  Whether to print a backslash+newline.
2380*44d4804dSStefan Eßer  */
2381*44d4804dSStefan Eßer static void bc_num_putchar(int c, bool bslash) {
2382*44d4804dSStefan 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 
2386*44d4804dSStefan Eßer #if !BC_ENABLE_LIBRARY
2387*44d4804dSStefan Eßer 
2388*44d4804dSStefan Eßer /**
2389*44d4804dSStefan Eßer  * Prints a character for a number's digit. This is for printing for dc's P
2390*44d4804dSStefan Eßer  * command. This function does not need to worry about radix points. This is a
2391*44d4804dSStefan Eßer  * BcNumDigitOp.
2392*44d4804dSStefan Eßer  * @param n       The "digit" to print.
2393*44d4804dSStefan Eßer  * @param len     The "length" of the digit, or number of characters that will
2394*44d4804dSStefan Eßer  *                need to be printed for the digit.
2395*44d4804dSStefan Eßer  * @param rdx     True if a decimal (radix) point should be printed.
2396*44d4804dSStefan Eßer  * @param bslash  True if a backslash+newline should be printed if the character
2397*44d4804dSStefan Eßer  *                limit for the line is reached, false otherwise.
2398*44d4804dSStefan Eßer  */
2399*44d4804dSStefan 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);
2402*44d4804dSStefan 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 
2407*44d4804dSStefan Eßer #endif // !BC_ENABLE_LIBRARY
2408*44d4804dSStefan Eßer 
2409*44d4804dSStefan Eßer /**
2410*44d4804dSStefan Eßer  * Prints a series of characters for large bases. This is for printing in bases
2411*44d4804dSStefan Eßer  * above hexadecimal. This is a BcNumDigitOp.
2412*44d4804dSStefan Eßer  * @param n       The "digit" to print.
2413*44d4804dSStefan Eßer  * @param len     The "length" of the digit, or number of characters that will
2414*44d4804dSStefan Eßer  *                need to be printed for the digit.
2415*44d4804dSStefan Eßer  * @param rdx     True if a decimal (radix) point should be printed.
2416*44d4804dSStefan Eßer  * @param bslash  True if a backslash+newline should be printed if the character
2417*44d4804dSStefan Eßer  *                limit for the line is reached, false otherwise.
2418*44d4804dSStefan Eßer  */
2419*44d4804dSStefan 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 
2423*44d4804dSStefan Eßer 	// If needed, print the radix; otherwise, print a space to separate digits.
2424*44d4804dSStefan Eßer 	bc_num_putchar(rdx ? '.' : ' ', true);
2425252884aeSStefan Eßer 
2426*44d4804dSStefan 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 
2429*44d4804dSStefan Eßer 	// Print each character individually.
2430252884aeSStefan Eßer 	for (exp = 0; exp < len; pow /= BC_BASE, ++exp) {
2431*44d4804dSStefan Eßer 
2432*44d4804dSStefan Eßer 		// The individual subdigit.
2433252884aeSStefan Eßer 		size_t dig = n / pow;
2434*44d4804dSStefan Eßer 
2435*44d4804dSStefan Eßer 		// Take the subdigit away.
2436252884aeSStefan Eßer 		n -= dig * pow;
2437*44d4804dSStefan Eßer 
2438*44d4804dSStefan Eßer 		// Print the subdigit.
2439*44d4804dSStefan Eßer 		bc_num_putchar(((uchar) dig) + '0', bslash || exp != len - 1);
2440252884aeSStefan Eßer 	}
2441252884aeSStefan Eßer }
2442252884aeSStefan Eßer 
2443*44d4804dSStefan Eßer /**
2444*44d4804dSStefan Eßer  * Prints a character for a number's digit. This is for printing in bases for
2445*44d4804dSStefan Eßer  * hexadecimal and below because they always print only one character at a time.
2446*44d4804dSStefan Eßer  * This is a BcNumDigitOp.
2447*44d4804dSStefan Eßer  * @param n       The "digit" to print.
2448*44d4804dSStefan Eßer  * @param len     The "length" of the digit, or number of characters that will
2449*44d4804dSStefan Eßer  *                need to be printed for the digit.
2450*44d4804dSStefan Eßer  * @param rdx     True if a decimal (radix) point should be printed.
2451*44d4804dSStefan Eßer  * @param bslash  True if a backslash+newline should be printed if the character
2452*44d4804dSStefan Eßer  *                limit for the line is reached, false otherwise.
2453*44d4804dSStefan Eßer  */
2454*44d4804dSStefan 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);
2457*44d4804dSStefan Eßer 	BC_UNUSED(bslash);
2458252884aeSStefan Eßer 
2459252884aeSStefan Eßer 	assert(len == 1);
2460252884aeSStefan Eßer 
2461*44d4804dSStefan Eßer 	if (rdx) bc_num_putchar('.', true);
2462252884aeSStefan Eßer 
2463*44d4804dSStefan Eßer 	bc_num_putchar(bc_num_hex_digits[n], bslash);
2464252884aeSStefan Eßer }
2465252884aeSStefan Eßer 
2466*44d4804dSStefan Eßer /**
2467*44d4804dSStefan Eßer  * Prints a decimal number. This is specially written for optimization since
2468*44d4804dSStefan Eßer  * this will be used the most and because bc's numbers are already in decimal.
2469*44d4804dSStefan Eßer  * @param n        The number to print.
2470*44d4804dSStefan Eßer  * @param newline  Whether to print backslash+newlines on long enough lines.
2471*44d4804dSStefan Eßer  */
2472*44d4804dSStefan 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 
2478*44d4804dSStefan Eßer 	// Print the sign.
2479*44d4804dSStefan Eßer 	if (BC_NUM_NEG(n)) bc_num_putchar('-', true);
2480252884aeSStefan Eßer 
2481*44d4804dSStefan Eßer 	// Print loop.
2482252884aeSStefan Eßer 	for (i = n->len - 1; i < n->len; --i) {
2483252884aeSStefan Eßer 
2484252884aeSStefan Eßer 		BcDig n9 = n->num[i];
2485252884aeSStefan Eßer 		size_t temp;
2486252884aeSStefan Eßer 		bool irdx = (i == rdx - 1);
2487252884aeSStefan Eßer 
2488*44d4804dSStefan Eßer 		// Calculate the number of digits in the limb.
2489252884aeSStefan Eßer 		zero = (zero & !irdx);
2490252884aeSStefan Eßer 		temp = n->scale % BC_BASE_DIGS;
2491252884aeSStefan Eßer 		temp = i || !temp ? 0 : BC_BASE_DIGS - temp;
2492252884aeSStefan Eßer 
2493252884aeSStefan Eßer 		memset(buffer, 0, BC_BASE_DIGS * sizeof(size_t));
2494252884aeSStefan Eßer 
2495*44d4804dSStefan Eßer 		// Fill the buffer with individual digits.
2496252884aeSStefan Eßer 		for (j = 0; n9 && j < BC_BASE_DIGS; ++j) {
2497d213476dSStefan Eßer 			buffer[j] = ((size_t) n9) % BC_BASE;
2498252884aeSStefan Eßer 			n9 /= BC_BASE;
2499252884aeSStefan Eßer 		}
2500252884aeSStefan Eßer 
2501*44d4804dSStefan Eßer 		// Print the digits in the buffer.
2502252884aeSStefan Eßer 		for (j = BC_BASE_DIGS - 1; j < BC_BASE_DIGS && j >= temp; --j) {
2503*44d4804dSStefan Eßer 
2504*44d4804dSStefan Eßer 			// Figure out whether to print the decimal point.
2505252884aeSStefan Eßer 			bool print_rdx = (irdx & (j == BC_BASE_DIGS - 1));
2506*44d4804dSStefan Eßer 
2507*44d4804dSStefan Eßer 			// The zero variable helps us skip leading zero digits in the limb.
2508252884aeSStefan Eßer 			zero = (zero && buffer[j] == 0);
2509*44d4804dSStefan Eßer 
2510*44d4804dSStefan Eßer 			if (!zero) {
2511*44d4804dSStefan Eßer 
2512*44d4804dSStefan Eßer 				// While the first three arguments should be self-explanatory,
2513*44d4804dSStefan Eßer 				// the last needs explaining. I don't want to print a newline
2514*44d4804dSStefan Eßer 				// when the last digit to be printed could take the place of the
2515*44d4804dSStefan Eßer 				// backslash rather than being pushed, as a single character, to
2516*44d4804dSStefan Eßer 				// the next line. That's what that last argument does for bc.
2517*44d4804dSStefan Eßer 				bc_num_printHex(buffer[j], 1, print_rdx,
2518*44d4804dSStefan Eßer 				                !newline || (j > temp || i != 0));
2519*44d4804dSStefan Eßer 			}
2520252884aeSStefan Eßer 		}
2521252884aeSStefan Eßer 	}
2522252884aeSStefan Eßer }
2523252884aeSStefan Eßer 
2524252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
2525252884aeSStefan Eßer 
2526*44d4804dSStefan Eßer /**
2527*44d4804dSStefan Eßer  * Prints a number in scientific or engineering format. When doing this, we are
2528*44d4804dSStefan Eßer  * always printing in decimal.
2529*44d4804dSStefan Eßer  * @param n        The number to print.
2530*44d4804dSStefan Eßer  * @param eng      True if we are in engineering mode.
2531*44d4804dSStefan Eßer  * @param newline  Whether to print backslash+newlines on long enough lines.
2532*44d4804dSStefan Eßer  */
2533*44d4804dSStefan Eßer static void bc_num_printExponent(const BcNum *restrict n,
2534*44d4804dSStefan Eßer                                  bool eng, bool newline)
2535*44d4804dSStefan Eßer {
253650696a6eSStefan Eßer 	size_t places, mod, nrdx = BC_NUM_RDX_VAL(n);
253750696a6eSStefan Eßer 	bool neg = (n->len <= nrdx);
2538252884aeSStefan Eßer 	BcNum temp, exp;
2539252884aeSStefan Eßer 	BcDig digs[BC_NUM_BIGDIG_LOG10];
2540252884aeSStefan Eßer 
2541252884aeSStefan Eßer 	BC_SIG_LOCK;
2542252884aeSStefan Eßer 
2543252884aeSStefan Eßer 	bc_num_createCopy(&temp, n);
2544252884aeSStefan Eßer 
2545252884aeSStefan Eßer 	BC_SETJMP_LOCKED(exit);
2546252884aeSStefan Eßer 
2547252884aeSStefan Eßer 	BC_SIG_UNLOCK;
2548252884aeSStefan Eßer 
2549*44d4804dSStefan Eßer 	// We need to calculate the exponents, and they change based on whether the
2550*44d4804dSStefan Eßer 	// number is all fractional or not, obviously.
2551252884aeSStefan Eßer 	if (neg) {
2552252884aeSStefan Eßer 
2553*44d4804dSStefan Eßer 		// Figure out how many limbs after the decimal point is zero.
2554*44d4804dSStefan Eßer 		size_t i, idx = bc_num_nonZeroLen(n) - 1;
2555252884aeSStefan Eßer 
2556252884aeSStefan Eßer 		places = 1;
2557252884aeSStefan Eßer 
2558*44d4804dSStefan Eßer 		// Figure out how much in the last limb is zero.
2559252884aeSStefan Eßer 		for (i = BC_BASE_DIGS - 1; i < BC_BASE_DIGS; --i) {
2560252884aeSStefan Eßer 			if (bc_num_pow10[i] > (BcBigDig) n->num[idx]) places += 1;
2561252884aeSStefan Eßer 			else break;
2562252884aeSStefan Eßer 		}
2563252884aeSStefan Eßer 
2564*44d4804dSStefan Eßer 		// Calculate the combination of zero limbs and zero digits in the last
2565*44d4804dSStefan Eßer 		// limb.
256650696a6eSStefan Eßer 		places += (nrdx - (idx + 1)) * BC_BASE_DIGS;
2567252884aeSStefan Eßer 		mod = places % 3;
2568252884aeSStefan Eßer 
2569*44d4804dSStefan Eßer 		// Calculate places if we are in engineering mode.
2570252884aeSStefan Eßer 		if (eng && mod != 0) places += 3 - mod;
2571*44d4804dSStefan Eßer 
2572*44d4804dSStefan Eßer 		// Shift the temp to the right place.
2573252884aeSStefan Eßer 		bc_num_shiftLeft(&temp, places);
2574252884aeSStefan Eßer 	}
2575252884aeSStefan Eßer 	else {
2576*44d4804dSStefan Eßer 
2577*44d4804dSStefan Eßer 		// This is the number of digits that we are supposed to put behind the
2578*44d4804dSStefan Eßer 		// decimal point.
2579252884aeSStefan Eßer 		places = bc_num_intDigits(n) - 1;
2580*44d4804dSStefan Eßer 
2581*44d4804dSStefan Eßer 		// Calculate the true number based on whether engineering mode is
2582*44d4804dSStefan Eßer 		// activated.
2583252884aeSStefan Eßer 		mod = places % 3;
2584252884aeSStefan Eßer 		if (eng && mod != 0) places -= 3 - (3 - mod);
2585*44d4804dSStefan Eßer 
2586*44d4804dSStefan Eßer 		// Shift the temp to the right place.
2587252884aeSStefan Eßer 		bc_num_shiftRight(&temp, places);
2588252884aeSStefan Eßer 	}
2589252884aeSStefan Eßer 
2590*44d4804dSStefan Eßer 	// Print the shifted number.
2591*44d4804dSStefan Eßer 	bc_num_printDecimal(&temp, newline);
2592252884aeSStefan Eßer 
2593*44d4804dSStefan Eßer 	// Print the e.
2594*44d4804dSStefan Eßer 	bc_num_putchar('e', !newline);
2595*44d4804dSStefan Eßer 
2596*44d4804dSStefan Eßer 	// Need to explicitly print a zero exponent.
2597252884aeSStefan Eßer 	if (!places) {
2598*44d4804dSStefan Eßer 		bc_num_printHex(0, 1, false, !newline);
2599252884aeSStefan Eßer 		goto exit;
2600252884aeSStefan Eßer 	}
2601252884aeSStefan Eßer 
2602*44d4804dSStefan Eßer 	// Need to print sign for the exponent.
2603*44d4804dSStefan Eßer 	if (neg) bc_num_putchar('-', true);
2604252884aeSStefan Eßer 
2605*44d4804dSStefan Eßer 	// Create a temporary for the exponent...
2606252884aeSStefan Eßer 	bc_num_setup(&exp, digs, BC_NUM_BIGDIG_LOG10);
2607252884aeSStefan Eßer 	bc_num_bigdig2num(&exp, (BcBigDig) places);
2608252884aeSStefan Eßer 
2609*44d4804dSStefan Eßer 	/// ..and print it.
2610*44d4804dSStefan Eßer 	bc_num_printDecimal(&exp, newline);
2611252884aeSStefan Eßer 
2612252884aeSStefan Eßer exit:
2613252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
2614252884aeSStefan Eßer 	bc_num_free(&temp);
2615252884aeSStefan Eßer 	BC_LONGJMP_CONT;
2616252884aeSStefan Eßer }
2617252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
2618252884aeSStefan Eßer 
2619*44d4804dSStefan Eßer /**
2620*44d4804dSStefan Eßer  * Converts a number from limbs with base BC_BASE_POW to base @a pow, where
2621*44d4804dSStefan Eßer  * @a pow is obase^N.
2622*44d4804dSStefan Eßer  * @param n    The number to convert.
2623*44d4804dSStefan Eßer  * @param rem  BC_BASE_POW - @a pow.
2624*44d4804dSStefan Eßer  * @param pow  The power of obase we will convert the number to.
2625*44d4804dSStefan Eßer  * @param idx  The index of the number to start converting at. Doing the
2626*44d4804dSStefan Eßer  *             conversion is O(n^2); we have to sweep through starting at the
2627*44d4804dSStefan Eßer  *             least significant limb
2628*44d4804dSStefan Eßer  */
2629252884aeSStefan Eßer static void bc_num_printFixup(BcNum *restrict n, BcBigDig rem,
2630252884aeSStefan Eßer                               BcBigDig pow, size_t idx)
2631252884aeSStefan Eßer {
2632252884aeSStefan Eßer 	size_t i, len = n->len - idx;
2633252884aeSStefan Eßer 	BcBigDig acc;
2634252884aeSStefan Eßer 	BcDig *a = n->num + idx;
2635252884aeSStefan Eßer 
2636*44d4804dSStefan Eßer 	// Ignore if there's just one limb left. This is the part that requires the
2637*44d4804dSStefan Eßer 	// extra loop after the one calling this function in bc_num_printPrepare().
2638252884aeSStefan Eßer 	if (len < 2) return;
2639252884aeSStefan Eßer 
2640*44d4804dSStefan Eßer 	// Loop through the remaining limbs and convert. We start at the second limb
2641*44d4804dSStefan Eßer 	// because we pull the value from the previous one as well.
2642252884aeSStefan Eßer 	for (i = len - 1; i > 0; --i) {
2643252884aeSStefan Eßer 
2644*44d4804dSStefan Eßer 		// Get the limb and add it to the previous, along with multiplying by
2645*44d4804dSStefan Eßer 		// the remainder because that's the proper overflow. "acc" means
2646*44d4804dSStefan Eßer 		// "accumulator," by the way.
2647252884aeSStefan Eßer 		acc = ((BcBigDig) a[i]) * rem + ((BcBigDig) a[i - 1]);
2648*44d4804dSStefan Eßer 
2649*44d4804dSStefan Eßer 		// Store a value in base pow in the previous limb.
2650252884aeSStefan Eßer 		a[i - 1] = (BcDig) (acc % pow);
2651*44d4804dSStefan Eßer 
2652*44d4804dSStefan Eßer 		// Divide by the base and accumulate the remaining value in the limb.
2653252884aeSStefan Eßer 		acc /= pow;
2654252884aeSStefan Eßer 		acc += (BcBigDig) a[i];
2655252884aeSStefan Eßer 
2656*44d4804dSStefan Eßer 		// If the accumulator is greater than the base...
2657252884aeSStefan Eßer 		if (acc >= BC_BASE_POW) {
2658252884aeSStefan Eßer 
2659*44d4804dSStefan Eßer 			// Do we need to grow?
2660252884aeSStefan Eßer 			if (i == len - 1) {
2661*44d4804dSStefan Eßer 
2662*44d4804dSStefan Eßer 				// Grow.
2663252884aeSStefan Eßer 				len = bc_vm_growSize(len, 1);
2664252884aeSStefan Eßer 				bc_num_expand(n, bc_vm_growSize(len, idx));
2665*44d4804dSStefan Eßer 
2666*44d4804dSStefan Eßer 				// Update the pointer because it may have moved.
2667252884aeSStefan Eßer 				a = n->num + idx;
2668*44d4804dSStefan Eßer 
2669*44d4804dSStefan Eßer 				// Zero out the last limb.
2670252884aeSStefan Eßer 				a[len - 1] = 0;
2671252884aeSStefan Eßer 			}
2672252884aeSStefan Eßer 
2673*44d4804dSStefan Eßer 			// Overflow into the next limb since we are over the base.
2674252884aeSStefan Eßer 			a[i + 1] += acc / BC_BASE_POW;
2675252884aeSStefan Eßer 			acc %= BC_BASE_POW;
2676252884aeSStefan Eßer 		}
2677252884aeSStefan Eßer 
2678252884aeSStefan Eßer 		assert(acc < BC_BASE_POW);
2679*44d4804dSStefan Eßer 
2680*44d4804dSStefan Eßer 		// Set the limb.
2681252884aeSStefan Eßer 		a[i] = (BcDig) acc;
2682252884aeSStefan Eßer 	}
2683252884aeSStefan Eßer 
2684*44d4804dSStefan Eßer 	// We may have grown the number, so adjust the length.
2685252884aeSStefan Eßer 	n->len = len + idx;
2686252884aeSStefan Eßer }
2687252884aeSStefan Eßer 
2688*44d4804dSStefan Eßer /**
2689*44d4804dSStefan Eßer  * Prepares a number for printing in a base that is not a divisor of
2690*44d4804dSStefan Eßer  * BC_BASE_POW. This basically converts the number from having limbs of base
2691*44d4804dSStefan Eßer  * BC_BASE_POW to limbs of pow, where pow is obase^N.
2692*44d4804dSStefan Eßer  * @param n    The number to prepare for printing.
2693*44d4804dSStefan Eßer  * @param rem  The remainder of BC_BASE_POW when divided by a power of the base.
2694*44d4804dSStefan Eßer  * @param pow  The power of the base.
2695*44d4804dSStefan Eßer  */
2696*44d4804dSStefan Eßer static void bc_num_printPrepare(BcNum *restrict n, BcBigDig rem, BcBigDig pow) {
2697*44d4804dSStefan Eßer 
2698252884aeSStefan Eßer 	size_t i;
2699252884aeSStefan Eßer 
2700*44d4804dSStefan Eßer 	// Loop from the least significant limb to the most significant limb and
2701*44d4804dSStefan Eßer 	// convert limbs in each pass.
2702252884aeSStefan Eßer 	for (i = 0; i < n->len; ++i) bc_num_printFixup(n, rem, pow, i);
2703252884aeSStefan Eßer 
2704*44d4804dSStefan Eßer 	// bc_num_printFixup() does not do everything it is supposed to, so we do
2705*44d4804dSStefan Eßer 	// the last bit of cleanup here. That cleanup is to ensure that each limb
2706*44d4804dSStefan Eßer 	// is less than pow and to expand the number to fit new limbs as necessary.
2707252884aeSStefan Eßer 	for (i = 0; i < n->len; ++i) {
2708252884aeSStefan Eßer 
2709252884aeSStefan Eßer 		assert(pow == ((BcBigDig) ((BcDig) pow)));
2710252884aeSStefan Eßer 
2711*44d4804dSStefan Eßer 		// If the limb needs fixing...
2712252884aeSStefan Eßer 		if (n->num[i] >= (BcDig) pow) {
2713252884aeSStefan Eßer 
2714*44d4804dSStefan Eßer 			// Do we need to grow?
2715252884aeSStefan Eßer 			if (i + 1 == n->len) {
2716*44d4804dSStefan Eßer 
2717*44d4804dSStefan Eßer 				// Grow the number.
2718252884aeSStefan Eßer 				n->len = bc_vm_growSize(n->len, 1);
2719252884aeSStefan Eßer 				bc_num_expand(n, n->len);
2720*44d4804dSStefan Eßer 
2721*44d4804dSStefan Eßer 				// Without this, we might use uninitialized data.
2722252884aeSStefan Eßer 				n->num[i + 1] = 0;
2723252884aeSStefan Eßer 			}
2724252884aeSStefan Eßer 
2725252884aeSStefan Eßer 			assert(pow < BC_BASE_POW);
2726*44d4804dSStefan Eßer 
2727*44d4804dSStefan Eßer 			// Overflow into the next limb.
2728252884aeSStefan Eßer 			n->num[i + 1] += n->num[i] / ((BcDig) pow);
2729252884aeSStefan Eßer 			n->num[i] %= (BcDig) pow;
2730252884aeSStefan Eßer 		}
2731252884aeSStefan Eßer 	}
2732252884aeSStefan Eßer }
2733252884aeSStefan Eßer 
2734*44d4804dSStefan Eßer static void bc_num_printNum(BcNum *restrict n, BcBigDig base, size_t len,
2735*44d4804dSStefan Eßer                             BcNumDigitOp print, bool newline)
2736252884aeSStefan Eßer {
2737252884aeSStefan Eßer 	BcVec stack;
2738252884aeSStefan Eßer 	BcNum intp, fracp1, fracp2, digit, flen1, flen2, *n1, *n2, *temp;
2739252884aeSStefan Eßer 	BcBigDig dig = 0, *ptr, acc, exp;
2740*44d4804dSStefan Eßer 	size_t i, j, nrdx, idigits;
2741252884aeSStefan Eßer 	bool radix;
2742252884aeSStefan Eßer 	BcDig digit_digs[BC_NUM_BIGDIG_LOG10 + 1];
2743252884aeSStefan Eßer 
2744252884aeSStefan Eßer 	assert(base > 1);
2745252884aeSStefan Eßer 
2746*44d4804dSStefan Eßer 	// Easy case. Even with scale, we just print this.
2747252884aeSStefan Eßer 	if (BC_NUM_ZERO(n)) {
2748*44d4804dSStefan Eßer 		print(0, len, false, !newline);
2749252884aeSStefan Eßer 		return;
2750252884aeSStefan Eßer 	}
2751252884aeSStefan Eßer 
2752252884aeSStefan Eßer 	// This function uses an algorithm that Stefan Esser <se@freebsd.org> came
2753252884aeSStefan Eßer 	// up with to print the integer part of a number. What it does is convert
2754252884aeSStefan Eßer 	// intp into a number of the specified base, but it does it directly,
2755252884aeSStefan Eßer 	// instead of just doing a series of divisions and printing the remainders
2756252884aeSStefan Eßer 	// in reverse order.
2757252884aeSStefan Eßer 	//
2758252884aeSStefan Eßer 	// Let me explain in a bit more detail:
2759252884aeSStefan Eßer 	//
2760*44d4804dSStefan Eßer 	// The algorithm takes the current least significant limb (after intp has
2761*44d4804dSStefan Eßer 	// been converted to an integer) and the next to least significant limb, and
2762*44d4804dSStefan Eßer 	// it converts the least significant limb into one of the specified base,
2763*44d4804dSStefan Eßer 	// putting any overflow into the next to least significant limb. It iterates
2764*44d4804dSStefan Eßer 	// through the whole number, from least significant to most significant,
2765*44d4804dSStefan Eßer 	// doing this conversion. At the end of that iteration, the least
2766*44d4804dSStefan Eßer 	// significant limb is converted, but the others are not, so it iterates
2767*44d4804dSStefan Eßer 	// again, starting at the next to least significant limb. It keeps doing
2768*44d4804dSStefan Eßer 	// that conversion, skipping one more limb than the last time, until all
2769*44d4804dSStefan Eßer 	// limbs have been converted. Then it prints them in reverse order.
2770252884aeSStefan Eßer 	//
2771252884aeSStefan Eßer 	// That is the gist of the algorithm. It leaves out several things, such as
2772*44d4804dSStefan Eßer 	// the fact that limbs are not always converted into the specified base, but
2773*44d4804dSStefan Eßer 	// into something close, basically a power of the specified base. In
2774252884aeSStefan Eßer 	// Stefan's words, "You could consider BcDigs to be of base 10^BC_BASE_DIGS
2775252884aeSStefan Eßer 	// in the normal case and obase^N for the largest value of N that satisfies
2776252884aeSStefan Eßer 	// obase^N <= 10^BC_BASE_DIGS. [This means that] the result is not in base
2777252884aeSStefan Eßer 	// "obase", but in base "obase^N", which happens to be printable as a number
2778252884aeSStefan Eßer 	// of base "obase" without consideration for neighbouring BcDigs." This fact
2779252884aeSStefan Eßer 	// is what necessitates the existence of the loop later in this function.
2780252884aeSStefan Eßer 	//
2781252884aeSStefan Eßer 	// The conversion happens in bc_num_printPrepare() where the outer loop
2782252884aeSStefan Eßer 	// happens and bc_num_printFixup() where the inner loop, or actual
2783*44d4804dSStefan Eßer 	// conversion, happens. In other words, bc_num_printPrepare() is where the
2784*44d4804dSStefan Eßer 	// loop that starts at the least significant limb and goes to the most
2785*44d4804dSStefan Eßer 	// significant limb. Then, on every iteration of its loop, it calls
2786*44d4804dSStefan Eßer 	// bc_num_printFixup(), which has the inner loop of actually converting
2787*44d4804dSStefan Eßer 	// the limbs it passes into limbs of base obase^N rather than base
2788*44d4804dSStefan Eßer 	// BC_BASE_POW.
2789252884aeSStefan Eßer 
279050696a6eSStefan Eßer 	nrdx = BC_NUM_RDX_VAL(n);
279150696a6eSStefan Eßer 
2792252884aeSStefan Eßer 	BC_SIG_LOCK;
2793252884aeSStefan Eßer 
2794*44d4804dSStefan Eßer 	// The stack is what allows us to reverse the digits for printing.
2795*44d4804dSStefan Eßer 	bc_vec_init(&stack, sizeof(BcBigDig), BC_DTOR_NONE);
279650696a6eSStefan Eßer 	bc_num_init(&fracp1, nrdx);
2797252884aeSStefan Eßer 
2798*44d4804dSStefan Eßer 	// intp will be the "integer part" of the number, so copy it.
2799252884aeSStefan Eßer 	bc_num_createCopy(&intp, n);
2800252884aeSStefan Eßer 
2801252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
2802252884aeSStefan Eßer 
2803252884aeSStefan Eßer 	BC_SIG_UNLOCK;
2804252884aeSStefan Eßer 
2805*44d4804dSStefan Eßer 	// Make intp an integer.
2806252884aeSStefan Eßer 	bc_num_truncate(&intp, intp.scale);
2807252884aeSStefan Eßer 
2808*44d4804dSStefan Eßer 	// Get the fractional part out.
2809252884aeSStefan Eßer 	bc_num_sub(n, &intp, &fracp1, 0);
2810252884aeSStefan Eßer 
2811*44d4804dSStefan Eßer 	// If the base is not the same as the last base used for printing, we need
2812*44d4804dSStefan Eßer 	// to update the cached exponent and power. Yes, we cache the values of the
2813*44d4804dSStefan Eßer 	// exponent and power. That is to prevent us from calculating them every
2814*44d4804dSStefan Eßer 	// time because printing will probably happen multiple times on the same
2815*44d4804dSStefan Eßer 	// base.
2816252884aeSStefan Eßer 	if (base != vm.last_base) {
2817252884aeSStefan Eßer 
2818252884aeSStefan Eßer 		vm.last_pow = 1;
2819252884aeSStefan Eßer 		vm.last_exp = 0;
2820252884aeSStefan Eßer 
2821*44d4804dSStefan Eßer 		// Calculate the exponent and power.
2822252884aeSStefan Eßer 		while (vm.last_pow * base <= BC_BASE_POW) {
2823252884aeSStefan Eßer 			vm.last_pow *= base;
2824252884aeSStefan Eßer 			vm.last_exp += 1;
2825252884aeSStefan Eßer 		}
2826252884aeSStefan Eßer 
2827*44d4804dSStefan Eßer 		// Also, the remainder and base itself.
2828252884aeSStefan Eßer 		vm.last_rem = BC_BASE_POW - vm.last_pow;
2829252884aeSStefan Eßer 		vm.last_base = base;
2830252884aeSStefan Eßer 	}
2831252884aeSStefan Eßer 
2832252884aeSStefan Eßer 	exp = vm.last_exp;
2833252884aeSStefan Eßer 
2834*44d4804dSStefan Eßer 	// If vm.last_rem is 0, then the base we are printing in is a divisor of
2835*44d4804dSStefan Eßer 	// BC_BASE_POW, which is the easy case because it means that BC_BASE_POW is
2836*44d4804dSStefan Eßer 	// a power of obase, and no conversion is needed. If it *is* 0, then we have
2837*44d4804dSStefan Eßer 	// the hard case, and we have to prepare the number for the base.
2838252884aeSStefan Eßer 	if (vm.last_rem != 0) bc_num_printPrepare(&intp, vm.last_rem, vm.last_pow);
2839252884aeSStefan Eßer 
2840*44d4804dSStefan Eßer 	// After the conversion comes the surprisingly easy part. From here on out,
2841*44d4804dSStefan Eßer 	// this is basically naive code that I wrote, adjusted for the larger bases.
2842*44d4804dSStefan Eßer 
2843*44d4804dSStefan Eßer 	// Fill the stack of digits for the integer part.
2844252884aeSStefan Eßer 	for (i = 0; i < intp.len; ++i) {
2845252884aeSStefan Eßer 
2846*44d4804dSStefan Eßer 		// Get the limb.
2847252884aeSStefan Eßer 		acc = (BcBigDig) intp.num[i];
2848252884aeSStefan Eßer 
2849*44d4804dSStefan Eßer 		// Turn the limb into digits of base obase.
2850252884aeSStefan Eßer 		for (j = 0; j < exp && (i < intp.len - 1 || acc != 0); ++j)
2851252884aeSStefan Eßer 		{
2852*44d4804dSStefan Eßer 			// This condition is true if we are not at the last digit.
2853252884aeSStefan Eßer 			if (j != exp - 1) {
2854252884aeSStefan Eßer 				dig = acc % base;
2855252884aeSStefan Eßer 				acc /= base;
2856252884aeSStefan Eßer 			}
2857252884aeSStefan Eßer 			else {
2858252884aeSStefan Eßer 				dig = acc;
2859252884aeSStefan Eßer 				acc = 0;
2860252884aeSStefan Eßer 			}
2861252884aeSStefan Eßer 
2862252884aeSStefan Eßer 			assert(dig < base);
2863252884aeSStefan Eßer 
2864*44d4804dSStefan Eßer 			// Push the digit onto the stack.
2865252884aeSStefan Eßer 			bc_vec_push(&stack, &dig);
2866252884aeSStefan Eßer 		}
2867252884aeSStefan Eßer 
2868252884aeSStefan Eßer 		assert(acc == 0);
2869252884aeSStefan Eßer 	}
2870252884aeSStefan Eßer 
2871*44d4804dSStefan Eßer 	// Go through the stack backwards and print each digit.
2872252884aeSStefan Eßer 	for (i = 0; i < stack.len; ++i) {
2873*44d4804dSStefan Eßer 
2874252884aeSStefan Eßer 		ptr = bc_vec_item_rev(&stack, i);
2875*44d4804dSStefan Eßer 
2876252884aeSStefan Eßer 		assert(ptr != NULL);
2877*44d4804dSStefan Eßer 
2878*44d4804dSStefan Eßer 		// While the first three arguments should be self-explanatory, the last
2879*44d4804dSStefan Eßer 		// needs explaining. I don't want to print a newline when the last digit
2880*44d4804dSStefan Eßer 		// to be printed could take the place of the backslash rather than being
2881*44d4804dSStefan Eßer 		// pushed, as a single character, to the next line. That's what that
2882*44d4804dSStefan Eßer 		// last argument does for bc.
2883*44d4804dSStefan Eßer 		print(*ptr, len, false, !newline ||
2884*44d4804dSStefan Eßer 		      (n->scale != 0 || i == stack.len - 1));
2885252884aeSStefan Eßer 	}
2886252884aeSStefan Eßer 
2887*44d4804dSStefan Eßer 	// We are done if there is no fractional part.
2888252884aeSStefan Eßer 	if (!n->scale) goto err;
2889252884aeSStefan Eßer 
2890252884aeSStefan Eßer 	BC_SIG_LOCK;
2891252884aeSStefan Eßer 
2892*44d4804dSStefan Eßer 	// Reset the jump because some locals are changing.
2893252884aeSStefan Eßer 	BC_UNSETJMP;
2894252884aeSStefan Eßer 
289550696a6eSStefan Eßer 	bc_num_init(&fracp2, nrdx);
2896252884aeSStefan Eßer 	bc_num_setup(&digit, digit_digs, sizeof(digit_digs) / sizeof(BcDig));
2897252884aeSStefan Eßer 	bc_num_init(&flen1, BC_NUM_BIGDIG_LOG10);
2898252884aeSStefan Eßer 	bc_num_init(&flen2, BC_NUM_BIGDIG_LOG10);
2899252884aeSStefan Eßer 
2900252884aeSStefan Eßer 	BC_SETJMP_LOCKED(frac_err);
2901252884aeSStefan Eßer 
2902252884aeSStefan Eßer 	BC_SIG_UNLOCK;
2903252884aeSStefan Eßer 
2904252884aeSStefan Eßer 	bc_num_one(&flen1);
2905252884aeSStefan Eßer 
2906252884aeSStefan Eßer 	radix = true;
2907*44d4804dSStefan Eßer 
2908*44d4804dSStefan Eßer 	// Pointers for easy switching.
2909252884aeSStefan Eßer 	n1 = &flen1;
2910252884aeSStefan Eßer 	n2 = &flen2;
2911252884aeSStefan Eßer 
2912252884aeSStefan Eßer 	fracp2.scale = n->scale;
291350696a6eSStefan Eßer 	BC_NUM_RDX_SET_NP(fracp2, BC_NUM_RDX(fracp2.scale));
2914252884aeSStefan Eßer 
2915*44d4804dSStefan Eßer 	// As long as we have not reached the scale of the number, keep printing.
2916*44d4804dSStefan Eßer 	while ((idigits = bc_num_intDigits(n1)) <= n->scale) {
2917252884aeSStefan Eßer 
2918*44d4804dSStefan Eßer 		// These numbers will keep growing.
2919252884aeSStefan Eßer 		bc_num_expand(&fracp2, fracp1.len + 1);
2920252884aeSStefan Eßer 		bc_num_mulArray(&fracp1, base, &fracp2);
292150696a6eSStefan Eßer 
292250696a6eSStefan Eßer 		nrdx = BC_NUM_RDX_VAL_NP(fracp2);
292350696a6eSStefan Eßer 
2924*44d4804dSStefan Eßer 		// Ensure an invariant.
292550696a6eSStefan Eßer 		if (fracp2.len < nrdx) fracp2.len = nrdx;
2926252884aeSStefan Eßer 
2927252884aeSStefan Eßer 		// fracp is guaranteed to be non-negative and small enough.
2928*44d4804dSStefan Eßer 		dig = bc_num_bigdig2(&fracp2);
2929252884aeSStefan Eßer 
2930*44d4804dSStefan Eßer 		// Convert the digit to a number and subtract it from the number.
2931252884aeSStefan Eßer 		bc_num_bigdig2num(&digit, dig);
2932252884aeSStefan Eßer 		bc_num_sub(&fracp2, &digit, &fracp1, 0);
2933252884aeSStefan Eßer 
2934*44d4804dSStefan Eßer 		// While the first three arguments should be self-explanatory, the last
2935*44d4804dSStefan Eßer 		// needs explaining. I don't want to print a newline when the last digit
2936*44d4804dSStefan Eßer 		// to be printed could take the place of the backslash rather than being
2937*44d4804dSStefan Eßer 		// pushed, as a single character, to the next line. That's what that
2938*44d4804dSStefan Eßer 		// last argument does for bc.
2939*44d4804dSStefan Eßer 		print(dig, len, radix, !newline || idigits != n->scale);
2940*44d4804dSStefan Eßer 
2941*44d4804dSStefan Eßer 		// Update the multipliers.
2942252884aeSStefan Eßer 		bc_num_mulArray(n1, base, n2);
2943252884aeSStefan Eßer 
2944252884aeSStefan Eßer 		radix = false;
2945*44d4804dSStefan Eßer 
2946*44d4804dSStefan Eßer 		// Switch.
2947252884aeSStefan Eßer 		temp = n1;
2948252884aeSStefan Eßer 		n1 = n2;
2949252884aeSStefan Eßer 		n2 = temp;
2950252884aeSStefan Eßer 	}
2951252884aeSStefan Eßer 
2952252884aeSStefan Eßer frac_err:
2953252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
2954252884aeSStefan Eßer 	bc_num_free(&flen2);
2955252884aeSStefan Eßer 	bc_num_free(&flen1);
2956252884aeSStefan Eßer 	bc_num_free(&fracp2);
2957252884aeSStefan Eßer err:
2958252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
2959252884aeSStefan Eßer 	bc_num_free(&fracp1);
2960252884aeSStefan Eßer 	bc_num_free(&intp);
2961252884aeSStefan Eßer 	bc_vec_free(&stack);
2962252884aeSStefan Eßer 	BC_LONGJMP_CONT;
2963252884aeSStefan Eßer }
2964252884aeSStefan Eßer 
2965*44d4804dSStefan Eßer /**
2966*44d4804dSStefan Eßer  * Prints a number in the specified base, or rather, figures out which function
2967*44d4804dSStefan Eßer  * to call to print the number in the specified base and calls it.
2968*44d4804dSStefan Eßer  * @param n        The number to print.
2969*44d4804dSStefan Eßer  * @param base     The base to print in.
2970*44d4804dSStefan Eßer  * @param newline  Whether to print backslash+newlines on long enough lines.
2971*44d4804dSStefan Eßer  */
2972*44d4804dSStefan Eßer static void bc_num_printBase(BcNum *restrict n, BcBigDig base, bool newline) {
2973252884aeSStefan Eßer 
2974252884aeSStefan Eßer 	size_t width;
2975252884aeSStefan Eßer 	BcNumDigitOp print;
297650696a6eSStefan Eßer 	bool neg = BC_NUM_NEG(n);
2977252884aeSStefan Eßer 
2978*44d4804dSStefan Eßer 	// Just take care of the sign right here.
2979*44d4804dSStefan Eßer 	if (neg) bc_num_putchar('-', true);
2980252884aeSStefan Eßer 
2981*44d4804dSStefan Eßer 	// Clear the sign because it makes the actual printing easier when we have
2982*44d4804dSStefan Eßer 	// to do math.
298350696a6eSStefan Eßer 	BC_NUM_NEG_CLR(n);
2984252884aeSStefan Eßer 
2985*44d4804dSStefan Eßer 	// Bases at hexadecimal and below are printed as one character, larger bases
2986*44d4804dSStefan Eßer 	// are printed as a series of digits separated by spaces.
2987252884aeSStefan Eßer 	if (base <= BC_NUM_MAX_POSIX_IBASE) {
2988252884aeSStefan Eßer 		width = 1;
2989252884aeSStefan Eßer 		print = bc_num_printHex;
2990252884aeSStefan Eßer 	}
2991252884aeSStefan Eßer 	else {
2992252884aeSStefan Eßer 		assert(base <= BC_BASE_POW);
2993252884aeSStefan Eßer 		width = bc_num_log10(base - 1);
2994252884aeSStefan Eßer 		print = bc_num_printDigits;
2995252884aeSStefan Eßer 	}
2996252884aeSStefan Eßer 
2997*44d4804dSStefan Eßer 	// Print.
2998*44d4804dSStefan Eßer 	bc_num_printNum(n, base, width, print, newline);
2999*44d4804dSStefan Eßer 
3000*44d4804dSStefan Eßer 	// Reset the sign.
300150696a6eSStefan Eßer 	n->rdx = BC_NUM_NEG_VAL(n, neg);
3002252884aeSStefan Eßer }
3003252884aeSStefan Eßer 
3004*44d4804dSStefan Eßer #if !BC_ENABLE_LIBRARY
3005*44d4804dSStefan Eßer 
3006*44d4804dSStefan Eßer void bc_num_stream(BcNum *restrict n) {
3007*44d4804dSStefan Eßer 	bc_num_printNum(n, BC_NUM_STREAM_BASE, 1, bc_num_printChar, false);
3008252884aeSStefan Eßer }
3009*44d4804dSStefan Eßer 
3010*44d4804dSStefan Eßer #endif // !BC_ENABLE_LIBRARY
3011252884aeSStefan Eßer 
3012252884aeSStefan Eßer void bc_num_setup(BcNum *restrict n, BcDig *restrict num, size_t cap) {
3013252884aeSStefan Eßer 	assert(n != NULL);
3014252884aeSStefan Eßer 	n->num = num;
3015252884aeSStefan Eßer 	n->cap = cap;
3016252884aeSStefan Eßer 	bc_num_zero(n);
3017252884aeSStefan Eßer }
3018252884aeSStefan Eßer 
3019252884aeSStefan Eßer void bc_num_init(BcNum *restrict n, size_t req) {
3020252884aeSStefan Eßer 
3021252884aeSStefan Eßer 	BcDig *num;
3022252884aeSStefan Eßer 
3023252884aeSStefan Eßer 	BC_SIG_ASSERT_LOCKED;
3024252884aeSStefan Eßer 
3025252884aeSStefan Eßer 	assert(n != NULL);
3026252884aeSStefan Eßer 
3027*44d4804dSStefan Eßer 	// BC_NUM_DEF_SIZE is set to be about the smallest allocation size that
3028*44d4804dSStefan Eßer 	// malloc() returns in practice, so just use it.
3029252884aeSStefan Eßer 	req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
3030252884aeSStefan Eßer 
3031*44d4804dSStefan Eßer 	// If we can't use a temp, allocate.
3032*44d4804dSStefan Eßer 	if (req != BC_NUM_DEF_SIZE || (num = bc_vm_takeTemp()) == NULL)
3033*44d4804dSStefan Eßer 		num = bc_vm_malloc(BC_NUM_SIZE(req));
3034252884aeSStefan Eßer 
3035252884aeSStefan Eßer 	bc_num_setup(n, num, req);
3036252884aeSStefan Eßer }
3037252884aeSStefan Eßer 
3038252884aeSStefan Eßer void bc_num_clear(BcNum *restrict n) {
3039252884aeSStefan Eßer 	n->num = NULL;
3040252884aeSStefan Eßer 	n->cap = 0;
3041252884aeSStefan Eßer }
3042252884aeSStefan Eßer 
3043252884aeSStefan Eßer void bc_num_free(void *num) {
3044252884aeSStefan Eßer 
3045252884aeSStefan Eßer 	BcNum *n = (BcNum*) num;
3046252884aeSStefan Eßer 
3047252884aeSStefan Eßer 	BC_SIG_ASSERT_LOCKED;
3048252884aeSStefan Eßer 
3049252884aeSStefan Eßer 	assert(n != NULL);
3050252884aeSStefan Eßer 
3051*44d4804dSStefan Eßer 	if (n->cap == BC_NUM_DEF_SIZE) bc_vm_addTemp(n->num);
3052252884aeSStefan Eßer 	else free(n->num);
3053252884aeSStefan Eßer }
3054252884aeSStefan Eßer 
3055252884aeSStefan Eßer void bc_num_copy(BcNum *d, const BcNum *s) {
3056*44d4804dSStefan Eßer 
3057252884aeSStefan Eßer 	assert(d != NULL && s != NULL);
3058*44d4804dSStefan Eßer 
3059252884aeSStefan Eßer 	if (d == s) return;
3060*44d4804dSStefan Eßer 
3061252884aeSStefan Eßer 	bc_num_expand(d, s->len);
3062252884aeSStefan Eßer 	d->len = s->len;
3063*44d4804dSStefan Eßer 
3064*44d4804dSStefan Eßer 	// I can just copy directly here because the sign *and* rdx will be
3065*44d4804dSStefan Eßer 	// properly preserved.
3066252884aeSStefan Eßer 	d->rdx = s->rdx;
3067252884aeSStefan Eßer 	d->scale = s->scale;
3068252884aeSStefan Eßer 	memcpy(d->num, s->num, BC_NUM_SIZE(d->len));
3069252884aeSStefan Eßer }
3070252884aeSStefan Eßer 
3071252884aeSStefan Eßer void bc_num_createCopy(BcNum *d, const BcNum *s) {
3072252884aeSStefan Eßer 	BC_SIG_ASSERT_LOCKED;
3073252884aeSStefan Eßer 	bc_num_init(d, s->len);
3074252884aeSStefan Eßer 	bc_num_copy(d, s);
3075252884aeSStefan Eßer }
3076252884aeSStefan Eßer 
3077*44d4804dSStefan Eßer void bc_num_createFromBigdig(BcNum *restrict n, BcBigDig val) {
3078252884aeSStefan Eßer 	BC_SIG_ASSERT_LOCKED;
307950696a6eSStefan Eßer 	bc_num_init(n, BC_NUM_BIGDIG_LOG10);
3080252884aeSStefan Eßer 	bc_num_bigdig2num(n, val);
3081252884aeSStefan Eßer }
3082252884aeSStefan Eßer 
3083252884aeSStefan Eßer size_t bc_num_scale(const BcNum *restrict n) {
3084252884aeSStefan Eßer 	return n->scale;
3085252884aeSStefan Eßer }
3086252884aeSStefan Eßer 
3087252884aeSStefan Eßer size_t bc_num_len(const BcNum *restrict n) {
3088252884aeSStefan Eßer 
3089252884aeSStefan Eßer 	size_t len = n->len;
3090252884aeSStefan Eßer 
3091*44d4804dSStefan Eßer 	// Always return at least 1.
3092028616d0SStefan Eßer 	if (BC_NUM_ZERO(n)) return n->scale ? n->scale : 1;
3093252884aeSStefan Eßer 
3094*44d4804dSStefan Eßer 	// If this is true, there is no integer portion of the number.
309550696a6eSStefan Eßer 	if (BC_NUM_RDX_VAL(n) == len) {
3096252884aeSStefan Eßer 
3097*44d4804dSStefan Eßer 		// We have to take into account the fact that some of the digits right
3098*44d4804dSStefan Eßer 		// after the decimal could be zero. If that is the case, we need to
3099*44d4804dSStefan Eßer 		// ignore them until we hit the first non-zero digit.
3100*44d4804dSStefan Eßer 
3101252884aeSStefan Eßer 		size_t zero, scale;
3102252884aeSStefan Eßer 
3103*44d4804dSStefan Eßer 		// The number of limbs with non-zero digits.
3104*44d4804dSStefan Eßer 		len = bc_num_nonZeroLen(n);
3105252884aeSStefan Eßer 
3106*44d4804dSStefan Eßer 		// Get the number of digits in the last limb.
3107252884aeSStefan Eßer 		scale = n->scale % BC_BASE_DIGS;
3108252884aeSStefan Eßer 		scale = scale ? scale : BC_BASE_DIGS;
3109252884aeSStefan Eßer 
3110*44d4804dSStefan Eßer 		// Get the number of zero digits.
3111252884aeSStefan Eßer 		zero = bc_num_zeroDigits(n->num + len - 1);
3112252884aeSStefan Eßer 
3113*44d4804dSStefan Eßer 		// Calculate the true length.
3114252884aeSStefan Eßer 		len = len * BC_BASE_DIGS - zero - (BC_BASE_DIGS - scale);
3115252884aeSStefan Eßer 	}
3116*44d4804dSStefan Eßer 	// Otherwise, count the number of int digits and return that plus the scale.
3117252884aeSStefan Eßer 	else len = bc_num_intDigits(n) + n->scale;
3118252884aeSStefan Eßer 
3119252884aeSStefan Eßer 	return len;
3120252884aeSStefan Eßer }
3121252884aeSStefan Eßer 
312250696a6eSStefan Eßer void bc_num_parse(BcNum *restrict n, const char *restrict val, BcBigDig base) {
312350696a6eSStefan Eßer 
3124252884aeSStefan Eßer 	assert(n != NULL && val != NULL && base);
3125252884aeSStefan Eßer 	assert(base >= BC_NUM_MIN_BASE && base <= vm.maxes[BC_PROG_GLOBALS_IBASE]);
3126252884aeSStefan Eßer 	assert(bc_num_strValid(val));
3127252884aeSStefan Eßer 
3128*44d4804dSStefan Eßer 	// A one character number is *always* parsed as though the base was the
3129*44d4804dSStefan Eßer 	// maximum allowed ibase, per the bc spec.
313050696a6eSStefan Eßer 	if (!val[1]) {
3131252884aeSStefan Eßer 		BcBigDig dig = bc_num_parseChar(val[0], BC_NUM_MAX_LBASE);
3132252884aeSStefan Eßer 		bc_num_bigdig2num(n, dig);
3133252884aeSStefan Eßer 	}
3134252884aeSStefan Eßer 	else if (base == BC_BASE) bc_num_parseDecimal(n, val);
3135252884aeSStefan Eßer 	else bc_num_parseBase(n, val, base);
313650696a6eSStefan Eßer 
313750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(n));
3138252884aeSStefan Eßer }
3139252884aeSStefan Eßer 
3140252884aeSStefan Eßer void bc_num_print(BcNum *restrict n, BcBigDig base, bool newline) {
3141252884aeSStefan Eßer 
3142252884aeSStefan Eßer 	assert(n != NULL);
3143252884aeSStefan Eßer 	assert(BC_ENABLE_EXTRA_MATH || base >= BC_NUM_MIN_BASE);
3144252884aeSStefan Eßer 
3145*44d4804dSStefan Eßer 	// We may need a newline, just to start.
3146252884aeSStefan Eßer 	bc_num_printNewline();
3147252884aeSStefan Eßer 
3148*44d4804dSStefan Eßer 	// Short-circuit 0.
3149*44d4804dSStefan Eßer 	if (BC_NUM_ZERO(n)) bc_num_printHex(0, 1, false, !newline);
3150*44d4804dSStefan Eßer 	else if (base == BC_BASE) bc_num_printDecimal(n, newline);
3151252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
3152*44d4804dSStefan Eßer 	else if (base == 0 || base == 1)
3153*44d4804dSStefan Eßer 		bc_num_printExponent(n, base != 0, newline);
3154252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
3155*44d4804dSStefan Eßer 	else bc_num_printBase(n, base, newline);
3156252884aeSStefan Eßer 
3157*44d4804dSStefan Eßer 	if (newline) bc_num_putchar('\n', false);
3158252884aeSStefan Eßer }
3159252884aeSStefan Eßer 
3160*44d4804dSStefan Eßer BcBigDig bc_num_bigdig2(const BcNum *restrict n) {
3161252884aeSStefan Eßer 
3162252884aeSStefan Eßer 	// This function returns no errors because it's guaranteed to succeed if
3163*44d4804dSStefan Eßer 	// its preconditions are met. Those preconditions include both n needs to
3164*44d4804dSStefan Eßer 	// be non-NULL, n being non-negative, and n being less than vm.max. If all
3165*44d4804dSStefan Eßer 	// of that is true, then we can just convert without worrying about negative
3166*44d4804dSStefan Eßer 	// errors or overflow.
3167252884aeSStefan Eßer 
3168252884aeSStefan Eßer 	BcBigDig r = 0;
316950696a6eSStefan Eßer 	size_t nrdx = BC_NUM_RDX_VAL(n);
3170252884aeSStefan Eßer 
3171*44d4804dSStefan Eßer 	assert(n != NULL);
317250696a6eSStefan Eßer 	assert(!BC_NUM_NEG(n));
3173252884aeSStefan Eßer 	assert(bc_num_cmp(n, &vm.max) < 0);
317450696a6eSStefan Eßer 	assert(n->len - nrdx <= 3);
3175252884aeSStefan Eßer 
3176252884aeSStefan Eßer 	// There is a small speed win from unrolling the loop here, and since it
3177252884aeSStefan Eßer 	// only adds 53 bytes, I decided that it was worth it.
317850696a6eSStefan Eßer 	switch (n->len - nrdx) {
317950696a6eSStefan Eßer 
3180252884aeSStefan Eßer 		case 3:
318150696a6eSStefan Eßer 		{
318250696a6eSStefan Eßer 			r = (BcBigDig) n->num[nrdx + 2];
318350696a6eSStefan Eßer 		}
3184252884aeSStefan Eßer 		// Fallthrough.
318550696a6eSStefan Eßer 		BC_FALLTHROUGH
318650696a6eSStefan Eßer 
3187252884aeSStefan Eßer 		case 2:
318850696a6eSStefan Eßer 		{
318950696a6eSStefan Eßer 			r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx + 1];
319050696a6eSStefan Eßer 		}
3191252884aeSStefan Eßer 		// Fallthrough.
319250696a6eSStefan Eßer 		BC_FALLTHROUGH
319350696a6eSStefan Eßer 
3194252884aeSStefan Eßer 		case 1:
319550696a6eSStefan Eßer 		{
319650696a6eSStefan Eßer 			r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx];
319750696a6eSStefan Eßer 		}
3198252884aeSStefan Eßer 	}
3199252884aeSStefan Eßer 
3200*44d4804dSStefan Eßer 	return r;
3201252884aeSStefan Eßer }
3202252884aeSStefan Eßer 
3203*44d4804dSStefan Eßer BcBigDig bc_num_bigdig(const BcNum *restrict n) {
3204252884aeSStefan Eßer 
3205*44d4804dSStefan Eßer 	assert(n != NULL);
3206252884aeSStefan Eßer 
3207*44d4804dSStefan Eßer 	// This error checking is extremely important, and if you do not have a
3208*44d4804dSStefan Eßer 	// guarantee that converting a number will always succeed in a particular
3209*44d4804dSStefan Eßer 	// case, you *must* call this function to get these error checks. This
3210*44d4804dSStefan Eßer 	// includes all instances of numbers inputted by the user or calculated by
3211*44d4804dSStefan Eßer 	// the user. Otherwise, you can call the faster bc_num_bigdig2().
3212*44d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_NEG(n))) bc_err(BC_ERR_MATH_NEGATIVE);
3213*44d4804dSStefan Eßer 	if (BC_ERR(bc_num_cmp(n, &vm.max) >= 0)) bc_err(BC_ERR_MATH_OVERFLOW);
3214252884aeSStefan Eßer 
3215*44d4804dSStefan Eßer 	return bc_num_bigdig2(n);
3216252884aeSStefan Eßer }
3217252884aeSStefan Eßer 
3218252884aeSStefan Eßer void bc_num_bigdig2num(BcNum *restrict n, BcBigDig val) {
3219252884aeSStefan Eßer 
3220252884aeSStefan Eßer 	BcDig *ptr;
3221252884aeSStefan Eßer 	size_t i;
3222252884aeSStefan Eßer 
3223252884aeSStefan Eßer 	assert(n != NULL);
3224252884aeSStefan Eßer 
3225252884aeSStefan Eßer 	bc_num_zero(n);
3226252884aeSStefan Eßer 
3227*44d4804dSStefan Eßer 	// Already 0.
3228252884aeSStefan Eßer 	if (!val) return;
3229252884aeSStefan Eßer 
3230*44d4804dSStefan Eßer 	// Expand first. This is the only way this function can fail, and it's a
3231*44d4804dSStefan Eßer 	// fatal error.
3232252884aeSStefan Eßer 	bc_num_expand(n, BC_NUM_BIGDIG_LOG10);
3233252884aeSStefan Eßer 
3234*44d4804dSStefan Eßer 	// The conversion is easy because numbers are laid out in little-endian
3235*44d4804dSStefan Eßer 	// order.
3236252884aeSStefan Eßer 	for (ptr = n->num, i = 0; val; ++i, val /= BC_BASE_POW)
3237252884aeSStefan Eßer 		ptr[i] = val % BC_BASE_POW;
3238252884aeSStefan Eßer 
3239252884aeSStefan Eßer 	n->len = i;
3240252884aeSStefan Eßer }
3241252884aeSStefan Eßer 
3242*44d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH
3243*44d4804dSStefan Eßer 
3244252884aeSStefan Eßer void bc_num_rng(const BcNum *restrict n, BcRNG *rng) {
3245252884aeSStefan Eßer 
324650696a6eSStefan Eßer 	BcNum temp, temp2, intn, frac;
3247252884aeSStefan Eßer 	BcRand state1, state2, inc1, inc2;
324850696a6eSStefan Eßer 	size_t nrdx = BC_NUM_RDX_VAL(n);
3249252884aeSStefan Eßer 
3250*44d4804dSStefan Eßer 	// This function holds the secret of how I interpret a seed number for the
3251*44d4804dSStefan Eßer 	// PRNG. Well, it's actually in the development manual
3252*44d4804dSStefan Eßer 	// (manuals/development.md#pseudo-random-number-generator), so look there
3253*44d4804dSStefan Eßer 	// before you try to understand this.
3254*44d4804dSStefan Eßer 
3255252884aeSStefan Eßer 	BC_SIG_LOCK;
3256252884aeSStefan Eßer 
3257252884aeSStefan Eßer 	bc_num_init(&temp, n->len);
3258252884aeSStefan Eßer 	bc_num_init(&temp2, n->len);
325950696a6eSStefan Eßer 	bc_num_init(&frac, nrdx);
3260252884aeSStefan Eßer 	bc_num_init(&intn, bc_num_int(n));
3261252884aeSStefan Eßer 
3262252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
3263252884aeSStefan Eßer 
3264252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3265252884aeSStefan Eßer 
326650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(vm.max));
3267252884aeSStefan Eßer 
326850696a6eSStefan Eßer 	memcpy(frac.num, n->num, BC_NUM_SIZE(nrdx));
326950696a6eSStefan Eßer 	frac.len = nrdx;
327050696a6eSStefan Eßer 	BC_NUM_RDX_SET_NP(frac, nrdx);
3271252884aeSStefan Eßer 	frac.scale = n->scale;
3272252884aeSStefan Eßer 
327350696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(frac));
327450696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(vm.max2));
327550696a6eSStefan Eßer 
3276*44d4804dSStefan Eßer 	// Multiply the fraction and truncate so that it's an integer. The
3277*44d4804dSStefan Eßer 	// truncation is what clamps it, by the way.
327850696a6eSStefan Eßer 	bc_num_mul(&frac, &vm.max2, &temp, 0);
3279252884aeSStefan Eßer 	bc_num_truncate(&temp, temp.scale);
3280252884aeSStefan Eßer 	bc_num_copy(&frac, &temp);
3281252884aeSStefan Eßer 
3282*44d4804dSStefan Eßer 	// Get the integer.
328350696a6eSStefan Eßer 	memcpy(intn.num, n->num + nrdx, BC_NUM_SIZE(bc_num_int(n)));
3284252884aeSStefan Eßer 	intn.len = bc_num_int(n);
3285252884aeSStefan Eßer 
3286252884aeSStefan Eßer 	// This assert is here because it has to be true. It is also here to justify
3287*44d4804dSStefan Eßer 	// some optimizations.
3288252884aeSStefan Eßer 	assert(BC_NUM_NONZERO(&vm.max));
3289252884aeSStefan Eßer 
3290*44d4804dSStefan Eßer 	// If there *was* a fractional part...
3291252884aeSStefan Eßer 	if (BC_NUM_NONZERO(&frac)) {
3292252884aeSStefan Eßer 
3293*44d4804dSStefan Eßer 		// This divmod splits frac into the two state parts.
3294252884aeSStefan Eßer 		bc_num_divmod(&frac, &vm.max, &temp, &temp2, 0);
3295252884aeSStefan Eßer 
3296252884aeSStefan Eßer 		// frac is guaranteed to be smaller than vm.max * vm.max (pow).
3297252884aeSStefan Eßer 		// This means that when dividing frac by vm.max, as above, the
3298252884aeSStefan Eßer 		// quotient and remainder are both guaranteed to be less than vm.max,
3299252884aeSStefan Eßer 		// which means we can use bc_num_bigdig2() here and not worry about
3300252884aeSStefan Eßer 		// overflow.
3301*44d4804dSStefan Eßer 		state1 = (BcRand) bc_num_bigdig2(&temp2);
3302*44d4804dSStefan Eßer 		state2 = (BcRand) bc_num_bigdig2(&temp);
3303252884aeSStefan Eßer 	}
3304252884aeSStefan Eßer 	else state1 = state2 = 0;
3305252884aeSStefan Eßer 
3306*44d4804dSStefan Eßer 	// If there *was* an integer part...
3307252884aeSStefan Eßer 	if (BC_NUM_NONZERO(&intn)) {
3308252884aeSStefan Eßer 
3309*44d4804dSStefan Eßer 		// This divmod splits intn into the two inc parts.
3310252884aeSStefan Eßer 		bc_num_divmod(&intn, &vm.max, &temp, &temp2, 0);
3311252884aeSStefan Eßer 
3312252884aeSStefan Eßer 		// Because temp2 is the mod of vm.max, from above, it is guaranteed
3313252884aeSStefan Eßer 		// to be small enough to use bc_num_bigdig2().
3314*44d4804dSStefan Eßer 		inc1 = (BcRand) bc_num_bigdig2(&temp2);
3315252884aeSStefan Eßer 
3316*44d4804dSStefan Eßer 		// Clamp the second inc part.
3317252884aeSStefan Eßer 		if (bc_num_cmp(&temp, &vm.max) >= 0) {
3318252884aeSStefan Eßer 			bc_num_copy(&temp2, &temp);
3319252884aeSStefan Eßer 			bc_num_mod(&temp2, &vm.max, &temp, 0);
3320252884aeSStefan Eßer 		}
3321252884aeSStefan Eßer 
3322252884aeSStefan Eßer 		// The if statement above ensures that temp is less than vm.max, which
3323252884aeSStefan Eßer 		// means that we can use bc_num_bigdig2() here.
3324*44d4804dSStefan Eßer 		inc2 = (BcRand) bc_num_bigdig2(&temp);
3325252884aeSStefan Eßer 	}
3326252884aeSStefan Eßer 	else inc1 = inc2 = 0;
3327252884aeSStefan Eßer 
3328252884aeSStefan Eßer 	bc_rand_seed(rng, state1, state2, inc1, inc2);
3329252884aeSStefan Eßer 
3330252884aeSStefan Eßer err:
3331252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
3332252884aeSStefan Eßer 	bc_num_free(&intn);
3333252884aeSStefan Eßer 	bc_num_free(&frac);
3334252884aeSStefan Eßer 	bc_num_free(&temp2);
3335252884aeSStefan Eßer 	bc_num_free(&temp);
3336252884aeSStefan Eßer 	BC_LONGJMP_CONT;
3337252884aeSStefan Eßer }
3338252884aeSStefan Eßer 
3339252884aeSStefan Eßer void bc_num_createFromRNG(BcNum *restrict n, BcRNG *rng) {
3340252884aeSStefan Eßer 
3341252884aeSStefan Eßer 	BcRand s1, s2, i1, i2;
334250696a6eSStefan Eßer 	BcNum conv, temp1, temp2, temp3;
3343252884aeSStefan Eßer 	BcDig temp1_num[BC_RAND_NUM_SIZE], temp2_num[BC_RAND_NUM_SIZE];
3344252884aeSStefan Eßer 	BcDig conv_num[BC_NUM_BIGDIG_LOG10];
3345252884aeSStefan Eßer 
3346252884aeSStefan Eßer 	BC_SIG_LOCK;
3347252884aeSStefan Eßer 
3348252884aeSStefan Eßer 	bc_num_init(&temp3, 2 * BC_RAND_NUM_SIZE);
3349252884aeSStefan Eßer 
3350252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
3351252884aeSStefan Eßer 
3352252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3353252884aeSStefan Eßer 
3354252884aeSStefan Eßer 	bc_num_setup(&temp1, temp1_num, sizeof(temp1_num) / sizeof(BcDig));
3355252884aeSStefan Eßer 	bc_num_setup(&temp2, temp2_num, sizeof(temp2_num) / sizeof(BcDig));
3356252884aeSStefan Eßer 	bc_num_setup(&conv, conv_num, sizeof(conv_num) / sizeof(BcDig));
3357252884aeSStefan Eßer 
3358252884aeSStefan Eßer 	// This assert is here because it has to be true. It is also here to justify
3359*44d4804dSStefan Eßer 	// the assumption that vm.max is not zero.
3360252884aeSStefan Eßer 	assert(BC_NUM_NONZERO(&vm.max));
3361252884aeSStefan Eßer 
3362*44d4804dSStefan Eßer 	// Because this is true, we can just ignore math errors that would happen
3363*44d4804dSStefan Eßer 	// otherwise.
336450696a6eSStefan Eßer 	assert(BC_NUM_NONZERO(&vm.max2));
3365252884aeSStefan Eßer 
3366252884aeSStefan Eßer 	bc_rand_getRands(rng, &s1, &s2, &i1, &i2);
3367252884aeSStefan Eßer 
3368*44d4804dSStefan Eßer 	// Put the second piece of state into a number.
3369252884aeSStefan Eßer 	bc_num_bigdig2num(&conv, (BcBigDig) s2);
3370252884aeSStefan Eßer 
337150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(conv));
337250696a6eSStefan Eßer 
3373*44d4804dSStefan Eßer 	// Multiply by max to make room for the first piece of state.
3374252884aeSStefan Eßer 	bc_num_mul(&conv, &vm.max, &temp1, 0);
3375252884aeSStefan Eßer 
3376*44d4804dSStefan Eßer 	// Add in the first piece of state.
3377252884aeSStefan Eßer 	bc_num_bigdig2num(&conv, (BcBigDig) s1);
3378252884aeSStefan Eßer 	bc_num_add(&conv, &temp1, &temp2, 0);
3379252884aeSStefan Eßer 
3380*44d4804dSStefan Eßer 	// Divide to make it an entirely fractional part.
338150696a6eSStefan Eßer 	bc_num_div(&temp2, &vm.max2, &temp3, BC_RAND_STATE_BITS);
3382252884aeSStefan Eßer 
3383*44d4804dSStefan Eßer 	// Now start on the increment parts. It's the same process without the
3384*44d4804dSStefan Eßer 	// divide, so put the second piece of increment into a number.
3385252884aeSStefan Eßer 	bc_num_bigdig2num(&conv, (BcBigDig) i2);
3386252884aeSStefan Eßer 
338750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID_NP(conv));
338850696a6eSStefan Eßer 
3389*44d4804dSStefan Eßer 	// Multiply by max to make room for the first piece of increment.
3390252884aeSStefan Eßer 	bc_num_mul(&conv, &vm.max, &temp1, 0);
3391252884aeSStefan Eßer 
3392*44d4804dSStefan Eßer 	// Add in the first piece of increment.
3393252884aeSStefan Eßer 	bc_num_bigdig2num(&conv, (BcBigDig) i1);
3394252884aeSStefan Eßer 	bc_num_add(&conv, &temp1, &temp2, 0);
3395252884aeSStefan Eßer 
3396*44d4804dSStefan Eßer 	// Now add the two together.
3397252884aeSStefan Eßer 	bc_num_add(&temp2, &temp3, n, 0);
3398252884aeSStefan Eßer 
339950696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(n));
340050696a6eSStefan Eßer 
3401252884aeSStefan Eßer err:
3402252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
3403252884aeSStefan Eßer 	bc_num_free(&temp3);
3404252884aeSStefan Eßer 	BC_LONGJMP_CONT;
3405252884aeSStefan Eßer }
3406252884aeSStefan Eßer 
3407*44d4804dSStefan Eßer void bc_num_irand(BcNum *restrict a, BcNum *restrict b, BcRNG *restrict rng) {
3408*44d4804dSStefan Eßer 
3409*44d4804dSStefan Eßer 	BcNum atemp;
3410*44d4804dSStefan Eßer 	size_t i, len;
3411252884aeSStefan Eßer 
3412252884aeSStefan Eßer 	assert(a != b);
3413252884aeSStefan Eßer 
3414*44d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_NEG(a))) bc_err(BC_ERR_MATH_NEGATIVE);
3415*44d4804dSStefan Eßer 
3416*44d4804dSStefan Eßer 	// If either of these are true, then the numbers are integers.
3417252884aeSStefan Eßer 	if (BC_NUM_ZERO(a) || BC_NUM_ONE(a)) return;
3418252884aeSStefan Eßer 
3419*44d4804dSStefan Eßer 	if (BC_ERR(bc_num_nonInt(a, &atemp))) bc_err(BC_ERR_MATH_NON_INTEGER);
3420252884aeSStefan Eßer 
3421*44d4804dSStefan Eßer 	assert(atemp.len);
3422252884aeSStefan Eßer 
3423*44d4804dSStefan Eßer 	len = atemp.len - 1;
3424252884aeSStefan Eßer 
3425*44d4804dSStefan Eßer 	// Just generate a random number for each limb.
3426*44d4804dSStefan Eßer 	for (i = 0; i < len; ++i)
3427*44d4804dSStefan Eßer 		b->num[i] = (BcDig) bc_rand_bounded(rng, BC_BASE_POW);
3428252884aeSStefan Eßer 
3429*44d4804dSStefan Eßer 	// Do the last digit explicitly because the bound must be right. But only
3430*44d4804dSStefan Eßer 	// do it if the limb does not equal 1. If it does, we have already hit the
3431*44d4804dSStefan Eßer 	// limit.
3432*44d4804dSStefan Eßer 	if (atemp.num[i] != 1) {
3433*44d4804dSStefan Eßer 		b->num[i] = (BcDig) bc_rand_bounded(rng, (BcRand) atemp.num[i]);
3434*44d4804dSStefan Eßer 		b->len = atemp.len;
3435252884aeSStefan Eßer 	}
3436*44d4804dSStefan Eßer 	// We want 1 less len in the case where we skip the last limb.
3437*44d4804dSStefan Eßer 	else b->len = len;
3438252884aeSStefan Eßer 
3439252884aeSStefan Eßer 	bc_num_clean(b);
3440252884aeSStefan Eßer 
344150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3442252884aeSStefan Eßer }
3443*44d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
3444252884aeSStefan Eßer 
3445252884aeSStefan Eßer size_t bc_num_addReq(const BcNum *a, const BcNum *b, size_t scale) {
3446252884aeSStefan Eßer 
3447252884aeSStefan Eßer 	size_t aint, bint, ardx, brdx;
3448252884aeSStefan Eßer 
3449*44d4804dSStefan Eßer 	// Addition and subtraction require the max of the length of the two numbers
3450*44d4804dSStefan Eßer 	// plus 1.
3451*44d4804dSStefan Eßer 
3452252884aeSStefan Eßer 	BC_UNUSED(scale);
3453252884aeSStefan Eßer 
345450696a6eSStefan Eßer 	ardx = BC_NUM_RDX_VAL(a);
3455252884aeSStefan Eßer 	aint = bc_num_int(a);
3456252884aeSStefan Eßer 	assert(aint <= a->len && ardx <= a->len);
3457252884aeSStefan Eßer 
345850696a6eSStefan Eßer 	brdx = BC_NUM_RDX_VAL(b);
3459252884aeSStefan Eßer 	bint = bc_num_int(b);
3460252884aeSStefan Eßer 	assert(bint <= b->len && brdx <= b->len);
3461252884aeSStefan Eßer 
3462252884aeSStefan Eßer 	ardx = BC_MAX(ardx, brdx);
3463252884aeSStefan Eßer 	aint = BC_MAX(aint, bint);
3464252884aeSStefan Eßer 
3465252884aeSStefan Eßer 	return bc_vm_growSize(bc_vm_growSize(ardx, aint), 1);
3466252884aeSStefan Eßer }
3467252884aeSStefan Eßer 
3468252884aeSStefan Eßer size_t bc_num_mulReq(const BcNum *a, const BcNum *b, size_t scale) {
3469*44d4804dSStefan Eßer 
3470252884aeSStefan Eßer 	size_t max, rdx;
3471*44d4804dSStefan Eßer 
3472*44d4804dSStefan Eßer 	// Multiplication requires the sum of the lengths of the numbers.
3473*44d4804dSStefan Eßer 
347450696a6eSStefan Eßer 	rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));
3475*44d4804dSStefan Eßer 
3476252884aeSStefan Eßer 	max = BC_NUM_RDX(scale);
3477*44d4804dSStefan Eßer 
3478252884aeSStefan Eßer 	max = bc_vm_growSize(BC_MAX(max, rdx), 1);
3479252884aeSStefan Eßer 	rdx = bc_vm_growSize(bc_vm_growSize(bc_num_int(a), bc_num_int(b)), max);
3480*44d4804dSStefan Eßer 
3481252884aeSStefan Eßer 	return rdx;
3482252884aeSStefan Eßer }
3483252884aeSStefan Eßer 
348450696a6eSStefan Eßer size_t bc_num_divReq(const BcNum *a, const BcNum *b, size_t scale) {
3485*44d4804dSStefan Eßer 
348650696a6eSStefan Eßer 	size_t max, rdx;
3487*44d4804dSStefan Eßer 
3488*44d4804dSStefan Eßer 	// Division requires the length of the dividend plus the scale.
3489*44d4804dSStefan Eßer 
349050696a6eSStefan Eßer 	rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));
3491*44d4804dSStefan Eßer 
349250696a6eSStefan Eßer 	max = BC_NUM_RDX(scale);
3493*44d4804dSStefan Eßer 
349450696a6eSStefan Eßer 	max = bc_vm_growSize(BC_MAX(max, rdx), 1);
349550696a6eSStefan Eßer 	rdx = bc_vm_growSize(bc_num_int(a), max);
3496*44d4804dSStefan Eßer 
349750696a6eSStefan Eßer 	return rdx;
349850696a6eSStefan Eßer }
349950696a6eSStefan Eßer 
3500252884aeSStefan Eßer size_t bc_num_powReq(const BcNum *a, const BcNum *b, size_t scale) {
3501252884aeSStefan Eßer 	BC_UNUSED(scale);
3502252884aeSStefan Eßer 	return bc_vm_growSize(bc_vm_growSize(a->len, b->len), 1);
3503252884aeSStefan Eßer }
3504252884aeSStefan Eßer 
3505252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
3506252884aeSStefan Eßer size_t bc_num_placesReq(const BcNum *a, const BcNum *b, size_t scale) {
3507252884aeSStefan Eßer 	BC_UNUSED(scale);
350850696a6eSStefan Eßer 	return a->len + b->len - BC_NUM_RDX_VAL(a) - BC_NUM_RDX_VAL(b);
3509252884aeSStefan Eßer }
3510252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
3511252884aeSStefan Eßer 
3512252884aeSStefan Eßer void bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
351350696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
351450696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3515252884aeSStefan Eßer 	bc_num_binary(a, b, c, false, bc_num_as, bc_num_addReq(a, b, scale));
3516252884aeSStefan Eßer }
3517252884aeSStefan Eßer 
3518252884aeSStefan Eßer void bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
351950696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
352050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3521252884aeSStefan Eßer 	bc_num_binary(a, b, c, true, bc_num_as, bc_num_addReq(a, b, scale));
3522252884aeSStefan Eßer }
3523252884aeSStefan Eßer 
3524252884aeSStefan Eßer void bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
352550696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
352650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3527252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_m, bc_num_mulReq(a, b, scale));
3528252884aeSStefan Eßer }
3529252884aeSStefan Eßer 
3530252884aeSStefan Eßer void bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
353150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
353250696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
353350696a6eSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_d, bc_num_divReq(a, b, scale));
3534252884aeSStefan Eßer }
3535252884aeSStefan Eßer 
3536252884aeSStefan Eßer void bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
353750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
353850696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
353950696a6eSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_rem, bc_num_divReq(a, b, scale));
3540252884aeSStefan Eßer }
3541252884aeSStefan Eßer 
3542252884aeSStefan Eßer void bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
354350696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
354450696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3545252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_p, bc_num_powReq(a, b, scale));
3546252884aeSStefan Eßer }
3547252884aeSStefan Eßer 
3548252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
3549252884aeSStefan Eßer void bc_num_places(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
355050696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
355150696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3552252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_place, bc_num_placesReq(a, b, scale));
3553252884aeSStefan Eßer }
3554252884aeSStefan Eßer 
3555252884aeSStefan Eßer void bc_num_lshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
355650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
355750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3558252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_left, bc_num_placesReq(a, b, scale));
3559252884aeSStefan Eßer }
3560252884aeSStefan Eßer 
3561252884aeSStefan Eßer void bc_num_rshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
356250696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(a));
356350696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
3564252884aeSStefan Eßer 	bc_num_binary(a, b, c, scale, bc_num_right, bc_num_placesReq(a, b, scale));
3565252884aeSStefan Eßer }
3566252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
3567252884aeSStefan Eßer 
3568252884aeSStefan Eßer void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
3569252884aeSStefan Eßer 
3570252884aeSStefan Eßer 	BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
357110328f8bSStefan Eßer 	size_t pow, len, rdx, req, resscale;
3572252884aeSStefan Eßer 	BcDig half_digs[1];
3573252884aeSStefan Eßer 
3574252884aeSStefan Eßer 	assert(a != NULL && b != NULL && a != b);
3575252884aeSStefan Eßer 
3576*44d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_NEG(a))) bc_err(BC_ERR_MATH_NEGATIVE);
3577252884aeSStefan Eßer 
3578*44d4804dSStefan Eßer 	// We want to calculate to a's scale if it is bigger so that the result will
3579*44d4804dSStefan Eßer 	// truncate properly.
3580252884aeSStefan Eßer 	if (a->scale > scale) scale = a->scale;
3581252884aeSStefan Eßer 
3582*44d4804dSStefan Eßer 	// Set parameters for the result.
3583252884aeSStefan Eßer 	len = bc_vm_growSize(bc_num_intDigits(a), 1);
3584252884aeSStefan Eßer 	rdx = BC_NUM_RDX(scale);
3585*44d4804dSStefan Eßer 
3586*44d4804dSStefan Eßer 	// Square root needs half of the length of the parameter.
358750696a6eSStefan Eßer 	req = bc_vm_growSize(BC_MAX(rdx, BC_NUM_RDX_VAL(a)), len >> 1);
3588252884aeSStefan Eßer 
3589252884aeSStefan Eßer 	BC_SIG_LOCK;
3590252884aeSStefan Eßer 
3591*44d4804dSStefan Eßer 	// Unlike the binary operators, this function is the only single parameter
3592*44d4804dSStefan Eßer 	// function and is expected to initialize the result. This means that it
3593*44d4804dSStefan Eßer 	// expects that b is *NOT* preallocated. We allocate it here.
3594252884aeSStefan Eßer 	bc_num_init(b, bc_vm_growSize(req, 1));
3595252884aeSStefan Eßer 
3596252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3597252884aeSStefan Eßer 
359850696a6eSStefan Eßer 	assert(a != NULL && b != NULL && a != b);
359950696a6eSStefan Eßer 	assert(a->num != NULL && b->num != NULL);
360050696a6eSStefan Eßer 
3601*44d4804dSStefan Eßer 	// Easy case.
3602252884aeSStefan Eßer 	if (BC_NUM_ZERO(a)) {
3603252884aeSStefan Eßer 		bc_num_setToZero(b, scale);
3604252884aeSStefan Eßer 		return;
3605252884aeSStefan Eßer 	}
3606*44d4804dSStefan Eßer 
3607*44d4804dSStefan Eßer 	// Another easy case.
3608252884aeSStefan Eßer 	if (BC_NUM_ONE(a)) {
3609252884aeSStefan Eßer 		bc_num_one(b);
3610252884aeSStefan Eßer 		bc_num_extend(b, scale);
3611252884aeSStefan Eßer 		return;
3612252884aeSStefan Eßer 	}
3613252884aeSStefan Eßer 
3614*44d4804dSStefan Eßer 	// Set the parameters again.
3615252884aeSStefan Eßer 	rdx = BC_NUM_RDX(scale);
361650696a6eSStefan Eßer 	rdx = BC_MAX(rdx, BC_NUM_RDX_VAL(a));
3617252884aeSStefan Eßer 	len = bc_vm_growSize(a->len, rdx);
3618252884aeSStefan Eßer 
3619252884aeSStefan Eßer 	BC_SIG_LOCK;
3620252884aeSStefan Eßer 
3621252884aeSStefan Eßer 	bc_num_init(&num1, len);
3622252884aeSStefan Eßer 	bc_num_init(&num2, len);
3623252884aeSStefan Eßer 	bc_num_setup(&half, half_digs, sizeof(half_digs) / sizeof(BcDig));
3624252884aeSStefan Eßer 
3625*44d4804dSStefan Eßer 	// There is a division by two in the formula. We setup a number that's 1/2
3626*44d4804dSStefan Eßer 	// so that we can use multiplication instead of heavy division.
3627252884aeSStefan Eßer 	bc_num_one(&half);
3628252884aeSStefan Eßer 	half.num[0] = BC_BASE_POW / 2;
3629252884aeSStefan Eßer 	half.len = 1;
363050696a6eSStefan Eßer 	BC_NUM_RDX_SET_NP(half, 1);
3631252884aeSStefan Eßer 	half.scale = 1;
3632252884aeSStefan Eßer 
3633252884aeSStefan Eßer 	bc_num_init(&f, len);
3634252884aeSStefan Eßer 	bc_num_init(&fprime, len);
3635252884aeSStefan Eßer 
3636252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
3637252884aeSStefan Eßer 
3638252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3639252884aeSStefan Eßer 
3640*44d4804dSStefan Eßer 	// Pointers for easy switching.
3641252884aeSStefan Eßer 	x0 = &num1;
3642252884aeSStefan Eßer 	x1 = &num2;
3643252884aeSStefan Eßer 
3644*44d4804dSStefan Eßer 	// Start with 1.
3645252884aeSStefan Eßer 	bc_num_one(x0);
3646*44d4804dSStefan Eßer 
3647*44d4804dSStefan Eßer 	// The power of the operand is needed for the estimate.
3648252884aeSStefan Eßer 	pow = bc_num_intDigits(a);
3649252884aeSStefan Eßer 
3650*44d4804dSStefan Eßer 	// The code in this if statement calculates the initial estimate. First, if
3651*44d4804dSStefan Eßer 	// a is less than 0, then 0 is a good estimate. Otherwise, we want something
3652*44d4804dSStefan Eßer 	// in the same ballpark. That ballpark is pow.
3653252884aeSStefan Eßer 	if (pow) {
3654252884aeSStefan Eßer 
3655*44d4804dSStefan Eßer 		// An odd number is served by starting with 2^((pow-1)/2), and an even
3656*44d4804dSStefan Eßer 		// number is served by starting with 6^((pow-2)/2). Why? Because math.
3657252884aeSStefan Eßer 		if (pow & 1) x0->num[0] = 2;
3658252884aeSStefan Eßer 		else x0->num[0] = 6;
3659252884aeSStefan Eßer 
3660252884aeSStefan Eßer 		pow -= 2 - (pow & 1);
3661252884aeSStefan Eßer 		bc_num_shiftLeft(x0, pow / 2);
3662252884aeSStefan Eßer 	}
3663252884aeSStefan Eßer 
366450696a6eSStefan Eßer 	// I can set the rdx here directly because neg should be false.
366510328f8bSStefan Eßer 	x0->scale = x0->rdx = 0;
3666252884aeSStefan Eßer 	resscale = (scale + BC_BASE_DIGS) + 2;
3667252884aeSStefan Eßer 
3668*44d4804dSStefan Eßer 	// This is the calculation loop. This compare goes to 0 eventually as the
3669*44d4804dSStefan Eßer 	// difference between the two numbers gets smaller than resscale.
3670252884aeSStefan Eßer 	while (bc_num_cmp(x1, x0)) {
3671252884aeSStefan Eßer 
3672252884aeSStefan Eßer 		assert(BC_NUM_NONZERO(x0));
3673252884aeSStefan Eßer 
3674*44d4804dSStefan Eßer 		// This loop directly corresponds to the iteration in Newton's method.
3675*44d4804dSStefan Eßer 		// If you know the formula, this loop makes sense. Go study the formula.
3676*44d4804dSStefan Eßer 
3677252884aeSStefan Eßer 		bc_num_div(a, x0, &f, resscale);
3678252884aeSStefan Eßer 		bc_num_add(x0, &f, &fprime, resscale);
367950696a6eSStefan Eßer 
368050696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(fprime));
368150696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(half));
368250696a6eSStefan Eßer 
3683252884aeSStefan Eßer 		bc_num_mul(&fprime, &half, x1, resscale);
3684252884aeSStefan Eßer 
3685*44d4804dSStefan Eßer 		// Switch.
3686252884aeSStefan Eßer 		temp = x0;
3687252884aeSStefan Eßer 		x0 = x1;
3688252884aeSStefan Eßer 		x1 = temp;
3689252884aeSStefan Eßer 	}
3690252884aeSStefan Eßer 
3691*44d4804dSStefan Eßer 	// Copy to the result and truncate.
3692252884aeSStefan Eßer 	bc_num_copy(b, x0);
3693252884aeSStefan Eßer 	if (b->scale > scale) bc_num_truncate(b, b->scale - scale);
3694252884aeSStefan Eßer 
369550696a6eSStefan Eßer 	assert(!BC_NUM_NEG(b) || BC_NUM_NONZERO(b));
369650696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(b));
369750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(b) <= b->len || !b->len);
369850696a6eSStefan Eßer 	assert(!b->len || b->num[b->len - 1] || BC_NUM_RDX_VAL(b) == b->len);
3699252884aeSStefan Eßer 
3700252884aeSStefan Eßer err:
3701252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
3702252884aeSStefan Eßer 	bc_num_free(&fprime);
3703252884aeSStefan Eßer 	bc_num_free(&f);
3704252884aeSStefan Eßer 	bc_num_free(&num2);
3705252884aeSStefan Eßer 	bc_num_free(&num1);
3706252884aeSStefan Eßer 	BC_LONGJMP_CONT;
3707252884aeSStefan Eßer }
3708252884aeSStefan Eßer 
3709252884aeSStefan Eßer void bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) {
3710252884aeSStefan Eßer 
3711252884aeSStefan Eßer 	size_t ts, len;
371250696a6eSStefan Eßer 	BcNum *ptr_a, num2;
371350696a6eSStefan Eßer 	bool init = false;
3714252884aeSStefan Eßer 
3715*44d4804dSStefan Eßer 	// The bulk of this function is just doing what bc_num_binary() does for the
3716*44d4804dSStefan Eßer 	// binary operators. However, it assumes that only c and a can be equal.
3717*44d4804dSStefan Eßer 
3718*44d4804dSStefan Eßer 	// Set up the parameters.
3719252884aeSStefan Eßer 	ts = BC_MAX(scale + b->scale, a->scale);
3720252884aeSStefan Eßer 	len = bc_num_mulReq(a, b, ts);
3721252884aeSStefan Eßer 
3722252884aeSStefan Eßer 	assert(a != NULL && b != NULL && c != NULL && d != NULL);
3723252884aeSStefan Eßer 	assert(c != d && a != d && b != d && b != c);
3724252884aeSStefan Eßer 
3725*44d4804dSStefan Eßer 	// Initialize or expand as necessary.
3726252884aeSStefan Eßer 	if (c == a) {
3727252884aeSStefan Eßer 
3728252884aeSStefan Eßer 		memcpy(&num2, c, sizeof(BcNum));
3729252884aeSStefan Eßer 		ptr_a = &num2;
3730252884aeSStefan Eßer 
3731252884aeSStefan Eßer 		BC_SIG_LOCK;
3732252884aeSStefan Eßer 
3733252884aeSStefan Eßer 		bc_num_init(c, len);
3734252884aeSStefan Eßer 
3735252884aeSStefan Eßer 		init = true;
3736252884aeSStefan Eßer 
3737252884aeSStefan Eßer 		BC_SETJMP_LOCKED(err);
3738252884aeSStefan Eßer 
3739252884aeSStefan Eßer 		BC_SIG_UNLOCK;
3740252884aeSStefan Eßer 	}
3741252884aeSStefan Eßer 	else {
3742252884aeSStefan Eßer 		ptr_a = a;
3743252884aeSStefan Eßer 		bc_num_expand(c, len);
3744252884aeSStefan Eßer 	}
3745252884aeSStefan Eßer 
3746*44d4804dSStefan Eßer 	// Do the quick version if possible.
374750696a6eSStefan Eßer 	if (BC_NUM_NONZERO(a) && !BC_NUM_RDX_VAL(a) &&
374850696a6eSStefan Eßer 	    !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale)
374950696a6eSStefan Eßer 	{
3750252884aeSStefan Eßer 		BcBigDig rem;
3751252884aeSStefan Eßer 
3752252884aeSStefan Eßer 		bc_num_divArray(ptr_a, (BcBigDig) b->num[0], c, &rem);
3753252884aeSStefan Eßer 
3754252884aeSStefan Eßer 		assert(rem < BC_BASE_POW);
3755252884aeSStefan Eßer 
3756252884aeSStefan Eßer 		d->num[0] = (BcDig) rem;
3757252884aeSStefan Eßer 		d->len = (rem != 0);
3758252884aeSStefan Eßer 	}
3759*44d4804dSStefan Eßer 	// Do the slow method.
3760252884aeSStefan Eßer 	else bc_num_r(ptr_a, b, c, d, scale, ts);
3761252884aeSStefan Eßer 
376250696a6eSStefan Eßer 	assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
376350696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(c));
376450696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
376550696a6eSStefan Eßer 	assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
376650696a6eSStefan Eßer 	assert(!BC_NUM_NEG(d) || BC_NUM_NONZERO(d));
376750696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(d));
376850696a6eSStefan Eßer 	assert(BC_NUM_RDX_VAL(d) <= d->len || !d->len);
376950696a6eSStefan Eßer 	assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
3770252884aeSStefan Eßer 
3771252884aeSStefan Eßer err:
3772*44d4804dSStefan Eßer 	// Only cleanup if we initialized.
3773252884aeSStefan Eßer 	if (init) {
3774252884aeSStefan Eßer 		BC_SIG_MAYLOCK;
3775252884aeSStefan Eßer 		bc_num_free(&num2);
3776252884aeSStefan Eßer 		BC_LONGJMP_CONT;
3777252884aeSStefan Eßer 	}
3778252884aeSStefan Eßer }
3779252884aeSStefan Eßer 
3780252884aeSStefan Eßer void bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) {
3781252884aeSStefan Eßer 
3782*44d4804dSStefan Eßer 	BcNum base, exp, two, temp, atemp, btemp, ctemp;
3783252884aeSStefan Eßer 	BcDig two_digs[2];
3784252884aeSStefan Eßer 
3785252884aeSStefan Eßer 	assert(a != NULL && b != NULL && c != NULL && d != NULL);
3786252884aeSStefan Eßer 	assert(a != d && b != d && c != d);
3787252884aeSStefan Eßer 
3788*44d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_ZERO(c))) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
3789252884aeSStefan Eßer 
3790*44d4804dSStefan Eßer 	if (BC_ERR(BC_NUM_NEG(b))) bc_err(BC_ERR_MATH_NEGATIVE);
3791*44d4804dSStefan Eßer 
3792*44d4804dSStefan Eßer #ifndef NDEBUG
3793*44d4804dSStefan Eßer 	// This is entirely for quieting a useless scan-build error.
3794*44d4804dSStefan Eßer 	btemp.len = 0;
3795*44d4804dSStefan Eßer 	ctemp.len = 0;
3796*44d4804dSStefan Eßer #endif // NDEBUG
3797*44d4804dSStefan Eßer 
3798*44d4804dSStefan Eßer 	// Eliminate fractional parts that are zero or error if they are not zero.
3799*44d4804dSStefan Eßer 	if (BC_ERR(bc_num_nonInt(a, &atemp) || bc_num_nonInt(b, &btemp) ||
3800*44d4804dSStefan Eßer 	           bc_num_nonInt(c, &ctemp)))
3801*44d4804dSStefan Eßer 	{
3802*44d4804dSStefan Eßer 		bc_err(BC_ERR_MATH_NON_INTEGER);
3803*44d4804dSStefan Eßer 	}
3804*44d4804dSStefan Eßer 
3805*44d4804dSStefan Eßer 	bc_num_expand(d, ctemp.len);
3806252884aeSStefan Eßer 
3807252884aeSStefan Eßer 	BC_SIG_LOCK;
3808252884aeSStefan Eßer 
3809*44d4804dSStefan Eßer 	bc_num_init(&base, ctemp.len);
3810252884aeSStefan Eßer 	bc_num_setup(&two, two_digs, sizeof(two_digs) / sizeof(BcDig));
3811*44d4804dSStefan Eßer 	bc_num_init(&temp, btemp.len + 1);
3812*44d4804dSStefan Eßer 	bc_num_createCopy(&exp, &btemp);
3813252884aeSStefan Eßer 
3814252884aeSStefan Eßer 	BC_SETJMP_LOCKED(err);
3815252884aeSStefan Eßer 
3816252884aeSStefan Eßer 	BC_SIG_UNLOCK;
3817252884aeSStefan Eßer 
3818252884aeSStefan Eßer 	bc_num_one(&two);
3819252884aeSStefan Eßer 	two.num[0] = 2;
3820252884aeSStefan Eßer 	bc_num_one(d);
3821252884aeSStefan Eßer 
3822252884aeSStefan Eßer 	// We already checked for 0.
3823*44d4804dSStefan Eßer 	bc_num_rem(&atemp, &ctemp, &base, 0);
3824252884aeSStefan Eßer 
3825*44d4804dSStefan Eßer 	// If you know the algorithm I used, the memory-efficient method, then this
3826*44d4804dSStefan Eßer 	// loop should be self-explanatory because it is the calculation loop.
3827252884aeSStefan Eßer 	while (BC_NUM_NONZERO(&exp)) {
3828252884aeSStefan Eßer 
3829252884aeSStefan Eßer 		// Num two cannot be 0, so no errors.
3830252884aeSStefan Eßer 		bc_num_divmod(&exp, &two, &exp, &temp, 0);
3831252884aeSStefan Eßer 
383250696a6eSStefan Eßer 		if (BC_NUM_ONE(&temp) && !BC_NUM_NEG_NP(temp)) {
383350696a6eSStefan Eßer 
383450696a6eSStefan Eßer 			assert(BC_NUM_RDX_VALID(d));
383550696a6eSStefan Eßer 			assert(BC_NUM_RDX_VALID_NP(base));
3836252884aeSStefan Eßer 
3837252884aeSStefan Eßer 			bc_num_mul(d, &base, &temp, 0);
3838252884aeSStefan Eßer 
3839252884aeSStefan Eßer 			// We already checked for 0.
3840*44d4804dSStefan Eßer 			bc_num_rem(&temp, &ctemp, d, 0);
3841252884aeSStefan Eßer 		}
3842252884aeSStefan Eßer 
384350696a6eSStefan Eßer 		assert(BC_NUM_RDX_VALID_NP(base));
384450696a6eSStefan Eßer 
3845252884aeSStefan Eßer 		bc_num_mul(&base, &base, &temp, 0);
3846252884aeSStefan Eßer 
3847252884aeSStefan Eßer 		// We already checked for 0.
3848*44d4804dSStefan Eßer 		bc_num_rem(&temp, &ctemp, &base, 0);
3849252884aeSStefan Eßer 	}
3850252884aeSStefan Eßer 
3851252884aeSStefan Eßer err:
3852252884aeSStefan Eßer 	BC_SIG_MAYLOCK;
3853252884aeSStefan Eßer 	bc_num_free(&exp);
3854252884aeSStefan Eßer 	bc_num_free(&temp);
3855252884aeSStefan Eßer 	bc_num_free(&base);
3856252884aeSStefan Eßer 	BC_LONGJMP_CONT;
385750696a6eSStefan Eßer 	assert(!BC_NUM_NEG(d) || d->len);
385850696a6eSStefan Eßer 	assert(BC_NUM_RDX_VALID(d));
385950696a6eSStefan Eßer 	assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
3860252884aeSStefan Eßer }
3861252884aeSStefan Eßer 
3862252884aeSStefan Eßer #if BC_DEBUG_CODE
3863252884aeSStefan Eßer void bc_num_printDebug(const BcNum *n, const char *name, bool emptyline) {
38647e5c51e5SStefan Eßer 	bc_file_puts(&vm.fout, bc_flush_none, name);
38657e5c51e5SStefan Eßer 	bc_file_puts(&vm.fout, bc_flush_none, ": ");
3866*44d4804dSStefan Eßer 	bc_num_printDecimal(n, true);
38677e5c51e5SStefan Eßer 	bc_file_putchar(&vm.fout, bc_flush_err, '\n');
38687e5c51e5SStefan Eßer 	if (emptyline) bc_file_putchar(&vm.fout, bc_flush_err, '\n');
3869252884aeSStefan Eßer 	vm.nchars = 0;
3870252884aeSStefan Eßer }
3871252884aeSStefan Eßer 
3872252884aeSStefan Eßer void bc_num_printDigs(const BcDig *n, size_t len, bool emptyline) {
3873252884aeSStefan Eßer 
3874252884aeSStefan Eßer 	size_t i;
3875252884aeSStefan Eßer 
3876252884aeSStefan Eßer 	for (i = len - 1; i < len; --i)
3877252884aeSStefan Eßer 		bc_file_printf(&vm.fout, " %lu", (unsigned long) n[i]);
3878252884aeSStefan Eßer 
38797e5c51e5SStefan Eßer 	bc_file_putchar(&vm.fout, bc_flush_err, '\n');
38807e5c51e5SStefan Eßer 	if (emptyline) bc_file_putchar(&vm.fout, bc_flush_err, '\n');
3881252884aeSStefan Eßer 	vm.nchars = 0;
3882252884aeSStefan Eßer }
3883252884aeSStefan Eßer 
3884252884aeSStefan Eßer void bc_num_printWithDigs(const BcNum *n, const char *name, bool emptyline) {
38857e5c51e5SStefan Eßer 	bc_file_puts(&vm.fout, bc_flush_none, name);
3886252884aeSStefan Eßer 	bc_file_printf(&vm.fout, " len: %zu, rdx: %zu, scale: %zu\n",
388750696a6eSStefan Eßer 	               name, n->len, BC_NUM_RDX_VAL(n), n->scale);
3888252884aeSStefan Eßer 	bc_num_printDigs(n->num, n->len, emptyline);
3889252884aeSStefan Eßer }
3890252884aeSStefan Eßer 
3891252884aeSStefan Eßer void bc_num_dump(const char *varname, const BcNum *n) {
3892252884aeSStefan Eßer 
3893252884aeSStefan Eßer 	ulong i, scale = n->scale;
3894252884aeSStefan Eßer 
3895252884aeSStefan Eßer 	bc_file_printf(&vm.ferr, "\n%s = %s", varname,
389650696a6eSStefan Eßer 	               n->len ? (BC_NUM_NEG(n) ? "-" : "+") : "0 ");
3897252884aeSStefan Eßer 
3898252884aeSStefan Eßer 	for (i = n->len - 1; i < n->len; --i) {
3899252884aeSStefan Eßer 
39007e5c51e5SStefan Eßer 		if (i + 1 == BC_NUM_RDX_VAL(n))
39017e5c51e5SStefan Eßer 			bc_file_puts(&vm.ferr, bc_flush_none, ". ");
3902252884aeSStefan Eßer 
390350696a6eSStefan Eßer 		if (scale / BC_BASE_DIGS != BC_NUM_RDX_VAL(n) - i - 1)
3904252884aeSStefan Eßer 			bc_file_printf(&vm.ferr, "%lu ", (unsigned long) n->num[i]);
3905252884aeSStefan Eßer 		else {
3906252884aeSStefan Eßer 
3907252884aeSStefan Eßer 			int mod = scale % BC_BASE_DIGS;
3908252884aeSStefan Eßer 			int d = BC_BASE_DIGS - mod;
3909252884aeSStefan Eßer 			BcDig div;
3910252884aeSStefan Eßer 
3911252884aeSStefan Eßer 			if (mod != 0) {
3912252884aeSStefan Eßer 				div = n->num[i] / ((BcDig) bc_num_pow10[(ulong) d]);
3913252884aeSStefan Eßer 				bc_file_printf(&vm.ferr, "%lu", (unsigned long) div);
3914252884aeSStefan Eßer 			}
3915252884aeSStefan Eßer 
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 
3921252884aeSStefan Eßer 	bc_file_printf(&vm.ferr, "(%zu | %zu.%zu / %zu) %lu\n",
392250696a6eSStefan Eßer 	               n->scale, n->len, BC_NUM_RDX_VAL(n), n->cap,
3923252884aeSStefan Eßer 	               (unsigned long) (void*) n->num);
39247e5c51e5SStefan Eßer 
39257e5c51e5SStefan Eßer 	bc_file_flush(&vm.ferr, bc_flush_err);
3926252884aeSStefan Eßer }
3927252884aeSStefan Eßer #endif // BC_DEBUG_CODE
3928