/*1* *****************************************************************************2*3* SPDX-License-Identifier: BSD-2-Clause4*5* Copyright (c) 2018-2025 Gavin D. Howard and contributors.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions are met:9*10* * Redistributions of source code must retain the above copyright notice, this11* list of conditions and the following disclaimer.12*13* * Redistributions in binary form must reproduce the above copyright notice,14* this list of conditions and the following disclaimer in the documentation15* and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"18* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE21* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS24* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN25* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)26* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE27* POSSIBILITY OF SUCH DAMAGE.28*29* *****************************************************************************30*31* Code for the number type.32*33*/3435#include <assert.h>36#include <ctype.h>37#include <stdbool.h>38#include <stdlib.h>39#include <string.h>40#include <setjmp.h>41#include <limits.h>4243#include <num.h>44#include <rand.h>45#include <vm.h>46#if BC_ENABLE_LIBRARY47#include <library.h>48#endif // BC_ENABLE_LIBRARY4950// Before you try to understand this code, see the development manual51// (manuals/development.md#numbers).5253static void54bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale);5556/**57* Multiply two numbers and throw a math error if they overflow.58* @param a The first operand.59* @param b The second operand.60* @return The product of the two operands.61*/62static inline size_t63bc_num_mulOverflow(size_t a, size_t b)64{65size_t res = a * b;66if (BC_ERR(BC_VM_MUL_OVERFLOW(a, b, res))) bc_err(BC_ERR_MATH_OVERFLOW);67return res;68}6970/**71* Conditionally negate @a n based on @a neg. Algorithm taken from72* https://graphics.stanford.edu/~seander/bithacks.html#ConditionalNegate .73* @param n The value to turn into a signed value and negate.74* @param neg The condition to negate or not.75*/76static inline ssize_t77bc_num_neg(size_t n, bool neg)78{79return (((ssize_t) n) ^ -((ssize_t) neg)) + neg;80}8182/**83* Compare a BcNum against zero.84* @param n The number to compare.85* @return -1 if the number is less than 0, 1 if greater, and 0 if equal.86*/87ssize_t88bc_num_cmpZero(const BcNum* n)89{90return bc_num_neg((n)->len != 0, BC_NUM_NEG(n));91}9293/**94* Return the number of integer limbs in a BcNum. This is the opposite of rdx.95* @param n The number to return the amount of integer limbs for.96* @return The amount of integer limbs in @a n.97*/98static inline size_t99bc_num_int(const BcNum* n)100{101return n->len ? n->len - BC_NUM_RDX_VAL(n) : 0;102}103104/**105* Expand a number's allocation capacity to at least req limbs.106* @param n The number to expand.107* @param req The number limbs to expand the allocation capacity to.108*/109static void110bc_num_expand(BcNum* restrict n, size_t req)111{112assert(n != NULL);113114req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;115116if (req > n->cap)117{118BC_SIG_LOCK;119120n->num = bc_vm_realloc(n->num, BC_NUM_SIZE(req));121n->cap = req;122123BC_SIG_UNLOCK;124}125}126127/**128* Set a number to 0 with the specified scale.129* @param n The number to set to zero.130* @param scale The scale to set the number to.131*/132static inline void133bc_num_setToZero(BcNum* restrict n, size_t scale)134{135assert(n != NULL);136n->scale = scale;137n->len = n->rdx = 0;138}139140void141bc_num_zero(BcNum* restrict n)142{143bc_num_setToZero(n, 0);144}145146void147bc_num_one(BcNum* restrict n)148{149bc_num_zero(n);150n->len = 1;151n->num[0] = 1;152}153154/**155* "Cleans" a number, which means reducing the length if the most significant156* limbs are zero.157* @param n The number to clean.158*/159static void160bc_num_clean(BcNum* restrict n)161{162// Reduce the length.163while (BC_NUM_NONZERO(n) && !n->num[n->len - 1])164{165n->len -= 1;166}167168// Special cases.169if (BC_NUM_ZERO(n)) n->rdx = 0;170else171{172// len must be at least as much as rdx.173size_t rdx = BC_NUM_RDX_VAL(n);174if (n->len < rdx) n->len = rdx;175}176}177178/**179* Returns the log base 10 of @a i. I could have done this with floating-point180* math, and in fact, I originally did. However, that was the only181* floating-point code in the entire codebase, and I decided I didn't want any.182* This is fast enough. Also, it might handle larger numbers better.183* @param i The number to return the log base 10 of.184* @return The log base 10 of @a i.185*/186static size_t187bc_num_log10(size_t i)188{189size_t len;190191for (len = 1; i; i /= BC_BASE, ++len)192{193continue;194}195196assert(len - 1 <= BC_BASE_DIGS + 1);197198return len - 1;199}200201/**202* Returns the number of decimal digits in a limb that are zero starting at the203* most significant digits. This basically returns how much of the limb is used.204* @param n The number.205* @return The number of decimal digits that are 0 starting at the most206* significant digits.207*/208static inline size_t209bc_num_zeroDigits(const BcDig* n)210{211assert(*n >= 0);212assert(((size_t) *n) < BC_BASE_POW);213return BC_BASE_DIGS - bc_num_log10((size_t) *n);214}215216/**217* Returns the power of 10 that the least significant limb should be multiplied218* by to put its digits in the right place. For example, if the scale only219* reaches 8 places into the limb, this will return 1 (because it should be220* multiplied by 10^1) to put the number in the correct place.221* @param scale The scale.222* @return The power of 10 that the least significant limb should be223* multiplied by224*/225static inline size_t226bc_num_leastSigPow(size_t scale)227{228size_t digs;229230digs = scale % BC_BASE_DIGS;231digs = digs != 0 ? BC_BASE_DIGS - digs : 0;232233return bc_num_pow10[digs];234}235236/**237* Return the total number of integer digits in a number. This is the opposite238* of scale, like bc_num_int() is the opposite of rdx.239* @param n The number.240* @return The number of integer digits in @a n.241*/242static size_t243bc_num_intDigits(const BcNum* n)244{245size_t digits = bc_num_int(n) * BC_BASE_DIGS;246if (digits > 0) digits -= bc_num_zeroDigits(n->num + n->len - 1);247return digits;248}249250/**251* Returns the number of limbs of a number that are non-zero starting at the252* most significant limbs. This expects that there are *no* integer limbs in the253* number because it is specifically to figure out how many zero limbs after the254* decimal place to ignore. If there are zero limbs after non-zero limbs, they255* are counted as non-zero limbs.256* @param n The number.257* @return The number of non-zero limbs after the decimal point.258*/259static size_t260bc_num_nonZeroLen(const BcNum* restrict n)261{262size_t i, len = n->len;263264assert(len == BC_NUM_RDX_VAL(n));265266for (i = len - 1; i < len && !n->num[i]; --i)267{268continue;269}270271assert(i + 1 > 0);272273return i + 1;274}275276#if BC_ENABLE_EXTRA_MATH277278/**279* Returns the power of 10 that a number with an absolute value less than 1280* needs to be multiplied by in order to be greater than 1 or less than -1.281* @param n The number.282* @return The power of 10 that a number greater than 1 and less than -1 must283* be multiplied by to be greater than 1 or less than -1.284*/285static size_t286bc_num_negPow10(const BcNum* restrict n)287{288// Figure out how many limbs after the decimal point is zero.289size_t i, places, idx = bc_num_nonZeroLen(n) - 1;290291places = 1;292293// Figure out how much in the last limb is zero.294for (i = BC_BASE_DIGS - 1; i < BC_BASE_DIGS; --i)295{296if (bc_num_pow10[i] > (BcBigDig) n->num[idx]) places += 1;297else break;298}299300// Calculate the combination of zero limbs and zero digits in the last301// limb.302return places + (BC_NUM_RDX_VAL(n) - (idx + 1)) * BC_BASE_DIGS;303}304305#endif // BC_ENABLE_EXTRA_MATH306307/**308* Performs a one-limb add with a carry.309* @param a The first limb.310* @param b The second limb.311* @param carry An in/out parameter; the carry in from the previous add and the312* carry out from this add.313* @return The resulting limb sum.314*/315static BcDig316bc_num_addDigits(BcDig a, BcDig b, bool* carry)317{318assert(((BcBigDig) BC_BASE_POW) * 2 == ((BcDig) BC_BASE_POW) * 2);319assert(a < BC_BASE_POW && a >= 0);320assert(b < BC_BASE_POW && b >= 0);321322a += b + *carry;323*carry = (a >= BC_BASE_POW);324if (*carry) a -= BC_BASE_POW;325326assert(a >= 0);327assert(a < BC_BASE_POW);328329return a;330}331332/**333* Performs a one-limb subtract with a carry.334* @param a The first limb.335* @param b The second limb.336* @param carry An in/out parameter; the carry in from the previous subtract337* and the carry out from this subtract.338* @return The resulting limb difference.339*/340static BcDig341bc_num_subDigits(BcDig a, BcDig b, bool* carry)342{343assert(a < BC_BASE_POW && a >= 0);344assert(b < BC_BASE_POW && b >= 0);345346b += *carry;347*carry = (a < b);348if (*carry) a += BC_BASE_POW;349350assert(a - b >= 0);351assert(a - b < BC_BASE_POW);352353return a - b;354}355356/**357* Add two BcDig arrays and store the result in the first array.358* @param a The first operand and out array.359* @param b The second operand.360* @param len The length of @a b.361*/362static void363bc_num_addArrays(BcDig* restrict a, const BcDig* restrict b, size_t len)364{365size_t i;366bool carry = false;367368for (i = 0; i < len; ++i)369{370a[i] = bc_num_addDigits(a[i], b[i], &carry);371}372373// Take care of the extra limbs in the bigger array.374for (; carry; ++i)375{376a[i] = bc_num_addDigits(a[i], 0, &carry);377}378}379380/**381* Subtract two BcDig arrays and store the result in the first array.382* @param a The first operand and out array.383* @param b The second operand.384* @param len The length of @a b.385*/386static void387bc_num_subArrays(BcDig* restrict a, const BcDig* restrict b, size_t len)388{389size_t i;390bool carry = false;391392for (i = 0; i < len; ++i)393{394a[i] = bc_num_subDigits(a[i], b[i], &carry);395}396397// Take care of the extra limbs in the bigger array.398for (; carry; ++i)399{400a[i] = bc_num_subDigits(a[i], 0, &carry);401}402}403404/**405* Multiply a BcNum array by a one-limb number. This is a faster version of406* multiplication for when we can use it.407* @param a The BcNum to multiply by the one-limb number.408* @param b The one limb of the one-limb number.409* @param c The return parameter.410*/411static void412bc_num_mulArray(const BcNum* restrict a, BcBigDig b, BcNum* restrict c)413{414size_t i;415BcBigDig carry = 0;416417assert(b <= BC_BASE_POW);418419// Make sure the return parameter is big enough.420if (a->len + 1 > c->cap) bc_num_expand(c, a->len + 1);421422// We want the entire return parameter to be zero for cleaning later.423// NOLINTNEXTLINE424memset(c->num, 0, BC_NUM_SIZE(c->cap));425426// Actual multiplication loop.427for (i = 0; i < a->len; ++i)428{429BcBigDig in = ((BcBigDig) a->num[i]) * b + carry;430c->num[i] = in % BC_BASE_POW;431carry = in / BC_BASE_POW;432}433434assert(carry < BC_BASE_POW);435436// Finishing touches.437c->num[i] = (BcDig) carry;438assert(c->num[i] >= 0 && c->num[i] < BC_BASE_POW);439c->len = a->len;440c->len += (carry != 0);441442bc_num_clean(c);443444// Postconditions.445assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));446assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);447assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);448}449450/**451* Divide a BcNum array by a one-limb number. This is a faster version of divide452* for when we can use it.453* @param a The BcNum to multiply by the one-limb number.454* @param b The one limb of the one-limb number.455* @param c The return parameter for the quotient.456* @param rem The return parameter for the remainder.457*/458static void459bc_num_divArray(const BcNum* restrict a, BcBigDig b, BcNum* restrict c,460BcBigDig* rem)461{462size_t i;463BcBigDig carry = 0;464465assert(c->cap >= a->len);466467// Actual division loop.468for (i = a->len - 1; i < a->len; --i)469{470BcBigDig in = ((BcBigDig) a->num[i]) + carry * BC_BASE_POW;471assert(in / b < BC_BASE_POW);472c->num[i] = (BcDig) (in / b);473assert(c->num[i] >= 0 && c->num[i] < BC_BASE_POW);474carry = in % b;475}476477// Finishing touches.478c->len = a->len;479bc_num_clean(c);480*rem = carry;481482// Postconditions.483assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));484assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);485assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);486}487488/**489* Compare two BcDig arrays and return >0 if @a b is greater, <0 if @a b is490* less, and 0 if equal. Both @a a and @a b must have the same length.491* @param a The first array.492* @param b The second array.493* @param len The minimum length of the arrays.494*/495static ssize_t496bc_num_compare(const BcDig* restrict a, const BcDig* restrict b, size_t len)497{498size_t i;499BcDig c = 0;500for (i = len - 1; i < len && !(c = a[i] - b[i]); --i)501{502continue;503}504return bc_num_neg(i + 1, c < 0);505}506507ssize_t508bc_num_cmp(const BcNum* a, const BcNum* b)509{510size_t i, min, a_int, b_int, diff, ardx, brdx;511BcDig* max_num;512BcDig* min_num;513bool a_max, neg = false;514ssize_t cmp;515516assert(a != NULL && b != NULL);517518// Same num? Equal.519if (a == b) return 0;520521// Easy cases.522if (BC_NUM_ZERO(a)) return bc_num_neg(b->len != 0, !BC_NUM_NEG(b));523if (BC_NUM_ZERO(b)) return bc_num_cmpZero(a);524if (BC_NUM_NEG(a))525{526if (BC_NUM_NEG(b)) neg = true;527else return -1;528}529else if (BC_NUM_NEG(b)) return 1;530531// Get the number of int limbs in each number and get the difference.532a_int = bc_num_int(a);533b_int = bc_num_int(b);534a_int -= b_int;535536// If there's a difference, then just return the comparison.537if (a_int) return neg ? -((ssize_t) a_int) : (ssize_t) a_int;538539// Get the rdx's and figure out the max.540ardx = BC_NUM_RDX_VAL(a);541brdx = BC_NUM_RDX_VAL(b);542a_max = (ardx > brdx);543544// Set variables based on the above.545if (a_max)546{547min = brdx;548diff = ardx - brdx;549max_num = a->num + diff;550min_num = b->num;551}552else553{554min = ardx;555diff = brdx - ardx;556max_num = b->num + diff;557min_num = a->num;558}559560// Do a full limb-by-limb comparison.561cmp = bc_num_compare(max_num, min_num, b_int + min);562563// If we found a difference, return it based on state.564if (cmp) return bc_num_neg((size_t) cmp, !a_max == !neg);565566// If there was no difference, then the final step is to check which number567// has greater or lesser limbs beyond the other's.568for (max_num -= diff, i = diff - 1; i < diff; --i)569{570if (max_num[i]) return bc_num_neg(1, !a_max == !neg);571}572573return 0;574}575576void577bc_num_truncate(BcNum* restrict n, size_t places)578{579size_t nrdx, places_rdx;580581if (!places) return;582583// Grab these needed values; places_rdx is the rdx equivalent to places like584// rdx is to scale.585nrdx = BC_NUM_RDX_VAL(n);586places_rdx = nrdx ? nrdx - BC_NUM_RDX(n->scale - places) : 0;587588// We cannot truncate more places than we have.589assert(places <= n->scale && (BC_NUM_ZERO(n) || places_rdx <= n->len));590591n->scale -= places;592BC_NUM_RDX_SET(n, nrdx - places_rdx);593594// Only when the number is nonzero do we need to do the hard stuff.595if (BC_NUM_NONZERO(n))596{597size_t pow;598599// This calculates how many decimal digits are in the least significant600// limb, then gets the power for that.601pow = bc_num_leastSigPow(n->scale);602603n->len -= places_rdx;604605// We have to move limbs to maintain invariants. The limbs must begin at606// the beginning of the BcNum array.607// NOLINTNEXTLINE608memmove(n->num, n->num + places_rdx, BC_NUM_SIZE(n->len));609610// Clear the lower part of the last digit.611if (BC_NUM_NONZERO(n)) n->num[0] -= n->num[0] % (BcDig) pow;612613bc_num_clean(n);614}615}616617void618bc_num_extend(BcNum* restrict n, size_t places)619{620size_t nrdx, places_rdx;621622if (!places) return;623624// Easy case with zero; set the scale.625if (BC_NUM_ZERO(n))626{627n->scale += places;628return;629}630631// Grab these needed values; places_rdx is the rdx equivalent to places like632// rdx is to scale.633nrdx = BC_NUM_RDX_VAL(n);634places_rdx = BC_NUM_RDX(places + n->scale) - nrdx;635636// This is the hard case. We need to expand the number, move the limbs, and637// set the limbs that were just cleared.638if (places_rdx)639{640bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));641// NOLINTNEXTLINE642memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len));643// NOLINTNEXTLINE644memset(n->num, 0, BC_NUM_SIZE(places_rdx));645}646647// Finally, set scale and rdx.648BC_NUM_RDX_SET(n, nrdx + places_rdx);649n->scale += places;650n->len += places_rdx;651652assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale));653}654655/**656* Retires (finishes) a multiplication or division operation.657*/658static void659bc_num_retireMul(BcNum* restrict n, size_t scale, bool neg1, bool neg2)660{661// Make sure scale is correct.662if (n->scale < scale) bc_num_extend(n, scale - n->scale);663else bc_num_truncate(n, n->scale - scale);664665bc_num_clean(n);666667// We need to ensure rdx is correct.668if (BC_NUM_NONZERO(n)) n->rdx = BC_NUM_NEG_VAL(n, !neg1 != !neg2);669}670671/**672* Splits a number into two BcNum's. This is used in Karatsuba.673* @param n The number to split.674* @param idx The index to split at.675* @param a An out parameter; the low part of @a n.676* @param b An out parameter; the high part of @a n.677*/678static void679bc_num_split(const BcNum* restrict n, size_t idx, BcNum* restrict a,680BcNum* restrict b)681{682// We want a and b to be clear.683assert(BC_NUM_ZERO(a));684assert(BC_NUM_ZERO(b));685686// The usual case.687if (idx < n->len)688{689// Set the fields first.690b->len = n->len - idx;691a->len = idx;692a->scale = b->scale = 0;693BC_NUM_RDX_SET(a, 0);694BC_NUM_RDX_SET(b, 0);695696assert(a->cap >= a->len);697assert(b->cap >= b->len);698699// Copy the arrays. This is not necessary for safety, but it is faster,700// for some reason.701// NOLINTNEXTLINE702memcpy(b->num, n->num + idx, BC_NUM_SIZE(b->len));703// NOLINTNEXTLINE704memcpy(a->num, n->num, BC_NUM_SIZE(idx));705706bc_num_clean(b);707}708// If the index is weird, just skip the split.709else bc_num_copy(a, n);710711bc_num_clean(a);712}713714/**715* Copies a number into another, but shifts the rdx so that the result number716* only sees the integer part of the source number.717* @param n The number to copy.718* @param r The result number with a shifted rdx, len, and num.719*/720static void721bc_num_shiftRdx(const BcNum* restrict n, BcNum* restrict r)722{723size_t rdx = BC_NUM_RDX_VAL(n);724725r->len = n->len - rdx;726r->cap = n->cap - rdx;727r->num = n->num + rdx;728729BC_NUM_RDX_SET_NEG(r, 0, BC_NUM_NEG(n));730r->scale = 0;731}732733/**734* Shifts a number so that all of the least significant limbs of the number are735* skipped. This must be undone by bc_num_unshiftZero().736* @param n The number to shift.737*/738static size_t739bc_num_shiftZero(BcNum* restrict n)740{741// This is volatile to quiet a GCC warning about longjmp() clobbering.742volatile size_t i;743744// If we don't have an integer, that is a problem, but it's also a bug745// because the caller should have set everything up right.746assert(!BC_NUM_RDX_VAL(n) || BC_NUM_ZERO(n));747748for (i = 0; i < n->len && !n->num[i]; ++i)749{750continue;751}752753n->len -= i;754n->num += i;755756return i;757}758759/**760* Undo the damage done by bc_num_unshiftZero(). This must be called like all761* cleanup functions: after a label used by setjmp() and longjmp().762* @param n The number to unshift.763* @param places_rdx The amount the number was originally shift.764*/765static void766bc_num_unshiftZero(BcNum* restrict n, size_t places_rdx)767{768n->len += places_rdx;769n->num -= places_rdx;770}771772/**773* Shifts the digits right within a number by no more than BC_BASE_DIGS - 1.774* This is the final step on shifting numbers with the shift operators. It775* depends on the caller to shift the limbs properly because all it does is776* ensure that the rdx point is realigned to be between limbs.777* @param n The number to shift digits in.778* @param dig The number of places to shift right.779*/780static void781bc_num_shift(BcNum* restrict n, BcBigDig dig)782{783size_t i, len = n->len;784BcBigDig carry = 0, pow;785BcDig* ptr = n->num;786787assert(dig < BC_BASE_DIGS);788789// Figure out the parameters for division.790pow = bc_num_pow10[dig];791dig = bc_num_pow10[BC_BASE_DIGS - dig];792793// Run a series of divisions and mods with carries across the entire number794// array. This effectively shifts everything over.795for (i = len - 1; i < len; --i)796{797BcBigDig in, temp;798in = ((BcBigDig) ptr[i]);799temp = carry * dig;800carry = in % pow;801ptr[i] = ((BcDig) (in / pow)) + (BcDig) temp;802assert(ptr[i] >= 0 && ptr[i] < BC_BASE_POW);803}804805assert(!carry);806}807808/**809* Shift a number left by a certain number of places. This is the workhorse of810* the left shift operator.811* @param n The number to shift left.812* @param places The amount of places to shift @a n left by.813*/814static void815bc_num_shiftLeft(BcNum* restrict n, size_t places)816{817BcBigDig dig;818size_t places_rdx;819bool shift;820821if (!places) return;822823// Make sure to grow the number if necessary.824if (places > n->scale)825{826size_t size = bc_vm_growSize(BC_NUM_RDX(places - n->scale), n->len);827if (size > SIZE_MAX - 1) bc_err(BC_ERR_MATH_OVERFLOW);828}829830// If zero, we can just set the scale and bail.831if (BC_NUM_ZERO(n))832{833if (n->scale >= places) n->scale -= places;834else n->scale = 0;835return;836}837838// When I changed bc to have multiple digits per limb, this was the hardest839// code to change. This and shift right. Make sure you understand this840// before attempting anything.841842// This is how many limbs we will shift.843dig = (BcBigDig) (places % BC_BASE_DIGS);844shift = (dig != 0);845846// Convert places to a rdx value.847places_rdx = BC_NUM_RDX(places);848849// If the number is not an integer, we need special care. The reason an850// integer doesn't is because left shift would only extend the integer,851// whereas a non-integer might have its fractional part eliminated or only852// partially eliminated.853if (n->scale)854{855size_t nrdx = BC_NUM_RDX_VAL(n);856857// If the number's rdx is bigger, that's the hard case.858if (nrdx >= places_rdx)859{860size_t mod = n->scale % BC_BASE_DIGS, revdig;861862// We want mod to be in the range [1, BC_BASE_DIGS], not863// [0, BC_BASE_DIGS).864mod = mod ? mod : BC_BASE_DIGS;865866// We need to reverse dig to get the actual number of digits.867revdig = dig ? BC_BASE_DIGS - dig : 0;868869// If the two overflow BC_BASE_DIGS, we need to move an extra place.870if (mod + revdig > BC_BASE_DIGS) places_rdx = 1;871else places_rdx = 0;872}873else places_rdx -= nrdx;874}875876// If this is non-zero, we need an extra place, so expand, move, and set.877if (places_rdx)878{879bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));880// NOLINTNEXTLINE881memmove(n->num + places_rdx, n->num, BC_NUM_SIZE(n->len));882// NOLINTNEXTLINE883memset(n->num, 0, BC_NUM_SIZE(places_rdx));884n->len += places_rdx;885}886887// Set the scale appropriately.888if (places > n->scale)889{890n->scale = 0;891BC_NUM_RDX_SET(n, 0);892}893else894{895n->scale -= places;896BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));897}898899// Finally, shift within limbs.900if (shift) bc_num_shift(n, BC_BASE_DIGS - dig);901902bc_num_clean(n);903}904905void906bc_num_shiftRight(BcNum* restrict n, size_t places)907{908BcBigDig dig;909size_t places_rdx, scale, scale_mod, int_len, expand;910bool shift;911912if (!places) return;913914// If zero, we can just set the scale and bail.915if (BC_NUM_ZERO(n))916{917n->scale += places;918bc_num_expand(n, BC_NUM_RDX(n->scale));919return;920}921922// Amount within a limb we have to shift by.923dig = (BcBigDig) (places % BC_BASE_DIGS);924shift = (dig != 0);925926scale = n->scale;927928// Figure out how the scale is affected.929scale_mod = scale % BC_BASE_DIGS;930scale_mod = scale_mod ? scale_mod : BC_BASE_DIGS;931932// We need to know the int length and rdx for places.933int_len = bc_num_int(n);934places_rdx = BC_NUM_RDX(places);935936// If we are going to shift past a limb boundary or not, set accordingly.937if (scale_mod + dig > BC_BASE_DIGS)938{939expand = places_rdx - 1;940places_rdx = 1;941}942else943{944expand = places_rdx;945places_rdx = 0;946}947948// Clamp expanding.949if (expand > int_len) expand -= int_len;950else expand = 0;951952// Extend, expand, and zero.953bc_num_extend(n, places_rdx * BC_BASE_DIGS);954bc_num_expand(n, bc_vm_growSize(expand, n->len));955// NOLINTNEXTLINE956memset(n->num + n->len, 0, BC_NUM_SIZE(expand));957958// Set the fields.959n->len += expand;960n->scale = 0;961BC_NUM_RDX_SET(n, 0);962963// Finally, shift within limbs.964if (shift) bc_num_shift(n, dig);965966n->scale = scale + places;967BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));968969bc_num_clean(n);970971assert(BC_NUM_RDX_VAL(n) <= n->len && n->len <= n->cap);972assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale));973}974975/**976* Tests if a number is a integer with scale or not. Returns true if the number977* is not an integer. If it is, its integer shifted form is copied into the978* result parameter for use where only integers are allowed.979* @param n The integer to test and shift.980* @param r The number to store the shifted result into. This number should981* *not* be allocated.982* @return True if the number is a non-integer, false otherwise.983*/984static bool985bc_num_nonInt(const BcNum* restrict n, BcNum* restrict r)986{987bool zero;988size_t i, rdx = BC_NUM_RDX_VAL(n);989990if (!rdx)991{992// NOLINTNEXTLINE993memcpy(r, n, sizeof(BcNum));994return false;995}996997zero = true;998999for (i = 0; zero && i < rdx; ++i)1000{1001zero = (n->num[i] == 0);1002}10031004if (BC_ERR(!zero)) return true;10051006bc_num_shiftRdx(n, r);10071008return false;1009}10101011#if BC_ENABLE_EXTRA_MATH10121013/**1014* Execute common code for an operater that needs an integer for the second1015* operand and return the integer operand as a BcBigDig.1016* @param a The first operand.1017* @param b The second operand.1018* @param c The result operand.1019* @return The second operand as a hardware integer.1020*/1021static BcBigDig1022bc_num_intop(const BcNum* a, const BcNum* b, BcNum* restrict c)1023{1024BcNum temp;10251026#if BC_GCC1027temp.len = 0;1028temp.rdx = 0;1029temp.num = NULL;1030#endif // BC_GCC10311032if (BC_ERR(bc_num_nonInt(b, &temp))) bc_err(BC_ERR_MATH_NON_INTEGER);10331034bc_num_copy(c, a);10351036return bc_num_bigdig(&temp);1037}1038#endif // BC_ENABLE_EXTRA_MATH10391040/**1041* This is the actual implementation of add *and* subtract. Since this function1042* doesn't need to use scale (per the bc spec), I am hijacking it to say whether1043* it's doing an add or a subtract. And then I convert substraction to addition1044* of negative second operand. This is a BcNumBinOp function.1045* @param a The first operand.1046* @param b The second operand.1047* @param c The return parameter.1048* @param sub Non-zero for a subtract, zero for an add.1049*/1050static void1051bc_num_as(BcNum* a, BcNum* b, BcNum* restrict c, size_t sub)1052{1053BcDig* ptr_c;1054BcDig* ptr_l;1055BcDig* ptr_r;1056size_t i, min_rdx, max_rdx, diff, a_int, b_int, min_len, max_len, max_int;1057size_t len_l, len_r, ardx, brdx;1058bool b_neg, do_sub, do_rev_sub, carry, c_neg;10591060if (BC_NUM_ZERO(b))1061{1062bc_num_copy(c, a);1063return;1064}10651066if (BC_NUM_ZERO(a))1067{1068bc_num_copy(c, b);1069c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(b) != sub);1070return;1071}10721073// Invert sign of b if it is to be subtracted. This operation must1074// precede the tests for any of the operands being zero.1075b_neg = (BC_NUM_NEG(b) != sub);10761077// Figure out if we will actually add the numbers if their signs are equal1078// or subtract.1079do_sub = (BC_NUM_NEG(a) != b_neg);10801081a_int = bc_num_int(a);1082b_int = bc_num_int(b);1083max_int = BC_MAX(a_int, b_int);10841085// Figure out which number will have its last limbs copied (for addition) or1086// subtracted (for subtraction).1087ardx = BC_NUM_RDX_VAL(a);1088brdx = BC_NUM_RDX_VAL(b);1089min_rdx = BC_MIN(ardx, brdx);1090max_rdx = BC_MAX(ardx, brdx);1091diff = max_rdx - min_rdx;10921093max_len = max_int + max_rdx;10941095// Figure out the max length and also if we need to reverse the operation.1096if (do_sub)1097{1098// Check whether b has to be subtracted from a or a from b.1099if (a_int != b_int) do_rev_sub = (a_int < b_int);1100else if (ardx > brdx)1101{1102do_rev_sub = (bc_num_compare(a->num + diff, b->num, b->len) < 0);1103}1104else do_rev_sub = (bc_num_compare(a->num, b->num + diff, a->len) <= 0);1105}1106else1107{1108// The result array of the addition might come out one element1109// longer than the bigger of the operand arrays.1110max_len += 1;1111do_rev_sub = (a_int < b_int);1112}11131114assert(max_len <= c->cap);11151116// Cache values for simple code later.1117if (do_rev_sub)1118{1119ptr_l = b->num;1120ptr_r = a->num;1121len_l = b->len;1122len_r = a->len;1123}1124else1125{1126ptr_l = a->num;1127ptr_r = b->num;1128len_l = a->len;1129len_r = b->len;1130}11311132ptr_c = c->num;1133carry = false;11341135// This is true if the numbers have a different number of limbs after the1136// decimal point.1137if (diff)1138{1139// If the rdx values of the operands do not match, the result will1140// have low end elements that are the positive or negative trailing1141// elements of the operand with higher rdx value.1142if ((ardx > brdx) != do_rev_sub)1143{1144// !do_rev_sub && ardx > brdx || do_rev_sub && brdx > ardx1145// The left operand has BcDig values that need to be copied,1146// either from a or from b (in case of a reversed subtraction).1147// NOLINTNEXTLINE1148memcpy(ptr_c, ptr_l, BC_NUM_SIZE(diff));1149ptr_l += diff;1150len_l -= diff;1151}1152else1153{1154// The right operand has BcDig values that need to be copied1155// or subtracted from zero (in case of a subtraction).1156if (do_sub)1157{1158// do_sub (do_rev_sub && ardx > brdx ||1159// !do_rev_sub && brdx > ardx)1160for (i = 0; i < diff; i++)1161{1162ptr_c[i] = bc_num_subDigits(0, ptr_r[i], &carry);1163}1164}1165else1166{1167// !do_sub && brdx > ardx1168// NOLINTNEXTLINE1169memcpy(ptr_c, ptr_r, BC_NUM_SIZE(diff));1170}11711172// Future code needs to ignore the limbs we just did.1173ptr_r += diff;1174len_r -= diff;1175}11761177// The return value pointer needs to ignore what we just did.1178ptr_c += diff;1179}11801181// This is the length that can be directly added/subtracted.1182min_len = BC_MIN(len_l, len_r);11831184// After dealing with possible low array elements that depend on only one1185// operand above, the actual add or subtract can be performed as if the rdx1186// of both operands was the same.1187//1188// Inlining takes care of eliminating constant zero arguments to1189// addDigit/subDigit (checked in disassembly of resulting bc binary1190// compiled with gcc and clang).1191if (do_sub)1192{1193// Actual subtraction.1194for (i = 0; i < min_len; ++i)1195{1196ptr_c[i] = bc_num_subDigits(ptr_l[i], ptr_r[i], &carry);1197}11981199// Finishing the limbs beyond the direct subtraction.1200for (; i < len_l; ++i)1201{1202ptr_c[i] = bc_num_subDigits(ptr_l[i], 0, &carry);1203}1204}1205else1206{1207// Actual addition.1208for (i = 0; i < min_len; ++i)1209{1210ptr_c[i] = bc_num_addDigits(ptr_l[i], ptr_r[i], &carry);1211}12121213// Finishing the limbs beyond the direct addition.1214for (; i < len_l; ++i)1215{1216ptr_c[i] = bc_num_addDigits(ptr_l[i], 0, &carry);1217}12181219// Addition can create an extra limb. We take care of that here.1220ptr_c[i] = bc_num_addDigits(0, 0, &carry);1221}12221223assert(carry == false);12241225// The result has the same sign as a, unless the operation was a1226// reverse subtraction (b - a).1227c_neg = BC_NUM_NEG(a) != (do_sub && do_rev_sub);1228BC_NUM_RDX_SET_NEG(c, max_rdx, c_neg);1229c->len = max_len;1230c->scale = BC_MAX(a->scale, b->scale);12311232bc_num_clean(c);1233}12341235/**1236* The simple multiplication that karatsuba dishes out to when the length of the1237* numbers gets low enough. This doesn't use scale because it treats the1238* operands as though they are integers.1239* @param a The first operand.1240* @param b The second operand.1241* @param c The return parameter.1242*/1243static void1244bc_num_m_simp(const BcNum* a, const BcNum* b, BcNum* restrict c)1245{1246size_t i, alen = a->len, blen = b->len, clen;1247BcDig* ptr_a = a->num;1248BcDig* ptr_b = b->num;1249BcDig* ptr_c;1250BcBigDig sum = 0, carry = 0;12511252assert(sizeof(sum) >= sizeof(BcDig) * 2);1253assert(!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b));12541255// Make sure c is big enough.1256clen = bc_vm_growSize(alen, blen);1257bc_num_expand(c, bc_vm_growSize(clen, 1));12581259// If we don't memset, then we might have uninitialized data use later.1260ptr_c = c->num;1261// NOLINTNEXTLINE1262memset(ptr_c, 0, BC_NUM_SIZE(c->cap));12631264// This is the actual multiplication loop. It uses the lattice form of long1265// multiplication (see the explanation on the web page at1266// https://knilt.arcc.albany.edu/What_is_Lattice_Multiplication or the1267// explanation at Wikipedia).1268for (i = 0; i < clen; ++i)1269{1270ssize_t sidx = (ssize_t) (i - blen + 1);1271size_t j, k;12721273// These are the start indices.1274j = (size_t) BC_MAX(0, sidx);1275k = BC_MIN(i, blen - 1);12761277// On every iteration of this loop, a multiplication happens, then the1278// sum is automatically calculated.1279for (; j < alen && k < blen; ++j, --k)1280{1281sum += ((BcBigDig) ptr_a[j]) * ((BcBigDig) ptr_b[k]);12821283if (sum >= ((BcBigDig) BC_BASE_POW) * BC_BASE_POW)1284{1285carry += sum / BC_BASE_POW;1286sum %= BC_BASE_POW;1287}1288}12891290// Calculate the carry.1291if (sum >= BC_BASE_POW)1292{1293carry += sum / BC_BASE_POW;1294sum %= BC_BASE_POW;1295}12961297// Store and set up for next iteration.1298ptr_c[i] = (BcDig) sum;1299assert(ptr_c[i] < BC_BASE_POW);1300sum = carry;1301carry = 0;1302}13031304// This should always be true because there should be no carry on the last1305// digit; multiplication never goes above the sum of both lengths.1306assert(!sum);13071308c->len = clen;1309}13101311/**1312* Does a shifted add or subtract for Karatsuba below. This calls either1313* bc_num_addArrays() or bc_num_subArrays().1314* @param n An in/out parameter; the first operand and return parameter.1315* @param a The second operand.1316* @param shift The amount to shift @a n by when adding/subtracting.1317* @param op The function to call, either bc_num_addArrays() or1318* bc_num_subArrays().1319*/1320static void1321bc_num_shiftAddSub(BcNum* restrict n, const BcNum* restrict a, size_t shift,1322BcNumShiftAddOp op)1323{1324assert(n->len >= shift + a->len);1325assert(!BC_NUM_RDX_VAL(n) && !BC_NUM_RDX_VAL(a));1326op(n->num + shift, a->num, a->len);1327}13281329/**1330* Implements the Karatsuba algorithm.1331*/1332static void1333bc_num_k(const BcNum* a, const BcNum* b, BcNum* restrict c)1334{1335size_t max, max2, total;1336BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;1337BcDig* digs;1338BcDig* dig_ptr;1339BcNumShiftAddOp op;1340bool aone = BC_NUM_ONE(a);1341#if BC_ENABLE_LIBRARY1342BcVm* vm = bcl_getspecific();1343#endif // BC_ENABLE_LIBRARY13441345assert(BC_NUM_ZERO(c));13461347if (BC_NUM_ZERO(a) || BC_NUM_ZERO(b)) return;13481349if (aone || BC_NUM_ONE(b))1350{1351bc_num_copy(c, aone ? b : a);1352if ((aone && BC_NUM_NEG(a)) || BC_NUM_NEG(b)) BC_NUM_NEG_TGL(c);1353return;1354}13551356// Shell out to the simple algorithm with certain conditions.1357if (a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN)1358{1359bc_num_m_simp(a, b, c);1360return;1361}13621363// We need to calculate the max size of the numbers that can result from the1364// operations.1365max = BC_MAX(a->len, b->len);1366max = BC_MAX(max, BC_NUM_DEF_SIZE);1367max2 = (max + 1) / 2;13681369// Calculate the space needed for all of the temporary allocations. We do1370// this to just allocate once.1371total = bc_vm_arraySize(BC_NUM_KARATSUBA_ALLOCS, max);13721373BC_SIG_LOCK;13741375// Allocate space for all of the temporaries.1376digs = dig_ptr = bc_vm_malloc(BC_NUM_SIZE(total));13771378// Set up the temporaries.1379bc_num_setup(&l1, dig_ptr, max);1380dig_ptr += max;1381bc_num_setup(&h1, dig_ptr, max);1382dig_ptr += max;1383bc_num_setup(&l2, dig_ptr, max);1384dig_ptr += max;1385bc_num_setup(&h2, dig_ptr, max);1386dig_ptr += max;1387bc_num_setup(&m1, dig_ptr, max);1388dig_ptr += max;1389bc_num_setup(&m2, dig_ptr, max);13901391// Some temporaries need the ability to grow, so we allocate them1392// separately.1393max = bc_vm_growSize(max, 1);1394bc_num_init(&z0, max);1395bc_num_init(&z1, max);1396bc_num_init(&z2, max);1397max = bc_vm_growSize(max, max) + 1;1398bc_num_init(&temp, max);13991400BC_SETJMP_LOCKED(vm, err);14011402BC_SIG_UNLOCK;14031404// First, set up c.1405bc_num_expand(c, max);1406c->len = max;1407// NOLINTNEXTLINE1408memset(c->num, 0, BC_NUM_SIZE(c->len));14091410// Split the parameters.1411bc_num_split(a, max2, &l1, &h1);1412bc_num_split(b, max2, &l2, &h2);14131414// Do the subtraction.1415bc_num_sub(&h1, &l1, &m1, 0);1416bc_num_sub(&l2, &h2, &m2, 0);14171418// The if statements below are there for efficiency reasons. The best way to1419// understand them is to understand the Karatsuba algorithm because now that1420// the ollocations and splits are done, the algorithm is pretty1421// straightforward.14221423if (BC_NUM_NONZERO(&h1) && BC_NUM_NONZERO(&h2))1424{1425assert(BC_NUM_RDX_VALID_NP(h1));1426assert(BC_NUM_RDX_VALID_NP(h2));14271428bc_num_m(&h1, &h2, &z2, 0);1429bc_num_clean(&z2);14301431bc_num_shiftAddSub(c, &z2, max2 * 2, bc_num_addArrays);1432bc_num_shiftAddSub(c, &z2, max2, bc_num_addArrays);1433}14341435if (BC_NUM_NONZERO(&l1) && BC_NUM_NONZERO(&l2))1436{1437assert(BC_NUM_RDX_VALID_NP(l1));1438assert(BC_NUM_RDX_VALID_NP(l2));14391440bc_num_m(&l1, &l2, &z0, 0);1441bc_num_clean(&z0);14421443bc_num_shiftAddSub(c, &z0, max2, bc_num_addArrays);1444bc_num_shiftAddSub(c, &z0, 0, bc_num_addArrays);1445}14461447if (BC_NUM_NONZERO(&m1) && BC_NUM_NONZERO(&m2))1448{1449assert(BC_NUM_RDX_VALID_NP(m1));1450assert(BC_NUM_RDX_VALID_NP(m1));14511452bc_num_m(&m1, &m2, &z1, 0);1453bc_num_clean(&z1);14541455op = (BC_NUM_NEG_NP(m1) != BC_NUM_NEG_NP(m2)) ?1456bc_num_subArrays :1457bc_num_addArrays;1458bc_num_shiftAddSub(c, &z1, max2, op);1459}14601461err:1462BC_SIG_MAYLOCK;1463free(digs);1464bc_num_free(&temp);1465bc_num_free(&z2);1466bc_num_free(&z1);1467bc_num_free(&z0);1468BC_LONGJMP_CONT(vm);1469}14701471/**1472* Does checks for Karatsuba. It also changes things to ensure that the1473* Karatsuba and simple multiplication can treat the numbers as integers. This1474* is a BcNumBinOp function.1475* @param a The first operand.1476* @param b The second operand.1477* @param c The return parameter.1478* @param scale The current scale.1479*/1480static void1481bc_num_m(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)1482{1483BcNum cpa, cpb;1484size_t ascale, bscale, ardx, brdx, zero, len, rscale;1485// These are meant to quiet warnings on GCC about longjmp() clobbering.1486// The problem is real here.1487size_t scale1, scale2, realscale;1488// These are meant to quiet the GCC longjmp() clobbering, even though it1489// does not apply here.1490volatile size_t azero;1491volatile size_t bzero;1492#if BC_ENABLE_LIBRARY1493BcVm* vm = bcl_getspecific();1494#endif // BC_ENABLE_LIBRARY14951496assert(BC_NUM_RDX_VALID(a));1497assert(BC_NUM_RDX_VALID(b));14981499bc_num_zero(c);15001501ascale = a->scale;1502bscale = b->scale;15031504// This sets the final scale according to the bc spec.1505scale1 = BC_MAX(scale, ascale);1506scale2 = BC_MAX(scale1, bscale);1507rscale = ascale + bscale;1508realscale = BC_MIN(rscale, scale2);15091510// If this condition is true, we can use bc_num_mulArray(), which would be1511// much faster.1512if ((a->len == 1 || b->len == 1) && !a->rdx && !b->rdx)1513{1514BcNum* operand;1515BcBigDig dig;15161517// Set the correct operands.1518if (a->len == 1)1519{1520dig = (BcBigDig) a->num[0];1521operand = b;1522}1523else1524{1525dig = (BcBigDig) b->num[0];1526operand = a;1527}15281529bc_num_mulArray(operand, dig, c);15301531// Need to make sure the sign is correct.1532if (BC_NUM_NONZERO(c))1533{1534c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(a) != BC_NUM_NEG(b));1535}15361537return;1538}15391540assert(BC_NUM_RDX_VALID(a));1541assert(BC_NUM_RDX_VALID(b));15421543BC_SIG_LOCK;15441545// We need copies because of all of the mutation needed to make Karatsuba1546// think the numbers are integers.1547bc_num_init(&cpa, a->len + BC_NUM_RDX_VAL(a));1548bc_num_init(&cpb, b->len + BC_NUM_RDX_VAL(b));15491550BC_SETJMP_LOCKED(vm, init_err);15511552BC_SIG_UNLOCK;15531554bc_num_copy(&cpa, a);1555bc_num_copy(&cpb, b);15561557assert(BC_NUM_RDX_VALID_NP(cpa));1558assert(BC_NUM_RDX_VALID_NP(cpb));15591560BC_NUM_NEG_CLR_NP(cpa);1561BC_NUM_NEG_CLR_NP(cpb);15621563assert(BC_NUM_RDX_VALID_NP(cpa));1564assert(BC_NUM_RDX_VALID_NP(cpb));15651566// These are what makes them appear like integers.1567ardx = BC_NUM_RDX_VAL_NP(cpa) * BC_BASE_DIGS;1568bc_num_shiftLeft(&cpa, ardx);15691570brdx = BC_NUM_RDX_VAL_NP(cpb) * BC_BASE_DIGS;1571bc_num_shiftLeft(&cpb, brdx);15721573// We need to reset the jump here because azero and bzero are used in the1574// cleanup, and local variables are not guaranteed to be the same after a1575// jump.1576BC_SIG_LOCK;15771578BC_UNSETJMP(vm);15791580// We want to ignore zero limbs.1581azero = bc_num_shiftZero(&cpa);1582bzero = bc_num_shiftZero(&cpb);15831584BC_SETJMP_LOCKED(vm, err);15851586BC_SIG_UNLOCK;15871588bc_num_clean(&cpa);1589bc_num_clean(&cpb);15901591bc_num_k(&cpa, &cpb, c);15921593// The return parameter needs to have its scale set. This is the start. It1594// also needs to be shifted by the same amount as a and b have limbs after1595// the decimal point.1596zero = bc_vm_growSize(azero, bzero);1597len = bc_vm_growSize(c->len, zero);15981599bc_num_expand(c, len);16001601// Shift c based on the limbs after the decimal point in a and b.1602bc_num_shiftLeft(c, (len - c->len) * BC_BASE_DIGS);1603bc_num_shiftRight(c, ardx + brdx);16041605bc_num_retireMul(c, realscale, BC_NUM_NEG(a), BC_NUM_NEG(b));16061607err:1608BC_SIG_MAYLOCK;1609bc_num_unshiftZero(&cpb, bzero);1610bc_num_unshiftZero(&cpa, azero);1611init_err:1612BC_SIG_MAYLOCK;1613bc_num_free(&cpb);1614bc_num_free(&cpa);1615BC_LONGJMP_CONT(vm);1616}16171618/**1619* Returns true if the BcDig array has non-zero limbs, false otherwise.1620* @param a The array to test.1621* @param len The length of the array.1622* @return True if @a has any non-zero limbs, false otherwise.1623*/1624static bool1625bc_num_nonZeroDig(BcDig* restrict a, size_t len)1626{1627size_t i;16281629for (i = len - 1; i < len; --i)1630{1631if (a[i] != 0) return true;1632}16331634return false;1635}16361637/**1638* Compares a BcDig array against a BcNum. This is especially suited for1639* division. Returns >0 if @a a is greater than @a b, <0 if it is less, and =01640* if they are equal.1641* @param a The array.1642* @param b The number.1643* @param len The length to assume the arrays are. This is always less than the1644* actual length because of how this is implemented.1645*/1646static ssize_t1647bc_num_divCmp(const BcDig* a, const BcNum* b, size_t len)1648{1649ssize_t cmp;16501651if (b->len > len && a[len]) cmp = bc_num_compare(a, b->num, len + 1);1652else if (b->len <= len)1653{1654if (a[len]) cmp = 1;1655else cmp = bc_num_compare(a, b->num, len);1656}1657else cmp = -1;16581659return cmp;1660}16611662/**1663* Extends the two operands of a division by BC_BASE_DIGS minus the number of1664* digits in the divisor estimate. In other words, it is shifting the numbers in1665* order to force the divisor estimate to fill the limb.1666* @param a The first operand.1667* @param b The second operand.1668* @param divisor The divisor estimate.1669*/1670static void1671bc_num_divExtend(BcNum* restrict a, BcNum* restrict b, BcBigDig divisor)1672{1673size_t pow;16741675assert(divisor < BC_BASE_POW);16761677pow = BC_BASE_DIGS - bc_num_log10((size_t) divisor);16781679bc_num_shiftLeft(a, pow);1680bc_num_shiftLeft(b, pow);1681}16821683/**1684* Actually does division. This is a rewrite of my original code by Stefan Esser1685* from FreeBSD.1686* @param a The first operand.1687* @param b The second operand.1688* @param c The return parameter.1689* @param scale The current scale.1690*/1691static void1692bc_num_d_long(BcNum* restrict a, BcNum* restrict b, BcNum* restrict c,1693size_t scale)1694{1695BcBigDig divisor;1696size_t i, rdx;1697// This is volatile and len 2 and reallen exist to quiet the GCC warning1698// about clobbering on longjmp(). This one is possible, I think.1699volatile size_t len;1700size_t len2, reallen;1701// This is volatile and realend exists to quiet the GCC warning about1702// clobbering on longjmp(). This one is possible, I think.1703volatile size_t end;1704size_t realend;1705BcNum cpb;1706// This is volatile and realnonzero exists to quiet the GCC warning about1707// clobbering on longjmp(). This one is possible, I think.1708volatile bool nonzero;1709bool realnonzero;1710#if BC_ENABLE_LIBRARY1711BcVm* vm = bcl_getspecific();1712#endif // BC_ENABLE_LIBRARY17131714assert(b->len < a->len);17151716len = b->len;1717end = a->len - len;17181719assert(len >= 1);17201721// This is a final time to make sure c is big enough and that its array is1722// properly zeroed.1723bc_num_expand(c, a->len);1724// NOLINTNEXTLINE1725memset(c->num, 0, c->cap * sizeof(BcDig));17261727// Setup.1728BC_NUM_RDX_SET(c, BC_NUM_RDX_VAL(a));1729c->scale = a->scale;1730c->len = a->len;17311732// This is pulling the most significant limb of b in order to establish a1733// good "estimate" for the actual divisor.1734divisor = (BcBigDig) b->num[len - 1];17351736// The entire bit of code in this if statement is to tighten the estimate of1737// the divisor. The condition asks if b has any other non-zero limbs.1738if (len > 1 && bc_num_nonZeroDig(b->num, len - 1))1739{1740// This takes a little bit of understanding. The "10*BC_BASE_DIGS/6+1"1741// results in either 16 for 64-bit 9-digit limbs or 7 for 32-bit 4-digit1742// limbs. Then it shifts a 1 by that many, which in both cases, puts the1743// result above *half* of the max value a limb can store. Basically,1744// this quickly calculates if the divisor is greater than half the max1745// of a limb.1746nonzero = (divisor > 1 << ((10 * BC_BASE_DIGS) / 6 + 1));17471748// If the divisor is *not* greater than half the limb...1749if (!nonzero)1750{1751// Extend the parameters by the number of missing digits in the1752// divisor.1753bc_num_divExtend(a, b, divisor);17541755// Check bc_num_d(). In there, we grow a again and again. We do it1756// again here; we *always* want to be sure it is big enough.1757len2 = BC_MAX(a->len, b->len);1758bc_num_expand(a, len2 + 1);17591760// Make a have a zero most significant limb to match the len.1761if (len2 + 1 > a->len) a->len = len2 + 1;17621763// Grab the new divisor estimate, new because the shift has made it1764// different.1765reallen = b->len;1766realend = a->len - reallen;1767divisor = (BcBigDig) b->num[reallen - 1];17681769realnonzero = bc_num_nonZeroDig(b->num, reallen - 1);1770}1771else1772{1773realend = end;1774realnonzero = nonzero;1775}1776}1777else1778{1779realend = end;1780realnonzero = false;1781}17821783// If b has other nonzero limbs, we want the divisor to be one higher, so1784// that it is an upper bound.1785divisor += realnonzero;17861787// Make sure c can fit the new length.1788bc_num_expand(c, a->len);1789// NOLINTNEXTLINE1790memset(c->num, 0, BC_NUM_SIZE(c->cap));17911792assert(c->scale >= scale);1793rdx = BC_NUM_RDX_VAL(c) - BC_NUM_RDX(scale);17941795BC_SIG_LOCK;17961797bc_num_init(&cpb, len + 1);17981799BC_SETJMP_LOCKED(vm, err);18001801BC_SIG_UNLOCK;18021803// This is the actual division loop.1804for (i = realend - 1; i < realend && i >= rdx && BC_NUM_NONZERO(a); --i)1805{1806ssize_t cmp;1807BcDig* n;1808BcBigDig result;18091810n = a->num + i;1811assert(n >= a->num);1812result = 0;18131814cmp = bc_num_divCmp(n, b, len);18151816// This is true if n is greater than b, which means that division can1817// proceed, so this inner loop is the part that implements one instance1818// of the division.1819while (cmp >= 0)1820{1821BcBigDig n1, dividend, quotient;18221823// These should be named obviously enough. Just imagine that it's a1824// division of one limb. Because that's what it is.1825n1 = (BcBigDig) n[len];1826dividend = n1 * BC_BASE_POW + (BcBigDig) n[len - 1];1827quotient = (dividend / divisor);18281829// If this is true, then we can just subtract. Remember: setting1830// quotient to 1 is not bad because we already know that n is1831// greater than b.1832if (quotient <= 1)1833{1834quotient = 1;1835bc_num_subArrays(n, b->num, len);1836}1837else1838{1839assert(quotient <= BC_BASE_POW);18401841// We need to multiply and subtract for a quotient above 1.1842bc_num_mulArray(b, (BcBigDig) quotient, &cpb);1843bc_num_subArrays(n, cpb.num, cpb.len);1844}18451846// The result is the *real* quotient, by the way, but it might take1847// multiple trips around this loop to get it.1848result += quotient;1849assert(result <= BC_BASE_POW);18501851// And here's why it might take multiple trips: n might *still* be1852// greater than b. So we have to loop again. That's what this is1853// setting up for: the condition of the while loop.1854if (realnonzero) cmp = bc_num_divCmp(n, b, len);1855else cmp = -1;1856}18571858assert(result < BC_BASE_POW);18591860// Store the actual limb quotient.1861c->num[i] = (BcDig) result;1862}18631864err:1865BC_SIG_MAYLOCK;1866bc_num_free(&cpb);1867BC_LONGJMP_CONT(vm);1868}18691870/**1871* Implements division. This is a BcNumBinOp function.1872* @param a The first operand.1873* @param b The second operand.1874* @param c The return parameter.1875* @param scale The current scale.1876*/1877static void1878bc_num_d(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)1879{1880size_t len, cpardx;1881BcNum cpa, cpb;1882#if BC_ENABLE_LIBRARY1883BcVm* vm = bcl_getspecific();1884#endif // BC_ENABLE_LIBRARY18851886if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);18871888if (BC_NUM_ZERO(a))1889{1890bc_num_setToZero(c, scale);1891return;1892}18931894if (BC_NUM_ONE(b))1895{1896bc_num_copy(c, a);1897bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));1898return;1899}19001901// If this is true, we can use bc_num_divArray(), which would be faster.1902if (!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale)1903{1904BcBigDig rem;1905bc_num_divArray(a, (BcBigDig) b->num[0], c, &rem);1906bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));1907return;1908}19091910len = bc_num_divReq(a, b, scale);19111912BC_SIG_LOCK;19131914// Initialize copies of the parameters. We want the length of the first1915// operand copy to be as big as the result because of the way the division1916// is implemented.1917bc_num_init(&cpa, len);1918bc_num_copy(&cpa, a);1919bc_num_createCopy(&cpb, b);19201921BC_SETJMP_LOCKED(vm, err);19221923BC_SIG_UNLOCK;19241925len = b->len;19261927// Like the above comment, we want the copy of the first parameter to be1928// larger than the second parameter.1929if (len > cpa.len)1930{1931bc_num_expand(&cpa, bc_vm_growSize(len, 2));1932bc_num_extend(&cpa, (len - cpa.len) * BC_BASE_DIGS);1933}19341935cpardx = BC_NUM_RDX_VAL_NP(cpa);1936cpa.scale = cpardx * BC_BASE_DIGS;19371938// This is just setting up the scale in preparation for the division.1939bc_num_extend(&cpa, b->scale);1940cpardx = BC_NUM_RDX_VAL_NP(cpa) - BC_NUM_RDX(b->scale);1941BC_NUM_RDX_SET_NP(cpa, cpardx);1942cpa.scale = cpardx * BC_BASE_DIGS;19431944// Once again, just setting things up, this time to match scale.1945if (scale > cpa.scale)1946{1947bc_num_extend(&cpa, scale);1948cpardx = BC_NUM_RDX_VAL_NP(cpa);1949cpa.scale = cpardx * BC_BASE_DIGS;1950}19511952// Grow if necessary.1953if (cpa.cap == cpa.len) bc_num_expand(&cpa, bc_vm_growSize(cpa.len, 1));19541955// We want an extra zero in front to make things simpler.1956cpa.num[cpa.len++] = 0;19571958// Still setting things up. Why all of these things are needed is not1959// something that can be easily explained, but it has to do with making the1960// actual algorithm easier to understand because it can assume a lot of1961// things. Thus, you should view all of this setup code as establishing1962// assumptions for bc_num_d_long(), where the actual division happens.1963//1964// But in short, this setup makes it so bc_num_d_long() can pretend the1965// numbers are integers.1966if (cpardx == cpa.len) cpa.len = bc_num_nonZeroLen(&cpa);1967if (BC_NUM_RDX_VAL_NP(cpb) == cpb.len) cpb.len = bc_num_nonZeroLen(&cpb);1968cpb.scale = 0;1969BC_NUM_RDX_SET_NP(cpb, 0);19701971bc_num_d_long(&cpa, &cpb, c, scale);19721973bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));19741975err:1976BC_SIG_MAYLOCK;1977bc_num_free(&cpb);1978bc_num_free(&cpa);1979BC_LONGJMP_CONT(vm);1980}19811982/**1983* Implements divmod. This is the actual modulus function; since modulus1984* requires a division anyway, this returns the quotient and modulus. Either can1985* be thrown out as desired.1986* @param a The first operand.1987* @param b The second operand.1988* @param c The return parameter for the quotient.1989* @param d The return parameter for the modulus.1990* @param scale The current scale.1991* @param ts The scale that the operation should be done to. Yes, it's not1992* necessarily the same as scale, per the bc spec.1993*/1994static void1995bc_num_r(BcNum* a, BcNum* b, BcNum* restrict c, BcNum* restrict d, size_t scale,1996size_t ts)1997{1998BcNum temp;1999// realscale is meant to quiet a warning on GCC about longjmp() clobbering.2000// This one is real.2001size_t realscale;2002bool neg;2003#if BC_ENABLE_LIBRARY2004BcVm* vm = bcl_getspecific();2005#endif // BC_ENABLE_LIBRARY20062007if (BC_NUM_ZERO(b)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);20082009if (BC_NUM_ZERO(a))2010{2011bc_num_setToZero(c, ts);2012bc_num_setToZero(d, ts);2013return;2014}20152016BC_SIG_LOCK;20172018bc_num_init(&temp, d->cap);20192020BC_SETJMP_LOCKED(vm, err);20212022BC_SIG_UNLOCK;20232024// Division.2025bc_num_d(a, b, c, scale);20262027// We want an extra digit so we can safely truncate.2028if (scale) realscale = ts + 1;2029else realscale = scale;20302031assert(BC_NUM_RDX_VALID(c));2032assert(BC_NUM_RDX_VALID(b));20332034// Implement the rest of the (a - (a / b) * b) formula.2035bc_num_m(c, b, &temp, realscale);2036bc_num_sub(a, &temp, d, realscale);20372038// Extend if necessary.2039if (ts > d->scale && BC_NUM_NONZERO(d)) bc_num_extend(d, ts - d->scale);20402041neg = BC_NUM_NEG(d);2042bc_num_retireMul(d, ts, BC_NUM_NEG(a), BC_NUM_NEG(b));2043d->rdx = BC_NUM_NEG_VAL(d, BC_NUM_NONZERO(d) ? neg : false);20442045err:2046BC_SIG_MAYLOCK;2047bc_num_free(&temp);2048BC_LONGJMP_CONT(vm);2049}20502051/**2052* Implements modulus/remainder. (Yes, I know they are different, but not in the2053* context of bc.) This is a BcNumBinOp function.2054* @param a The first operand.2055* @param b The second operand.2056* @param c The return parameter.2057* @param scale The current scale.2058*/2059static void2060bc_num_rem(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)2061{2062BcNum c1;2063size_t ts;2064#if BC_ENABLE_LIBRARY2065BcVm* vm = bcl_getspecific();2066#endif // BC_ENABLE_LIBRARY20672068ts = bc_vm_growSize(scale, b->scale);2069ts = BC_MAX(ts, a->scale);20702071BC_SIG_LOCK;20722073// Need a temp for the quotient.2074bc_num_init(&c1, bc_num_mulReq(a, b, ts));20752076BC_SETJMP_LOCKED(vm, err);20772078BC_SIG_UNLOCK;20792080bc_num_r(a, b, &c1, c, scale, ts);20812082err:2083BC_SIG_MAYLOCK;2084bc_num_free(&c1);2085BC_LONGJMP_CONT(vm);2086}20872088/**2089* Implements power (exponentiation). This is a BcNumBinOp function.2090* @param a The first operand.2091* @param b The second operand.2092* @param c The return parameter.2093* @param scale The current scale.2094*/2095static void2096bc_num_p(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)2097{2098BcNum copy, btemp;2099BcBigDig exp;2100// realscale is meant to quiet a warning on GCC about longjmp() clobbering.2101// This one is real.2102size_t powrdx, resrdx, realscale;2103bool neg;2104#if BC_ENABLE_LIBRARY2105BcVm* vm = bcl_getspecific();2106#endif // BC_ENABLE_LIBRARY21072108// This is here to silence a warning from GCC.2109#if BC_GCC2110btemp.len = 0;2111btemp.rdx = 0;2112btemp.num = NULL;2113#endif // BC_GCC21142115if (BC_ERR(bc_num_nonInt(b, &btemp))) bc_err(BC_ERR_MATH_NON_INTEGER);21162117assert(btemp.len == 0 || btemp.num != NULL);21182119if (BC_NUM_ZERO(&btemp))2120{2121bc_num_one(c);2122return;2123}21242125if (BC_NUM_ZERO(a))2126{2127if (BC_NUM_NEG_NP(btemp)) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);2128bc_num_setToZero(c, scale);2129return;2130}21312132if (BC_NUM_ONE(&btemp))2133{2134if (!BC_NUM_NEG_NP(btemp)) bc_num_copy(c, a);2135else bc_num_inv(a, c, scale);2136return;2137}21382139neg = BC_NUM_NEG_NP(btemp);2140BC_NUM_NEG_CLR_NP(btemp);21412142exp = bc_num_bigdig(&btemp);21432144BC_SIG_LOCK;21452146bc_num_createCopy(©, a);21472148BC_SETJMP_LOCKED(vm, err);21492150BC_SIG_UNLOCK;21512152// If this is true, then we do not have to do a division, and we need to2153// set scale accordingly.2154if (!neg)2155{2156size_t max = BC_MAX(scale, a->scale), scalepow;2157scalepow = bc_num_mulOverflow(a->scale, exp);2158realscale = BC_MIN(scalepow, max);2159}2160else realscale = scale;21612162// This is only implementing the first exponentiation by squaring, until it2163// reaches the first time where the square is actually used.2164for (powrdx = a->scale; !(exp & 1); exp >>= 1)2165{2166powrdx <<= 1;2167assert(BC_NUM_RDX_VALID_NP(copy));2168bc_num_mul(©, ©, ©, powrdx);2169}21702171// Make c a copy of copy for the purpose of saving the squares that should2172// be saved.2173bc_num_copy(c, ©);2174resrdx = powrdx;21752176// Now finish the exponentiation by squaring, this time saving the squares2177// as necessary.2178while (exp >>= 1)2179{2180powrdx <<= 1;2181assert(BC_NUM_RDX_VALID_NP(copy));2182bc_num_mul(©, ©, ©, powrdx);21832184// If this is true, we want to save that particular square. This does2185// that by multiplying c with copy.2186if (exp & 1)2187{2188resrdx += powrdx;2189assert(BC_NUM_RDX_VALID(c));2190assert(BC_NUM_RDX_VALID_NP(copy));2191bc_num_mul(c, ©, c, resrdx);2192}2193}21942195// Invert if necessary.2196if (neg) bc_num_inv(c, c, realscale);21972198// Truncate if necessary.2199if (c->scale > realscale) bc_num_truncate(c, c->scale - realscale);22002201bc_num_clean(c);22022203err:2204BC_SIG_MAYLOCK;2205bc_num_free(©);2206BC_LONGJMP_CONT(vm);2207}22082209#if BC_ENABLE_EXTRA_MATH2210/**2211* Implements the places operator. This is a BcNumBinOp function.2212* @param a The first operand.2213* @param b The second operand.2214* @param c The return parameter.2215* @param scale The current scale.2216*/2217static void2218bc_num_place(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)2219{2220BcBigDig val;22212222BC_UNUSED(scale);22232224val = bc_num_intop(a, b, c);22252226// Just truncate or extend as appropriate.2227if (val < c->scale) bc_num_truncate(c, c->scale - val);2228else if (val > c->scale) bc_num_extend(c, val - c->scale);2229}22302231/**2232* Implements the left shift operator. This is a BcNumBinOp function.2233*/2234static void2235bc_num_left(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)2236{2237BcBigDig val;22382239BC_UNUSED(scale);22402241val = bc_num_intop(a, b, c);22422243bc_num_shiftLeft(c, (size_t) val);2244}22452246/**2247* Implements the right shift operator. This is a BcNumBinOp function.2248*/2249static void2250bc_num_right(BcNum* a, BcNum* b, BcNum* restrict c, size_t scale)2251{2252BcBigDig val;22532254BC_UNUSED(scale);22552256val = bc_num_intop(a, b, c);22572258if (BC_NUM_ZERO(c)) return;22592260bc_num_shiftRight(c, (size_t) val);2261}2262#endif // BC_ENABLE_EXTRA_MATH22632264/**2265* Prepares for, and calls, a binary operator function. This is probably the2266* most important function in the entire file because it establishes assumptions2267* that make the rest of the code so easy. Those assumptions include:2268*2269* - a is not the same pointer as c.2270* - b is not the same pointer as c.2271* - there is enough room in c for the result.2272*2273* Without these, this whole function would basically have to be duplicated for2274* *all* binary operators.2275*2276* @param a The first operand.2277* @param b The second operand.2278* @param c The return parameter.2279* @param scale The current scale.2280* @param req The number of limbs needed to fit the result.2281*/2282static void2283bc_num_binary(BcNum* a, BcNum* b, BcNum* c, size_t scale, BcNumBinOp op,2284size_t req)2285{2286BcNum* ptr_a;2287BcNum* ptr_b;2288BcNum num2;2289#if BC_ENABLE_LIBRARY2290BcVm* vm = NULL;2291#endif // BC_ENABLE_LIBRARY22922293assert(a != NULL && b != NULL && c != NULL && op != NULL);22942295assert(BC_NUM_RDX_VALID(a));2296assert(BC_NUM_RDX_VALID(b));22972298BC_SIG_LOCK;22992300ptr_a = c == a ? &num2 : a;2301ptr_b = c == b ? &num2 : b;23022303// Actually reallocate. If we don't reallocate, we want to expand at the2304// very least.2305if (c == a || c == b)2306{2307#if BC_ENABLE_LIBRARY2308vm = bcl_getspecific();2309#endif // BC_ENABLE_LIBRARY23102311// NOLINTNEXTLINE2312memcpy(&num2, c, sizeof(BcNum));23132314bc_num_init(c, req);23152316// Must prepare for cleanup. We want this here so that locals that got2317// set stay set since a longjmp() is not guaranteed to preserve locals.2318BC_SETJMP_LOCKED(vm, err);2319BC_SIG_UNLOCK;2320}2321else2322{2323BC_SIG_UNLOCK;2324bc_num_expand(c, req);2325}23262327// It is okay for a and b to be the same. If a binary operator function does2328// need them to be different, the binary operator function is responsible2329// for that.23302331// Call the actual binary operator function.2332op(ptr_a, ptr_b, c, scale);23332334assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));2335assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);2336assert(BC_NUM_RDX_VALID(c));2337assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);23382339err:2340// Cleanup only needed if we initialized c to a new number.2341if (c == a || c == b)2342{2343BC_SIG_MAYLOCK;2344bc_num_free(&num2);2345BC_LONGJMP_CONT(vm);2346}2347}23482349/**2350* Tests a number string for validity. This function has a history; I originally2351* wrote it because I did not trust my parser. Over time, however, I came to2352* trust it, so I was able to relegate this function to debug builds only, and I2353* used it in assert()'s. But then I created the library, and well, I can't2354* trust users, so I reused this for yelling at users.2355* @param val The string to check to see if it's a valid number string.2356* @return True if the string is a valid number string, false otherwise.2357*/2358bool2359bc_num_strValid(const char* restrict val)2360{2361bool radix = false;2362size_t i, len = strlen(val);23632364// Notice that I don't check if there is a negative sign. That is not part2365// of a valid number, except in the library. The library-specific code takes2366// care of that part.23672368// Nothing in the string is okay.2369if (!len) return true;23702371// Loop through the characters.2372for (i = 0; i < len; ++i)2373{2374BcDig c = val[i];23752376// If we have found a radix point...2377if (c == '.')2378{2379// We don't allow two radices.2380if (radix) return false;23812382radix = true;2383continue;2384}23852386// We only allow digits and uppercase letters.2387if (!(isdigit(c) || isupper(c))) return false;2388}23892390return true;2391}23922393/**2394* Parses one character and returns the digit that corresponds to that2395* character according to the base.2396* @param c The character to parse.2397* @param base The base.2398* @return The character as a digit.2399*/2400static BcBigDig2401bc_num_parseChar(char c, size_t base)2402{2403assert(isupper(c) || isdigit(c));24042405// If a letter...2406if (isupper(c))2407{2408#if BC_ENABLE_LIBRARY2409BcVm* vm = bcl_getspecific();2410#endif // BC_ENABLE_LIBRARY24112412// This returns the digit that directly corresponds with the letter.2413c = BC_NUM_NUM_LETTER(c);24142415// If the digit is greater than the base, we clamp.2416if (BC_DIGIT_CLAMP)2417{2418c = ((size_t) c) >= base ? (char) base - 1 : c;2419}2420}2421// Straight convert the digit to a number.2422else c -= '0';24232424return (BcBigDig) (uchar) c;2425}24262427/**2428* Parses a string as a decimal number. This is separate because it's going to2429* be the most used, and it can be heavily optimized for decimal only.2430* @param n The number to parse into and return. Must be preallocated.2431* @param val The string to parse.2432*/2433static void2434bc_num_parseDecimal(BcNum* restrict n, const char* restrict val)2435{2436size_t len, i, temp, mod;2437const char* ptr;2438bool zero = true, rdx;2439#if BC_ENABLE_LIBRARY2440BcVm* vm = bcl_getspecific();2441#endif // BC_ENABLE_LIBRARY24422443// Eat leading zeroes.2444for (i = 0; val[i] == '0'; ++i)2445{2446continue;2447}24482449val += i;2450assert(!val[0] || isalnum(val[0]) || val[0] == '.');24512452// All 0's. We can just return, since this procedure expects a virgin2453// (already 0) BcNum.2454if (!val[0]) return;24552456// The length of the string is the length of the number, except it might be2457// one bigger because of a decimal point.2458len = strlen(val);24592460// Find the location of the decimal point.2461ptr = strchr(val, '.');2462rdx = (ptr != NULL);24632464// We eat leading zeroes again. These leading zeroes are different because2465// they will come after the decimal point if they exist, and since that's2466// the case, they must be preserved.2467for (i = 0; i < len && (zero = (val[i] == '0' || val[i] == '.')); ++i)2468{2469continue;2470}24712472// Set the scale of the number based on the location of the decimal point.2473// The casts to uintptr_t is to ensure that bc does not hit undefined2474// behavior when doing math on the values.2475n->scale = (size_t) (rdx *2476(((uintptr_t) (val + len)) - (((uintptr_t) ptr) + 1)));24772478// Set rdx.2479BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));24802481// Calculate length. First, the length of the integer, then the number of2482// digits in the last limb, then the length.2483i = len - (ptr == val ? 0 : i) - rdx;2484temp = BC_NUM_ROUND_POW(i);2485mod = n->scale % BC_BASE_DIGS;2486i = mod ? BC_BASE_DIGS - mod : 0;2487n->len = ((temp + i) / BC_BASE_DIGS);24882489// Expand and zero. The plus extra is in case the lack of clamping causes2490// the number to overflow the original bounds.2491bc_num_expand(n, n->len + !BC_DIGIT_CLAMP);2492// NOLINTNEXTLINE2493memset(n->num, 0, BC_NUM_SIZE(n->len + !BC_DIGIT_CLAMP));24942495if (zero)2496{2497// I think I can set rdx directly to zero here because n should be a2498// new number with sign set to false.2499n->len = n->rdx = 0;2500}2501else2502{2503// There is actually stuff to parse if we make it here. Yay...2504BcBigDig exp, pow;25052506assert(i <= BC_NUM_BIGDIG_MAX);25072508// The exponent and power.2509exp = (BcBigDig) i;2510pow = bc_num_pow10[exp];25112512// Parse loop. We parse backwards because numbers are stored little2513// endian.2514for (i = len - 1; i < len; --i, ++exp)2515{2516char c = val[i];25172518// Skip the decimal point.2519if (c == '.') exp -= 1;2520else2521{2522// The index of the limb.2523size_t idx = exp / BC_BASE_DIGS;2524BcBigDig dig;25252526if (isupper(c))2527{2528// Clamp for the base.2529if (!BC_DIGIT_CLAMP) c = BC_NUM_NUM_LETTER(c);2530else c = 9;2531}2532else c -= '0';25332534// Add the digit to the limb. This takes care of overflow from2535// lack of clamping.2536dig = ((BcBigDig) n->num[idx]) + ((BcBigDig) c) * pow;2537if (dig >= BC_BASE_POW)2538{2539// We cannot go over BC_BASE_POW with clamping.2540assert(!BC_DIGIT_CLAMP);25412542n->num[idx + 1] = (BcDig) (dig / BC_BASE_POW);2543n->num[idx] = (BcDig) (dig % BC_BASE_POW);2544assert(n->num[idx] >= 0 && n->num[idx] < BC_BASE_POW);2545assert(n->num[idx + 1] >= 0 &&2546n->num[idx + 1] < BC_BASE_POW);2547}2548else2549{2550n->num[idx] = (BcDig) dig;2551assert(n->num[idx] >= 0 && n->num[idx] < BC_BASE_POW);2552}25532554// Adjust the power and exponent.2555if ((exp + 1) % BC_BASE_DIGS == 0) pow = 1;2556else pow *= BC_BASE;2557}2558}2559}25602561// Make sure to add one to the length if needed from lack of clamping.2562n->len += (!BC_DIGIT_CLAMP && n->num[n->len] != 0);2563}25642565/**2566* Parse a number in any base (besides decimal).2567* @param n The number to parse into and return. Must be preallocated.2568* @param val The string to parse.2569* @param base The base to parse as.2570*/2571static void2572bc_num_parseBase(BcNum* restrict n, const char* restrict val, BcBigDig base)2573{2574BcNum temp, mult1, mult2, result1, result2;2575BcNum* m1;2576BcNum* m2;2577BcNum* ptr;2578char c = 0;2579bool zero = true;2580BcBigDig v;2581size_t digs, len = strlen(val);2582// This is volatile to quiet a warning on GCC about longjmp() clobbering.2583volatile size_t i;2584#if BC_ENABLE_LIBRARY2585BcVm* vm = bcl_getspecific();2586#endif // BC_ENABLE_LIBRARY25872588// If zero, just return because the number should be virgin (already 0).2589for (i = 0; zero && i < len; ++i)2590{2591zero = (val[i] == '.' || val[i] == '0');2592}2593if (zero) return;25942595BC_SIG_LOCK;25962597bc_num_init(&temp, BC_NUM_BIGDIG_LOG10);2598bc_num_init(&mult1, BC_NUM_BIGDIG_LOG10);25992600BC_SETJMP_LOCKED(vm, int_err);26012602BC_SIG_UNLOCK;26032604// We split parsing into parsing the integer and parsing the fractional2605// part.26062607// Parse the integer part. This is the easy part because we just multiply2608// the number by the base, then add the digit.2609for (i = 0; i < len && (c = val[i]) && c != '.'; ++i)2610{2611// Convert the character to a digit.2612v = bc_num_parseChar(c, base);26132614// Multiply the number.2615bc_num_mulArray(n, base, &mult1);26162617// Convert the digit to a number and add.2618bc_num_bigdig2num(&temp, v);2619bc_num_add(&mult1, &temp, n, 0);2620}26212622// If this condition is true, then we are done. We still need to do cleanup2623// though.2624if (i == len && !val[i]) goto int_err;26252626// If we get here, we *must* be at the radix point.2627assert(val[i] == '.');26282629BC_SIG_LOCK;26302631// Unset the jump to reset in for these new initializations.2632BC_UNSETJMP(vm);26332634bc_num_init(&mult2, BC_NUM_BIGDIG_LOG10);2635bc_num_init(&result1, BC_NUM_DEF_SIZE);2636bc_num_init(&result2, BC_NUM_DEF_SIZE);2637bc_num_one(&mult1);26382639BC_SETJMP_LOCKED(vm, err);26402641BC_SIG_UNLOCK;26422643// Pointers for easy switching.2644m1 = &mult1;2645m2 = &mult2;26462647// Parse the fractional part. This is the hard part.2648for (i += 1, digs = 0; i < len && (c = val[i]); ++i, ++digs)2649{2650size_t rdx;26512652// Convert the character to a digit.2653v = bc_num_parseChar(c, base);26542655// We keep growing result2 according to the base because the more digits2656// after the radix, the more significant the digits close to the radix2657// should be.2658bc_num_mulArray(&result1, base, &result2);26592660// Convert the digit to a number.2661bc_num_bigdig2num(&temp, v);26622663// Add the digit into the fraction part.2664bc_num_add(&result2, &temp, &result1, 0);26652666// Keep growing m1 and m2 for use after the loop.2667bc_num_mulArray(m1, base, m2);26682669rdx = BC_NUM_RDX_VAL(m2);26702671if (m2->len < rdx) m2->len = rdx;26722673// Switch.2674ptr = m1;2675m1 = m2;2676m2 = ptr;2677}26782679// This one cannot be a divide by 0 because mult starts out at 1, then is2680// multiplied by base, and base cannot be 0, so mult cannot be 0. And this2681// is the reason we keep growing m1 and m2; this division is what converts2682// the parsed fractional part from an integer to a fractional part.2683bc_num_div(&result1, m1, &result2, digs * 2);26842685// Pretruncate.2686bc_num_truncate(&result2, digs);26872688// The final add of the integer part to the fractional part.2689bc_num_add(n, &result2, n, digs);26902691// Basic cleanup.2692if (BC_NUM_NONZERO(n))2693{2694if (n->scale < digs) bc_num_extend(n, digs - n->scale);2695}2696else bc_num_zero(n);26972698err:2699BC_SIG_MAYLOCK;2700bc_num_free(&result2);2701bc_num_free(&result1);2702bc_num_free(&mult2);2703int_err:2704BC_SIG_MAYLOCK;2705bc_num_free(&mult1);2706bc_num_free(&temp);2707BC_LONGJMP_CONT(vm);2708}27092710/**2711* Prints a backslash+newline combo if the number of characters needs it. This2712* is really a convenience function.2713*/2714static inline void2715bc_num_printNewline(void)2716{2717#if !BC_ENABLE_LIBRARY2718if (vm->nchars >= vm->line_len - 1 && vm->line_len)2719{2720bc_vm_putchar('\\', bc_flush_none);2721bc_vm_putchar('\n', bc_flush_err);2722}2723#endif // !BC_ENABLE_LIBRARY2724}27252726/**2727* Prints a character after a backslash+newline, if needed.2728* @param c The character to print.2729* @param bslash Whether to print a backslash+newline.2730*/2731static void2732bc_num_putchar(int c, bool bslash)2733{2734if (c != '\n' && bslash) bc_num_printNewline();2735bc_vm_putchar(c, bc_flush_save);2736}27372738#if !BC_ENABLE_LIBRARY27392740/**2741* Prints a character for a number's digit. This is for printing for dc's P2742* command. This function does not need to worry about radix points. This is a2743* BcNumDigitOp.2744* @param n The "digit" to print.2745* @param len The "length" of the digit, or number of characters that will2746* need to be printed for the digit.2747* @param rdx True if a decimal (radix) point should be printed.2748* @param bslash True if a backslash+newline should be printed if the character2749* limit for the line is reached, false otherwise.2750*/2751static void2752bc_num_printChar(size_t n, size_t len, bool rdx, bool bslash)2753{2754BC_UNUSED(rdx);2755BC_UNUSED(len);2756BC_UNUSED(bslash);2757assert(len == 1);2758bc_vm_putchar((uchar) n, bc_flush_save);2759}27602761#endif // !BC_ENABLE_LIBRARY27622763/**2764* Prints a series of characters for large bases. This is for printing in bases2765* above hexadecimal. This is a BcNumDigitOp.2766* @param n The "digit" to print.2767* @param len The "length" of the digit, or number of characters that will2768* need to be printed for the digit.2769* @param rdx True if a decimal (radix) point should be printed.2770* @param bslash True if a backslash+newline should be printed if the character2771* limit for the line is reached, false otherwise.2772*/2773static void2774bc_num_printDigits(size_t n, size_t len, bool rdx, bool bslash)2775{2776size_t exp, pow;27772778// If needed, print the radix; otherwise, print a space to separate digits.2779bc_num_putchar(rdx ? '.' : ' ', true);27802781// Calculate the exponent and power.2782for (exp = 0, pow = 1; exp < len - 1; ++exp, pow *= BC_BASE)2783{2784continue;2785}27862787// Print each character individually.2788for (exp = 0; exp < len; pow /= BC_BASE, ++exp)2789{2790// The individual subdigit.2791size_t dig = n / pow;27922793// Take the subdigit away.2794n -= dig * pow;27952796// Print the subdigit.2797bc_num_putchar(((uchar) dig) + '0', bslash || exp != len - 1);2798}2799}28002801/**2802* Prints a character for a number's digit. This is for printing in bases for2803* hexadecimal and below because they always print only one character at a time.2804* This is a BcNumDigitOp.2805* @param n The "digit" to print.2806* @param len The "length" of the digit, or number of characters that will2807* need to be printed for the digit.2808* @param rdx True if a decimal (radix) point should be printed.2809* @param bslash True if a backslash+newline should be printed if the character2810* limit for the line is reached, false otherwise.2811*/2812static void2813bc_num_printHex(size_t n, size_t len, bool rdx, bool bslash)2814{2815BC_UNUSED(len);2816BC_UNUSED(bslash);28172818assert(len == 1);28192820if (rdx) bc_num_putchar('.', true);28212822bc_num_putchar(bc_num_hex_digits[n], bslash);2823}28242825/**2826* Prints a decimal number. This is specially written for optimization since2827* this will be used the most and because bc's numbers are already in decimal.2828* @param n The number to print.2829* @param newline Whether to print backslash+newlines on long enough lines.2830*/2831static void2832bc_num_printDecimal(const BcNum* restrict n, bool newline)2833{2834size_t i, j, rdx = BC_NUM_RDX_VAL(n);2835bool zero = true;2836size_t buffer[BC_BASE_DIGS];28372838// Print loop.2839for (i = n->len - 1; i < n->len; --i)2840{2841BcDig n9 = n->num[i];2842size_t temp;2843bool irdx = (i == rdx - 1);28442845// Calculate the number of digits in the limb.2846zero = (zero & !irdx);2847temp = n->scale % BC_BASE_DIGS;2848temp = i || !temp ? 0 : BC_BASE_DIGS - temp;28492850// NOLINTNEXTLINE2851memset(buffer, 0, BC_BASE_DIGS * sizeof(size_t));28522853// Fill the buffer with individual digits.2854for (j = 0; n9 && j < BC_BASE_DIGS; ++j)2855{2856buffer[j] = ((size_t) n9) % BC_BASE;2857n9 /= BC_BASE;2858}28592860// Print the digits in the buffer.2861for (j = BC_BASE_DIGS - 1; j < BC_BASE_DIGS && j >= temp; --j)2862{2863// Figure out whether to print the decimal point.2864bool print_rdx = (irdx & (j == BC_BASE_DIGS - 1));28652866// The zero variable helps us skip leading zero digits in the limb.2867zero = (zero && buffer[j] == 0);28682869if (!zero)2870{2871// While the first three arguments should be self-explanatory,2872// the last needs explaining. I don't want to print a newline2873// when the last digit to be printed could take the place of the2874// backslash rather than being pushed, as a single character, to2875// the next line. That's what that last argument does for bc.2876bc_num_printHex(buffer[j], 1, print_rdx,2877!newline || (j > temp || i != 0));2878}2879}2880}2881}28822883#if BC_ENABLE_EXTRA_MATH28842885/**2886* Prints a number in scientific or engineering format. When doing this, we are2887* always printing in decimal.2888* @param n The number to print.2889* @param eng True if we are in engineering mode.2890* @param newline Whether to print backslash+newlines on long enough lines.2891*/2892static void2893bc_num_printExponent(const BcNum* restrict n, bool eng, bool newline)2894{2895size_t places, mod, nrdx = BC_NUM_RDX_VAL(n);2896bool neg = (n->len <= nrdx);2897BcNum temp, exp;2898BcDig digs[BC_NUM_BIGDIG_LOG10];2899#if BC_ENABLE_LIBRARY2900BcVm* vm = bcl_getspecific();2901#endif // BC_ENABLE_LIBRARY29022903BC_SIG_LOCK;29042905bc_num_createCopy(&temp, n);29062907BC_SETJMP_LOCKED(vm, exit);29082909BC_SIG_UNLOCK;29102911// We need to calculate the exponents, and they change based on whether the2912// number is all fractional or not, obviously.2913if (neg)2914{2915// Figure out the negative power of 10.2916places = bc_num_negPow10(n);29172918// Figure out how many digits mod 3 there are (important for2919// engineering mode).2920mod = places % 3;29212922// Calculate places if we are in engineering mode.2923if (eng && mod != 0) places += 3 - mod;29242925// Shift the temp to the right place.2926bc_num_shiftLeft(&temp, places);2927}2928else2929{2930// This is the number of digits that we are supposed to put behind the2931// decimal point.2932places = bc_num_intDigits(n) - 1;29332934// Calculate the true number based on whether engineering mode is2935// activated.2936mod = places % 3;2937if (eng && mod != 0) places -= 3 - (3 - mod);29382939// Shift the temp to the right place.2940bc_num_shiftRight(&temp, places);2941}29422943// Print the shifted number.2944bc_num_printDecimal(&temp, newline);29452946// Print the e.2947bc_num_putchar('e', !newline);29482949// Need to explicitly print a zero exponent.2950if (!places)2951{2952bc_num_printHex(0, 1, false, !newline);2953goto exit;2954}29552956// Need to print sign for the exponent.2957if (neg) bc_num_putchar('-', true);29582959// Create a temporary for the exponent...2960bc_num_setup(&exp, digs, BC_NUM_BIGDIG_LOG10);2961bc_num_bigdig2num(&exp, (BcBigDig) places);29622963/// ..and print it.2964bc_num_printDecimal(&exp, newline);29652966exit:2967BC_SIG_MAYLOCK;2968bc_num_free(&temp);2969BC_LONGJMP_CONT(vm);2970}2971#endif // BC_ENABLE_EXTRA_MATH29722973/**2974* Takes a number with limbs with base BC_BASE_POW and converts the limb at the2975* given index to base @a pow, where @a pow is obase^N.2976* @param n The number to convert.2977* @param rem BC_BASE_POW - @a pow.2978* @param pow The power of obase we will convert the number to.2979* @param idx The index of the number to start converting at. Doing the2980* conversion is O(n^2); we have to sweep through starting at the2981* least significant limb.2982*/2983static void2984bc_num_printFixup(BcNum* restrict n, BcBigDig rem, BcBigDig pow, size_t idx)2985{2986size_t i, len = n->len - idx;2987BcBigDig acc;2988BcDig* a = n->num + idx;29892990// Ignore if there's just one limb left. This is the part that requires the2991// extra loop after the one calling this function in bc_num_printPrepare().2992if (len < 2) return;29932994// Loop through the remaining limbs and convert. We start at the second limb2995// because we pull the value from the previous one as well.2996for (i = len - 1; i > 0; --i)2997{2998// Get the limb and add it to the previous, along with multiplying by2999// the remainder because that's the proper overflow. "acc" means3000// "accumulator," by the way.3001acc = ((BcBigDig) a[i]) * rem + ((BcBigDig) a[i - 1]);30023003// Store a value in base pow in the previous limb.3004a[i - 1] = (BcDig) (acc % pow);30053006// Divide by the base and accumulate the remaining value in the limb.3007acc /= pow;3008acc += (BcBigDig) a[i];30093010// If the accumulator is greater than the base...3011if (acc >= BC_BASE_POW)3012{3013// Do we need to grow?3014if (i == len - 1)3015{3016// Grow.3017len = bc_vm_growSize(len, 1);3018bc_num_expand(n, bc_vm_growSize(len, idx));30193020// Update the pointer because it may have moved.3021a = n->num + idx;30223023// Zero out the last limb.3024a[len - 1] = 0;3025}30263027// Overflow into the next limb since we are over the base.3028a[i + 1] += acc / BC_BASE_POW;3029acc %= BC_BASE_POW;3030}30313032assert(acc < BC_BASE_POW);30333034// Set the limb.3035a[i] = (BcDig) acc;3036}30373038// We may have grown the number, so adjust the length.3039n->len = len + idx;3040}30413042/**3043* Prepares a number for printing in a base that does not have BC_BASE_POW as a3044* power. This basically converts the number from having limbs of base3045* BC_BASE_POW to limbs of pow, where pow is obase^N.3046* @param n The number to prepare for printing.3047* @param rem The remainder of BC_BASE_POW when divided by a power of the base.3048* @param pow The power of the base.3049*/3050static void3051bc_num_printPrepare(BcNum* restrict n, BcBigDig rem, BcBigDig pow)3052{3053size_t i;30543055// Loop from the least significant limb to the most significant limb and3056// convert limbs in each pass.3057for (i = 0; i < n->len; ++i)3058{3059bc_num_printFixup(n, rem, pow, i);3060}30613062// bc_num_printFixup() does not do everything it is supposed to, so we do3063// the last bit of cleanup here. That cleanup is to ensure that each limb3064// is less than pow and to expand the number to fit new limbs as necessary.3065for (i = 0; i < n->len; ++i)3066{3067assert(pow == ((BcBigDig) ((BcDig) pow)));30683069// If the limb needs fixing...3070if (n->num[i] >= (BcDig) pow)3071{3072// Do we need to grow?3073if (i + 1 == n->len)3074{3075// Grow the number.3076n->len = bc_vm_growSize(n->len, 1);3077bc_num_expand(n, n->len);30783079// Without this, we might use uninitialized data.3080n->num[i + 1] = 0;3081}30823083assert(pow < BC_BASE_POW);30843085// Overflow into the next limb.3086n->num[i + 1] += n->num[i] / ((BcDig) pow);3087n->num[i] %= (BcDig) pow;3088}3089}3090}30913092static void3093bc_num_printNum(BcNum* restrict n, BcBigDig base, size_t len,3094BcNumDigitOp print, bool newline)3095{3096BcVec stack;3097BcNum intp, fracp1, fracp2, digit, flen1, flen2;3098BcNum* n1;3099BcNum* n2;3100BcNum* temp;3101BcBigDig dig = 0, acc, exp;3102BcBigDig* ptr;3103size_t i, j, nrdx, idigits;3104bool radix;3105BcDig digit_digs[BC_NUM_BIGDIG_LOG10 + 1];3106#if BC_ENABLE_LIBRARY3107BcVm* vm = bcl_getspecific();3108#endif // BC_ENABLE_LIBRARY31093110assert(base > 1);31113112// Easy case. Even with scale, we just print this.3113if (BC_NUM_ZERO(n))3114{3115print(0, len, false, !newline);3116return;3117}31183119// This function uses an algorithm that Stefan Esser <[email protected]> came3120// up with to print the integer part of a number. What it does is convert3121// intp into a number of the specified base, but it does it directly,3122// instead of just doing a series of divisions and printing the remainders3123// in reverse order.3124//3125// Let me explain in a bit more detail:3126//3127// The algorithm takes the current least significant limb (after intp has3128// been converted to an integer) and the next to least significant limb, and3129// it converts the least significant limb into one of the specified base,3130// putting any overflow into the next to least significant limb. It iterates3131// through the whole number, from least significant to most significant,3132// doing this conversion. At the end of that iteration, the least3133// significant limb is converted, but the others are not, so it iterates3134// again, starting at the next to least significant limb. It keeps doing3135// that conversion, skipping one more limb than the last time, until all3136// limbs have been converted. Then it prints them in reverse order.3137//3138// That is the gist of the algorithm. It leaves out several things, such as3139// the fact that limbs are not always converted into the specified base, but3140// into something close, basically a power of the specified base. In3141// Stefan's words, "You could consider BcDigs to be of base 10^BC_BASE_DIGS3142// in the normal case and obase^N for the largest value of N that satisfies3143// obase^N <= 10^BC_BASE_DIGS. [This means that] the result is not in base3144// "obase", but in base "obase^N", which happens to be printable as a number3145// of base "obase" without consideration for neighbouring BcDigs." This fact3146// is what necessitates the existence of the loop later in this function.3147//3148// The conversion happens in bc_num_printPrepare() where the outer loop3149// happens and bc_num_printFixup() where the inner loop, or actual3150// conversion, happens. In other words, bc_num_printPrepare() is where the3151// loop that starts at the least significant limb and goes to the most3152// significant limb. Then, on every iteration of its loop, it calls3153// bc_num_printFixup(), which has the inner loop of actually converting3154// the limbs it passes into limbs of base obase^N rather than base3155// BC_BASE_POW.31563157nrdx = BC_NUM_RDX_VAL(n);31583159BC_SIG_LOCK;31603161// The stack is what allows us to reverse the digits for printing.3162bc_vec_init(&stack, sizeof(BcBigDig), BC_DTOR_NONE);3163bc_num_init(&fracp1, nrdx);31643165// intp will be the "integer part" of the number, so copy it.3166bc_num_createCopy(&intp, n);31673168BC_SETJMP_LOCKED(vm, err);31693170BC_SIG_UNLOCK;31713172// Make intp an integer.3173bc_num_truncate(&intp, intp.scale);31743175// Get the fractional part out.3176bc_num_sub(n, &intp, &fracp1, 0);31773178// If the base is not the same as the last base used for printing, we need3179// to update the cached exponent and power. Yes, we cache the values of the3180// exponent and power. That is to prevent us from calculating them every3181// time because printing will probably happen multiple times on the same3182// base.3183if (base != vm->last_base)3184{3185vm->last_pow = 1;3186vm->last_exp = 0;31873188// Calculate the exponent and power.3189while (vm->last_pow * base <= BC_BASE_POW)3190{3191vm->last_pow *= base;3192vm->last_exp += 1;3193}31943195// Also, the remainder and base itself.3196vm->last_rem = BC_BASE_POW - vm->last_pow;3197vm->last_base = base;3198}31993200exp = vm->last_exp;32013202// If vm->last_rem is 0, then the base we are printing in is a divisor of3203// BC_BASE_POW, which is the easy case because it means that BC_BASE_POW is3204// a power of obase, and no conversion is needed. If it *is* 0, then we have3205// the hard case, and we have to prepare the number for the base.3206if (vm->last_rem != 0)3207{3208bc_num_printPrepare(&intp, vm->last_rem, vm->last_pow);3209}32103211// After the conversion comes the surprisingly easy part. From here on out,3212// this is basically naive code that I wrote, adjusted for the larger bases.32133214// Fill the stack of digits for the integer part.3215for (i = 0; i < intp.len; ++i)3216{3217// Get the limb.3218acc = (BcBigDig) intp.num[i];32193220// Turn the limb into digits of base obase.3221for (j = 0; j < exp && (i < intp.len - 1 || acc != 0); ++j)3222{3223// This condition is true if we are not at the last digit.3224if (j != exp - 1)3225{3226dig = acc % base;3227acc /= base;3228}3229else3230{3231dig = acc;3232acc = 0;3233}32343235assert(dig < base);32363237// Push the digit onto the stack.3238bc_vec_push(&stack, &dig);3239}32403241assert(acc == 0);3242}32433244// Go through the stack backwards and print each digit.3245for (i = 0; i < stack.len; ++i)3246{3247ptr = bc_vec_item_rev(&stack, i);32483249assert(ptr != NULL);32503251// While the first three arguments should be self-explanatory, the last3252// needs explaining. I don't want to print a backslash+newline when the3253// last digit to be printed could take the place of the backslash rather3254// than being pushed, as a single character, to the next line. That's3255// what that last argument does for bc.3256//3257// First, it needs to check if newlines are completely disabled. If they3258// are not disabled, it needs to check the next part.3259//3260// If the number has a scale, then because we are printing just the3261// integer part, there will be at least two more characters (a radix3262// point plus at least one digit). So if there is a scale, a backslash3263// is necessary.3264//3265// Finally, the last condition checks to see if we are at the end of the3266// stack. If we are *not* (i.e., the index is not one less than the3267// stack length), then a backslash is necessary because there is at3268// least one more character for at least one more digit). Otherwise, if3269// the index is equal to one less than the stack length, we want to3270// disable backslash printing.3271//3272// The function that prints bases 17 and above will take care of not3273// printing a backslash in the right case.3274print(*ptr, len, false,3275!newline || (n->scale != 0 || i < stack.len - 1));3276}32773278// We are done if there is no fractional part.3279if (!n->scale) goto err;32803281BC_SIG_LOCK;32823283// Reset the jump because some locals are changing.3284BC_UNSETJMP(vm);32853286bc_num_init(&fracp2, nrdx);3287bc_num_setup(&digit, digit_digs, sizeof(digit_digs) / sizeof(BcDig));3288bc_num_init(&flen1, BC_NUM_BIGDIG_LOG10);3289bc_num_init(&flen2, BC_NUM_BIGDIG_LOG10);32903291BC_SETJMP_LOCKED(vm, frac_err);32923293BC_SIG_UNLOCK;32943295bc_num_one(&flen1);32963297radix = true;32983299// Pointers for easy switching.3300n1 = &flen1;3301n2 = &flen2;33023303fracp2.scale = n->scale;3304BC_NUM_RDX_SET_NP(fracp2, BC_NUM_RDX(fracp2.scale));33053306// As long as we have not reached the scale of the number, keep printing.3307while ((idigits = bc_num_intDigits(n1)) <= n->scale)3308{3309// These numbers will keep growing.3310bc_num_expand(&fracp2, fracp1.len + 1);3311bc_num_mulArray(&fracp1, base, &fracp2);33123313nrdx = BC_NUM_RDX_VAL_NP(fracp2);33143315// Ensure an invariant.3316if (fracp2.len < nrdx) fracp2.len = nrdx;33173318// fracp is guaranteed to be non-negative and small enough.3319dig = bc_num_bigdig2(&fracp2);33203321// Convert the digit to a number and subtract it from the number.3322bc_num_bigdig2num(&digit, dig);3323bc_num_sub(&fracp2, &digit, &fracp1, 0);33243325// While the first three arguments should be self-explanatory, the last3326// needs explaining. I don't want to print a newline when the last digit3327// to be printed could take the place of the backslash rather than being3328// pushed, as a single character, to the next line. That's what that3329// last argument does for bc.3330print(dig, len, radix, !newline || idigits != n->scale);33313332// Update the multipliers.3333bc_num_mulArray(n1, base, n2);33343335radix = false;33363337// Switch.3338temp = n1;3339n1 = n2;3340n2 = temp;3341}33423343frac_err:3344BC_SIG_MAYLOCK;3345bc_num_free(&flen2);3346bc_num_free(&flen1);3347bc_num_free(&fracp2);3348err:3349BC_SIG_MAYLOCK;3350bc_num_free(&fracp1);3351bc_num_free(&intp);3352bc_vec_free(&stack);3353BC_LONGJMP_CONT(vm);3354}33553356/**3357* Prints a number in the specified base, or rather, figures out which function3358* to call to print the number in the specified base and calls it.3359* @param n The number to print.3360* @param base The base to print in.3361* @param newline Whether to print backslash+newlines on long enough lines.3362*/3363static void3364bc_num_printBase(BcNum* restrict n, BcBigDig base, bool newline)3365{3366size_t width;3367BcNumDigitOp print;3368bool neg = BC_NUM_NEG(n);33693370// Clear the sign because it makes the actual printing easier when we have3371// to do math.3372BC_NUM_NEG_CLR(n);33733374// Bases at hexadecimal and below are printed as one character, larger bases3375// are printed as a series of digits separated by spaces.3376if (base <= BC_NUM_MAX_POSIX_IBASE)3377{3378width = 1;3379print = bc_num_printHex;3380}3381else3382{3383assert(base <= BC_BASE_POW);3384width = bc_num_log10(base - 1);3385print = bc_num_printDigits;3386}33873388// Print.3389bc_num_printNum(n, base, width, print, newline);33903391// Reset the sign.3392n->rdx = BC_NUM_NEG_VAL(n, neg);3393}33943395#if !BC_ENABLE_LIBRARY33963397void3398bc_num_stream(BcNum* restrict n)3399{3400bc_num_printNum(n, BC_NUM_STREAM_BASE, 1, bc_num_printChar, false);3401}34023403#endif // !BC_ENABLE_LIBRARY34043405void3406bc_num_setup(BcNum* restrict n, BcDig* restrict num, size_t cap)3407{3408assert(n != NULL);3409n->num = num;3410n->cap = cap;3411bc_num_zero(n);3412}34133414void3415bc_num_init(BcNum* restrict n, size_t req)3416{3417BcDig* num;34183419BC_SIG_ASSERT_LOCKED;34203421assert(n != NULL);34223423// BC_NUM_DEF_SIZE is set to be about the smallest allocation size that3424// malloc() returns in practice, so just use it.3425req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;34263427// If we can't use a temp, allocate.3428if (req != BC_NUM_DEF_SIZE) num = bc_vm_malloc(BC_NUM_SIZE(req));3429else3430{3431num = bc_vm_getTemp() == NULL ? bc_vm_malloc(BC_NUM_SIZE(req)) :3432bc_vm_takeTemp();3433}34343435bc_num_setup(n, num, req);3436}34373438void3439bc_num_clear(BcNum* restrict n)3440{3441n->num = NULL;3442n->cap = 0;3443}34443445void3446bc_num_free(void* num)3447{3448BcNum* n = (BcNum*) num;34493450BC_SIG_ASSERT_LOCKED;34513452assert(n != NULL);34533454if (n->cap == BC_NUM_DEF_SIZE) bc_vm_addTemp(n->num);3455else free(n->num);3456}34573458void3459bc_num_copy(BcNum* d, const BcNum* s)3460{3461assert(d != NULL && s != NULL);34623463if (d == s) return;34643465bc_num_expand(d, s->len);3466d->len = s->len;34673468// I can just copy directly here because the sign *and* rdx will be3469// properly preserved.3470d->rdx = s->rdx;3471d->scale = s->scale;3472// NOLINTNEXTLINE3473memcpy(d->num, s->num, BC_NUM_SIZE(d->len));3474}34753476void3477bc_num_createCopy(BcNum* d, const BcNum* s)3478{3479BC_SIG_ASSERT_LOCKED;3480bc_num_init(d, s->len);3481bc_num_copy(d, s);3482}34833484void3485bc_num_createFromBigdig(BcNum* restrict n, BcBigDig val)3486{3487BC_SIG_ASSERT_LOCKED;3488bc_num_init(n, BC_NUM_BIGDIG_LOG10);3489bc_num_bigdig2num(n, val);3490}34913492size_t3493bc_num_scale(const BcNum* restrict n)3494{3495return n->scale;3496}34973498size_t3499bc_num_len(const BcNum* restrict n)3500{3501size_t len = n->len;35023503// Always return at least 1.3504if (BC_NUM_ZERO(n)) return n->scale ? n->scale : 1;35053506// If this is true, there is no integer portion of the number.3507if (BC_NUM_RDX_VAL(n) == len)3508{3509// We have to take into account the fact that some of the digits right3510// after the decimal could be zero. If that is the case, we need to3511// ignore them until we hit the first non-zero digit.35123513size_t zero, scale;35143515// The number of limbs with non-zero digits.3516len = bc_num_nonZeroLen(n);35173518// Get the number of digits in the last limb.3519scale = n->scale % BC_BASE_DIGS;3520scale = scale ? scale : BC_BASE_DIGS;35213522// Get the number of zero digits.3523zero = bc_num_zeroDigits(n->num + len - 1);35243525// Calculate the true length.3526len = len * BC_BASE_DIGS - zero - (BC_BASE_DIGS - scale);3527}3528// Otherwise, count the number of int digits and return that plus the scale.3529else len = bc_num_intDigits(n) + n->scale;35303531return len;3532}35333534void3535bc_num_parse(BcNum* restrict n, const char* restrict val, BcBigDig base)3536{3537#if BC_DEBUG3538#if BC_ENABLE_LIBRARY3539BcVm* vm = bcl_getspecific();3540#endif // BC_ENABLE_LIBRARY3541#endif // BC_DEBUG35423543assert(n != NULL && val != NULL && base);3544assert(base >= BC_NUM_MIN_BASE && base <= vm->maxes[BC_PROG_GLOBALS_IBASE]);3545assert(bc_num_strValid(val));35463547// A one character number is *always* parsed as though the base was the3548// maximum allowed ibase, per the bc spec.3549if (!val[1])3550{3551BcBigDig dig = bc_num_parseChar(val[0], BC_NUM_MAX_LBASE);3552bc_num_bigdig2num(n, dig);3553}3554else if (base == BC_BASE) bc_num_parseDecimal(n, val);3555else bc_num_parseBase(n, val, base);35563557assert(BC_NUM_RDX_VALID(n));3558}35593560void3561bc_num_print(BcNum* restrict n, BcBigDig base, bool newline)3562{3563assert(n != NULL);3564assert(BC_ENABLE_EXTRA_MATH || base >= BC_NUM_MIN_BASE);35653566// We may need a newline, just to start.3567bc_num_printNewline();35683569if (BC_NUM_NONZERO(n))3570{3571#if BC_ENABLE_LIBRARY3572BcVm* vm = bcl_getspecific();3573#endif // BC_ENABLE_LIBRARY35743575// Print the sign.3576if (BC_NUM_NEG(n)) bc_num_putchar('-', true);35773578// Print the leading zero if necessary. We don't print when using3579// scientific or engineering modes.3580if (BC_Z && BC_NUM_RDX_VAL(n) == n->len && base != 0 && base != 1)3581{3582bc_num_printHex(0, 1, false, !newline);3583}3584}35853586// Short-circuit 0.3587if (BC_NUM_ZERO(n)) bc_num_printHex(0, 1, false, !newline);3588else if (base == BC_BASE) bc_num_printDecimal(n, newline);3589#if BC_ENABLE_EXTRA_MATH3590else if (base == 0 || base == 1)3591{3592bc_num_printExponent(n, base != 0, newline);3593}3594#endif // BC_ENABLE_EXTRA_MATH3595else bc_num_printBase(n, base, newline);35963597if (newline) bc_num_putchar('\n', false);3598}35993600BcBigDig3601bc_num_bigdig2(const BcNum* restrict n)3602{3603#if BC_DEBUG3604#if BC_ENABLE_LIBRARY3605BcVm* vm = bcl_getspecific();3606#endif // BC_ENABLE_LIBRARY3607#endif // BC_DEBUG36083609// This function returns no errors because it's guaranteed to succeed if3610// its preconditions are met. Those preconditions include both n needs to3611// be non-NULL, n being non-negative, and n being less than vm->max. If all3612// of that is true, then we can just convert without worrying about negative3613// errors or overflow.36143615BcBigDig r = 0;3616size_t nrdx = BC_NUM_RDX_VAL(n);36173618assert(n != NULL);3619assert(!BC_NUM_NEG(n));3620assert(bc_num_cmp(n, &vm->max) < 0);3621assert(n->len - nrdx <= 3);36223623// There is a small speed win from unrolling the loop here, and since it3624// only adds 53 bytes, I decided that it was worth it.3625switch (n->len - nrdx)3626{3627case 3:3628{3629r = (BcBigDig) n->num[nrdx + 2];36303631// Fallthrough.3632BC_FALLTHROUGH3633}36343635case 2:3636{3637r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx + 1];36383639// Fallthrough.3640BC_FALLTHROUGH3641}36423643case 1:3644{3645r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx];3646}3647}36483649return r;3650}36513652BcBigDig3653bc_num_bigdig(const BcNum* restrict n)3654{3655#if BC_ENABLE_LIBRARY3656BcVm* vm = bcl_getspecific();3657#endif // BC_ENABLE_LIBRARY36583659assert(n != NULL);36603661// This error checking is extremely important, and if you do not have a3662// guarantee that converting a number will always succeed in a particular3663// case, you *must* call this function to get these error checks. This3664// includes all instances of numbers inputted by the user or calculated by3665// the user. Otherwise, you can call the faster bc_num_bigdig2().3666if (BC_ERR(BC_NUM_NEG(n))) bc_err(BC_ERR_MATH_NEGATIVE);3667if (BC_ERR(bc_num_cmp(n, &vm->max) >= 0)) bc_err(BC_ERR_MATH_OVERFLOW);36683669return bc_num_bigdig2(n);3670}36713672void3673bc_num_bigdig2num(BcNum* restrict n, BcBigDig val)3674{3675BcDig* ptr;3676size_t i;36773678assert(n != NULL);36793680bc_num_zero(n);36813682// Already 0.3683if (!val) return;36843685// Expand first. This is the only way this function can fail, and it's a3686// fatal error.3687bc_num_expand(n, BC_NUM_BIGDIG_LOG10);36883689// The conversion is easy because numbers are laid out in little-endian3690// order.3691for (ptr = n->num, i = 0; val; ++i, val /= BC_BASE_POW)3692{3693ptr[i] = val % BC_BASE_POW;3694}36953696n->len = i;3697}36983699#if BC_ENABLE_EXTRA_MATH37003701void3702bc_num_rng(const BcNum* restrict n, BcRNG* rng)3703{3704BcNum temp, temp2, intn, frac;3705BcRand state1, state2, inc1, inc2;3706size_t nrdx = BC_NUM_RDX_VAL(n);3707#if BC_ENABLE_LIBRARY3708BcVm* vm = bcl_getspecific();3709#endif // BC_ENABLE_LIBRARY37103711// This function holds the secret of how I interpret a seed number for the3712// PRNG. Well, it's actually in the development manual3713// (manuals/development.md#pseudo-random-number-generator), so look there3714// before you try to understand this.37153716BC_SIG_LOCK;37173718bc_num_init(&temp, n->len);3719bc_num_init(&temp2, n->len);3720bc_num_init(&frac, nrdx);3721bc_num_init(&intn, bc_num_int(n));37223723BC_SETJMP_LOCKED(vm, err);37243725BC_SIG_UNLOCK;37263727assert(BC_NUM_RDX_VALID_NP(vm->max));37283729// NOLINTNEXTLINE3730memcpy(frac.num, n->num, BC_NUM_SIZE(nrdx));3731frac.len = nrdx;3732BC_NUM_RDX_SET_NP(frac, nrdx);3733frac.scale = n->scale;37343735assert(BC_NUM_RDX_VALID_NP(frac));3736assert(BC_NUM_RDX_VALID_NP(vm->max2));37373738// Multiply the fraction and truncate so that it's an integer. The3739// truncation is what clamps it, by the way.3740bc_num_mul(&frac, &vm->max2, &temp, 0);3741bc_num_truncate(&temp, temp.scale);3742bc_num_copy(&frac, &temp);37433744// Get the integer.3745// NOLINTNEXTLINE3746memcpy(intn.num, n->num + nrdx, BC_NUM_SIZE(bc_num_int(n)));3747intn.len = bc_num_int(n);37483749// This assert is here because it has to be true. It is also here to justify3750// some optimizations.3751assert(BC_NUM_NONZERO(&vm->max));37523753// If there *was* a fractional part...3754if (BC_NUM_NONZERO(&frac))3755{3756// This divmod splits frac into the two state parts.3757bc_num_divmod(&frac, &vm->max, &temp, &temp2, 0);37583759// frac is guaranteed to be smaller than vm->max * vm->max (pow).3760// This means that when dividing frac by vm->max, as above, the3761// quotient and remainder are both guaranteed to be less than vm->max,3762// which means we can use bc_num_bigdig2() here and not worry about3763// overflow.3764state1 = (BcRand) bc_num_bigdig2(&temp2);3765state2 = (BcRand) bc_num_bigdig2(&temp);3766}3767else state1 = state2 = 0;37683769// If there *was* an integer part...3770if (BC_NUM_NONZERO(&intn))3771{3772// This divmod splits intn into the two inc parts.3773bc_num_divmod(&intn, &vm->max, &temp, &temp2, 0);37743775// Because temp2 is the mod of vm->max, from above, it is guaranteed3776// to be small enough to use bc_num_bigdig2().3777inc1 = (BcRand) bc_num_bigdig2(&temp2);37783779// Clamp the second inc part.3780if (bc_num_cmp(&temp, &vm->max) >= 0)3781{3782bc_num_copy(&temp2, &temp);3783bc_num_mod(&temp2, &vm->max, &temp, 0);3784}37853786// The if statement above ensures that temp is less than vm->max, which3787// means that we can use bc_num_bigdig2() here.3788inc2 = (BcRand) bc_num_bigdig2(&temp);3789}3790else inc1 = inc2 = 0;37913792bc_rand_seed(rng, state1, state2, inc1, inc2);37933794err:3795BC_SIG_MAYLOCK;3796bc_num_free(&intn);3797bc_num_free(&frac);3798bc_num_free(&temp2);3799bc_num_free(&temp);3800BC_LONGJMP_CONT(vm);3801}38023803void3804bc_num_createFromRNG(BcNum* restrict n, BcRNG* rng)3805{3806BcRand s1, s2, i1, i2;3807BcNum conv, temp1, temp2, temp3;3808BcDig temp1_num[BC_RAND_NUM_SIZE], temp2_num[BC_RAND_NUM_SIZE];3809BcDig conv_num[BC_NUM_BIGDIG_LOG10];3810#if BC_ENABLE_LIBRARY3811BcVm* vm = bcl_getspecific();3812#endif // BC_ENABLE_LIBRARY38133814BC_SIG_LOCK;38153816bc_num_init(&temp3, 2 * BC_RAND_NUM_SIZE);38173818BC_SETJMP_LOCKED(vm, err);38193820BC_SIG_UNLOCK;38213822bc_num_setup(&temp1, temp1_num, sizeof(temp1_num) / sizeof(BcDig));3823bc_num_setup(&temp2, temp2_num, sizeof(temp2_num) / sizeof(BcDig));3824bc_num_setup(&conv, conv_num, sizeof(conv_num) / sizeof(BcDig));38253826// This assert is here because it has to be true. It is also here to justify3827// the assumption that vm->max is not zero.3828assert(BC_NUM_NONZERO(&vm->max));38293830// Because this is true, we can just ignore math errors that would happen3831// otherwise.3832assert(BC_NUM_NONZERO(&vm->max2));38333834bc_rand_getRands(rng, &s1, &s2, &i1, &i2);38353836// Put the second piece of state into a number.3837bc_num_bigdig2num(&conv, (BcBigDig) s2);38383839assert(BC_NUM_RDX_VALID_NP(conv));38403841// Multiply by max to make room for the first piece of state.3842bc_num_mul(&conv, &vm->max, &temp1, 0);38433844// Add in the first piece of state.3845bc_num_bigdig2num(&conv, (BcBigDig) s1);3846bc_num_add(&conv, &temp1, &temp2, 0);38473848// Divide to make it an entirely fractional part.3849bc_num_div(&temp2, &vm->max2, &temp3, BC_RAND_STATE_BITS);38503851// Now start on the increment parts. It's the same process without the3852// divide, so put the second piece of increment into a number.3853bc_num_bigdig2num(&conv, (BcBigDig) i2);38543855assert(BC_NUM_RDX_VALID_NP(conv));38563857// Multiply by max to make room for the first piece of increment.3858bc_num_mul(&conv, &vm->max, &temp1, 0);38593860// Add in the first piece of increment.3861bc_num_bigdig2num(&conv, (BcBigDig) i1);3862bc_num_add(&conv, &temp1, &temp2, 0);38633864// Now add the two together.3865bc_num_add(&temp2, &temp3, n, 0);38663867assert(BC_NUM_RDX_VALID(n));38683869err:3870BC_SIG_MAYLOCK;3871bc_num_free(&temp3);3872BC_LONGJMP_CONT(vm);3873}38743875void3876bc_num_irand(BcNum* restrict a, BcNum* restrict b, BcRNG* restrict rng)3877{3878BcNum atemp;3879size_t i;38803881assert(a != b);38823883if (BC_ERR(BC_NUM_NEG(a))) bc_err(BC_ERR_MATH_NEGATIVE);38843885// If either of these are true, then the numbers are integers.3886if (BC_NUM_ZERO(a) || BC_NUM_ONE(a)) return;38873888#if BC_GCC3889// This is here in GCC to quiet the "maybe-uninitialized" warning.3890atemp.num = NULL;3891atemp.len = 0;3892#endif // BC_GCC38933894if (BC_ERR(bc_num_nonInt(a, &atemp))) bc_err(BC_ERR_MATH_NON_INTEGER);38953896assert(atemp.num != NULL);3897assert(atemp.len);38983899if (atemp.len > 2)3900{3901size_t len;39023903len = atemp.len - 2;39043905// Just generate a random number for each limb.3906for (i = 0; i < len; i += 2)3907{3908BcRand dig;39093910dig = bc_rand_bounded(rng, BC_BASE_RAND_POW);39113912b->num[i] = (BcDig) (dig % BC_BASE_POW);3913b->num[i + 1] = (BcDig) (dig / BC_BASE_POW);3914}3915}3916else3917{3918// We need this set.3919i = 0;3920}39213922// This will be true if there's one full limb after the two limb groups.3923if (i == atemp.len - 2)3924{3925// Increment this for easy use.3926i += 1;39273928// If the last digit is not one, we need to set a bound for it3929// explicitly. Since there's still an empty limb, we need to fill that.3930if (atemp.num[i] != 1)3931{3932BcRand dig;3933BcRand bound;39343935// Set the bound to the bound of the last limb times the amount3936// needed to fill the second-to-last limb as well.3937bound = ((BcRand) atemp.num[i]) * BC_BASE_POW;39383939dig = bc_rand_bounded(rng, bound);39403941// Fill the last two.3942b->num[i - 1] = (BcDig) (dig % BC_BASE_POW);3943b->num[i] = (BcDig) (dig / BC_BASE_POW);39443945// Ensure that the length will be correct. If the last limb is zero,3946// then the length needs to be one less than the bound.3947b->len = atemp.len - (b->num[i] == 0);3948}3949// Here the last limb *is* one, which means the last limb does *not*3950// need to be filled. Also, the length needs to be one less because the3951// last limb is 0.3952else3953{3954b->num[i - 1] = (BcDig) bc_rand_bounded(rng, BC_BASE_POW);3955b->len = atemp.len - 1;3956}3957}3958// Here, there is only one limb to fill.3959else3960{3961// See above for how this works.3962if (atemp.num[i] != 1)3963{3964b->num[i] = (BcDig) bc_rand_bounded(rng, (BcRand) atemp.num[i]);3965b->len = atemp.len - (b->num[i] == 0);3966}3967else b->len = atemp.len - 1;3968}39693970bc_num_clean(b);39713972assert(BC_NUM_RDX_VALID(b));3973}3974#endif // BC_ENABLE_EXTRA_MATH39753976size_t3977bc_num_addReq(const BcNum* a, const BcNum* b, size_t scale)3978{3979size_t aint, bint, ardx, brdx;39803981// Addition and subtraction require the max of the length of the two numbers3982// plus 1.39833984BC_UNUSED(scale);39853986ardx = BC_NUM_RDX_VAL(a);3987aint = bc_num_int(a);3988assert(aint <= a->len && ardx <= a->len);39893990brdx = BC_NUM_RDX_VAL(b);3991bint = bc_num_int(b);3992assert(bint <= b->len && brdx <= b->len);39933994ardx = BC_MAX(ardx, brdx);3995aint = BC_MAX(aint, bint);39963997return bc_vm_growSize(bc_vm_growSize(ardx, aint), 1);3998}39994000size_t4001bc_num_mulReq(const BcNum* a, const BcNum* b, size_t scale)4002{4003size_t max, rdx;40044005// Multiplication requires the sum of the lengths of the numbers.40064007rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));40084009max = BC_NUM_RDX(scale);40104011max = bc_vm_growSize(BC_MAX(max, rdx), 1);4012rdx = bc_vm_growSize(bc_vm_growSize(bc_num_int(a), bc_num_int(b)), max);40134014return rdx;4015}40164017size_t4018bc_num_divReq(const BcNum* a, const BcNum* b, size_t scale)4019{4020size_t max, rdx;40214022// Division requires the length of the dividend plus the scale.40234024rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));40254026max = BC_NUM_RDX(scale);40274028max = bc_vm_growSize(BC_MAX(max, rdx), 1);4029rdx = bc_vm_growSize(bc_num_int(a), max);40304031return rdx;4032}40334034size_t4035bc_num_powReq(const BcNum* a, const BcNum* b, size_t scale)4036{4037BC_UNUSED(scale);4038return bc_vm_growSize(bc_vm_growSize(a->len, b->len), 1);4039}40404041#if BC_ENABLE_EXTRA_MATH4042size_t4043bc_num_placesReq(const BcNum* a, const BcNum* b, size_t scale)4044{4045BC_UNUSED(scale);4046return a->len + b->len - BC_NUM_RDX_VAL(a) - BC_NUM_RDX_VAL(b);4047}4048#endif // BC_ENABLE_EXTRA_MATH40494050void4051bc_num_add(BcNum* a, BcNum* b, BcNum* c, size_t scale)4052{4053assert(BC_NUM_RDX_VALID(a));4054assert(BC_NUM_RDX_VALID(b));4055bc_num_binary(a, b, c, false, bc_num_as, bc_num_addReq(a, b, scale));4056}40574058void4059bc_num_sub(BcNum* a, BcNum* b, BcNum* c, size_t scale)4060{4061assert(BC_NUM_RDX_VALID(a));4062assert(BC_NUM_RDX_VALID(b));4063bc_num_binary(a, b, c, true, bc_num_as, bc_num_addReq(a, b, scale));4064}40654066void4067bc_num_mul(BcNum* a, BcNum* b, BcNum* c, size_t scale)4068{4069assert(BC_NUM_RDX_VALID(a));4070assert(BC_NUM_RDX_VALID(b));4071bc_num_binary(a, b, c, scale, bc_num_m, bc_num_mulReq(a, b, scale));4072}40734074void4075bc_num_div(BcNum* a, BcNum* b, BcNum* c, size_t scale)4076{4077assert(BC_NUM_RDX_VALID(a));4078assert(BC_NUM_RDX_VALID(b));4079bc_num_binary(a, b, c, scale, bc_num_d, bc_num_divReq(a, b, scale));4080}40814082void4083bc_num_mod(BcNum* a, BcNum* b, BcNum* c, size_t scale)4084{4085assert(BC_NUM_RDX_VALID(a));4086assert(BC_NUM_RDX_VALID(b));4087bc_num_binary(a, b, c, scale, bc_num_rem, bc_num_divReq(a, b, scale));4088}40894090void4091bc_num_pow(BcNum* a, BcNum* b, BcNum* c, size_t scale)4092{4093assert(BC_NUM_RDX_VALID(a));4094assert(BC_NUM_RDX_VALID(b));4095bc_num_binary(a, b, c, scale, bc_num_p, bc_num_powReq(a, b, scale));4096}40974098#if BC_ENABLE_EXTRA_MATH4099void4100bc_num_places(BcNum* a, BcNum* b, BcNum* c, size_t scale)4101{4102assert(BC_NUM_RDX_VALID(a));4103assert(BC_NUM_RDX_VALID(b));4104bc_num_binary(a, b, c, scale, bc_num_place, bc_num_placesReq(a, b, scale));4105}41064107void4108bc_num_lshift(BcNum* a, BcNum* b, BcNum* c, size_t scale)4109{4110assert(BC_NUM_RDX_VALID(a));4111assert(BC_NUM_RDX_VALID(b));4112bc_num_binary(a, b, c, scale, bc_num_left, bc_num_placesReq(a, b, scale));4113}41144115void4116bc_num_rshift(BcNum* a, BcNum* b, BcNum* c, size_t scale)4117{4118assert(BC_NUM_RDX_VALID(a));4119assert(BC_NUM_RDX_VALID(b));4120bc_num_binary(a, b, c, scale, bc_num_right, bc_num_placesReq(a, b, scale));4121}4122#endif // BC_ENABLE_EXTRA_MATH41234124void4125bc_num_sqrt(BcNum* restrict a, BcNum* restrict b, size_t scale)4126{4127BcNum num1, num2, half, f, fprime;4128BcNum* x0;4129BcNum* x1;4130BcNum* temp;4131// realscale is meant to quiet a warning on GCC about longjmp() clobbering.4132// This one is real.4133size_t pow, len, rdx, req, resscale, realscale;4134BcDig half_digs[1];4135#if BC_ENABLE_LIBRARY4136BcVm* vm = bcl_getspecific();4137#endif // BC_ENABLE_LIBRARY41384139assert(a != NULL && b != NULL && a != b);41404141if (BC_ERR(BC_NUM_NEG(a))) bc_err(BC_ERR_MATH_NEGATIVE);41424143// We want to calculate to a's scale if it is bigger so that the result will4144// truncate properly.4145if (a->scale > scale) realscale = a->scale;4146else realscale = scale;41474148// Set parameters for the result.4149len = bc_vm_growSize(bc_num_intDigits(a), 1);4150rdx = BC_NUM_RDX(realscale);41514152// Square root needs half of the length of the parameter.4153req = bc_vm_growSize(BC_MAX(rdx, BC_NUM_RDX_VAL(a)), len >> 1);4154req = bc_vm_growSize(req, 1);41554156BC_SIG_LOCK;41574158// Unlike the binary operators, this function is the only single parameter4159// function and is expected to initialize the result. This means that it4160// expects that b is *NOT* preallocated. We allocate it here.4161bc_num_init(b, req);41624163BC_SIG_UNLOCK;41644165assert(a != NULL && b != NULL && a != b);4166assert(a->num != NULL && b->num != NULL);41674168// Easy case.4169if (BC_NUM_ZERO(a))4170{4171bc_num_setToZero(b, realscale);4172return;4173}41744175// Another easy case.4176if (BC_NUM_ONE(a))4177{4178bc_num_one(b);4179bc_num_extend(b, realscale);4180return;4181}41824183// Set the parameters again.4184rdx = BC_NUM_RDX(realscale);4185rdx = BC_MAX(rdx, BC_NUM_RDX_VAL(a));4186len = bc_vm_growSize(a->len, rdx);41874188BC_SIG_LOCK;41894190bc_num_init(&num1, len);4191bc_num_init(&num2, len);4192bc_num_setup(&half, half_digs, sizeof(half_digs) / sizeof(BcDig));41934194// There is a division by two in the formula. We set up a number that's 1/24195// so that we can use multiplication instead of heavy division.4196bc_num_setToZero(&half, 1);4197half.num[0] = BC_BASE_POW / 2;4198half.len = 1;4199BC_NUM_RDX_SET_NP(half, 1);42004201bc_num_init(&f, len);4202bc_num_init(&fprime, len);42034204BC_SETJMP_LOCKED(vm, err);42054206BC_SIG_UNLOCK;42074208// Pointers for easy switching.4209x0 = &num1;4210x1 = &num2;42114212// Start with 1.4213bc_num_one(x0);42144215// The power of the operand is needed for the estimate.4216pow = bc_num_intDigits(a);42174218// The code in this if statement calculates the initial estimate. First, if4219// a is less than 1, then 0 is a good estimate. Otherwise, we want something4220// in the same ballpark. That ballpark is half of pow because the result4221// will have half the digits.4222if (pow)4223{4224// An odd number is served by starting with 2^((pow-1)/2), and an even4225// number is served by starting with 6^((pow-2)/2). Why? Because math.4226if (pow & 1) x0->num[0] = 2;4227else x0->num[0] = 6;42284229pow -= 2 - (pow & 1);4230bc_num_shiftLeft(x0, pow / 2);4231}42324233// I can set the rdx here directly because neg should be false.4234x0->scale = x0->rdx = 0;4235resscale = (realscale + BC_BASE_DIGS) + 2;42364237// This is the calculation loop. This compare goes to 0 eventually as the4238// difference between the two numbers gets smaller than resscale.4239while (bc_num_cmp(x1, x0))4240{4241assert(BC_NUM_NONZERO(x0));42424243// This loop directly corresponds to the iteration in Newton's method.4244// If you know the formula, this loop makes sense. Go study the formula.42454246bc_num_div(a, x0, &f, resscale);4247bc_num_add(x0, &f, &fprime, resscale);42484249assert(BC_NUM_RDX_VALID_NP(fprime));4250assert(BC_NUM_RDX_VALID_NP(half));42514252bc_num_mul(&fprime, &half, x1, resscale);42534254// Switch.4255temp = x0;4256x0 = x1;4257x1 = temp;4258}42594260// Copy to the result and truncate.4261bc_num_copy(b, x0);4262if (b->scale > realscale) bc_num_truncate(b, b->scale - realscale);42634264assert(!BC_NUM_NEG(b) || BC_NUM_NONZERO(b));4265assert(BC_NUM_RDX_VALID(b));4266assert(BC_NUM_RDX_VAL(b) <= b->len || !b->len);4267assert(!b->len || b->num[b->len - 1] || BC_NUM_RDX_VAL(b) == b->len);42684269err:4270BC_SIG_MAYLOCK;4271bc_num_free(&fprime);4272bc_num_free(&f);4273bc_num_free(&num2);4274bc_num_free(&num1);4275BC_LONGJMP_CONT(vm);4276}42774278void4279bc_num_divmod(BcNum* a, BcNum* b, BcNum* c, BcNum* d, size_t scale)4280{4281size_t ts, len;4282BcNum *ptr_a, num2;4283// This is volatile to quiet a warning on GCC about clobbering with4284// longjmp().4285volatile bool init = false;4286#if BC_ENABLE_LIBRARY4287BcVm* vm = bcl_getspecific();4288#endif // BC_ENABLE_LIBRARY42894290// The bulk of this function is just doing what bc_num_binary() does for the4291// binary operators. However, it assumes that only c and a can be equal.42924293// Set up the parameters.4294ts = BC_MAX(scale + b->scale, a->scale);4295len = bc_num_mulReq(a, b, ts);42964297assert(a != NULL && b != NULL && c != NULL && d != NULL);4298assert(c != d && a != d && b != d && b != c);42994300// Initialize or expand as necessary.4301if (c == a)4302{4303// NOLINTNEXTLINE4304memcpy(&num2, c, sizeof(BcNum));4305ptr_a = &num2;43064307BC_SIG_LOCK;43084309bc_num_init(c, len);43104311init = true;43124313BC_SETJMP_LOCKED(vm, err);43144315BC_SIG_UNLOCK;4316}4317else4318{4319ptr_a = a;4320bc_num_expand(c, len);4321}43224323// Do the quick version if possible.4324if (BC_NUM_NONZERO(a) && !BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b) &&4325b->len == 1 && !scale)4326{4327BcBigDig rem;43284329bc_num_divArray(ptr_a, (BcBigDig) b->num[0], c, &rem);43304331assert(rem < BC_BASE_POW);43324333d->num[0] = (BcDig) rem;4334d->len = (rem != 0);4335}4336// Do the slow method.4337else bc_num_r(ptr_a, b, c, d, scale, ts);43384339assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));4340assert(BC_NUM_RDX_VALID(c));4341assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);4342assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);4343assert(!BC_NUM_NEG(d) || BC_NUM_NONZERO(d));4344assert(BC_NUM_RDX_VALID(d));4345assert(BC_NUM_RDX_VAL(d) <= d->len || !d->len);4346assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);43474348err:4349// Only cleanup if we initialized.4350if (init)4351{4352BC_SIG_MAYLOCK;4353bc_num_free(&num2);4354BC_LONGJMP_CONT(vm);4355}4356}43574358void4359bc_num_modexp(BcNum* a, BcNum* b, BcNum* c, BcNum* restrict d)4360{4361BcNum base, exp, two, temp, atemp, btemp, ctemp;4362BcDig two_digs[2];4363#if BC_ENABLE_LIBRARY4364BcVm* vm = bcl_getspecific();4365#endif // BC_ENABLE_LIBRARY43664367assert(a != NULL && b != NULL && c != NULL && d != NULL);4368assert(a != d && b != d && c != d);43694370if (BC_ERR(BC_NUM_ZERO(c))) bc_err(BC_ERR_MATH_DIVIDE_BY_ZERO);4371if (BC_ERR(BC_NUM_NEG(b))) bc_err(BC_ERR_MATH_NEGATIVE);43724373#if BC_DEBUG || BC_GCC4374// This is entirely for quieting a useless scan-build error.4375btemp.len = 0;4376ctemp.len = 0;4377#endif // BC_DEBUG || BC_GCC43784379// Eliminate fractional parts that are zero or error if they are not zero.4380if (BC_ERR(bc_num_nonInt(a, &atemp) || bc_num_nonInt(b, &btemp) ||4381bc_num_nonInt(c, &ctemp)))4382{4383bc_err(BC_ERR_MATH_NON_INTEGER);4384}43854386bc_num_expand(d, ctemp.len);43874388BC_SIG_LOCK;43894390bc_num_init(&base, ctemp.len);4391bc_num_setup(&two, two_digs, sizeof(two_digs) / sizeof(BcDig));4392bc_num_init(&temp, btemp.len + 1);4393bc_num_createCopy(&exp, &btemp);43944395BC_SETJMP_LOCKED(vm, err);43964397BC_SIG_UNLOCK;43984399bc_num_one(&two);4400two.num[0] = 2;4401bc_num_one(d);44024403// We already checked for 0.4404bc_num_rem(&atemp, &ctemp, &base, 0);44054406// If you know the algorithm I used, the memory-efficient method, then this4407// loop should be self-explanatory because it is the calculation loop.4408while (BC_NUM_NONZERO(&exp))4409{4410// Num two cannot be 0, so no errors.4411bc_num_divmod(&exp, &two, &exp, &temp, 0);44124413if (BC_NUM_ONE(&temp) && !BC_NUM_NEG_NP(temp))4414{4415assert(BC_NUM_RDX_VALID(d));4416assert(BC_NUM_RDX_VALID_NP(base));44174418bc_num_mul(d, &base, &temp, 0);44194420// We already checked for 0.4421bc_num_rem(&temp, &ctemp, d, 0);4422}44234424assert(BC_NUM_RDX_VALID_NP(base));44254426bc_num_mul(&base, &base, &temp, 0);44274428// We already checked for 0.4429bc_num_rem(&temp, &ctemp, &base, 0);4430}44314432err:4433BC_SIG_MAYLOCK;4434bc_num_free(&exp);4435bc_num_free(&temp);4436bc_num_free(&base);4437BC_LONGJMP_CONT(vm);4438assert(!BC_NUM_NEG(d) || d->len);4439assert(BC_NUM_RDX_VALID(d));4440assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);4441}44424443#if BC_DEBUG_CODE4444void4445bc_num_printDebug(const BcNum* n, const char* name, bool emptyline)4446{4447bc_file_puts(&vm->fout, bc_flush_none, name);4448bc_file_puts(&vm->fout, bc_flush_none, ": ");4449bc_num_printDecimal(n, true);4450bc_file_putchar(&vm->fout, bc_flush_err, '\n');4451if (emptyline) bc_file_putchar(&vm->fout, bc_flush_err, '\n');4452vm->nchars = 0;4453}44544455void4456bc_num_printDigs(const BcDig* n, size_t len, bool emptyline)4457{4458size_t i;44594460for (i = len - 1; i < len; --i)4461{4462bc_file_printf(&vm->fout, " %lu", (unsigned long) n[i]);4463}44644465bc_file_putchar(&vm->fout, bc_flush_err, '\n');4466if (emptyline) bc_file_putchar(&vm->fout, bc_flush_err, '\n');4467vm->nchars = 0;4468}44694470void4471bc_num_printWithDigs(const BcNum* n, const char* name, bool emptyline)4472{4473bc_file_puts(&vm->fout, bc_flush_none, name);4474bc_file_printf(&vm->fout, " len: %zu, rdx: %zu, scale: %zu\n", name, n->len,4475BC_NUM_RDX_VAL(n), n->scale);4476bc_num_printDigs(n->num, n->len, emptyline);4477}44784479void4480bc_num_dump(const char* varname, const BcNum* n)4481{4482ulong i, scale = n->scale;44834484bc_file_printf(&vm->ferr, "\n%s = %s", varname,4485n->len ? (BC_NUM_NEG(n) ? "-" : "+") : "0 ");44864487for (i = n->len - 1; i < n->len; --i)4488{4489if (i + 1 == BC_NUM_RDX_VAL(n))4490{4491bc_file_puts(&vm->ferr, bc_flush_none, ". ");4492}44934494if (scale / BC_BASE_DIGS != BC_NUM_RDX_VAL(n) - i - 1)4495{4496bc_file_printf(&vm->ferr, "%lu ", (unsigned long) n->num[i]);4497}4498else4499{4500int mod = scale % BC_BASE_DIGS;4501int d = BC_BASE_DIGS - mod;4502BcDig div;45034504if (mod != 0)4505{4506div = n->num[i] / ((BcDig) bc_num_pow10[(ulong) d]);4507bc_file_printf(&vm->ferr, "%lu", (unsigned long) div);4508}45094510div = n->num[i] % ((BcDig) bc_num_pow10[(ulong) d]);4511bc_file_printf(&vm->ferr, " ' %lu ", (unsigned long) div);4512}4513}45144515bc_file_printf(&vm->ferr, "(%zu | %zu.%zu / %zu) %lu\n", n->scale, n->len,4516BC_NUM_RDX_VAL(n), n->cap, (unsigned long) (void*) n->num);45174518bc_file_flush(&vm->ferr, bc_flush_err);4519}4520#endif // BC_DEBUG_CODE452145224523