1*5a6e8488SAndroid Build Coastguard Worker /*
2*5a6e8488SAndroid Build Coastguard Worker * *****************************************************************************
3*5a6e8488SAndroid Build Coastguard Worker *
4*5a6e8488SAndroid Build Coastguard Worker * SPDX-License-Identifier: BSD-2-Clause
5*5a6e8488SAndroid Build Coastguard Worker *
6*5a6e8488SAndroid Build Coastguard Worker * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7*5a6e8488SAndroid Build Coastguard Worker *
8*5a6e8488SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
9*5a6e8488SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
10*5a6e8488SAndroid Build Coastguard Worker *
11*5a6e8488SAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright notice, this
12*5a6e8488SAndroid Build Coastguard Worker * list of conditions and the following disclaimer.
13*5a6e8488SAndroid Build Coastguard Worker *
14*5a6e8488SAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright notice,
15*5a6e8488SAndroid Build Coastguard Worker * this list of conditions and the following disclaimer in the documentation
16*5a6e8488SAndroid Build Coastguard Worker * and/or other materials provided with the distribution.
17*5a6e8488SAndroid Build Coastguard Worker *
18*5a6e8488SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*5a6e8488SAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*5a6e8488SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*5a6e8488SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*5a6e8488SAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*5a6e8488SAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*5a6e8488SAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*5a6e8488SAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*5a6e8488SAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*5a6e8488SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*5a6e8488SAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
29*5a6e8488SAndroid Build Coastguard Worker *
30*5a6e8488SAndroid Build Coastguard Worker * *****************************************************************************
31*5a6e8488SAndroid Build Coastguard Worker *
32*5a6e8488SAndroid Build Coastguard Worker * Code for the number type.
33*5a6e8488SAndroid Build Coastguard Worker *
34*5a6e8488SAndroid Build Coastguard Worker */
35*5a6e8488SAndroid Build Coastguard Worker
36*5a6e8488SAndroid Build Coastguard Worker #include <assert.h>
37*5a6e8488SAndroid Build Coastguard Worker #include <ctype.h>
38*5a6e8488SAndroid Build Coastguard Worker #include <stdbool.h>
39*5a6e8488SAndroid Build Coastguard Worker #include <stdlib.h>
40*5a6e8488SAndroid Build Coastguard Worker #include <string.h>
41*5a6e8488SAndroid Build Coastguard Worker #include <setjmp.h>
42*5a6e8488SAndroid Build Coastguard Worker #include <limits.h>
43*5a6e8488SAndroid Build Coastguard Worker
44*5a6e8488SAndroid Build Coastguard Worker #include <num.h>
45*5a6e8488SAndroid Build Coastguard Worker #include <rand.h>
46*5a6e8488SAndroid Build Coastguard Worker #include <vm.h>
47*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
48*5a6e8488SAndroid Build Coastguard Worker #include <library.h>
49*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
50*5a6e8488SAndroid Build Coastguard Worker
51*5a6e8488SAndroid Build Coastguard Worker // Before you try to understand this code, see the development manual
52*5a6e8488SAndroid Build Coastguard Worker // (manuals/development.md#numbers).
53*5a6e8488SAndroid Build Coastguard Worker
54*5a6e8488SAndroid Build Coastguard Worker static void
55*5a6e8488SAndroid Build Coastguard Worker bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale);
56*5a6e8488SAndroid Build Coastguard Worker
57*5a6e8488SAndroid Build Coastguard Worker /**
58*5a6e8488SAndroid Build Coastguard Worker * Multiply two numbers and throw a math error if they overflow.
59*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
60*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
61*5a6e8488SAndroid Build Coastguard Worker * @return The product of the two operands.
62*5a6e8488SAndroid Build Coastguard Worker */
63*5a6e8488SAndroid Build Coastguard Worker static inline size_t
bc_num_mulOverflow(size_t a,size_t b)64*5a6e8488SAndroid Build Coastguard Worker bc_num_mulOverflow(size_t a, size_t b)
65*5a6e8488SAndroid Build Coastguard Worker {
66*5a6e8488SAndroid Build Coastguard Worker size_t res = a * b;
67*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(BC_VM_MUL_OVERFLOW(a, b, res))) bc_err(BC_ERR_MATH_OVERFLOW);
68*5a6e8488SAndroid Build Coastguard Worker return res;
69*5a6e8488SAndroid Build Coastguard Worker }
70*5a6e8488SAndroid Build Coastguard Worker
71*5a6e8488SAndroid Build Coastguard Worker /**
72*5a6e8488SAndroid Build Coastguard Worker * Conditionally negate @a n based on @a neg. Algorithm taken from
73*5a6e8488SAndroid Build Coastguard Worker * https://graphics.stanford.edu/~seander/bithacks.html#ConditionalNegate .
74*5a6e8488SAndroid Build Coastguard Worker * @param n The value to turn into a signed value and negate.
75*5a6e8488SAndroid Build Coastguard Worker * @param neg The condition to negate or not.
76*5a6e8488SAndroid Build Coastguard Worker */
77*5a6e8488SAndroid Build Coastguard Worker static inline ssize_t
bc_num_neg(size_t n,bool neg)78*5a6e8488SAndroid Build Coastguard Worker bc_num_neg(size_t n, bool neg)
79*5a6e8488SAndroid Build Coastguard Worker {
80*5a6e8488SAndroid Build Coastguard Worker return (((ssize_t) n) ^ -((ssize_t) neg)) + neg;
81*5a6e8488SAndroid Build Coastguard Worker }
82*5a6e8488SAndroid Build Coastguard Worker
83*5a6e8488SAndroid Build Coastguard Worker /**
84*5a6e8488SAndroid Build Coastguard Worker * Compare a BcNum against zero.
85*5a6e8488SAndroid Build Coastguard Worker * @param n The number to compare.
86*5a6e8488SAndroid Build Coastguard Worker * @return -1 if the number is less than 0, 1 if greater, and 0 if equal.
87*5a6e8488SAndroid Build Coastguard Worker */
88*5a6e8488SAndroid Build Coastguard Worker ssize_t
bc_num_cmpZero(const BcNum * n)89*5a6e8488SAndroid Build Coastguard Worker bc_num_cmpZero(const BcNum* n)
90*5a6e8488SAndroid Build Coastguard Worker {
91*5a6e8488SAndroid Build Coastguard Worker return bc_num_neg((n)->len != 0, BC_NUM_NEG(n));
92*5a6e8488SAndroid Build Coastguard Worker }
93*5a6e8488SAndroid Build Coastguard Worker
94*5a6e8488SAndroid Build Coastguard Worker /**
95*5a6e8488SAndroid Build Coastguard Worker * Return the number of integer limbs in a BcNum. This is the opposite of rdx.
96*5a6e8488SAndroid Build Coastguard Worker * @param n The number to return the amount of integer limbs for.
97*5a6e8488SAndroid Build Coastguard Worker * @return The amount of integer limbs in @a n.
98*5a6e8488SAndroid Build Coastguard Worker */
99*5a6e8488SAndroid Build Coastguard Worker static inline size_t
bc_num_int(const BcNum * n)100*5a6e8488SAndroid Build Coastguard Worker bc_num_int(const BcNum* n)
101*5a6e8488SAndroid Build Coastguard Worker {
102*5a6e8488SAndroid Build Coastguard Worker return n->len ? n->len - BC_NUM_RDX_VAL(n) : 0;
103*5a6e8488SAndroid Build Coastguard Worker }
104*5a6e8488SAndroid Build Coastguard Worker
105*5a6e8488SAndroid Build Coastguard Worker /**
106*5a6e8488SAndroid Build Coastguard Worker * Expand a number's allocation capacity to at least req limbs.
107*5a6e8488SAndroid Build Coastguard Worker * @param n The number to expand.
108*5a6e8488SAndroid Build Coastguard Worker * @param req The number limbs to expand the allocation capacity to.
109*5a6e8488SAndroid Build Coastguard Worker */
110*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_expand(BcNum * restrict n,size_t req)111*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(BcNum* restrict n, size_t req)
112*5a6e8488SAndroid Build Coastguard Worker {
113*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
114*5a6e8488SAndroid Build Coastguard Worker
115*5a6e8488SAndroid Build Coastguard Worker req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
116*5a6e8488SAndroid Build Coastguard Worker
117*5a6e8488SAndroid Build Coastguard Worker if (req > n->cap)
118*5a6e8488SAndroid Build Coastguard Worker {
119*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
120*5a6e8488SAndroid Build Coastguard Worker
121*5a6e8488SAndroid Build Coastguard Worker n->num = bc_vm_realloc(n->num, BC_NUM_SIZE(req));
122*5a6e8488SAndroid Build Coastguard Worker n->cap = req;
123*5a6e8488SAndroid Build Coastguard Worker
124*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
125*5a6e8488SAndroid Build Coastguard Worker }
126*5a6e8488SAndroid Build Coastguard Worker }
127*5a6e8488SAndroid Build Coastguard Worker
128*5a6e8488SAndroid Build Coastguard Worker /**
129*5a6e8488SAndroid Build Coastguard Worker * Set a number to 0 with the specified scale.
130*5a6e8488SAndroid Build Coastguard Worker * @param n The number to set to zero.
131*5a6e8488SAndroid Build Coastguard Worker * @param scale The scale to set the number to.
132*5a6e8488SAndroid Build Coastguard Worker */
133*5a6e8488SAndroid Build Coastguard Worker static inline void
bc_num_setToZero(BcNum * restrict n,size_t scale)134*5a6e8488SAndroid Build Coastguard Worker bc_num_setToZero(BcNum* restrict n, size_t scale)
135*5a6e8488SAndroid Build Coastguard Worker {
136*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
137*5a6e8488SAndroid Build Coastguard Worker n->scale = scale;
138*5a6e8488SAndroid Build Coastguard Worker n->len = n->rdx = 0;
139*5a6e8488SAndroid Build Coastguard Worker }
140*5a6e8488SAndroid Build Coastguard Worker
141*5a6e8488SAndroid Build Coastguard Worker void
bc_num_zero(BcNum * restrict n)142*5a6e8488SAndroid Build Coastguard Worker bc_num_zero(BcNum* restrict n)
143*5a6e8488SAndroid Build Coastguard Worker {
144*5a6e8488SAndroid Build Coastguard Worker bc_num_setToZero(n, 0);
145*5a6e8488SAndroid Build Coastguard Worker }
146*5a6e8488SAndroid Build Coastguard Worker
147*5a6e8488SAndroid Build Coastguard Worker void
bc_num_one(BcNum * restrict n)148*5a6e8488SAndroid Build Coastguard Worker bc_num_one(BcNum* restrict n)
149*5a6e8488SAndroid Build Coastguard Worker {
150*5a6e8488SAndroid Build Coastguard Worker bc_num_zero(n);
151*5a6e8488SAndroid Build Coastguard Worker n->len = 1;
152*5a6e8488SAndroid Build Coastguard Worker n->num[0] = 1;
153*5a6e8488SAndroid Build Coastguard Worker }
154*5a6e8488SAndroid Build Coastguard Worker
155*5a6e8488SAndroid Build Coastguard Worker /**
156*5a6e8488SAndroid Build Coastguard Worker * "Cleans" a number, which means reducing the length if the most significant
157*5a6e8488SAndroid Build Coastguard Worker * limbs are zero.
158*5a6e8488SAndroid Build Coastguard Worker * @param n The number to clean.
159*5a6e8488SAndroid Build Coastguard Worker */
160*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_clean(BcNum * restrict n)161*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(BcNum* restrict n)
162*5a6e8488SAndroid Build Coastguard Worker {
163*5a6e8488SAndroid Build Coastguard Worker // Reduce the length.
164*5a6e8488SAndroid Build Coastguard Worker while (BC_NUM_NONZERO(n) && !n->num[n->len - 1])
165*5a6e8488SAndroid Build Coastguard Worker {
166*5a6e8488SAndroid Build Coastguard Worker n->len -= 1;
167*5a6e8488SAndroid Build Coastguard Worker }
168*5a6e8488SAndroid Build Coastguard Worker
169*5a6e8488SAndroid Build Coastguard Worker // Special cases.
170*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(n)) n->rdx = 0;
171*5a6e8488SAndroid Build Coastguard Worker else
172*5a6e8488SAndroid Build Coastguard Worker {
173*5a6e8488SAndroid Build Coastguard Worker // len must be at least as much as rdx.
174*5a6e8488SAndroid Build Coastguard Worker size_t rdx = BC_NUM_RDX_VAL(n);
175*5a6e8488SAndroid Build Coastguard Worker if (n->len < rdx) n->len = rdx;
176*5a6e8488SAndroid Build Coastguard Worker }
177*5a6e8488SAndroid Build Coastguard Worker }
178*5a6e8488SAndroid Build Coastguard Worker
179*5a6e8488SAndroid Build Coastguard Worker /**
180*5a6e8488SAndroid Build Coastguard Worker * Returns the log base 10 of @a i. I could have done this with floating-point
181*5a6e8488SAndroid Build Coastguard Worker * math, and in fact, I originally did. However, that was the only
182*5a6e8488SAndroid Build Coastguard Worker * floating-point code in the entire codebase, and I decided I didn't want any.
183*5a6e8488SAndroid Build Coastguard Worker * This is fast enough. Also, it might handle larger numbers better.
184*5a6e8488SAndroid Build Coastguard Worker * @param i The number to return the log base 10 of.
185*5a6e8488SAndroid Build Coastguard Worker * @return The log base 10 of @a i.
186*5a6e8488SAndroid Build Coastguard Worker */
187*5a6e8488SAndroid Build Coastguard Worker static size_t
bc_num_log10(size_t i)188*5a6e8488SAndroid Build Coastguard Worker bc_num_log10(size_t i)
189*5a6e8488SAndroid Build Coastguard Worker {
190*5a6e8488SAndroid Build Coastguard Worker size_t len;
191*5a6e8488SAndroid Build Coastguard Worker
192*5a6e8488SAndroid Build Coastguard Worker for (len = 1; i; i /= BC_BASE, ++len)
193*5a6e8488SAndroid Build Coastguard Worker {
194*5a6e8488SAndroid Build Coastguard Worker continue;
195*5a6e8488SAndroid Build Coastguard Worker }
196*5a6e8488SAndroid Build Coastguard Worker
197*5a6e8488SAndroid Build Coastguard Worker assert(len - 1 <= BC_BASE_DIGS + 1);
198*5a6e8488SAndroid Build Coastguard Worker
199*5a6e8488SAndroid Build Coastguard Worker return len - 1;
200*5a6e8488SAndroid Build Coastguard Worker }
201*5a6e8488SAndroid Build Coastguard Worker
202*5a6e8488SAndroid Build Coastguard Worker /**
203*5a6e8488SAndroid Build Coastguard Worker * Returns the number of decimal digits in a limb that are zero starting at the
204*5a6e8488SAndroid Build Coastguard Worker * most significant digits. This basically returns how much of the limb is used.
205*5a6e8488SAndroid Build Coastguard Worker * @param n The number.
206*5a6e8488SAndroid Build Coastguard Worker * @return The number of decimal digits that are 0 starting at the most
207*5a6e8488SAndroid Build Coastguard Worker * significant digits.
208*5a6e8488SAndroid Build Coastguard Worker */
209*5a6e8488SAndroid Build Coastguard Worker static inline size_t
bc_num_zeroDigits(const BcDig * n)210*5a6e8488SAndroid Build Coastguard Worker bc_num_zeroDigits(const BcDig* n)
211*5a6e8488SAndroid Build Coastguard Worker {
212*5a6e8488SAndroid Build Coastguard Worker assert(*n >= 0);
213*5a6e8488SAndroid Build Coastguard Worker assert(((size_t) *n) < BC_BASE_POW);
214*5a6e8488SAndroid Build Coastguard Worker return BC_BASE_DIGS - bc_num_log10((size_t) *n);
215*5a6e8488SAndroid Build Coastguard Worker }
216*5a6e8488SAndroid Build Coastguard Worker
217*5a6e8488SAndroid Build Coastguard Worker /**
218*5a6e8488SAndroid Build Coastguard Worker * Returns the power of 10 that the least significant limb should be multiplied
219*5a6e8488SAndroid Build Coastguard Worker * by to put its digits in the right place. For example, if the scale only
220*5a6e8488SAndroid Build Coastguard Worker * reaches 8 places into the limb, this will return 1 (because it should be
221*5a6e8488SAndroid Build Coastguard Worker * multiplied by 10^1) to put the number in the correct place.
222*5a6e8488SAndroid Build Coastguard Worker * @param scale The scale.
223*5a6e8488SAndroid Build Coastguard Worker * @return The power of 10 that the least significant limb should be
224*5a6e8488SAndroid Build Coastguard Worker * multiplied by
225*5a6e8488SAndroid Build Coastguard Worker */
226*5a6e8488SAndroid Build Coastguard Worker static inline size_t
bc_num_leastSigPow(size_t scale)227*5a6e8488SAndroid Build Coastguard Worker bc_num_leastSigPow(size_t scale)
228*5a6e8488SAndroid Build Coastguard Worker {
229*5a6e8488SAndroid Build Coastguard Worker size_t digs;
230*5a6e8488SAndroid Build Coastguard Worker
231*5a6e8488SAndroid Build Coastguard Worker digs = scale % BC_BASE_DIGS;
232*5a6e8488SAndroid Build Coastguard Worker digs = digs != 0 ? BC_BASE_DIGS - digs : 0;
233*5a6e8488SAndroid Build Coastguard Worker
234*5a6e8488SAndroid Build Coastguard Worker return bc_num_pow10[digs];
235*5a6e8488SAndroid Build Coastguard Worker }
236*5a6e8488SAndroid Build Coastguard Worker
237*5a6e8488SAndroid Build Coastguard Worker /**
238*5a6e8488SAndroid Build Coastguard Worker * Return the total number of integer digits in a number. This is the opposite
239*5a6e8488SAndroid Build Coastguard Worker * of scale, like bc_num_int() is the opposite of rdx.
240*5a6e8488SAndroid Build Coastguard Worker * @param n The number.
241*5a6e8488SAndroid Build Coastguard Worker * @return The number of integer digits in @a n.
242*5a6e8488SAndroid Build Coastguard Worker */
243*5a6e8488SAndroid Build Coastguard Worker static size_t
bc_num_intDigits(const BcNum * n)244*5a6e8488SAndroid Build Coastguard Worker bc_num_intDigits(const BcNum* n)
245*5a6e8488SAndroid Build Coastguard Worker {
246*5a6e8488SAndroid Build Coastguard Worker size_t digits = bc_num_int(n) * BC_BASE_DIGS;
247*5a6e8488SAndroid Build Coastguard Worker if (digits > 0) digits -= bc_num_zeroDigits(n->num + n->len - 1);
248*5a6e8488SAndroid Build Coastguard Worker return digits;
249*5a6e8488SAndroid Build Coastguard Worker }
250*5a6e8488SAndroid Build Coastguard Worker
251*5a6e8488SAndroid Build Coastguard Worker /**
252*5a6e8488SAndroid Build Coastguard Worker * Returns the number of limbs of a number that are non-zero starting at the
253*5a6e8488SAndroid Build Coastguard Worker * most significant limbs. This expects that there are *no* integer limbs in the
254*5a6e8488SAndroid Build Coastguard Worker * number because it is specifically to figure out how many zero limbs after the
255*5a6e8488SAndroid Build Coastguard Worker * decimal place to ignore. If there are zero limbs after non-zero limbs, they
256*5a6e8488SAndroid Build Coastguard Worker * are counted as non-zero limbs.
257*5a6e8488SAndroid Build Coastguard Worker * @param n The number.
258*5a6e8488SAndroid Build Coastguard Worker * @return The number of non-zero limbs after the decimal point.
259*5a6e8488SAndroid Build Coastguard Worker */
260*5a6e8488SAndroid Build Coastguard Worker static size_t
bc_num_nonZeroLen(const BcNum * restrict n)261*5a6e8488SAndroid Build Coastguard Worker bc_num_nonZeroLen(const BcNum* restrict n)
262*5a6e8488SAndroid Build Coastguard Worker {
263*5a6e8488SAndroid Build Coastguard Worker size_t i, len = n->len;
264*5a6e8488SAndroid Build Coastguard Worker
265*5a6e8488SAndroid Build Coastguard Worker assert(len == BC_NUM_RDX_VAL(n));
266*5a6e8488SAndroid Build Coastguard Worker
267*5a6e8488SAndroid Build Coastguard Worker for (i = len - 1; i < len && !n->num[i]; --i)
268*5a6e8488SAndroid Build Coastguard Worker {
269*5a6e8488SAndroid Build Coastguard Worker continue;
270*5a6e8488SAndroid Build Coastguard Worker }
271*5a6e8488SAndroid Build Coastguard Worker
272*5a6e8488SAndroid Build Coastguard Worker assert(i + 1 > 0);
273*5a6e8488SAndroid Build Coastguard Worker
274*5a6e8488SAndroid Build Coastguard Worker return i + 1;
275*5a6e8488SAndroid Build Coastguard Worker }
276*5a6e8488SAndroid Build Coastguard Worker
277*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
278*5a6e8488SAndroid Build Coastguard Worker
279*5a6e8488SAndroid Build Coastguard Worker /**
280*5a6e8488SAndroid Build Coastguard Worker * Returns the power of 10 that a number with an absolute value less than 1
281*5a6e8488SAndroid Build Coastguard Worker * needs to be multiplied by in order to be greater than 1 or less than -1.
282*5a6e8488SAndroid Build Coastguard Worker * @param n The number.
283*5a6e8488SAndroid Build Coastguard Worker * @return The power of 10 that a number greater than 1 and less than -1 must
284*5a6e8488SAndroid Build Coastguard Worker * be multiplied by to be greater than 1 or less than -1.
285*5a6e8488SAndroid Build Coastguard Worker */
286*5a6e8488SAndroid Build Coastguard Worker static size_t
bc_num_negPow10(const BcNum * restrict n)287*5a6e8488SAndroid Build Coastguard Worker bc_num_negPow10(const BcNum* restrict n)
288*5a6e8488SAndroid Build Coastguard Worker {
289*5a6e8488SAndroid Build Coastguard Worker // Figure out how many limbs after the decimal point is zero.
290*5a6e8488SAndroid Build Coastguard Worker size_t i, places, idx = bc_num_nonZeroLen(n) - 1;
291*5a6e8488SAndroid Build Coastguard Worker
292*5a6e8488SAndroid Build Coastguard Worker places = 1;
293*5a6e8488SAndroid Build Coastguard Worker
294*5a6e8488SAndroid Build Coastguard Worker // Figure out how much in the last limb is zero.
295*5a6e8488SAndroid Build Coastguard Worker for (i = BC_BASE_DIGS - 1; i < BC_BASE_DIGS; --i)
296*5a6e8488SAndroid Build Coastguard Worker {
297*5a6e8488SAndroid Build Coastguard Worker if (bc_num_pow10[i] > (BcBigDig) n->num[idx]) places += 1;
298*5a6e8488SAndroid Build Coastguard Worker else break;
299*5a6e8488SAndroid Build Coastguard Worker }
300*5a6e8488SAndroid Build Coastguard Worker
301*5a6e8488SAndroid Build Coastguard Worker // Calculate the combination of zero limbs and zero digits in the last
302*5a6e8488SAndroid Build Coastguard Worker // limb.
303*5a6e8488SAndroid Build Coastguard Worker return places + (BC_NUM_RDX_VAL(n) - (idx + 1)) * BC_BASE_DIGS;
304*5a6e8488SAndroid Build Coastguard Worker }
305*5a6e8488SAndroid Build Coastguard Worker
306*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
307*5a6e8488SAndroid Build Coastguard Worker
308*5a6e8488SAndroid Build Coastguard Worker /**
309*5a6e8488SAndroid Build Coastguard Worker * Performs a one-limb add with a carry.
310*5a6e8488SAndroid Build Coastguard Worker * @param a The first limb.
311*5a6e8488SAndroid Build Coastguard Worker * @param b The second limb.
312*5a6e8488SAndroid Build Coastguard Worker * @param carry An in/out parameter; the carry in from the previous add and the
313*5a6e8488SAndroid Build Coastguard Worker * carry out from this add.
314*5a6e8488SAndroid Build Coastguard Worker * @return The resulting limb sum.
315*5a6e8488SAndroid Build Coastguard Worker */
316*5a6e8488SAndroid Build Coastguard Worker static BcDig
bc_num_addDigits(BcDig a,BcDig b,bool * carry)317*5a6e8488SAndroid Build Coastguard Worker bc_num_addDigits(BcDig a, BcDig b, bool* carry)
318*5a6e8488SAndroid Build Coastguard Worker {
319*5a6e8488SAndroid Build Coastguard Worker assert(((BcBigDig) BC_BASE_POW) * 2 == ((BcDig) BC_BASE_POW) * 2);
320*5a6e8488SAndroid Build Coastguard Worker assert(a < BC_BASE_POW && a >= 0);
321*5a6e8488SAndroid Build Coastguard Worker assert(b < BC_BASE_POW && b >= 0);
322*5a6e8488SAndroid Build Coastguard Worker
323*5a6e8488SAndroid Build Coastguard Worker a += b + *carry;
324*5a6e8488SAndroid Build Coastguard Worker *carry = (a >= BC_BASE_POW);
325*5a6e8488SAndroid Build Coastguard Worker if (*carry) a -= BC_BASE_POW;
326*5a6e8488SAndroid Build Coastguard Worker
327*5a6e8488SAndroid Build Coastguard Worker assert(a >= 0);
328*5a6e8488SAndroid Build Coastguard Worker assert(a < BC_BASE_POW);
329*5a6e8488SAndroid Build Coastguard Worker
330*5a6e8488SAndroid Build Coastguard Worker return a;
331*5a6e8488SAndroid Build Coastguard Worker }
332*5a6e8488SAndroid Build Coastguard Worker
333*5a6e8488SAndroid Build Coastguard Worker /**
334*5a6e8488SAndroid Build Coastguard Worker * Performs a one-limb subtract with a carry.
335*5a6e8488SAndroid Build Coastguard Worker * @param a The first limb.
336*5a6e8488SAndroid Build Coastguard Worker * @param b The second limb.
337*5a6e8488SAndroid Build Coastguard Worker * @param carry An in/out parameter; the carry in from the previous subtract
338*5a6e8488SAndroid Build Coastguard Worker * and the carry out from this subtract.
339*5a6e8488SAndroid Build Coastguard Worker * @return The resulting limb difference.
340*5a6e8488SAndroid Build Coastguard Worker */
341*5a6e8488SAndroid Build Coastguard Worker static BcDig
bc_num_subDigits(BcDig a,BcDig b,bool * carry)342*5a6e8488SAndroid Build Coastguard Worker bc_num_subDigits(BcDig a, BcDig b, bool* carry)
343*5a6e8488SAndroid Build Coastguard Worker {
344*5a6e8488SAndroid Build Coastguard Worker assert(a < BC_BASE_POW && a >= 0);
345*5a6e8488SAndroid Build Coastguard Worker assert(b < BC_BASE_POW && b >= 0);
346*5a6e8488SAndroid Build Coastguard Worker
347*5a6e8488SAndroid Build Coastguard Worker b += *carry;
348*5a6e8488SAndroid Build Coastguard Worker *carry = (a < b);
349*5a6e8488SAndroid Build Coastguard Worker if (*carry) a += BC_BASE_POW;
350*5a6e8488SAndroid Build Coastguard Worker
351*5a6e8488SAndroid Build Coastguard Worker assert(a - b >= 0);
352*5a6e8488SAndroid Build Coastguard Worker assert(a - b < BC_BASE_POW);
353*5a6e8488SAndroid Build Coastguard Worker
354*5a6e8488SAndroid Build Coastguard Worker return a - b;
355*5a6e8488SAndroid Build Coastguard Worker }
356*5a6e8488SAndroid Build Coastguard Worker
357*5a6e8488SAndroid Build Coastguard Worker /**
358*5a6e8488SAndroid Build Coastguard Worker * Add two BcDig arrays and store the result in the first array.
359*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand and out array.
360*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
361*5a6e8488SAndroid Build Coastguard Worker * @param len The length of @a b.
362*5a6e8488SAndroid Build Coastguard Worker */
363*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_addArrays(BcDig * restrict a,const BcDig * restrict b,size_t len)364*5a6e8488SAndroid Build Coastguard Worker bc_num_addArrays(BcDig* restrict a, const BcDig* restrict b, size_t len)
365*5a6e8488SAndroid Build Coastguard Worker {
366*5a6e8488SAndroid Build Coastguard Worker size_t i;
367*5a6e8488SAndroid Build Coastguard Worker bool carry = false;
368*5a6e8488SAndroid Build Coastguard Worker
369*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < len; ++i)
370*5a6e8488SAndroid Build Coastguard Worker {
371*5a6e8488SAndroid Build Coastguard Worker a[i] = bc_num_addDigits(a[i], b[i], &carry);
372*5a6e8488SAndroid Build Coastguard Worker }
373*5a6e8488SAndroid Build Coastguard Worker
374*5a6e8488SAndroid Build Coastguard Worker // Take care of the extra limbs in the bigger array.
375*5a6e8488SAndroid Build Coastguard Worker for (; carry; ++i)
376*5a6e8488SAndroid Build Coastguard Worker {
377*5a6e8488SAndroid Build Coastguard Worker a[i] = bc_num_addDigits(a[i], 0, &carry);
378*5a6e8488SAndroid Build Coastguard Worker }
379*5a6e8488SAndroid Build Coastguard Worker }
380*5a6e8488SAndroid Build Coastguard Worker
381*5a6e8488SAndroid Build Coastguard Worker /**
382*5a6e8488SAndroid Build Coastguard Worker * Subtract two BcDig arrays and store the result in the first array.
383*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand and out array.
384*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
385*5a6e8488SAndroid Build Coastguard Worker * @param len The length of @a b.
386*5a6e8488SAndroid Build Coastguard Worker */
387*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_subArrays(BcDig * restrict a,const BcDig * restrict b,size_t len)388*5a6e8488SAndroid Build Coastguard Worker bc_num_subArrays(BcDig* restrict a, const BcDig* restrict b, size_t len)
389*5a6e8488SAndroid Build Coastguard Worker {
390*5a6e8488SAndroid Build Coastguard Worker size_t i;
391*5a6e8488SAndroid Build Coastguard Worker bool carry = false;
392*5a6e8488SAndroid Build Coastguard Worker
393*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < len; ++i)
394*5a6e8488SAndroid Build Coastguard Worker {
395*5a6e8488SAndroid Build Coastguard Worker a[i] = bc_num_subDigits(a[i], b[i], &carry);
396*5a6e8488SAndroid Build Coastguard Worker }
397*5a6e8488SAndroid Build Coastguard Worker
398*5a6e8488SAndroid Build Coastguard Worker // Take care of the extra limbs in the bigger array.
399*5a6e8488SAndroid Build Coastguard Worker for (; carry; ++i)
400*5a6e8488SAndroid Build Coastguard Worker {
401*5a6e8488SAndroid Build Coastguard Worker a[i] = bc_num_subDigits(a[i], 0, &carry);
402*5a6e8488SAndroid Build Coastguard Worker }
403*5a6e8488SAndroid Build Coastguard Worker }
404*5a6e8488SAndroid Build Coastguard Worker
405*5a6e8488SAndroid Build Coastguard Worker /**
406*5a6e8488SAndroid Build Coastguard Worker * Multiply a BcNum array by a one-limb number. This is a faster version of
407*5a6e8488SAndroid Build Coastguard Worker * multiplication for when we can use it.
408*5a6e8488SAndroid Build Coastguard Worker * @param a The BcNum to multiply by the one-limb number.
409*5a6e8488SAndroid Build Coastguard Worker * @param b The one limb of the one-limb number.
410*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
411*5a6e8488SAndroid Build Coastguard Worker */
412*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_mulArray(const BcNum * restrict a,BcBigDig b,BcNum * restrict c)413*5a6e8488SAndroid Build Coastguard Worker bc_num_mulArray(const BcNum* restrict a, BcBigDig b, BcNum* restrict c)
414*5a6e8488SAndroid Build Coastguard Worker {
415*5a6e8488SAndroid Build Coastguard Worker size_t i;
416*5a6e8488SAndroid Build Coastguard Worker BcBigDig carry = 0;
417*5a6e8488SAndroid Build Coastguard Worker
418*5a6e8488SAndroid Build Coastguard Worker assert(b <= BC_BASE_POW);
419*5a6e8488SAndroid Build Coastguard Worker
420*5a6e8488SAndroid Build Coastguard Worker // Make sure the return parameter is big enough.
421*5a6e8488SAndroid Build Coastguard Worker if (a->len + 1 > c->cap) bc_num_expand(c, a->len + 1);
422*5a6e8488SAndroid Build Coastguard Worker
423*5a6e8488SAndroid Build Coastguard Worker // We want the entire return parameter to be zero for cleaning later.
424*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
425*5a6e8488SAndroid Build Coastguard Worker memset(c->num, 0, BC_NUM_SIZE(c->cap));
426*5a6e8488SAndroid Build Coastguard Worker
427*5a6e8488SAndroid Build Coastguard Worker // Actual multiplication loop.
428*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < a->len; ++i)
429*5a6e8488SAndroid Build Coastguard Worker {
430*5a6e8488SAndroid Build Coastguard Worker BcBigDig in = ((BcBigDig) a->num[i]) * b + carry;
431*5a6e8488SAndroid Build Coastguard Worker c->num[i] = in % BC_BASE_POW;
432*5a6e8488SAndroid Build Coastguard Worker carry = in / BC_BASE_POW;
433*5a6e8488SAndroid Build Coastguard Worker }
434*5a6e8488SAndroid Build Coastguard Worker
435*5a6e8488SAndroid Build Coastguard Worker assert(carry < BC_BASE_POW);
436*5a6e8488SAndroid Build Coastguard Worker
437*5a6e8488SAndroid Build Coastguard Worker // Finishing touches.
438*5a6e8488SAndroid Build Coastguard Worker c->num[i] = (BcDig) carry;
439*5a6e8488SAndroid Build Coastguard Worker assert(c->num[i] >= 0 && c->num[i] < BC_BASE_POW);
440*5a6e8488SAndroid Build Coastguard Worker c->len = a->len;
441*5a6e8488SAndroid Build Coastguard Worker c->len += (carry != 0);
442*5a6e8488SAndroid Build Coastguard Worker
443*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(c);
444*5a6e8488SAndroid Build Coastguard Worker
445*5a6e8488SAndroid Build Coastguard Worker // Postconditions.
446*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
447*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
448*5a6e8488SAndroid Build Coastguard Worker assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
449*5a6e8488SAndroid Build Coastguard Worker }
450*5a6e8488SAndroid Build Coastguard Worker
451*5a6e8488SAndroid Build Coastguard Worker /**
452*5a6e8488SAndroid Build Coastguard Worker * Divide a BcNum array by a one-limb number. This is a faster version of divide
453*5a6e8488SAndroid Build Coastguard Worker * for when we can use it.
454*5a6e8488SAndroid Build Coastguard Worker * @param a The BcNum to multiply by the one-limb number.
455*5a6e8488SAndroid Build Coastguard Worker * @param b The one limb of the one-limb number.
456*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter for the quotient.
457*5a6e8488SAndroid Build Coastguard Worker * @param rem The return parameter for the remainder.
458*5a6e8488SAndroid Build Coastguard Worker */
459*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_divArray(const BcNum * restrict a,BcBigDig b,BcNum * restrict c,BcBigDig * rem)460*5a6e8488SAndroid Build Coastguard Worker bc_num_divArray(const BcNum* restrict a, BcBigDig b, BcNum* restrict c,
461*5a6e8488SAndroid Build Coastguard Worker BcBigDig* rem)
462*5a6e8488SAndroid Build Coastguard Worker {
463*5a6e8488SAndroid Build Coastguard Worker size_t i;
464*5a6e8488SAndroid Build Coastguard Worker BcBigDig carry = 0;
465*5a6e8488SAndroid Build Coastguard Worker
466*5a6e8488SAndroid Build Coastguard Worker assert(c->cap >= a->len);
467*5a6e8488SAndroid Build Coastguard Worker
468*5a6e8488SAndroid Build Coastguard Worker // Actual division loop.
469*5a6e8488SAndroid Build Coastguard Worker for (i = a->len - 1; i < a->len; --i)
470*5a6e8488SAndroid Build Coastguard Worker {
471*5a6e8488SAndroid Build Coastguard Worker BcBigDig in = ((BcBigDig) a->num[i]) + carry * BC_BASE_POW;
472*5a6e8488SAndroid Build Coastguard Worker assert(in / b < BC_BASE_POW);
473*5a6e8488SAndroid Build Coastguard Worker c->num[i] = (BcDig) (in / b);
474*5a6e8488SAndroid Build Coastguard Worker assert(c->num[i] >= 0 && c->num[i] < BC_BASE_POW);
475*5a6e8488SAndroid Build Coastguard Worker carry = in % b;
476*5a6e8488SAndroid Build Coastguard Worker }
477*5a6e8488SAndroid Build Coastguard Worker
478*5a6e8488SAndroid Build Coastguard Worker // Finishing touches.
479*5a6e8488SAndroid Build Coastguard Worker c->len = a->len;
480*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(c);
481*5a6e8488SAndroid Build Coastguard Worker *rem = carry;
482*5a6e8488SAndroid Build Coastguard Worker
483*5a6e8488SAndroid Build Coastguard Worker // Postconditions.
484*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
485*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
486*5a6e8488SAndroid Build Coastguard Worker assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
487*5a6e8488SAndroid Build Coastguard Worker }
488*5a6e8488SAndroid Build Coastguard Worker
489*5a6e8488SAndroid Build Coastguard Worker /**
490*5a6e8488SAndroid Build Coastguard Worker * Compare two BcDig arrays and return >0 if @a b is greater, <0 if @a b is
491*5a6e8488SAndroid Build Coastguard Worker * less, and 0 if equal. Both @a a and @a b must have the same length.
492*5a6e8488SAndroid Build Coastguard Worker * @param a The first array.
493*5a6e8488SAndroid Build Coastguard Worker * @param b The second array.
494*5a6e8488SAndroid Build Coastguard Worker * @param len The minimum length of the arrays.
495*5a6e8488SAndroid Build Coastguard Worker */
496*5a6e8488SAndroid Build Coastguard Worker static ssize_t
bc_num_compare(const BcDig * restrict a,const BcDig * restrict b,size_t len)497*5a6e8488SAndroid Build Coastguard Worker bc_num_compare(const BcDig* restrict a, const BcDig* restrict b, size_t len)
498*5a6e8488SAndroid Build Coastguard Worker {
499*5a6e8488SAndroid Build Coastguard Worker size_t i;
500*5a6e8488SAndroid Build Coastguard Worker BcDig c = 0;
501*5a6e8488SAndroid Build Coastguard Worker for (i = len - 1; i < len && !(c = a[i] - b[i]); --i)
502*5a6e8488SAndroid Build Coastguard Worker {
503*5a6e8488SAndroid Build Coastguard Worker continue;
504*5a6e8488SAndroid Build Coastguard Worker }
505*5a6e8488SAndroid Build Coastguard Worker return bc_num_neg(i + 1, c < 0);
506*5a6e8488SAndroid Build Coastguard Worker }
507*5a6e8488SAndroid Build Coastguard Worker
508*5a6e8488SAndroid Build Coastguard Worker ssize_t
bc_num_cmp(const BcNum * a,const BcNum * b)509*5a6e8488SAndroid Build Coastguard Worker bc_num_cmp(const BcNum* a, const BcNum* b)
510*5a6e8488SAndroid Build Coastguard Worker {
511*5a6e8488SAndroid Build Coastguard Worker size_t i, min, a_int, b_int, diff, ardx, brdx;
512*5a6e8488SAndroid Build Coastguard Worker BcDig* max_num;
513*5a6e8488SAndroid Build Coastguard Worker BcDig* min_num;
514*5a6e8488SAndroid Build Coastguard Worker bool a_max, neg = false;
515*5a6e8488SAndroid Build Coastguard Worker ssize_t cmp;
516*5a6e8488SAndroid Build Coastguard Worker
517*5a6e8488SAndroid Build Coastguard Worker assert(a != NULL && b != NULL);
518*5a6e8488SAndroid Build Coastguard Worker
519*5a6e8488SAndroid Build Coastguard Worker // Same num? Equal.
520*5a6e8488SAndroid Build Coastguard Worker if (a == b) return 0;
521*5a6e8488SAndroid Build Coastguard Worker
522*5a6e8488SAndroid Build Coastguard Worker // Easy cases.
523*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(a)) return bc_num_neg(b->len != 0, !BC_NUM_NEG(b));
524*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(b)) return bc_num_cmpZero(a);
525*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NEG(a))
526*5a6e8488SAndroid Build Coastguard Worker {
527*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NEG(b)) neg = true;
528*5a6e8488SAndroid Build Coastguard Worker else return -1;
529*5a6e8488SAndroid Build Coastguard Worker }
530*5a6e8488SAndroid Build Coastguard Worker else if (BC_NUM_NEG(b)) return 1;
531*5a6e8488SAndroid Build Coastguard Worker
532*5a6e8488SAndroid Build Coastguard Worker // Get the number of int limbs in each number and get the difference.
533*5a6e8488SAndroid Build Coastguard Worker a_int = bc_num_int(a);
534*5a6e8488SAndroid Build Coastguard Worker b_int = bc_num_int(b);
535*5a6e8488SAndroid Build Coastguard Worker a_int -= b_int;
536*5a6e8488SAndroid Build Coastguard Worker
537*5a6e8488SAndroid Build Coastguard Worker // If there's a difference, then just return the comparison.
538*5a6e8488SAndroid Build Coastguard Worker if (a_int) return neg ? -((ssize_t) a_int) : (ssize_t) a_int;
539*5a6e8488SAndroid Build Coastguard Worker
540*5a6e8488SAndroid Build Coastguard Worker // Get the rdx's and figure out the max.
541*5a6e8488SAndroid Build Coastguard Worker ardx = BC_NUM_RDX_VAL(a);
542*5a6e8488SAndroid Build Coastguard Worker brdx = BC_NUM_RDX_VAL(b);
543*5a6e8488SAndroid Build Coastguard Worker a_max = (ardx > brdx);
544*5a6e8488SAndroid Build Coastguard Worker
545*5a6e8488SAndroid Build Coastguard Worker // Set variables based on the above.
546*5a6e8488SAndroid Build Coastguard Worker if (a_max)
547*5a6e8488SAndroid Build Coastguard Worker {
548*5a6e8488SAndroid Build Coastguard Worker min = brdx;
549*5a6e8488SAndroid Build Coastguard Worker diff = ardx - brdx;
550*5a6e8488SAndroid Build Coastguard Worker max_num = a->num + diff;
551*5a6e8488SAndroid Build Coastguard Worker min_num = b->num;
552*5a6e8488SAndroid Build Coastguard Worker }
553*5a6e8488SAndroid Build Coastguard Worker else
554*5a6e8488SAndroid Build Coastguard Worker {
555*5a6e8488SAndroid Build Coastguard Worker min = ardx;
556*5a6e8488SAndroid Build Coastguard Worker diff = brdx - ardx;
557*5a6e8488SAndroid Build Coastguard Worker max_num = b->num + diff;
558*5a6e8488SAndroid Build Coastguard Worker min_num = a->num;
559*5a6e8488SAndroid Build Coastguard Worker }
560*5a6e8488SAndroid Build Coastguard Worker
561*5a6e8488SAndroid Build Coastguard Worker // Do a full limb-by-limb comparison.
562*5a6e8488SAndroid Build Coastguard Worker cmp = bc_num_compare(max_num, min_num, b_int + min);
563*5a6e8488SAndroid Build Coastguard Worker
564*5a6e8488SAndroid Build Coastguard Worker // If we found a difference, return it based on state.
565*5a6e8488SAndroid Build Coastguard Worker if (cmp) return bc_num_neg((size_t) cmp, !a_max == !neg);
566*5a6e8488SAndroid Build Coastguard Worker
567*5a6e8488SAndroid Build Coastguard Worker // If there was no difference, then the final step is to check which number
568*5a6e8488SAndroid Build Coastguard Worker // has greater or lesser limbs beyond the other's.
569*5a6e8488SAndroid Build Coastguard Worker for (max_num -= diff, i = diff - 1; i < diff; --i)
570*5a6e8488SAndroid Build Coastguard Worker {
571*5a6e8488SAndroid Build Coastguard Worker if (max_num[i]) return bc_num_neg(1, !a_max == !neg);
572*5a6e8488SAndroid Build Coastguard Worker }
573*5a6e8488SAndroid Build Coastguard Worker
574*5a6e8488SAndroid Build Coastguard Worker return 0;
575*5a6e8488SAndroid Build Coastguard Worker }
576*5a6e8488SAndroid Build Coastguard Worker
577*5a6e8488SAndroid Build Coastguard Worker void
bc_num_truncate(BcNum * restrict n,size_t places)578*5a6e8488SAndroid Build Coastguard Worker bc_num_truncate(BcNum* restrict n, size_t places)
579*5a6e8488SAndroid Build Coastguard Worker {
580*5a6e8488SAndroid Build Coastguard Worker size_t nrdx, places_rdx;
581*5a6e8488SAndroid Build Coastguard Worker
582*5a6e8488SAndroid Build Coastguard Worker if (!places) return;
583*5a6e8488SAndroid Build Coastguard Worker
584*5a6e8488SAndroid Build Coastguard Worker // Grab these needed values; places_rdx is the rdx equivalent to places like
585*5a6e8488SAndroid Build Coastguard Worker // rdx is to scale.
586*5a6e8488SAndroid Build Coastguard Worker nrdx = BC_NUM_RDX_VAL(n);
587*5a6e8488SAndroid Build Coastguard Worker places_rdx = nrdx ? nrdx - BC_NUM_RDX(n->scale - places) : 0;
588*5a6e8488SAndroid Build Coastguard Worker
589*5a6e8488SAndroid Build Coastguard Worker // We cannot truncate more places than we have.
590*5a6e8488SAndroid Build Coastguard Worker assert(places <= n->scale && (BC_NUM_ZERO(n) || places_rdx <= n->len));
591*5a6e8488SAndroid Build Coastguard Worker
592*5a6e8488SAndroid Build Coastguard Worker n->scale -= places;
593*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(n, nrdx - places_rdx);
594*5a6e8488SAndroid Build Coastguard Worker
595*5a6e8488SAndroid Build Coastguard Worker // Only when the number is nonzero do we need to do the hard stuff.
596*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(n))
597*5a6e8488SAndroid Build Coastguard Worker {
598*5a6e8488SAndroid Build Coastguard Worker size_t pow;
599*5a6e8488SAndroid Build Coastguard Worker
600*5a6e8488SAndroid Build Coastguard Worker // This calculates how many decimal digits are in the least significant
601*5a6e8488SAndroid Build Coastguard Worker // limb, then gets the power for that.
602*5a6e8488SAndroid Build Coastguard Worker pow = bc_num_leastSigPow(n->scale);
603*5a6e8488SAndroid Build Coastguard Worker
604*5a6e8488SAndroid Build Coastguard Worker n->len -= places_rdx;
605*5a6e8488SAndroid Build Coastguard Worker
606*5a6e8488SAndroid Build Coastguard Worker // We have to move limbs to maintain invariants. The limbs must begin at
607*5a6e8488SAndroid Build Coastguard Worker // the beginning of the BcNum array.
608*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
609*5a6e8488SAndroid Build Coastguard Worker memmove(n->num, n->num + places_rdx, BC_NUM_SIZE(n->len));
610*5a6e8488SAndroid Build Coastguard Worker
611*5a6e8488SAndroid Build Coastguard Worker // Clear the lower part of the last digit.
612*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(n)) n->num[0] -= n->num[0] % (BcDig) pow;
613*5a6e8488SAndroid Build Coastguard Worker
614*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(n);
615*5a6e8488SAndroid Build Coastguard Worker }
616*5a6e8488SAndroid Build Coastguard Worker }
617*5a6e8488SAndroid Build Coastguard Worker
618*5a6e8488SAndroid Build Coastguard Worker void
bc_num_extend(BcNum * restrict n,size_t places)619*5a6e8488SAndroid Build Coastguard Worker bc_num_extend(BcNum* restrict n, size_t places)
620*5a6e8488SAndroid Build Coastguard Worker {
621*5a6e8488SAndroid Build Coastguard Worker size_t nrdx, places_rdx;
622*5a6e8488SAndroid Build Coastguard Worker
623*5a6e8488SAndroid Build Coastguard Worker if (!places) return;
624*5a6e8488SAndroid Build Coastguard Worker
625*5a6e8488SAndroid Build Coastguard Worker // Easy case with zero; set the scale.
626*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(n))
627*5a6e8488SAndroid Build Coastguard Worker {
628*5a6e8488SAndroid Build Coastguard Worker n->scale += places;
629*5a6e8488SAndroid Build Coastguard Worker return;
630*5a6e8488SAndroid Build Coastguard Worker }
631*5a6e8488SAndroid Build Coastguard Worker
632*5a6e8488SAndroid Build Coastguard Worker // Grab these needed values; places_rdx is the rdx equivalent to places like
633*5a6e8488SAndroid Build Coastguard Worker // rdx is to scale.
634*5a6e8488SAndroid Build Coastguard Worker nrdx = BC_NUM_RDX_VAL(n);
635*5a6e8488SAndroid Build Coastguard Worker places_rdx = BC_NUM_RDX(places + n->scale) - nrdx;
636*5a6e8488SAndroid Build Coastguard Worker
637*5a6e8488SAndroid Build Coastguard Worker // This is the hard case. We need to expand the number, move the limbs, and
638*5a6e8488SAndroid Build Coastguard Worker // set the limbs that were just cleared.
639*5a6e8488SAndroid Build Coastguard Worker if (places_rdx)
640*5a6e8488SAndroid Build Coastguard Worker {
641*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));
642*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
643*5a6e8488SAndroid Build Coastguard Worker memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len));
644*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
645*5a6e8488SAndroid Build Coastguard Worker memset(n->num, 0, BC_NUM_SIZE(places_rdx));
646*5a6e8488SAndroid Build Coastguard Worker }
647*5a6e8488SAndroid Build Coastguard Worker
648*5a6e8488SAndroid Build Coastguard Worker // Finally, set scale and rdx.
649*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(n, nrdx + places_rdx);
650*5a6e8488SAndroid Build Coastguard Worker n->scale += places;
651*5a6e8488SAndroid Build Coastguard Worker n->len += places_rdx;
652*5a6e8488SAndroid Build Coastguard Worker
653*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale));
654*5a6e8488SAndroid Build Coastguard Worker }
655*5a6e8488SAndroid Build Coastguard Worker
656*5a6e8488SAndroid Build Coastguard Worker /**
657*5a6e8488SAndroid Build Coastguard Worker * Retires (finishes) a multiplication or division operation.
658*5a6e8488SAndroid Build Coastguard Worker */
659*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_retireMul(BcNum * restrict n,size_t scale,bool neg1,bool neg2)660*5a6e8488SAndroid Build Coastguard Worker bc_num_retireMul(BcNum* restrict n, size_t scale, bool neg1, bool neg2)
661*5a6e8488SAndroid Build Coastguard Worker {
662*5a6e8488SAndroid Build Coastguard Worker // Make sure scale is correct.
663*5a6e8488SAndroid Build Coastguard Worker if (n->scale < scale) bc_num_extend(n, scale - n->scale);
664*5a6e8488SAndroid Build Coastguard Worker else bc_num_truncate(n, n->scale - scale);
665*5a6e8488SAndroid Build Coastguard Worker
666*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(n);
667*5a6e8488SAndroid Build Coastguard Worker
668*5a6e8488SAndroid Build Coastguard Worker // We need to ensure rdx is correct.
669*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(n)) n->rdx = BC_NUM_NEG_VAL(n, !neg1 != !neg2);
670*5a6e8488SAndroid Build Coastguard Worker }
671*5a6e8488SAndroid Build Coastguard Worker
672*5a6e8488SAndroid Build Coastguard Worker /**
673*5a6e8488SAndroid Build Coastguard Worker * Splits a number into two BcNum's. This is used in Karatsuba.
674*5a6e8488SAndroid Build Coastguard Worker * @param n The number to split.
675*5a6e8488SAndroid Build Coastguard Worker * @param idx The index to split at.
676*5a6e8488SAndroid Build Coastguard Worker * @param a An out parameter; the low part of @a n.
677*5a6e8488SAndroid Build Coastguard Worker * @param b An out parameter; the high part of @a n.
678*5a6e8488SAndroid Build Coastguard Worker */
679*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_split(const BcNum * restrict n,size_t idx,BcNum * restrict a,BcNum * restrict b)680*5a6e8488SAndroid Build Coastguard Worker bc_num_split(const BcNum* restrict n, size_t idx, BcNum* restrict a,
681*5a6e8488SAndroid Build Coastguard Worker BcNum* restrict b)
682*5a6e8488SAndroid Build Coastguard Worker {
683*5a6e8488SAndroid Build Coastguard Worker // We want a and b to be clear.
684*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_ZERO(a));
685*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_ZERO(b));
686*5a6e8488SAndroid Build Coastguard Worker
687*5a6e8488SAndroid Build Coastguard Worker // The usual case.
688*5a6e8488SAndroid Build Coastguard Worker if (idx < n->len)
689*5a6e8488SAndroid Build Coastguard Worker {
690*5a6e8488SAndroid Build Coastguard Worker // Set the fields first.
691*5a6e8488SAndroid Build Coastguard Worker b->len = n->len - idx;
692*5a6e8488SAndroid Build Coastguard Worker a->len = idx;
693*5a6e8488SAndroid Build Coastguard Worker a->scale = b->scale = 0;
694*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(a, 0);
695*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(b, 0);
696*5a6e8488SAndroid Build Coastguard Worker
697*5a6e8488SAndroid Build Coastguard Worker assert(a->cap >= a->len);
698*5a6e8488SAndroid Build Coastguard Worker assert(b->cap >= b->len);
699*5a6e8488SAndroid Build Coastguard Worker
700*5a6e8488SAndroid Build Coastguard Worker // Copy the arrays. This is not necessary for safety, but it is faster,
701*5a6e8488SAndroid Build Coastguard Worker // for some reason.
702*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
703*5a6e8488SAndroid Build Coastguard Worker memcpy(b->num, n->num + idx, BC_NUM_SIZE(b->len));
704*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
705*5a6e8488SAndroid Build Coastguard Worker memcpy(a->num, n->num, BC_NUM_SIZE(idx));
706*5a6e8488SAndroid Build Coastguard Worker
707*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(b);
708*5a6e8488SAndroid Build Coastguard Worker }
709*5a6e8488SAndroid Build Coastguard Worker // If the index is weird, just skip the split.
710*5a6e8488SAndroid Build Coastguard Worker else bc_num_copy(a, n);
711*5a6e8488SAndroid Build Coastguard Worker
712*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(a);
713*5a6e8488SAndroid Build Coastguard Worker }
714*5a6e8488SAndroid Build Coastguard Worker
715*5a6e8488SAndroid Build Coastguard Worker /**
716*5a6e8488SAndroid Build Coastguard Worker * Copies a number into another, but shifts the rdx so that the result number
717*5a6e8488SAndroid Build Coastguard Worker * only sees the integer part of the source number.
718*5a6e8488SAndroid Build Coastguard Worker * @param n The number to copy.
719*5a6e8488SAndroid Build Coastguard Worker * @param r The result number with a shifted rdx, len, and num.
720*5a6e8488SAndroid Build Coastguard Worker */
721*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_shiftRdx(const BcNum * restrict n,BcNum * restrict r)722*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftRdx(const BcNum* restrict n, BcNum* restrict r)
723*5a6e8488SAndroid Build Coastguard Worker {
724*5a6e8488SAndroid Build Coastguard Worker size_t rdx = BC_NUM_RDX_VAL(n);
725*5a6e8488SAndroid Build Coastguard Worker
726*5a6e8488SAndroid Build Coastguard Worker r->len = n->len - rdx;
727*5a6e8488SAndroid Build Coastguard Worker r->cap = n->cap - rdx;
728*5a6e8488SAndroid Build Coastguard Worker r->num = n->num + rdx;
729*5a6e8488SAndroid Build Coastguard Worker
730*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET_NEG(r, 0, BC_NUM_NEG(n));
731*5a6e8488SAndroid Build Coastguard Worker r->scale = 0;
732*5a6e8488SAndroid Build Coastguard Worker }
733*5a6e8488SAndroid Build Coastguard Worker
734*5a6e8488SAndroid Build Coastguard Worker /**
735*5a6e8488SAndroid Build Coastguard Worker * Shifts a number so that all of the least significant limbs of the number are
736*5a6e8488SAndroid Build Coastguard Worker * skipped. This must be undone by bc_num_unshiftZero().
737*5a6e8488SAndroid Build Coastguard Worker * @param n The number to shift.
738*5a6e8488SAndroid Build Coastguard Worker */
739*5a6e8488SAndroid Build Coastguard Worker static size_t
bc_num_shiftZero(BcNum * restrict n)740*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftZero(BcNum* restrict n)
741*5a6e8488SAndroid Build Coastguard Worker {
742*5a6e8488SAndroid Build Coastguard Worker // This is volatile to quiet a GCC warning about longjmp() clobbering.
743*5a6e8488SAndroid Build Coastguard Worker volatile size_t i;
744*5a6e8488SAndroid Build Coastguard Worker
745*5a6e8488SAndroid Build Coastguard Worker // If we don't have an integer, that is a problem, but it's also a bug
746*5a6e8488SAndroid Build Coastguard Worker // because the caller should have set everything up right.
747*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_RDX_VAL(n) || BC_NUM_ZERO(n));
748*5a6e8488SAndroid Build Coastguard Worker
749*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < n->len && !n->num[i]; ++i)
750*5a6e8488SAndroid Build Coastguard Worker {
751*5a6e8488SAndroid Build Coastguard Worker continue;
752*5a6e8488SAndroid Build Coastguard Worker }
753*5a6e8488SAndroid Build Coastguard Worker
754*5a6e8488SAndroid Build Coastguard Worker n->len -= i;
755*5a6e8488SAndroid Build Coastguard Worker n->num += i;
756*5a6e8488SAndroid Build Coastguard Worker
757*5a6e8488SAndroid Build Coastguard Worker return i;
758*5a6e8488SAndroid Build Coastguard Worker }
759*5a6e8488SAndroid Build Coastguard Worker
760*5a6e8488SAndroid Build Coastguard Worker /**
761*5a6e8488SAndroid Build Coastguard Worker * Undo the damage done by bc_num_unshiftZero(). This must be called like all
762*5a6e8488SAndroid Build Coastguard Worker * cleanup functions: after a label used by setjmp() and longjmp().
763*5a6e8488SAndroid Build Coastguard Worker * @param n The number to unshift.
764*5a6e8488SAndroid Build Coastguard Worker * @param places_rdx The amount the number was originally shift.
765*5a6e8488SAndroid Build Coastguard Worker */
766*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_unshiftZero(BcNum * restrict n,size_t places_rdx)767*5a6e8488SAndroid Build Coastguard Worker bc_num_unshiftZero(BcNum* restrict n, size_t places_rdx)
768*5a6e8488SAndroid Build Coastguard Worker {
769*5a6e8488SAndroid Build Coastguard Worker n->len += places_rdx;
770*5a6e8488SAndroid Build Coastguard Worker n->num -= places_rdx;
771*5a6e8488SAndroid Build Coastguard Worker }
772*5a6e8488SAndroid Build Coastguard Worker
773*5a6e8488SAndroid Build Coastguard Worker /**
774*5a6e8488SAndroid Build Coastguard Worker * Shifts the digits right within a number by no more than BC_BASE_DIGS - 1.
775*5a6e8488SAndroid Build Coastguard Worker * This is the final step on shifting numbers with the shift operators. It
776*5a6e8488SAndroid Build Coastguard Worker * depends on the caller to shift the limbs properly because all it does is
777*5a6e8488SAndroid Build Coastguard Worker * ensure that the rdx point is realigned to be between limbs.
778*5a6e8488SAndroid Build Coastguard Worker * @param n The number to shift digits in.
779*5a6e8488SAndroid Build Coastguard Worker * @param dig The number of places to shift right.
780*5a6e8488SAndroid Build Coastguard Worker */
781*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_shift(BcNum * restrict n,BcBigDig dig)782*5a6e8488SAndroid Build Coastguard Worker bc_num_shift(BcNum* restrict n, BcBigDig dig)
783*5a6e8488SAndroid Build Coastguard Worker {
784*5a6e8488SAndroid Build Coastguard Worker size_t i, len = n->len;
785*5a6e8488SAndroid Build Coastguard Worker BcBigDig carry = 0, pow;
786*5a6e8488SAndroid Build Coastguard Worker BcDig* ptr = n->num;
787*5a6e8488SAndroid Build Coastguard Worker
788*5a6e8488SAndroid Build Coastguard Worker assert(dig < BC_BASE_DIGS);
789*5a6e8488SAndroid Build Coastguard Worker
790*5a6e8488SAndroid Build Coastguard Worker // Figure out the parameters for division.
791*5a6e8488SAndroid Build Coastguard Worker pow = bc_num_pow10[dig];
792*5a6e8488SAndroid Build Coastguard Worker dig = bc_num_pow10[BC_BASE_DIGS - dig];
793*5a6e8488SAndroid Build Coastguard Worker
794*5a6e8488SAndroid Build Coastguard Worker // Run a series of divisions and mods with carries across the entire number
795*5a6e8488SAndroid Build Coastguard Worker // array. This effectively shifts everything over.
796*5a6e8488SAndroid Build Coastguard Worker for (i = len - 1; i < len; --i)
797*5a6e8488SAndroid Build Coastguard Worker {
798*5a6e8488SAndroid Build Coastguard Worker BcBigDig in, temp;
799*5a6e8488SAndroid Build Coastguard Worker in = ((BcBigDig) ptr[i]);
800*5a6e8488SAndroid Build Coastguard Worker temp = carry * dig;
801*5a6e8488SAndroid Build Coastguard Worker carry = in % pow;
802*5a6e8488SAndroid Build Coastguard Worker ptr[i] = ((BcDig) (in / pow)) + (BcDig) temp;
803*5a6e8488SAndroid Build Coastguard Worker assert(ptr[i] >= 0 && ptr[i] < BC_BASE_POW);
804*5a6e8488SAndroid Build Coastguard Worker }
805*5a6e8488SAndroid Build Coastguard Worker
806*5a6e8488SAndroid Build Coastguard Worker assert(!carry);
807*5a6e8488SAndroid Build Coastguard Worker }
808*5a6e8488SAndroid Build Coastguard Worker
809*5a6e8488SAndroid Build Coastguard Worker /**
810*5a6e8488SAndroid Build Coastguard Worker * Shift a number left by a certain number of places. This is the workhorse of
811*5a6e8488SAndroid Build Coastguard Worker * the left shift operator.
812*5a6e8488SAndroid Build Coastguard Worker * @param n The number to shift left.
813*5a6e8488SAndroid Build Coastguard Worker * @param places The amount of places to shift @a n left by.
814*5a6e8488SAndroid Build Coastguard Worker */
815*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_shiftLeft(BcNum * restrict n,size_t places)816*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(BcNum* restrict n, size_t places)
817*5a6e8488SAndroid Build Coastguard Worker {
818*5a6e8488SAndroid Build Coastguard Worker BcBigDig dig;
819*5a6e8488SAndroid Build Coastguard Worker size_t places_rdx;
820*5a6e8488SAndroid Build Coastguard Worker bool shift;
821*5a6e8488SAndroid Build Coastguard Worker
822*5a6e8488SAndroid Build Coastguard Worker if (!places) return;
823*5a6e8488SAndroid Build Coastguard Worker
824*5a6e8488SAndroid Build Coastguard Worker // Make sure to grow the number if necessary.
825*5a6e8488SAndroid Build Coastguard Worker if (places > n->scale)
826*5a6e8488SAndroid Build Coastguard Worker {
827*5a6e8488SAndroid Build Coastguard Worker size_t size = bc_vm_growSize(BC_NUM_RDX(places - n->scale), n->len);
828*5a6e8488SAndroid Build Coastguard Worker if (size > SIZE_MAX - 1) bc_err(BC_ERR_MATH_OVERFLOW);
829*5a6e8488SAndroid Build Coastguard Worker }
830*5a6e8488SAndroid Build Coastguard Worker
831*5a6e8488SAndroid Build Coastguard Worker // If zero, we can just set the scale and bail.
832*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(n))
833*5a6e8488SAndroid Build Coastguard Worker {
834*5a6e8488SAndroid Build Coastguard Worker if (n->scale >= places) n->scale -= places;
835*5a6e8488SAndroid Build Coastguard Worker else n->scale = 0;
836*5a6e8488SAndroid Build Coastguard Worker return;
837*5a6e8488SAndroid Build Coastguard Worker }
838*5a6e8488SAndroid Build Coastguard Worker
839*5a6e8488SAndroid Build Coastguard Worker // When I changed bc to have multiple digits per limb, this was the hardest
840*5a6e8488SAndroid Build Coastguard Worker // code to change. This and shift right. Make sure you understand this
841*5a6e8488SAndroid Build Coastguard Worker // before attempting anything.
842*5a6e8488SAndroid Build Coastguard Worker
843*5a6e8488SAndroid Build Coastguard Worker // This is how many limbs we will shift.
844*5a6e8488SAndroid Build Coastguard Worker dig = (BcBigDig) (places % BC_BASE_DIGS);
845*5a6e8488SAndroid Build Coastguard Worker shift = (dig != 0);
846*5a6e8488SAndroid Build Coastguard Worker
847*5a6e8488SAndroid Build Coastguard Worker // Convert places to a rdx value.
848*5a6e8488SAndroid Build Coastguard Worker places_rdx = BC_NUM_RDX(places);
849*5a6e8488SAndroid Build Coastguard Worker
850*5a6e8488SAndroid Build Coastguard Worker // If the number is not an integer, we need special care. The reason an
851*5a6e8488SAndroid Build Coastguard Worker // integer doesn't is because left shift would only extend the integer,
852*5a6e8488SAndroid Build Coastguard Worker // whereas a non-integer might have its fractional part eliminated or only
853*5a6e8488SAndroid Build Coastguard Worker // partially eliminated.
854*5a6e8488SAndroid Build Coastguard Worker if (n->scale)
855*5a6e8488SAndroid Build Coastguard Worker {
856*5a6e8488SAndroid Build Coastguard Worker size_t nrdx = BC_NUM_RDX_VAL(n);
857*5a6e8488SAndroid Build Coastguard Worker
858*5a6e8488SAndroid Build Coastguard Worker // If the number's rdx is bigger, that's the hard case.
859*5a6e8488SAndroid Build Coastguard Worker if (nrdx >= places_rdx)
860*5a6e8488SAndroid Build Coastguard Worker {
861*5a6e8488SAndroid Build Coastguard Worker size_t mod = n->scale % BC_BASE_DIGS, revdig;
862*5a6e8488SAndroid Build Coastguard Worker
863*5a6e8488SAndroid Build Coastguard Worker // We want mod to be in the range [1, BC_BASE_DIGS], not
864*5a6e8488SAndroid Build Coastguard Worker // [0, BC_BASE_DIGS).
865*5a6e8488SAndroid Build Coastguard Worker mod = mod ? mod : BC_BASE_DIGS;
866*5a6e8488SAndroid Build Coastguard Worker
867*5a6e8488SAndroid Build Coastguard Worker // We need to reverse dig to get the actual number of digits.
868*5a6e8488SAndroid Build Coastguard Worker revdig = dig ? BC_BASE_DIGS - dig : 0;
869*5a6e8488SAndroid Build Coastguard Worker
870*5a6e8488SAndroid Build Coastguard Worker // If the two overflow BC_BASE_DIGS, we need to move an extra place.
871*5a6e8488SAndroid Build Coastguard Worker if (mod + revdig > BC_BASE_DIGS) places_rdx = 1;
872*5a6e8488SAndroid Build Coastguard Worker else places_rdx = 0;
873*5a6e8488SAndroid Build Coastguard Worker }
874*5a6e8488SAndroid Build Coastguard Worker else places_rdx -= nrdx;
875*5a6e8488SAndroid Build Coastguard Worker }
876*5a6e8488SAndroid Build Coastguard Worker
877*5a6e8488SAndroid Build Coastguard Worker // If this is non-zero, we need an extra place, so expand, move, and set.
878*5a6e8488SAndroid Build Coastguard Worker if (places_rdx)
879*5a6e8488SAndroid Build Coastguard Worker {
880*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));
881*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
882*5a6e8488SAndroid Build Coastguard Worker memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len));
883*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
884*5a6e8488SAndroid Build Coastguard Worker memset(n->num, 0, BC_NUM_SIZE(places_rdx));
885*5a6e8488SAndroid Build Coastguard Worker n->len += places_rdx;
886*5a6e8488SAndroid Build Coastguard Worker }
887*5a6e8488SAndroid Build Coastguard Worker
888*5a6e8488SAndroid Build Coastguard Worker // Set the scale appropriately.
889*5a6e8488SAndroid Build Coastguard Worker if (places > n->scale)
890*5a6e8488SAndroid Build Coastguard Worker {
891*5a6e8488SAndroid Build Coastguard Worker n->scale = 0;
892*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(n, 0);
893*5a6e8488SAndroid Build Coastguard Worker }
894*5a6e8488SAndroid Build Coastguard Worker else
895*5a6e8488SAndroid Build Coastguard Worker {
896*5a6e8488SAndroid Build Coastguard Worker n->scale -= places;
897*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
898*5a6e8488SAndroid Build Coastguard Worker }
899*5a6e8488SAndroid Build Coastguard Worker
900*5a6e8488SAndroid Build Coastguard Worker // Finally, shift within limbs.
901*5a6e8488SAndroid Build Coastguard Worker if (shift) bc_num_shift(n, BC_BASE_DIGS - dig);
902*5a6e8488SAndroid Build Coastguard Worker
903*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(n);
904*5a6e8488SAndroid Build Coastguard Worker }
905*5a6e8488SAndroid Build Coastguard Worker
906*5a6e8488SAndroid Build Coastguard Worker void
bc_num_shiftRight(BcNum * restrict n,size_t places)907*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftRight(BcNum* restrict n, size_t places)
908*5a6e8488SAndroid Build Coastguard Worker {
909*5a6e8488SAndroid Build Coastguard Worker BcBigDig dig;
910*5a6e8488SAndroid Build Coastguard Worker size_t places_rdx, scale, scale_mod, int_len, expand;
911*5a6e8488SAndroid Build Coastguard Worker bool shift;
912*5a6e8488SAndroid Build Coastguard Worker
913*5a6e8488SAndroid Build Coastguard Worker if (!places) return;
914*5a6e8488SAndroid Build Coastguard Worker
915*5a6e8488SAndroid Build Coastguard Worker // If zero, we can just set the scale and bail.
916*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(n))
917*5a6e8488SAndroid Build Coastguard Worker {
918*5a6e8488SAndroid Build Coastguard Worker n->scale += places;
919*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(n, BC_NUM_RDX(n->scale));
920*5a6e8488SAndroid Build Coastguard Worker return;
921*5a6e8488SAndroid Build Coastguard Worker }
922*5a6e8488SAndroid Build Coastguard Worker
923*5a6e8488SAndroid Build Coastguard Worker // Amount within a limb we have to shift by.
924*5a6e8488SAndroid Build Coastguard Worker dig = (BcBigDig) (places % BC_BASE_DIGS);
925*5a6e8488SAndroid Build Coastguard Worker shift = (dig != 0);
926*5a6e8488SAndroid Build Coastguard Worker
927*5a6e8488SAndroid Build Coastguard Worker scale = n->scale;
928*5a6e8488SAndroid Build Coastguard Worker
929*5a6e8488SAndroid Build Coastguard Worker // Figure out how the scale is affected.
930*5a6e8488SAndroid Build Coastguard Worker scale_mod = scale % BC_BASE_DIGS;
931*5a6e8488SAndroid Build Coastguard Worker scale_mod = scale_mod ? scale_mod : BC_BASE_DIGS;
932*5a6e8488SAndroid Build Coastguard Worker
933*5a6e8488SAndroid Build Coastguard Worker // We need to know the int length and rdx for places.
934*5a6e8488SAndroid Build Coastguard Worker int_len = bc_num_int(n);
935*5a6e8488SAndroid Build Coastguard Worker places_rdx = BC_NUM_RDX(places);
936*5a6e8488SAndroid Build Coastguard Worker
937*5a6e8488SAndroid Build Coastguard Worker // If we are going to shift past a limb boundary or not, set accordingly.
938*5a6e8488SAndroid Build Coastguard Worker if (scale_mod + dig > BC_BASE_DIGS)
939*5a6e8488SAndroid Build Coastguard Worker {
940*5a6e8488SAndroid Build Coastguard Worker expand = places_rdx - 1;
941*5a6e8488SAndroid Build Coastguard Worker places_rdx = 1;
942*5a6e8488SAndroid Build Coastguard Worker }
943*5a6e8488SAndroid Build Coastguard Worker else
944*5a6e8488SAndroid Build Coastguard Worker {
945*5a6e8488SAndroid Build Coastguard Worker expand = places_rdx;
946*5a6e8488SAndroid Build Coastguard Worker places_rdx = 0;
947*5a6e8488SAndroid Build Coastguard Worker }
948*5a6e8488SAndroid Build Coastguard Worker
949*5a6e8488SAndroid Build Coastguard Worker // Clamp expanding.
950*5a6e8488SAndroid Build Coastguard Worker if (expand > int_len) expand -= int_len;
951*5a6e8488SAndroid Build Coastguard Worker else expand = 0;
952*5a6e8488SAndroid Build Coastguard Worker
953*5a6e8488SAndroid Build Coastguard Worker // Extend, expand, and zero.
954*5a6e8488SAndroid Build Coastguard Worker bc_num_extend(n, places_rdx * BC_BASE_DIGS);
955*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(n, bc_vm_growSize(expand, n->len));
956*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
957*5a6e8488SAndroid Build Coastguard Worker memset(n->num + n->len, 0, BC_NUM_SIZE(expand));
958*5a6e8488SAndroid Build Coastguard Worker
959*5a6e8488SAndroid Build Coastguard Worker // Set the fields.
960*5a6e8488SAndroid Build Coastguard Worker n->len += expand;
961*5a6e8488SAndroid Build Coastguard Worker n->scale = 0;
962*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(n, 0);
963*5a6e8488SAndroid Build Coastguard Worker
964*5a6e8488SAndroid Build Coastguard Worker // Finally, shift within limbs.
965*5a6e8488SAndroid Build Coastguard Worker if (shift) bc_num_shift(n, dig);
966*5a6e8488SAndroid Build Coastguard Worker
967*5a6e8488SAndroid Build Coastguard Worker n->scale = scale + places;
968*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
969*5a6e8488SAndroid Build Coastguard Worker
970*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(n);
971*5a6e8488SAndroid Build Coastguard Worker
972*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(n) <= n->len && n->len <= n->cap);
973*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale));
974*5a6e8488SAndroid Build Coastguard Worker }
975*5a6e8488SAndroid Build Coastguard Worker
976*5a6e8488SAndroid Build Coastguard Worker /**
977*5a6e8488SAndroid Build Coastguard Worker * Tests if a number is a integer with scale or not. Returns true if the number
978*5a6e8488SAndroid Build Coastguard Worker * is not an integer. If it is, its integer shifted form is copied into the
979*5a6e8488SAndroid Build Coastguard Worker * result parameter for use where only integers are allowed.
980*5a6e8488SAndroid Build Coastguard Worker * @param n The integer to test and shift.
981*5a6e8488SAndroid Build Coastguard Worker * @param r The number to store the shifted result into. This number should
982*5a6e8488SAndroid Build Coastguard Worker * *not* be allocated.
983*5a6e8488SAndroid Build Coastguard Worker * @return True if the number is a non-integer, false otherwise.
984*5a6e8488SAndroid Build Coastguard Worker */
985*5a6e8488SAndroid Build Coastguard Worker static bool
bc_num_nonInt(const BcNum * restrict n,BcNum * restrict r)986*5a6e8488SAndroid Build Coastguard Worker bc_num_nonInt(const BcNum* restrict n, BcNum* restrict r)
987*5a6e8488SAndroid Build Coastguard Worker {
988*5a6e8488SAndroid Build Coastguard Worker bool zero;
989*5a6e8488SAndroid Build Coastguard Worker size_t i, rdx = BC_NUM_RDX_VAL(n);
990*5a6e8488SAndroid Build Coastguard Worker
991*5a6e8488SAndroid Build Coastguard Worker if (!rdx)
992*5a6e8488SAndroid Build Coastguard Worker {
993*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
994*5a6e8488SAndroid Build Coastguard Worker memcpy(r, n, sizeof(BcNum));
995*5a6e8488SAndroid Build Coastguard Worker return false;
996*5a6e8488SAndroid Build Coastguard Worker }
997*5a6e8488SAndroid Build Coastguard Worker
998*5a6e8488SAndroid Build Coastguard Worker zero = true;
999*5a6e8488SAndroid Build Coastguard Worker
1000*5a6e8488SAndroid Build Coastguard Worker for (i = 0; zero && i < rdx; ++i)
1001*5a6e8488SAndroid Build Coastguard Worker {
1002*5a6e8488SAndroid Build Coastguard Worker zero = (n->num[i] == 0);
1003*5a6e8488SAndroid Build Coastguard Worker }
1004*5a6e8488SAndroid Build Coastguard Worker
1005*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(!zero)) return true;
1006*5a6e8488SAndroid Build Coastguard Worker
1007*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftRdx(n, r);
1008*5a6e8488SAndroid Build Coastguard Worker
1009*5a6e8488SAndroid Build Coastguard Worker return false;
1010*5a6e8488SAndroid Build Coastguard Worker }
1011*5a6e8488SAndroid Build Coastguard Worker
1012*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1013*5a6e8488SAndroid Build Coastguard Worker
1014*5a6e8488SAndroid Build Coastguard Worker /**
1015*5a6e8488SAndroid Build Coastguard Worker * Execute common code for an operater that needs an integer for the second
1016*5a6e8488SAndroid Build Coastguard Worker * operand and return the integer operand as a BcBigDig.
1017*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
1018*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
1019*5a6e8488SAndroid Build Coastguard Worker * @param c The result operand.
1020*5a6e8488SAndroid Build Coastguard Worker * @return The second operand as a hardware integer.
1021*5a6e8488SAndroid Build Coastguard Worker */
1022*5a6e8488SAndroid Build Coastguard Worker static BcBigDig
bc_num_intop(const BcNum * a,const BcNum * b,BcNum * restrict c)1023*5a6e8488SAndroid Build Coastguard Worker bc_num_intop(const BcNum* a, const BcNum* b, BcNum* restrict c)
1024*5a6e8488SAndroid Build Coastguard Worker {
1025*5a6e8488SAndroid Build Coastguard Worker BcNum temp;
1026*5a6e8488SAndroid Build Coastguard Worker
1027*5a6e8488SAndroid Build Coastguard Worker #if BC_GCC
1028*5a6e8488SAndroid Build Coastguard Worker temp.len = 0;
1029*5a6e8488SAndroid Build Coastguard Worker temp.rdx = 0;
1030*5a6e8488SAndroid Build Coastguard Worker temp.num = NULL;
1031*5a6e8488SAndroid Build Coastguard Worker #endif // BC_GCC
1032*5a6e8488SAndroid Build Coastguard Worker
1033*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(bc_num_nonInt(b, &temp))) bc_err(BC_ERR_MATH_NON_INTEGER);
1034*5a6e8488SAndroid Build Coastguard Worker
1035*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(c, a);
1036*5a6e8488SAndroid Build Coastguard Worker
1037*5a6e8488SAndroid Build Coastguard Worker return bc_num_bigdig(&temp);
1038*5a6e8488SAndroid Build Coastguard Worker }
1039*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1040*5a6e8488SAndroid Build Coastguard Worker
1041*5a6e8488SAndroid Build Coastguard Worker /**
1042*5a6e8488SAndroid Build Coastguard Worker * This is the actual implementation of add *and* subtract. Since this function
1043*5a6e8488SAndroid Build Coastguard Worker * doesn't need to use scale (per the bc spec), I am hijacking it to say whether
1044*5a6e8488SAndroid Build Coastguard Worker * it's doing an add or a subtract. And then I convert substraction to addition
1045*5a6e8488SAndroid Build Coastguard Worker * of negative second operand. This is a BcNumBinOp function.
1046*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
1047*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
1048*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
1049*5a6e8488SAndroid Build Coastguard Worker * @param sub Non-zero for a subtract, zero for an add.
1050*5a6e8488SAndroid Build Coastguard Worker */
1051*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_as(BcNum * a,BcNum * b,BcNum * restrict c,size_t sub)1052*5a6e8488SAndroid Build Coastguard Worker bc_num_as(BcNum* a, BcNum* b, BcNum* restrict c, size_t sub)
1053*5a6e8488SAndroid Build Coastguard Worker {
1054*5a6e8488SAndroid Build Coastguard Worker BcDig* ptr_c;
1055*5a6e8488SAndroid Build Coastguard Worker BcDig* ptr_l;
1056*5a6e8488SAndroid Build Coastguard Worker BcDig* ptr_r;
1057*5a6e8488SAndroid Build Coastguard Worker size_t i, min_rdx, max_rdx, diff, a_int, b_int, min_len, max_len, max_int;
1058*5a6e8488SAndroid Build Coastguard Worker size_t len_l, len_r, ardx, brdx;
1059*5a6e8488SAndroid Build Coastguard Worker bool b_neg, do_sub, do_rev_sub, carry, c_neg;
1060*5a6e8488SAndroid Build Coastguard Worker
1061*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(b))
1062*5a6e8488SAndroid Build Coastguard Worker {
1063*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(c, a);
1064*5a6e8488SAndroid Build Coastguard Worker return;
1065*5a6e8488SAndroid Build Coastguard Worker }
1066*5a6e8488SAndroid Build Coastguard Worker
1067*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(a))
1068*5a6e8488SAndroid Build Coastguard Worker {
1069*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(c, b);
1070*5a6e8488SAndroid Build Coastguard Worker c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(b) != sub);
1071*5a6e8488SAndroid Build Coastguard Worker return;
1072*5a6e8488SAndroid Build Coastguard Worker }
1073*5a6e8488SAndroid Build Coastguard Worker
1074*5a6e8488SAndroid Build Coastguard Worker // Invert sign of b if it is to be subtracted. This operation must
1075*5a6e8488SAndroid Build Coastguard Worker // precede the tests for any of the operands being zero.
1076*5a6e8488SAndroid Build Coastguard Worker b_neg = (BC_NUM_NEG(b) != sub);
1077*5a6e8488SAndroid Build Coastguard Worker
1078*5a6e8488SAndroid Build Coastguard Worker // Figure out if we will actually add the numbers if their signs are equal
1079*5a6e8488SAndroid Build Coastguard Worker // or subtract.
1080*5a6e8488SAndroid Build Coastguard Worker do_sub = (BC_NUM_NEG(a) != b_neg);
1081*5a6e8488SAndroid Build Coastguard Worker
1082*5a6e8488SAndroid Build Coastguard Worker a_int = bc_num_int(a);
1083*5a6e8488SAndroid Build Coastguard Worker b_int = bc_num_int(b);
1084*5a6e8488SAndroid Build Coastguard Worker max_int = BC_MAX(a_int, b_int);
1085*5a6e8488SAndroid Build Coastguard Worker
1086*5a6e8488SAndroid Build Coastguard Worker // Figure out which number will have its last limbs copied (for addition) or
1087*5a6e8488SAndroid Build Coastguard Worker // subtracted (for subtraction).
1088*5a6e8488SAndroid Build Coastguard Worker ardx = BC_NUM_RDX_VAL(a);
1089*5a6e8488SAndroid Build Coastguard Worker brdx = BC_NUM_RDX_VAL(b);
1090*5a6e8488SAndroid Build Coastguard Worker min_rdx = BC_MIN(ardx, brdx);
1091*5a6e8488SAndroid Build Coastguard Worker max_rdx = BC_MAX(ardx, brdx);
1092*5a6e8488SAndroid Build Coastguard Worker diff = max_rdx - min_rdx;
1093*5a6e8488SAndroid Build Coastguard Worker
1094*5a6e8488SAndroid Build Coastguard Worker max_len = max_int + max_rdx;
1095*5a6e8488SAndroid Build Coastguard Worker
1096*5a6e8488SAndroid Build Coastguard Worker if (do_sub)
1097*5a6e8488SAndroid Build Coastguard Worker {
1098*5a6e8488SAndroid Build Coastguard Worker // Check whether b has to be subtracted from a or a from b.
1099*5a6e8488SAndroid Build Coastguard Worker if (a_int != b_int) do_rev_sub = (a_int < b_int);
1100*5a6e8488SAndroid Build Coastguard Worker else if (ardx > brdx)
1101*5a6e8488SAndroid Build Coastguard Worker {
1102*5a6e8488SAndroid Build Coastguard Worker do_rev_sub = (bc_num_compare(a->num + diff, b->num, b->len) < 0);
1103*5a6e8488SAndroid Build Coastguard Worker }
1104*5a6e8488SAndroid Build Coastguard Worker else do_rev_sub = (bc_num_compare(a->num, b->num + diff, a->len) <= 0);
1105*5a6e8488SAndroid Build Coastguard Worker }
1106*5a6e8488SAndroid Build Coastguard Worker else
1107*5a6e8488SAndroid Build Coastguard Worker {
1108*5a6e8488SAndroid Build Coastguard Worker // The result array of the addition might come out one element
1109*5a6e8488SAndroid Build Coastguard Worker // longer than the bigger of the operand arrays.
1110*5a6e8488SAndroid Build Coastguard Worker max_len += 1;
1111*5a6e8488SAndroid Build Coastguard Worker do_rev_sub = (a_int < b_int);
1112*5a6e8488SAndroid Build Coastguard Worker }
1113*5a6e8488SAndroid Build Coastguard Worker
1114*5a6e8488SAndroid Build Coastguard Worker assert(max_len <= c->cap);
1115*5a6e8488SAndroid Build Coastguard Worker
1116*5a6e8488SAndroid Build Coastguard Worker // Cache values for simple code later.
1117*5a6e8488SAndroid Build Coastguard Worker if (do_rev_sub)
1118*5a6e8488SAndroid Build Coastguard Worker {
1119*5a6e8488SAndroid Build Coastguard Worker ptr_l = b->num;
1120*5a6e8488SAndroid Build Coastguard Worker ptr_r = a->num;
1121*5a6e8488SAndroid Build Coastguard Worker len_l = b->len;
1122*5a6e8488SAndroid Build Coastguard Worker len_r = a->len;
1123*5a6e8488SAndroid Build Coastguard Worker }
1124*5a6e8488SAndroid Build Coastguard Worker else
1125*5a6e8488SAndroid Build Coastguard Worker {
1126*5a6e8488SAndroid Build Coastguard Worker ptr_l = a->num;
1127*5a6e8488SAndroid Build Coastguard Worker ptr_r = b->num;
1128*5a6e8488SAndroid Build Coastguard Worker len_l = a->len;
1129*5a6e8488SAndroid Build Coastguard Worker len_r = b->len;
1130*5a6e8488SAndroid Build Coastguard Worker }
1131*5a6e8488SAndroid Build Coastguard Worker
1132*5a6e8488SAndroid Build Coastguard Worker ptr_c = c->num;
1133*5a6e8488SAndroid Build Coastguard Worker carry = false;
1134*5a6e8488SAndroid Build Coastguard Worker
1135*5a6e8488SAndroid Build Coastguard Worker // This is true if the numbers have a different number of limbs after the
1136*5a6e8488SAndroid Build Coastguard Worker // decimal point.
1137*5a6e8488SAndroid Build Coastguard Worker if (diff)
1138*5a6e8488SAndroid Build Coastguard Worker {
1139*5a6e8488SAndroid Build Coastguard Worker // If the rdx values of the operands do not match, the result will
1140*5a6e8488SAndroid Build Coastguard Worker // have low end elements that are the positive or negative trailing
1141*5a6e8488SAndroid Build Coastguard Worker // elements of the operand with higher rdx value.
1142*5a6e8488SAndroid Build Coastguard Worker if ((ardx > brdx) != do_rev_sub)
1143*5a6e8488SAndroid Build Coastguard Worker {
1144*5a6e8488SAndroid Build Coastguard Worker // !do_rev_sub && ardx > brdx || do_rev_sub && brdx > ardx
1145*5a6e8488SAndroid Build Coastguard Worker // The left operand has BcDig values that need to be copied,
1146*5a6e8488SAndroid Build Coastguard Worker // either from a or from b (in case of a reversed subtraction).
1147*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
1148*5a6e8488SAndroid Build Coastguard Worker memcpy(ptr_c, ptr_l, BC_NUM_SIZE(diff));
1149*5a6e8488SAndroid Build Coastguard Worker ptr_l += diff;
1150*5a6e8488SAndroid Build Coastguard Worker len_l -= diff;
1151*5a6e8488SAndroid Build Coastguard Worker }
1152*5a6e8488SAndroid Build Coastguard Worker else
1153*5a6e8488SAndroid Build Coastguard Worker {
1154*5a6e8488SAndroid Build Coastguard Worker // The right operand has BcDig values that need to be copied
1155*5a6e8488SAndroid Build Coastguard Worker // or subtracted from zero (in case of a subtraction).
1156*5a6e8488SAndroid Build Coastguard Worker if (do_sub)
1157*5a6e8488SAndroid Build Coastguard Worker {
1158*5a6e8488SAndroid Build Coastguard Worker // do_sub (do_rev_sub && ardx > brdx ||
1159*5a6e8488SAndroid Build Coastguard Worker // !do_rev_sub && brdx > ardx)
1160*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < diff; i++)
1161*5a6e8488SAndroid Build Coastguard Worker {
1162*5a6e8488SAndroid Build Coastguard Worker ptr_c[i] = bc_num_subDigits(0, ptr_r[i], &carry);
1163*5a6e8488SAndroid Build Coastguard Worker }
1164*5a6e8488SAndroid Build Coastguard Worker }
1165*5a6e8488SAndroid Build Coastguard Worker else
1166*5a6e8488SAndroid Build Coastguard Worker {
1167*5a6e8488SAndroid Build Coastguard Worker // !do_sub && brdx > ardx
1168*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
1169*5a6e8488SAndroid Build Coastguard Worker memcpy(ptr_c, ptr_r, BC_NUM_SIZE(diff));
1170*5a6e8488SAndroid Build Coastguard Worker }
1171*5a6e8488SAndroid Build Coastguard Worker
1172*5a6e8488SAndroid Build Coastguard Worker // Future code needs to ignore the limbs we just did.
1173*5a6e8488SAndroid Build Coastguard Worker ptr_r += diff;
1174*5a6e8488SAndroid Build Coastguard Worker len_r -= diff;
1175*5a6e8488SAndroid Build Coastguard Worker }
1176*5a6e8488SAndroid Build Coastguard Worker
1177*5a6e8488SAndroid Build Coastguard Worker // The return value pointer needs to ignore what we just did.
1178*5a6e8488SAndroid Build Coastguard Worker ptr_c += diff;
1179*5a6e8488SAndroid Build Coastguard Worker }
1180*5a6e8488SAndroid Build Coastguard Worker
1181*5a6e8488SAndroid Build Coastguard Worker // This is the length that can be directly added/subtracted.
1182*5a6e8488SAndroid Build Coastguard Worker min_len = BC_MIN(len_l, len_r);
1183*5a6e8488SAndroid Build Coastguard Worker
1184*5a6e8488SAndroid Build Coastguard Worker // After dealing with possible low array elements that depend on only one
1185*5a6e8488SAndroid Build Coastguard Worker // operand above, the actual add or subtract can be performed as if the rdx
1186*5a6e8488SAndroid Build Coastguard Worker // of both operands was the same.
1187*5a6e8488SAndroid Build Coastguard Worker //
1188*5a6e8488SAndroid Build Coastguard Worker // Inlining takes care of eliminating constant zero arguments to
1189*5a6e8488SAndroid Build Coastguard Worker // addDigit/subDigit (checked in disassembly of resulting bc binary
1190*5a6e8488SAndroid Build Coastguard Worker // compiled with gcc and clang).
1191*5a6e8488SAndroid Build Coastguard Worker if (do_sub)
1192*5a6e8488SAndroid Build Coastguard Worker {
1193*5a6e8488SAndroid Build Coastguard Worker // Actual subtraction.
1194*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < min_len; ++i)
1195*5a6e8488SAndroid Build Coastguard Worker {
1196*5a6e8488SAndroid Build Coastguard Worker ptr_c[i] = bc_num_subDigits(ptr_l[i], ptr_r[i], &carry);
1197*5a6e8488SAndroid Build Coastguard Worker }
1198*5a6e8488SAndroid Build Coastguard Worker
1199*5a6e8488SAndroid Build Coastguard Worker // Finishing the limbs beyond the direct subtraction.
1200*5a6e8488SAndroid Build Coastguard Worker for (; i < len_l; ++i)
1201*5a6e8488SAndroid Build Coastguard Worker {
1202*5a6e8488SAndroid Build Coastguard Worker ptr_c[i] = bc_num_subDigits(ptr_l[i], 0, &carry);
1203*5a6e8488SAndroid Build Coastguard Worker }
1204*5a6e8488SAndroid Build Coastguard Worker }
1205*5a6e8488SAndroid Build Coastguard Worker else
1206*5a6e8488SAndroid Build Coastguard Worker {
1207*5a6e8488SAndroid Build Coastguard Worker // Actual addition.
1208*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < min_len; ++i)
1209*5a6e8488SAndroid Build Coastguard Worker {
1210*5a6e8488SAndroid Build Coastguard Worker ptr_c[i] = bc_num_addDigits(ptr_l[i], ptr_r[i], &carry);
1211*5a6e8488SAndroid Build Coastguard Worker }
1212*5a6e8488SAndroid Build Coastguard Worker
1213*5a6e8488SAndroid Build Coastguard Worker // Finishing the limbs beyond the direct addition.
1214*5a6e8488SAndroid Build Coastguard Worker for (; i < len_l; ++i)
1215*5a6e8488SAndroid Build Coastguard Worker {
1216*5a6e8488SAndroid Build Coastguard Worker ptr_c[i] = bc_num_addDigits(ptr_l[i], 0, &carry);
1217*5a6e8488SAndroid Build Coastguard Worker }
1218*5a6e8488SAndroid Build Coastguard Worker
1219*5a6e8488SAndroid Build Coastguard Worker // Addition can create an extra limb. We take care of that here.
1220*5a6e8488SAndroid Build Coastguard Worker ptr_c[i] = bc_num_addDigits(0, 0, &carry);
1221*5a6e8488SAndroid Build Coastguard Worker }
1222*5a6e8488SAndroid Build Coastguard Worker
1223*5a6e8488SAndroid Build Coastguard Worker assert(carry == false);
1224*5a6e8488SAndroid Build Coastguard Worker
1225*5a6e8488SAndroid Build Coastguard Worker // The result has the same sign as a, unless the operation was a
1226*5a6e8488SAndroid Build Coastguard Worker // reverse subtraction (b - a).
1227*5a6e8488SAndroid Build Coastguard Worker c_neg = BC_NUM_NEG(a) != (do_sub && do_rev_sub);
1228*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET_NEG(c, max_rdx, c_neg);
1229*5a6e8488SAndroid Build Coastguard Worker c->len = max_len;
1230*5a6e8488SAndroid Build Coastguard Worker c->scale = BC_MAX(a->scale, b->scale);
1231*5a6e8488SAndroid Build Coastguard Worker
1232*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(c);
1233*5a6e8488SAndroid Build Coastguard Worker }
1234*5a6e8488SAndroid Build Coastguard Worker
1235*5a6e8488SAndroid Build Coastguard Worker /**
1236*5a6e8488SAndroid Build Coastguard Worker * The simple multiplication that karatsuba dishes out to when the length of the
1237*5a6e8488SAndroid Build Coastguard Worker * numbers gets low enough. This doesn't use scale because it treats the
1238*5a6e8488SAndroid Build Coastguard Worker * operands as though they are integers.
1239*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
1240*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
1241*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
1242*5a6e8488SAndroid Build Coastguard Worker */
1243*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_m_simp(const BcNum * a,const BcNum * b,BcNum * restrict c)1244*5a6e8488SAndroid Build Coastguard Worker bc_num_m_simp(const BcNum* a, const BcNum* b, BcNum* restrict c)
1245*5a6e8488SAndroid Build Coastguard Worker {
1246*5a6e8488SAndroid Build Coastguard Worker size_t i, alen = a->len, blen = b->len, clen;
1247*5a6e8488SAndroid Build Coastguard Worker BcDig* ptr_a = a->num;
1248*5a6e8488SAndroid Build Coastguard Worker BcDig* ptr_b = b->num;
1249*5a6e8488SAndroid Build Coastguard Worker BcDig* ptr_c;
1250*5a6e8488SAndroid Build Coastguard Worker BcBigDig sum = 0, carry = 0;
1251*5a6e8488SAndroid Build Coastguard Worker
1252*5a6e8488SAndroid Build Coastguard Worker assert(sizeof(sum) >= sizeof(BcDig) * 2);
1253*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b));
1254*5a6e8488SAndroid Build Coastguard Worker
1255*5a6e8488SAndroid Build Coastguard Worker // Make sure c is big enough.
1256*5a6e8488SAndroid Build Coastguard Worker clen = bc_vm_growSize(alen, blen);
1257*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(c, bc_vm_growSize(clen, 1));
1258*5a6e8488SAndroid Build Coastguard Worker
1259*5a6e8488SAndroid Build Coastguard Worker // If we don't memset, then we might have uninitialized data use later.
1260*5a6e8488SAndroid Build Coastguard Worker ptr_c = c->num;
1261*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
1262*5a6e8488SAndroid Build Coastguard Worker memset(ptr_c, 0, BC_NUM_SIZE(c->cap));
1263*5a6e8488SAndroid Build Coastguard Worker
1264*5a6e8488SAndroid Build Coastguard Worker // This is the actual multiplication loop. It uses the lattice form of long
1265*5a6e8488SAndroid Build Coastguard Worker // multiplication (see the explanation on the web page at
1266*5a6e8488SAndroid Build Coastguard Worker // https://knilt.arcc.albany.edu/What_is_Lattice_Multiplication or the
1267*5a6e8488SAndroid Build Coastguard Worker // explanation at Wikipedia).
1268*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < clen; ++i)
1269*5a6e8488SAndroid Build Coastguard Worker {
1270*5a6e8488SAndroid Build Coastguard Worker ssize_t sidx = (ssize_t) (i - blen + 1);
1271*5a6e8488SAndroid Build Coastguard Worker size_t j, k;
1272*5a6e8488SAndroid Build Coastguard Worker
1273*5a6e8488SAndroid Build Coastguard Worker // These are the start indices.
1274*5a6e8488SAndroid Build Coastguard Worker j = (size_t) BC_MAX(0, sidx);
1275*5a6e8488SAndroid Build Coastguard Worker k = BC_MIN(i, blen - 1);
1276*5a6e8488SAndroid Build Coastguard Worker
1277*5a6e8488SAndroid Build Coastguard Worker // On every iteration of this loop, a multiplication happens, then the
1278*5a6e8488SAndroid Build Coastguard Worker // sum is automatically calculated.
1279*5a6e8488SAndroid Build Coastguard Worker for (; j < alen && k < blen; ++j, --k)
1280*5a6e8488SAndroid Build Coastguard Worker {
1281*5a6e8488SAndroid Build Coastguard Worker sum += ((BcBigDig) ptr_a[j]) * ((BcBigDig) ptr_b[k]);
1282*5a6e8488SAndroid Build Coastguard Worker
1283*5a6e8488SAndroid Build Coastguard Worker if (sum >= ((BcBigDig) BC_BASE_POW) * BC_BASE_POW)
1284*5a6e8488SAndroid Build Coastguard Worker {
1285*5a6e8488SAndroid Build Coastguard Worker carry += sum / BC_BASE_POW;
1286*5a6e8488SAndroid Build Coastguard Worker sum %= BC_BASE_POW;
1287*5a6e8488SAndroid Build Coastguard Worker }
1288*5a6e8488SAndroid Build Coastguard Worker }
1289*5a6e8488SAndroid Build Coastguard Worker
1290*5a6e8488SAndroid Build Coastguard Worker // Calculate the carry.
1291*5a6e8488SAndroid Build Coastguard Worker if (sum >= BC_BASE_POW)
1292*5a6e8488SAndroid Build Coastguard Worker {
1293*5a6e8488SAndroid Build Coastguard Worker carry += sum / BC_BASE_POW;
1294*5a6e8488SAndroid Build Coastguard Worker sum %= BC_BASE_POW;
1295*5a6e8488SAndroid Build Coastguard Worker }
1296*5a6e8488SAndroid Build Coastguard Worker
1297*5a6e8488SAndroid Build Coastguard Worker // Store and set up for next iteration.
1298*5a6e8488SAndroid Build Coastguard Worker ptr_c[i] = (BcDig) sum;
1299*5a6e8488SAndroid Build Coastguard Worker assert(ptr_c[i] < BC_BASE_POW);
1300*5a6e8488SAndroid Build Coastguard Worker sum = carry;
1301*5a6e8488SAndroid Build Coastguard Worker carry = 0;
1302*5a6e8488SAndroid Build Coastguard Worker }
1303*5a6e8488SAndroid Build Coastguard Worker
1304*5a6e8488SAndroid Build Coastguard Worker // This should always be true because there should be no carry on the last
1305*5a6e8488SAndroid Build Coastguard Worker // digit; multiplication never goes above the sum of both lengths.
1306*5a6e8488SAndroid Build Coastguard Worker assert(!sum);
1307*5a6e8488SAndroid Build Coastguard Worker
1308*5a6e8488SAndroid Build Coastguard Worker c->len = clen;
1309*5a6e8488SAndroid Build Coastguard Worker }
1310*5a6e8488SAndroid Build Coastguard Worker
1311*5a6e8488SAndroid Build Coastguard Worker /**
1312*5a6e8488SAndroid Build Coastguard Worker * Does a shifted add or subtract for Karatsuba below. This calls either
1313*5a6e8488SAndroid Build Coastguard Worker * bc_num_addArrays() or bc_num_subArrays().
1314*5a6e8488SAndroid Build Coastguard Worker * @param n An in/out parameter; the first operand and return parameter.
1315*5a6e8488SAndroid Build Coastguard Worker * @param a The second operand.
1316*5a6e8488SAndroid Build Coastguard Worker * @param shift The amount to shift @a n by when adding/subtracting.
1317*5a6e8488SAndroid Build Coastguard Worker * @param op The function to call, either bc_num_addArrays() or
1318*5a6e8488SAndroid Build Coastguard Worker * bc_num_subArrays().
1319*5a6e8488SAndroid Build Coastguard Worker */
1320*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_shiftAddSub(BcNum * restrict n,const BcNum * restrict a,size_t shift,BcNumShiftAddOp op)1321*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftAddSub(BcNum* restrict n, const BcNum* restrict a, size_t shift,
1322*5a6e8488SAndroid Build Coastguard Worker BcNumShiftAddOp op)
1323*5a6e8488SAndroid Build Coastguard Worker {
1324*5a6e8488SAndroid Build Coastguard Worker assert(n->len >= shift + a->len);
1325*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_RDX_VAL(n) && !BC_NUM_RDX_VAL(a));
1326*5a6e8488SAndroid Build Coastguard Worker op(n->num + shift, a->num, a->len);
1327*5a6e8488SAndroid Build Coastguard Worker }
1328*5a6e8488SAndroid Build Coastguard Worker
1329*5a6e8488SAndroid Build Coastguard Worker /**
1330*5a6e8488SAndroid Build Coastguard Worker * Implements the Karatsuba algorithm.
1331*5a6e8488SAndroid Build Coastguard Worker */
1332*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_k(const BcNum * a,const BcNum * b,BcNum * restrict c)1333*5a6e8488SAndroid Build Coastguard Worker bc_num_k(const BcNum* a, const BcNum* b, BcNum* restrict c)
1334*5a6e8488SAndroid Build Coastguard Worker {
1335*5a6e8488SAndroid Build Coastguard Worker size_t max, max2, total;
1336*5a6e8488SAndroid Build Coastguard Worker BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
1337*5a6e8488SAndroid Build Coastguard Worker BcDig* digs;
1338*5a6e8488SAndroid Build Coastguard Worker BcDig* dig_ptr;
1339*5a6e8488SAndroid Build Coastguard Worker BcNumShiftAddOp op;
1340*5a6e8488SAndroid Build Coastguard Worker bool aone = BC_NUM_ONE(a);
1341*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
1342*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1343*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
1344*5a6e8488SAndroid Build Coastguard Worker
1345*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_ZERO(c));
1346*5a6e8488SAndroid Build Coastguard Worker
1347*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(a) || BC_NUM_ZERO(b)) return;
1348*5a6e8488SAndroid Build Coastguard Worker
1349*5a6e8488SAndroid Build Coastguard Worker if (aone || BC_NUM_ONE(b))
1350*5a6e8488SAndroid Build Coastguard Worker {
1351*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(c, aone ? b : a);
1352*5a6e8488SAndroid Build Coastguard Worker if ((aone && BC_NUM_NEG(a)) || BC_NUM_NEG(b)) BC_NUM_NEG_TGL(c);
1353*5a6e8488SAndroid Build Coastguard Worker return;
1354*5a6e8488SAndroid Build Coastguard Worker }
1355*5a6e8488SAndroid Build Coastguard Worker
1356*5a6e8488SAndroid Build Coastguard Worker // Shell out to the simple algorithm with certain conditions.
1357*5a6e8488SAndroid Build Coastguard Worker if (a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN)
1358*5a6e8488SAndroid Build Coastguard Worker {
1359*5a6e8488SAndroid Build Coastguard Worker bc_num_m_simp(a, b, c);
1360*5a6e8488SAndroid Build Coastguard Worker return;
1361*5a6e8488SAndroid Build Coastguard Worker }
1362*5a6e8488SAndroid Build Coastguard Worker
1363*5a6e8488SAndroid Build Coastguard Worker // We need to calculate the max size of the numbers that can result from the
1364*5a6e8488SAndroid Build Coastguard Worker // operations.
1365*5a6e8488SAndroid Build Coastguard Worker max = BC_MAX(a->len, b->len);
1366*5a6e8488SAndroid Build Coastguard Worker max = BC_MAX(max, BC_NUM_DEF_SIZE);
1367*5a6e8488SAndroid Build Coastguard Worker max2 = (max + 1) / 2;
1368*5a6e8488SAndroid Build Coastguard Worker
1369*5a6e8488SAndroid Build Coastguard Worker // Calculate the space needed for all of the temporary allocations. We do
1370*5a6e8488SAndroid Build Coastguard Worker // this to just allocate once.
1371*5a6e8488SAndroid Build Coastguard Worker total = bc_vm_arraySize(BC_NUM_KARATSUBA_ALLOCS, max);
1372*5a6e8488SAndroid Build Coastguard Worker
1373*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
1374*5a6e8488SAndroid Build Coastguard Worker
1375*5a6e8488SAndroid Build Coastguard Worker // Allocate space for all of the temporaries.
1376*5a6e8488SAndroid Build Coastguard Worker digs = dig_ptr = bc_vm_malloc(BC_NUM_SIZE(total));
1377*5a6e8488SAndroid Build Coastguard Worker
1378*5a6e8488SAndroid Build Coastguard Worker // Set up the temporaries.
1379*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&l1, dig_ptr, max);
1380*5a6e8488SAndroid Build Coastguard Worker dig_ptr += max;
1381*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&h1, dig_ptr, max);
1382*5a6e8488SAndroid Build Coastguard Worker dig_ptr += max;
1383*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&l2, dig_ptr, max);
1384*5a6e8488SAndroid Build Coastguard Worker dig_ptr += max;
1385*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&h2, dig_ptr, max);
1386*5a6e8488SAndroid Build Coastguard Worker dig_ptr += max;
1387*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&m1, dig_ptr, max);
1388*5a6e8488SAndroid Build Coastguard Worker dig_ptr += max;
1389*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&m2, dig_ptr, max);
1390*5a6e8488SAndroid Build Coastguard Worker
1391*5a6e8488SAndroid Build Coastguard Worker // Some temporaries need the ability to grow, so we allocate them
1392*5a6e8488SAndroid Build Coastguard Worker // separately.
1393*5a6e8488SAndroid Build Coastguard Worker max = bc_vm_growSize(max, 1);
1394*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&z0, max);
1395*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&z1, max);
1396*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&z2, max);
1397*5a6e8488SAndroid Build Coastguard Worker max = bc_vm_growSize(max, max) + 1;
1398*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&temp, max);
1399*5a6e8488SAndroid Build Coastguard Worker
1400*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
1401*5a6e8488SAndroid Build Coastguard Worker
1402*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
1403*5a6e8488SAndroid Build Coastguard Worker
1404*5a6e8488SAndroid Build Coastguard Worker // First, set up c.
1405*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(c, max);
1406*5a6e8488SAndroid Build Coastguard Worker c->len = max;
1407*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
1408*5a6e8488SAndroid Build Coastguard Worker memset(c->num, 0, BC_NUM_SIZE(c->len));
1409*5a6e8488SAndroid Build Coastguard Worker
1410*5a6e8488SAndroid Build Coastguard Worker // Split the parameters.
1411*5a6e8488SAndroid Build Coastguard Worker bc_num_split(a, max2, &l1, &h1);
1412*5a6e8488SAndroid Build Coastguard Worker bc_num_split(b, max2, &l2, &h2);
1413*5a6e8488SAndroid Build Coastguard Worker
1414*5a6e8488SAndroid Build Coastguard Worker // Do the subtraction.
1415*5a6e8488SAndroid Build Coastguard Worker bc_num_sub(&h1, &l1, &m1, 0);
1416*5a6e8488SAndroid Build Coastguard Worker bc_num_sub(&l2, &h2, &m2, 0);
1417*5a6e8488SAndroid Build Coastguard Worker
1418*5a6e8488SAndroid Build Coastguard Worker // The if statements below are there for efficiency reasons. The best way to
1419*5a6e8488SAndroid Build Coastguard Worker // understand them is to understand the Karatsuba algorithm because now that
1420*5a6e8488SAndroid Build Coastguard Worker // the ollocations and splits are done, the algorithm is pretty
1421*5a6e8488SAndroid Build Coastguard Worker // straightforward.
1422*5a6e8488SAndroid Build Coastguard Worker
1423*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(&h1) && BC_NUM_NONZERO(&h2))
1424*5a6e8488SAndroid Build Coastguard Worker {
1425*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(h1));
1426*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(h2));
1427*5a6e8488SAndroid Build Coastguard Worker
1428*5a6e8488SAndroid Build Coastguard Worker bc_num_m(&h1, &h2, &z2, 0);
1429*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(&z2);
1430*5a6e8488SAndroid Build Coastguard Worker
1431*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftAddSub(c, &z2, max2 * 2, bc_num_addArrays);
1432*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftAddSub(c, &z2, max2, bc_num_addArrays);
1433*5a6e8488SAndroid Build Coastguard Worker }
1434*5a6e8488SAndroid Build Coastguard Worker
1435*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(&l1) && BC_NUM_NONZERO(&l2))
1436*5a6e8488SAndroid Build Coastguard Worker {
1437*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(l1));
1438*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(l2));
1439*5a6e8488SAndroid Build Coastguard Worker
1440*5a6e8488SAndroid Build Coastguard Worker bc_num_m(&l1, &l2, &z0, 0);
1441*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(&z0);
1442*5a6e8488SAndroid Build Coastguard Worker
1443*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftAddSub(c, &z0, max2, bc_num_addArrays);
1444*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftAddSub(c, &z0, 0, bc_num_addArrays);
1445*5a6e8488SAndroid Build Coastguard Worker }
1446*5a6e8488SAndroid Build Coastguard Worker
1447*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(&m1) && BC_NUM_NONZERO(&m2))
1448*5a6e8488SAndroid Build Coastguard Worker {
1449*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(m1));
1450*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(m1));
1451*5a6e8488SAndroid Build Coastguard Worker
1452*5a6e8488SAndroid Build Coastguard Worker bc_num_m(&m1, &m2, &z1, 0);
1453*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(&z1);
1454*5a6e8488SAndroid Build Coastguard Worker
1455*5a6e8488SAndroid Build Coastguard Worker op = (BC_NUM_NEG_NP(m1) != BC_NUM_NEG_NP(m2)) ?
1456*5a6e8488SAndroid Build Coastguard Worker bc_num_subArrays :
1457*5a6e8488SAndroid Build Coastguard Worker bc_num_addArrays;
1458*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftAddSub(c, &z1, max2, op);
1459*5a6e8488SAndroid Build Coastguard Worker }
1460*5a6e8488SAndroid Build Coastguard Worker
1461*5a6e8488SAndroid Build Coastguard Worker err:
1462*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
1463*5a6e8488SAndroid Build Coastguard Worker free(digs);
1464*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&temp);
1465*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&z2);
1466*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&z1);
1467*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&z0);
1468*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
1469*5a6e8488SAndroid Build Coastguard Worker }
1470*5a6e8488SAndroid Build Coastguard Worker
1471*5a6e8488SAndroid Build Coastguard Worker /**
1472*5a6e8488SAndroid Build Coastguard Worker * Does checks for Karatsuba. It also changes things to ensure that the
1473*5a6e8488SAndroid Build Coastguard Worker * Karatsuba and simple multiplication can treat the numbers as integers. This
1474*5a6e8488SAndroid Build Coastguard Worker * is a BcNumBinOp function.
1475*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
1476*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
1477*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
1478*5a6e8488SAndroid Build Coastguard Worker * @param scale The current scale.
1479*5a6e8488SAndroid Build Coastguard Worker */
1480*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_m(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)1481*5a6e8488SAndroid Build Coastguard Worker bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
1482*5a6e8488SAndroid Build Coastguard Worker {
1483*5a6e8488SAndroid Build Coastguard Worker BcNum cpa, cpb;
1484*5a6e8488SAndroid Build Coastguard Worker size_t ascale, bscale, ardx, brdx, zero, len, rscale;
1485*5a6e8488SAndroid Build Coastguard Worker // These are meant to quiet warnings on GCC about longjmp() clobbering.
1486*5a6e8488SAndroid Build Coastguard Worker // The problem is real here.
1487*5a6e8488SAndroid Build Coastguard Worker size_t scale1, scale2, realscale;
1488*5a6e8488SAndroid Build Coastguard Worker // These are meant to quiet the GCC longjmp() clobbering, even though it
1489*5a6e8488SAndroid Build Coastguard Worker // does not apply here.
1490*5a6e8488SAndroid Build Coastguard Worker volatile size_t azero;
1491*5a6e8488SAndroid Build Coastguard Worker volatile size_t bzero;
1492*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
1493*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1494*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
1495*5a6e8488SAndroid Build Coastguard Worker
1496*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
1497*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
1498*5a6e8488SAndroid Build Coastguard Worker
1499*5a6e8488SAndroid Build Coastguard Worker bc_num_zero(c);
1500*5a6e8488SAndroid Build Coastguard Worker
1501*5a6e8488SAndroid Build Coastguard Worker ascale = a->scale;
1502*5a6e8488SAndroid Build Coastguard Worker bscale = b->scale;
1503*5a6e8488SAndroid Build Coastguard Worker
1504*5a6e8488SAndroid Build Coastguard Worker // This sets the final scale according to the bc spec.
1505*5a6e8488SAndroid Build Coastguard Worker scale1 = BC_MAX(scale, ascale);
1506*5a6e8488SAndroid Build Coastguard Worker scale2 = BC_MAX(scale1, bscale);
1507*5a6e8488SAndroid Build Coastguard Worker rscale = ascale + bscale;
1508*5a6e8488SAndroid Build Coastguard Worker realscale = BC_MIN(rscale, scale2);
1509*5a6e8488SAndroid Build Coastguard Worker
1510*5a6e8488SAndroid Build Coastguard Worker // If this condition is true, we can use bc_num_mulArray(), which would be
1511*5a6e8488SAndroid Build Coastguard Worker // much faster.
1512*5a6e8488SAndroid Build Coastguard Worker if ((a->len == 1 || b->len == 1) && !a->rdx && !b->rdx)
1513*5a6e8488SAndroid Build Coastguard Worker {
1514*5a6e8488SAndroid Build Coastguard Worker BcNum* operand;
1515*5a6e8488SAndroid Build Coastguard Worker BcBigDig dig;
1516*5a6e8488SAndroid Build Coastguard Worker
1517*5a6e8488SAndroid Build Coastguard Worker // Set the correct operands.
1518*5a6e8488SAndroid Build Coastguard Worker if (a->len == 1)
1519*5a6e8488SAndroid Build Coastguard Worker {
1520*5a6e8488SAndroid Build Coastguard Worker dig = (BcBigDig) a->num[0];
1521*5a6e8488SAndroid Build Coastguard Worker operand = b;
1522*5a6e8488SAndroid Build Coastguard Worker }
1523*5a6e8488SAndroid Build Coastguard Worker else
1524*5a6e8488SAndroid Build Coastguard Worker {
1525*5a6e8488SAndroid Build Coastguard Worker dig = (BcBigDig) b->num[0];
1526*5a6e8488SAndroid Build Coastguard Worker operand = a;
1527*5a6e8488SAndroid Build Coastguard Worker }
1528*5a6e8488SAndroid Build Coastguard Worker
1529*5a6e8488SAndroid Build Coastguard Worker bc_num_mulArray(operand, dig, c);
1530*5a6e8488SAndroid Build Coastguard Worker
1531*5a6e8488SAndroid Build Coastguard Worker // Need to make sure the sign is correct.
1532*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(c))
1533*5a6e8488SAndroid Build Coastguard Worker {
1534*5a6e8488SAndroid Build Coastguard Worker c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(a) != BC_NUM_NEG(b));
1535*5a6e8488SAndroid Build Coastguard Worker }
1536*5a6e8488SAndroid Build Coastguard Worker
1537*5a6e8488SAndroid Build Coastguard Worker return;
1538*5a6e8488SAndroid Build Coastguard Worker }
1539*5a6e8488SAndroid Build Coastguard Worker
1540*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
1541*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
1542*5a6e8488SAndroid Build Coastguard Worker
1543*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
1544*5a6e8488SAndroid Build Coastguard Worker
1545*5a6e8488SAndroid Build Coastguard Worker // We need copies because of all of the mutation needed to make Karatsuba
1546*5a6e8488SAndroid Build Coastguard Worker // think the numbers are integers.
1547*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&cpa, a->len + BC_NUM_RDX_VAL(a));
1548*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&cpb, b->len + BC_NUM_RDX_VAL(b));
1549*5a6e8488SAndroid Build Coastguard Worker
1550*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, init_err);
1551*5a6e8488SAndroid Build Coastguard Worker
1552*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
1553*5a6e8488SAndroid Build Coastguard Worker
1554*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(&cpa, a);
1555*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(&cpb, b);
1556*5a6e8488SAndroid Build Coastguard Worker
1557*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(cpa));
1558*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(cpb));
1559*5a6e8488SAndroid Build Coastguard Worker
1560*5a6e8488SAndroid Build Coastguard Worker BC_NUM_NEG_CLR_NP(cpa);
1561*5a6e8488SAndroid Build Coastguard Worker BC_NUM_NEG_CLR_NP(cpb);
1562*5a6e8488SAndroid Build Coastguard Worker
1563*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(cpa));
1564*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(cpb));
1565*5a6e8488SAndroid Build Coastguard Worker
1566*5a6e8488SAndroid Build Coastguard Worker // These are what makes them appear like integers.
1567*5a6e8488SAndroid Build Coastguard Worker ardx = BC_NUM_RDX_VAL_NP(cpa) * BC_BASE_DIGS;
1568*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(&cpa, ardx);
1569*5a6e8488SAndroid Build Coastguard Worker
1570*5a6e8488SAndroid Build Coastguard Worker brdx = BC_NUM_RDX_VAL_NP(cpb) * BC_BASE_DIGS;
1571*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(&cpb, brdx);
1572*5a6e8488SAndroid Build Coastguard Worker
1573*5a6e8488SAndroid Build Coastguard Worker // We need to reset the jump here because azero and bzero are used in the
1574*5a6e8488SAndroid Build Coastguard Worker // cleanup, and local variables are not guaranteed to be the same after a
1575*5a6e8488SAndroid Build Coastguard Worker // jump.
1576*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
1577*5a6e8488SAndroid Build Coastguard Worker
1578*5a6e8488SAndroid Build Coastguard Worker BC_UNSETJMP(vm);
1579*5a6e8488SAndroid Build Coastguard Worker
1580*5a6e8488SAndroid Build Coastguard Worker // We want to ignore zero limbs.
1581*5a6e8488SAndroid Build Coastguard Worker azero = bc_num_shiftZero(&cpa);
1582*5a6e8488SAndroid Build Coastguard Worker bzero = bc_num_shiftZero(&cpb);
1583*5a6e8488SAndroid Build Coastguard Worker
1584*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
1585*5a6e8488SAndroid Build Coastguard Worker
1586*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
1587*5a6e8488SAndroid Build Coastguard Worker
1588*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(&cpa);
1589*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(&cpb);
1590*5a6e8488SAndroid Build Coastguard Worker
1591*5a6e8488SAndroid Build Coastguard Worker bc_num_k(&cpa, &cpb, c);
1592*5a6e8488SAndroid Build Coastguard Worker
1593*5a6e8488SAndroid Build Coastguard Worker // The return parameter needs to have its scale set. This is the start. It
1594*5a6e8488SAndroid Build Coastguard Worker // also needs to be shifted by the same amount as a and b have limbs after
1595*5a6e8488SAndroid Build Coastguard Worker // the decimal point.
1596*5a6e8488SAndroid Build Coastguard Worker zero = bc_vm_growSize(azero, bzero);
1597*5a6e8488SAndroid Build Coastguard Worker len = bc_vm_growSize(c->len, zero);
1598*5a6e8488SAndroid Build Coastguard Worker
1599*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(c, len);
1600*5a6e8488SAndroid Build Coastguard Worker
1601*5a6e8488SAndroid Build Coastguard Worker // Shift c based on the limbs after the decimal point in a and b.
1602*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(c, (len - c->len) * BC_BASE_DIGS);
1603*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftRight(c, ardx + brdx);
1604*5a6e8488SAndroid Build Coastguard Worker
1605*5a6e8488SAndroid Build Coastguard Worker bc_num_retireMul(c, realscale, BC_NUM_NEG(a), BC_NUM_NEG(b));
1606*5a6e8488SAndroid Build Coastguard Worker
1607*5a6e8488SAndroid Build Coastguard Worker err:
1608*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
1609*5a6e8488SAndroid Build Coastguard Worker bc_num_unshiftZero(&cpb, bzero);
1610*5a6e8488SAndroid Build Coastguard Worker bc_num_unshiftZero(&cpa, azero);
1611*5a6e8488SAndroid Build Coastguard Worker init_err:
1612*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
1613*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&cpb);
1614*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&cpa);
1615*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
1616*5a6e8488SAndroid Build Coastguard Worker }
1617*5a6e8488SAndroid Build Coastguard Worker
1618*5a6e8488SAndroid Build Coastguard Worker /**
1619*5a6e8488SAndroid Build Coastguard Worker * Returns true if the BcDig array has non-zero limbs, false otherwise.
1620*5a6e8488SAndroid Build Coastguard Worker * @param a The array to test.
1621*5a6e8488SAndroid Build Coastguard Worker * @param len The length of the array.
1622*5a6e8488SAndroid Build Coastguard Worker * @return True if @a has any non-zero limbs, false otherwise.
1623*5a6e8488SAndroid Build Coastguard Worker */
1624*5a6e8488SAndroid Build Coastguard Worker static bool
bc_num_nonZeroDig(BcDig * restrict a,size_t len)1625*5a6e8488SAndroid Build Coastguard Worker bc_num_nonZeroDig(BcDig* restrict a, size_t len)
1626*5a6e8488SAndroid Build Coastguard Worker {
1627*5a6e8488SAndroid Build Coastguard Worker size_t i;
1628*5a6e8488SAndroid Build Coastguard Worker
1629*5a6e8488SAndroid Build Coastguard Worker for (i = len - 1; i < len; --i)
1630*5a6e8488SAndroid Build Coastguard Worker {
1631*5a6e8488SAndroid Build Coastguard Worker if (a[i] != 0) return true;
1632*5a6e8488SAndroid Build Coastguard Worker }
1633*5a6e8488SAndroid Build Coastguard Worker
1634*5a6e8488SAndroid Build Coastguard Worker return false;
1635*5a6e8488SAndroid Build Coastguard Worker }
1636*5a6e8488SAndroid Build Coastguard Worker
1637*5a6e8488SAndroid Build Coastguard Worker /**
1638*5a6e8488SAndroid Build Coastguard Worker * Compares a BcDig array against a BcNum. This is especially suited for
1639*5a6e8488SAndroid Build Coastguard Worker * division. Returns >0 if @a a is greater than @a b, <0 if it is less, and =0
1640*5a6e8488SAndroid Build Coastguard Worker * if they are equal.
1641*5a6e8488SAndroid Build Coastguard Worker * @param a The array.
1642*5a6e8488SAndroid Build Coastguard Worker * @param b The number.
1643*5a6e8488SAndroid Build Coastguard Worker * @param len The length to assume the arrays are. This is always less than the
1644*5a6e8488SAndroid Build Coastguard Worker * actual length because of how this is implemented.
1645*5a6e8488SAndroid Build Coastguard Worker */
1646*5a6e8488SAndroid Build Coastguard Worker static ssize_t
bc_num_divCmp(const BcDig * a,const BcNum * b,size_t len)1647*5a6e8488SAndroid Build Coastguard Worker bc_num_divCmp(const BcDig* a, const BcNum* b, size_t len)
1648*5a6e8488SAndroid Build Coastguard Worker {
1649*5a6e8488SAndroid Build Coastguard Worker ssize_t cmp;
1650*5a6e8488SAndroid Build Coastguard Worker
1651*5a6e8488SAndroid Build Coastguard Worker if (b->len > len && a[len]) cmp = bc_num_compare(a, b->num, len + 1);
1652*5a6e8488SAndroid Build Coastguard Worker else if (b->len <= len)
1653*5a6e8488SAndroid Build Coastguard Worker {
1654*5a6e8488SAndroid Build Coastguard Worker if (a[len]) cmp = 1;
1655*5a6e8488SAndroid Build Coastguard Worker else cmp = bc_num_compare(a, b->num, len);
1656*5a6e8488SAndroid Build Coastguard Worker }
1657*5a6e8488SAndroid Build Coastguard Worker else cmp = -1;
1658*5a6e8488SAndroid Build Coastguard Worker
1659*5a6e8488SAndroid Build Coastguard Worker return cmp;
1660*5a6e8488SAndroid Build Coastguard Worker }
1661*5a6e8488SAndroid Build Coastguard Worker
1662*5a6e8488SAndroid Build Coastguard Worker /**
1663*5a6e8488SAndroid Build Coastguard Worker * Extends the two operands of a division by BC_BASE_DIGS minus the number of
1664*5a6e8488SAndroid Build Coastguard Worker * digits in the divisor estimate. In other words, it is shifting the numbers in
1665*5a6e8488SAndroid Build Coastguard Worker * order to force the divisor estimate to fill the limb.
1666*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
1667*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
1668*5a6e8488SAndroid Build Coastguard Worker * @param divisor The divisor estimate.
1669*5a6e8488SAndroid Build Coastguard Worker */
1670*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_divExtend(BcNum * restrict a,BcNum * restrict b,BcBigDig divisor)1671*5a6e8488SAndroid Build Coastguard Worker bc_num_divExtend(BcNum* restrict a, BcNum* restrict b, BcBigDig divisor)
1672*5a6e8488SAndroid Build Coastguard Worker {
1673*5a6e8488SAndroid Build Coastguard Worker size_t pow;
1674*5a6e8488SAndroid Build Coastguard Worker
1675*5a6e8488SAndroid Build Coastguard Worker assert(divisor < BC_BASE_POW);
1676*5a6e8488SAndroid Build Coastguard Worker
1677*5a6e8488SAndroid Build Coastguard Worker pow = BC_BASE_DIGS - bc_num_log10((size_t) divisor);
1678*5a6e8488SAndroid Build Coastguard Worker
1679*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(a, pow);
1680*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(b, pow);
1681*5a6e8488SAndroid Build Coastguard Worker }
1682*5a6e8488SAndroid Build Coastguard Worker
1683*5a6e8488SAndroid Build Coastguard Worker /**
1684*5a6e8488SAndroid Build Coastguard Worker * Actually does division. This is a rewrite of my original code by Stefan Esser
1685*5a6e8488SAndroid Build Coastguard Worker * from FreeBSD.
1686*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
1687*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
1688*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
1689*5a6e8488SAndroid Build Coastguard Worker * @param scale The current scale.
1690*5a6e8488SAndroid Build Coastguard Worker */
1691*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_d_long(BcNum * restrict a,BcNum * restrict b,BcNum * restrict c,size_t scale)1692*5a6e8488SAndroid Build Coastguard Worker bc_num_d_long(BcNum* restrict a, BcNum* restrict b, BcNum* restrict c,
1693*5a6e8488SAndroid Build Coastguard Worker size_t scale)
1694*5a6e8488SAndroid Build Coastguard Worker {
1695*5a6e8488SAndroid Build Coastguard Worker BcBigDig divisor;
1696*5a6e8488SAndroid Build Coastguard Worker size_t i, rdx;
1697*5a6e8488SAndroid Build Coastguard Worker // This is volatile and len 2 and reallen exist to quiet the GCC warning
1698*5a6e8488SAndroid Build Coastguard Worker // about clobbering on longjmp(). This one is possible, I think.
1699*5a6e8488SAndroid Build Coastguard Worker volatile size_t len;
1700*5a6e8488SAndroid Build Coastguard Worker size_t len2, reallen;
1701*5a6e8488SAndroid Build Coastguard Worker // This is volatile and realend exists to quiet the GCC warning about
1702*5a6e8488SAndroid Build Coastguard Worker // clobbering on longjmp(). This one is possible, I think.
1703*5a6e8488SAndroid Build Coastguard Worker volatile size_t end;
1704*5a6e8488SAndroid Build Coastguard Worker size_t realend;
1705*5a6e8488SAndroid Build Coastguard Worker BcNum cpb;
1706*5a6e8488SAndroid Build Coastguard Worker // This is volatile and realnonzero exists to quiet the GCC warning about
1707*5a6e8488SAndroid Build Coastguard Worker // clobbering on longjmp(). This one is possible, I think.
1708*5a6e8488SAndroid Build Coastguard Worker volatile bool nonzero;
1709*5a6e8488SAndroid Build Coastguard Worker bool realnonzero;
1710*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
1711*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1712*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
1713*5a6e8488SAndroid Build Coastguard Worker
1714*5a6e8488SAndroid Build Coastguard Worker assert(b->len < a->len);
1715*5a6e8488SAndroid Build Coastguard Worker
1716*5a6e8488SAndroid Build Coastguard Worker len = b->len;
1717*5a6e8488SAndroid Build Coastguard Worker end = a->len - len;
1718*5a6e8488SAndroid Build Coastguard Worker
1719*5a6e8488SAndroid Build Coastguard Worker assert(len >= 1);
1720*5a6e8488SAndroid Build Coastguard Worker
1721*5a6e8488SAndroid Build Coastguard Worker // This is a final time to make sure c is big enough and that its array is
1722*5a6e8488SAndroid Build Coastguard Worker // properly zeroed.
1723*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(c, a->len);
1724*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
1725*5a6e8488SAndroid Build Coastguard Worker memset(c->num, 0, c->cap * sizeof(BcDig));
1726*5a6e8488SAndroid Build Coastguard Worker
1727*5a6e8488SAndroid Build Coastguard Worker // Setup.
1728*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(c, BC_NUM_RDX_VAL(a));
1729*5a6e8488SAndroid Build Coastguard Worker c->scale = a->scale;
1730*5a6e8488SAndroid Build Coastguard Worker c->len = a->len;
1731*5a6e8488SAndroid Build Coastguard Worker
1732*5a6e8488SAndroid Build Coastguard Worker // This is pulling the most significant limb of b in order to establish a
1733*5a6e8488SAndroid Build Coastguard Worker // good "estimate" for the actual divisor.
1734*5a6e8488SAndroid Build Coastguard Worker divisor = (BcBigDig) b->num[len - 1];
1735*5a6e8488SAndroid Build Coastguard Worker
1736*5a6e8488SAndroid Build Coastguard Worker // The entire bit of code in this if statement is to tighten the estimate of
1737*5a6e8488SAndroid Build Coastguard Worker // the divisor. The condition asks if b has any other non-zero limbs.
1738*5a6e8488SAndroid Build Coastguard Worker if (len > 1 && bc_num_nonZeroDig(b->num, len - 1))
1739*5a6e8488SAndroid Build Coastguard Worker {
1740*5a6e8488SAndroid Build Coastguard Worker // This takes a little bit of understanding. The "10*BC_BASE_DIGS/6+1"
1741*5a6e8488SAndroid Build Coastguard Worker // results in either 16 for 64-bit 9-digit limbs or 7 for 32-bit 4-digit
1742*5a6e8488SAndroid Build Coastguard Worker // limbs. Then it shifts a 1 by that many, which in both cases, puts the
1743*5a6e8488SAndroid Build Coastguard Worker // result above *half* of the max value a limb can store. Basically,
1744*5a6e8488SAndroid Build Coastguard Worker // this quickly calculates if the divisor is greater than half the max
1745*5a6e8488SAndroid Build Coastguard Worker // of a limb.
1746*5a6e8488SAndroid Build Coastguard Worker nonzero = (divisor > 1 << ((10 * BC_BASE_DIGS) / 6 + 1));
1747*5a6e8488SAndroid Build Coastguard Worker
1748*5a6e8488SAndroid Build Coastguard Worker // If the divisor is *not* greater than half the limb...
1749*5a6e8488SAndroid Build Coastguard Worker if (!nonzero)
1750*5a6e8488SAndroid Build Coastguard Worker {
1751*5a6e8488SAndroid Build Coastguard Worker // Extend the parameters by the number of missing digits in the
1752*5a6e8488SAndroid Build Coastguard Worker // divisor.
1753*5a6e8488SAndroid Build Coastguard Worker bc_num_divExtend(a, b, divisor);
1754*5a6e8488SAndroid Build Coastguard Worker
1755*5a6e8488SAndroid Build Coastguard Worker // Check bc_num_d(). In there, we grow a again and again. We do it
1756*5a6e8488SAndroid Build Coastguard Worker // again here; we *always* want to be sure it is big enough.
1757*5a6e8488SAndroid Build Coastguard Worker len2 = BC_MAX(a->len, b->len);
1758*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(a, len2 + 1);
1759*5a6e8488SAndroid Build Coastguard Worker
1760*5a6e8488SAndroid Build Coastguard Worker // Make a have a zero most significant limb to match the len.
1761*5a6e8488SAndroid Build Coastguard Worker if (len2 + 1 > a->len) a->len = len2 + 1;
1762*5a6e8488SAndroid Build Coastguard Worker
1763*5a6e8488SAndroid Build Coastguard Worker // Grab the new divisor estimate, new because the shift has made it
1764*5a6e8488SAndroid Build Coastguard Worker // different.
1765*5a6e8488SAndroid Build Coastguard Worker reallen = b->len;
1766*5a6e8488SAndroid Build Coastguard Worker realend = a->len - reallen;
1767*5a6e8488SAndroid Build Coastguard Worker divisor = (BcBigDig) b->num[reallen - 1];
1768*5a6e8488SAndroid Build Coastguard Worker
1769*5a6e8488SAndroid Build Coastguard Worker realnonzero = bc_num_nonZeroDig(b->num, reallen - 1);
1770*5a6e8488SAndroid Build Coastguard Worker }
1771*5a6e8488SAndroid Build Coastguard Worker else
1772*5a6e8488SAndroid Build Coastguard Worker {
1773*5a6e8488SAndroid Build Coastguard Worker realend = end;
1774*5a6e8488SAndroid Build Coastguard Worker realnonzero = nonzero;
1775*5a6e8488SAndroid Build Coastguard Worker }
1776*5a6e8488SAndroid Build Coastguard Worker }
1777*5a6e8488SAndroid Build Coastguard Worker else
1778*5a6e8488SAndroid Build Coastguard Worker {
1779*5a6e8488SAndroid Build Coastguard Worker realend = end;
1780*5a6e8488SAndroid Build Coastguard Worker realnonzero = false;
1781*5a6e8488SAndroid Build Coastguard Worker }
1782*5a6e8488SAndroid Build Coastguard Worker
1783*5a6e8488SAndroid Build Coastguard Worker // If b has other nonzero limbs, we want the divisor to be one higher, so
1784*5a6e8488SAndroid Build Coastguard Worker // that it is an upper bound.
1785*5a6e8488SAndroid Build Coastguard Worker divisor += realnonzero;
1786*5a6e8488SAndroid Build Coastguard Worker
1787*5a6e8488SAndroid Build Coastguard Worker // Make sure c can fit the new length.
1788*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(c, a->len);
1789*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
1790*5a6e8488SAndroid Build Coastguard Worker memset(c->num, 0, BC_NUM_SIZE(c->cap));
1791*5a6e8488SAndroid Build Coastguard Worker
1792*5a6e8488SAndroid Build Coastguard Worker assert(c->scale >= scale);
1793*5a6e8488SAndroid Build Coastguard Worker rdx = BC_NUM_RDX_VAL(c) - BC_NUM_RDX(scale);
1794*5a6e8488SAndroid Build Coastguard Worker
1795*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
1796*5a6e8488SAndroid Build Coastguard Worker
1797*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&cpb, len + 1);
1798*5a6e8488SAndroid Build Coastguard Worker
1799*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
1800*5a6e8488SAndroid Build Coastguard Worker
1801*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
1802*5a6e8488SAndroid Build Coastguard Worker
1803*5a6e8488SAndroid Build Coastguard Worker // This is the actual division loop.
1804*5a6e8488SAndroid Build Coastguard Worker for (i = realend - 1; i < realend && i >= rdx && BC_NUM_NONZERO(a); --i)
1805*5a6e8488SAndroid Build Coastguard Worker {
1806*5a6e8488SAndroid Build Coastguard Worker ssize_t cmp;
1807*5a6e8488SAndroid Build Coastguard Worker BcDig* n;
1808*5a6e8488SAndroid Build Coastguard Worker BcBigDig result;
1809*5a6e8488SAndroid Build Coastguard Worker
1810*5a6e8488SAndroid Build Coastguard Worker n = a->num + i;
1811*5a6e8488SAndroid Build Coastguard Worker assert(n >= a->num);
1812*5a6e8488SAndroid Build Coastguard Worker result = 0;
1813*5a6e8488SAndroid Build Coastguard Worker
1814*5a6e8488SAndroid Build Coastguard Worker cmp = bc_num_divCmp(n, b, len);
1815*5a6e8488SAndroid Build Coastguard Worker
1816*5a6e8488SAndroid Build Coastguard Worker // This is true if n is greater than b, which means that division can
1817*5a6e8488SAndroid Build Coastguard Worker // proceed, so this inner loop is the part that implements one instance
1818*5a6e8488SAndroid Build Coastguard Worker // of the division.
1819*5a6e8488SAndroid Build Coastguard Worker while (cmp >= 0)
1820*5a6e8488SAndroid Build Coastguard Worker {
1821*5a6e8488SAndroid Build Coastguard Worker BcBigDig n1, dividend, quotient;
1822*5a6e8488SAndroid Build Coastguard Worker
1823*5a6e8488SAndroid Build Coastguard Worker // These should be named obviously enough. Just imagine that it's a
1824*5a6e8488SAndroid Build Coastguard Worker // division of one limb. Because that's what it is.
1825*5a6e8488SAndroid Build Coastguard Worker n1 = (BcBigDig) n[len];
1826*5a6e8488SAndroid Build Coastguard Worker dividend = n1 * BC_BASE_POW + (BcBigDig) n[len - 1];
1827*5a6e8488SAndroid Build Coastguard Worker quotient = (dividend / divisor);
1828*5a6e8488SAndroid Build Coastguard Worker
1829*5a6e8488SAndroid Build Coastguard Worker // If this is true, then we can just subtract. Remember: setting
1830*5a6e8488SAndroid Build Coastguard Worker // quotient to 1 is not bad because we already know that n is
1831*5a6e8488SAndroid Build Coastguard Worker // greater than b.
1832*5a6e8488SAndroid Build Coastguard Worker if (quotient <= 1)
1833*5a6e8488SAndroid Build Coastguard Worker {
1834*5a6e8488SAndroid Build Coastguard Worker quotient = 1;
1835*5a6e8488SAndroid Build Coastguard Worker bc_num_subArrays(n, b->num, len);
1836*5a6e8488SAndroid Build Coastguard Worker }
1837*5a6e8488SAndroid Build Coastguard Worker else
1838*5a6e8488SAndroid Build Coastguard Worker {
1839*5a6e8488SAndroid Build Coastguard Worker assert(quotient <= BC_BASE_POW);
1840*5a6e8488SAndroid Build Coastguard Worker
1841*5a6e8488SAndroid Build Coastguard Worker // We need to multiply and subtract for a quotient above 1.
1842*5a6e8488SAndroid Build Coastguard Worker bc_num_mulArray(b, (BcBigDig) quotient, &cpb);
1843*5a6e8488SAndroid Build Coastguard Worker bc_num_subArrays(n, cpb.num, cpb.len);
1844*5a6e8488SAndroid Build Coastguard Worker }
1845*5a6e8488SAndroid Build Coastguard Worker
1846*5a6e8488SAndroid Build Coastguard Worker // The result is the *real* quotient, by the way, but it might take
1847*5a6e8488SAndroid Build Coastguard Worker // multiple trips around this loop to get it.
1848*5a6e8488SAndroid Build Coastguard Worker result += quotient;
1849*5a6e8488SAndroid Build Coastguard Worker assert(result <= BC_BASE_POW);
1850*5a6e8488SAndroid Build Coastguard Worker
1851*5a6e8488SAndroid Build Coastguard Worker // And here's why it might take multiple trips: n might *still* be
1852*5a6e8488SAndroid Build Coastguard Worker // greater than b. So we have to loop again. That's what this is
1853*5a6e8488SAndroid Build Coastguard Worker // setting up for: the condition of the while loop.
1854*5a6e8488SAndroid Build Coastguard Worker if (realnonzero) cmp = bc_num_divCmp(n, b, len);
1855*5a6e8488SAndroid Build Coastguard Worker else cmp = -1;
1856*5a6e8488SAndroid Build Coastguard Worker }
1857*5a6e8488SAndroid Build Coastguard Worker
1858*5a6e8488SAndroid Build Coastguard Worker assert(result < BC_BASE_POW);
1859*5a6e8488SAndroid Build Coastguard Worker
1860*5a6e8488SAndroid Build Coastguard Worker // Store the actual limb quotient.
1861*5a6e8488SAndroid Build Coastguard Worker c->num[i] = (BcDig) result;
1862*5a6e8488SAndroid Build Coastguard Worker }
1863*5a6e8488SAndroid Build Coastguard Worker
1864*5a6e8488SAndroid Build Coastguard Worker err:
1865*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
1866*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&cpb);
1867*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
1868*5a6e8488SAndroid Build Coastguard Worker }
1869*5a6e8488SAndroid Build Coastguard Worker
1870*5a6e8488SAndroid Build Coastguard Worker /**
1871*5a6e8488SAndroid Build Coastguard Worker * Implements division. This is a BcNumBinOp function.
1872*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
1873*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
1874*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
1875*5a6e8488SAndroid Build Coastguard Worker * @param scale The current scale.
1876*5a6e8488SAndroid Build Coastguard Worker */
1877*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_d(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)1878*5a6e8488SAndroid Build Coastguard Worker bc_num_d(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
1879*5a6e8488SAndroid Build Coastguard Worker {
1880*5a6e8488SAndroid Build Coastguard Worker size_t len, cpardx;
1881*5a6e8488SAndroid Build Coastguard Worker BcNum cpa, cpb;
1882*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
1883*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
1884*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
1885*5a6e8488SAndroid Build Coastguard Worker
1886*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
1887*5a6e8488SAndroid Build Coastguard Worker
1888*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(a))
1889*5a6e8488SAndroid Build Coastguard Worker {
1890*5a6e8488SAndroid Build Coastguard Worker bc_num_setToZero(c, scale);
1891*5a6e8488SAndroid Build Coastguard Worker return;
1892*5a6e8488SAndroid Build Coastguard Worker }
1893*5a6e8488SAndroid Build Coastguard Worker
1894*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ONE(b))
1895*5a6e8488SAndroid Build Coastguard Worker {
1896*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(c, a);
1897*5a6e8488SAndroid Build Coastguard Worker bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
1898*5a6e8488SAndroid Build Coastguard Worker return;
1899*5a6e8488SAndroid Build Coastguard Worker }
1900*5a6e8488SAndroid Build Coastguard Worker
1901*5a6e8488SAndroid Build Coastguard Worker // If this is true, we can use bc_num_divArray(), which would be faster.
1902*5a6e8488SAndroid Build Coastguard Worker if (!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale)
1903*5a6e8488SAndroid Build Coastguard Worker {
1904*5a6e8488SAndroid Build Coastguard Worker BcBigDig rem;
1905*5a6e8488SAndroid Build Coastguard Worker bc_num_divArray(a, (BcBigDig) b->num[0], c, &rem);
1906*5a6e8488SAndroid Build Coastguard Worker bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
1907*5a6e8488SAndroid Build Coastguard Worker return;
1908*5a6e8488SAndroid Build Coastguard Worker }
1909*5a6e8488SAndroid Build Coastguard Worker
1910*5a6e8488SAndroid Build Coastguard Worker len = bc_num_divReq(a, b, scale);
1911*5a6e8488SAndroid Build Coastguard Worker
1912*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
1913*5a6e8488SAndroid Build Coastguard Worker
1914*5a6e8488SAndroid Build Coastguard Worker // Initialize copies of the parameters. We want the length of the first
1915*5a6e8488SAndroid Build Coastguard Worker // operand copy to be as big as the result because of the way the division
1916*5a6e8488SAndroid Build Coastguard Worker // is implemented.
1917*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&cpa, len);
1918*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(&cpa, a);
1919*5a6e8488SAndroid Build Coastguard Worker bc_num_createCopy(&cpb, b);
1920*5a6e8488SAndroid Build Coastguard Worker
1921*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
1922*5a6e8488SAndroid Build Coastguard Worker
1923*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
1924*5a6e8488SAndroid Build Coastguard Worker
1925*5a6e8488SAndroid Build Coastguard Worker len = b->len;
1926*5a6e8488SAndroid Build Coastguard Worker
1927*5a6e8488SAndroid Build Coastguard Worker // Like the above comment, we want the copy of the first parameter to be
1928*5a6e8488SAndroid Build Coastguard Worker // larger than the second parameter.
1929*5a6e8488SAndroid Build Coastguard Worker if (len > cpa.len)
1930*5a6e8488SAndroid Build Coastguard Worker {
1931*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(&cpa, bc_vm_growSize(len, 2));
1932*5a6e8488SAndroid Build Coastguard Worker bc_num_extend(&cpa, (len - cpa.len) * BC_BASE_DIGS);
1933*5a6e8488SAndroid Build Coastguard Worker }
1934*5a6e8488SAndroid Build Coastguard Worker
1935*5a6e8488SAndroid Build Coastguard Worker cpardx = BC_NUM_RDX_VAL_NP(cpa);
1936*5a6e8488SAndroid Build Coastguard Worker cpa.scale = cpardx * BC_BASE_DIGS;
1937*5a6e8488SAndroid Build Coastguard Worker
1938*5a6e8488SAndroid Build Coastguard Worker // This is just setting up the scale in preparation for the division.
1939*5a6e8488SAndroid Build Coastguard Worker bc_num_extend(&cpa, b->scale);
1940*5a6e8488SAndroid Build Coastguard Worker cpardx = BC_NUM_RDX_VAL_NP(cpa) - BC_NUM_RDX(b->scale);
1941*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET_NP(cpa, cpardx);
1942*5a6e8488SAndroid Build Coastguard Worker cpa.scale = cpardx * BC_BASE_DIGS;
1943*5a6e8488SAndroid Build Coastguard Worker
1944*5a6e8488SAndroid Build Coastguard Worker // Once again, just setting things up, this time to match scale.
1945*5a6e8488SAndroid Build Coastguard Worker if (scale > cpa.scale)
1946*5a6e8488SAndroid Build Coastguard Worker {
1947*5a6e8488SAndroid Build Coastguard Worker bc_num_extend(&cpa, scale);
1948*5a6e8488SAndroid Build Coastguard Worker cpardx = BC_NUM_RDX_VAL_NP(cpa);
1949*5a6e8488SAndroid Build Coastguard Worker cpa.scale = cpardx * BC_BASE_DIGS;
1950*5a6e8488SAndroid Build Coastguard Worker }
1951*5a6e8488SAndroid Build Coastguard Worker
1952*5a6e8488SAndroid Build Coastguard Worker // Grow if necessary.
1953*5a6e8488SAndroid Build Coastguard Worker if (cpa.cap == cpa.len) bc_num_expand(&cpa, bc_vm_growSize(cpa.len, 1));
1954*5a6e8488SAndroid Build Coastguard Worker
1955*5a6e8488SAndroid Build Coastguard Worker // We want an extra zero in front to make things simpler.
1956*5a6e8488SAndroid Build Coastguard Worker cpa.num[cpa.len++] = 0;
1957*5a6e8488SAndroid Build Coastguard Worker
1958*5a6e8488SAndroid Build Coastguard Worker // Still setting things up. Why all of these things are needed is not
1959*5a6e8488SAndroid Build Coastguard Worker // something that can be easily explained, but it has to do with making the
1960*5a6e8488SAndroid Build Coastguard Worker // actual algorithm easier to understand because it can assume a lot of
1961*5a6e8488SAndroid Build Coastguard Worker // things. Thus, you should view all of this setup code as establishing
1962*5a6e8488SAndroid Build Coastguard Worker // assumptions for bc_num_d_long(), where the actual division happens.
1963*5a6e8488SAndroid Build Coastguard Worker //
1964*5a6e8488SAndroid Build Coastguard Worker // But in short, this setup makes it so bc_num_d_long() can pretend the
1965*5a6e8488SAndroid Build Coastguard Worker // numbers are integers.
1966*5a6e8488SAndroid Build Coastguard Worker if (cpardx == cpa.len) cpa.len = bc_num_nonZeroLen(&cpa);
1967*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_RDX_VAL_NP(cpb) == cpb.len) cpb.len = bc_num_nonZeroLen(&cpb);
1968*5a6e8488SAndroid Build Coastguard Worker cpb.scale = 0;
1969*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET_NP(cpb, 0);
1970*5a6e8488SAndroid Build Coastguard Worker
1971*5a6e8488SAndroid Build Coastguard Worker bc_num_d_long(&cpa, &cpb, c, scale);
1972*5a6e8488SAndroid Build Coastguard Worker
1973*5a6e8488SAndroid Build Coastguard Worker bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
1974*5a6e8488SAndroid Build Coastguard Worker
1975*5a6e8488SAndroid Build Coastguard Worker err:
1976*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
1977*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&cpb);
1978*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&cpa);
1979*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
1980*5a6e8488SAndroid Build Coastguard Worker }
1981*5a6e8488SAndroid Build Coastguard Worker
1982*5a6e8488SAndroid Build Coastguard Worker /**
1983*5a6e8488SAndroid Build Coastguard Worker * Implements divmod. This is the actual modulus function; since modulus
1984*5a6e8488SAndroid Build Coastguard Worker * requires a division anyway, this returns the quotient and modulus. Either can
1985*5a6e8488SAndroid Build Coastguard Worker * be thrown out as desired.
1986*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
1987*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
1988*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter for the quotient.
1989*5a6e8488SAndroid Build Coastguard Worker * @param d The return parameter for the modulus.
1990*5a6e8488SAndroid Build Coastguard Worker * @param scale The current scale.
1991*5a6e8488SAndroid Build Coastguard Worker * @param ts The scale that the operation should be done to. Yes, it's not
1992*5a6e8488SAndroid Build Coastguard Worker * necessarily the same as scale, per the bc spec.
1993*5a6e8488SAndroid Build Coastguard Worker */
1994*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_r(BcNum * a,BcNum * b,BcNum * restrict c,BcNum * restrict d,size_t scale,size_t ts)1995*5a6e8488SAndroid Build Coastguard Worker bc_num_r(BcNum* a, BcNum* b, BcNum* restrict c, BcNum* restrict d, size_t scale,
1996*5a6e8488SAndroid Build Coastguard Worker size_t ts)
1997*5a6e8488SAndroid Build Coastguard Worker {
1998*5a6e8488SAndroid Build Coastguard Worker BcNum temp;
1999*5a6e8488SAndroid Build Coastguard Worker // realscale is meant to quiet a warning on GCC about longjmp() clobbering.
2000*5a6e8488SAndroid Build Coastguard Worker // This one is real.
2001*5a6e8488SAndroid Build Coastguard Worker size_t realscale;
2002*5a6e8488SAndroid Build Coastguard Worker bool neg;
2003*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2004*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
2005*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2006*5a6e8488SAndroid Build Coastguard Worker
2007*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
2008*5a6e8488SAndroid Build Coastguard Worker
2009*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(a))
2010*5a6e8488SAndroid Build Coastguard Worker {
2011*5a6e8488SAndroid Build Coastguard Worker bc_num_setToZero(c, ts);
2012*5a6e8488SAndroid Build Coastguard Worker bc_num_setToZero(d, ts);
2013*5a6e8488SAndroid Build Coastguard Worker return;
2014*5a6e8488SAndroid Build Coastguard Worker }
2015*5a6e8488SAndroid Build Coastguard Worker
2016*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
2017*5a6e8488SAndroid Build Coastguard Worker
2018*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&temp, d->cap);
2019*5a6e8488SAndroid Build Coastguard Worker
2020*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
2021*5a6e8488SAndroid Build Coastguard Worker
2022*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
2023*5a6e8488SAndroid Build Coastguard Worker
2024*5a6e8488SAndroid Build Coastguard Worker // Division.
2025*5a6e8488SAndroid Build Coastguard Worker bc_num_d(a, b, c, scale);
2026*5a6e8488SAndroid Build Coastguard Worker
2027*5a6e8488SAndroid Build Coastguard Worker // We want an extra digit so we can safely truncate.
2028*5a6e8488SAndroid Build Coastguard Worker if (scale) realscale = ts + 1;
2029*5a6e8488SAndroid Build Coastguard Worker else realscale = scale;
2030*5a6e8488SAndroid Build Coastguard Worker
2031*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(c));
2032*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
2033*5a6e8488SAndroid Build Coastguard Worker
2034*5a6e8488SAndroid Build Coastguard Worker // Implement the rest of the (a - (a / b) * b) formula.
2035*5a6e8488SAndroid Build Coastguard Worker bc_num_m(c, b, &temp, realscale);
2036*5a6e8488SAndroid Build Coastguard Worker bc_num_sub(a, &temp, d, realscale);
2037*5a6e8488SAndroid Build Coastguard Worker
2038*5a6e8488SAndroid Build Coastguard Worker // Extend if necessary.
2039*5a6e8488SAndroid Build Coastguard Worker if (ts > d->scale && BC_NUM_NONZERO(d)) bc_num_extend(d, ts - d->scale);
2040*5a6e8488SAndroid Build Coastguard Worker
2041*5a6e8488SAndroid Build Coastguard Worker neg = BC_NUM_NEG(d);
2042*5a6e8488SAndroid Build Coastguard Worker bc_num_retireMul(d, ts, BC_NUM_NEG(a), BC_NUM_NEG(b));
2043*5a6e8488SAndroid Build Coastguard Worker d->rdx = BC_NUM_NEG_VAL(d, BC_NUM_NONZERO(d) ? neg : false);
2044*5a6e8488SAndroid Build Coastguard Worker
2045*5a6e8488SAndroid Build Coastguard Worker err:
2046*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
2047*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&temp);
2048*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
2049*5a6e8488SAndroid Build Coastguard Worker }
2050*5a6e8488SAndroid Build Coastguard Worker
2051*5a6e8488SAndroid Build Coastguard Worker /**
2052*5a6e8488SAndroid Build Coastguard Worker * Implements modulus/remainder. (Yes, I know they are different, but not in the
2053*5a6e8488SAndroid Build Coastguard Worker * context of bc.) This is a BcNumBinOp function.
2054*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
2055*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
2056*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
2057*5a6e8488SAndroid Build Coastguard Worker * @param scale The current scale.
2058*5a6e8488SAndroid Build Coastguard Worker */
2059*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_rem(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)2060*5a6e8488SAndroid Build Coastguard Worker bc_num_rem(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
2061*5a6e8488SAndroid Build Coastguard Worker {
2062*5a6e8488SAndroid Build Coastguard Worker BcNum c1;
2063*5a6e8488SAndroid Build Coastguard Worker size_t ts;
2064*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2065*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
2066*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2067*5a6e8488SAndroid Build Coastguard Worker
2068*5a6e8488SAndroid Build Coastguard Worker ts = bc_vm_growSize(scale, b->scale);
2069*5a6e8488SAndroid Build Coastguard Worker ts = BC_MAX(ts, a->scale);
2070*5a6e8488SAndroid Build Coastguard Worker
2071*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
2072*5a6e8488SAndroid Build Coastguard Worker
2073*5a6e8488SAndroid Build Coastguard Worker // Need a temp for the quotient.
2074*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&c1, bc_num_mulReq(a, b, ts));
2075*5a6e8488SAndroid Build Coastguard Worker
2076*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
2077*5a6e8488SAndroid Build Coastguard Worker
2078*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
2079*5a6e8488SAndroid Build Coastguard Worker
2080*5a6e8488SAndroid Build Coastguard Worker bc_num_r(a, b, &c1, c, scale, ts);
2081*5a6e8488SAndroid Build Coastguard Worker
2082*5a6e8488SAndroid Build Coastguard Worker err:
2083*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
2084*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&c1);
2085*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
2086*5a6e8488SAndroid Build Coastguard Worker }
2087*5a6e8488SAndroid Build Coastguard Worker
2088*5a6e8488SAndroid Build Coastguard Worker /**
2089*5a6e8488SAndroid Build Coastguard Worker * Implements power (exponentiation). This is a BcNumBinOp function.
2090*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
2091*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
2092*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
2093*5a6e8488SAndroid Build Coastguard Worker * @param scale The current scale.
2094*5a6e8488SAndroid Build Coastguard Worker */
2095*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_p(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)2096*5a6e8488SAndroid Build Coastguard Worker bc_num_p(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
2097*5a6e8488SAndroid Build Coastguard Worker {
2098*5a6e8488SAndroid Build Coastguard Worker BcNum copy, btemp;
2099*5a6e8488SAndroid Build Coastguard Worker BcBigDig exp;
2100*5a6e8488SAndroid Build Coastguard Worker // realscale is meant to quiet a warning on GCC about longjmp() clobbering.
2101*5a6e8488SAndroid Build Coastguard Worker // This one is real.
2102*5a6e8488SAndroid Build Coastguard Worker size_t powrdx, resrdx, realscale;
2103*5a6e8488SAndroid Build Coastguard Worker bool neg;
2104*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2105*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
2106*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2107*5a6e8488SAndroid Build Coastguard Worker
2108*5a6e8488SAndroid Build Coastguard Worker // This is here to silence a warning from GCC.
2109*5a6e8488SAndroid Build Coastguard Worker #if BC_GCC
2110*5a6e8488SAndroid Build Coastguard Worker btemp.len = 0;
2111*5a6e8488SAndroid Build Coastguard Worker btemp.rdx = 0;
2112*5a6e8488SAndroid Build Coastguard Worker btemp.num = NULL;
2113*5a6e8488SAndroid Build Coastguard Worker #endif // BC_GCC
2114*5a6e8488SAndroid Build Coastguard Worker
2115*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(bc_num_nonInt(b, &btemp))) bc_err(BC_ERR_MATH_NON_INTEGER);
2116*5a6e8488SAndroid Build Coastguard Worker
2117*5a6e8488SAndroid Build Coastguard Worker assert(btemp.len == 0 || btemp.num != NULL);
2118*5a6e8488SAndroid Build Coastguard Worker
2119*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(&btemp))
2120*5a6e8488SAndroid Build Coastguard Worker {
2121*5a6e8488SAndroid Build Coastguard Worker bc_num_one(c);
2122*5a6e8488SAndroid Build Coastguard Worker return;
2123*5a6e8488SAndroid Build Coastguard Worker }
2124*5a6e8488SAndroid Build Coastguard Worker
2125*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(a))
2126*5a6e8488SAndroid Build Coastguard Worker {
2127*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NEG_NP(btemp)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
2128*5a6e8488SAndroid Build Coastguard Worker bc_num_setToZero(c, scale);
2129*5a6e8488SAndroid Build Coastguard Worker return;
2130*5a6e8488SAndroid Build Coastguard Worker }
2131*5a6e8488SAndroid Build Coastguard Worker
2132*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ONE(&btemp))
2133*5a6e8488SAndroid Build Coastguard Worker {
2134*5a6e8488SAndroid Build Coastguard Worker if (!BC_NUM_NEG_NP(btemp)) bc_num_copy(c, a);
2135*5a6e8488SAndroid Build Coastguard Worker else bc_num_inv(a, c, scale);
2136*5a6e8488SAndroid Build Coastguard Worker return;
2137*5a6e8488SAndroid Build Coastguard Worker }
2138*5a6e8488SAndroid Build Coastguard Worker
2139*5a6e8488SAndroid Build Coastguard Worker neg = BC_NUM_NEG_NP(btemp);
2140*5a6e8488SAndroid Build Coastguard Worker BC_NUM_NEG_CLR_NP(btemp);
2141*5a6e8488SAndroid Build Coastguard Worker
2142*5a6e8488SAndroid Build Coastguard Worker exp = bc_num_bigdig(&btemp);
2143*5a6e8488SAndroid Build Coastguard Worker
2144*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
2145*5a6e8488SAndroid Build Coastguard Worker
2146*5a6e8488SAndroid Build Coastguard Worker bc_num_createCopy(©, a);
2147*5a6e8488SAndroid Build Coastguard Worker
2148*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
2149*5a6e8488SAndroid Build Coastguard Worker
2150*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
2151*5a6e8488SAndroid Build Coastguard Worker
2152*5a6e8488SAndroid Build Coastguard Worker // If this is true, then we do not have to do a division, and we need to
2153*5a6e8488SAndroid Build Coastguard Worker // set scale accordingly.
2154*5a6e8488SAndroid Build Coastguard Worker if (!neg)
2155*5a6e8488SAndroid Build Coastguard Worker {
2156*5a6e8488SAndroid Build Coastguard Worker size_t max = BC_MAX(scale, a->scale), scalepow;
2157*5a6e8488SAndroid Build Coastguard Worker scalepow = bc_num_mulOverflow(a->scale, exp);
2158*5a6e8488SAndroid Build Coastguard Worker realscale = BC_MIN(scalepow, max);
2159*5a6e8488SAndroid Build Coastguard Worker }
2160*5a6e8488SAndroid Build Coastguard Worker else realscale = scale;
2161*5a6e8488SAndroid Build Coastguard Worker
2162*5a6e8488SAndroid Build Coastguard Worker // This is only implementing the first exponentiation by squaring, until it
2163*5a6e8488SAndroid Build Coastguard Worker // reaches the first time where the square is actually used.
2164*5a6e8488SAndroid Build Coastguard Worker for (powrdx = a->scale; !(exp & 1); exp >>= 1)
2165*5a6e8488SAndroid Build Coastguard Worker {
2166*5a6e8488SAndroid Build Coastguard Worker powrdx <<= 1;
2167*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(copy));
2168*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(©, ©, ©, powrdx);
2169*5a6e8488SAndroid Build Coastguard Worker }
2170*5a6e8488SAndroid Build Coastguard Worker
2171*5a6e8488SAndroid Build Coastguard Worker // Make c a copy of copy for the purpose of saving the squares that should
2172*5a6e8488SAndroid Build Coastguard Worker // be saved.
2173*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(c, ©);
2174*5a6e8488SAndroid Build Coastguard Worker resrdx = powrdx;
2175*5a6e8488SAndroid Build Coastguard Worker
2176*5a6e8488SAndroid Build Coastguard Worker // Now finish the exponentiation by squaring, this time saving the squares
2177*5a6e8488SAndroid Build Coastguard Worker // as necessary.
2178*5a6e8488SAndroid Build Coastguard Worker while (exp >>= 1)
2179*5a6e8488SAndroid Build Coastguard Worker {
2180*5a6e8488SAndroid Build Coastguard Worker powrdx <<= 1;
2181*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(copy));
2182*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(©, ©, ©, powrdx);
2183*5a6e8488SAndroid Build Coastguard Worker
2184*5a6e8488SAndroid Build Coastguard Worker // If this is true, we want to save that particular square. This does
2185*5a6e8488SAndroid Build Coastguard Worker // that by multiplying c with copy.
2186*5a6e8488SAndroid Build Coastguard Worker if (exp & 1)
2187*5a6e8488SAndroid Build Coastguard Worker {
2188*5a6e8488SAndroid Build Coastguard Worker resrdx += powrdx;
2189*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(c));
2190*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(copy));
2191*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(c, ©, c, resrdx);
2192*5a6e8488SAndroid Build Coastguard Worker }
2193*5a6e8488SAndroid Build Coastguard Worker }
2194*5a6e8488SAndroid Build Coastguard Worker
2195*5a6e8488SAndroid Build Coastguard Worker // Invert if necessary.
2196*5a6e8488SAndroid Build Coastguard Worker if (neg) bc_num_inv(c, c, realscale);
2197*5a6e8488SAndroid Build Coastguard Worker
2198*5a6e8488SAndroid Build Coastguard Worker // Truncate if necessary.
2199*5a6e8488SAndroid Build Coastguard Worker if (c->scale > realscale) bc_num_truncate(c, c->scale - realscale);
2200*5a6e8488SAndroid Build Coastguard Worker
2201*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(c);
2202*5a6e8488SAndroid Build Coastguard Worker
2203*5a6e8488SAndroid Build Coastguard Worker err:
2204*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
2205*5a6e8488SAndroid Build Coastguard Worker bc_num_free(©);
2206*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
2207*5a6e8488SAndroid Build Coastguard Worker }
2208*5a6e8488SAndroid Build Coastguard Worker
2209*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2210*5a6e8488SAndroid Build Coastguard Worker /**
2211*5a6e8488SAndroid Build Coastguard Worker * Implements the places operator. This is a BcNumBinOp function.
2212*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
2213*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
2214*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
2215*5a6e8488SAndroid Build Coastguard Worker * @param scale The current scale.
2216*5a6e8488SAndroid Build Coastguard Worker */
2217*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_place(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)2218*5a6e8488SAndroid Build Coastguard Worker bc_num_place(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
2219*5a6e8488SAndroid Build Coastguard Worker {
2220*5a6e8488SAndroid Build Coastguard Worker BcBigDig val;
2221*5a6e8488SAndroid Build Coastguard Worker
2222*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(scale);
2223*5a6e8488SAndroid Build Coastguard Worker
2224*5a6e8488SAndroid Build Coastguard Worker val = bc_num_intop(a, b, c);
2225*5a6e8488SAndroid Build Coastguard Worker
2226*5a6e8488SAndroid Build Coastguard Worker // Just truncate or extend as appropriate.
2227*5a6e8488SAndroid Build Coastguard Worker if (val < c->scale) bc_num_truncate(c, c->scale - val);
2228*5a6e8488SAndroid Build Coastguard Worker else if (val > c->scale) bc_num_extend(c, val - c->scale);
2229*5a6e8488SAndroid Build Coastguard Worker }
2230*5a6e8488SAndroid Build Coastguard Worker
2231*5a6e8488SAndroid Build Coastguard Worker /**
2232*5a6e8488SAndroid Build Coastguard Worker * Implements the left shift operator. This is a BcNumBinOp function.
2233*5a6e8488SAndroid Build Coastguard Worker */
2234*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_left(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)2235*5a6e8488SAndroid Build Coastguard Worker bc_num_left(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
2236*5a6e8488SAndroid Build Coastguard Worker {
2237*5a6e8488SAndroid Build Coastguard Worker BcBigDig val;
2238*5a6e8488SAndroid Build Coastguard Worker
2239*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(scale);
2240*5a6e8488SAndroid Build Coastguard Worker
2241*5a6e8488SAndroid Build Coastguard Worker val = bc_num_intop(a, b, c);
2242*5a6e8488SAndroid Build Coastguard Worker
2243*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(c, (size_t) val);
2244*5a6e8488SAndroid Build Coastguard Worker }
2245*5a6e8488SAndroid Build Coastguard Worker
2246*5a6e8488SAndroid Build Coastguard Worker /**
2247*5a6e8488SAndroid Build Coastguard Worker * Implements the right shift operator. This is a BcNumBinOp function.
2248*5a6e8488SAndroid Build Coastguard Worker */
2249*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_right(BcNum * a,BcNum * b,BcNum * restrict c,size_t scale)2250*5a6e8488SAndroid Build Coastguard Worker bc_num_right(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)
2251*5a6e8488SAndroid Build Coastguard Worker {
2252*5a6e8488SAndroid Build Coastguard Worker BcBigDig val;
2253*5a6e8488SAndroid Build Coastguard Worker
2254*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(scale);
2255*5a6e8488SAndroid Build Coastguard Worker
2256*5a6e8488SAndroid Build Coastguard Worker val = bc_num_intop(a, b, c);
2257*5a6e8488SAndroid Build Coastguard Worker
2258*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(c)) return;
2259*5a6e8488SAndroid Build Coastguard Worker
2260*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftRight(c, (size_t) val);
2261*5a6e8488SAndroid Build Coastguard Worker }
2262*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2263*5a6e8488SAndroid Build Coastguard Worker
2264*5a6e8488SAndroid Build Coastguard Worker /**
2265*5a6e8488SAndroid Build Coastguard Worker * Prepares for, and calls, a binary operator function. This is probably the
2266*5a6e8488SAndroid Build Coastguard Worker * most important function in the entire file because it establishes assumptions
2267*5a6e8488SAndroid Build Coastguard Worker * that make the rest of the code so easy. Those assumptions include:
2268*5a6e8488SAndroid Build Coastguard Worker *
2269*5a6e8488SAndroid Build Coastguard Worker * - a is not the same pointer as c.
2270*5a6e8488SAndroid Build Coastguard Worker * - b is not the same pointer as c.
2271*5a6e8488SAndroid Build Coastguard Worker * - there is enough room in c for the result.
2272*5a6e8488SAndroid Build Coastguard Worker *
2273*5a6e8488SAndroid Build Coastguard Worker * Without these, this whole function would basically have to be duplicated for
2274*5a6e8488SAndroid Build Coastguard Worker * *all* binary operators.
2275*5a6e8488SAndroid Build Coastguard Worker *
2276*5a6e8488SAndroid Build Coastguard Worker * @param a The first operand.
2277*5a6e8488SAndroid Build Coastguard Worker * @param b The second operand.
2278*5a6e8488SAndroid Build Coastguard Worker * @param c The return parameter.
2279*5a6e8488SAndroid Build Coastguard Worker * @param scale The current scale.
2280*5a6e8488SAndroid Build Coastguard Worker * @param req The number of limbs needed to fit the result.
2281*5a6e8488SAndroid Build Coastguard Worker */
2282*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_binary(BcNum * a,BcNum * b,BcNum * c,size_t scale,BcNumBinOp op,size_t req)2283*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(BcNum* a, BcNum* b, BcNum* c, size_t scale, BcNumBinOp op,
2284*5a6e8488SAndroid Build Coastguard Worker size_t req)
2285*5a6e8488SAndroid Build Coastguard Worker {
2286*5a6e8488SAndroid Build Coastguard Worker BcNum* ptr_a;
2287*5a6e8488SAndroid Build Coastguard Worker BcNum* ptr_b;
2288*5a6e8488SAndroid Build Coastguard Worker BcNum num2;
2289*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2290*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = NULL;
2291*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2292*5a6e8488SAndroid Build Coastguard Worker
2293*5a6e8488SAndroid Build Coastguard Worker assert(a != NULL && b != NULL && c != NULL && op != NULL);
2294*5a6e8488SAndroid Build Coastguard Worker
2295*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
2296*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
2297*5a6e8488SAndroid Build Coastguard Worker
2298*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
2299*5a6e8488SAndroid Build Coastguard Worker
2300*5a6e8488SAndroid Build Coastguard Worker ptr_a = c == a ? &num2 : a;
2301*5a6e8488SAndroid Build Coastguard Worker ptr_b = c == b ? &num2 : b;
2302*5a6e8488SAndroid Build Coastguard Worker
2303*5a6e8488SAndroid Build Coastguard Worker // Actually reallocate. If we don't reallocate, we want to expand at the
2304*5a6e8488SAndroid Build Coastguard Worker // very least.
2305*5a6e8488SAndroid Build Coastguard Worker if (c == a || c == b)
2306*5a6e8488SAndroid Build Coastguard Worker {
2307*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2308*5a6e8488SAndroid Build Coastguard Worker vm = bcl_getspecific();
2309*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2310*5a6e8488SAndroid Build Coastguard Worker
2311*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
2312*5a6e8488SAndroid Build Coastguard Worker memcpy(&num2, c, sizeof(BcNum));
2313*5a6e8488SAndroid Build Coastguard Worker
2314*5a6e8488SAndroid Build Coastguard Worker bc_num_init(c, req);
2315*5a6e8488SAndroid Build Coastguard Worker
2316*5a6e8488SAndroid Build Coastguard Worker // Must prepare for cleanup. We want this here so that locals that got
2317*5a6e8488SAndroid Build Coastguard Worker // set stay set since a longjmp() is not guaranteed to preserve locals.
2318*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
2319*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
2320*5a6e8488SAndroid Build Coastguard Worker }
2321*5a6e8488SAndroid Build Coastguard Worker else
2322*5a6e8488SAndroid Build Coastguard Worker {
2323*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
2324*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(c, req);
2325*5a6e8488SAndroid Build Coastguard Worker }
2326*5a6e8488SAndroid Build Coastguard Worker
2327*5a6e8488SAndroid Build Coastguard Worker // It is okay for a and b to be the same. If a binary operator function does
2328*5a6e8488SAndroid Build Coastguard Worker // need them to be different, the binary operator function is responsible
2329*5a6e8488SAndroid Build Coastguard Worker // for that.
2330*5a6e8488SAndroid Build Coastguard Worker
2331*5a6e8488SAndroid Build Coastguard Worker // Call the actual binary operator function.
2332*5a6e8488SAndroid Build Coastguard Worker op(ptr_a, ptr_b, c, scale);
2333*5a6e8488SAndroid Build Coastguard Worker
2334*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
2335*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
2336*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(c));
2337*5a6e8488SAndroid Build Coastguard Worker assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
2338*5a6e8488SAndroid Build Coastguard Worker
2339*5a6e8488SAndroid Build Coastguard Worker err:
2340*5a6e8488SAndroid Build Coastguard Worker // Cleanup only needed if we initialized c to a new number.
2341*5a6e8488SAndroid Build Coastguard Worker if (c == a || c == b)
2342*5a6e8488SAndroid Build Coastguard Worker {
2343*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
2344*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&num2);
2345*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
2346*5a6e8488SAndroid Build Coastguard Worker }
2347*5a6e8488SAndroid Build Coastguard Worker }
2348*5a6e8488SAndroid Build Coastguard Worker
2349*5a6e8488SAndroid Build Coastguard Worker /**
2350*5a6e8488SAndroid Build Coastguard Worker * Tests a number string for validity. This function has a history; I originally
2351*5a6e8488SAndroid Build Coastguard Worker * wrote it because I did not trust my parser. Over time, however, I came to
2352*5a6e8488SAndroid Build Coastguard Worker * trust it, so I was able to relegate this function to debug builds only, and I
2353*5a6e8488SAndroid Build Coastguard Worker * used it in assert()'s. But then I created the library, and well, I can't
2354*5a6e8488SAndroid Build Coastguard Worker * trust users, so I reused this for yelling at users.
2355*5a6e8488SAndroid Build Coastguard Worker * @param val The string to check to see if it's a valid number string.
2356*5a6e8488SAndroid Build Coastguard Worker * @return True if the string is a valid number string, false otherwise.
2357*5a6e8488SAndroid Build Coastguard Worker */
2358*5a6e8488SAndroid Build Coastguard Worker bool
bc_num_strValid(const char * restrict val)2359*5a6e8488SAndroid Build Coastguard Worker bc_num_strValid(const char* restrict val)
2360*5a6e8488SAndroid Build Coastguard Worker {
2361*5a6e8488SAndroid Build Coastguard Worker bool radix = false;
2362*5a6e8488SAndroid Build Coastguard Worker size_t i, len = strlen(val);
2363*5a6e8488SAndroid Build Coastguard Worker
2364*5a6e8488SAndroid Build Coastguard Worker // Notice that I don't check if there is a negative sign. That is not part
2365*5a6e8488SAndroid Build Coastguard Worker // of a valid number, except in the library. The library-specific code takes
2366*5a6e8488SAndroid Build Coastguard Worker // care of that part.
2367*5a6e8488SAndroid Build Coastguard Worker
2368*5a6e8488SAndroid Build Coastguard Worker // Nothing in the string is okay.
2369*5a6e8488SAndroid Build Coastguard Worker if (!len) return true;
2370*5a6e8488SAndroid Build Coastguard Worker
2371*5a6e8488SAndroid Build Coastguard Worker // Loop through the characters.
2372*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < len; ++i)
2373*5a6e8488SAndroid Build Coastguard Worker {
2374*5a6e8488SAndroid Build Coastguard Worker BcDig c = val[i];
2375*5a6e8488SAndroid Build Coastguard Worker
2376*5a6e8488SAndroid Build Coastguard Worker // If we have found a radix point...
2377*5a6e8488SAndroid Build Coastguard Worker if (c == '.')
2378*5a6e8488SAndroid Build Coastguard Worker {
2379*5a6e8488SAndroid Build Coastguard Worker // We don't allow two radices.
2380*5a6e8488SAndroid Build Coastguard Worker if (radix) return false;
2381*5a6e8488SAndroid Build Coastguard Worker
2382*5a6e8488SAndroid Build Coastguard Worker radix = true;
2383*5a6e8488SAndroid Build Coastguard Worker continue;
2384*5a6e8488SAndroid Build Coastguard Worker }
2385*5a6e8488SAndroid Build Coastguard Worker
2386*5a6e8488SAndroid Build Coastguard Worker // We only allow digits and uppercase letters.
2387*5a6e8488SAndroid Build Coastguard Worker if (!(isdigit(c) || isupper(c))) return false;
2388*5a6e8488SAndroid Build Coastguard Worker }
2389*5a6e8488SAndroid Build Coastguard Worker
2390*5a6e8488SAndroid Build Coastguard Worker return true;
2391*5a6e8488SAndroid Build Coastguard Worker }
2392*5a6e8488SAndroid Build Coastguard Worker
2393*5a6e8488SAndroid Build Coastguard Worker /**
2394*5a6e8488SAndroid Build Coastguard Worker * Parses one character and returns the digit that corresponds to that
2395*5a6e8488SAndroid Build Coastguard Worker * character according to the base.
2396*5a6e8488SAndroid Build Coastguard Worker * @param c The character to parse.
2397*5a6e8488SAndroid Build Coastguard Worker * @param base The base.
2398*5a6e8488SAndroid Build Coastguard Worker * @return The character as a digit.
2399*5a6e8488SAndroid Build Coastguard Worker */
2400*5a6e8488SAndroid Build Coastguard Worker static BcBigDig
bc_num_parseChar(char c,size_t base)2401*5a6e8488SAndroid Build Coastguard Worker bc_num_parseChar(char c, size_t base)
2402*5a6e8488SAndroid Build Coastguard Worker {
2403*5a6e8488SAndroid Build Coastguard Worker assert(isupper(c) || isdigit(c));
2404*5a6e8488SAndroid Build Coastguard Worker
2405*5a6e8488SAndroid Build Coastguard Worker // If a letter...
2406*5a6e8488SAndroid Build Coastguard Worker if (isupper(c))
2407*5a6e8488SAndroid Build Coastguard Worker {
2408*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2409*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
2410*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2411*5a6e8488SAndroid Build Coastguard Worker
2412*5a6e8488SAndroid Build Coastguard Worker // This returns the digit that directly corresponds with the letter.
2413*5a6e8488SAndroid Build Coastguard Worker c = BC_NUM_NUM_LETTER(c);
2414*5a6e8488SAndroid Build Coastguard Worker
2415*5a6e8488SAndroid Build Coastguard Worker // If the digit is greater than the base, we clamp.
2416*5a6e8488SAndroid Build Coastguard Worker if (BC_DIGIT_CLAMP)
2417*5a6e8488SAndroid Build Coastguard Worker {
2418*5a6e8488SAndroid Build Coastguard Worker c = ((size_t) c) >= base ? (char) base - 1 : c;
2419*5a6e8488SAndroid Build Coastguard Worker }
2420*5a6e8488SAndroid Build Coastguard Worker }
2421*5a6e8488SAndroid Build Coastguard Worker // Straight convert the digit to a number.
2422*5a6e8488SAndroid Build Coastguard Worker else c -= '0';
2423*5a6e8488SAndroid Build Coastguard Worker
2424*5a6e8488SAndroid Build Coastguard Worker return (BcBigDig) (uchar) c;
2425*5a6e8488SAndroid Build Coastguard Worker }
2426*5a6e8488SAndroid Build Coastguard Worker
2427*5a6e8488SAndroid Build Coastguard Worker /**
2428*5a6e8488SAndroid Build Coastguard Worker * Parses a string as a decimal number. This is separate because it's going to
2429*5a6e8488SAndroid Build Coastguard Worker * be the most used, and it can be heavily optimized for decimal only.
2430*5a6e8488SAndroid Build Coastguard Worker * @param n The number to parse into and return. Must be preallocated.
2431*5a6e8488SAndroid Build Coastguard Worker * @param val The string to parse.
2432*5a6e8488SAndroid Build Coastguard Worker */
2433*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_parseDecimal(BcNum * restrict n,const char * restrict val)2434*5a6e8488SAndroid Build Coastguard Worker bc_num_parseDecimal(BcNum* restrict n, const char* restrict val)
2435*5a6e8488SAndroid Build Coastguard Worker {
2436*5a6e8488SAndroid Build Coastguard Worker size_t len, i, temp, mod;
2437*5a6e8488SAndroid Build Coastguard Worker const char* ptr;
2438*5a6e8488SAndroid Build Coastguard Worker bool zero = true, rdx;
2439*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2440*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
2441*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2442*5a6e8488SAndroid Build Coastguard Worker
2443*5a6e8488SAndroid Build Coastguard Worker // Eat leading zeroes.
2444*5a6e8488SAndroid Build Coastguard Worker for (i = 0; val[i] == '0'; ++i)
2445*5a6e8488SAndroid Build Coastguard Worker {
2446*5a6e8488SAndroid Build Coastguard Worker continue;
2447*5a6e8488SAndroid Build Coastguard Worker }
2448*5a6e8488SAndroid Build Coastguard Worker
2449*5a6e8488SAndroid Build Coastguard Worker val += i;
2450*5a6e8488SAndroid Build Coastguard Worker assert(!val[0] || isalnum(val[0]) || val[0] == '.');
2451*5a6e8488SAndroid Build Coastguard Worker
2452*5a6e8488SAndroid Build Coastguard Worker // All 0's. We can just return, since this procedure expects a virgin
2453*5a6e8488SAndroid Build Coastguard Worker // (already 0) BcNum.
2454*5a6e8488SAndroid Build Coastguard Worker if (!val[0]) return;
2455*5a6e8488SAndroid Build Coastguard Worker
2456*5a6e8488SAndroid Build Coastguard Worker // The length of the string is the length of the number, except it might be
2457*5a6e8488SAndroid Build Coastguard Worker // one bigger because of a decimal point.
2458*5a6e8488SAndroid Build Coastguard Worker len = strlen(val);
2459*5a6e8488SAndroid Build Coastguard Worker
2460*5a6e8488SAndroid Build Coastguard Worker // Find the location of the decimal point.
2461*5a6e8488SAndroid Build Coastguard Worker ptr = strchr(val, '.');
2462*5a6e8488SAndroid Build Coastguard Worker rdx = (ptr != NULL);
2463*5a6e8488SAndroid Build Coastguard Worker
2464*5a6e8488SAndroid Build Coastguard Worker // We eat leading zeroes again. These leading zeroes are different because
2465*5a6e8488SAndroid Build Coastguard Worker // they will come after the decimal point if they exist, and since that's
2466*5a6e8488SAndroid Build Coastguard Worker // the case, they must be preserved.
2467*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < len && (zero = (val[i] == '0' || val[i] == '.')); ++i)
2468*5a6e8488SAndroid Build Coastguard Worker {
2469*5a6e8488SAndroid Build Coastguard Worker continue;
2470*5a6e8488SAndroid Build Coastguard Worker }
2471*5a6e8488SAndroid Build Coastguard Worker
2472*5a6e8488SAndroid Build Coastguard Worker // Set the scale of the number based on the location of the decimal point.
2473*5a6e8488SAndroid Build Coastguard Worker // The casts to uintptr_t is to ensure that bc does not hit undefined
2474*5a6e8488SAndroid Build Coastguard Worker // behavior when doing math on the values.
2475*5a6e8488SAndroid Build Coastguard Worker n->scale = (size_t) (rdx *
2476*5a6e8488SAndroid Build Coastguard Worker (((uintptr_t) (val + len)) - (((uintptr_t) ptr) + 1)));
2477*5a6e8488SAndroid Build Coastguard Worker
2478*5a6e8488SAndroid Build Coastguard Worker // Set rdx.
2479*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
2480*5a6e8488SAndroid Build Coastguard Worker
2481*5a6e8488SAndroid Build Coastguard Worker // Calculate length. First, the length of the integer, then the number of
2482*5a6e8488SAndroid Build Coastguard Worker // digits in the last limb, then the length.
2483*5a6e8488SAndroid Build Coastguard Worker i = len - (ptr == val ? 0 : i) - rdx;
2484*5a6e8488SAndroid Build Coastguard Worker temp = BC_NUM_ROUND_POW(i);
2485*5a6e8488SAndroid Build Coastguard Worker mod = n->scale % BC_BASE_DIGS;
2486*5a6e8488SAndroid Build Coastguard Worker i = mod ? BC_BASE_DIGS - mod : 0;
2487*5a6e8488SAndroid Build Coastguard Worker n->len = ((temp + i) / BC_BASE_DIGS);
2488*5a6e8488SAndroid Build Coastguard Worker
2489*5a6e8488SAndroid Build Coastguard Worker // Expand and zero. The plus extra is in case the lack of clamping causes
2490*5a6e8488SAndroid Build Coastguard Worker // the number to overflow the original bounds.
2491*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(n, n->len + !BC_DIGIT_CLAMP);
2492*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
2493*5a6e8488SAndroid Build Coastguard Worker memset(n->num, 0, BC_NUM_SIZE(n->len + !BC_DIGIT_CLAMP));
2494*5a6e8488SAndroid Build Coastguard Worker
2495*5a6e8488SAndroid Build Coastguard Worker if (zero)
2496*5a6e8488SAndroid Build Coastguard Worker {
2497*5a6e8488SAndroid Build Coastguard Worker // I think I can set rdx directly to zero here because n should be a
2498*5a6e8488SAndroid Build Coastguard Worker // new number with sign set to false.
2499*5a6e8488SAndroid Build Coastguard Worker n->len = n->rdx = 0;
2500*5a6e8488SAndroid Build Coastguard Worker }
2501*5a6e8488SAndroid Build Coastguard Worker else
2502*5a6e8488SAndroid Build Coastguard Worker {
2503*5a6e8488SAndroid Build Coastguard Worker // There is actually stuff to parse if we make it here. Yay...
2504*5a6e8488SAndroid Build Coastguard Worker BcBigDig exp, pow;
2505*5a6e8488SAndroid Build Coastguard Worker
2506*5a6e8488SAndroid Build Coastguard Worker assert(i <= BC_NUM_BIGDIG_MAX);
2507*5a6e8488SAndroid Build Coastguard Worker
2508*5a6e8488SAndroid Build Coastguard Worker // The exponent and power.
2509*5a6e8488SAndroid Build Coastguard Worker exp = (BcBigDig) i;
2510*5a6e8488SAndroid Build Coastguard Worker pow = bc_num_pow10[exp];
2511*5a6e8488SAndroid Build Coastguard Worker
2512*5a6e8488SAndroid Build Coastguard Worker // Parse loop. We parse backwards because numbers are stored little
2513*5a6e8488SAndroid Build Coastguard Worker // endian.
2514*5a6e8488SAndroid Build Coastguard Worker for (i = len - 1; i < len; --i, ++exp)
2515*5a6e8488SAndroid Build Coastguard Worker {
2516*5a6e8488SAndroid Build Coastguard Worker char c = val[i];
2517*5a6e8488SAndroid Build Coastguard Worker
2518*5a6e8488SAndroid Build Coastguard Worker // Skip the decimal point.
2519*5a6e8488SAndroid Build Coastguard Worker if (c == '.') exp -= 1;
2520*5a6e8488SAndroid Build Coastguard Worker else
2521*5a6e8488SAndroid Build Coastguard Worker {
2522*5a6e8488SAndroid Build Coastguard Worker // The index of the limb.
2523*5a6e8488SAndroid Build Coastguard Worker size_t idx = exp / BC_BASE_DIGS;
2524*5a6e8488SAndroid Build Coastguard Worker BcBigDig dig;
2525*5a6e8488SAndroid Build Coastguard Worker
2526*5a6e8488SAndroid Build Coastguard Worker if (isupper(c))
2527*5a6e8488SAndroid Build Coastguard Worker {
2528*5a6e8488SAndroid Build Coastguard Worker // Clamp for the base.
2529*5a6e8488SAndroid Build Coastguard Worker if (!BC_DIGIT_CLAMP) c = BC_NUM_NUM_LETTER(c);
2530*5a6e8488SAndroid Build Coastguard Worker else c = 9;
2531*5a6e8488SAndroid Build Coastguard Worker }
2532*5a6e8488SAndroid Build Coastguard Worker else c -= '0';
2533*5a6e8488SAndroid Build Coastguard Worker
2534*5a6e8488SAndroid Build Coastguard Worker // Add the digit to the limb. This takes care of overflow from
2535*5a6e8488SAndroid Build Coastguard Worker // lack of clamping.
2536*5a6e8488SAndroid Build Coastguard Worker dig = ((BcBigDig) n->num[idx]) + ((BcBigDig) c) * pow;
2537*5a6e8488SAndroid Build Coastguard Worker if (dig >= BC_BASE_POW)
2538*5a6e8488SAndroid Build Coastguard Worker {
2539*5a6e8488SAndroid Build Coastguard Worker // We cannot go over BC_BASE_POW with clamping.
2540*5a6e8488SAndroid Build Coastguard Worker assert(!BC_DIGIT_CLAMP);
2541*5a6e8488SAndroid Build Coastguard Worker
2542*5a6e8488SAndroid Build Coastguard Worker n->num[idx + 1] = (BcDig) (dig / BC_BASE_POW);
2543*5a6e8488SAndroid Build Coastguard Worker n->num[idx] = (BcDig) (dig % BC_BASE_POW);
2544*5a6e8488SAndroid Build Coastguard Worker assert(n->num[idx] >= 0 && n->num[idx] < BC_BASE_POW);
2545*5a6e8488SAndroid Build Coastguard Worker assert(n->num[idx + 1] >= 0 &&
2546*5a6e8488SAndroid Build Coastguard Worker n->num[idx + 1] < BC_BASE_POW);
2547*5a6e8488SAndroid Build Coastguard Worker }
2548*5a6e8488SAndroid Build Coastguard Worker else
2549*5a6e8488SAndroid Build Coastguard Worker {
2550*5a6e8488SAndroid Build Coastguard Worker n->num[idx] = (BcDig) dig;
2551*5a6e8488SAndroid Build Coastguard Worker assert(n->num[idx] >= 0 && n->num[idx] < BC_BASE_POW);
2552*5a6e8488SAndroid Build Coastguard Worker }
2553*5a6e8488SAndroid Build Coastguard Worker
2554*5a6e8488SAndroid Build Coastguard Worker // Adjust the power and exponent.
2555*5a6e8488SAndroid Build Coastguard Worker if ((exp + 1) % BC_BASE_DIGS == 0) pow = 1;
2556*5a6e8488SAndroid Build Coastguard Worker else pow *= BC_BASE;
2557*5a6e8488SAndroid Build Coastguard Worker }
2558*5a6e8488SAndroid Build Coastguard Worker }
2559*5a6e8488SAndroid Build Coastguard Worker }
2560*5a6e8488SAndroid Build Coastguard Worker
2561*5a6e8488SAndroid Build Coastguard Worker // Make sure to add one to the length if needed from lack of clamping.
2562*5a6e8488SAndroid Build Coastguard Worker n->len += (!BC_DIGIT_CLAMP && n->num[n->len] != 0);
2563*5a6e8488SAndroid Build Coastguard Worker }
2564*5a6e8488SAndroid Build Coastguard Worker
2565*5a6e8488SAndroid Build Coastguard Worker /**
2566*5a6e8488SAndroid Build Coastguard Worker * Parse a number in any base (besides decimal).
2567*5a6e8488SAndroid Build Coastguard Worker * @param n The number to parse into and return. Must be preallocated.
2568*5a6e8488SAndroid Build Coastguard Worker * @param val The string to parse.
2569*5a6e8488SAndroid Build Coastguard Worker * @param base The base to parse as.
2570*5a6e8488SAndroid Build Coastguard Worker */
2571*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_parseBase(BcNum * restrict n,const char * restrict val,BcBigDig base)2572*5a6e8488SAndroid Build Coastguard Worker bc_num_parseBase(BcNum* restrict n, const char* restrict val, BcBigDig base)
2573*5a6e8488SAndroid Build Coastguard Worker {
2574*5a6e8488SAndroid Build Coastguard Worker BcNum temp, mult1, mult2, result1, result2;
2575*5a6e8488SAndroid Build Coastguard Worker BcNum* m1;
2576*5a6e8488SAndroid Build Coastguard Worker BcNum* m2;
2577*5a6e8488SAndroid Build Coastguard Worker BcNum* ptr;
2578*5a6e8488SAndroid Build Coastguard Worker char c = 0;
2579*5a6e8488SAndroid Build Coastguard Worker bool zero = true;
2580*5a6e8488SAndroid Build Coastguard Worker BcBigDig v;
2581*5a6e8488SAndroid Build Coastguard Worker size_t digs, len = strlen(val);
2582*5a6e8488SAndroid Build Coastguard Worker // This is volatile to quiet a warning on GCC about longjmp() clobbering.
2583*5a6e8488SAndroid Build Coastguard Worker volatile size_t i;
2584*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2585*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
2586*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2587*5a6e8488SAndroid Build Coastguard Worker
2588*5a6e8488SAndroid Build Coastguard Worker // If zero, just return because the number should be virgin (already 0).
2589*5a6e8488SAndroid Build Coastguard Worker for (i = 0; zero && i < len; ++i)
2590*5a6e8488SAndroid Build Coastguard Worker {
2591*5a6e8488SAndroid Build Coastguard Worker zero = (val[i] == '.' || val[i] == '0');
2592*5a6e8488SAndroid Build Coastguard Worker }
2593*5a6e8488SAndroid Build Coastguard Worker if (zero) return;
2594*5a6e8488SAndroid Build Coastguard Worker
2595*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
2596*5a6e8488SAndroid Build Coastguard Worker
2597*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&temp, BC_NUM_BIGDIG_LOG10);
2598*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&mult1, BC_NUM_BIGDIG_LOG10);
2599*5a6e8488SAndroid Build Coastguard Worker
2600*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, int_err);
2601*5a6e8488SAndroid Build Coastguard Worker
2602*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
2603*5a6e8488SAndroid Build Coastguard Worker
2604*5a6e8488SAndroid Build Coastguard Worker // We split parsing into parsing the integer and parsing the fractional
2605*5a6e8488SAndroid Build Coastguard Worker // part.
2606*5a6e8488SAndroid Build Coastguard Worker
2607*5a6e8488SAndroid Build Coastguard Worker // Parse the integer part. This is the easy part because we just multiply
2608*5a6e8488SAndroid Build Coastguard Worker // the number by the base, then add the digit.
2609*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < len && (c = val[i]) && c != '.'; ++i)
2610*5a6e8488SAndroid Build Coastguard Worker {
2611*5a6e8488SAndroid Build Coastguard Worker // Convert the character to a digit.
2612*5a6e8488SAndroid Build Coastguard Worker v = bc_num_parseChar(c, base);
2613*5a6e8488SAndroid Build Coastguard Worker
2614*5a6e8488SAndroid Build Coastguard Worker // Multiply the number.
2615*5a6e8488SAndroid Build Coastguard Worker bc_num_mulArray(n, base, &mult1);
2616*5a6e8488SAndroid Build Coastguard Worker
2617*5a6e8488SAndroid Build Coastguard Worker // Convert the digit to a number and add.
2618*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&temp, v);
2619*5a6e8488SAndroid Build Coastguard Worker bc_num_add(&mult1, &temp, n, 0);
2620*5a6e8488SAndroid Build Coastguard Worker }
2621*5a6e8488SAndroid Build Coastguard Worker
2622*5a6e8488SAndroid Build Coastguard Worker // If this condition is true, then we are done. We still need to do cleanup
2623*5a6e8488SAndroid Build Coastguard Worker // though.
2624*5a6e8488SAndroid Build Coastguard Worker if (i == len && !val[i]) goto int_err;
2625*5a6e8488SAndroid Build Coastguard Worker
2626*5a6e8488SAndroid Build Coastguard Worker // If we get here, we *must* be at the radix point.
2627*5a6e8488SAndroid Build Coastguard Worker assert(val[i] == '.');
2628*5a6e8488SAndroid Build Coastguard Worker
2629*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
2630*5a6e8488SAndroid Build Coastguard Worker
2631*5a6e8488SAndroid Build Coastguard Worker // Unset the jump to reset in for these new initializations.
2632*5a6e8488SAndroid Build Coastguard Worker BC_UNSETJMP(vm);
2633*5a6e8488SAndroid Build Coastguard Worker
2634*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&mult2, BC_NUM_BIGDIG_LOG10);
2635*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&result1, BC_NUM_DEF_SIZE);
2636*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&result2, BC_NUM_DEF_SIZE);
2637*5a6e8488SAndroid Build Coastguard Worker bc_num_one(&mult1);
2638*5a6e8488SAndroid Build Coastguard Worker
2639*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
2640*5a6e8488SAndroid Build Coastguard Worker
2641*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
2642*5a6e8488SAndroid Build Coastguard Worker
2643*5a6e8488SAndroid Build Coastguard Worker // Pointers for easy switching.
2644*5a6e8488SAndroid Build Coastguard Worker m1 = &mult1;
2645*5a6e8488SAndroid Build Coastguard Worker m2 = &mult2;
2646*5a6e8488SAndroid Build Coastguard Worker
2647*5a6e8488SAndroid Build Coastguard Worker // Parse the fractional part. This is the hard part.
2648*5a6e8488SAndroid Build Coastguard Worker for (i += 1, digs = 0; i < len && (c = val[i]); ++i, ++digs)
2649*5a6e8488SAndroid Build Coastguard Worker {
2650*5a6e8488SAndroid Build Coastguard Worker size_t rdx;
2651*5a6e8488SAndroid Build Coastguard Worker
2652*5a6e8488SAndroid Build Coastguard Worker // Convert the character to a digit.
2653*5a6e8488SAndroid Build Coastguard Worker v = bc_num_parseChar(c, base);
2654*5a6e8488SAndroid Build Coastguard Worker
2655*5a6e8488SAndroid Build Coastguard Worker // We keep growing result2 according to the base because the more digits
2656*5a6e8488SAndroid Build Coastguard Worker // after the radix, the more significant the digits close to the radix
2657*5a6e8488SAndroid Build Coastguard Worker // should be.
2658*5a6e8488SAndroid Build Coastguard Worker bc_num_mulArray(&result1, base, &result2);
2659*5a6e8488SAndroid Build Coastguard Worker
2660*5a6e8488SAndroid Build Coastguard Worker // Convert the digit to a number.
2661*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&temp, v);
2662*5a6e8488SAndroid Build Coastguard Worker
2663*5a6e8488SAndroid Build Coastguard Worker // Add the digit into the fraction part.
2664*5a6e8488SAndroid Build Coastguard Worker bc_num_add(&result2, &temp, &result1, 0);
2665*5a6e8488SAndroid Build Coastguard Worker
2666*5a6e8488SAndroid Build Coastguard Worker // Keep growing m1 and m2 for use after the loop.
2667*5a6e8488SAndroid Build Coastguard Worker bc_num_mulArray(m1, base, m2);
2668*5a6e8488SAndroid Build Coastguard Worker
2669*5a6e8488SAndroid Build Coastguard Worker rdx = BC_NUM_RDX_VAL(m2);
2670*5a6e8488SAndroid Build Coastguard Worker
2671*5a6e8488SAndroid Build Coastguard Worker if (m2->len < rdx) m2->len = rdx;
2672*5a6e8488SAndroid Build Coastguard Worker
2673*5a6e8488SAndroid Build Coastguard Worker // Switch.
2674*5a6e8488SAndroid Build Coastguard Worker ptr = m1;
2675*5a6e8488SAndroid Build Coastguard Worker m1 = m2;
2676*5a6e8488SAndroid Build Coastguard Worker m2 = ptr;
2677*5a6e8488SAndroid Build Coastguard Worker }
2678*5a6e8488SAndroid Build Coastguard Worker
2679*5a6e8488SAndroid Build Coastguard Worker // This one cannot be a divide by 0 because mult starts out at 1, then is
2680*5a6e8488SAndroid Build Coastguard Worker // multiplied by base, and base cannot be 0, so mult cannot be 0. And this
2681*5a6e8488SAndroid Build Coastguard Worker // is the reason we keep growing m1 and m2; this division is what converts
2682*5a6e8488SAndroid Build Coastguard Worker // the parsed fractional part from an integer to a fractional part.
2683*5a6e8488SAndroid Build Coastguard Worker bc_num_div(&result1, m1, &result2, digs * 2);
2684*5a6e8488SAndroid Build Coastguard Worker
2685*5a6e8488SAndroid Build Coastguard Worker // Pretruncate.
2686*5a6e8488SAndroid Build Coastguard Worker bc_num_truncate(&result2, digs);
2687*5a6e8488SAndroid Build Coastguard Worker
2688*5a6e8488SAndroid Build Coastguard Worker // The final add of the integer part to the fractional part.
2689*5a6e8488SAndroid Build Coastguard Worker bc_num_add(n, &result2, n, digs);
2690*5a6e8488SAndroid Build Coastguard Worker
2691*5a6e8488SAndroid Build Coastguard Worker // Basic cleanup.
2692*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(n))
2693*5a6e8488SAndroid Build Coastguard Worker {
2694*5a6e8488SAndroid Build Coastguard Worker if (n->scale < digs) bc_num_extend(n, digs - n->scale);
2695*5a6e8488SAndroid Build Coastguard Worker }
2696*5a6e8488SAndroid Build Coastguard Worker else bc_num_zero(n);
2697*5a6e8488SAndroid Build Coastguard Worker
2698*5a6e8488SAndroid Build Coastguard Worker err:
2699*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
2700*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&result2);
2701*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&result1);
2702*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&mult2);
2703*5a6e8488SAndroid Build Coastguard Worker int_err:
2704*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
2705*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&mult1);
2706*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&temp);
2707*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
2708*5a6e8488SAndroid Build Coastguard Worker }
2709*5a6e8488SAndroid Build Coastguard Worker
2710*5a6e8488SAndroid Build Coastguard Worker /**
2711*5a6e8488SAndroid Build Coastguard Worker * Prints a backslash+newline combo if the number of characters needs it. This
2712*5a6e8488SAndroid Build Coastguard Worker * is really a convenience function.
2713*5a6e8488SAndroid Build Coastguard Worker */
2714*5a6e8488SAndroid Build Coastguard Worker static inline void
bc_num_printNewline(void)2715*5a6e8488SAndroid Build Coastguard Worker bc_num_printNewline(void)
2716*5a6e8488SAndroid Build Coastguard Worker {
2717*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
2718*5a6e8488SAndroid Build Coastguard Worker if (vm->nchars >= vm->line_len - 1 && vm->line_len)
2719*5a6e8488SAndroid Build Coastguard Worker {
2720*5a6e8488SAndroid Build Coastguard Worker bc_vm_putchar('\\', bc_flush_none);
2721*5a6e8488SAndroid Build Coastguard Worker bc_vm_putchar('\n', bc_flush_err);
2722*5a6e8488SAndroid Build Coastguard Worker }
2723*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
2724*5a6e8488SAndroid Build Coastguard Worker }
2725*5a6e8488SAndroid Build Coastguard Worker
2726*5a6e8488SAndroid Build Coastguard Worker /**
2727*5a6e8488SAndroid Build Coastguard Worker * Prints a character after a backslash+newline, if needed.
2728*5a6e8488SAndroid Build Coastguard Worker * @param c The character to print.
2729*5a6e8488SAndroid Build Coastguard Worker * @param bslash Whether to print a backslash+newline.
2730*5a6e8488SAndroid Build Coastguard Worker */
2731*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_putchar(int c,bool bslash)2732*5a6e8488SAndroid Build Coastguard Worker bc_num_putchar(int c, bool bslash)
2733*5a6e8488SAndroid Build Coastguard Worker {
2734*5a6e8488SAndroid Build Coastguard Worker if (c != '\n' && bslash) bc_num_printNewline();
2735*5a6e8488SAndroid Build Coastguard Worker bc_vm_putchar(c, bc_flush_save);
2736*5a6e8488SAndroid Build Coastguard Worker }
2737*5a6e8488SAndroid Build Coastguard Worker
2738*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
2739*5a6e8488SAndroid Build Coastguard Worker
2740*5a6e8488SAndroid Build Coastguard Worker /**
2741*5a6e8488SAndroid Build Coastguard Worker * Prints a character for a number's digit. This is for printing for dc's P
2742*5a6e8488SAndroid Build Coastguard Worker * command. This function does not need to worry about radix points. This is a
2743*5a6e8488SAndroid Build Coastguard Worker * BcNumDigitOp.
2744*5a6e8488SAndroid Build Coastguard Worker * @param n The "digit" to print.
2745*5a6e8488SAndroid Build Coastguard Worker * @param len The "length" of the digit, or number of characters that will
2746*5a6e8488SAndroid Build Coastguard Worker * need to be printed for the digit.
2747*5a6e8488SAndroid Build Coastguard Worker * @param rdx True if a decimal (radix) point should be printed.
2748*5a6e8488SAndroid Build Coastguard Worker * @param bslash True if a backslash+newline should be printed if the character
2749*5a6e8488SAndroid Build Coastguard Worker * limit for the line is reached, false otherwise.
2750*5a6e8488SAndroid Build Coastguard Worker */
2751*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printChar(size_t n,size_t len,bool rdx,bool bslash)2752*5a6e8488SAndroid Build Coastguard Worker bc_num_printChar(size_t n, size_t len, bool rdx, bool bslash)
2753*5a6e8488SAndroid Build Coastguard Worker {
2754*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(rdx);
2755*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(len);
2756*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(bslash);
2757*5a6e8488SAndroid Build Coastguard Worker assert(len == 1);
2758*5a6e8488SAndroid Build Coastguard Worker bc_vm_putchar((uchar) n, bc_flush_save);
2759*5a6e8488SAndroid Build Coastguard Worker }
2760*5a6e8488SAndroid Build Coastguard Worker
2761*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
2762*5a6e8488SAndroid Build Coastguard Worker
2763*5a6e8488SAndroid Build Coastguard Worker /**
2764*5a6e8488SAndroid Build Coastguard Worker * Prints a series of characters for large bases. This is for printing in bases
2765*5a6e8488SAndroid Build Coastguard Worker * above hexadecimal. This is a BcNumDigitOp.
2766*5a6e8488SAndroid Build Coastguard Worker * @param n The "digit" to print.
2767*5a6e8488SAndroid Build Coastguard Worker * @param len The "length" of the digit, or number of characters that will
2768*5a6e8488SAndroid Build Coastguard Worker * need to be printed for the digit.
2769*5a6e8488SAndroid Build Coastguard Worker * @param rdx True if a decimal (radix) point should be printed.
2770*5a6e8488SAndroid Build Coastguard Worker * @param bslash True if a backslash+newline should be printed if the character
2771*5a6e8488SAndroid Build Coastguard Worker * limit for the line is reached, false otherwise.
2772*5a6e8488SAndroid Build Coastguard Worker */
2773*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printDigits(size_t n,size_t len,bool rdx,bool bslash)2774*5a6e8488SAndroid Build Coastguard Worker bc_num_printDigits(size_t n, size_t len, bool rdx, bool bslash)
2775*5a6e8488SAndroid Build Coastguard Worker {
2776*5a6e8488SAndroid Build Coastguard Worker size_t exp, pow;
2777*5a6e8488SAndroid Build Coastguard Worker
2778*5a6e8488SAndroid Build Coastguard Worker // If needed, print the radix; otherwise, print a space to separate digits.
2779*5a6e8488SAndroid Build Coastguard Worker bc_num_putchar(rdx ? '.' : ' ', true);
2780*5a6e8488SAndroid Build Coastguard Worker
2781*5a6e8488SAndroid Build Coastguard Worker // Calculate the exponent and power.
2782*5a6e8488SAndroid Build Coastguard Worker for (exp = 0, pow = 1; exp < len - 1; ++exp, pow *= BC_BASE)
2783*5a6e8488SAndroid Build Coastguard Worker {
2784*5a6e8488SAndroid Build Coastguard Worker continue;
2785*5a6e8488SAndroid Build Coastguard Worker }
2786*5a6e8488SAndroid Build Coastguard Worker
2787*5a6e8488SAndroid Build Coastguard Worker // Print each character individually.
2788*5a6e8488SAndroid Build Coastguard Worker for (exp = 0; exp < len; pow /= BC_BASE, ++exp)
2789*5a6e8488SAndroid Build Coastguard Worker {
2790*5a6e8488SAndroid Build Coastguard Worker // The individual subdigit.
2791*5a6e8488SAndroid Build Coastguard Worker size_t dig = n / pow;
2792*5a6e8488SAndroid Build Coastguard Worker
2793*5a6e8488SAndroid Build Coastguard Worker // Take the subdigit away.
2794*5a6e8488SAndroid Build Coastguard Worker n -= dig * pow;
2795*5a6e8488SAndroid Build Coastguard Worker
2796*5a6e8488SAndroid Build Coastguard Worker // Print the subdigit.
2797*5a6e8488SAndroid Build Coastguard Worker bc_num_putchar(((uchar) dig) + '0', bslash || exp != len - 1);
2798*5a6e8488SAndroid Build Coastguard Worker }
2799*5a6e8488SAndroid Build Coastguard Worker }
2800*5a6e8488SAndroid Build Coastguard Worker
2801*5a6e8488SAndroid Build Coastguard Worker /**
2802*5a6e8488SAndroid Build Coastguard Worker * Prints a character for a number's digit. This is for printing in bases for
2803*5a6e8488SAndroid Build Coastguard Worker * hexadecimal and below because they always print only one character at a time.
2804*5a6e8488SAndroid Build Coastguard Worker * This is a BcNumDigitOp.
2805*5a6e8488SAndroid Build Coastguard Worker * @param n The "digit" to print.
2806*5a6e8488SAndroid Build Coastguard Worker * @param len The "length" of the digit, or number of characters that will
2807*5a6e8488SAndroid Build Coastguard Worker * need to be printed for the digit.
2808*5a6e8488SAndroid Build Coastguard Worker * @param rdx True if a decimal (radix) point should be printed.
2809*5a6e8488SAndroid Build Coastguard Worker * @param bslash True if a backslash+newline should be printed if the character
2810*5a6e8488SAndroid Build Coastguard Worker * limit for the line is reached, false otherwise.
2811*5a6e8488SAndroid Build Coastguard Worker */
2812*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printHex(size_t n,size_t len,bool rdx,bool bslash)2813*5a6e8488SAndroid Build Coastguard Worker bc_num_printHex(size_t n, size_t len, bool rdx, bool bslash)
2814*5a6e8488SAndroid Build Coastguard Worker {
2815*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(len);
2816*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(bslash);
2817*5a6e8488SAndroid Build Coastguard Worker
2818*5a6e8488SAndroid Build Coastguard Worker assert(len == 1);
2819*5a6e8488SAndroid Build Coastguard Worker
2820*5a6e8488SAndroid Build Coastguard Worker if (rdx) bc_num_putchar('.', true);
2821*5a6e8488SAndroid Build Coastguard Worker
2822*5a6e8488SAndroid Build Coastguard Worker bc_num_putchar(bc_num_hex_digits[n], bslash);
2823*5a6e8488SAndroid Build Coastguard Worker }
2824*5a6e8488SAndroid Build Coastguard Worker
2825*5a6e8488SAndroid Build Coastguard Worker /**
2826*5a6e8488SAndroid Build Coastguard Worker * Prints a decimal number. This is specially written for optimization since
2827*5a6e8488SAndroid Build Coastguard Worker * this will be used the most and because bc's numbers are already in decimal.
2828*5a6e8488SAndroid Build Coastguard Worker * @param n The number to print.
2829*5a6e8488SAndroid Build Coastguard Worker * @param newline Whether to print backslash+newlines on long enough lines.
2830*5a6e8488SAndroid Build Coastguard Worker */
2831*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printDecimal(const BcNum * restrict n,bool newline)2832*5a6e8488SAndroid Build Coastguard Worker bc_num_printDecimal(const BcNum* restrict n, bool newline)
2833*5a6e8488SAndroid Build Coastguard Worker {
2834*5a6e8488SAndroid Build Coastguard Worker size_t i, j, rdx = BC_NUM_RDX_VAL(n);
2835*5a6e8488SAndroid Build Coastguard Worker bool zero = true;
2836*5a6e8488SAndroid Build Coastguard Worker size_t buffer[BC_BASE_DIGS];
2837*5a6e8488SAndroid Build Coastguard Worker
2838*5a6e8488SAndroid Build Coastguard Worker // Print loop.
2839*5a6e8488SAndroid Build Coastguard Worker for (i = n->len - 1; i < n->len; --i)
2840*5a6e8488SAndroid Build Coastguard Worker {
2841*5a6e8488SAndroid Build Coastguard Worker BcDig n9 = n->num[i];
2842*5a6e8488SAndroid Build Coastguard Worker size_t temp;
2843*5a6e8488SAndroid Build Coastguard Worker bool irdx = (i == rdx - 1);
2844*5a6e8488SAndroid Build Coastguard Worker
2845*5a6e8488SAndroid Build Coastguard Worker // Calculate the number of digits in the limb.
2846*5a6e8488SAndroid Build Coastguard Worker zero = (zero & !irdx);
2847*5a6e8488SAndroid Build Coastguard Worker temp = n->scale % BC_BASE_DIGS;
2848*5a6e8488SAndroid Build Coastguard Worker temp = i || !temp ? 0 : BC_BASE_DIGS - temp;
2849*5a6e8488SAndroid Build Coastguard Worker
2850*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
2851*5a6e8488SAndroid Build Coastguard Worker memset(buffer, 0, BC_BASE_DIGS * sizeof(size_t));
2852*5a6e8488SAndroid Build Coastguard Worker
2853*5a6e8488SAndroid Build Coastguard Worker // Fill the buffer with individual digits.
2854*5a6e8488SAndroid Build Coastguard Worker for (j = 0; n9 && j < BC_BASE_DIGS; ++j)
2855*5a6e8488SAndroid Build Coastguard Worker {
2856*5a6e8488SAndroid Build Coastguard Worker buffer[j] = ((size_t) n9) % BC_BASE;
2857*5a6e8488SAndroid Build Coastguard Worker n9 /= BC_BASE;
2858*5a6e8488SAndroid Build Coastguard Worker }
2859*5a6e8488SAndroid Build Coastguard Worker
2860*5a6e8488SAndroid Build Coastguard Worker // Print the digits in the buffer.
2861*5a6e8488SAndroid Build Coastguard Worker for (j = BC_BASE_DIGS - 1; j < BC_BASE_DIGS && j >= temp; --j)
2862*5a6e8488SAndroid Build Coastguard Worker {
2863*5a6e8488SAndroid Build Coastguard Worker // Figure out whether to print the decimal point.
2864*5a6e8488SAndroid Build Coastguard Worker bool print_rdx = (irdx & (j == BC_BASE_DIGS - 1));
2865*5a6e8488SAndroid Build Coastguard Worker
2866*5a6e8488SAndroid Build Coastguard Worker // The zero variable helps us skip leading zero digits in the limb.
2867*5a6e8488SAndroid Build Coastguard Worker zero = (zero && buffer[j] == 0);
2868*5a6e8488SAndroid Build Coastguard Worker
2869*5a6e8488SAndroid Build Coastguard Worker if (!zero)
2870*5a6e8488SAndroid Build Coastguard Worker {
2871*5a6e8488SAndroid Build Coastguard Worker // While the first three arguments should be self-explanatory,
2872*5a6e8488SAndroid Build Coastguard Worker // the last needs explaining. I don't want to print a newline
2873*5a6e8488SAndroid Build Coastguard Worker // when the last digit to be printed could take the place of the
2874*5a6e8488SAndroid Build Coastguard Worker // backslash rather than being pushed, as a single character, to
2875*5a6e8488SAndroid Build Coastguard Worker // the next line. That's what that last argument does for bc.
2876*5a6e8488SAndroid Build Coastguard Worker bc_num_printHex(buffer[j], 1, print_rdx,
2877*5a6e8488SAndroid Build Coastguard Worker !newline || (j > temp || i != 0));
2878*5a6e8488SAndroid Build Coastguard Worker }
2879*5a6e8488SAndroid Build Coastguard Worker }
2880*5a6e8488SAndroid Build Coastguard Worker }
2881*5a6e8488SAndroid Build Coastguard Worker }
2882*5a6e8488SAndroid Build Coastguard Worker
2883*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2884*5a6e8488SAndroid Build Coastguard Worker
2885*5a6e8488SAndroid Build Coastguard Worker /**
2886*5a6e8488SAndroid Build Coastguard Worker * Prints a number in scientific or engineering format. When doing this, we are
2887*5a6e8488SAndroid Build Coastguard Worker * always printing in decimal.
2888*5a6e8488SAndroid Build Coastguard Worker * @param n The number to print.
2889*5a6e8488SAndroid Build Coastguard Worker * @param eng True if we are in engineering mode.
2890*5a6e8488SAndroid Build Coastguard Worker * @param newline Whether to print backslash+newlines on long enough lines.
2891*5a6e8488SAndroid Build Coastguard Worker */
2892*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printExponent(const BcNum * restrict n,bool eng,bool newline)2893*5a6e8488SAndroid Build Coastguard Worker bc_num_printExponent(const BcNum* restrict n, bool eng, bool newline)
2894*5a6e8488SAndroid Build Coastguard Worker {
2895*5a6e8488SAndroid Build Coastguard Worker size_t places, mod, nrdx = BC_NUM_RDX_VAL(n);
2896*5a6e8488SAndroid Build Coastguard Worker bool neg = (n->len <= nrdx);
2897*5a6e8488SAndroid Build Coastguard Worker BcNum temp, exp;
2898*5a6e8488SAndroid Build Coastguard Worker BcDig digs[BC_NUM_BIGDIG_LOG10];
2899*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
2900*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
2901*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
2902*5a6e8488SAndroid Build Coastguard Worker
2903*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
2904*5a6e8488SAndroid Build Coastguard Worker
2905*5a6e8488SAndroid Build Coastguard Worker bc_num_createCopy(&temp, n);
2906*5a6e8488SAndroid Build Coastguard Worker
2907*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, exit);
2908*5a6e8488SAndroid Build Coastguard Worker
2909*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
2910*5a6e8488SAndroid Build Coastguard Worker
2911*5a6e8488SAndroid Build Coastguard Worker // We need to calculate the exponents, and they change based on whether the
2912*5a6e8488SAndroid Build Coastguard Worker // number is all fractional or not, obviously.
2913*5a6e8488SAndroid Build Coastguard Worker if (neg)
2914*5a6e8488SAndroid Build Coastguard Worker {
2915*5a6e8488SAndroid Build Coastguard Worker // Figure out the negative power of 10.
2916*5a6e8488SAndroid Build Coastguard Worker places = bc_num_negPow10(n);
2917*5a6e8488SAndroid Build Coastguard Worker
2918*5a6e8488SAndroid Build Coastguard Worker // Figure out how many digits mod 3 there are (important for
2919*5a6e8488SAndroid Build Coastguard Worker // engineering mode).
2920*5a6e8488SAndroid Build Coastguard Worker mod = places % 3;
2921*5a6e8488SAndroid Build Coastguard Worker
2922*5a6e8488SAndroid Build Coastguard Worker // Calculate places if we are in engineering mode.
2923*5a6e8488SAndroid Build Coastguard Worker if (eng && mod != 0) places += 3 - mod;
2924*5a6e8488SAndroid Build Coastguard Worker
2925*5a6e8488SAndroid Build Coastguard Worker // Shift the temp to the right place.
2926*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(&temp, places);
2927*5a6e8488SAndroid Build Coastguard Worker }
2928*5a6e8488SAndroid Build Coastguard Worker else
2929*5a6e8488SAndroid Build Coastguard Worker {
2930*5a6e8488SAndroid Build Coastguard Worker // This is the number of digits that we are supposed to put behind the
2931*5a6e8488SAndroid Build Coastguard Worker // decimal point.
2932*5a6e8488SAndroid Build Coastguard Worker places = bc_num_intDigits(n) - 1;
2933*5a6e8488SAndroid Build Coastguard Worker
2934*5a6e8488SAndroid Build Coastguard Worker // Calculate the true number based on whether engineering mode is
2935*5a6e8488SAndroid Build Coastguard Worker // activated.
2936*5a6e8488SAndroid Build Coastguard Worker mod = places % 3;
2937*5a6e8488SAndroid Build Coastguard Worker if (eng && mod != 0) places -= 3 - (3 - mod);
2938*5a6e8488SAndroid Build Coastguard Worker
2939*5a6e8488SAndroid Build Coastguard Worker // Shift the temp to the right place.
2940*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftRight(&temp, places);
2941*5a6e8488SAndroid Build Coastguard Worker }
2942*5a6e8488SAndroid Build Coastguard Worker
2943*5a6e8488SAndroid Build Coastguard Worker // Print the shifted number.
2944*5a6e8488SAndroid Build Coastguard Worker bc_num_printDecimal(&temp, newline);
2945*5a6e8488SAndroid Build Coastguard Worker
2946*5a6e8488SAndroid Build Coastguard Worker // Print the e.
2947*5a6e8488SAndroid Build Coastguard Worker bc_num_putchar('e', !newline);
2948*5a6e8488SAndroid Build Coastguard Worker
2949*5a6e8488SAndroid Build Coastguard Worker // Need to explicitly print a zero exponent.
2950*5a6e8488SAndroid Build Coastguard Worker if (!places)
2951*5a6e8488SAndroid Build Coastguard Worker {
2952*5a6e8488SAndroid Build Coastguard Worker bc_num_printHex(0, 1, false, !newline);
2953*5a6e8488SAndroid Build Coastguard Worker goto exit;
2954*5a6e8488SAndroid Build Coastguard Worker }
2955*5a6e8488SAndroid Build Coastguard Worker
2956*5a6e8488SAndroid Build Coastguard Worker // Need to print sign for the exponent.
2957*5a6e8488SAndroid Build Coastguard Worker if (neg) bc_num_putchar('-', true);
2958*5a6e8488SAndroid Build Coastguard Worker
2959*5a6e8488SAndroid Build Coastguard Worker // Create a temporary for the exponent...
2960*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&exp, digs, BC_NUM_BIGDIG_LOG10);
2961*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&exp, (BcBigDig) places);
2962*5a6e8488SAndroid Build Coastguard Worker
2963*5a6e8488SAndroid Build Coastguard Worker /// ..and print it.
2964*5a6e8488SAndroid Build Coastguard Worker bc_num_printDecimal(&exp, newline);
2965*5a6e8488SAndroid Build Coastguard Worker
2966*5a6e8488SAndroid Build Coastguard Worker exit:
2967*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
2968*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&temp);
2969*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
2970*5a6e8488SAndroid Build Coastguard Worker }
2971*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2972*5a6e8488SAndroid Build Coastguard Worker
2973*5a6e8488SAndroid Build Coastguard Worker /**
2974*5a6e8488SAndroid Build Coastguard Worker * Takes a number with limbs with base BC_BASE_POW and converts the limb at the
2975*5a6e8488SAndroid Build Coastguard Worker * given index to base @a pow, where @a pow is obase^N.
2976*5a6e8488SAndroid Build Coastguard Worker * @param n The number to convert.
2977*5a6e8488SAndroid Build Coastguard Worker * @param rem BC_BASE_POW - @a pow.
2978*5a6e8488SAndroid Build Coastguard Worker * @param pow The power of obase we will convert the number to.
2979*5a6e8488SAndroid Build Coastguard Worker * @param idx The index of the number to start converting at. Doing the
2980*5a6e8488SAndroid Build Coastguard Worker * conversion is O(n^2); we have to sweep through starting at the
2981*5a6e8488SAndroid Build Coastguard Worker * least significant limb.
2982*5a6e8488SAndroid Build Coastguard Worker */
2983*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printFixup(BcNum * restrict n,BcBigDig rem,BcBigDig pow,size_t idx)2984*5a6e8488SAndroid Build Coastguard Worker bc_num_printFixup(BcNum* restrict n, BcBigDig rem, BcBigDig pow, size_t idx)
2985*5a6e8488SAndroid Build Coastguard Worker {
2986*5a6e8488SAndroid Build Coastguard Worker size_t i, len = n->len - idx;
2987*5a6e8488SAndroid Build Coastguard Worker BcBigDig acc;
2988*5a6e8488SAndroid Build Coastguard Worker BcDig* a = n->num + idx;
2989*5a6e8488SAndroid Build Coastguard Worker
2990*5a6e8488SAndroid Build Coastguard Worker // Ignore if there's just one limb left. This is the part that requires the
2991*5a6e8488SAndroid Build Coastguard Worker // extra loop after the one calling this function in bc_num_printPrepare().
2992*5a6e8488SAndroid Build Coastguard Worker if (len < 2) return;
2993*5a6e8488SAndroid Build Coastguard Worker
2994*5a6e8488SAndroid Build Coastguard Worker // Loop through the remaining limbs and convert. We start at the second limb
2995*5a6e8488SAndroid Build Coastguard Worker // because we pull the value from the previous one as well.
2996*5a6e8488SAndroid Build Coastguard Worker for (i = len - 1; i > 0; --i)
2997*5a6e8488SAndroid Build Coastguard Worker {
2998*5a6e8488SAndroid Build Coastguard Worker // Get the limb and add it to the previous, along with multiplying by
2999*5a6e8488SAndroid Build Coastguard Worker // the remainder because that's the proper overflow. "acc" means
3000*5a6e8488SAndroid Build Coastguard Worker // "accumulator," by the way.
3001*5a6e8488SAndroid Build Coastguard Worker acc = ((BcBigDig) a[i]) * rem + ((BcBigDig) a[i - 1]);
3002*5a6e8488SAndroid Build Coastguard Worker
3003*5a6e8488SAndroid Build Coastguard Worker // Store a value in base pow in the previous limb.
3004*5a6e8488SAndroid Build Coastguard Worker a[i - 1] = (BcDig) (acc % pow);
3005*5a6e8488SAndroid Build Coastguard Worker
3006*5a6e8488SAndroid Build Coastguard Worker // Divide by the base and accumulate the remaining value in the limb.
3007*5a6e8488SAndroid Build Coastguard Worker acc /= pow;
3008*5a6e8488SAndroid Build Coastguard Worker acc += (BcBigDig) a[i];
3009*5a6e8488SAndroid Build Coastguard Worker
3010*5a6e8488SAndroid Build Coastguard Worker // If the accumulator is greater than the base...
3011*5a6e8488SAndroid Build Coastguard Worker if (acc >= BC_BASE_POW)
3012*5a6e8488SAndroid Build Coastguard Worker {
3013*5a6e8488SAndroid Build Coastguard Worker // Do we need to grow?
3014*5a6e8488SAndroid Build Coastguard Worker if (i == len - 1)
3015*5a6e8488SAndroid Build Coastguard Worker {
3016*5a6e8488SAndroid Build Coastguard Worker // Grow.
3017*5a6e8488SAndroid Build Coastguard Worker len = bc_vm_growSize(len, 1);
3018*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(n, bc_vm_growSize(len, idx));
3019*5a6e8488SAndroid Build Coastguard Worker
3020*5a6e8488SAndroid Build Coastguard Worker // Update the pointer because it may have moved.
3021*5a6e8488SAndroid Build Coastguard Worker a = n->num + idx;
3022*5a6e8488SAndroid Build Coastguard Worker
3023*5a6e8488SAndroid Build Coastguard Worker // Zero out the last limb.
3024*5a6e8488SAndroid Build Coastguard Worker a[len - 1] = 0;
3025*5a6e8488SAndroid Build Coastguard Worker }
3026*5a6e8488SAndroid Build Coastguard Worker
3027*5a6e8488SAndroid Build Coastguard Worker // Overflow into the next limb since we are over the base.
3028*5a6e8488SAndroid Build Coastguard Worker a[i + 1] += acc / BC_BASE_POW;
3029*5a6e8488SAndroid Build Coastguard Worker acc %= BC_BASE_POW;
3030*5a6e8488SAndroid Build Coastguard Worker }
3031*5a6e8488SAndroid Build Coastguard Worker
3032*5a6e8488SAndroid Build Coastguard Worker assert(acc < BC_BASE_POW);
3033*5a6e8488SAndroid Build Coastguard Worker
3034*5a6e8488SAndroid Build Coastguard Worker // Set the limb.
3035*5a6e8488SAndroid Build Coastguard Worker a[i] = (BcDig) acc;
3036*5a6e8488SAndroid Build Coastguard Worker }
3037*5a6e8488SAndroid Build Coastguard Worker
3038*5a6e8488SAndroid Build Coastguard Worker // We may have grown the number, so adjust the length.
3039*5a6e8488SAndroid Build Coastguard Worker n->len = len + idx;
3040*5a6e8488SAndroid Build Coastguard Worker }
3041*5a6e8488SAndroid Build Coastguard Worker
3042*5a6e8488SAndroid Build Coastguard Worker /**
3043*5a6e8488SAndroid Build Coastguard Worker * Prepares a number for printing in a base that does not have BC_BASE_POW as a
3044*5a6e8488SAndroid Build Coastguard Worker * power. This basically converts the number from having limbs of base
3045*5a6e8488SAndroid Build Coastguard Worker * BC_BASE_POW to limbs of pow, where pow is obase^N.
3046*5a6e8488SAndroid Build Coastguard Worker * @param n The number to prepare for printing.
3047*5a6e8488SAndroid Build Coastguard Worker * @param rem The remainder of BC_BASE_POW when divided by a power of the base.
3048*5a6e8488SAndroid Build Coastguard Worker * @param pow The power of the base.
3049*5a6e8488SAndroid Build Coastguard Worker */
3050*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printPrepare(BcNum * restrict n,BcBigDig rem,BcBigDig pow)3051*5a6e8488SAndroid Build Coastguard Worker bc_num_printPrepare(BcNum* restrict n, BcBigDig rem, BcBigDig pow)
3052*5a6e8488SAndroid Build Coastguard Worker {
3053*5a6e8488SAndroid Build Coastguard Worker size_t i;
3054*5a6e8488SAndroid Build Coastguard Worker
3055*5a6e8488SAndroid Build Coastguard Worker // Loop from the least significant limb to the most significant limb and
3056*5a6e8488SAndroid Build Coastguard Worker // convert limbs in each pass.
3057*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < n->len; ++i)
3058*5a6e8488SAndroid Build Coastguard Worker {
3059*5a6e8488SAndroid Build Coastguard Worker bc_num_printFixup(n, rem, pow, i);
3060*5a6e8488SAndroid Build Coastguard Worker }
3061*5a6e8488SAndroid Build Coastguard Worker
3062*5a6e8488SAndroid Build Coastguard Worker // bc_num_printFixup() does not do everything it is supposed to, so we do
3063*5a6e8488SAndroid Build Coastguard Worker // the last bit of cleanup here. That cleanup is to ensure that each limb
3064*5a6e8488SAndroid Build Coastguard Worker // is less than pow and to expand the number to fit new limbs as necessary.
3065*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < n->len; ++i)
3066*5a6e8488SAndroid Build Coastguard Worker {
3067*5a6e8488SAndroid Build Coastguard Worker assert(pow == ((BcBigDig) ((BcDig) pow)));
3068*5a6e8488SAndroid Build Coastguard Worker
3069*5a6e8488SAndroid Build Coastguard Worker // If the limb needs fixing...
3070*5a6e8488SAndroid Build Coastguard Worker if (n->num[i] >= (BcDig) pow)
3071*5a6e8488SAndroid Build Coastguard Worker {
3072*5a6e8488SAndroid Build Coastguard Worker // Do we need to grow?
3073*5a6e8488SAndroid Build Coastguard Worker if (i + 1 == n->len)
3074*5a6e8488SAndroid Build Coastguard Worker {
3075*5a6e8488SAndroid Build Coastguard Worker // Grow the number.
3076*5a6e8488SAndroid Build Coastguard Worker n->len = bc_vm_growSize(n->len, 1);
3077*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(n, n->len);
3078*5a6e8488SAndroid Build Coastguard Worker
3079*5a6e8488SAndroid Build Coastguard Worker // Without this, we might use uninitialized data.
3080*5a6e8488SAndroid Build Coastguard Worker n->num[i + 1] = 0;
3081*5a6e8488SAndroid Build Coastguard Worker }
3082*5a6e8488SAndroid Build Coastguard Worker
3083*5a6e8488SAndroid Build Coastguard Worker assert(pow < BC_BASE_POW);
3084*5a6e8488SAndroid Build Coastguard Worker
3085*5a6e8488SAndroid Build Coastguard Worker // Overflow into the next limb.
3086*5a6e8488SAndroid Build Coastguard Worker n->num[i + 1] += n->num[i] / ((BcDig) pow);
3087*5a6e8488SAndroid Build Coastguard Worker n->num[i] %= (BcDig) pow;
3088*5a6e8488SAndroid Build Coastguard Worker }
3089*5a6e8488SAndroid Build Coastguard Worker }
3090*5a6e8488SAndroid Build Coastguard Worker }
3091*5a6e8488SAndroid Build Coastguard Worker
3092*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printNum(BcNum * restrict n,BcBigDig base,size_t len,BcNumDigitOp print,bool newline)3093*5a6e8488SAndroid Build Coastguard Worker bc_num_printNum(BcNum* restrict n, BcBigDig base, size_t len,
3094*5a6e8488SAndroid Build Coastguard Worker BcNumDigitOp print, bool newline)
3095*5a6e8488SAndroid Build Coastguard Worker {
3096*5a6e8488SAndroid Build Coastguard Worker BcVec stack;
3097*5a6e8488SAndroid Build Coastguard Worker BcNum intp, fracp1, fracp2, digit, flen1, flen2;
3098*5a6e8488SAndroid Build Coastguard Worker BcNum* n1;
3099*5a6e8488SAndroid Build Coastguard Worker BcNum* n2;
3100*5a6e8488SAndroid Build Coastguard Worker BcNum* temp;
3101*5a6e8488SAndroid Build Coastguard Worker BcBigDig dig = 0, acc, exp;
3102*5a6e8488SAndroid Build Coastguard Worker BcBigDig* ptr;
3103*5a6e8488SAndroid Build Coastguard Worker size_t i, j, nrdx, idigits;
3104*5a6e8488SAndroid Build Coastguard Worker bool radix;
3105*5a6e8488SAndroid Build Coastguard Worker BcDig digit_digs[BC_NUM_BIGDIG_LOG10 + 1];
3106*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
3107*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
3108*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
3109*5a6e8488SAndroid Build Coastguard Worker
3110*5a6e8488SAndroid Build Coastguard Worker assert(base > 1);
3111*5a6e8488SAndroid Build Coastguard Worker
3112*5a6e8488SAndroid Build Coastguard Worker // Easy case. Even with scale, we just print this.
3113*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(n))
3114*5a6e8488SAndroid Build Coastguard Worker {
3115*5a6e8488SAndroid Build Coastguard Worker print(0, len, false, !newline);
3116*5a6e8488SAndroid Build Coastguard Worker return;
3117*5a6e8488SAndroid Build Coastguard Worker }
3118*5a6e8488SAndroid Build Coastguard Worker
3119*5a6e8488SAndroid Build Coastguard Worker // This function uses an algorithm that Stefan Esser <[email protected]> came
3120*5a6e8488SAndroid Build Coastguard Worker // up with to print the integer part of a number. What it does is convert
3121*5a6e8488SAndroid Build Coastguard Worker // intp into a number of the specified base, but it does it directly,
3122*5a6e8488SAndroid Build Coastguard Worker // instead of just doing a series of divisions and printing the remainders
3123*5a6e8488SAndroid Build Coastguard Worker // in reverse order.
3124*5a6e8488SAndroid Build Coastguard Worker //
3125*5a6e8488SAndroid Build Coastguard Worker // Let me explain in a bit more detail:
3126*5a6e8488SAndroid Build Coastguard Worker //
3127*5a6e8488SAndroid Build Coastguard Worker // The algorithm takes the current least significant limb (after intp has
3128*5a6e8488SAndroid Build Coastguard Worker // been converted to an integer) and the next to least significant limb, and
3129*5a6e8488SAndroid Build Coastguard Worker // it converts the least significant limb into one of the specified base,
3130*5a6e8488SAndroid Build Coastguard Worker // putting any overflow into the next to least significant limb. It iterates
3131*5a6e8488SAndroid Build Coastguard Worker // through the whole number, from least significant to most significant,
3132*5a6e8488SAndroid Build Coastguard Worker // doing this conversion. At the end of that iteration, the least
3133*5a6e8488SAndroid Build Coastguard Worker // significant limb is converted, but the others are not, so it iterates
3134*5a6e8488SAndroid Build Coastguard Worker // again, starting at the next to least significant limb. It keeps doing
3135*5a6e8488SAndroid Build Coastguard Worker // that conversion, skipping one more limb than the last time, until all
3136*5a6e8488SAndroid Build Coastguard Worker // limbs have been converted. Then it prints them in reverse order.
3137*5a6e8488SAndroid Build Coastguard Worker //
3138*5a6e8488SAndroid Build Coastguard Worker // That is the gist of the algorithm. It leaves out several things, such as
3139*5a6e8488SAndroid Build Coastguard Worker // the fact that limbs are not always converted into the specified base, but
3140*5a6e8488SAndroid Build Coastguard Worker // into something close, basically a power of the specified base. In
3141*5a6e8488SAndroid Build Coastguard Worker // Stefan's words, "You could consider BcDigs to be of base 10^BC_BASE_DIGS
3142*5a6e8488SAndroid Build Coastguard Worker // in the normal case and obase^N for the largest value of N that satisfies
3143*5a6e8488SAndroid Build Coastguard Worker // obase^N <= 10^BC_BASE_DIGS. [This means that] the result is not in base
3144*5a6e8488SAndroid Build Coastguard Worker // "obase", but in base "obase^N", which happens to be printable as a number
3145*5a6e8488SAndroid Build Coastguard Worker // of base "obase" without consideration for neighbouring BcDigs." This fact
3146*5a6e8488SAndroid Build Coastguard Worker // is what necessitates the existence of the loop later in this function.
3147*5a6e8488SAndroid Build Coastguard Worker //
3148*5a6e8488SAndroid Build Coastguard Worker // The conversion happens in bc_num_printPrepare() where the outer loop
3149*5a6e8488SAndroid Build Coastguard Worker // happens and bc_num_printFixup() where the inner loop, or actual
3150*5a6e8488SAndroid Build Coastguard Worker // conversion, happens. In other words, bc_num_printPrepare() is where the
3151*5a6e8488SAndroid Build Coastguard Worker // loop that starts at the least significant limb and goes to the most
3152*5a6e8488SAndroid Build Coastguard Worker // significant limb. Then, on every iteration of its loop, it calls
3153*5a6e8488SAndroid Build Coastguard Worker // bc_num_printFixup(), which has the inner loop of actually converting
3154*5a6e8488SAndroid Build Coastguard Worker // the limbs it passes into limbs of base obase^N rather than base
3155*5a6e8488SAndroid Build Coastguard Worker // BC_BASE_POW.
3156*5a6e8488SAndroid Build Coastguard Worker
3157*5a6e8488SAndroid Build Coastguard Worker nrdx = BC_NUM_RDX_VAL(n);
3158*5a6e8488SAndroid Build Coastguard Worker
3159*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
3160*5a6e8488SAndroid Build Coastguard Worker
3161*5a6e8488SAndroid Build Coastguard Worker // The stack is what allows us to reverse the digits for printing.
3162*5a6e8488SAndroid Build Coastguard Worker bc_vec_init(&stack, sizeof(BcBigDig), BC_DTOR_NONE);
3163*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&fracp1, nrdx);
3164*5a6e8488SAndroid Build Coastguard Worker
3165*5a6e8488SAndroid Build Coastguard Worker // intp will be the "integer part" of the number, so copy it.
3166*5a6e8488SAndroid Build Coastguard Worker bc_num_createCopy(&intp, n);
3167*5a6e8488SAndroid Build Coastguard Worker
3168*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
3169*5a6e8488SAndroid Build Coastguard Worker
3170*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
3171*5a6e8488SAndroid Build Coastguard Worker
3172*5a6e8488SAndroid Build Coastguard Worker // Make intp an integer.
3173*5a6e8488SAndroid Build Coastguard Worker bc_num_truncate(&intp, intp.scale);
3174*5a6e8488SAndroid Build Coastguard Worker
3175*5a6e8488SAndroid Build Coastguard Worker // Get the fractional part out.
3176*5a6e8488SAndroid Build Coastguard Worker bc_num_sub(n, &intp, &fracp1, 0);
3177*5a6e8488SAndroid Build Coastguard Worker
3178*5a6e8488SAndroid Build Coastguard Worker // If the base is not the same as the last base used for printing, we need
3179*5a6e8488SAndroid Build Coastguard Worker // to update the cached exponent and power. Yes, we cache the values of the
3180*5a6e8488SAndroid Build Coastguard Worker // exponent and power. That is to prevent us from calculating them every
3181*5a6e8488SAndroid Build Coastguard Worker // time because printing will probably happen multiple times on the same
3182*5a6e8488SAndroid Build Coastguard Worker // base.
3183*5a6e8488SAndroid Build Coastguard Worker if (base != vm->last_base)
3184*5a6e8488SAndroid Build Coastguard Worker {
3185*5a6e8488SAndroid Build Coastguard Worker vm->last_pow = 1;
3186*5a6e8488SAndroid Build Coastguard Worker vm->last_exp = 0;
3187*5a6e8488SAndroid Build Coastguard Worker
3188*5a6e8488SAndroid Build Coastguard Worker // Calculate the exponent and power.
3189*5a6e8488SAndroid Build Coastguard Worker while (vm->last_pow * base <= BC_BASE_POW)
3190*5a6e8488SAndroid Build Coastguard Worker {
3191*5a6e8488SAndroid Build Coastguard Worker vm->last_pow *= base;
3192*5a6e8488SAndroid Build Coastguard Worker vm->last_exp += 1;
3193*5a6e8488SAndroid Build Coastguard Worker }
3194*5a6e8488SAndroid Build Coastguard Worker
3195*5a6e8488SAndroid Build Coastguard Worker // Also, the remainder and base itself.
3196*5a6e8488SAndroid Build Coastguard Worker vm->last_rem = BC_BASE_POW - vm->last_pow;
3197*5a6e8488SAndroid Build Coastguard Worker vm->last_base = base;
3198*5a6e8488SAndroid Build Coastguard Worker }
3199*5a6e8488SAndroid Build Coastguard Worker
3200*5a6e8488SAndroid Build Coastguard Worker exp = vm->last_exp;
3201*5a6e8488SAndroid Build Coastguard Worker
3202*5a6e8488SAndroid Build Coastguard Worker // If vm->last_rem is 0, then the base we are printing in is a divisor of
3203*5a6e8488SAndroid Build Coastguard Worker // BC_BASE_POW, which is the easy case because it means that BC_BASE_POW is
3204*5a6e8488SAndroid Build Coastguard Worker // a power of obase, and no conversion is needed. If it *is* 0, then we have
3205*5a6e8488SAndroid Build Coastguard Worker // the hard case, and we have to prepare the number for the base.
3206*5a6e8488SAndroid Build Coastguard Worker if (vm->last_rem != 0)
3207*5a6e8488SAndroid Build Coastguard Worker {
3208*5a6e8488SAndroid Build Coastguard Worker bc_num_printPrepare(&intp, vm->last_rem, vm->last_pow);
3209*5a6e8488SAndroid Build Coastguard Worker }
3210*5a6e8488SAndroid Build Coastguard Worker
3211*5a6e8488SAndroid Build Coastguard Worker // After the conversion comes the surprisingly easy part. From here on out,
3212*5a6e8488SAndroid Build Coastguard Worker // this is basically naive code that I wrote, adjusted for the larger bases.
3213*5a6e8488SAndroid Build Coastguard Worker
3214*5a6e8488SAndroid Build Coastguard Worker // Fill the stack of digits for the integer part.
3215*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < intp.len; ++i)
3216*5a6e8488SAndroid Build Coastguard Worker {
3217*5a6e8488SAndroid Build Coastguard Worker // Get the limb.
3218*5a6e8488SAndroid Build Coastguard Worker acc = (BcBigDig) intp.num[i];
3219*5a6e8488SAndroid Build Coastguard Worker
3220*5a6e8488SAndroid Build Coastguard Worker // Turn the limb into digits of base obase.
3221*5a6e8488SAndroid Build Coastguard Worker for (j = 0; j < exp && (i < intp.len - 1 || acc != 0); ++j)
3222*5a6e8488SAndroid Build Coastguard Worker {
3223*5a6e8488SAndroid Build Coastguard Worker // This condition is true if we are not at the last digit.
3224*5a6e8488SAndroid Build Coastguard Worker if (j != exp - 1)
3225*5a6e8488SAndroid Build Coastguard Worker {
3226*5a6e8488SAndroid Build Coastguard Worker dig = acc % base;
3227*5a6e8488SAndroid Build Coastguard Worker acc /= base;
3228*5a6e8488SAndroid Build Coastguard Worker }
3229*5a6e8488SAndroid Build Coastguard Worker else
3230*5a6e8488SAndroid Build Coastguard Worker {
3231*5a6e8488SAndroid Build Coastguard Worker dig = acc;
3232*5a6e8488SAndroid Build Coastguard Worker acc = 0;
3233*5a6e8488SAndroid Build Coastguard Worker }
3234*5a6e8488SAndroid Build Coastguard Worker
3235*5a6e8488SAndroid Build Coastguard Worker assert(dig < base);
3236*5a6e8488SAndroid Build Coastguard Worker
3237*5a6e8488SAndroid Build Coastguard Worker // Push the digit onto the stack.
3238*5a6e8488SAndroid Build Coastguard Worker bc_vec_push(&stack, &dig);
3239*5a6e8488SAndroid Build Coastguard Worker }
3240*5a6e8488SAndroid Build Coastguard Worker
3241*5a6e8488SAndroid Build Coastguard Worker assert(acc == 0);
3242*5a6e8488SAndroid Build Coastguard Worker }
3243*5a6e8488SAndroid Build Coastguard Worker
3244*5a6e8488SAndroid Build Coastguard Worker // Go through the stack backwards and print each digit.
3245*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < stack.len; ++i)
3246*5a6e8488SAndroid Build Coastguard Worker {
3247*5a6e8488SAndroid Build Coastguard Worker ptr = bc_vec_item_rev(&stack, i);
3248*5a6e8488SAndroid Build Coastguard Worker
3249*5a6e8488SAndroid Build Coastguard Worker assert(ptr != NULL);
3250*5a6e8488SAndroid Build Coastguard Worker
3251*5a6e8488SAndroid Build Coastguard Worker // While the first three arguments should be self-explanatory, the last
3252*5a6e8488SAndroid Build Coastguard Worker // needs explaining. I don't want to print a backslash+newline when the
3253*5a6e8488SAndroid Build Coastguard Worker // last digit to be printed could take the place of the backslash rather
3254*5a6e8488SAndroid Build Coastguard Worker // than being pushed, as a single character, to the next line. That's
3255*5a6e8488SAndroid Build Coastguard Worker // what that last argument does for bc.
3256*5a6e8488SAndroid Build Coastguard Worker //
3257*5a6e8488SAndroid Build Coastguard Worker // First, it needs to check if newlines are completely disabled. If they
3258*5a6e8488SAndroid Build Coastguard Worker // are not disabled, it needs to check the next part.
3259*5a6e8488SAndroid Build Coastguard Worker //
3260*5a6e8488SAndroid Build Coastguard Worker // If the number has a scale, then because we are printing just the
3261*5a6e8488SAndroid Build Coastguard Worker // integer part, there will be at least two more characters (a radix
3262*5a6e8488SAndroid Build Coastguard Worker // point plus at least one digit). So if there is a scale, a backslash
3263*5a6e8488SAndroid Build Coastguard Worker // is necessary.
3264*5a6e8488SAndroid Build Coastguard Worker //
3265*5a6e8488SAndroid Build Coastguard Worker // Finally, the last condition checks to see if we are at the end of the
3266*5a6e8488SAndroid Build Coastguard Worker // stack. If we are *not* (i.e., the index is not one less than the
3267*5a6e8488SAndroid Build Coastguard Worker // stack length), then a backslash is necessary because there is at
3268*5a6e8488SAndroid Build Coastguard Worker // least one more character for at least one more digit). Otherwise, if
3269*5a6e8488SAndroid Build Coastguard Worker // the index is equal to one less than the stack length, we want to
3270*5a6e8488SAndroid Build Coastguard Worker // disable backslash printing.
3271*5a6e8488SAndroid Build Coastguard Worker //
3272*5a6e8488SAndroid Build Coastguard Worker // The function that prints bases 17 and above will take care of not
3273*5a6e8488SAndroid Build Coastguard Worker // printing a backslash in the right case.
3274*5a6e8488SAndroid Build Coastguard Worker print(*ptr, len, false,
3275*5a6e8488SAndroid Build Coastguard Worker !newline || (n->scale != 0 || i < stack.len - 1));
3276*5a6e8488SAndroid Build Coastguard Worker }
3277*5a6e8488SAndroid Build Coastguard Worker
3278*5a6e8488SAndroid Build Coastguard Worker // We are done if there is no fractional part.
3279*5a6e8488SAndroid Build Coastguard Worker if (!n->scale) goto err;
3280*5a6e8488SAndroid Build Coastguard Worker
3281*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
3282*5a6e8488SAndroid Build Coastguard Worker
3283*5a6e8488SAndroid Build Coastguard Worker // Reset the jump because some locals are changing.
3284*5a6e8488SAndroid Build Coastguard Worker BC_UNSETJMP(vm);
3285*5a6e8488SAndroid Build Coastguard Worker
3286*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&fracp2, nrdx);
3287*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&digit, digit_digs, sizeof(digit_digs) / sizeof(BcDig));
3288*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&flen1, BC_NUM_BIGDIG_LOG10);
3289*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&flen2, BC_NUM_BIGDIG_LOG10);
3290*5a6e8488SAndroid Build Coastguard Worker
3291*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, frac_err);
3292*5a6e8488SAndroid Build Coastguard Worker
3293*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
3294*5a6e8488SAndroid Build Coastguard Worker
3295*5a6e8488SAndroid Build Coastguard Worker bc_num_one(&flen1);
3296*5a6e8488SAndroid Build Coastguard Worker
3297*5a6e8488SAndroid Build Coastguard Worker radix = true;
3298*5a6e8488SAndroid Build Coastguard Worker
3299*5a6e8488SAndroid Build Coastguard Worker // Pointers for easy switching.
3300*5a6e8488SAndroid Build Coastguard Worker n1 = &flen1;
3301*5a6e8488SAndroid Build Coastguard Worker n2 = &flen2;
3302*5a6e8488SAndroid Build Coastguard Worker
3303*5a6e8488SAndroid Build Coastguard Worker fracp2.scale = n->scale;
3304*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET_NP(fracp2, BC_NUM_RDX(fracp2.scale));
3305*5a6e8488SAndroid Build Coastguard Worker
3306*5a6e8488SAndroid Build Coastguard Worker // As long as we have not reached the scale of the number, keep printing.
3307*5a6e8488SAndroid Build Coastguard Worker while ((idigits = bc_num_intDigits(n1)) <= n->scale)
3308*5a6e8488SAndroid Build Coastguard Worker {
3309*5a6e8488SAndroid Build Coastguard Worker // These numbers will keep growing.
3310*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(&fracp2, fracp1.len + 1);
3311*5a6e8488SAndroid Build Coastguard Worker bc_num_mulArray(&fracp1, base, &fracp2);
3312*5a6e8488SAndroid Build Coastguard Worker
3313*5a6e8488SAndroid Build Coastguard Worker nrdx = BC_NUM_RDX_VAL_NP(fracp2);
3314*5a6e8488SAndroid Build Coastguard Worker
3315*5a6e8488SAndroid Build Coastguard Worker // Ensure an invariant.
3316*5a6e8488SAndroid Build Coastguard Worker if (fracp2.len < nrdx) fracp2.len = nrdx;
3317*5a6e8488SAndroid Build Coastguard Worker
3318*5a6e8488SAndroid Build Coastguard Worker // fracp is guaranteed to be non-negative and small enough.
3319*5a6e8488SAndroid Build Coastguard Worker dig = bc_num_bigdig2(&fracp2);
3320*5a6e8488SAndroid Build Coastguard Worker
3321*5a6e8488SAndroid Build Coastguard Worker // Convert the digit to a number and subtract it from the number.
3322*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&digit, dig);
3323*5a6e8488SAndroid Build Coastguard Worker bc_num_sub(&fracp2, &digit, &fracp1, 0);
3324*5a6e8488SAndroid Build Coastguard Worker
3325*5a6e8488SAndroid Build Coastguard Worker // While the first three arguments should be self-explanatory, the last
3326*5a6e8488SAndroid Build Coastguard Worker // needs explaining. I don't want to print a newline when the last digit
3327*5a6e8488SAndroid Build Coastguard Worker // to be printed could take the place of the backslash rather than being
3328*5a6e8488SAndroid Build Coastguard Worker // pushed, as a single character, to the next line. That's what that
3329*5a6e8488SAndroid Build Coastguard Worker // last argument does for bc.
3330*5a6e8488SAndroid Build Coastguard Worker print(dig, len, radix, !newline || idigits != n->scale);
3331*5a6e8488SAndroid Build Coastguard Worker
3332*5a6e8488SAndroid Build Coastguard Worker // Update the multipliers.
3333*5a6e8488SAndroid Build Coastguard Worker bc_num_mulArray(n1, base, n2);
3334*5a6e8488SAndroid Build Coastguard Worker
3335*5a6e8488SAndroid Build Coastguard Worker radix = false;
3336*5a6e8488SAndroid Build Coastguard Worker
3337*5a6e8488SAndroid Build Coastguard Worker // Switch.
3338*5a6e8488SAndroid Build Coastguard Worker temp = n1;
3339*5a6e8488SAndroid Build Coastguard Worker n1 = n2;
3340*5a6e8488SAndroid Build Coastguard Worker n2 = temp;
3341*5a6e8488SAndroid Build Coastguard Worker }
3342*5a6e8488SAndroid Build Coastguard Worker
3343*5a6e8488SAndroid Build Coastguard Worker frac_err:
3344*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
3345*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&flen2);
3346*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&flen1);
3347*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&fracp2);
3348*5a6e8488SAndroid Build Coastguard Worker err:
3349*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
3350*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&fracp1);
3351*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&intp);
3352*5a6e8488SAndroid Build Coastguard Worker bc_vec_free(&stack);
3353*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
3354*5a6e8488SAndroid Build Coastguard Worker }
3355*5a6e8488SAndroid Build Coastguard Worker
3356*5a6e8488SAndroid Build Coastguard Worker /**
3357*5a6e8488SAndroid Build Coastguard Worker * Prints a number in the specified base, or rather, figures out which function
3358*5a6e8488SAndroid Build Coastguard Worker * to call to print the number in the specified base and calls it.
3359*5a6e8488SAndroid Build Coastguard Worker * @param n The number to print.
3360*5a6e8488SAndroid Build Coastguard Worker * @param base The base to print in.
3361*5a6e8488SAndroid Build Coastguard Worker * @param newline Whether to print backslash+newlines on long enough lines.
3362*5a6e8488SAndroid Build Coastguard Worker */
3363*5a6e8488SAndroid Build Coastguard Worker static void
bc_num_printBase(BcNum * restrict n,BcBigDig base,bool newline)3364*5a6e8488SAndroid Build Coastguard Worker bc_num_printBase(BcNum* restrict n, BcBigDig base, bool newline)
3365*5a6e8488SAndroid Build Coastguard Worker {
3366*5a6e8488SAndroid Build Coastguard Worker size_t width;
3367*5a6e8488SAndroid Build Coastguard Worker BcNumDigitOp print;
3368*5a6e8488SAndroid Build Coastguard Worker bool neg = BC_NUM_NEG(n);
3369*5a6e8488SAndroid Build Coastguard Worker
3370*5a6e8488SAndroid Build Coastguard Worker // Clear the sign because it makes the actual printing easier when we have
3371*5a6e8488SAndroid Build Coastguard Worker // to do math.
3372*5a6e8488SAndroid Build Coastguard Worker BC_NUM_NEG_CLR(n);
3373*5a6e8488SAndroid Build Coastguard Worker
3374*5a6e8488SAndroid Build Coastguard Worker // Bases at hexadecimal and below are printed as one character, larger bases
3375*5a6e8488SAndroid Build Coastguard Worker // are printed as a series of digits separated by spaces.
3376*5a6e8488SAndroid Build Coastguard Worker if (base <= BC_NUM_MAX_POSIX_IBASE)
3377*5a6e8488SAndroid Build Coastguard Worker {
3378*5a6e8488SAndroid Build Coastguard Worker width = 1;
3379*5a6e8488SAndroid Build Coastguard Worker print = bc_num_printHex;
3380*5a6e8488SAndroid Build Coastguard Worker }
3381*5a6e8488SAndroid Build Coastguard Worker else
3382*5a6e8488SAndroid Build Coastguard Worker {
3383*5a6e8488SAndroid Build Coastguard Worker assert(base <= BC_BASE_POW);
3384*5a6e8488SAndroid Build Coastguard Worker width = bc_num_log10(base - 1);
3385*5a6e8488SAndroid Build Coastguard Worker print = bc_num_printDigits;
3386*5a6e8488SAndroid Build Coastguard Worker }
3387*5a6e8488SAndroid Build Coastguard Worker
3388*5a6e8488SAndroid Build Coastguard Worker // Print.
3389*5a6e8488SAndroid Build Coastguard Worker bc_num_printNum(n, base, width, print, newline);
3390*5a6e8488SAndroid Build Coastguard Worker
3391*5a6e8488SAndroid Build Coastguard Worker // Reset the sign.
3392*5a6e8488SAndroid Build Coastguard Worker n->rdx = BC_NUM_NEG_VAL(n, neg);
3393*5a6e8488SAndroid Build Coastguard Worker }
3394*5a6e8488SAndroid Build Coastguard Worker
3395*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
3396*5a6e8488SAndroid Build Coastguard Worker
3397*5a6e8488SAndroid Build Coastguard Worker void
bc_num_stream(BcNum * restrict n)3398*5a6e8488SAndroid Build Coastguard Worker bc_num_stream(BcNum* restrict n)
3399*5a6e8488SAndroid Build Coastguard Worker {
3400*5a6e8488SAndroid Build Coastguard Worker bc_num_printNum(n, BC_NUM_STREAM_BASE, 1, bc_num_printChar, false);
3401*5a6e8488SAndroid Build Coastguard Worker }
3402*5a6e8488SAndroid Build Coastguard Worker
3403*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
3404*5a6e8488SAndroid Build Coastguard Worker
3405*5a6e8488SAndroid Build Coastguard Worker void
bc_num_setup(BcNum * restrict n,BcDig * restrict num,size_t cap)3406*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(BcNum* restrict n, BcDig* restrict num, size_t cap)
3407*5a6e8488SAndroid Build Coastguard Worker {
3408*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
3409*5a6e8488SAndroid Build Coastguard Worker n->num = num;
3410*5a6e8488SAndroid Build Coastguard Worker n->cap = cap;
3411*5a6e8488SAndroid Build Coastguard Worker bc_num_zero(n);
3412*5a6e8488SAndroid Build Coastguard Worker }
3413*5a6e8488SAndroid Build Coastguard Worker
3414*5a6e8488SAndroid Build Coastguard Worker void
bc_num_init(BcNum * restrict n,size_t req)3415*5a6e8488SAndroid Build Coastguard Worker bc_num_init(BcNum* restrict n, size_t req)
3416*5a6e8488SAndroid Build Coastguard Worker {
3417*5a6e8488SAndroid Build Coastguard Worker BcDig* num;
3418*5a6e8488SAndroid Build Coastguard Worker
3419*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
3420*5a6e8488SAndroid Build Coastguard Worker
3421*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
3422*5a6e8488SAndroid Build Coastguard Worker
3423*5a6e8488SAndroid Build Coastguard Worker // BC_NUM_DEF_SIZE is set to be about the smallest allocation size that
3424*5a6e8488SAndroid Build Coastguard Worker // malloc() returns in practice, so just use it.
3425*5a6e8488SAndroid Build Coastguard Worker req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
3426*5a6e8488SAndroid Build Coastguard Worker
3427*5a6e8488SAndroid Build Coastguard Worker // If we can't use a temp, allocate.
3428*5a6e8488SAndroid Build Coastguard Worker if (req != BC_NUM_DEF_SIZE) num = bc_vm_malloc(BC_NUM_SIZE(req));
3429*5a6e8488SAndroid Build Coastguard Worker else
3430*5a6e8488SAndroid Build Coastguard Worker {
3431*5a6e8488SAndroid Build Coastguard Worker num = bc_vm_getTemp() == NULL ? bc_vm_malloc(BC_NUM_SIZE(req)) :
3432*5a6e8488SAndroid Build Coastguard Worker bc_vm_takeTemp();
3433*5a6e8488SAndroid Build Coastguard Worker }
3434*5a6e8488SAndroid Build Coastguard Worker
3435*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(n, num, req);
3436*5a6e8488SAndroid Build Coastguard Worker }
3437*5a6e8488SAndroid Build Coastguard Worker
3438*5a6e8488SAndroid Build Coastguard Worker void
bc_num_clear(BcNum * restrict n)3439*5a6e8488SAndroid Build Coastguard Worker bc_num_clear(BcNum* restrict n)
3440*5a6e8488SAndroid Build Coastguard Worker {
3441*5a6e8488SAndroid Build Coastguard Worker n->num = NULL;
3442*5a6e8488SAndroid Build Coastguard Worker n->cap = 0;
3443*5a6e8488SAndroid Build Coastguard Worker }
3444*5a6e8488SAndroid Build Coastguard Worker
3445*5a6e8488SAndroid Build Coastguard Worker void
bc_num_free(void * num)3446*5a6e8488SAndroid Build Coastguard Worker bc_num_free(void* num)
3447*5a6e8488SAndroid Build Coastguard Worker {
3448*5a6e8488SAndroid Build Coastguard Worker BcNum* n = (BcNum*) num;
3449*5a6e8488SAndroid Build Coastguard Worker
3450*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
3451*5a6e8488SAndroid Build Coastguard Worker
3452*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
3453*5a6e8488SAndroid Build Coastguard Worker
3454*5a6e8488SAndroid Build Coastguard Worker if (n->cap == BC_NUM_DEF_SIZE) bc_vm_addTemp(n->num);
3455*5a6e8488SAndroid Build Coastguard Worker else free(n->num);
3456*5a6e8488SAndroid Build Coastguard Worker }
3457*5a6e8488SAndroid Build Coastguard Worker
3458*5a6e8488SAndroid Build Coastguard Worker void
bc_num_copy(BcNum * d,const BcNum * s)3459*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(BcNum* d, const BcNum* s)
3460*5a6e8488SAndroid Build Coastguard Worker {
3461*5a6e8488SAndroid Build Coastguard Worker assert(d != NULL && s != NULL);
3462*5a6e8488SAndroid Build Coastguard Worker
3463*5a6e8488SAndroid Build Coastguard Worker if (d == s) return;
3464*5a6e8488SAndroid Build Coastguard Worker
3465*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(d, s->len);
3466*5a6e8488SAndroid Build Coastguard Worker d->len = s->len;
3467*5a6e8488SAndroid Build Coastguard Worker
3468*5a6e8488SAndroid Build Coastguard Worker // I can just copy directly here because the sign *and* rdx will be
3469*5a6e8488SAndroid Build Coastguard Worker // properly preserved.
3470*5a6e8488SAndroid Build Coastguard Worker d->rdx = s->rdx;
3471*5a6e8488SAndroid Build Coastguard Worker d->scale = s->scale;
3472*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
3473*5a6e8488SAndroid Build Coastguard Worker memcpy(d->num, s->num, BC_NUM_SIZE(d->len));
3474*5a6e8488SAndroid Build Coastguard Worker }
3475*5a6e8488SAndroid Build Coastguard Worker
3476*5a6e8488SAndroid Build Coastguard Worker void
bc_num_createCopy(BcNum * d,const BcNum * s)3477*5a6e8488SAndroid Build Coastguard Worker bc_num_createCopy(BcNum* d, const BcNum* s)
3478*5a6e8488SAndroid Build Coastguard Worker {
3479*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
3480*5a6e8488SAndroid Build Coastguard Worker bc_num_init(d, s->len);
3481*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(d, s);
3482*5a6e8488SAndroid Build Coastguard Worker }
3483*5a6e8488SAndroid Build Coastguard Worker
3484*5a6e8488SAndroid Build Coastguard Worker void
bc_num_createFromBigdig(BcNum * restrict n,BcBigDig val)3485*5a6e8488SAndroid Build Coastguard Worker bc_num_createFromBigdig(BcNum* restrict n, BcBigDig val)
3486*5a6e8488SAndroid Build Coastguard Worker {
3487*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
3488*5a6e8488SAndroid Build Coastguard Worker bc_num_init(n, BC_NUM_BIGDIG_LOG10);
3489*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(n, val);
3490*5a6e8488SAndroid Build Coastguard Worker }
3491*5a6e8488SAndroid Build Coastguard Worker
3492*5a6e8488SAndroid Build Coastguard Worker size_t
bc_num_scale(const BcNum * restrict n)3493*5a6e8488SAndroid Build Coastguard Worker bc_num_scale(const BcNum* restrict n)
3494*5a6e8488SAndroid Build Coastguard Worker {
3495*5a6e8488SAndroid Build Coastguard Worker return n->scale;
3496*5a6e8488SAndroid Build Coastguard Worker }
3497*5a6e8488SAndroid Build Coastguard Worker
3498*5a6e8488SAndroid Build Coastguard Worker size_t
bc_num_len(const BcNum * restrict n)3499*5a6e8488SAndroid Build Coastguard Worker bc_num_len(const BcNum* restrict n)
3500*5a6e8488SAndroid Build Coastguard Worker {
3501*5a6e8488SAndroid Build Coastguard Worker size_t len = n->len;
3502*5a6e8488SAndroid Build Coastguard Worker
3503*5a6e8488SAndroid Build Coastguard Worker // Always return at least 1.
3504*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(n)) return n->scale ? n->scale : 1;
3505*5a6e8488SAndroid Build Coastguard Worker
3506*5a6e8488SAndroid Build Coastguard Worker // If this is true, there is no integer portion of the number.
3507*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_RDX_VAL(n) == len)
3508*5a6e8488SAndroid Build Coastguard Worker {
3509*5a6e8488SAndroid Build Coastguard Worker // We have to take into account the fact that some of the digits right
3510*5a6e8488SAndroid Build Coastguard Worker // after the decimal could be zero. If that is the case, we need to
3511*5a6e8488SAndroid Build Coastguard Worker // ignore them until we hit the first non-zero digit.
3512*5a6e8488SAndroid Build Coastguard Worker
3513*5a6e8488SAndroid Build Coastguard Worker size_t zero, scale;
3514*5a6e8488SAndroid Build Coastguard Worker
3515*5a6e8488SAndroid Build Coastguard Worker // The number of limbs with non-zero digits.
3516*5a6e8488SAndroid Build Coastguard Worker len = bc_num_nonZeroLen(n);
3517*5a6e8488SAndroid Build Coastguard Worker
3518*5a6e8488SAndroid Build Coastguard Worker // Get the number of digits in the last limb.
3519*5a6e8488SAndroid Build Coastguard Worker scale = n->scale % BC_BASE_DIGS;
3520*5a6e8488SAndroid Build Coastguard Worker scale = scale ? scale : BC_BASE_DIGS;
3521*5a6e8488SAndroid Build Coastguard Worker
3522*5a6e8488SAndroid Build Coastguard Worker // Get the number of zero digits.
3523*5a6e8488SAndroid Build Coastguard Worker zero = bc_num_zeroDigits(n->num + len - 1);
3524*5a6e8488SAndroid Build Coastguard Worker
3525*5a6e8488SAndroid Build Coastguard Worker // Calculate the true length.
3526*5a6e8488SAndroid Build Coastguard Worker len = len * BC_BASE_DIGS - zero - (BC_BASE_DIGS - scale);
3527*5a6e8488SAndroid Build Coastguard Worker }
3528*5a6e8488SAndroid Build Coastguard Worker // Otherwise, count the number of int digits and return that plus the scale.
3529*5a6e8488SAndroid Build Coastguard Worker else len = bc_num_intDigits(n) + n->scale;
3530*5a6e8488SAndroid Build Coastguard Worker
3531*5a6e8488SAndroid Build Coastguard Worker return len;
3532*5a6e8488SAndroid Build Coastguard Worker }
3533*5a6e8488SAndroid Build Coastguard Worker
3534*5a6e8488SAndroid Build Coastguard Worker void
bc_num_parse(BcNum * restrict n,const char * restrict val,BcBigDig base)3535*5a6e8488SAndroid Build Coastguard Worker bc_num_parse(BcNum* restrict n, const char* restrict val, BcBigDig base)
3536*5a6e8488SAndroid Build Coastguard Worker {
3537*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG
3538*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
3539*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
3540*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
3541*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG
3542*5a6e8488SAndroid Build Coastguard Worker
3543*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL && val != NULL && base);
3544*5a6e8488SAndroid Build Coastguard Worker assert(base >= BC_NUM_MIN_BASE && base <= vm->maxes[BC_PROG_GLOBALS_IBASE]);
3545*5a6e8488SAndroid Build Coastguard Worker assert(bc_num_strValid(val));
3546*5a6e8488SAndroid Build Coastguard Worker
3547*5a6e8488SAndroid Build Coastguard Worker // A one character number is *always* parsed as though the base was the
3548*5a6e8488SAndroid Build Coastguard Worker // maximum allowed ibase, per the bc spec.
3549*5a6e8488SAndroid Build Coastguard Worker if (!val[1])
3550*5a6e8488SAndroid Build Coastguard Worker {
3551*5a6e8488SAndroid Build Coastguard Worker BcBigDig dig = bc_num_parseChar(val[0], BC_NUM_MAX_LBASE);
3552*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(n, dig);
3553*5a6e8488SAndroid Build Coastguard Worker }
3554*5a6e8488SAndroid Build Coastguard Worker else if (base == BC_BASE) bc_num_parseDecimal(n, val);
3555*5a6e8488SAndroid Build Coastguard Worker else bc_num_parseBase(n, val, base);
3556*5a6e8488SAndroid Build Coastguard Worker
3557*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(n));
3558*5a6e8488SAndroid Build Coastguard Worker }
3559*5a6e8488SAndroid Build Coastguard Worker
3560*5a6e8488SAndroid Build Coastguard Worker void
bc_num_print(BcNum * restrict n,BcBigDig base,bool newline)3561*5a6e8488SAndroid Build Coastguard Worker bc_num_print(BcNum* restrict n, BcBigDig base, bool newline)
3562*5a6e8488SAndroid Build Coastguard Worker {
3563*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
3564*5a6e8488SAndroid Build Coastguard Worker assert(BC_ENABLE_EXTRA_MATH || base >= BC_NUM_MIN_BASE);
3565*5a6e8488SAndroid Build Coastguard Worker
3566*5a6e8488SAndroid Build Coastguard Worker // We may need a newline, just to start.
3567*5a6e8488SAndroid Build Coastguard Worker bc_num_printNewline();
3568*5a6e8488SAndroid Build Coastguard Worker
3569*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(n))
3570*5a6e8488SAndroid Build Coastguard Worker {
3571*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
3572*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
3573*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
3574*5a6e8488SAndroid Build Coastguard Worker
3575*5a6e8488SAndroid Build Coastguard Worker // Print the sign.
3576*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NEG(n)) bc_num_putchar('-', true);
3577*5a6e8488SAndroid Build Coastguard Worker
3578*5a6e8488SAndroid Build Coastguard Worker // Print the leading zero if necessary. We don't print when using
3579*5a6e8488SAndroid Build Coastguard Worker // scientific or engineering modes.
3580*5a6e8488SAndroid Build Coastguard Worker if (BC_Z && BC_NUM_RDX_VAL(n) == n->len && base != 0 && base != 1)
3581*5a6e8488SAndroid Build Coastguard Worker {
3582*5a6e8488SAndroid Build Coastguard Worker bc_num_printHex(0, 1, false, !newline);
3583*5a6e8488SAndroid Build Coastguard Worker }
3584*5a6e8488SAndroid Build Coastguard Worker }
3585*5a6e8488SAndroid Build Coastguard Worker
3586*5a6e8488SAndroid Build Coastguard Worker // Short-circuit 0.
3587*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(n)) bc_num_printHex(0, 1, false, !newline);
3588*5a6e8488SAndroid Build Coastguard Worker else if (base == BC_BASE) bc_num_printDecimal(n, newline);
3589*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
3590*5a6e8488SAndroid Build Coastguard Worker else if (base == 0 || base == 1)
3591*5a6e8488SAndroid Build Coastguard Worker {
3592*5a6e8488SAndroid Build Coastguard Worker bc_num_printExponent(n, base != 0, newline);
3593*5a6e8488SAndroid Build Coastguard Worker }
3594*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
3595*5a6e8488SAndroid Build Coastguard Worker else bc_num_printBase(n, base, newline);
3596*5a6e8488SAndroid Build Coastguard Worker
3597*5a6e8488SAndroid Build Coastguard Worker if (newline) bc_num_putchar('\n', false);
3598*5a6e8488SAndroid Build Coastguard Worker }
3599*5a6e8488SAndroid Build Coastguard Worker
3600*5a6e8488SAndroid Build Coastguard Worker BcBigDig
bc_num_bigdig2(const BcNum * restrict n)3601*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2(const BcNum* restrict n)
3602*5a6e8488SAndroid Build Coastguard Worker {
3603*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG
3604*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
3605*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
3606*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
3607*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG
3608*5a6e8488SAndroid Build Coastguard Worker
3609*5a6e8488SAndroid Build Coastguard Worker // This function returns no errors because it's guaranteed to succeed if
3610*5a6e8488SAndroid Build Coastguard Worker // its preconditions are met. Those preconditions include both n needs to
3611*5a6e8488SAndroid Build Coastguard Worker // be non-NULL, n being non-negative, and n being less than vm->max. If all
3612*5a6e8488SAndroid Build Coastguard Worker // of that is true, then we can just convert without worrying about negative
3613*5a6e8488SAndroid Build Coastguard Worker // errors or overflow.
3614*5a6e8488SAndroid Build Coastguard Worker
3615*5a6e8488SAndroid Build Coastguard Worker BcBigDig r = 0;
3616*5a6e8488SAndroid Build Coastguard Worker size_t nrdx = BC_NUM_RDX_VAL(n);
3617*5a6e8488SAndroid Build Coastguard Worker
3618*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
3619*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_NEG(n));
3620*5a6e8488SAndroid Build Coastguard Worker assert(bc_num_cmp(n, &vm->max) < 0);
3621*5a6e8488SAndroid Build Coastguard Worker assert(n->len - nrdx <= 3);
3622*5a6e8488SAndroid Build Coastguard Worker
3623*5a6e8488SAndroid Build Coastguard Worker // There is a small speed win from unrolling the loop here, and since it
3624*5a6e8488SAndroid Build Coastguard Worker // only adds 53 bytes, I decided that it was worth it.
3625*5a6e8488SAndroid Build Coastguard Worker switch (n->len - nrdx)
3626*5a6e8488SAndroid Build Coastguard Worker {
3627*5a6e8488SAndroid Build Coastguard Worker case 3:
3628*5a6e8488SAndroid Build Coastguard Worker {
3629*5a6e8488SAndroid Build Coastguard Worker r = (BcBigDig) n->num[nrdx + 2];
3630*5a6e8488SAndroid Build Coastguard Worker
3631*5a6e8488SAndroid Build Coastguard Worker // Fallthrough.
3632*5a6e8488SAndroid Build Coastguard Worker BC_FALLTHROUGH
3633*5a6e8488SAndroid Build Coastguard Worker }
3634*5a6e8488SAndroid Build Coastguard Worker
3635*5a6e8488SAndroid Build Coastguard Worker case 2:
3636*5a6e8488SAndroid Build Coastguard Worker {
3637*5a6e8488SAndroid Build Coastguard Worker r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx + 1];
3638*5a6e8488SAndroid Build Coastguard Worker
3639*5a6e8488SAndroid Build Coastguard Worker // Fallthrough.
3640*5a6e8488SAndroid Build Coastguard Worker BC_FALLTHROUGH
3641*5a6e8488SAndroid Build Coastguard Worker }
3642*5a6e8488SAndroid Build Coastguard Worker
3643*5a6e8488SAndroid Build Coastguard Worker case 1:
3644*5a6e8488SAndroid Build Coastguard Worker {
3645*5a6e8488SAndroid Build Coastguard Worker r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx];
3646*5a6e8488SAndroid Build Coastguard Worker }
3647*5a6e8488SAndroid Build Coastguard Worker }
3648*5a6e8488SAndroid Build Coastguard Worker
3649*5a6e8488SAndroid Build Coastguard Worker return r;
3650*5a6e8488SAndroid Build Coastguard Worker }
3651*5a6e8488SAndroid Build Coastguard Worker
3652*5a6e8488SAndroid Build Coastguard Worker BcBigDig
bc_num_bigdig(const BcNum * restrict n)3653*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig(const BcNum* restrict n)
3654*5a6e8488SAndroid Build Coastguard Worker {
3655*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
3656*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
3657*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
3658*5a6e8488SAndroid Build Coastguard Worker
3659*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
3660*5a6e8488SAndroid Build Coastguard Worker
3661*5a6e8488SAndroid Build Coastguard Worker // This error checking is extremely important, and if you do not have a
3662*5a6e8488SAndroid Build Coastguard Worker // guarantee that converting a number will always succeed in a particular
3663*5a6e8488SAndroid Build Coastguard Worker // case, you *must* call this function to get these error checks. This
3664*5a6e8488SAndroid Build Coastguard Worker // includes all instances of numbers inputted by the user or calculated by
3665*5a6e8488SAndroid Build Coastguard Worker // the user. Otherwise, you can call the faster bc_num_bigdig2().
3666*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(BC_NUM_NEG(n))) bc_err(BC_ERR_MATH_NEGATIVE);
3667*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(bc_num_cmp(n, &vm->max) >= 0)) bc_err(BC_ERR_MATH_OVERFLOW);
3668*5a6e8488SAndroid Build Coastguard Worker
3669*5a6e8488SAndroid Build Coastguard Worker return bc_num_bigdig2(n);
3670*5a6e8488SAndroid Build Coastguard Worker }
3671*5a6e8488SAndroid Build Coastguard Worker
3672*5a6e8488SAndroid Build Coastguard Worker void
bc_num_bigdig2num(BcNum * restrict n,BcBigDig val)3673*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(BcNum* restrict n, BcBigDig val)
3674*5a6e8488SAndroid Build Coastguard Worker {
3675*5a6e8488SAndroid Build Coastguard Worker BcDig* ptr;
3676*5a6e8488SAndroid Build Coastguard Worker size_t i;
3677*5a6e8488SAndroid Build Coastguard Worker
3678*5a6e8488SAndroid Build Coastguard Worker assert(n != NULL);
3679*5a6e8488SAndroid Build Coastguard Worker
3680*5a6e8488SAndroid Build Coastguard Worker bc_num_zero(n);
3681*5a6e8488SAndroid Build Coastguard Worker
3682*5a6e8488SAndroid Build Coastguard Worker // Already 0.
3683*5a6e8488SAndroid Build Coastguard Worker if (!val) return;
3684*5a6e8488SAndroid Build Coastguard Worker
3685*5a6e8488SAndroid Build Coastguard Worker // Expand first. This is the only way this function can fail, and it's a
3686*5a6e8488SAndroid Build Coastguard Worker // fatal error.
3687*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(n, BC_NUM_BIGDIG_LOG10);
3688*5a6e8488SAndroid Build Coastguard Worker
3689*5a6e8488SAndroid Build Coastguard Worker // The conversion is easy because numbers are laid out in little-endian
3690*5a6e8488SAndroid Build Coastguard Worker // order.
3691*5a6e8488SAndroid Build Coastguard Worker for (ptr = n->num, i = 0; val; ++i, val /= BC_BASE_POW)
3692*5a6e8488SAndroid Build Coastguard Worker {
3693*5a6e8488SAndroid Build Coastguard Worker ptr[i] = val % BC_BASE_POW;
3694*5a6e8488SAndroid Build Coastguard Worker }
3695*5a6e8488SAndroid Build Coastguard Worker
3696*5a6e8488SAndroid Build Coastguard Worker n->len = i;
3697*5a6e8488SAndroid Build Coastguard Worker }
3698*5a6e8488SAndroid Build Coastguard Worker
3699*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
3700*5a6e8488SAndroid Build Coastguard Worker
3701*5a6e8488SAndroid Build Coastguard Worker void
bc_num_rng(const BcNum * restrict n,BcRNG * rng)3702*5a6e8488SAndroid Build Coastguard Worker bc_num_rng(const BcNum* restrict n, BcRNG* rng)
3703*5a6e8488SAndroid Build Coastguard Worker {
3704*5a6e8488SAndroid Build Coastguard Worker BcNum temp, temp2, intn, frac;
3705*5a6e8488SAndroid Build Coastguard Worker BcRand state1, state2, inc1, inc2;
3706*5a6e8488SAndroid Build Coastguard Worker size_t nrdx = BC_NUM_RDX_VAL(n);
3707*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
3708*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
3709*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
3710*5a6e8488SAndroid Build Coastguard Worker
3711*5a6e8488SAndroid Build Coastguard Worker // This function holds the secret of how I interpret a seed number for the
3712*5a6e8488SAndroid Build Coastguard Worker // PRNG. Well, it's actually in the development manual
3713*5a6e8488SAndroid Build Coastguard Worker // (manuals/development.md#pseudo-random-number-generator), so look there
3714*5a6e8488SAndroid Build Coastguard Worker // before you try to understand this.
3715*5a6e8488SAndroid Build Coastguard Worker
3716*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
3717*5a6e8488SAndroid Build Coastguard Worker
3718*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&temp, n->len);
3719*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&temp2, n->len);
3720*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&frac, nrdx);
3721*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&intn, bc_num_int(n));
3722*5a6e8488SAndroid Build Coastguard Worker
3723*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
3724*5a6e8488SAndroid Build Coastguard Worker
3725*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
3726*5a6e8488SAndroid Build Coastguard Worker
3727*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(vm->max));
3728*5a6e8488SAndroid Build Coastguard Worker
3729*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
3730*5a6e8488SAndroid Build Coastguard Worker memcpy(frac.num, n->num, BC_NUM_SIZE(nrdx));
3731*5a6e8488SAndroid Build Coastguard Worker frac.len = nrdx;
3732*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET_NP(frac, nrdx);
3733*5a6e8488SAndroid Build Coastguard Worker frac.scale = n->scale;
3734*5a6e8488SAndroid Build Coastguard Worker
3735*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(frac));
3736*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(vm->max2));
3737*5a6e8488SAndroid Build Coastguard Worker
3738*5a6e8488SAndroid Build Coastguard Worker // Multiply the fraction and truncate so that it's an integer. The
3739*5a6e8488SAndroid Build Coastguard Worker // truncation is what clamps it, by the way.
3740*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(&frac, &vm->max2, &temp, 0);
3741*5a6e8488SAndroid Build Coastguard Worker bc_num_truncate(&temp, temp.scale);
3742*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(&frac, &temp);
3743*5a6e8488SAndroid Build Coastguard Worker
3744*5a6e8488SAndroid Build Coastguard Worker // Get the integer.
3745*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
3746*5a6e8488SAndroid Build Coastguard Worker memcpy(intn.num, n->num + nrdx, BC_NUM_SIZE(bc_num_int(n)));
3747*5a6e8488SAndroid Build Coastguard Worker intn.len = bc_num_int(n);
3748*5a6e8488SAndroid Build Coastguard Worker
3749*5a6e8488SAndroid Build Coastguard Worker // This assert is here because it has to be true. It is also here to justify
3750*5a6e8488SAndroid Build Coastguard Worker // some optimizations.
3751*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_NONZERO(&vm->max));
3752*5a6e8488SAndroid Build Coastguard Worker
3753*5a6e8488SAndroid Build Coastguard Worker // If there *was* a fractional part...
3754*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(&frac))
3755*5a6e8488SAndroid Build Coastguard Worker {
3756*5a6e8488SAndroid Build Coastguard Worker // This divmod splits frac into the two state parts.
3757*5a6e8488SAndroid Build Coastguard Worker bc_num_divmod(&frac, &vm->max, &temp, &temp2, 0);
3758*5a6e8488SAndroid Build Coastguard Worker
3759*5a6e8488SAndroid Build Coastguard Worker // frac is guaranteed to be smaller than vm->max * vm->max (pow).
3760*5a6e8488SAndroid Build Coastguard Worker // This means that when dividing frac by vm->max, as above, the
3761*5a6e8488SAndroid Build Coastguard Worker // quotient and remainder are both guaranteed to be less than vm->max,
3762*5a6e8488SAndroid Build Coastguard Worker // which means we can use bc_num_bigdig2() here and not worry about
3763*5a6e8488SAndroid Build Coastguard Worker // overflow.
3764*5a6e8488SAndroid Build Coastguard Worker state1 = (BcRand) bc_num_bigdig2(&temp2);
3765*5a6e8488SAndroid Build Coastguard Worker state2 = (BcRand) bc_num_bigdig2(&temp);
3766*5a6e8488SAndroid Build Coastguard Worker }
3767*5a6e8488SAndroid Build Coastguard Worker else state1 = state2 = 0;
3768*5a6e8488SAndroid Build Coastguard Worker
3769*5a6e8488SAndroid Build Coastguard Worker // If there *was* an integer part...
3770*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(&intn))
3771*5a6e8488SAndroid Build Coastguard Worker {
3772*5a6e8488SAndroid Build Coastguard Worker // This divmod splits intn into the two inc parts.
3773*5a6e8488SAndroid Build Coastguard Worker bc_num_divmod(&intn, &vm->max, &temp, &temp2, 0);
3774*5a6e8488SAndroid Build Coastguard Worker
3775*5a6e8488SAndroid Build Coastguard Worker // Because temp2 is the mod of vm->max, from above, it is guaranteed
3776*5a6e8488SAndroid Build Coastguard Worker // to be small enough to use bc_num_bigdig2().
3777*5a6e8488SAndroid Build Coastguard Worker inc1 = (BcRand) bc_num_bigdig2(&temp2);
3778*5a6e8488SAndroid Build Coastguard Worker
3779*5a6e8488SAndroid Build Coastguard Worker // Clamp the second inc part.
3780*5a6e8488SAndroid Build Coastguard Worker if (bc_num_cmp(&temp, &vm->max) >= 0)
3781*5a6e8488SAndroid Build Coastguard Worker {
3782*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(&temp2, &temp);
3783*5a6e8488SAndroid Build Coastguard Worker bc_num_mod(&temp2, &vm->max, &temp, 0);
3784*5a6e8488SAndroid Build Coastguard Worker }
3785*5a6e8488SAndroid Build Coastguard Worker
3786*5a6e8488SAndroid Build Coastguard Worker // The if statement above ensures that temp is less than vm->max, which
3787*5a6e8488SAndroid Build Coastguard Worker // means that we can use bc_num_bigdig2() here.
3788*5a6e8488SAndroid Build Coastguard Worker inc2 = (BcRand) bc_num_bigdig2(&temp);
3789*5a6e8488SAndroid Build Coastguard Worker }
3790*5a6e8488SAndroid Build Coastguard Worker else inc1 = inc2 = 0;
3791*5a6e8488SAndroid Build Coastguard Worker
3792*5a6e8488SAndroid Build Coastguard Worker bc_rand_seed(rng, state1, state2, inc1, inc2);
3793*5a6e8488SAndroid Build Coastguard Worker
3794*5a6e8488SAndroid Build Coastguard Worker err:
3795*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
3796*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&intn);
3797*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&frac);
3798*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&temp2);
3799*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&temp);
3800*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
3801*5a6e8488SAndroid Build Coastguard Worker }
3802*5a6e8488SAndroid Build Coastguard Worker
3803*5a6e8488SAndroid Build Coastguard Worker void
bc_num_createFromRNG(BcNum * restrict n,BcRNG * rng)3804*5a6e8488SAndroid Build Coastguard Worker bc_num_createFromRNG(BcNum* restrict n, BcRNG* rng)
3805*5a6e8488SAndroid Build Coastguard Worker {
3806*5a6e8488SAndroid Build Coastguard Worker BcRand s1, s2, i1, i2;
3807*5a6e8488SAndroid Build Coastguard Worker BcNum conv, temp1, temp2, temp3;
3808*5a6e8488SAndroid Build Coastguard Worker BcDig temp1_num[BC_RAND_NUM_SIZE], temp2_num[BC_RAND_NUM_SIZE];
3809*5a6e8488SAndroid Build Coastguard Worker BcDig conv_num[BC_NUM_BIGDIG_LOG10];
3810*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
3811*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
3812*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
3813*5a6e8488SAndroid Build Coastguard Worker
3814*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
3815*5a6e8488SAndroid Build Coastguard Worker
3816*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&temp3, 2 * BC_RAND_NUM_SIZE);
3817*5a6e8488SAndroid Build Coastguard Worker
3818*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
3819*5a6e8488SAndroid Build Coastguard Worker
3820*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
3821*5a6e8488SAndroid Build Coastguard Worker
3822*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&temp1, temp1_num, sizeof(temp1_num) / sizeof(BcDig));
3823*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&temp2, temp2_num, sizeof(temp2_num) / sizeof(BcDig));
3824*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&conv, conv_num, sizeof(conv_num) / sizeof(BcDig));
3825*5a6e8488SAndroid Build Coastguard Worker
3826*5a6e8488SAndroid Build Coastguard Worker // This assert is here because it has to be true. It is also here to justify
3827*5a6e8488SAndroid Build Coastguard Worker // the assumption that vm->max is not zero.
3828*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_NONZERO(&vm->max));
3829*5a6e8488SAndroid Build Coastguard Worker
3830*5a6e8488SAndroid Build Coastguard Worker // Because this is true, we can just ignore math errors that would happen
3831*5a6e8488SAndroid Build Coastguard Worker // otherwise.
3832*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_NONZERO(&vm->max2));
3833*5a6e8488SAndroid Build Coastguard Worker
3834*5a6e8488SAndroid Build Coastguard Worker bc_rand_getRands(rng, &s1, &s2, &i1, &i2);
3835*5a6e8488SAndroid Build Coastguard Worker
3836*5a6e8488SAndroid Build Coastguard Worker // Put the second piece of state into a number.
3837*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&conv, (BcBigDig) s2);
3838*5a6e8488SAndroid Build Coastguard Worker
3839*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(conv));
3840*5a6e8488SAndroid Build Coastguard Worker
3841*5a6e8488SAndroid Build Coastguard Worker // Multiply by max to make room for the first piece of state.
3842*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(&conv, &vm->max, &temp1, 0);
3843*5a6e8488SAndroid Build Coastguard Worker
3844*5a6e8488SAndroid Build Coastguard Worker // Add in the first piece of state.
3845*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&conv, (BcBigDig) s1);
3846*5a6e8488SAndroid Build Coastguard Worker bc_num_add(&conv, &temp1, &temp2, 0);
3847*5a6e8488SAndroid Build Coastguard Worker
3848*5a6e8488SAndroid Build Coastguard Worker // Divide to make it an entirely fractional part.
3849*5a6e8488SAndroid Build Coastguard Worker bc_num_div(&temp2, &vm->max2, &temp3, BC_RAND_STATE_BITS);
3850*5a6e8488SAndroid Build Coastguard Worker
3851*5a6e8488SAndroid Build Coastguard Worker // Now start on the increment parts. It's the same process without the
3852*5a6e8488SAndroid Build Coastguard Worker // divide, so put the second piece of increment into a number.
3853*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&conv, (BcBigDig) i2);
3854*5a6e8488SAndroid Build Coastguard Worker
3855*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(conv));
3856*5a6e8488SAndroid Build Coastguard Worker
3857*5a6e8488SAndroid Build Coastguard Worker // Multiply by max to make room for the first piece of increment.
3858*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(&conv, &vm->max, &temp1, 0);
3859*5a6e8488SAndroid Build Coastguard Worker
3860*5a6e8488SAndroid Build Coastguard Worker // Add in the first piece of increment.
3861*5a6e8488SAndroid Build Coastguard Worker bc_num_bigdig2num(&conv, (BcBigDig) i1);
3862*5a6e8488SAndroid Build Coastguard Worker bc_num_add(&conv, &temp1, &temp2, 0);
3863*5a6e8488SAndroid Build Coastguard Worker
3864*5a6e8488SAndroid Build Coastguard Worker // Now add the two together.
3865*5a6e8488SAndroid Build Coastguard Worker bc_num_add(&temp2, &temp3, n, 0);
3866*5a6e8488SAndroid Build Coastguard Worker
3867*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(n));
3868*5a6e8488SAndroid Build Coastguard Worker
3869*5a6e8488SAndroid Build Coastguard Worker err:
3870*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
3871*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&temp3);
3872*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
3873*5a6e8488SAndroid Build Coastguard Worker }
3874*5a6e8488SAndroid Build Coastguard Worker
3875*5a6e8488SAndroid Build Coastguard Worker void
bc_num_irand(BcNum * restrict a,BcNum * restrict b,BcRNG * restrict rng)3876*5a6e8488SAndroid Build Coastguard Worker bc_num_irand(BcNum* restrict a, BcNum* restrict b, BcRNG* restrict rng)
3877*5a6e8488SAndroid Build Coastguard Worker {
3878*5a6e8488SAndroid Build Coastguard Worker BcNum atemp;
3879*5a6e8488SAndroid Build Coastguard Worker size_t i;
3880*5a6e8488SAndroid Build Coastguard Worker
3881*5a6e8488SAndroid Build Coastguard Worker assert(a != b);
3882*5a6e8488SAndroid Build Coastguard Worker
3883*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(BC_NUM_NEG(a))) bc_err(BC_ERR_MATH_NEGATIVE);
3884*5a6e8488SAndroid Build Coastguard Worker
3885*5a6e8488SAndroid Build Coastguard Worker // If either of these are true, then the numbers are integers.
3886*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(a) || BC_NUM_ONE(a)) return;
3887*5a6e8488SAndroid Build Coastguard Worker
3888*5a6e8488SAndroid Build Coastguard Worker #if BC_GCC
3889*5a6e8488SAndroid Build Coastguard Worker // This is here in GCC to quiet the "maybe-uninitialized" warning.
3890*5a6e8488SAndroid Build Coastguard Worker atemp.num = NULL;
3891*5a6e8488SAndroid Build Coastguard Worker atemp.len = 0;
3892*5a6e8488SAndroid Build Coastguard Worker #endif // BC_GCC
3893*5a6e8488SAndroid Build Coastguard Worker
3894*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(bc_num_nonInt(a, &atemp))) bc_err(BC_ERR_MATH_NON_INTEGER);
3895*5a6e8488SAndroid Build Coastguard Worker
3896*5a6e8488SAndroid Build Coastguard Worker assert(atemp.num != NULL);
3897*5a6e8488SAndroid Build Coastguard Worker assert(atemp.len);
3898*5a6e8488SAndroid Build Coastguard Worker
3899*5a6e8488SAndroid Build Coastguard Worker if (atemp.len > 2)
3900*5a6e8488SAndroid Build Coastguard Worker {
3901*5a6e8488SAndroid Build Coastguard Worker size_t len;
3902*5a6e8488SAndroid Build Coastguard Worker
3903*5a6e8488SAndroid Build Coastguard Worker len = atemp.len - 2;
3904*5a6e8488SAndroid Build Coastguard Worker
3905*5a6e8488SAndroid Build Coastguard Worker // Just generate a random number for each limb.
3906*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < len; i += 2)
3907*5a6e8488SAndroid Build Coastguard Worker {
3908*5a6e8488SAndroid Build Coastguard Worker BcRand dig;
3909*5a6e8488SAndroid Build Coastguard Worker
3910*5a6e8488SAndroid Build Coastguard Worker dig = bc_rand_bounded(rng, BC_BASE_RAND_POW);
3911*5a6e8488SAndroid Build Coastguard Worker
3912*5a6e8488SAndroid Build Coastguard Worker b->num[i] = (BcDig) (dig % BC_BASE_POW);
3913*5a6e8488SAndroid Build Coastguard Worker b->num[i + 1] = (BcDig) (dig / BC_BASE_POW);
3914*5a6e8488SAndroid Build Coastguard Worker }
3915*5a6e8488SAndroid Build Coastguard Worker }
3916*5a6e8488SAndroid Build Coastguard Worker else
3917*5a6e8488SAndroid Build Coastguard Worker {
3918*5a6e8488SAndroid Build Coastguard Worker // We need this set.
3919*5a6e8488SAndroid Build Coastguard Worker i = 0;
3920*5a6e8488SAndroid Build Coastguard Worker }
3921*5a6e8488SAndroid Build Coastguard Worker
3922*5a6e8488SAndroid Build Coastguard Worker // This will be true if there's one full limb after the two limb groups.
3923*5a6e8488SAndroid Build Coastguard Worker if (i == atemp.len - 2)
3924*5a6e8488SAndroid Build Coastguard Worker {
3925*5a6e8488SAndroid Build Coastguard Worker // Increment this for easy use.
3926*5a6e8488SAndroid Build Coastguard Worker i += 1;
3927*5a6e8488SAndroid Build Coastguard Worker
3928*5a6e8488SAndroid Build Coastguard Worker // If the last digit is not one, we need to set a bound for it
3929*5a6e8488SAndroid Build Coastguard Worker // explicitly. Since there's still an empty limb, we need to fill that.
3930*5a6e8488SAndroid Build Coastguard Worker if (atemp.num[i] != 1)
3931*5a6e8488SAndroid Build Coastguard Worker {
3932*5a6e8488SAndroid Build Coastguard Worker BcRand dig;
3933*5a6e8488SAndroid Build Coastguard Worker BcRand bound;
3934*5a6e8488SAndroid Build Coastguard Worker
3935*5a6e8488SAndroid Build Coastguard Worker // Set the bound to the bound of the last limb times the amount
3936*5a6e8488SAndroid Build Coastguard Worker // needed to fill the second-to-last limb as well.
3937*5a6e8488SAndroid Build Coastguard Worker bound = ((BcRand) atemp.num[i]) * BC_BASE_POW;
3938*5a6e8488SAndroid Build Coastguard Worker
3939*5a6e8488SAndroid Build Coastguard Worker dig = bc_rand_bounded(rng, bound);
3940*5a6e8488SAndroid Build Coastguard Worker
3941*5a6e8488SAndroid Build Coastguard Worker // Fill the last two.
3942*5a6e8488SAndroid Build Coastguard Worker b->num[i - 1] = (BcDig) (dig % BC_BASE_POW);
3943*5a6e8488SAndroid Build Coastguard Worker b->num[i] = (BcDig) (dig / BC_BASE_POW);
3944*5a6e8488SAndroid Build Coastguard Worker
3945*5a6e8488SAndroid Build Coastguard Worker // Ensure that the length will be correct. If the last limb is zero,
3946*5a6e8488SAndroid Build Coastguard Worker // then the length needs to be one less than the bound.
3947*5a6e8488SAndroid Build Coastguard Worker b->len = atemp.len - (b->num[i] == 0);
3948*5a6e8488SAndroid Build Coastguard Worker }
3949*5a6e8488SAndroid Build Coastguard Worker // Here the last limb *is* one, which means the last limb does *not*
3950*5a6e8488SAndroid Build Coastguard Worker // need to be filled. Also, the length needs to be one less because the
3951*5a6e8488SAndroid Build Coastguard Worker // last limb is 0.
3952*5a6e8488SAndroid Build Coastguard Worker else
3953*5a6e8488SAndroid Build Coastguard Worker {
3954*5a6e8488SAndroid Build Coastguard Worker b->num[i - 1] = (BcDig) bc_rand_bounded(rng, BC_BASE_POW);
3955*5a6e8488SAndroid Build Coastguard Worker b->len = atemp.len - 1;
3956*5a6e8488SAndroid Build Coastguard Worker }
3957*5a6e8488SAndroid Build Coastguard Worker }
3958*5a6e8488SAndroid Build Coastguard Worker // Here, there is only one limb to fill.
3959*5a6e8488SAndroid Build Coastguard Worker else
3960*5a6e8488SAndroid Build Coastguard Worker {
3961*5a6e8488SAndroid Build Coastguard Worker // See above for how this works.
3962*5a6e8488SAndroid Build Coastguard Worker if (atemp.num[i] != 1)
3963*5a6e8488SAndroid Build Coastguard Worker {
3964*5a6e8488SAndroid Build Coastguard Worker b->num[i] = (BcDig) bc_rand_bounded(rng, (BcRand) atemp.num[i]);
3965*5a6e8488SAndroid Build Coastguard Worker b->len = atemp.len - (b->num[i] == 0);
3966*5a6e8488SAndroid Build Coastguard Worker }
3967*5a6e8488SAndroid Build Coastguard Worker else b->len = atemp.len - 1;
3968*5a6e8488SAndroid Build Coastguard Worker }
3969*5a6e8488SAndroid Build Coastguard Worker
3970*5a6e8488SAndroid Build Coastguard Worker bc_num_clean(b);
3971*5a6e8488SAndroid Build Coastguard Worker
3972*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
3973*5a6e8488SAndroid Build Coastguard Worker }
3974*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
3975*5a6e8488SAndroid Build Coastguard Worker
3976*5a6e8488SAndroid Build Coastguard Worker size_t
bc_num_addReq(const BcNum * a,const BcNum * b,size_t scale)3977*5a6e8488SAndroid Build Coastguard Worker bc_num_addReq(const BcNum* a, const BcNum* b, size_t scale)
3978*5a6e8488SAndroid Build Coastguard Worker {
3979*5a6e8488SAndroid Build Coastguard Worker size_t aint, bint, ardx, brdx;
3980*5a6e8488SAndroid Build Coastguard Worker
3981*5a6e8488SAndroid Build Coastguard Worker // Addition and subtraction require the max of the length of the two numbers
3982*5a6e8488SAndroid Build Coastguard Worker // plus 1.
3983*5a6e8488SAndroid Build Coastguard Worker
3984*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(scale);
3985*5a6e8488SAndroid Build Coastguard Worker
3986*5a6e8488SAndroid Build Coastguard Worker ardx = BC_NUM_RDX_VAL(a);
3987*5a6e8488SAndroid Build Coastguard Worker aint = bc_num_int(a);
3988*5a6e8488SAndroid Build Coastguard Worker assert(aint <= a->len && ardx <= a->len);
3989*5a6e8488SAndroid Build Coastguard Worker
3990*5a6e8488SAndroid Build Coastguard Worker brdx = BC_NUM_RDX_VAL(b);
3991*5a6e8488SAndroid Build Coastguard Worker bint = bc_num_int(b);
3992*5a6e8488SAndroid Build Coastguard Worker assert(bint <= b->len && brdx <= b->len);
3993*5a6e8488SAndroid Build Coastguard Worker
3994*5a6e8488SAndroid Build Coastguard Worker ardx = BC_MAX(ardx, brdx);
3995*5a6e8488SAndroid Build Coastguard Worker aint = BC_MAX(aint, bint);
3996*5a6e8488SAndroid Build Coastguard Worker
3997*5a6e8488SAndroid Build Coastguard Worker return bc_vm_growSize(bc_vm_growSize(ardx, aint), 1);
3998*5a6e8488SAndroid Build Coastguard Worker }
3999*5a6e8488SAndroid Build Coastguard Worker
4000*5a6e8488SAndroid Build Coastguard Worker size_t
bc_num_mulReq(const BcNum * a,const BcNum * b,size_t scale)4001*5a6e8488SAndroid Build Coastguard Worker bc_num_mulReq(const BcNum* a, const BcNum* b, size_t scale)
4002*5a6e8488SAndroid Build Coastguard Worker {
4003*5a6e8488SAndroid Build Coastguard Worker size_t max, rdx;
4004*5a6e8488SAndroid Build Coastguard Worker
4005*5a6e8488SAndroid Build Coastguard Worker // Multiplication requires the sum of the lengths of the numbers.
4006*5a6e8488SAndroid Build Coastguard Worker
4007*5a6e8488SAndroid Build Coastguard Worker rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));
4008*5a6e8488SAndroid Build Coastguard Worker
4009*5a6e8488SAndroid Build Coastguard Worker max = BC_NUM_RDX(scale);
4010*5a6e8488SAndroid Build Coastguard Worker
4011*5a6e8488SAndroid Build Coastguard Worker max = bc_vm_growSize(BC_MAX(max, rdx), 1);
4012*5a6e8488SAndroid Build Coastguard Worker rdx = bc_vm_growSize(bc_vm_growSize(bc_num_int(a), bc_num_int(b)), max);
4013*5a6e8488SAndroid Build Coastguard Worker
4014*5a6e8488SAndroid Build Coastguard Worker return rdx;
4015*5a6e8488SAndroid Build Coastguard Worker }
4016*5a6e8488SAndroid Build Coastguard Worker
4017*5a6e8488SAndroid Build Coastguard Worker size_t
bc_num_divReq(const BcNum * a,const BcNum * b,size_t scale)4018*5a6e8488SAndroid Build Coastguard Worker bc_num_divReq(const BcNum* a, const BcNum* b, size_t scale)
4019*5a6e8488SAndroid Build Coastguard Worker {
4020*5a6e8488SAndroid Build Coastguard Worker size_t max, rdx;
4021*5a6e8488SAndroid Build Coastguard Worker
4022*5a6e8488SAndroid Build Coastguard Worker // Division requires the length of the dividend plus the scale.
4023*5a6e8488SAndroid Build Coastguard Worker
4024*5a6e8488SAndroid Build Coastguard Worker rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));
4025*5a6e8488SAndroid Build Coastguard Worker
4026*5a6e8488SAndroid Build Coastguard Worker max = BC_NUM_RDX(scale);
4027*5a6e8488SAndroid Build Coastguard Worker
4028*5a6e8488SAndroid Build Coastguard Worker max = bc_vm_growSize(BC_MAX(max, rdx), 1);
4029*5a6e8488SAndroid Build Coastguard Worker rdx = bc_vm_growSize(bc_num_int(a), max);
4030*5a6e8488SAndroid Build Coastguard Worker
4031*5a6e8488SAndroid Build Coastguard Worker return rdx;
4032*5a6e8488SAndroid Build Coastguard Worker }
4033*5a6e8488SAndroid Build Coastguard Worker
4034*5a6e8488SAndroid Build Coastguard Worker size_t
bc_num_powReq(const BcNum * a,const BcNum * b,size_t scale)4035*5a6e8488SAndroid Build Coastguard Worker bc_num_powReq(const BcNum* a, const BcNum* b, size_t scale)
4036*5a6e8488SAndroid Build Coastguard Worker {
4037*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(scale);
4038*5a6e8488SAndroid Build Coastguard Worker return bc_vm_growSize(bc_vm_growSize(a->len, b->len), 1);
4039*5a6e8488SAndroid Build Coastguard Worker }
4040*5a6e8488SAndroid Build Coastguard Worker
4041*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
4042*5a6e8488SAndroid Build Coastguard Worker size_t
bc_num_placesReq(const BcNum * a,const BcNum * b,size_t scale)4043*5a6e8488SAndroid Build Coastguard Worker bc_num_placesReq(const BcNum* a, const BcNum* b, size_t scale)
4044*5a6e8488SAndroid Build Coastguard Worker {
4045*5a6e8488SAndroid Build Coastguard Worker BC_UNUSED(scale);
4046*5a6e8488SAndroid Build Coastguard Worker return a->len + b->len - BC_NUM_RDX_VAL(a) - BC_NUM_RDX_VAL(b);
4047*5a6e8488SAndroid Build Coastguard Worker }
4048*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
4049*5a6e8488SAndroid Build Coastguard Worker
4050*5a6e8488SAndroid Build Coastguard Worker void
bc_num_add(BcNum * a,BcNum * b,BcNum * c,size_t scale)4051*5a6e8488SAndroid Build Coastguard Worker bc_num_add(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4052*5a6e8488SAndroid Build Coastguard Worker {
4053*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4054*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4055*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, false, bc_num_as, bc_num_addReq(a, b, scale));
4056*5a6e8488SAndroid Build Coastguard Worker }
4057*5a6e8488SAndroid Build Coastguard Worker
4058*5a6e8488SAndroid Build Coastguard Worker void
bc_num_sub(BcNum * a,BcNum * b,BcNum * c,size_t scale)4059*5a6e8488SAndroid Build Coastguard Worker bc_num_sub(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4060*5a6e8488SAndroid Build Coastguard Worker {
4061*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4062*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4063*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, true, bc_num_as, bc_num_addReq(a, b, scale));
4064*5a6e8488SAndroid Build Coastguard Worker }
4065*5a6e8488SAndroid Build Coastguard Worker
4066*5a6e8488SAndroid Build Coastguard Worker void
bc_num_mul(BcNum * a,BcNum * b,BcNum * c,size_t scale)4067*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4068*5a6e8488SAndroid Build Coastguard Worker {
4069*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4070*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4071*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, scale, bc_num_m, bc_num_mulReq(a, b, scale));
4072*5a6e8488SAndroid Build Coastguard Worker }
4073*5a6e8488SAndroid Build Coastguard Worker
4074*5a6e8488SAndroid Build Coastguard Worker void
bc_num_div(BcNum * a,BcNum * b,BcNum * c,size_t scale)4075*5a6e8488SAndroid Build Coastguard Worker bc_num_div(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4076*5a6e8488SAndroid Build Coastguard Worker {
4077*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4078*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4079*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, scale, bc_num_d, bc_num_divReq(a, b, scale));
4080*5a6e8488SAndroid Build Coastguard Worker }
4081*5a6e8488SAndroid Build Coastguard Worker
4082*5a6e8488SAndroid Build Coastguard Worker void
bc_num_mod(BcNum * a,BcNum * b,BcNum * c,size_t scale)4083*5a6e8488SAndroid Build Coastguard Worker bc_num_mod(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4084*5a6e8488SAndroid Build Coastguard Worker {
4085*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4086*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4087*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, scale, bc_num_rem, bc_num_divReq(a, b, scale));
4088*5a6e8488SAndroid Build Coastguard Worker }
4089*5a6e8488SAndroid Build Coastguard Worker
4090*5a6e8488SAndroid Build Coastguard Worker void
bc_num_pow(BcNum * a,BcNum * b,BcNum * c,size_t scale)4091*5a6e8488SAndroid Build Coastguard Worker bc_num_pow(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4092*5a6e8488SAndroid Build Coastguard Worker {
4093*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4094*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4095*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, scale, bc_num_p, bc_num_powReq(a, b, scale));
4096*5a6e8488SAndroid Build Coastguard Worker }
4097*5a6e8488SAndroid Build Coastguard Worker
4098*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
4099*5a6e8488SAndroid Build Coastguard Worker void
bc_num_places(BcNum * a,BcNum * b,BcNum * c,size_t scale)4100*5a6e8488SAndroid Build Coastguard Worker bc_num_places(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4101*5a6e8488SAndroid Build Coastguard Worker {
4102*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4103*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4104*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, scale, bc_num_place, bc_num_placesReq(a, b, scale));
4105*5a6e8488SAndroid Build Coastguard Worker }
4106*5a6e8488SAndroid Build Coastguard Worker
4107*5a6e8488SAndroid Build Coastguard Worker void
bc_num_lshift(BcNum * a,BcNum * b,BcNum * c,size_t scale)4108*5a6e8488SAndroid Build Coastguard Worker bc_num_lshift(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4109*5a6e8488SAndroid Build Coastguard Worker {
4110*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4111*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4112*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, scale, bc_num_left, bc_num_placesReq(a, b, scale));
4113*5a6e8488SAndroid Build Coastguard Worker }
4114*5a6e8488SAndroid Build Coastguard Worker
4115*5a6e8488SAndroid Build Coastguard Worker void
bc_num_rshift(BcNum * a,BcNum * b,BcNum * c,size_t scale)4116*5a6e8488SAndroid Build Coastguard Worker bc_num_rshift(BcNum* a, BcNum* b, BcNum* c, size_t scale)
4117*5a6e8488SAndroid Build Coastguard Worker {
4118*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(a));
4119*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4120*5a6e8488SAndroid Build Coastguard Worker bc_num_binary(a, b, c, scale, bc_num_right, bc_num_placesReq(a, b, scale));
4121*5a6e8488SAndroid Build Coastguard Worker }
4122*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
4123*5a6e8488SAndroid Build Coastguard Worker
4124*5a6e8488SAndroid Build Coastguard Worker void
bc_num_sqrt(BcNum * restrict a,BcNum * restrict b,size_t scale)4125*5a6e8488SAndroid Build Coastguard Worker bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)
4126*5a6e8488SAndroid Build Coastguard Worker {
4127*5a6e8488SAndroid Build Coastguard Worker BcNum num1, num2, half, f, fprime;
4128*5a6e8488SAndroid Build Coastguard Worker BcNum* x0;
4129*5a6e8488SAndroid Build Coastguard Worker BcNum* x1;
4130*5a6e8488SAndroid Build Coastguard Worker BcNum* temp;
4131*5a6e8488SAndroid Build Coastguard Worker // realscale is meant to quiet a warning on GCC about longjmp() clobbering.
4132*5a6e8488SAndroid Build Coastguard Worker // This one is real.
4133*5a6e8488SAndroid Build Coastguard Worker size_t pow, len, rdx, req, resscale, realscale;
4134*5a6e8488SAndroid Build Coastguard Worker BcDig half_digs[1];
4135*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
4136*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
4137*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
4138*5a6e8488SAndroid Build Coastguard Worker
4139*5a6e8488SAndroid Build Coastguard Worker assert(a != NULL && b != NULL && a != b);
4140*5a6e8488SAndroid Build Coastguard Worker
4141*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(BC_NUM_NEG(a))) bc_err(BC_ERR_MATH_NEGATIVE);
4142*5a6e8488SAndroid Build Coastguard Worker
4143*5a6e8488SAndroid Build Coastguard Worker // We want to calculate to a's scale if it is bigger so that the result will
4144*5a6e8488SAndroid Build Coastguard Worker // truncate properly.
4145*5a6e8488SAndroid Build Coastguard Worker if (a->scale > scale) realscale = a->scale;
4146*5a6e8488SAndroid Build Coastguard Worker else realscale = scale;
4147*5a6e8488SAndroid Build Coastguard Worker
4148*5a6e8488SAndroid Build Coastguard Worker // Set parameters for the result.
4149*5a6e8488SAndroid Build Coastguard Worker len = bc_vm_growSize(bc_num_intDigits(a), 1);
4150*5a6e8488SAndroid Build Coastguard Worker rdx = BC_NUM_RDX(realscale);
4151*5a6e8488SAndroid Build Coastguard Worker
4152*5a6e8488SAndroid Build Coastguard Worker // Square root needs half of the length of the parameter.
4153*5a6e8488SAndroid Build Coastguard Worker req = bc_vm_growSize(BC_MAX(rdx, BC_NUM_RDX_VAL(a)), len >> 1);
4154*5a6e8488SAndroid Build Coastguard Worker req = bc_vm_growSize(req, 1);
4155*5a6e8488SAndroid Build Coastguard Worker
4156*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
4157*5a6e8488SAndroid Build Coastguard Worker
4158*5a6e8488SAndroid Build Coastguard Worker // Unlike the binary operators, this function is the only single parameter
4159*5a6e8488SAndroid Build Coastguard Worker // function and is expected to initialize the result. This means that it
4160*5a6e8488SAndroid Build Coastguard Worker // expects that b is *NOT* preallocated. We allocate it here.
4161*5a6e8488SAndroid Build Coastguard Worker bc_num_init(b, req);
4162*5a6e8488SAndroid Build Coastguard Worker
4163*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
4164*5a6e8488SAndroid Build Coastguard Worker
4165*5a6e8488SAndroid Build Coastguard Worker assert(a != NULL && b != NULL && a != b);
4166*5a6e8488SAndroid Build Coastguard Worker assert(a->num != NULL && b->num != NULL);
4167*5a6e8488SAndroid Build Coastguard Worker
4168*5a6e8488SAndroid Build Coastguard Worker // Easy case.
4169*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ZERO(a))
4170*5a6e8488SAndroid Build Coastguard Worker {
4171*5a6e8488SAndroid Build Coastguard Worker bc_num_setToZero(b, realscale);
4172*5a6e8488SAndroid Build Coastguard Worker return;
4173*5a6e8488SAndroid Build Coastguard Worker }
4174*5a6e8488SAndroid Build Coastguard Worker
4175*5a6e8488SAndroid Build Coastguard Worker // Another easy case.
4176*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ONE(a))
4177*5a6e8488SAndroid Build Coastguard Worker {
4178*5a6e8488SAndroid Build Coastguard Worker bc_num_one(b);
4179*5a6e8488SAndroid Build Coastguard Worker bc_num_extend(b, realscale);
4180*5a6e8488SAndroid Build Coastguard Worker return;
4181*5a6e8488SAndroid Build Coastguard Worker }
4182*5a6e8488SAndroid Build Coastguard Worker
4183*5a6e8488SAndroid Build Coastguard Worker // Set the parameters again.
4184*5a6e8488SAndroid Build Coastguard Worker rdx = BC_NUM_RDX(realscale);
4185*5a6e8488SAndroid Build Coastguard Worker rdx = BC_MAX(rdx, BC_NUM_RDX_VAL(a));
4186*5a6e8488SAndroid Build Coastguard Worker len = bc_vm_growSize(a->len, rdx);
4187*5a6e8488SAndroid Build Coastguard Worker
4188*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
4189*5a6e8488SAndroid Build Coastguard Worker
4190*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&num1, len);
4191*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&num2, len);
4192*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&half, half_digs, sizeof(half_digs) / sizeof(BcDig));
4193*5a6e8488SAndroid Build Coastguard Worker
4194*5a6e8488SAndroid Build Coastguard Worker // There is a division by two in the formula. We set up a number that's 1/2
4195*5a6e8488SAndroid Build Coastguard Worker // so that we can use multiplication instead of heavy division.
4196*5a6e8488SAndroid Build Coastguard Worker bc_num_setToZero(&half, 1);
4197*5a6e8488SAndroid Build Coastguard Worker half.num[0] = BC_BASE_POW / 2;
4198*5a6e8488SAndroid Build Coastguard Worker half.len = 1;
4199*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_SET_NP(half, 1);
4200*5a6e8488SAndroid Build Coastguard Worker
4201*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&f, len);
4202*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&fprime, len);
4203*5a6e8488SAndroid Build Coastguard Worker
4204*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
4205*5a6e8488SAndroid Build Coastguard Worker
4206*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
4207*5a6e8488SAndroid Build Coastguard Worker
4208*5a6e8488SAndroid Build Coastguard Worker // Pointers for easy switching.
4209*5a6e8488SAndroid Build Coastguard Worker x0 = &num1;
4210*5a6e8488SAndroid Build Coastguard Worker x1 = &num2;
4211*5a6e8488SAndroid Build Coastguard Worker
4212*5a6e8488SAndroid Build Coastguard Worker // Start with 1.
4213*5a6e8488SAndroid Build Coastguard Worker bc_num_one(x0);
4214*5a6e8488SAndroid Build Coastguard Worker
4215*5a6e8488SAndroid Build Coastguard Worker // The power of the operand is needed for the estimate.
4216*5a6e8488SAndroid Build Coastguard Worker pow = bc_num_intDigits(a);
4217*5a6e8488SAndroid Build Coastguard Worker
4218*5a6e8488SAndroid Build Coastguard Worker // The code in this if statement calculates the initial estimate. First, if
4219*5a6e8488SAndroid Build Coastguard Worker // a is less than 1, then 0 is a good estimate. Otherwise, we want something
4220*5a6e8488SAndroid Build Coastguard Worker // in the same ballpark. That ballpark is half of pow because the result
4221*5a6e8488SAndroid Build Coastguard Worker // will have half the digits.
4222*5a6e8488SAndroid Build Coastguard Worker if (pow)
4223*5a6e8488SAndroid Build Coastguard Worker {
4224*5a6e8488SAndroid Build Coastguard Worker // An odd number is served by starting with 2^((pow-1)/2), and an even
4225*5a6e8488SAndroid Build Coastguard Worker // number is served by starting with 6^((pow-2)/2). Why? Because math.
4226*5a6e8488SAndroid Build Coastguard Worker if (pow & 1) x0->num[0] = 2;
4227*5a6e8488SAndroid Build Coastguard Worker else x0->num[0] = 6;
4228*5a6e8488SAndroid Build Coastguard Worker
4229*5a6e8488SAndroid Build Coastguard Worker pow -= 2 - (pow & 1);
4230*5a6e8488SAndroid Build Coastguard Worker bc_num_shiftLeft(x0, pow / 2);
4231*5a6e8488SAndroid Build Coastguard Worker }
4232*5a6e8488SAndroid Build Coastguard Worker
4233*5a6e8488SAndroid Build Coastguard Worker // I can set the rdx here directly because neg should be false.
4234*5a6e8488SAndroid Build Coastguard Worker x0->scale = x0->rdx = 0;
4235*5a6e8488SAndroid Build Coastguard Worker resscale = (realscale + BC_BASE_DIGS) + 2;
4236*5a6e8488SAndroid Build Coastguard Worker
4237*5a6e8488SAndroid Build Coastguard Worker // This is the calculation loop. This compare goes to 0 eventually as the
4238*5a6e8488SAndroid Build Coastguard Worker // difference between the two numbers gets smaller than resscale.
4239*5a6e8488SAndroid Build Coastguard Worker while (bc_num_cmp(x1, x0))
4240*5a6e8488SAndroid Build Coastguard Worker {
4241*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_NONZERO(x0));
4242*5a6e8488SAndroid Build Coastguard Worker
4243*5a6e8488SAndroid Build Coastguard Worker // This loop directly corresponds to the iteration in Newton's method.
4244*5a6e8488SAndroid Build Coastguard Worker // If you know the formula, this loop makes sense. Go study the formula.
4245*5a6e8488SAndroid Build Coastguard Worker
4246*5a6e8488SAndroid Build Coastguard Worker bc_num_div(a, x0, &f, resscale);
4247*5a6e8488SAndroid Build Coastguard Worker bc_num_add(x0, &f, &fprime, resscale);
4248*5a6e8488SAndroid Build Coastguard Worker
4249*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(fprime));
4250*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(half));
4251*5a6e8488SAndroid Build Coastguard Worker
4252*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(&fprime, &half, x1, resscale);
4253*5a6e8488SAndroid Build Coastguard Worker
4254*5a6e8488SAndroid Build Coastguard Worker // Switch.
4255*5a6e8488SAndroid Build Coastguard Worker temp = x0;
4256*5a6e8488SAndroid Build Coastguard Worker x0 = x1;
4257*5a6e8488SAndroid Build Coastguard Worker x1 = temp;
4258*5a6e8488SAndroid Build Coastguard Worker }
4259*5a6e8488SAndroid Build Coastguard Worker
4260*5a6e8488SAndroid Build Coastguard Worker // Copy to the result and truncate.
4261*5a6e8488SAndroid Build Coastguard Worker bc_num_copy(b, x0);
4262*5a6e8488SAndroid Build Coastguard Worker if (b->scale > realscale) bc_num_truncate(b, b->scale - realscale);
4263*5a6e8488SAndroid Build Coastguard Worker
4264*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_NEG(b) || BC_NUM_NONZERO(b));
4265*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(b));
4266*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(b) <= b->len || !b->len);
4267*5a6e8488SAndroid Build Coastguard Worker assert(!b->len || b->num[b->len - 1] || BC_NUM_RDX_VAL(b) == b->len);
4268*5a6e8488SAndroid Build Coastguard Worker
4269*5a6e8488SAndroid Build Coastguard Worker err:
4270*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
4271*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&fprime);
4272*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&f);
4273*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&num2);
4274*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&num1);
4275*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
4276*5a6e8488SAndroid Build Coastguard Worker }
4277*5a6e8488SAndroid Build Coastguard Worker
4278*5a6e8488SAndroid Build Coastguard Worker void
bc_num_divmod(BcNum * a,BcNum * b,BcNum * c,BcNum * d,size_t scale)4279*5a6e8488SAndroid Build Coastguard Worker bc_num_divmod(BcNum* a, BcNum* b, BcNum* c, BcNum* d, size_t scale)
4280*5a6e8488SAndroid Build Coastguard Worker {
4281*5a6e8488SAndroid Build Coastguard Worker size_t ts, len;
4282*5a6e8488SAndroid Build Coastguard Worker BcNum *ptr_a, num2;
4283*5a6e8488SAndroid Build Coastguard Worker // This is volatile to quiet a warning on GCC about clobbering with
4284*5a6e8488SAndroid Build Coastguard Worker // longjmp().
4285*5a6e8488SAndroid Build Coastguard Worker volatile bool init = false;
4286*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
4287*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
4288*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
4289*5a6e8488SAndroid Build Coastguard Worker
4290*5a6e8488SAndroid Build Coastguard Worker // The bulk of this function is just doing what bc_num_binary() does for the
4291*5a6e8488SAndroid Build Coastguard Worker // binary operators. However, it assumes that only c and a can be equal.
4292*5a6e8488SAndroid Build Coastguard Worker
4293*5a6e8488SAndroid Build Coastguard Worker // Set up the parameters.
4294*5a6e8488SAndroid Build Coastguard Worker ts = BC_MAX(scale + b->scale, a->scale);
4295*5a6e8488SAndroid Build Coastguard Worker len = bc_num_mulReq(a, b, ts);
4296*5a6e8488SAndroid Build Coastguard Worker
4297*5a6e8488SAndroid Build Coastguard Worker assert(a != NULL && b != NULL && c != NULL && d != NULL);
4298*5a6e8488SAndroid Build Coastguard Worker assert(c != d && a != d && b != d && b != c);
4299*5a6e8488SAndroid Build Coastguard Worker
4300*5a6e8488SAndroid Build Coastguard Worker // Initialize or expand as necessary.
4301*5a6e8488SAndroid Build Coastguard Worker if (c == a)
4302*5a6e8488SAndroid Build Coastguard Worker {
4303*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
4304*5a6e8488SAndroid Build Coastguard Worker memcpy(&num2, c, sizeof(BcNum));
4305*5a6e8488SAndroid Build Coastguard Worker ptr_a = &num2;
4306*5a6e8488SAndroid Build Coastguard Worker
4307*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
4308*5a6e8488SAndroid Build Coastguard Worker
4309*5a6e8488SAndroid Build Coastguard Worker bc_num_init(c, len);
4310*5a6e8488SAndroid Build Coastguard Worker
4311*5a6e8488SAndroid Build Coastguard Worker init = true;
4312*5a6e8488SAndroid Build Coastguard Worker
4313*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
4314*5a6e8488SAndroid Build Coastguard Worker
4315*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
4316*5a6e8488SAndroid Build Coastguard Worker }
4317*5a6e8488SAndroid Build Coastguard Worker else
4318*5a6e8488SAndroid Build Coastguard Worker {
4319*5a6e8488SAndroid Build Coastguard Worker ptr_a = a;
4320*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(c, len);
4321*5a6e8488SAndroid Build Coastguard Worker }
4322*5a6e8488SAndroid Build Coastguard Worker
4323*5a6e8488SAndroid Build Coastguard Worker // Do the quick version if possible.
4324*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_NONZERO(a) && !BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b) &&
4325*5a6e8488SAndroid Build Coastguard Worker b->len == 1 && !scale)
4326*5a6e8488SAndroid Build Coastguard Worker {
4327*5a6e8488SAndroid Build Coastguard Worker BcBigDig rem;
4328*5a6e8488SAndroid Build Coastguard Worker
4329*5a6e8488SAndroid Build Coastguard Worker bc_num_divArray(ptr_a, (BcBigDig) b->num[0], c, &rem);
4330*5a6e8488SAndroid Build Coastguard Worker
4331*5a6e8488SAndroid Build Coastguard Worker assert(rem < BC_BASE_POW);
4332*5a6e8488SAndroid Build Coastguard Worker
4333*5a6e8488SAndroid Build Coastguard Worker d->num[0] = (BcDig) rem;
4334*5a6e8488SAndroid Build Coastguard Worker d->len = (rem != 0);
4335*5a6e8488SAndroid Build Coastguard Worker }
4336*5a6e8488SAndroid Build Coastguard Worker // Do the slow method.
4337*5a6e8488SAndroid Build Coastguard Worker else bc_num_r(ptr_a, b, c, d, scale, ts);
4338*5a6e8488SAndroid Build Coastguard Worker
4339*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
4340*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(c));
4341*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
4342*5a6e8488SAndroid Build Coastguard Worker assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
4343*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_NEG(d) || BC_NUM_NONZERO(d));
4344*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(d));
4345*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VAL(d) <= d->len || !d->len);
4346*5a6e8488SAndroid Build Coastguard Worker assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
4347*5a6e8488SAndroid Build Coastguard Worker
4348*5a6e8488SAndroid Build Coastguard Worker err:
4349*5a6e8488SAndroid Build Coastguard Worker // Only cleanup if we initialized.
4350*5a6e8488SAndroid Build Coastguard Worker if (init)
4351*5a6e8488SAndroid Build Coastguard Worker {
4352*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
4353*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&num2);
4354*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
4355*5a6e8488SAndroid Build Coastguard Worker }
4356*5a6e8488SAndroid Build Coastguard Worker }
4357*5a6e8488SAndroid Build Coastguard Worker
4358*5a6e8488SAndroid Build Coastguard Worker void
bc_num_modexp(BcNum * a,BcNum * b,BcNum * c,BcNum * restrict d)4359*5a6e8488SAndroid Build Coastguard Worker bc_num_modexp(BcNum* a, BcNum* b, BcNum* c, BcNum* restrict d)
4360*5a6e8488SAndroid Build Coastguard Worker {
4361*5a6e8488SAndroid Build Coastguard Worker BcNum base, exp, two, temp, atemp, btemp, ctemp;
4362*5a6e8488SAndroid Build Coastguard Worker BcDig two_digs[2];
4363*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_LIBRARY
4364*5a6e8488SAndroid Build Coastguard Worker BcVm* vm = bcl_getspecific();
4365*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_LIBRARY
4366*5a6e8488SAndroid Build Coastguard Worker
4367*5a6e8488SAndroid Build Coastguard Worker assert(a != NULL && b != NULL && c != NULL && d != NULL);
4368*5a6e8488SAndroid Build Coastguard Worker assert(a != d && b != d && c != d);
4369*5a6e8488SAndroid Build Coastguard Worker
4370*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(BC_NUM_ZERO(c))) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
4371*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(BC_NUM_NEG(b))) bc_err(BC_ERR_MATH_NEGATIVE);
4372*5a6e8488SAndroid Build Coastguard Worker
4373*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG || BC_GCC
4374*5a6e8488SAndroid Build Coastguard Worker // This is entirely for quieting a useless scan-build error.
4375*5a6e8488SAndroid Build Coastguard Worker btemp.len = 0;
4376*5a6e8488SAndroid Build Coastguard Worker ctemp.len = 0;
4377*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG || BC_GCC
4378*5a6e8488SAndroid Build Coastguard Worker
4379*5a6e8488SAndroid Build Coastguard Worker // Eliminate fractional parts that are zero or error if they are not zero.
4380*5a6e8488SAndroid Build Coastguard Worker if (BC_ERR(bc_num_nonInt(a, &atemp) || bc_num_nonInt(b, &btemp) ||
4381*5a6e8488SAndroid Build Coastguard Worker bc_num_nonInt(c, &ctemp)))
4382*5a6e8488SAndroid Build Coastguard Worker {
4383*5a6e8488SAndroid Build Coastguard Worker bc_err(BC_ERR_MATH_NON_INTEGER);
4384*5a6e8488SAndroid Build Coastguard Worker }
4385*5a6e8488SAndroid Build Coastguard Worker
4386*5a6e8488SAndroid Build Coastguard Worker bc_num_expand(d, ctemp.len);
4387*5a6e8488SAndroid Build Coastguard Worker
4388*5a6e8488SAndroid Build Coastguard Worker BC_SIG_LOCK;
4389*5a6e8488SAndroid Build Coastguard Worker
4390*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&base, ctemp.len);
4391*5a6e8488SAndroid Build Coastguard Worker bc_num_setup(&two, two_digs, sizeof(two_digs) / sizeof(BcDig));
4392*5a6e8488SAndroid Build Coastguard Worker bc_num_init(&temp, btemp.len + 1);
4393*5a6e8488SAndroid Build Coastguard Worker bc_num_createCopy(&exp, &btemp);
4394*5a6e8488SAndroid Build Coastguard Worker
4395*5a6e8488SAndroid Build Coastguard Worker BC_SETJMP_LOCKED(vm, err);
4396*5a6e8488SAndroid Build Coastguard Worker
4397*5a6e8488SAndroid Build Coastguard Worker BC_SIG_UNLOCK;
4398*5a6e8488SAndroid Build Coastguard Worker
4399*5a6e8488SAndroid Build Coastguard Worker bc_num_one(&two);
4400*5a6e8488SAndroid Build Coastguard Worker two.num[0] = 2;
4401*5a6e8488SAndroid Build Coastguard Worker bc_num_one(d);
4402*5a6e8488SAndroid Build Coastguard Worker
4403*5a6e8488SAndroid Build Coastguard Worker // We already checked for 0.
4404*5a6e8488SAndroid Build Coastguard Worker bc_num_rem(&atemp, &ctemp, &base, 0);
4405*5a6e8488SAndroid Build Coastguard Worker
4406*5a6e8488SAndroid Build Coastguard Worker // If you know the algorithm I used, the memory-efficient method, then this
4407*5a6e8488SAndroid Build Coastguard Worker // loop should be self-explanatory because it is the calculation loop.
4408*5a6e8488SAndroid Build Coastguard Worker while (BC_NUM_NONZERO(&exp))
4409*5a6e8488SAndroid Build Coastguard Worker {
4410*5a6e8488SAndroid Build Coastguard Worker // Num two cannot be 0, so no errors.
4411*5a6e8488SAndroid Build Coastguard Worker bc_num_divmod(&exp, &two, &exp, &temp, 0);
4412*5a6e8488SAndroid Build Coastguard Worker
4413*5a6e8488SAndroid Build Coastguard Worker if (BC_NUM_ONE(&temp) && !BC_NUM_NEG_NP(temp))
4414*5a6e8488SAndroid Build Coastguard Worker {
4415*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(d));
4416*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(base));
4417*5a6e8488SAndroid Build Coastguard Worker
4418*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(d, &base, &temp, 0);
4419*5a6e8488SAndroid Build Coastguard Worker
4420*5a6e8488SAndroid Build Coastguard Worker // We already checked for 0.
4421*5a6e8488SAndroid Build Coastguard Worker bc_num_rem(&temp, &ctemp, d, 0);
4422*5a6e8488SAndroid Build Coastguard Worker }
4423*5a6e8488SAndroid Build Coastguard Worker
4424*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID_NP(base));
4425*5a6e8488SAndroid Build Coastguard Worker
4426*5a6e8488SAndroid Build Coastguard Worker bc_num_mul(&base, &base, &temp, 0);
4427*5a6e8488SAndroid Build Coastguard Worker
4428*5a6e8488SAndroid Build Coastguard Worker // We already checked for 0.
4429*5a6e8488SAndroid Build Coastguard Worker bc_num_rem(&temp, &ctemp, &base, 0);
4430*5a6e8488SAndroid Build Coastguard Worker }
4431*5a6e8488SAndroid Build Coastguard Worker
4432*5a6e8488SAndroid Build Coastguard Worker err:
4433*5a6e8488SAndroid Build Coastguard Worker BC_SIG_MAYLOCK;
4434*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&exp);
4435*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&temp);
4436*5a6e8488SAndroid Build Coastguard Worker bc_num_free(&base);
4437*5a6e8488SAndroid Build Coastguard Worker BC_LONGJMP_CONT(vm);
4438*5a6e8488SAndroid Build Coastguard Worker assert(!BC_NUM_NEG(d) || d->len);
4439*5a6e8488SAndroid Build Coastguard Worker assert(BC_NUM_RDX_VALID(d));
4440*5a6e8488SAndroid Build Coastguard Worker assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
4441*5a6e8488SAndroid Build Coastguard Worker }
4442*5a6e8488SAndroid Build Coastguard Worker
4443*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG_CODE
4444*5a6e8488SAndroid Build Coastguard Worker void
bc_num_printDebug(const BcNum * n,const char * name,bool emptyline)4445*5a6e8488SAndroid Build Coastguard Worker bc_num_printDebug(const BcNum* n, const char* name, bool emptyline)
4446*5a6e8488SAndroid Build Coastguard Worker {
4447*5a6e8488SAndroid Build Coastguard Worker bc_file_puts(&vm->fout, bc_flush_none, name);
4448*5a6e8488SAndroid Build Coastguard Worker bc_file_puts(&vm->fout, bc_flush_none, ": ");
4449*5a6e8488SAndroid Build Coastguard Worker bc_num_printDecimal(n, true);
4450*5a6e8488SAndroid Build Coastguard Worker bc_file_putchar(&vm->fout, bc_flush_err, '\n');
4451*5a6e8488SAndroid Build Coastguard Worker if (emptyline) bc_file_putchar(&vm->fout, bc_flush_err, '\n');
4452*5a6e8488SAndroid Build Coastguard Worker vm->nchars = 0;
4453*5a6e8488SAndroid Build Coastguard Worker }
4454*5a6e8488SAndroid Build Coastguard Worker
4455*5a6e8488SAndroid Build Coastguard Worker void
bc_num_printDigs(const BcDig * n,size_t len,bool emptyline)4456*5a6e8488SAndroid Build Coastguard Worker bc_num_printDigs(const BcDig* n, size_t len, bool emptyline)
4457*5a6e8488SAndroid Build Coastguard Worker {
4458*5a6e8488SAndroid Build Coastguard Worker size_t i;
4459*5a6e8488SAndroid Build Coastguard Worker
4460*5a6e8488SAndroid Build Coastguard Worker for (i = len - 1; i < len; --i)
4461*5a6e8488SAndroid Build Coastguard Worker {
4462*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->fout, " %lu", (unsigned long) n[i]);
4463*5a6e8488SAndroid Build Coastguard Worker }
4464*5a6e8488SAndroid Build Coastguard Worker
4465*5a6e8488SAndroid Build Coastguard Worker bc_file_putchar(&vm->fout, bc_flush_err, '\n');
4466*5a6e8488SAndroid Build Coastguard Worker if (emptyline) bc_file_putchar(&vm->fout, bc_flush_err, '\n');
4467*5a6e8488SAndroid Build Coastguard Worker vm->nchars = 0;
4468*5a6e8488SAndroid Build Coastguard Worker }
4469*5a6e8488SAndroid Build Coastguard Worker
4470*5a6e8488SAndroid Build Coastguard Worker void
bc_num_printWithDigs(const BcNum * n,const char * name,bool emptyline)4471*5a6e8488SAndroid Build Coastguard Worker bc_num_printWithDigs(const BcNum* n, const char* name, bool emptyline)
4472*5a6e8488SAndroid Build Coastguard Worker {
4473*5a6e8488SAndroid Build Coastguard Worker bc_file_puts(&vm->fout, bc_flush_none, name);
4474*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->fout, " len: %zu, rdx: %zu, scale: %zu\n", name, n->len,
4475*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_VAL(n), n->scale);
4476*5a6e8488SAndroid Build Coastguard Worker bc_num_printDigs(n->num, n->len, emptyline);
4477*5a6e8488SAndroid Build Coastguard Worker }
4478*5a6e8488SAndroid Build Coastguard Worker
4479*5a6e8488SAndroid Build Coastguard Worker void
bc_num_dump(const char * varname,const BcNum * n)4480*5a6e8488SAndroid Build Coastguard Worker bc_num_dump(const char* varname, const BcNum* n)
4481*5a6e8488SAndroid Build Coastguard Worker {
4482*5a6e8488SAndroid Build Coastguard Worker ulong i, scale = n->scale;
4483*5a6e8488SAndroid Build Coastguard Worker
4484*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->ferr, "\n%s = %s", varname,
4485*5a6e8488SAndroid Build Coastguard Worker n->len ? (BC_NUM_NEG(n) ? "-" : "+") : "0 ");
4486*5a6e8488SAndroid Build Coastguard Worker
4487*5a6e8488SAndroid Build Coastguard Worker for (i = n->len - 1; i < n->len; --i)
4488*5a6e8488SAndroid Build Coastguard Worker {
4489*5a6e8488SAndroid Build Coastguard Worker if (i + 1 == BC_NUM_RDX_VAL(n))
4490*5a6e8488SAndroid Build Coastguard Worker {
4491*5a6e8488SAndroid Build Coastguard Worker bc_file_puts(&vm->ferr, bc_flush_none, ". ");
4492*5a6e8488SAndroid Build Coastguard Worker }
4493*5a6e8488SAndroid Build Coastguard Worker
4494*5a6e8488SAndroid Build Coastguard Worker if (scale / BC_BASE_DIGS != BC_NUM_RDX_VAL(n) - i - 1)
4495*5a6e8488SAndroid Build Coastguard Worker {
4496*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->ferr, "%lu ", (unsigned long) n->num[i]);
4497*5a6e8488SAndroid Build Coastguard Worker }
4498*5a6e8488SAndroid Build Coastguard Worker else
4499*5a6e8488SAndroid Build Coastguard Worker {
4500*5a6e8488SAndroid Build Coastguard Worker int mod = scale % BC_BASE_DIGS;
4501*5a6e8488SAndroid Build Coastguard Worker int d = BC_BASE_DIGS - mod;
4502*5a6e8488SAndroid Build Coastguard Worker BcDig div;
4503*5a6e8488SAndroid Build Coastguard Worker
4504*5a6e8488SAndroid Build Coastguard Worker if (mod != 0)
4505*5a6e8488SAndroid Build Coastguard Worker {
4506*5a6e8488SAndroid Build Coastguard Worker div = n->num[i] / ((BcDig) bc_num_pow10[(ulong) d]);
4507*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->ferr, "%lu", (unsigned long) div);
4508*5a6e8488SAndroid Build Coastguard Worker }
4509*5a6e8488SAndroid Build Coastguard Worker
4510*5a6e8488SAndroid Build Coastguard Worker div = n->num[i] % ((BcDig) bc_num_pow10[(ulong) d]);
4511*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->ferr, " ' %lu ", (unsigned long) div);
4512*5a6e8488SAndroid Build Coastguard Worker }
4513*5a6e8488SAndroid Build Coastguard Worker }
4514*5a6e8488SAndroid Build Coastguard Worker
4515*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->ferr, "(%zu | %zu.%zu / %zu) %lu\n", n->scale, n->len,
4516*5a6e8488SAndroid Build Coastguard Worker BC_NUM_RDX_VAL(n), n->cap, (unsigned long) (void*) n->num);
4517*5a6e8488SAndroid Build Coastguard Worker
4518*5a6e8488SAndroid Build Coastguard Worker bc_file_flush(&vm->ferr, bc_flush_err);
4519*5a6e8488SAndroid Build Coastguard Worker }
4520*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG_CODE
4521