Path: blob/main/Modules/_decimal/libmpdec/mpdecimal.c
12 views
/*1* Copyright (c) 2008-2020 Stefan Krah. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/262728#include "mpdecimal.h"2930#include <assert.h>31#include <limits.h>32#include <math.h>33#include <stdio.h>34#include <stdlib.h>35#include <string.h>3637#include "basearith.h"38#include "bits.h"39#include "constants.h"40#include "convolute.h"41#include "crt.h"42#include "mpalloc.h"43#include "typearith.h"4445#ifdef PPRO46#if defined(_MSC_VER)47#include <float.h>48#pragma float_control(precise, on)49#pragma fenv_access(on)50#elif !defined(__OpenBSD__) && !defined(__NetBSD__)51/* C99 */52#include <fenv.h>53#pragma STDC FENV_ACCESS ON54#endif55#endif565758/* Disable warning that is part of -Wextra since gcc 7.0. */59#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && __GNUC__ >= 760#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"61#endif626364#if defined(_MSC_VER)65#define ALWAYS_INLINE __forceinline66#elif defined (__IBMC__) || defined(LEGACY_COMPILER)67#define ALWAYS_INLINE68#undef inline69#define inline70#else71#ifdef TEST_COVERAGE72#define ALWAYS_INLINE73#else74#define ALWAYS_INLINE inline __attribute__ ((always_inline))75#endif76#endif7778/* ClangCL claims to support 128-bit int, but doesn't */79#if defined(__SIZEOF_INT128__) && defined(__clang__) && defined(_MSC_VER)80#undef __SIZEOF_INT128__81#endif82838485#define MPD_NEWTONDIV_CUTOFF 1024L8687#define MPD_NEW_STATIC(name, flags, exp, digits, len) \88mpd_uint_t name##_data[MPD_MINALLOC_MAX]; \89mpd_t name = {flags|MPD_STATIC|MPD_STATIC_DATA, exp, digits, \90len, MPD_MINALLOC_MAX, name##_data}9192#define MPD_NEW_CONST(name, flags, exp, digits, len, alloc, initval) \93mpd_uint_t name##_data[alloc] = {initval}; \94mpd_t name = {flags|MPD_STATIC|MPD_CONST_DATA, exp, digits, \95len, alloc, name##_data}9697#define MPD_NEW_SHARED(name, a) \98mpd_t name = {(a->flags&~MPD_DATAFLAGS)|MPD_STATIC|MPD_SHARED_DATA, \99a->exp, a->digits, a->len, a->alloc, a->data}100101102static mpd_uint_t data_one[1] = {1};103static mpd_uint_t data_zero[1] = {0};104static const mpd_t one = {MPD_STATIC|MPD_CONST_DATA, 0, 1, 1, 1, data_one};105static const mpd_t minus_one = {MPD_NEG|MPD_STATIC|MPD_CONST_DATA, 0, 1, 1, 1,106data_one};107static const mpd_t zero = {MPD_STATIC|MPD_CONST_DATA, 0, 1, 1, 1, data_zero};108109static inline void _mpd_check_exp(mpd_t *dec, const mpd_context_t *ctx,110uint32_t *status);111static void _settriple(mpd_t *result, uint8_t sign, mpd_uint_t a,112mpd_ssize_t exp);113static inline mpd_ssize_t _mpd_real_size(mpd_uint_t *data, mpd_ssize_t size);114115static int _mpd_cmp_abs(const mpd_t *a, const mpd_t *b);116117static void _mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,118const mpd_context_t *ctx, uint32_t *status);119static inline void _mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,120const mpd_context_t *ctx, uint32_t *status);121static void _mpd_base_ndivmod(mpd_t *q, mpd_t *r, const mpd_t *a,122const mpd_t *b, uint32_t *status);123static inline void _mpd_qpow_uint(mpd_t *result, const mpd_t *base,124mpd_uint_t exp, uint8_t resultsign,125const mpd_context_t *ctx, uint32_t *status);126127static mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n);128129130/******************************************************************************/131/* Version */132/******************************************************************************/133134const char *135mpd_version(void)136{137return MPD_VERSION;138}139140141/******************************************************************************/142/* Performance critical inline functions */143/******************************************************************************/144145#ifdef CONFIG_64146/* Digits in a word, primarily useful for the most significant word. */147ALWAYS_INLINE int148mpd_word_digits(mpd_uint_t word)149{150if (word < mpd_pow10[9]) {151if (word < mpd_pow10[4]) {152if (word < mpd_pow10[2]) {153return (word < mpd_pow10[1]) ? 1 : 2;154}155return (word < mpd_pow10[3]) ? 3 : 4;156}157if (word < mpd_pow10[6]) {158return (word < mpd_pow10[5]) ? 5 : 6;159}160if (word < mpd_pow10[8]) {161return (word < mpd_pow10[7]) ? 7 : 8;162}163return 9;164}165if (word < mpd_pow10[14]) {166if (word < mpd_pow10[11]) {167return (word < mpd_pow10[10]) ? 10 : 11;168}169if (word < mpd_pow10[13]) {170return (word < mpd_pow10[12]) ? 12 : 13;171}172return 14;173}174if (word < mpd_pow10[18]) {175if (word < mpd_pow10[16]) {176return (word < mpd_pow10[15]) ? 15 : 16;177}178return (word < mpd_pow10[17]) ? 17 : 18;179}180181return (word < mpd_pow10[19]) ? 19 : 20;182}183#else184ALWAYS_INLINE int185mpd_word_digits(mpd_uint_t word)186{187if (word < mpd_pow10[4]) {188if (word < mpd_pow10[2]) {189return (word < mpd_pow10[1]) ? 1 : 2;190}191return (word < mpd_pow10[3]) ? 3 : 4;192}193if (word < mpd_pow10[6]) {194return (word < mpd_pow10[5]) ? 5 : 6;195}196if (word < mpd_pow10[8]) {197return (word < mpd_pow10[7]) ? 7 : 8;198}199200return (word < mpd_pow10[9]) ? 9 : 10;201}202#endif203204205/* Adjusted exponent */206ALWAYS_INLINE mpd_ssize_t207mpd_adjexp(const mpd_t *dec)208{209return (dec->exp + dec->digits) - 1;210}211212/* Etiny */213ALWAYS_INLINE mpd_ssize_t214mpd_etiny(const mpd_context_t *ctx)215{216return ctx->emin - (ctx->prec - 1);217}218219/* Etop: used for folding down in IEEE clamping */220ALWAYS_INLINE mpd_ssize_t221mpd_etop(const mpd_context_t *ctx)222{223return ctx->emax - (ctx->prec - 1);224}225226/* Most significant word */227ALWAYS_INLINE mpd_uint_t228mpd_msword(const mpd_t *dec)229{230assert(dec->len > 0);231return dec->data[dec->len-1];232}233234/* Most significant digit of a word */235inline mpd_uint_t236mpd_msd(mpd_uint_t word)237{238int n;239240n = mpd_word_digits(word);241return word / mpd_pow10[n-1];242}243244/* Least significant digit of a word */245ALWAYS_INLINE mpd_uint_t246mpd_lsd(mpd_uint_t word)247{248return word % 10;249}250251/* Coefficient size needed to store 'digits' */252mpd_ssize_t253mpd_digits_to_size(mpd_ssize_t digits)254{255mpd_ssize_t q, r;256257_mpd_idiv_word(&q, &r, digits, MPD_RDIGITS);258return (r == 0) ? q : q+1;259}260261/* Number of digits in the exponent. Not defined for MPD_SSIZE_MIN. */262inline int263mpd_exp_digits(mpd_ssize_t exp)264{265exp = (exp < 0) ? -exp : exp;266return mpd_word_digits(exp);267}268269/* Canonical */270ALWAYS_INLINE int271mpd_iscanonical(const mpd_t *dec)272{273(void)dec;274return 1;275}276277/* Finite */278ALWAYS_INLINE int279mpd_isfinite(const mpd_t *dec)280{281return !(dec->flags & MPD_SPECIAL);282}283284/* Infinite */285ALWAYS_INLINE int286mpd_isinfinite(const mpd_t *dec)287{288return dec->flags & MPD_INF;289}290291/* NaN */292ALWAYS_INLINE int293mpd_isnan(const mpd_t *dec)294{295return dec->flags & (MPD_NAN|MPD_SNAN);296}297298/* Negative */299ALWAYS_INLINE int300mpd_isnegative(const mpd_t *dec)301{302return dec->flags & MPD_NEG;303}304305/* Positive */306ALWAYS_INLINE int307mpd_ispositive(const mpd_t *dec)308{309return !(dec->flags & MPD_NEG);310}311312/* qNaN */313ALWAYS_INLINE int314mpd_isqnan(const mpd_t *dec)315{316return dec->flags & MPD_NAN;317}318319/* Signed */320ALWAYS_INLINE int321mpd_issigned(const mpd_t *dec)322{323return dec->flags & MPD_NEG;324}325326/* sNaN */327ALWAYS_INLINE int328mpd_issnan(const mpd_t *dec)329{330return dec->flags & MPD_SNAN;331}332333/* Special */334ALWAYS_INLINE int335mpd_isspecial(const mpd_t *dec)336{337return dec->flags & MPD_SPECIAL;338}339340/* Zero */341ALWAYS_INLINE int342mpd_iszero(const mpd_t *dec)343{344return !mpd_isspecial(dec) && mpd_msword(dec) == 0;345}346347/* Test for zero when specials have been ruled out already */348ALWAYS_INLINE int349mpd_iszerocoeff(const mpd_t *dec)350{351return mpd_msword(dec) == 0;352}353354/* Normal */355inline int356mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx)357{358if (mpd_isspecial(dec)) return 0;359if (mpd_iszerocoeff(dec)) return 0;360361return mpd_adjexp(dec) >= ctx->emin;362}363364/* Subnormal */365inline int366mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx)367{368if (mpd_isspecial(dec)) return 0;369if (mpd_iszerocoeff(dec)) return 0;370371return mpd_adjexp(dec) < ctx->emin;372}373374/* Odd word */375ALWAYS_INLINE int376mpd_isoddword(mpd_uint_t word)377{378return word & 1;379}380381/* Odd coefficient */382ALWAYS_INLINE int383mpd_isoddcoeff(const mpd_t *dec)384{385return mpd_isoddword(dec->data[0]);386}387388/* 0 if dec is positive, 1 if dec is negative */389ALWAYS_INLINE uint8_t390mpd_sign(const mpd_t *dec)391{392return dec->flags & MPD_NEG;393}394395/* 1 if dec is positive, -1 if dec is negative */396ALWAYS_INLINE int397mpd_arith_sign(const mpd_t *dec)398{399return 1 - 2 * mpd_isnegative(dec);400}401402/* Radix */403ALWAYS_INLINE long404mpd_radix(void)405{406return 10;407}408409/* Dynamic decimal */410ALWAYS_INLINE int411mpd_isdynamic(const mpd_t *dec)412{413return !(dec->flags & MPD_STATIC);414}415416/* Static decimal */417ALWAYS_INLINE int418mpd_isstatic(const mpd_t *dec)419{420return dec->flags & MPD_STATIC;421}422423/* Data of decimal is dynamic */424ALWAYS_INLINE int425mpd_isdynamic_data(const mpd_t *dec)426{427return !(dec->flags & MPD_DATAFLAGS);428}429430/* Data of decimal is static */431ALWAYS_INLINE int432mpd_isstatic_data(const mpd_t *dec)433{434return dec->flags & MPD_STATIC_DATA;435}436437/* Data of decimal is shared */438ALWAYS_INLINE int439mpd_isshared_data(const mpd_t *dec)440{441return dec->flags & MPD_SHARED_DATA;442}443444/* Data of decimal is const */445ALWAYS_INLINE int446mpd_isconst_data(const mpd_t *dec)447{448return dec->flags & MPD_CONST_DATA;449}450451452/******************************************************************************/453/* Inline memory handling */454/******************************************************************************/455456/* Fill destination with zeros */457ALWAYS_INLINE void458mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len)459{460mpd_size_t i;461462for (i = 0; i < len; i++) {463dest[i] = 0;464}465}466467/* Free a decimal */468ALWAYS_INLINE void469mpd_del(mpd_t *dec)470{471if (mpd_isdynamic_data(dec)) {472mpd_free(dec->data);473}474if (mpd_isdynamic(dec)) {475mpd_free(dec);476}477}478479/*480* Resize the coefficient. Existing data up to 'nwords' is left untouched.481* Return 1 on success, 0 otherwise.482*483* Input invariant: MPD_MINALLOC <= result->alloc.484*485* Case nwords == result->alloc:486* 'result' is unchanged. Return 1.487*488* Case nwords > result->alloc:489* Case realloc success:490* The value of 'result' does not change. Return 1.491* Case realloc failure:492* 'result' is NaN, status is updated with MPD_Malloc_error. Return 0.493*494* Case nwords < result->alloc:495* Case is_static_data or realloc failure [1]:496* 'result' is unchanged. Return 1.497* Case realloc success:498* The value of result is undefined (expected). Return 1.499*500*501* [1] In that case the old (now oversized) area is still valid.502*/503ALWAYS_INLINE int504mpd_qresize(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)505{506assert(!mpd_isconst_data(result)); /* illegal operation for a const */507assert(!mpd_isshared_data(result)); /* illegal operation for a shared */508assert(MPD_MINALLOC <= result->alloc);509510nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords;511if (nwords == result->alloc) {512return 1;513}514if (mpd_isstatic_data(result)) {515if (nwords > result->alloc) {516return mpd_switch_to_dyn(result, nwords, status);517}518return 1;519}520521return mpd_realloc_dyn(result, nwords, status);522}523524/* Same as mpd_qresize, but do not set the result no NaN on failure. */525static ALWAYS_INLINE int526mpd_qresize_cxx(mpd_t *result, mpd_ssize_t nwords)527{528assert(!mpd_isconst_data(result)); /* illegal operation for a const */529assert(!mpd_isshared_data(result)); /* illegal operation for a shared */530assert(MPD_MINALLOC <= result->alloc);531532nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords;533if (nwords == result->alloc) {534return 1;535}536if (mpd_isstatic_data(result)) {537if (nwords > result->alloc) {538return mpd_switch_to_dyn_cxx(result, nwords);539}540return 1;541}542543return mpd_realloc_dyn_cxx(result, nwords);544}545546/* Same as mpd_qresize, but the complete coefficient (including the old547* memory area!) is initialized to zero. */548ALWAYS_INLINE int549mpd_qresize_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)550{551assert(!mpd_isconst_data(result)); /* illegal operation for a const */552assert(!mpd_isshared_data(result)); /* illegal operation for a shared */553assert(MPD_MINALLOC <= result->alloc);554555nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords;556if (nwords != result->alloc) {557if (mpd_isstatic_data(result)) {558if (nwords > result->alloc) {559return mpd_switch_to_dyn_zero(result, nwords, status);560}561}562else if (!mpd_realloc_dyn(result, nwords, status)) {563return 0;564}565}566567mpd_uint_zero(result->data, nwords);568return 1;569}570571/*572* Reduce memory size for the coefficient to MPD_MINALLOC. In theory,573* realloc may fail even when reducing the memory size. But in that case574* the old memory area is always big enough, so checking for MPD_Malloc_error575* is not imperative.576*/577ALWAYS_INLINE void578mpd_minalloc(mpd_t *result)579{580assert(!mpd_isconst_data(result)); /* illegal operation for a const */581assert(!mpd_isshared_data(result)); /* illegal operation for a shared */582583if (!mpd_isstatic_data(result) && result->alloc > MPD_MINALLOC) {584uint8_t err = 0;585result->data = mpd_realloc(result->data, MPD_MINALLOC,586sizeof *result->data, &err);587if (!err) {588result->alloc = MPD_MINALLOC;589}590}591}592593int594mpd_resize(mpd_t *result, mpd_ssize_t nwords, mpd_context_t *ctx)595{596uint32_t status = 0;597if (!mpd_qresize(result, nwords, &status)) {598mpd_addstatus_raise(ctx, status);599return 0;600}601return 1;602}603604int605mpd_resize_zero(mpd_t *result, mpd_ssize_t nwords, mpd_context_t *ctx)606{607uint32_t status = 0;608if (!mpd_qresize_zero(result, nwords, &status)) {609mpd_addstatus_raise(ctx, status);610return 0;611}612return 1;613}614615616/******************************************************************************/617/* Set attributes of a decimal */618/******************************************************************************/619620/* Set digits. Assumption: result->len is initialized and > 0. */621inline void622mpd_setdigits(mpd_t *result)623{624mpd_ssize_t wdigits = mpd_word_digits(mpd_msword(result));625result->digits = wdigits + (result->len-1) * MPD_RDIGITS;626}627628/* Set sign */629ALWAYS_INLINE void630mpd_set_sign(mpd_t *result, uint8_t sign)631{632result->flags &= ~MPD_NEG;633result->flags |= sign;634}635636/* Copy sign from another decimal */637ALWAYS_INLINE void638mpd_signcpy(mpd_t *result, const mpd_t *a)639{640uint8_t sign = a->flags&MPD_NEG;641642result->flags &= ~MPD_NEG;643result->flags |= sign;644}645646/* Set infinity */647ALWAYS_INLINE void648mpd_set_infinity(mpd_t *result)649{650result->flags &= ~MPD_SPECIAL;651result->flags |= MPD_INF;652}653654/* Set qNaN */655ALWAYS_INLINE void656mpd_set_qnan(mpd_t *result)657{658result->flags &= ~MPD_SPECIAL;659result->flags |= MPD_NAN;660}661662/* Set sNaN */663ALWAYS_INLINE void664mpd_set_snan(mpd_t *result)665{666result->flags &= ~MPD_SPECIAL;667result->flags |= MPD_SNAN;668}669670/* Set to negative */671ALWAYS_INLINE void672mpd_set_negative(mpd_t *result)673{674result->flags |= MPD_NEG;675}676677/* Set to positive */678ALWAYS_INLINE void679mpd_set_positive(mpd_t *result)680{681result->flags &= ~MPD_NEG;682}683684/* Set to dynamic */685ALWAYS_INLINE void686mpd_set_dynamic(mpd_t *result)687{688result->flags &= ~MPD_STATIC;689}690691/* Set to static */692ALWAYS_INLINE void693mpd_set_static(mpd_t *result)694{695result->flags |= MPD_STATIC;696}697698/* Set data to dynamic */699ALWAYS_INLINE void700mpd_set_dynamic_data(mpd_t *result)701{702result->flags &= ~MPD_DATAFLAGS;703}704705/* Set data to static */706ALWAYS_INLINE void707mpd_set_static_data(mpd_t *result)708{709result->flags &= ~MPD_DATAFLAGS;710result->flags |= MPD_STATIC_DATA;711}712713/* Set data to shared */714ALWAYS_INLINE void715mpd_set_shared_data(mpd_t *result)716{717result->flags &= ~MPD_DATAFLAGS;718result->flags |= MPD_SHARED_DATA;719}720721/* Set data to const */722ALWAYS_INLINE void723mpd_set_const_data(mpd_t *result)724{725result->flags &= ~MPD_DATAFLAGS;726result->flags |= MPD_CONST_DATA;727}728729/* Clear flags, preserving memory attributes. */730ALWAYS_INLINE void731mpd_clear_flags(mpd_t *result)732{733result->flags &= (MPD_STATIC|MPD_DATAFLAGS);734}735736/* Set flags, preserving memory attributes. */737ALWAYS_INLINE void738mpd_set_flags(mpd_t *result, uint8_t flags)739{740result->flags &= (MPD_STATIC|MPD_DATAFLAGS);741result->flags |= flags;742}743744/* Copy flags, preserving memory attributes of result. */745ALWAYS_INLINE void746mpd_copy_flags(mpd_t *result, const mpd_t *a)747{748uint8_t aflags = a->flags;749result->flags &= (MPD_STATIC|MPD_DATAFLAGS);750result->flags |= (aflags & ~(MPD_STATIC|MPD_DATAFLAGS));751}752753/* Initialize a workcontext from ctx. Set traps, flags and newtrap to 0. */754static inline void755mpd_workcontext(mpd_context_t *workctx, const mpd_context_t *ctx)756{757workctx->prec = ctx->prec;758workctx->emax = ctx->emax;759workctx->emin = ctx->emin;760workctx->round = ctx->round;761workctx->traps = 0;762workctx->status = 0;763workctx->newtrap = 0;764workctx->clamp = ctx->clamp;765workctx->allcr = ctx->allcr;766}767768769/******************************************************************************/770/* Getting and setting parts of decimals */771/******************************************************************************/772773/* Flip the sign of a decimal */774static inline void775_mpd_negate(mpd_t *dec)776{777dec->flags ^= MPD_NEG;778}779780/* Set coefficient to zero */781void782mpd_zerocoeff(mpd_t *result)783{784mpd_minalloc(result);785result->digits = 1;786result->len = 1;787result->data[0] = 0;788}789790/* Set the coefficient to all nines. */791void792mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)793{794mpd_ssize_t len, r;795796_mpd_idiv_word(&len, &r, ctx->prec, MPD_RDIGITS);797len = (r == 0) ? len : len+1;798799if (!mpd_qresize(result, len, status)) {800return;801}802803result->len = len;804result->digits = ctx->prec;805806--len;807if (r > 0) {808result->data[len--] = mpd_pow10[r]-1;809}810for (; len >= 0; --len) {811result->data[len] = MPD_RADIX-1;812}813}814815/*816* Cut off the most significant digits so that the rest fits in ctx->prec.817* Cannot fail.818*/819static void820_mpd_cap(mpd_t *result, const mpd_context_t *ctx)821{822uint32_t dummy;823mpd_ssize_t len, r;824825if (result->len > 0 && result->digits > ctx->prec) {826_mpd_idiv_word(&len, &r, ctx->prec, MPD_RDIGITS);827len = (r == 0) ? len : len+1;828829if (r != 0) {830result->data[len-1] %= mpd_pow10[r];831}832833len = _mpd_real_size(result->data, len);834/* resize to fewer words cannot fail */835mpd_qresize(result, len, &dummy);836result->len = len;837mpd_setdigits(result);838}839if (mpd_iszero(result)) {840_settriple(result, mpd_sign(result), 0, result->exp);841}842}843844/*845* Cut off the most significant digits of a NaN payload so that the rest846* fits in ctx->prec - ctx->clamp. Cannot fail.847*/848static void849_mpd_fix_nan(mpd_t *result, const mpd_context_t *ctx)850{851uint32_t dummy;852mpd_ssize_t prec;853mpd_ssize_t len, r;854855prec = ctx->prec - ctx->clamp;856if (result->len > 0 && result->digits > prec) {857if (prec == 0) {858mpd_minalloc(result);859result->len = result->digits = 0;860}861else {862_mpd_idiv_word(&len, &r, prec, MPD_RDIGITS);863len = (r == 0) ? len : len+1;864865if (r != 0) {866result->data[len-1] %= mpd_pow10[r];867}868869len = _mpd_real_size(result->data, len);870/* resize to fewer words cannot fail */871mpd_qresize(result, len, &dummy);872result->len = len;873mpd_setdigits(result);874if (mpd_iszerocoeff(result)) {875/* NaN0 is not a valid representation */876result->len = result->digits = 0;877}878}879}880}881882/*883* Get n most significant digits from a decimal, where 0 < n <= MPD_UINT_DIGITS.884* Assumes MPD_UINT_DIGITS == MPD_RDIGITS+1, which is true for 32 and 64 bit885* machines.886*887* The result of the operation will be in lo. If the operation is impossible,888* hi will be nonzero. This is used to indicate an error.889*/890static inline void891_mpd_get_msdigits(mpd_uint_t *hi, mpd_uint_t *lo, const mpd_t *dec,892unsigned int n)893{894mpd_uint_t r, tmp;895896assert(0 < n && n <= MPD_RDIGITS+1);897898_mpd_div_word(&tmp, &r, dec->digits, MPD_RDIGITS);899r = (r == 0) ? MPD_RDIGITS : r; /* digits in the most significant word */900901*hi = 0;902*lo = dec->data[dec->len-1];903if (n <= r) {904*lo /= mpd_pow10[r-n];905}906else if (dec->len > 1) {907/* at this point 1 <= r < n <= MPD_RDIGITS+1 */908_mpd_mul_words(hi, lo, *lo, mpd_pow10[n-r]);909tmp = dec->data[dec->len-2] / mpd_pow10[MPD_RDIGITS-(n-r)];910*lo = *lo + tmp;911if (*lo < tmp) (*hi)++;912}913}914915916/******************************************************************************/917/* Gathering information about a decimal */918/******************************************************************************/919920/* The real size of the coefficient without leading zero words. */921static inline mpd_ssize_t922_mpd_real_size(mpd_uint_t *data, mpd_ssize_t size)923{924while (size > 1 && data[size-1] == 0) {925size--;926}927928return size;929}930931/* Return number of trailing zeros. No errors are possible. */932mpd_ssize_t933mpd_trail_zeros(const mpd_t *dec)934{935mpd_uint_t word;936mpd_ssize_t i, tz = 0;937938for (i=0; i < dec->len; ++i) {939if (dec->data[i] != 0) {940word = dec->data[i];941tz = i * MPD_RDIGITS;942while (word % 10 == 0) {943word /= 10;944tz++;945}946break;947}948}949950return tz;951}952953/* Integer: Undefined for specials */954static int955_mpd_isint(const mpd_t *dec)956{957mpd_ssize_t tz;958959if (mpd_iszerocoeff(dec)) {960return 1;961}962963tz = mpd_trail_zeros(dec);964return (dec->exp + tz >= 0);965}966967/* Integer */968int969mpd_isinteger(const mpd_t *dec)970{971if (mpd_isspecial(dec)) {972return 0;973}974return _mpd_isint(dec);975}976977/* Word is a power of 10 */978static int979mpd_word_ispow10(mpd_uint_t word)980{981int n;982983n = mpd_word_digits(word);984if (word == mpd_pow10[n-1]) {985return 1;986}987988return 0;989}990991/* Coefficient is a power of 10 */992static int993mpd_coeff_ispow10(const mpd_t *dec)994{995if (mpd_word_ispow10(mpd_msword(dec))) {996if (_mpd_isallzero(dec->data, dec->len-1)) {997return 1;998}999}10001001return 0;1002}10031004/* All digits of a word are nines */1005static int1006mpd_word_isallnine(mpd_uint_t word)1007{1008int n;10091010n = mpd_word_digits(word);1011if (word == mpd_pow10[n]-1) {1012return 1;1013}10141015return 0;1016}10171018/* All digits of the coefficient are nines */1019static int1020mpd_coeff_isallnine(const mpd_t *dec)1021{1022if (mpd_word_isallnine(mpd_msword(dec))) {1023if (_mpd_isallnine(dec->data, dec->len-1)) {1024return 1;1025}1026}10271028return 0;1029}10301031/* Odd decimal: Undefined for non-integers! */1032int1033mpd_isodd(const mpd_t *dec)1034{1035mpd_uint_t q, r;1036assert(mpd_isinteger(dec));1037if (mpd_iszerocoeff(dec)) return 0;1038if (dec->exp < 0) {1039_mpd_div_word(&q, &r, -dec->exp, MPD_RDIGITS);1040q = dec->data[q] / mpd_pow10[r];1041return mpd_isoddword(q);1042}1043return dec->exp == 0 && mpd_isoddword(dec->data[0]);1044}10451046/* Even: Undefined for non-integers! */1047int1048mpd_iseven(const mpd_t *dec)1049{1050return !mpd_isodd(dec);1051}10521053/******************************************************************************/1054/* Getting and setting decimals */1055/******************************************************************************/10561057/* Internal function: Set a static decimal from a triple, no error checking. */1058static void1059_ssettriple(mpd_t *result, uint8_t sign, mpd_uint_t a, mpd_ssize_t exp)1060{1061mpd_set_flags(result, sign);1062result->exp = exp;1063_mpd_div_word(&result->data[1], &result->data[0], a, MPD_RADIX);1064result->len = (result->data[1] == 0) ? 1 : 2;1065mpd_setdigits(result);1066}10671068/* Internal function: Set a decimal from a triple, no error checking. */1069static void1070_settriple(mpd_t *result, uint8_t sign, mpd_uint_t a, mpd_ssize_t exp)1071{1072mpd_minalloc(result);1073mpd_set_flags(result, sign);1074result->exp = exp;1075_mpd_div_word(&result->data[1], &result->data[0], a, MPD_RADIX);1076result->len = (result->data[1] == 0) ? 1 : 2;1077mpd_setdigits(result);1078}10791080/* Set a special number from a triple */1081void1082mpd_setspecial(mpd_t *result, uint8_t sign, uint8_t type)1083{1084mpd_minalloc(result);1085result->flags &= ~(MPD_NEG|MPD_SPECIAL);1086result->flags |= (sign|type);1087result->exp = result->digits = result->len = 0;1088}10891090/* Set result of NaN with an error status */1091void1092mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status)1093{1094mpd_minalloc(result);1095mpd_set_qnan(result);1096mpd_set_positive(result);1097result->exp = result->digits = result->len = 0;1098*status |= flags;1099}11001101/* quietly set a static decimal from an mpd_ssize_t */1102void1103mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx,1104uint32_t *status)1105{1106mpd_uint_t u;1107uint8_t sign = MPD_POS;11081109if (a < 0) {1110if (a == MPD_SSIZE_MIN) {1111u = (mpd_uint_t)MPD_SSIZE_MAX +1112(-(MPD_SSIZE_MIN+MPD_SSIZE_MAX));1113}1114else {1115u = -a;1116}1117sign = MPD_NEG;1118}1119else {1120u = a;1121}1122_ssettriple(result, sign, u, 0);1123mpd_qfinalize(result, ctx, status);1124}11251126/* quietly set a static decimal from an mpd_uint_t */1127void1128mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx,1129uint32_t *status)1130{1131_ssettriple(result, MPD_POS, a, 0);1132mpd_qfinalize(result, ctx, status);1133}11341135/* quietly set a static decimal from an int32_t */1136void1137mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx,1138uint32_t *status)1139{1140mpd_qsset_ssize(result, a, ctx, status);1141}11421143/* quietly set a static decimal from a uint32_t */1144void1145mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx,1146uint32_t *status)1147{1148mpd_qsset_uint(result, a, ctx, status);1149}11501151#ifdef CONFIG_641152/* quietly set a static decimal from an int64_t */1153void1154mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,1155uint32_t *status)1156{1157mpd_qsset_ssize(result, a, ctx, status);1158}11591160/* quietly set a static decimal from a uint64_t */1161void1162mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,1163uint32_t *status)1164{1165mpd_qsset_uint(result, a, ctx, status);1166}1167#endif11681169/* quietly set a decimal from an mpd_ssize_t */1170void1171mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx,1172uint32_t *status)1173{1174mpd_minalloc(result);1175mpd_qsset_ssize(result, a, ctx, status);1176}11771178/* quietly set a decimal from an mpd_uint_t */1179void1180mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx,1181uint32_t *status)1182{1183_settriple(result, MPD_POS, a, 0);1184mpd_qfinalize(result, ctx, status);1185}11861187/* quietly set a decimal from an int32_t */1188void1189mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx,1190uint32_t *status)1191{1192mpd_qset_ssize(result, a, ctx, status);1193}11941195/* quietly set a decimal from a uint32_t */1196void1197mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx,1198uint32_t *status)1199{1200mpd_qset_uint(result, a, ctx, status);1201}12021203#if defined(CONFIG_32) && !defined(LEGACY_COMPILER)1204/* set a decimal from a uint64_t */1205static void1206_c32setu64(mpd_t *result, uint64_t u, uint8_t sign, uint32_t *status)1207{1208mpd_uint_t w[3];1209uint64_t q;1210int i, len;12111212len = 0;1213do {1214q = u / MPD_RADIX;1215w[len] = (mpd_uint_t)(u - q * MPD_RADIX);1216u = q; len++;1217} while (u != 0);12181219if (!mpd_qresize(result, len, status)) {1220return;1221}1222for (i = 0; i < len; i++) {1223result->data[i] = w[i];1224}12251226mpd_set_flags(result, sign);1227result->exp = 0;1228result->len = len;1229mpd_setdigits(result);1230}12311232static void1233_c32_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,1234uint32_t *status)1235{1236_c32setu64(result, a, MPD_POS, status);1237mpd_qfinalize(result, ctx, status);1238}12391240/* set a decimal from an int64_t */1241static void1242_c32_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,1243uint32_t *status)1244{1245uint64_t u;1246uint8_t sign = MPD_POS;12471248if (a < 0) {1249if (a == INT64_MIN) {1250u = (uint64_t)INT64_MAX + (-(INT64_MIN+INT64_MAX));1251}1252else {1253u = -a;1254}1255sign = MPD_NEG;1256}1257else {1258u = a;1259}1260_c32setu64(result, u, sign, status);1261mpd_qfinalize(result, ctx, status);1262}1263#endif /* CONFIG_32 && !LEGACY_COMPILER */12641265#ifndef LEGACY_COMPILER1266/* quietly set a decimal from an int64_t */1267void1268mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,1269uint32_t *status)1270{1271#ifdef CONFIG_641272mpd_qset_ssize(result, a, ctx, status);1273#else1274_c32_qset_i64(result, a, ctx, status);1275#endif1276}12771278/* quietly set a decimal from an int64_t, use a maxcontext for conversion */1279void1280mpd_qset_i64_exact(mpd_t *result, int64_t a, uint32_t *status)1281{1282mpd_context_t maxcontext;12831284mpd_maxcontext(&maxcontext);1285#ifdef CONFIG_641286mpd_qset_ssize(result, a, &maxcontext, status);1287#else1288_c32_qset_i64(result, a, &maxcontext, status);1289#endif12901291if (*status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {1292/* we want exact results */1293mpd_seterror(result, MPD_Invalid_operation, status);1294}1295*status &= MPD_Errors;1296}12971298/* quietly set a decimal from a uint64_t */1299void1300mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,1301uint32_t *status)1302{1303#ifdef CONFIG_641304mpd_qset_uint(result, a, ctx, status);1305#else1306_c32_qset_u64(result, a, ctx, status);1307#endif1308}13091310/* quietly set a decimal from a uint64_t, use a maxcontext for conversion */1311void1312mpd_qset_u64_exact(mpd_t *result, uint64_t a, uint32_t *status)1313{1314mpd_context_t maxcontext;13151316mpd_maxcontext(&maxcontext);1317#ifdef CONFIG_641318mpd_qset_uint(result, a, &maxcontext, status);1319#else1320_c32_qset_u64(result, a, &maxcontext, status);1321#endif13221323if (*status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {1324/* we want exact results */1325mpd_seterror(result, MPD_Invalid_operation, status);1326}1327*status &= MPD_Errors;1328}1329#endif /* !LEGACY_COMPILER */13301331/*1332* Quietly get an mpd_uint_t from a decimal. Assumes1333* MPD_UINT_DIGITS == MPD_RDIGITS+1, which is true for1334* 32 and 64 bit machines.1335*1336* If the operation is impossible, MPD_Invalid_operation is set.1337*/1338static mpd_uint_t1339_mpd_qget_uint(int use_sign, const mpd_t *a, uint32_t *status)1340{1341mpd_t tmp;1342mpd_uint_t tmp_data[2];1343mpd_uint_t lo, hi;13441345if (mpd_isspecial(a)) {1346*status |= MPD_Invalid_operation;1347return MPD_UINT_MAX;1348}1349if (mpd_iszero(a)) {1350return 0;1351}1352if (use_sign && mpd_isnegative(a)) {1353*status |= MPD_Invalid_operation;1354return MPD_UINT_MAX;1355}13561357if (a->digits+a->exp > MPD_RDIGITS+1) {1358*status |= MPD_Invalid_operation;1359return MPD_UINT_MAX;1360}13611362if (a->exp < 0) {1363if (!_mpd_isint(a)) {1364*status |= MPD_Invalid_operation;1365return MPD_UINT_MAX;1366}1367/* At this point a->digits+a->exp <= MPD_RDIGITS+1,1368* so the shift fits. */1369tmp.data = tmp_data;1370tmp.flags = MPD_STATIC|MPD_STATIC_DATA;1371tmp.alloc = 2;1372mpd_qsshiftr(&tmp, a, -a->exp);1373tmp.exp = 0;1374a = &tmp;1375}13761377_mpd_get_msdigits(&hi, &lo, a, MPD_RDIGITS+1);1378if (hi) {1379*status |= MPD_Invalid_operation;1380return MPD_UINT_MAX;1381}13821383if (a->exp > 0) {1384_mpd_mul_words(&hi, &lo, lo, mpd_pow10[a->exp]);1385if (hi) {1386*status |= MPD_Invalid_operation;1387return MPD_UINT_MAX;1388}1389}13901391return lo;1392}13931394/*1395* Sets Invalid_operation for:1396* - specials1397* - negative numbers (except negative zero)1398* - non-integers1399* - overflow1400*/1401mpd_uint_t1402mpd_qget_uint(const mpd_t *a, uint32_t *status)1403{1404return _mpd_qget_uint(1, a, status);1405}14061407/* Same as above, but gets the absolute value, i.e. the sign is ignored. */1408mpd_uint_t1409mpd_qabs_uint(const mpd_t *a, uint32_t *status)1410{1411return _mpd_qget_uint(0, a, status);1412}14131414/* quietly get an mpd_ssize_t from a decimal */1415mpd_ssize_t1416mpd_qget_ssize(const mpd_t *a, uint32_t *status)1417{1418uint32_t workstatus = 0;1419mpd_uint_t u;1420int isneg;14211422u = mpd_qabs_uint(a, &workstatus);1423if (workstatus&MPD_Invalid_operation) {1424*status |= workstatus;1425return MPD_SSIZE_MAX;1426}14271428isneg = mpd_isnegative(a);1429if (u <= MPD_SSIZE_MAX) {1430return isneg ? -((mpd_ssize_t)u) : (mpd_ssize_t)u;1431}1432else if (isneg && u+(MPD_SSIZE_MIN+MPD_SSIZE_MAX) == MPD_SSIZE_MAX) {1433return MPD_SSIZE_MIN;1434}14351436*status |= MPD_Invalid_operation;1437return MPD_SSIZE_MAX;1438}14391440#if defined(CONFIG_32) && !defined(LEGACY_COMPILER)1441/*1442* Quietly get a uint64_t from a decimal. If the operation is impossible,1443* MPD_Invalid_operation is set.1444*/1445static uint64_t1446_c32_qget_u64(int use_sign, const mpd_t *a, uint32_t *status)1447{1448MPD_NEW_STATIC(tmp,0,0,20,3);1449mpd_context_t maxcontext;1450uint64_t ret;14511452tmp_data[0] = 709551615;1453tmp_data[1] = 446744073;1454tmp_data[2] = 18;14551456if (mpd_isspecial(a)) {1457*status |= MPD_Invalid_operation;1458return UINT64_MAX;1459}1460if (mpd_iszero(a)) {1461return 0;1462}1463if (use_sign && mpd_isnegative(a)) {1464*status |= MPD_Invalid_operation;1465return UINT64_MAX;1466}1467if (!_mpd_isint(a)) {1468*status |= MPD_Invalid_operation;1469return UINT64_MAX;1470}14711472if (_mpd_cmp_abs(a, &tmp) > 0) {1473*status |= MPD_Invalid_operation;1474return UINT64_MAX;1475}14761477mpd_maxcontext(&maxcontext);1478mpd_qrescale(&tmp, a, 0, &maxcontext, &maxcontext.status);1479maxcontext.status &= ~MPD_Rounded;1480if (maxcontext.status != 0) {1481*status |= (maxcontext.status|MPD_Invalid_operation); /* GCOV_NOT_REACHED */1482return UINT64_MAX; /* GCOV_NOT_REACHED */1483}14841485ret = 0;1486switch (tmp.len) {1487case 3:1488ret += (uint64_t)tmp_data[2] * 1000000000000000000ULL;1489case 2:1490ret += (uint64_t)tmp_data[1] * 1000000000ULL;1491case 1:1492ret += tmp_data[0];1493break;1494default:1495abort(); /* GCOV_NOT_REACHED */1496}14971498return ret;1499}15001501static int64_t1502_c32_qget_i64(const mpd_t *a, uint32_t *status)1503{1504uint64_t u;1505int isneg;15061507u = _c32_qget_u64(0, a, status);1508if (*status&MPD_Invalid_operation) {1509return INT64_MAX;1510}15111512isneg = mpd_isnegative(a);1513if (u <= INT64_MAX) {1514return isneg ? -((int64_t)u) : (int64_t)u;1515}1516else if (isneg && u+(INT64_MIN+INT64_MAX) == INT64_MAX) {1517return INT64_MIN;1518}15191520*status |= MPD_Invalid_operation;1521return INT64_MAX;1522}1523#endif /* CONFIG_32 && !LEGACY_COMPILER */15241525#ifdef CONFIG_641526/* quietly get a uint64_t from a decimal */1527uint64_t1528mpd_qget_u64(const mpd_t *a, uint32_t *status)1529{1530return mpd_qget_uint(a, status);1531}15321533/* quietly get an int64_t from a decimal */1534int64_t1535mpd_qget_i64(const mpd_t *a, uint32_t *status)1536{1537return mpd_qget_ssize(a, status);1538}15391540/* quietly get a uint32_t from a decimal */1541uint32_t1542mpd_qget_u32(const mpd_t *a, uint32_t *status)1543{1544uint32_t workstatus = 0;1545uint64_t x = mpd_qget_uint(a, &workstatus);15461547if (workstatus&MPD_Invalid_operation) {1548*status |= workstatus;1549return UINT32_MAX;1550}1551if (x > UINT32_MAX) {1552*status |= MPD_Invalid_operation;1553return UINT32_MAX;1554}15551556return (uint32_t)x;1557}15581559/* quietly get an int32_t from a decimal */1560int32_t1561mpd_qget_i32(const mpd_t *a, uint32_t *status)1562{1563uint32_t workstatus = 0;1564int64_t x = mpd_qget_ssize(a, &workstatus);15651566if (workstatus&MPD_Invalid_operation) {1567*status |= workstatus;1568return INT32_MAX;1569}1570if (x < INT32_MIN || x > INT32_MAX) {1571*status |= MPD_Invalid_operation;1572return INT32_MAX;1573}15741575return (int32_t)x;1576}1577#else1578#ifndef LEGACY_COMPILER1579/* quietly get a uint64_t from a decimal */1580uint64_t1581mpd_qget_u64(const mpd_t *a, uint32_t *status)1582{1583uint32_t workstatus = 0;1584uint64_t x = _c32_qget_u64(1, a, &workstatus);1585*status |= workstatus;1586return x;1587}15881589/* quietly get an int64_t from a decimal */1590int64_t1591mpd_qget_i64(const mpd_t *a, uint32_t *status)1592{1593uint32_t workstatus = 0;1594int64_t x = _c32_qget_i64(a, &workstatus);1595*status |= workstatus;1596return x;1597}1598#endif15991600/* quietly get a uint32_t from a decimal */1601uint32_t1602mpd_qget_u32(const mpd_t *a, uint32_t *status)1603{1604return mpd_qget_uint(a, status);1605}16061607/* quietly get an int32_t from a decimal */1608int32_t1609mpd_qget_i32(const mpd_t *a, uint32_t *status)1610{1611return mpd_qget_ssize(a, status);1612}1613#endif161416151616/******************************************************************************/1617/* Filtering input of functions, finalizing output of functions */1618/******************************************************************************/16191620/*1621* Check if the operand is NaN, copy to result and return 1 if this is1622* the case. Copying can fail since NaNs are allowed to have a payload that1623* does not fit in MPD_MINALLOC.1624*/1625int1626mpd_qcheck_nan(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,1627uint32_t *status)1628{1629if (mpd_isnan(a)) {1630*status |= mpd_issnan(a) ? MPD_Invalid_operation : 0;1631mpd_qcopy(result, a, status);1632mpd_set_qnan(result);1633_mpd_fix_nan(result, ctx);1634return 1;1635}1636return 0;1637}16381639/*1640* Check if either operand is NaN, copy to result and return 1 if this1641* is the case. Copying can fail since NaNs are allowed to have a payload1642* that does not fit in MPD_MINALLOC.1643*/1644int1645mpd_qcheck_nans(mpd_t *result, const mpd_t *a, const mpd_t *b,1646const mpd_context_t *ctx, uint32_t *status)1647{1648if ((a->flags|b->flags)&(MPD_NAN|MPD_SNAN)) {1649const mpd_t *choice = b;1650if (mpd_issnan(a)) {1651choice = a;1652*status |= MPD_Invalid_operation;1653}1654else if (mpd_issnan(b)) {1655*status |= MPD_Invalid_operation;1656}1657else if (mpd_isqnan(a)) {1658choice = a;1659}1660mpd_qcopy(result, choice, status);1661mpd_set_qnan(result);1662_mpd_fix_nan(result, ctx);1663return 1;1664}1665return 0;1666}16671668/*1669* Check if one of the operands is NaN, copy to result and return 1 if this1670* is the case. Copying can fail since NaNs are allowed to have a payload1671* that does not fit in MPD_MINALLOC.1672*/1673static int1674mpd_qcheck_3nans(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c,1675const mpd_context_t *ctx, uint32_t *status)1676{1677if ((a->flags|b->flags|c->flags)&(MPD_NAN|MPD_SNAN)) {1678const mpd_t *choice = c;1679if (mpd_issnan(a)) {1680choice = a;1681*status |= MPD_Invalid_operation;1682}1683else if (mpd_issnan(b)) {1684choice = b;1685*status |= MPD_Invalid_operation;1686}1687else if (mpd_issnan(c)) {1688*status |= MPD_Invalid_operation;1689}1690else if (mpd_isqnan(a)) {1691choice = a;1692}1693else if (mpd_isqnan(b)) {1694choice = b;1695}1696mpd_qcopy(result, choice, status);1697mpd_set_qnan(result);1698_mpd_fix_nan(result, ctx);1699return 1;1700}1701return 0;1702}17031704/* Check if rounding digit 'rnd' leads to an increment. */1705static inline int1706_mpd_rnd_incr(const mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx)1707{1708int ld;17091710switch (ctx->round) {1711case MPD_ROUND_DOWN: case MPD_ROUND_TRUNC:1712return 0;1713case MPD_ROUND_HALF_UP:1714return (rnd >= 5);1715case MPD_ROUND_HALF_EVEN:1716return (rnd > 5) || ((rnd == 5) && mpd_isoddcoeff(dec));1717case MPD_ROUND_CEILING:1718return !(rnd == 0 || mpd_isnegative(dec));1719case MPD_ROUND_FLOOR:1720return !(rnd == 0 || mpd_ispositive(dec));1721case MPD_ROUND_HALF_DOWN:1722return (rnd > 5);1723case MPD_ROUND_UP:1724return !(rnd == 0);1725case MPD_ROUND_05UP:1726ld = (int)mpd_lsd(dec->data[0]);1727return (!(rnd == 0) && (ld == 0 || ld == 5));1728default:1729/* Without a valid context, further results will be undefined. */1730return 0; /* GCOV_NOT_REACHED */1731}1732}17331734/*1735* Apply rounding to a decimal that has been right-shifted into a full1736* precision decimal. If an increment leads to an overflow of the precision,1737* adjust the coefficient and the exponent and check the new exponent for1738* overflow.1739*/1740static inline void1741_mpd_apply_round(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,1742uint32_t *status)1743{1744if (_mpd_rnd_incr(dec, rnd, ctx)) {1745/* We have a number with exactly ctx->prec digits. The increment1746* can only lead to an overflow if the decimal is all nines. In1747* that case, the result is a power of ten with prec+1 digits.1748*1749* If the precision is a multiple of MPD_RDIGITS, this situation is1750* detected by _mpd_baseincr returning a carry.1751* If the precision is not a multiple of MPD_RDIGITS, we have to1752* check if the result has one digit too many.1753*/1754mpd_uint_t carry = _mpd_baseincr(dec->data, dec->len);1755if (carry) {1756dec->data[dec->len-1] = mpd_pow10[MPD_RDIGITS-1];1757dec->exp += 1;1758_mpd_check_exp(dec, ctx, status);1759return;1760}1761mpd_setdigits(dec);1762if (dec->digits > ctx->prec) {1763mpd_qshiftr_inplace(dec, 1);1764dec->exp += 1;1765dec->digits = ctx->prec;1766_mpd_check_exp(dec, ctx, status);1767}1768}1769}17701771/*1772* Apply rounding to a decimal. Allow overflow of the precision.1773*/1774static inline void1775_mpd_apply_round_excess(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,1776uint32_t *status)1777{1778if (_mpd_rnd_incr(dec, rnd, ctx)) {1779mpd_uint_t carry = _mpd_baseincr(dec->data, dec->len);1780if (carry) {1781if (!mpd_qresize(dec, dec->len+1, status)) {1782return;1783}1784dec->data[dec->len] = 1;1785dec->len += 1;1786}1787mpd_setdigits(dec);1788}1789}17901791/*1792* Apply rounding to a decimal that has been right-shifted into a decimal1793* with full precision or less. Return failure if an increment would1794* overflow the precision.1795*/1796static inline int1797_mpd_apply_round_fit(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,1798uint32_t *status)1799{1800if (_mpd_rnd_incr(dec, rnd, ctx)) {1801mpd_uint_t carry = _mpd_baseincr(dec->data, dec->len);1802if (carry) {1803if (!mpd_qresize(dec, dec->len+1, status)) {1804return 0;1805}1806dec->data[dec->len] = 1;1807dec->len += 1;1808}1809mpd_setdigits(dec);1810if (dec->digits > ctx->prec) {1811mpd_seterror(dec, MPD_Invalid_operation, status);1812return 0;1813}1814}1815return 1;1816}18171818/* Check a normal number for overflow, underflow, clamping. If the operand1819is modified, it will be zero, special or (sub)normal with a coefficient1820that fits into the current context precision. */1821static inline void1822_mpd_check_exp(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)1823{1824mpd_ssize_t adjexp, etiny, shift;1825int rnd;18261827adjexp = mpd_adjexp(dec);1828if (adjexp > ctx->emax) {18291830if (mpd_iszerocoeff(dec)) {1831dec->exp = ctx->emax;1832if (ctx->clamp) {1833dec->exp -= (ctx->prec-1);1834}1835mpd_zerocoeff(dec);1836*status |= MPD_Clamped;1837return;1838}18391840switch (ctx->round) {1841case MPD_ROUND_HALF_UP: case MPD_ROUND_HALF_EVEN:1842case MPD_ROUND_HALF_DOWN: case MPD_ROUND_UP:1843case MPD_ROUND_TRUNC:1844mpd_setspecial(dec, mpd_sign(dec), MPD_INF);1845break;1846case MPD_ROUND_DOWN: case MPD_ROUND_05UP:1847mpd_qmaxcoeff(dec, ctx, status);1848dec->exp = ctx->emax - ctx->prec + 1;1849break;1850case MPD_ROUND_CEILING:1851if (mpd_isnegative(dec)) {1852mpd_qmaxcoeff(dec, ctx, status);1853dec->exp = ctx->emax - ctx->prec + 1;1854}1855else {1856mpd_setspecial(dec, MPD_POS, MPD_INF);1857}1858break;1859case MPD_ROUND_FLOOR:1860if (mpd_ispositive(dec)) {1861mpd_qmaxcoeff(dec, ctx, status);1862dec->exp = ctx->emax - ctx->prec + 1;1863}1864else {1865mpd_setspecial(dec, MPD_NEG, MPD_INF);1866}1867break;1868default: /* debug */1869abort(); /* GCOV_NOT_REACHED */1870}18711872*status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;18731874} /* fold down */1875else if (ctx->clamp && dec->exp > mpd_etop(ctx)) {1876/* At this point adjexp=exp+digits-1 <= emax and exp > etop=emax-prec+1:1877* (1) shift = exp -emax+prec-1 > 01878* (2) digits+shift = exp+digits-1 - emax + prec <= prec */1879shift = dec->exp - mpd_etop(ctx);1880if (!mpd_qshiftl(dec, dec, shift, status)) {1881return;1882}1883dec->exp -= shift;1884*status |= MPD_Clamped;1885if (!mpd_iszerocoeff(dec) && adjexp < ctx->emin) {1886/* Underflow is impossible, since exp < etiny=emin-prec+11887* and exp > etop=emax-prec+1 would imply emax < emin. */1888*status |= MPD_Subnormal;1889}1890}1891else if (adjexp < ctx->emin) {18921893etiny = mpd_etiny(ctx);18941895if (mpd_iszerocoeff(dec)) {1896if (dec->exp < etiny) {1897dec->exp = etiny;1898mpd_zerocoeff(dec);1899*status |= MPD_Clamped;1900}1901return;1902}19031904*status |= MPD_Subnormal;1905if (dec->exp < etiny) {1906/* At this point adjexp=exp+digits-1 < emin and exp < etiny=emin-prec+1:1907* (1) shift = emin-prec+1 - exp > 01908* (2) digits-shift = exp+digits-1 - emin + prec < prec */1909shift = etiny - dec->exp;1910rnd = (int)mpd_qshiftr_inplace(dec, shift);1911dec->exp = etiny;1912/* We always have a spare digit in case of an increment. */1913_mpd_apply_round_excess(dec, rnd, ctx, status);1914*status |= MPD_Rounded;1915if (rnd) {1916*status |= (MPD_Inexact|MPD_Underflow);1917if (mpd_iszerocoeff(dec)) {1918mpd_zerocoeff(dec);1919*status |= MPD_Clamped;1920}1921}1922}1923/* Case exp >= etiny=emin-prec+1:1924* (1) adjexp=exp+digits-1 < emin1925* (2) digits < emin-exp+1 <= prec */1926}1927}19281929/* Transcendental functions do not always set Underflow reliably,1930* since they only use as much precision as is necessary for correct1931* rounding. If a result like 1.0000000000e-101 is finalized, there1932* is no rounding digit that would trigger Underflow. But we can1933* assume Inexact, so a short check suffices. */1934static inline void1935mpd_check_underflow(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)1936{1937if (mpd_adjexp(dec) < ctx->emin && !mpd_iszero(dec) &&1938dec->exp < mpd_etiny(ctx)) {1939*status |= MPD_Underflow;1940}1941}19421943/* Check if a normal number must be rounded after the exponent has been checked. */1944static inline void1945_mpd_check_round(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)1946{1947mpd_uint_t rnd;1948mpd_ssize_t shift;19491950/* must handle specials: _mpd_check_exp() can produce infinities or NaNs */1951if (mpd_isspecial(dec)) {1952return;1953}19541955if (dec->digits > ctx->prec) {1956shift = dec->digits - ctx->prec;1957rnd = mpd_qshiftr_inplace(dec, shift);1958dec->exp += shift;1959_mpd_apply_round(dec, rnd, ctx, status);1960*status |= MPD_Rounded;1961if (rnd) {1962*status |= MPD_Inexact;1963}1964}1965}19661967/* Finalize all operations. */1968void1969mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)1970{1971if (mpd_isspecial(result)) {1972if (mpd_isnan(result)) {1973_mpd_fix_nan(result, ctx);1974}1975return;1976}19771978_mpd_check_exp(result, ctx, status);1979_mpd_check_round(result, ctx, status);1980}198119821983/******************************************************************************/1984/* Copying */1985/******************************************************************************/19861987/* Internal function: Copy a decimal, share data with src: USE WITH CARE! */1988static inline void1989_mpd_copy_shared(mpd_t *dest, const mpd_t *src)1990{1991dest->flags = src->flags;1992dest->exp = src->exp;1993dest->digits = src->digits;1994dest->len = src->len;1995dest->alloc = src->alloc;1996dest->data = src->data;19971998mpd_set_shared_data(dest);1999}20002001/*2002* Copy a decimal. In case of an error, status is set to MPD_Malloc_error.2003*/2004int2005mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status)2006{2007if (result == a) return 1;20082009if (!mpd_qresize(result, a->len, status)) {2010return 0;2011}20122013mpd_copy_flags(result, a);2014result->exp = a->exp;2015result->digits = a->digits;2016result->len = a->len;2017memcpy(result->data, a->data, a->len * (sizeof *result->data));20182019return 1;2020}20212022/* Same as mpd_qcopy, but do not set the result to NaN on failure. */2023int2024mpd_qcopy_cxx(mpd_t *result, const mpd_t *a)2025{2026if (result == a) return 1;20272028if (!mpd_qresize_cxx(result, a->len)) {2029return 0;2030}20312032mpd_copy_flags(result, a);2033result->exp = a->exp;2034result->digits = a->digits;2035result->len = a->len;2036memcpy(result->data, a->data, a->len * (sizeof *result->data));20372038return 1;2039}20402041/*2042* Copy to a decimal with a static buffer. The caller has to make sure that2043* the buffer is big enough. Cannot fail.2044*/2045static void2046mpd_qcopy_static(mpd_t *result, const mpd_t *a)2047{2048if (result == a) return;20492050memcpy(result->data, a->data, a->len * (sizeof *result->data));20512052mpd_copy_flags(result, a);2053result->exp = a->exp;2054result->digits = a->digits;2055result->len = a->len;2056}20572058/*2059* Return a newly allocated copy of the operand. In case of an error,2060* status is set to MPD_Malloc_error and the return value is NULL.2061*/2062mpd_t *2063mpd_qncopy(const mpd_t *a)2064{2065mpd_t *result;20662067if ((result = mpd_qnew_size(a->len)) == NULL) {2068return NULL;2069}2070memcpy(result->data, a->data, a->len * (sizeof *result->data));2071mpd_copy_flags(result, a);2072result->exp = a->exp;2073result->digits = a->digits;2074result->len = a->len;20752076return result;2077}20782079/*2080* Copy a decimal and set the sign to positive. In case of an error, the2081* status is set to MPD_Malloc_error.2082*/2083int2084mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status)2085{2086if (!mpd_qcopy(result, a, status)) {2087return 0;2088}2089mpd_set_positive(result);2090return 1;2091}20922093/*2094* Copy a decimal and negate the sign. In case of an error, the2095* status is set to MPD_Malloc_error.2096*/2097int2098mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status)2099{2100if (!mpd_qcopy(result, a, status)) {2101return 0;2102}2103_mpd_negate(result);2104return 1;2105}21062107/*2108* Copy a decimal, setting the sign of the first operand to the sign of the2109* second operand. In case of an error, the status is set to MPD_Malloc_error.2110*/2111int2112mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status)2113{2114uint8_t sign_b = mpd_sign(b); /* result may equal b! */21152116if (!mpd_qcopy(result, a, status)) {2117return 0;2118}2119mpd_set_sign(result, sign_b);2120return 1;2121}212221232124/******************************************************************************/2125/* Comparisons */2126/******************************************************************************/21272128/*2129* For all functions that compare two operands and return an int the usual2130* convention applies to the return value:2131*2132* -1 if op1 < op22133* 0 if op1 == op22134* 1 if op1 > op22135*2136* INT_MAX for error2137*/213821392140/* Convenience macro. If a and b are not equal, return from the calling2141* function with the correct comparison value. */2142#define CMP_EQUAL_OR_RETURN(a, b) \2143if (a != b) { \2144if (a < b) { \2145return -1; \2146} \2147return 1; \2148}21492150/*2151* Compare the data of big and small. This function does the equivalent2152* of first shifting small to the left and then comparing the data of2153* big and small, except that no allocation for the left shift is needed.2154*/2155static int2156_mpd_basecmp(mpd_uint_t *big, mpd_uint_t *small, mpd_size_t n, mpd_size_t m,2157mpd_size_t shift)2158{2159#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)2160/* spurious uninitialized warnings */2161mpd_uint_t l=l, lprev=lprev, h=h;2162#else2163mpd_uint_t l, lprev, h;2164#endif2165mpd_uint_t q, r;2166mpd_uint_t ph, x;21672168assert(m > 0 && n >= m && shift > 0);21692170_mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);21712172if (r != 0) {21732174ph = mpd_pow10[r];21752176--m; --n;2177_mpd_divmod_pow10(&h, &lprev, small[m--], MPD_RDIGITS-r);2178if (h != 0) {2179CMP_EQUAL_OR_RETURN(big[n], h)2180--n;2181}2182for (; m != MPD_SIZE_MAX; m--,n--) {2183_mpd_divmod_pow10(&h, &l, small[m], MPD_RDIGITS-r);2184x = ph * lprev + h;2185CMP_EQUAL_OR_RETURN(big[n], x)2186lprev = l;2187}2188x = ph * lprev;2189CMP_EQUAL_OR_RETURN(big[q], x)2190}2191else {2192while (--m != MPD_SIZE_MAX) {2193CMP_EQUAL_OR_RETURN(big[m+q], small[m])2194}2195}21962197return !_mpd_isallzero(big, q);2198}21992200/* Compare two decimals with the same adjusted exponent. */2201static int2202_mpd_cmp_same_adjexp(const mpd_t *a, const mpd_t *b)2203{2204mpd_ssize_t shift, i;22052206if (a->exp != b->exp) {2207/* Cannot wrap: a->exp + a->digits = b->exp + b->digits, so2208* a->exp - b->exp = b->digits - a->digits. */2209shift = a->exp - b->exp;2210if (shift > 0) {2211return -1 * _mpd_basecmp(b->data, a->data, b->len, a->len, shift);2212}2213else {2214return _mpd_basecmp(a->data, b->data, a->len, b->len, -shift);2215}2216}22172218/*2219* At this point adjexp(a) == adjexp(b) and a->exp == b->exp,2220* so a->digits == b->digits, therefore a->len == b->len.2221*/2222for (i = a->len-1; i >= 0; --i) {2223CMP_EQUAL_OR_RETURN(a->data[i], b->data[i])2224}22252226return 0;2227}22282229/* Compare two numerical values. */2230static int2231_mpd_cmp(const mpd_t *a, const mpd_t *b)2232{2233mpd_ssize_t adjexp_a, adjexp_b;22342235/* equal pointers */2236if (a == b) {2237return 0;2238}22392240/* infinities */2241if (mpd_isinfinite(a)) {2242if (mpd_isinfinite(b)) {2243return mpd_isnegative(b) - mpd_isnegative(a);2244}2245return mpd_arith_sign(a);2246}2247if (mpd_isinfinite(b)) {2248return -mpd_arith_sign(b);2249}22502251/* zeros */2252if (mpd_iszerocoeff(a)) {2253if (mpd_iszerocoeff(b)) {2254return 0;2255}2256return -mpd_arith_sign(b);2257}2258if (mpd_iszerocoeff(b)) {2259return mpd_arith_sign(a);2260}22612262/* different signs */2263if (mpd_sign(a) != mpd_sign(b)) {2264return mpd_sign(b) - mpd_sign(a);2265}22662267/* different adjusted exponents */2268adjexp_a = mpd_adjexp(a);2269adjexp_b = mpd_adjexp(b);2270if (adjexp_a != adjexp_b) {2271if (adjexp_a < adjexp_b) {2272return -1 * mpd_arith_sign(a);2273}2274return mpd_arith_sign(a);2275}22762277/* same adjusted exponents */2278return _mpd_cmp_same_adjexp(a, b) * mpd_arith_sign(a);2279}22802281/* Compare the absolutes of two numerical values. */2282static int2283_mpd_cmp_abs(const mpd_t *a, const mpd_t *b)2284{2285mpd_ssize_t adjexp_a, adjexp_b;22862287/* equal pointers */2288if (a == b) {2289return 0;2290}22912292/* infinities */2293if (mpd_isinfinite(a)) {2294if (mpd_isinfinite(b)) {2295return 0;2296}2297return 1;2298}2299if (mpd_isinfinite(b)) {2300return -1;2301}23022303/* zeros */2304if (mpd_iszerocoeff(a)) {2305if (mpd_iszerocoeff(b)) {2306return 0;2307}2308return -1;2309}2310if (mpd_iszerocoeff(b)) {2311return 1;2312}23132314/* different adjusted exponents */2315adjexp_a = mpd_adjexp(a);2316adjexp_b = mpd_adjexp(b);2317if (adjexp_a != adjexp_b) {2318if (adjexp_a < adjexp_b) {2319return -1;2320}2321return 1;2322}23232324/* same adjusted exponents */2325return _mpd_cmp_same_adjexp(a, b);2326}23272328/* Compare two values and return an integer result. */2329int2330mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status)2331{2332if (mpd_isspecial(a) || mpd_isspecial(b)) {2333if (mpd_isnan(a) || mpd_isnan(b)) {2334*status |= MPD_Invalid_operation;2335return INT_MAX;2336}2337}23382339return _mpd_cmp(a, b);2340}23412342/*2343* Compare a and b, convert the usual integer result to a decimal and2344* store it in 'result'. For convenience, the integer result of the comparison2345* is returned. Comparisons involving NaNs return NaN/INT_MAX.2346*/2347int2348mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b,2349const mpd_context_t *ctx, uint32_t *status)2350{2351int c;23522353if (mpd_isspecial(a) || mpd_isspecial(b)) {2354if (mpd_qcheck_nans(result, a, b, ctx, status)) {2355return INT_MAX;2356}2357}23582359c = _mpd_cmp(a, b);2360_settriple(result, (c < 0), (c != 0), 0);2361return c;2362}23632364/* Same as mpd_compare(), but signal for all NaNs, i.e. also for quiet NaNs. */2365int2366mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b,2367const mpd_context_t *ctx, uint32_t *status)2368{2369int c;23702371if (mpd_isspecial(a) || mpd_isspecial(b)) {2372if (mpd_qcheck_nans(result, a, b, ctx, status)) {2373*status |= MPD_Invalid_operation;2374return INT_MAX;2375}2376}23772378c = _mpd_cmp(a, b);2379_settriple(result, (c < 0), (c != 0), 0);2380return c;2381}23822383/* Compare the operands using a total order. */2384int2385mpd_cmp_total(const mpd_t *a, const mpd_t *b)2386{2387mpd_t aa, bb;2388int nan_a, nan_b;2389int c;23902391if (mpd_sign(a) != mpd_sign(b)) {2392return mpd_sign(b) - mpd_sign(a);2393}239423952396if (mpd_isnan(a)) {2397c = 1;2398if (mpd_isnan(b)) {2399nan_a = (mpd_isqnan(a)) ? 1 : 0;2400nan_b = (mpd_isqnan(b)) ? 1 : 0;2401if (nan_b == nan_a) {2402if (a->len > 0 && b->len > 0) {2403_mpd_copy_shared(&aa, a);2404_mpd_copy_shared(&bb, b);2405aa.exp = bb.exp = 0;2406/* compare payload */2407c = _mpd_cmp_abs(&aa, &bb);2408}2409else {2410c = (a->len > 0) - (b->len > 0);2411}2412}2413else {2414c = nan_a - nan_b;2415}2416}2417}2418else if (mpd_isnan(b)) {2419c = -1;2420}2421else {2422c = _mpd_cmp_abs(a, b);2423if (c == 0 && a->exp != b->exp) {2424c = (a->exp < b->exp) ? -1 : 1;2425}2426}24272428return c * mpd_arith_sign(a);2429}24302431/*2432* Compare a and b according to a total order, convert the usual integer result2433* to a decimal and store it in 'result'. For convenience, the integer result2434* of the comparison is returned.2435*/2436int2437mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b)2438{2439int c;24402441c = mpd_cmp_total(a, b);2442_settriple(result, (c < 0), (c != 0), 0);2443return c;2444}24452446/* Compare the magnitude of the operands using a total order. */2447int2448mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b)2449{2450mpd_t aa, bb;24512452_mpd_copy_shared(&aa, a);2453_mpd_copy_shared(&bb, b);24542455mpd_set_positive(&aa);2456mpd_set_positive(&bb);24572458return mpd_cmp_total(&aa, &bb);2459}24602461/*2462* Compare the magnitude of a and b according to a total order, convert the2463* the usual integer result to a decimal and store it in 'result'.2464* For convenience, the integer result of the comparison is returned.2465*/2466int2467mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b)2468{2469int c;24702471c = mpd_cmp_total_mag(a, b);2472_settriple(result, (c < 0), (c != 0), 0);2473return c;2474}24752476/* Determine an ordering for operands that are numerically equal. */2477static inline int2478_mpd_cmp_numequal(const mpd_t *a, const mpd_t *b)2479{2480int sign_a, sign_b;2481int c;24822483sign_a = mpd_sign(a);2484sign_b = mpd_sign(b);2485if (sign_a != sign_b) {2486c = sign_b - sign_a;2487}2488else {2489c = (a->exp < b->exp) ? -1 : 1;2490c *= mpd_arith_sign(a);2491}24922493return c;2494}249524962497/******************************************************************************/2498/* Shifting the coefficient */2499/******************************************************************************/25002501/*2502* Shift the coefficient of the operand to the left, no check for specials.2503* Both operands may be the same pointer. If the result length has to be2504* increased, mpd_qresize() might fail with MPD_Malloc_error.2505*/2506int2507mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status)2508{2509mpd_ssize_t size;25102511assert(!mpd_isspecial(a));2512assert(n >= 0);25132514if (mpd_iszerocoeff(a) || n == 0) {2515return mpd_qcopy(result, a, status);2516}25172518size = mpd_digits_to_size(a->digits+n);2519if (!mpd_qresize(result, size, status)) {2520return 0; /* result is NaN */2521}25222523_mpd_baseshiftl(result->data, a->data, size, a->len, n);25242525mpd_copy_flags(result, a);2526result->exp = a->exp;2527result->digits = a->digits+n;2528result->len = size;25292530return 1;2531}25322533/* Determine the rounding indicator if all digits of the coefficient are shifted2534* out of the picture. */2535static mpd_uint_t2536_mpd_get_rnd(const mpd_uint_t *data, mpd_ssize_t len, int use_msd)2537{2538mpd_uint_t rnd = 0, rest = 0, word;25392540word = data[len-1];2541/* special treatment for the most significant digit if shift == digits */2542if (use_msd) {2543_mpd_divmod_pow10(&rnd, &rest, word, mpd_word_digits(word)-1);2544if (len > 1 && rest == 0) {2545rest = !_mpd_isallzero(data, len-1);2546}2547}2548else {2549rest = !_mpd_isallzero(data, len);2550}25512552return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd;2553}25542555/*2556* Same as mpd_qshiftr(), but 'result' is an mpd_t with a static coefficient.2557* It is the caller's responsibility to ensure that the coefficient is big2558* enough. The function cannot fail.2559*/2560static mpd_uint_t2561mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n)2562{2563mpd_uint_t rnd;2564mpd_ssize_t size;25652566assert(!mpd_isspecial(a));2567assert(n >= 0);25682569if (mpd_iszerocoeff(a) || n == 0) {2570mpd_qcopy_static(result, a);2571return 0;2572}25732574if (n >= a->digits) {2575rnd = _mpd_get_rnd(a->data, a->len, (n==a->digits));2576mpd_zerocoeff(result);2577}2578else {2579result->digits = a->digits-n;2580size = mpd_digits_to_size(result->digits);2581rnd = _mpd_baseshiftr(result->data, a->data, a->len, n);2582result->len = size;2583}25842585mpd_copy_flags(result, a);2586result->exp = a->exp;25872588return rnd;2589}25902591/*2592* Inplace shift of the coefficient to the right, no check for specials.2593* Returns the rounding indicator for mpd_rnd_incr().2594* The function cannot fail.2595*/2596mpd_uint_t2597mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n)2598{2599uint32_t dummy;2600mpd_uint_t rnd;2601mpd_ssize_t size;26022603assert(!mpd_isspecial(result));2604assert(n >= 0);26052606if (mpd_iszerocoeff(result) || n == 0) {2607return 0;2608}26092610if (n >= result->digits) {2611rnd = _mpd_get_rnd(result->data, result->len, (n==result->digits));2612mpd_zerocoeff(result);2613}2614else {2615rnd = _mpd_baseshiftr(result->data, result->data, result->len, n);2616result->digits -= n;2617size = mpd_digits_to_size(result->digits);2618/* reducing the size cannot fail */2619mpd_qresize(result, size, &dummy);2620result->len = size;2621}26222623return rnd;2624}26252626/*2627* Shift the coefficient of the operand to the right, no check for specials.2628* Both operands may be the same pointer. Returns the rounding indicator to2629* be used by mpd_rnd_incr(). If the result length has to be increased,2630* mpd_qcopy() or mpd_qresize() might fail with MPD_Malloc_error. In those2631* cases, MPD_UINT_MAX is returned.2632*/2633mpd_uint_t2634mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status)2635{2636mpd_uint_t rnd;2637mpd_ssize_t size;26382639assert(!mpd_isspecial(a));2640assert(n >= 0);26412642if (mpd_iszerocoeff(a) || n == 0) {2643if (!mpd_qcopy(result, a, status)) {2644return MPD_UINT_MAX;2645}2646return 0;2647}26482649if (n >= a->digits) {2650rnd = _mpd_get_rnd(a->data, a->len, (n==a->digits));2651mpd_zerocoeff(result);2652}2653else {2654result->digits = a->digits-n;2655size = mpd_digits_to_size(result->digits);2656if (result == a) {2657rnd = _mpd_baseshiftr(result->data, a->data, a->len, n);2658/* reducing the size cannot fail */2659mpd_qresize(result, size, status);2660}2661else {2662if (!mpd_qresize(result, size, status)) {2663return MPD_UINT_MAX;2664}2665rnd = _mpd_baseshiftr(result->data, a->data, a->len, n);2666}2667result->len = size;2668}26692670mpd_copy_flags(result, a);2671result->exp = a->exp;26722673return rnd;2674}267526762677/******************************************************************************/2678/* Miscellaneous operations */2679/******************************************************************************/26802681/* Logical And */2682void2683mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b,2684const mpd_context_t *ctx, uint32_t *status)2685{2686const mpd_t *big = a, *small = b;2687mpd_uint_t x, y, z, xbit, ybit;2688int k, mswdigits;2689mpd_ssize_t i;26902691if (mpd_isspecial(a) || mpd_isspecial(b) ||2692mpd_isnegative(a) || mpd_isnegative(b) ||2693a->exp != 0 || b->exp != 0) {2694mpd_seterror(result, MPD_Invalid_operation, status);2695return;2696}2697if (b->digits > a->digits) {2698big = b;2699small = a;2700}2701if (!mpd_qresize(result, big->len, status)) {2702return;2703}270427052706/* full words */2707for (i = 0; i < small->len-1; i++) {2708x = small->data[i];2709y = big->data[i];2710z = 0;2711for (k = 0; k < MPD_RDIGITS; k++) {2712xbit = x % 10;2713x /= 10;2714ybit = y % 10;2715y /= 10;2716if (xbit > 1 || ybit > 1) {2717goto invalid_operation;2718}2719z += (xbit&ybit) ? mpd_pow10[k] : 0;2720}2721result->data[i] = z;2722}2723/* most significant word of small */2724x = small->data[i];2725y = big->data[i];2726z = 0;2727mswdigits = mpd_word_digits(x);2728for (k = 0; k < mswdigits; k++) {2729xbit = x % 10;2730x /= 10;2731ybit = y % 10;2732y /= 10;2733if (xbit > 1 || ybit > 1) {2734goto invalid_operation;2735}2736z += (xbit&ybit) ? mpd_pow10[k] : 0;2737}2738result->data[i++] = z;27392740/* scan the rest of y for digits > 1 */2741for (; k < MPD_RDIGITS; k++) {2742ybit = y % 10;2743y /= 10;2744if (ybit > 1) {2745goto invalid_operation;2746}2747}2748/* scan the rest of big for digits > 1 */2749for (; i < big->len; i++) {2750y = big->data[i];2751for (k = 0; k < MPD_RDIGITS; k++) {2752ybit = y % 10;2753y /= 10;2754if (ybit > 1) {2755goto invalid_operation;2756}2757}2758}27592760mpd_clear_flags(result);2761result->exp = 0;2762result->len = _mpd_real_size(result->data, small->len);2763mpd_qresize(result, result->len, status);2764mpd_setdigits(result);2765_mpd_cap(result, ctx);2766return;27672768invalid_operation:2769mpd_seterror(result, MPD_Invalid_operation, status);2770}27712772/* Class of an operand. Returns a pointer to the constant name. */2773const char *2774mpd_class(const mpd_t *a, const mpd_context_t *ctx)2775{2776if (mpd_isnan(a)) {2777if (mpd_isqnan(a))2778return "NaN";2779else2780return "sNaN";2781}2782else if (mpd_ispositive(a)) {2783if (mpd_isinfinite(a))2784return "+Infinity";2785else if (mpd_iszero(a))2786return "+Zero";2787else if (mpd_isnormal(a, ctx))2788return "+Normal";2789else2790return "+Subnormal";2791}2792else {2793if (mpd_isinfinite(a))2794return "-Infinity";2795else if (mpd_iszero(a))2796return "-Zero";2797else if (mpd_isnormal(a, ctx))2798return "-Normal";2799else2800return "-Subnormal";2801}2802}28032804/* Logical Xor */2805void2806mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,2807uint32_t *status)2808{2809mpd_uint_t x, z, xbit;2810mpd_ssize_t i, digits, len;2811mpd_ssize_t q, r;2812int k;28132814if (mpd_isspecial(a) || mpd_isnegative(a) || a->exp != 0) {2815mpd_seterror(result, MPD_Invalid_operation, status);2816return;2817}28182819digits = (a->digits < ctx->prec) ? ctx->prec : a->digits;2820_mpd_idiv_word(&q, &r, digits, MPD_RDIGITS);2821len = (r == 0) ? q : q+1;2822if (!mpd_qresize(result, len, status)) {2823return;2824}28252826for (i = 0; i < len; i++) {2827x = (i < a->len) ? a->data[i] : 0;2828z = 0;2829for (k = 0; k < MPD_RDIGITS; k++) {2830xbit = x % 10;2831x /= 10;2832if (xbit > 1) {2833goto invalid_operation;2834}2835z += !xbit ? mpd_pow10[k] : 0;2836}2837result->data[i] = z;2838}28392840mpd_clear_flags(result);2841result->exp = 0;2842result->len = _mpd_real_size(result->data, len);2843mpd_qresize(result, result->len, status);2844mpd_setdigits(result);2845_mpd_cap(result, ctx);2846return;28472848invalid_operation:2849mpd_seterror(result, MPD_Invalid_operation, status);2850}28512852/* Exponent of the magnitude of the most significant digit of the operand. */2853void2854mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,2855uint32_t *status)2856{2857if (mpd_isspecial(a)) {2858if (mpd_qcheck_nan(result, a, ctx, status)) {2859return;2860}2861mpd_setspecial(result, MPD_POS, MPD_INF);2862}2863else if (mpd_iszerocoeff(a)) {2864mpd_setspecial(result, MPD_NEG, MPD_INF);2865*status |= MPD_Division_by_zero;2866}2867else {2868mpd_qset_ssize(result, mpd_adjexp(a), ctx, status);2869}2870}28712872/* Logical Or */2873void2874mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b,2875const mpd_context_t *ctx, uint32_t *status)2876{2877const mpd_t *big = a, *small = b;2878mpd_uint_t x, y, z, xbit, ybit;2879int k, mswdigits;2880mpd_ssize_t i;28812882if (mpd_isspecial(a) || mpd_isspecial(b) ||2883mpd_isnegative(a) || mpd_isnegative(b) ||2884a->exp != 0 || b->exp != 0) {2885mpd_seterror(result, MPD_Invalid_operation, status);2886return;2887}2888if (b->digits > a->digits) {2889big = b;2890small = a;2891}2892if (!mpd_qresize(result, big->len, status)) {2893return;2894}289528962897/* full words */2898for (i = 0; i < small->len-1; i++) {2899x = small->data[i];2900y = big->data[i];2901z = 0;2902for (k = 0; k < MPD_RDIGITS; k++) {2903xbit = x % 10;2904x /= 10;2905ybit = y % 10;2906y /= 10;2907if (xbit > 1 || ybit > 1) {2908goto invalid_operation;2909}2910z += (xbit|ybit) ? mpd_pow10[k] : 0;2911}2912result->data[i] = z;2913}2914/* most significant word of small */2915x = small->data[i];2916y = big->data[i];2917z = 0;2918mswdigits = mpd_word_digits(x);2919for (k = 0; k < mswdigits; k++) {2920xbit = x % 10;2921x /= 10;2922ybit = y % 10;2923y /= 10;2924if (xbit > 1 || ybit > 1) {2925goto invalid_operation;2926}2927z += (xbit|ybit) ? mpd_pow10[k] : 0;2928}29292930/* scan for digits > 1 and copy the rest of y */2931for (; k < MPD_RDIGITS; k++) {2932ybit = y % 10;2933y /= 10;2934if (ybit > 1) {2935goto invalid_operation;2936}2937z += ybit*mpd_pow10[k];2938}2939result->data[i++] = z;2940/* scan for digits > 1 and copy the rest of big */2941for (; i < big->len; i++) {2942y = big->data[i];2943for (k = 0; k < MPD_RDIGITS; k++) {2944ybit = y % 10;2945y /= 10;2946if (ybit > 1) {2947goto invalid_operation;2948}2949}2950result->data[i] = big->data[i];2951}29522953mpd_clear_flags(result);2954result->exp = 0;2955result->len = _mpd_real_size(result->data, big->len);2956mpd_qresize(result, result->len, status);2957mpd_setdigits(result);2958_mpd_cap(result, ctx);2959return;29602961invalid_operation:2962mpd_seterror(result, MPD_Invalid_operation, status);2963}29642965/*2966* Rotate the coefficient of 'a' by 'b' digits. 'b' must be an integer with2967* exponent 0.2968*/2969void2970mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b,2971const mpd_context_t *ctx, uint32_t *status)2972{2973uint32_t workstatus = 0;2974MPD_NEW_STATIC(tmp,0,0,0,0);2975MPD_NEW_STATIC(big,0,0,0,0);2976MPD_NEW_STATIC(small,0,0,0,0);2977mpd_ssize_t n, lshift, rshift;29782979if (mpd_isspecial(a) || mpd_isspecial(b)) {2980if (mpd_qcheck_nans(result, a, b, ctx, status)) {2981return;2982}2983}2984if (b->exp != 0 || mpd_isinfinite(b)) {2985mpd_seterror(result, MPD_Invalid_operation, status);2986return;2987}29882989n = mpd_qget_ssize(b, &workstatus);2990if (workstatus&MPD_Invalid_operation) {2991mpd_seterror(result, MPD_Invalid_operation, status);2992return;2993}2994if (n > ctx->prec || n < -ctx->prec) {2995mpd_seterror(result, MPD_Invalid_operation, status);2996return;2997}2998if (mpd_isinfinite(a)) {2999mpd_qcopy(result, a, status);3000return;3001}30023003if (n >= 0) {3004lshift = n;3005rshift = ctx->prec-n;3006}3007else {3008lshift = ctx->prec+n;3009rshift = -n;3010}30113012if (a->digits > ctx->prec) {3013if (!mpd_qcopy(&tmp, a, status)) {3014mpd_seterror(result, MPD_Malloc_error, status);3015goto finish;3016}3017_mpd_cap(&tmp, ctx);3018a = &tmp;3019}30203021if (!mpd_qshiftl(&big, a, lshift, status)) {3022mpd_seterror(result, MPD_Malloc_error, status);3023goto finish;3024}3025_mpd_cap(&big, ctx);30263027if (mpd_qshiftr(&small, a, rshift, status) == MPD_UINT_MAX) {3028mpd_seterror(result, MPD_Malloc_error, status);3029goto finish;3030}3031_mpd_qadd(result, &big, &small, ctx, status);303230333034finish:3035mpd_del(&tmp);3036mpd_del(&big);3037mpd_del(&small);3038}30393040/*3041* b must be an integer with exponent 0 and in the range +-2*(emax + prec).3042* XXX: In my opinion +-(2*emax + prec) would be more sensible.3043* The result is a with the value of b added to its exponent.3044*/3045void3046mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b,3047const mpd_context_t *ctx, uint32_t *status)3048{3049uint32_t workstatus = 0;3050mpd_uint_t n, maxjump;3051#ifndef LEGACY_COMPILER3052int64_t exp;3053#else3054mpd_uint_t x;3055int x_sign, n_sign;3056mpd_ssize_t exp;3057#endif30583059if (mpd_isspecial(a) || mpd_isspecial(b)) {3060if (mpd_qcheck_nans(result, a, b, ctx, status)) {3061return;3062}3063}3064if (b->exp != 0 || mpd_isinfinite(b)) {3065mpd_seterror(result, MPD_Invalid_operation, status);3066return;3067}30683069n = mpd_qabs_uint(b, &workstatus);3070/* the spec demands this */3071maxjump = 2 * (mpd_uint_t)(ctx->emax + ctx->prec);30723073if (n > maxjump || workstatus&MPD_Invalid_operation) {3074mpd_seterror(result, MPD_Invalid_operation, status);3075return;3076}3077if (mpd_isinfinite(a)) {3078mpd_qcopy(result, a, status);3079return;3080}30813082#ifndef LEGACY_COMPILER3083exp = a->exp + (int64_t)n * mpd_arith_sign(b);3084exp = (exp > MPD_EXP_INF) ? MPD_EXP_INF : exp;3085exp = (exp < MPD_EXP_CLAMP) ? MPD_EXP_CLAMP : exp;3086#else3087x = (a->exp < 0) ? -a->exp : a->exp;3088x_sign = (a->exp < 0) ? 1 : 0;3089n_sign = mpd_isnegative(b) ? 1 : 0;30903091if (x_sign == n_sign) {3092x = x + n;3093if (x < n) x = MPD_UINT_MAX;3094}3095else {3096x_sign = (x >= n) ? x_sign : n_sign;3097x = (x >= n) ? x - n : n - x;3098}3099if (!x_sign && x > MPD_EXP_INF) x = MPD_EXP_INF;3100if (x_sign && x > -MPD_EXP_CLAMP) x = -MPD_EXP_CLAMP;3101exp = x_sign ? -((mpd_ssize_t)x) : (mpd_ssize_t)x;3102#endif31033104mpd_qcopy(result, a, status);3105result->exp = (mpd_ssize_t)exp;31063107mpd_qfinalize(result, ctx, status);3108}31093110/*3111* Shift the coefficient by n digits, positive n is a left shift. In the case3112* of a left shift, the result is decapitated to fit the context precision. If3113* you don't want that, use mpd_shiftl().3114*/3115void3116mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx,3117uint32_t *status)3118{3119if (mpd_isspecial(a)) {3120if (mpd_qcheck_nan(result, a, ctx, status)) {3121return;3122}3123mpd_qcopy(result, a, status);3124return;3125}31263127if (n >= 0 && n <= ctx->prec) {3128mpd_qshiftl(result, a, n, status);3129_mpd_cap(result, ctx);3130}3131else if (n < 0 && n >= -ctx->prec) {3132if (!mpd_qcopy(result, a, status)) {3133return;3134}3135_mpd_cap(result, ctx);3136mpd_qshiftr_inplace(result, -n);3137}3138else {3139mpd_seterror(result, MPD_Invalid_operation, status);3140}3141}31423143/*3144* Same as mpd_shiftn(), but the shift is specified by the decimal b, which3145* must be an integer with a zero exponent. Infinities remain infinities.3146*/3147void3148mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx,3149uint32_t *status)3150{3151uint32_t workstatus = 0;3152mpd_ssize_t n;31533154if (mpd_isspecial(a) || mpd_isspecial(b)) {3155if (mpd_qcheck_nans(result, a, b, ctx, status)) {3156return;3157}3158}3159if (b->exp != 0 || mpd_isinfinite(b)) {3160mpd_seterror(result, MPD_Invalid_operation, status);3161return;3162}31633164n = mpd_qget_ssize(b, &workstatus);3165if (workstatus&MPD_Invalid_operation) {3166mpd_seterror(result, MPD_Invalid_operation, status);3167return;3168}3169if (n > ctx->prec || n < -ctx->prec) {3170mpd_seterror(result, MPD_Invalid_operation, status);3171return;3172}3173if (mpd_isinfinite(a)) {3174mpd_qcopy(result, a, status);3175return;3176}31773178if (n >= 0) {3179mpd_qshiftl(result, a, n, status);3180_mpd_cap(result, ctx);3181}3182else {3183if (!mpd_qcopy(result, a, status)) {3184return;3185}3186_mpd_cap(result, ctx);3187mpd_qshiftr_inplace(result, -n);3188}3189}31903191/* Logical Xor */3192void3193mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b,3194const mpd_context_t *ctx, uint32_t *status)3195{3196const mpd_t *big = a, *small = b;3197mpd_uint_t x, y, z, xbit, ybit;3198int k, mswdigits;3199mpd_ssize_t i;32003201if (mpd_isspecial(a) || mpd_isspecial(b) ||3202mpd_isnegative(a) || mpd_isnegative(b) ||3203a->exp != 0 || b->exp != 0) {3204mpd_seterror(result, MPD_Invalid_operation, status);3205return;3206}3207if (b->digits > a->digits) {3208big = b;3209small = a;3210}3211if (!mpd_qresize(result, big->len, status)) {3212return;3213}321432153216/* full words */3217for (i = 0; i < small->len-1; i++) {3218x = small->data[i];3219y = big->data[i];3220z = 0;3221for (k = 0; k < MPD_RDIGITS; k++) {3222xbit = x % 10;3223x /= 10;3224ybit = y % 10;3225y /= 10;3226if (xbit > 1 || ybit > 1) {3227goto invalid_operation;3228}3229z += (xbit^ybit) ? mpd_pow10[k] : 0;3230}3231result->data[i] = z;3232}3233/* most significant word of small */3234x = small->data[i];3235y = big->data[i];3236z = 0;3237mswdigits = mpd_word_digits(x);3238for (k = 0; k < mswdigits; k++) {3239xbit = x % 10;3240x /= 10;3241ybit = y % 10;3242y /= 10;3243if (xbit > 1 || ybit > 1) {3244goto invalid_operation;3245}3246z += (xbit^ybit) ? mpd_pow10[k] : 0;3247}32483249/* scan for digits > 1 and copy the rest of y */3250for (; k < MPD_RDIGITS; k++) {3251ybit = y % 10;3252y /= 10;3253if (ybit > 1) {3254goto invalid_operation;3255}3256z += ybit*mpd_pow10[k];3257}3258result->data[i++] = z;3259/* scan for digits > 1 and copy the rest of big */3260for (; i < big->len; i++) {3261y = big->data[i];3262for (k = 0; k < MPD_RDIGITS; k++) {3263ybit = y % 10;3264y /= 10;3265if (ybit > 1) {3266goto invalid_operation;3267}3268}3269result->data[i] = big->data[i];3270}32713272mpd_clear_flags(result);3273result->exp = 0;3274result->len = _mpd_real_size(result->data, big->len);3275mpd_qresize(result, result->len, status);3276mpd_setdigits(result);3277_mpd_cap(result, ctx);3278return;32793280invalid_operation:3281mpd_seterror(result, MPD_Invalid_operation, status);3282}328332843285/******************************************************************************/3286/* Arithmetic operations */3287/******************************************************************************/32883289/*3290* The absolute value of a. If a is negative, the result is the same3291* as the result of the minus operation. Otherwise, the result is the3292* result of the plus operation.3293*/3294void3295mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,3296uint32_t *status)3297{3298if (mpd_isspecial(a)) {3299if (mpd_qcheck_nan(result, a, ctx, status)) {3300return;3301}3302}33033304if (mpd_isnegative(a)) {3305mpd_qminus(result, a, ctx, status);3306}3307else {3308mpd_qplus(result, a, ctx, status);3309}3310}33113312static inline void3313_mpd_ptrswap(const mpd_t **a, const mpd_t **b)3314{3315const mpd_t *t = *a;3316*a = *b;3317*b = t;3318}33193320/* Add or subtract infinities. */3321static void3322_mpd_qaddsub_inf(mpd_t *result, const mpd_t *a, const mpd_t *b, uint8_t sign_b,3323uint32_t *status)3324{3325if (mpd_isinfinite(a)) {3326if (mpd_sign(a) != sign_b && mpd_isinfinite(b)) {3327mpd_seterror(result, MPD_Invalid_operation, status);3328}3329else {3330mpd_setspecial(result, mpd_sign(a), MPD_INF);3331}3332return;3333}3334assert(mpd_isinfinite(b));3335mpd_setspecial(result, sign_b, MPD_INF);3336}33373338/* Add or subtract non-special numbers. */3339static void3340_mpd_qaddsub(mpd_t *result, const mpd_t *a, const mpd_t *b, uint8_t sign_b,3341const mpd_context_t *ctx, uint32_t *status)3342{3343const mpd_t *big, *small;3344MPD_NEW_STATIC(big_aligned,0,0,0,0);3345MPD_NEW_CONST(tiny,0,0,1,1,1,1);3346mpd_uint_t carry;3347mpd_ssize_t newsize, shift;3348mpd_ssize_t exp, i;3349int swap = 0;335033513352/* compare exponents */3353big = a; small = b;3354if (big->exp != small->exp) {3355if (small->exp > big->exp) {3356_mpd_ptrswap(&big, &small);3357swap++;3358}3359/* align the coefficients */3360if (!mpd_iszerocoeff(big)) {3361exp = big->exp - 1;3362exp += (big->digits > ctx->prec) ? 0 : big->digits-ctx->prec-1;3363if (mpd_adjexp(small) < exp) {3364/*3365* Avoid huge shifts by substituting a value for small that is3366* guaranteed to produce the same results.3367*3368* adjexp(small) < exp if and only if:3369*3370* bdigits <= prec AND3371* bdigits+shift >= prec+2+sdigits AND3372* exp = bexp+bdigits-prec-23373*3374* 1234567000000000 -> bdigits + shift3375* ----------XX1234 -> sdigits3376* ----------X1 -> tiny-digits3377* |- prec -|3378*3379* OR3380*3381* bdigits > prec AND3382* shift > sdigits AND3383* exp = bexp-13384*3385* 1234567892100000 -> bdigits + shift3386* ----------XX1234 -> sdigits3387* ----------X1 -> tiny-digits3388* |- prec -|3389*3390* If tiny is zero, adding or subtracting is a no-op.3391* Otherwise, adding tiny generates a non-zero digit either3392* below the rounding digit or the least significant digit3393* of big. When subtracting, tiny is in the same position as3394* the carry that would be generated by subtracting sdigits.3395*/3396mpd_copy_flags(&tiny, small);3397tiny.exp = exp;3398tiny.digits = 1;3399tiny.len = 1;3400tiny.data[0] = mpd_iszerocoeff(small) ? 0 : 1;3401small = &tiny;3402}3403/* This cannot wrap: the difference is positive and <= maxprec */3404shift = big->exp - small->exp;3405if (!mpd_qshiftl(&big_aligned, big, shift, status)) {3406mpd_seterror(result, MPD_Malloc_error, status);3407goto finish;3408}3409big = &big_aligned;3410}3411}3412result->exp = small->exp;341334143415/* compare length of coefficients */3416if (big->len < small->len) {3417_mpd_ptrswap(&big, &small);3418swap++;3419}34203421newsize = big->len;3422if (!mpd_qresize(result, newsize, status)) {3423goto finish;3424}34253426if (mpd_sign(a) == sign_b) {34273428carry = _mpd_baseadd(result->data, big->data, small->data,3429big->len, small->len);34303431if (carry) {3432newsize = big->len + 1;3433if (!mpd_qresize(result, newsize, status)) {3434goto finish;3435}3436result->data[newsize-1] = carry;3437}34383439result->len = newsize;3440mpd_set_flags(result, sign_b);3441}3442else {3443if (big->len == small->len) {3444for (i=big->len-1; i >= 0; --i) {3445if (big->data[i] != small->data[i]) {3446if (big->data[i] < small->data[i]) {3447_mpd_ptrswap(&big, &small);3448swap++;3449}3450break;3451}3452}3453}34543455_mpd_basesub(result->data, big->data, small->data,3456big->len, small->len);3457newsize = _mpd_real_size(result->data, big->len);3458/* resize to smaller cannot fail */3459(void)mpd_qresize(result, newsize, status);34603461result->len = newsize;3462sign_b = (swap & 1) ? sign_b : mpd_sign(a);3463mpd_set_flags(result, sign_b);34643465if (mpd_iszerocoeff(result)) {3466mpd_set_positive(result);3467if (ctx->round == MPD_ROUND_FLOOR) {3468mpd_set_negative(result);3469}3470}3471}34723473mpd_setdigits(result);34743475finish:3476mpd_del(&big_aligned);3477}34783479/* Add a and b. No specials, no finalizing. */3480static void3481_mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,3482const mpd_context_t *ctx, uint32_t *status)3483{3484_mpd_qaddsub(result, a, b, mpd_sign(b), ctx, status);3485}34863487/* Subtract b from a. No specials, no finalizing. */3488static void3489_mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b,3490const mpd_context_t *ctx, uint32_t *status)3491{3492_mpd_qaddsub(result, a, b, !mpd_sign(b), ctx, status);3493}34943495/* Add a and b. */3496void3497mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,3498const mpd_context_t *ctx, uint32_t *status)3499{3500if (mpd_isspecial(a) || mpd_isspecial(b)) {3501if (mpd_qcheck_nans(result, a, b, ctx, status)) {3502return;3503}3504_mpd_qaddsub_inf(result, a, b, mpd_sign(b), status);3505return;3506}35073508_mpd_qaddsub(result, a, b, mpd_sign(b), ctx, status);3509mpd_qfinalize(result, ctx, status);3510}35113512/* Add a and b. Set NaN/Invalid_operation if the result is inexact. */3513static void3514_mpd_qadd_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,3515const mpd_context_t *ctx, uint32_t *status)3516{3517uint32_t workstatus = 0;35183519mpd_qadd(result, a, b, ctx, &workstatus);3520*status |= workstatus;3521if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {3522mpd_seterror(result, MPD_Invalid_operation, status);3523}3524}35253526/* Subtract b from a. */3527void3528mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b,3529const mpd_context_t *ctx, uint32_t *status)3530{3531if (mpd_isspecial(a) || mpd_isspecial(b)) {3532if (mpd_qcheck_nans(result, a, b, ctx, status)) {3533return;3534}3535_mpd_qaddsub_inf(result, a, b, !mpd_sign(b), status);3536return;3537}35383539_mpd_qaddsub(result, a, b, !mpd_sign(b), ctx, status);3540mpd_qfinalize(result, ctx, status);3541}35423543/* Subtract b from a. Set NaN/Invalid_operation if the result is inexact. */3544static void3545_mpd_qsub_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,3546const mpd_context_t *ctx, uint32_t *status)3547{3548uint32_t workstatus = 0;35493550mpd_qsub(result, a, b, ctx, &workstatus);3551*status |= workstatus;3552if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {3553mpd_seterror(result, MPD_Invalid_operation, status);3554}3555}35563557/* Add decimal and mpd_ssize_t. */3558void3559mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,3560const mpd_context_t *ctx, uint32_t *status)3561{3562mpd_context_t maxcontext;3563MPD_NEW_STATIC(bb,0,0,0,0);35643565mpd_maxcontext(&maxcontext);3566mpd_qsset_ssize(&bb, b, &maxcontext, status);3567mpd_qadd(result, a, &bb, ctx, status);3568mpd_del(&bb);3569}35703571/* Add decimal and mpd_uint_t. */3572void3573mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,3574const mpd_context_t *ctx, uint32_t *status)3575{3576mpd_context_t maxcontext;3577MPD_NEW_STATIC(bb,0,0,0,0);35783579mpd_maxcontext(&maxcontext);3580mpd_qsset_uint(&bb, b, &maxcontext, status);3581mpd_qadd(result, a, &bb, ctx, status);3582mpd_del(&bb);3583}35843585/* Subtract mpd_ssize_t from decimal. */3586void3587mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,3588const mpd_context_t *ctx, uint32_t *status)3589{3590mpd_context_t maxcontext;3591MPD_NEW_STATIC(bb,0,0,0,0);35923593mpd_maxcontext(&maxcontext);3594mpd_qsset_ssize(&bb, b, &maxcontext, status);3595mpd_qsub(result, a, &bb, ctx, status);3596mpd_del(&bb);3597}35983599/* Subtract mpd_uint_t from decimal. */3600void3601mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,3602const mpd_context_t *ctx, uint32_t *status)3603{3604mpd_context_t maxcontext;3605MPD_NEW_STATIC(bb,0,0,0,0);36063607mpd_maxcontext(&maxcontext);3608mpd_qsset_uint(&bb, b, &maxcontext, status);3609mpd_qsub(result, a, &bb, ctx, status);3610mpd_del(&bb);3611}36123613/* Add decimal and int32_t. */3614void3615mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b,3616const mpd_context_t *ctx, uint32_t *status)3617{3618mpd_qadd_ssize(result, a, b, ctx, status);3619}36203621/* Add decimal and uint32_t. */3622void3623mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b,3624const mpd_context_t *ctx, uint32_t *status)3625{3626mpd_qadd_uint(result, a, b, ctx, status);3627}36283629#ifdef CONFIG_643630/* Add decimal and int64_t. */3631void3632mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b,3633const mpd_context_t *ctx, uint32_t *status)3634{3635mpd_qadd_ssize(result, a, b, ctx, status);3636}36373638/* Add decimal and uint64_t. */3639void3640mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,3641const mpd_context_t *ctx, uint32_t *status)3642{3643mpd_qadd_uint(result, a, b, ctx, status);3644}3645#elif !defined(LEGACY_COMPILER)3646/* Add decimal and int64_t. */3647void3648mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b,3649const mpd_context_t *ctx, uint32_t *status)3650{3651mpd_context_t maxcontext;3652MPD_NEW_STATIC(bb,0,0,0,0);36533654mpd_maxcontext(&maxcontext);3655mpd_qset_i64(&bb, b, &maxcontext, status);3656mpd_qadd(result, a, &bb, ctx, status);3657mpd_del(&bb);3658}36593660/* Add decimal and uint64_t. */3661void3662mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,3663const mpd_context_t *ctx, uint32_t *status)3664{3665mpd_context_t maxcontext;3666MPD_NEW_STATIC(bb,0,0,0,0);36673668mpd_maxcontext(&maxcontext);3669mpd_qset_u64(&bb, b, &maxcontext, status);3670mpd_qadd(result, a, &bb, ctx, status);3671mpd_del(&bb);3672}3673#endif36743675/* Subtract int32_t from decimal. */3676void3677mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b,3678const mpd_context_t *ctx, uint32_t *status)3679{3680mpd_qsub_ssize(result, a, b, ctx, status);3681}36823683/* Subtract uint32_t from decimal. */3684void3685mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b,3686const mpd_context_t *ctx, uint32_t *status)3687{3688mpd_qsub_uint(result, a, b, ctx, status);3689}36903691#ifdef CONFIG_643692/* Subtract int64_t from decimal. */3693void3694mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,3695const mpd_context_t *ctx, uint32_t *status)3696{3697mpd_qsub_ssize(result, a, b, ctx, status);3698}36993700/* Subtract uint64_t from decimal. */3701void3702mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,3703const mpd_context_t *ctx, uint32_t *status)3704{3705mpd_qsub_uint(result, a, b, ctx, status);3706}3707#elif !defined(LEGACY_COMPILER)3708/* Subtract int64_t from decimal. */3709void3710mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,3711const mpd_context_t *ctx, uint32_t *status)3712{3713mpd_context_t maxcontext;3714MPD_NEW_STATIC(bb,0,0,0,0);37153716mpd_maxcontext(&maxcontext);3717mpd_qset_i64(&bb, b, &maxcontext, status);3718mpd_qsub(result, a, &bb, ctx, status);3719mpd_del(&bb);3720}37213722/* Subtract uint64_t from decimal. */3723void3724mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,3725const mpd_context_t *ctx, uint32_t *status)3726{3727mpd_context_t maxcontext;3728MPD_NEW_STATIC(bb,0,0,0,0);37293730mpd_maxcontext(&maxcontext);3731mpd_qset_u64(&bb, b, &maxcontext, status);3732mpd_qsub(result, a, &bb, ctx, status);3733mpd_del(&bb);3734}3735#endif373637373738/* Divide infinities. */3739static void3740_mpd_qdiv_inf(mpd_t *result, const mpd_t *a, const mpd_t *b,3741const mpd_context_t *ctx, uint32_t *status)3742{3743if (mpd_isinfinite(a)) {3744if (mpd_isinfinite(b)) {3745mpd_seterror(result, MPD_Invalid_operation, status);3746return;3747}3748mpd_setspecial(result, mpd_sign(a)^mpd_sign(b), MPD_INF);3749return;3750}3751assert(mpd_isinfinite(b));3752_settriple(result, mpd_sign(a)^mpd_sign(b), 0, mpd_etiny(ctx));3753*status |= MPD_Clamped;3754}37553756enum {NO_IDEAL_EXP, SET_IDEAL_EXP};3757/* Divide a by b. */3758static void3759_mpd_qdiv(int action, mpd_t *q, const mpd_t *a, const mpd_t *b,3760const mpd_context_t *ctx, uint32_t *status)3761{3762MPD_NEW_STATIC(aligned,0,0,0,0);3763mpd_uint_t ld;3764mpd_ssize_t shift, exp, tz;3765mpd_ssize_t newsize;3766mpd_ssize_t ideal_exp;3767mpd_uint_t rem;3768uint8_t sign_a = mpd_sign(a);3769uint8_t sign_b = mpd_sign(b);377037713772if (mpd_isspecial(a) || mpd_isspecial(b)) {3773if (mpd_qcheck_nans(q, a, b, ctx, status)) {3774return;3775}3776_mpd_qdiv_inf(q, a, b, ctx, status);3777return;3778}3779if (mpd_iszerocoeff(b)) {3780if (mpd_iszerocoeff(a)) {3781mpd_seterror(q, MPD_Division_undefined, status);3782}3783else {3784mpd_setspecial(q, sign_a^sign_b, MPD_INF);3785*status |= MPD_Division_by_zero;3786}3787return;3788}3789if (mpd_iszerocoeff(a)) {3790exp = a->exp - b->exp;3791_settriple(q, sign_a^sign_b, 0, exp);3792mpd_qfinalize(q, ctx, status);3793return;3794}37953796shift = (b->digits - a->digits) + ctx->prec + 1;3797ideal_exp = a->exp - b->exp;3798exp = ideal_exp - shift;3799if (shift > 0) {3800if (!mpd_qshiftl(&aligned, a, shift, status)) {3801mpd_seterror(q, MPD_Malloc_error, status);3802goto finish;3803}3804a = &aligned;3805}3806else if (shift < 0) {3807shift = -shift;3808if (!mpd_qshiftl(&aligned, b, shift, status)) {3809mpd_seterror(q, MPD_Malloc_error, status);3810goto finish;3811}3812b = &aligned;3813}381438153816newsize = a->len - b->len + 1;3817if ((q != b && q != a) || (q == b && newsize > b->len)) {3818if (!mpd_qresize(q, newsize, status)) {3819mpd_seterror(q, MPD_Malloc_error, status);3820goto finish;3821}3822}382338243825if (b->len == 1) {3826rem = _mpd_shortdiv(q->data, a->data, a->len, b->data[0]);3827}3828else if (b->len <= MPD_NEWTONDIV_CUTOFF) {3829int ret = _mpd_basedivmod(q->data, NULL, a->data, b->data,3830a->len, b->len);3831if (ret < 0) {3832mpd_seterror(q, MPD_Malloc_error, status);3833goto finish;3834}3835rem = ret;3836}3837else {3838MPD_NEW_STATIC(r,0,0,0,0);3839_mpd_base_ndivmod(q, &r, a, b, status);3840if (mpd_isspecial(q) || mpd_isspecial(&r)) {3841mpd_setspecial(q, MPD_POS, MPD_NAN);3842mpd_del(&r);3843goto finish;3844}3845rem = !mpd_iszerocoeff(&r);3846mpd_del(&r);3847newsize = q->len;3848}38493850newsize = _mpd_real_size(q->data, newsize);3851/* resize to smaller cannot fail */3852mpd_qresize(q, newsize, status);3853mpd_set_flags(q, sign_a^sign_b);3854q->len = newsize;3855mpd_setdigits(q);38563857shift = ideal_exp - exp;3858if (rem) {3859ld = mpd_lsd(q->data[0]);3860if (ld == 0 || ld == 5) {3861q->data[0] += 1;3862}3863}3864else if (action == SET_IDEAL_EXP && shift > 0) {3865tz = mpd_trail_zeros(q);3866shift = (tz > shift) ? shift : tz;3867mpd_qshiftr_inplace(q, shift);3868exp += shift;3869}38703871q->exp = exp;387238733874finish:3875mpd_del(&aligned);3876mpd_qfinalize(q, ctx, status);3877}38783879/* Divide a by b. */3880void3881mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b,3882const mpd_context_t *ctx, uint32_t *status)3883{3884MPD_NEW_STATIC(aa,0,0,0,0);3885MPD_NEW_STATIC(bb,0,0,0,0);3886uint32_t xstatus = 0;38873888if (q == a) {3889if (!mpd_qcopy(&aa, a, status)) {3890mpd_seterror(q, MPD_Malloc_error, status);3891goto out;3892}3893a = &aa;3894}38953896if (q == b) {3897if (!mpd_qcopy(&bb, b, status)) {3898mpd_seterror(q, MPD_Malloc_error, status);3899goto out;3900}3901b = &bb;3902}39033904_mpd_qdiv(SET_IDEAL_EXP, q, a, b, ctx, &xstatus);39053906if (xstatus & (MPD_Malloc_error|MPD_Division_impossible)) {3907/* Inexact quotients (the usual case) fill the entire context precision,3908* which can lead to the above errors for very high precisions. Retry3909* the operation with a lower precision in case the result is exact.3910*3911* We need an upper bound for the number of digits of a_coeff / b_coeff3912* when the result is exact. If a_coeff' * 1 / b_coeff' is in lowest3913* terms, then maxdigits(a_coeff') + maxdigits(1 / b_coeff') is a suitable3914* bound.3915*3916* 1 / b_coeff' is exact iff b_coeff' exclusively has prime factors 2 or 5.3917* The largest amount of digits is generated if b_coeff' is a power of 2 or3918* a power of 5 and is less than or equal to log5(b_coeff') <= log2(b_coeff').3919*3920* We arrive at a total upper bound:3921*3922* maxdigits(a_coeff') + maxdigits(1 / b_coeff') <=3923* log10(a_coeff) + log2(b_coeff) =3924* log10(a_coeff) + log10(b_coeff) / log10(2) <=3925* a->digits + b->digits * 4;3926*/3927mpd_context_t workctx = *ctx;3928uint32_t ystatus = 0;39293930workctx.prec = a->digits + b->digits * 4;3931if (workctx.prec >= ctx->prec) {3932*status |= (xstatus&MPD_Errors);3933goto out; /* No point in retrying, keep the original error. */3934}39353936_mpd_qdiv(SET_IDEAL_EXP, q, a, b, &workctx, &ystatus);3937if (ystatus != 0) {3938ystatus = *status | ((ystatus|xstatus)&MPD_Errors);3939mpd_seterror(q, ystatus, status);3940}3941}3942else {3943*status |= xstatus;3944}394539463947out:3948mpd_del(&aa);3949mpd_del(&bb);3950}39513952/* Internal function. */3953static void3954_mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,3955const mpd_context_t *ctx, uint32_t *status)3956{3957MPD_NEW_STATIC(aligned,0,0,0,0);3958mpd_ssize_t qsize, rsize;3959mpd_ssize_t ideal_exp, expdiff, shift;3960uint8_t sign_a = mpd_sign(a);3961uint8_t sign_ab = mpd_sign(a)^mpd_sign(b);396239633964ideal_exp = (a->exp > b->exp) ? b->exp : a->exp;3965if (mpd_iszerocoeff(a)) {3966if (!mpd_qcopy(r, a, status)) {3967goto nanresult; /* GCOV_NOT_REACHED */3968}3969r->exp = ideal_exp;3970_settriple(q, sign_ab, 0, 0);3971return;3972}39733974expdiff = mpd_adjexp(a) - mpd_adjexp(b);3975if (expdiff < 0) {3976if (a->exp > b->exp) {3977/* positive and less than b->digits - a->digits */3978shift = a->exp - b->exp;3979if (!mpd_qshiftl(r, a, shift, status)) {3980goto nanresult;3981}3982r->exp = ideal_exp;3983}3984else {3985if (!mpd_qcopy(r, a, status)) {3986goto nanresult;3987}3988}3989_settriple(q, sign_ab, 0, 0);3990return;3991}3992if (expdiff > ctx->prec) {3993*status |= MPD_Division_impossible;3994goto nanresult;3995}399639973998/*3999* At this point we have:4000* (1) 0 <= a->exp + a->digits - b->exp - b->digits <= prec4001* (2) a->exp - b->exp >= b->digits - a->digits4002* (3) a->exp - b->exp <= prec + b->digits - a->digits4003*/4004if (a->exp != b->exp) {4005shift = a->exp - b->exp;4006if (shift > 0) {4007/* by (3), after the shift a->digits <= prec + b->digits */4008if (!mpd_qshiftl(&aligned, a, shift, status)) {4009goto nanresult;4010}4011a = &aligned;4012}4013else {4014shift = -shift;4015/* by (2), after the shift b->digits <= a->digits */4016if (!mpd_qshiftl(&aligned, b, shift, status)) {4017goto nanresult;4018}4019b = &aligned;4020}4021}402240234024qsize = a->len - b->len + 1;4025if (!(q == a && qsize < a->len) && !(q == b && qsize < b->len)) {4026if (!mpd_qresize(q, qsize, status)) {4027goto nanresult;4028}4029}40304031rsize = b->len;4032if (!(r == a && rsize < a->len)) {4033if (!mpd_qresize(r, rsize, status)) {4034goto nanresult;4035}4036}40374038if (b->len == 1) {4039assert(b->data[0] != 0); /* annotation for scan-build */4040if (a->len == 1) {4041_mpd_div_word(&q->data[0], &r->data[0], a->data[0], b->data[0]);4042}4043else {4044r->data[0] = _mpd_shortdiv(q->data, a->data, a->len, b->data[0]);4045}4046}4047else if (b->len <= MPD_NEWTONDIV_CUTOFF) {4048int ret;4049ret = _mpd_basedivmod(q->data, r->data, a->data, b->data,4050a->len, b->len);4051if (ret == -1) {4052*status |= MPD_Malloc_error;4053goto nanresult;4054}4055}4056else {4057_mpd_base_ndivmod(q, r, a, b, status);4058if (mpd_isspecial(q) || mpd_isspecial(r)) {4059goto nanresult;4060}4061qsize = q->len;4062rsize = r->len;4063}40644065qsize = _mpd_real_size(q->data, qsize);4066/* resize to smaller cannot fail */4067mpd_qresize(q, qsize, status);4068q->len = qsize;4069mpd_setdigits(q);4070mpd_set_flags(q, sign_ab);4071q->exp = 0;4072if (q->digits > ctx->prec) {4073*status |= MPD_Division_impossible;4074goto nanresult;4075}40764077rsize = _mpd_real_size(r->data, rsize);4078/* resize to smaller cannot fail */4079mpd_qresize(r, rsize, status);4080r->len = rsize;4081mpd_setdigits(r);4082mpd_set_flags(r, sign_a);4083r->exp = ideal_exp;40844085out:4086mpd_del(&aligned);4087return;40884089nanresult:4090mpd_setspecial(q, MPD_POS, MPD_NAN);4091mpd_setspecial(r, MPD_POS, MPD_NAN);4092goto out;4093}40944095/* Integer division with remainder. */4096void4097mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,4098const mpd_context_t *ctx, uint32_t *status)4099{4100uint8_t sign = mpd_sign(a)^mpd_sign(b);41014102if (mpd_isspecial(a) || mpd_isspecial(b)) {4103if (mpd_qcheck_nans(q, a, b, ctx, status)) {4104mpd_qcopy(r, q, status);4105return;4106}4107if (mpd_isinfinite(a)) {4108if (mpd_isinfinite(b)) {4109mpd_setspecial(q, MPD_POS, MPD_NAN);4110}4111else {4112mpd_setspecial(q, sign, MPD_INF);4113}4114mpd_setspecial(r, MPD_POS, MPD_NAN);4115*status |= MPD_Invalid_operation;4116return;4117}4118if (mpd_isinfinite(b)) {4119if (!mpd_qcopy(r, a, status)) {4120mpd_seterror(q, MPD_Malloc_error, status);4121return;4122}4123mpd_qfinalize(r, ctx, status);4124_settriple(q, sign, 0, 0);4125return;4126}4127/* debug */4128abort(); /* GCOV_NOT_REACHED */4129}4130if (mpd_iszerocoeff(b)) {4131if (mpd_iszerocoeff(a)) {4132mpd_setspecial(q, MPD_POS, MPD_NAN);4133mpd_setspecial(r, MPD_POS, MPD_NAN);4134*status |= MPD_Division_undefined;4135}4136else {4137mpd_setspecial(q, sign, MPD_INF);4138mpd_setspecial(r, MPD_POS, MPD_NAN);4139*status |= (MPD_Division_by_zero|MPD_Invalid_operation);4140}4141return;4142}41434144_mpd_qdivmod(q, r, a, b, ctx, status);4145mpd_qfinalize(q, ctx, status);4146mpd_qfinalize(r, ctx, status);4147}41484149void4150mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b,4151const mpd_context_t *ctx, uint32_t *status)4152{4153MPD_NEW_STATIC(r,0,0,0,0);4154uint8_t sign = mpd_sign(a)^mpd_sign(b);41554156if (mpd_isspecial(a) || mpd_isspecial(b)) {4157if (mpd_qcheck_nans(q, a, b, ctx, status)) {4158return;4159}4160if (mpd_isinfinite(a) && mpd_isinfinite(b)) {4161mpd_seterror(q, MPD_Invalid_operation, status);4162return;4163}4164if (mpd_isinfinite(a)) {4165mpd_setspecial(q, sign, MPD_INF);4166return;4167}4168if (mpd_isinfinite(b)) {4169_settriple(q, sign, 0, 0);4170return;4171}4172/* debug */4173abort(); /* GCOV_NOT_REACHED */4174}4175if (mpd_iszerocoeff(b)) {4176if (mpd_iszerocoeff(a)) {4177mpd_seterror(q, MPD_Division_undefined, status);4178}4179else {4180mpd_setspecial(q, sign, MPD_INF);4181*status |= MPD_Division_by_zero;4182}4183return;4184}418541864187_mpd_qdivmod(q, &r, a, b, ctx, status);4188mpd_del(&r);4189mpd_qfinalize(q, ctx, status);4190}41914192/* Divide decimal by mpd_ssize_t. */4193void4194mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,4195const mpd_context_t *ctx, uint32_t *status)4196{4197mpd_context_t maxcontext;4198MPD_NEW_STATIC(bb,0,0,0,0);41994200mpd_maxcontext(&maxcontext);4201mpd_qsset_ssize(&bb, b, &maxcontext, status);4202mpd_qdiv(result, a, &bb, ctx, status);4203mpd_del(&bb);4204}42054206/* Divide decimal by mpd_uint_t. */4207void4208mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,4209const mpd_context_t *ctx, uint32_t *status)4210{4211mpd_context_t maxcontext;4212MPD_NEW_STATIC(bb,0,0,0,0);42134214mpd_maxcontext(&maxcontext);4215mpd_qsset_uint(&bb, b, &maxcontext, status);4216mpd_qdiv(result, a, &bb, ctx, status);4217mpd_del(&bb);4218}42194220/* Divide decimal by int32_t. */4221void4222mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b,4223const mpd_context_t *ctx, uint32_t *status)4224{4225mpd_qdiv_ssize(result, a, b, ctx, status);4226}42274228/* Divide decimal by uint32_t. */4229void4230mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b,4231const mpd_context_t *ctx, uint32_t *status)4232{4233mpd_qdiv_uint(result, a, b, ctx, status);4234}42354236#ifdef CONFIG_644237/* Divide decimal by int64_t. */4238void4239mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b,4240const mpd_context_t *ctx, uint32_t *status)4241{4242mpd_qdiv_ssize(result, a, b, ctx, status);4243}42444245/* Divide decimal by uint64_t. */4246void4247mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,4248const mpd_context_t *ctx, uint32_t *status)4249{4250mpd_qdiv_uint(result, a, b, ctx, status);4251}4252#elif !defined(LEGACY_COMPILER)4253/* Divide decimal by int64_t. */4254void4255mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b,4256const mpd_context_t *ctx, uint32_t *status)4257{4258mpd_context_t maxcontext;4259MPD_NEW_STATIC(bb,0,0,0,0);42604261mpd_maxcontext(&maxcontext);4262mpd_qset_i64(&bb, b, &maxcontext, status);4263mpd_qdiv(result, a, &bb, ctx, status);4264mpd_del(&bb);4265}42664267/* Divide decimal by uint64_t. */4268void4269mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,4270const mpd_context_t *ctx, uint32_t *status)4271{4272mpd_context_t maxcontext;4273MPD_NEW_STATIC(bb,0,0,0,0);42744275mpd_maxcontext(&maxcontext);4276mpd_qset_u64(&bb, b, &maxcontext, status);4277mpd_qdiv(result, a, &bb, ctx, status);4278mpd_del(&bb);4279}4280#endif42814282/* Pad the result with trailing zeros if it has fewer digits than prec. */4283static void4284_mpd_zeropad(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)4285{4286if (!mpd_isspecial(result) && !mpd_iszero(result) &&4287result->digits < ctx->prec) {4288mpd_ssize_t shift = ctx->prec - result->digits;4289mpd_qshiftl(result, result, shift, status);4290result->exp -= shift;4291}4292}42934294/* Check if the result is guaranteed to be one. */4295static int4296_mpd_qexp_check_one(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,4297uint32_t *status)4298{4299MPD_NEW_CONST(lim,0,-(ctx->prec+1),1,1,1,9);4300MPD_NEW_SHARED(aa, a);43014302mpd_set_positive(&aa);43034304/* abs(a) <= 9 * 10**(-prec-1) */4305if (_mpd_cmp(&aa, &lim) <= 0) {4306_settriple(result, 0, 1, 0);4307*status |= MPD_Rounded|MPD_Inexact;4308return 1;4309}43104311return 0;4312}43134314/*4315* Get the number of iterations for the Horner scheme in _mpd_qexp().4316*/4317static inline mpd_ssize_t4318_mpd_get_exp_iterations(const mpd_t *r, mpd_ssize_t p)4319{4320mpd_ssize_t log10pbyr; /* lower bound for log10(p / abs(r)) */4321mpd_ssize_t n;43224323assert(p >= 10);4324assert(!mpd_iszero(r));4325assert(-p < mpd_adjexp(r) && mpd_adjexp(r) <= -1);43264327#ifdef CONFIG_644328if (p > (mpd_ssize_t)(1ULL<<52)) {4329return MPD_SSIZE_MAX;4330}4331#endif43324333/*4334* Lower bound for log10(p / abs(r)): adjexp(p) - (adjexp(r) + 1)4335* At this point (for CONFIG_64, CONFIG_32 is not problematic):4336* 1) 10 <= p <= 2**524337* 2) -p < adjexp(r) <= -14338* 3) 1 <= log10pbyr <= 2**52 + 144339*/4340log10pbyr = (mpd_word_digits(p)-1) - (mpd_adjexp(r)+1);43414342/*4343* The numerator in the paper is 1.435 * p - 1.182, calculated4344* exactly. We compensate for rounding errors by using 1.43503.4345* ACL2 proofs:4346* 1) exp-iter-approx-lower-bound: The term below evaluated4347* in 53-bit floating point arithmetic is greater than or4348* equal to the exact term used in the paper.4349* 2) exp-iter-approx-upper-bound: The term below is less than4350* or equal to 3/2 * p <= 3/2 * 2**52.4351*/4352n = (mpd_ssize_t)ceil((1.43503*(double)p - 1.182) / (double)log10pbyr);4353return n >= 3 ? n : 3;4354}43554356/*4357* Internal function, specials have been dealt with. Apart from Overflow4358* and Underflow, two cases must be considered for the error of the result:4359*4360* 1) abs(a) <= 9 * 10**(-prec-1) ==> result == 14361*4362* Absolute error: abs(1 - e**x) < 10**(-prec)4363* -------------------------------------------4364*4365* 2) abs(a) > 9 * 10**(-prec-1)4366*4367* Relative error: abs(result - e**x) < 0.5 * 10**(-prec) * e**x4368* -------------------------------------------------------------4369*4370* The algorithm is from Hull&Abrham, Variable Precision Exponential Function,4371* ACM Transactions on Mathematical Software, Vol. 12, No. 2, June 1986.4372*4373* Main differences:4374*4375* - The number of iterations for the Horner scheme is calculated using4376* 53-bit floating point arithmetic.4377*4378* - In the error analysis for ER (relative error accumulated in the4379* evaluation of the truncated series) the reduced operand r may4380* have any number of digits.4381* ACL2 proof: exponent-relative-error4382*4383* - The analysis for early abortion has been adapted for the mpd_t4384* ranges.4385*/4386static void4387_mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,4388uint32_t *status)4389{4390mpd_context_t workctx;4391MPD_NEW_STATIC(tmp,0,0,0,0);4392MPD_NEW_STATIC(sum,0,0,0,0);4393MPD_NEW_CONST(word,0,0,1,1,1,1);4394mpd_ssize_t j, n, t;43954396assert(!mpd_isspecial(a));43974398if (mpd_iszerocoeff(a)) {4399_settriple(result, MPD_POS, 1, 0);4400return;4401}44024403/*4404* We are calculating e^x = e^(r*10^t) = (e^r)^(10^t), where abs(r) < 1 and t >= 0.4405*4406* If t > 0, we have:4407*4408* (1) 0.1 <= r < 1, so e^0.1 <= e^r. If t > MAX_T, overflow occurs:4409*4410* MAX-EMAX+1 < log10(e^(0.1*10*t)) <= log10(e^(r*10^t)) < adjexp(e^(r*10^t))+14411*4412* (2) -1 < r <= -0.1, so e^r <= e^-0.1. If t > MAX_T, underflow occurs:4413*4414* adjexp(e^(r*10^t)) <= log10(e^(r*10^t)) <= log10(e^(-0.1*10^t)) < MIN-ETINY4415*/4416#if defined(CONFIG_64)4417#define MPD_EXP_MAX_T 194418#elif defined(CONFIG_32)4419#define MPD_EXP_MAX_T 104420#endif4421t = a->digits + a->exp;4422t = (t > 0) ? t : 0;4423if (t > MPD_EXP_MAX_T) {4424if (mpd_ispositive(a)) {4425mpd_setspecial(result, MPD_POS, MPD_INF);4426*status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;4427}4428else {4429_settriple(result, MPD_POS, 0, mpd_etiny(ctx));4430*status |= (MPD_Inexact|MPD_Rounded|MPD_Subnormal|4431MPD_Underflow|MPD_Clamped);4432}4433return;4434}44354436/* abs(a) <= 9 * 10**(-prec-1) */4437if (_mpd_qexp_check_one(result, a, ctx, status)) {4438return;4439}44404441mpd_maxcontext(&workctx);4442workctx.prec = ctx->prec + t + 2;4443workctx.prec = (workctx.prec < 10) ? 10 : workctx.prec;4444workctx.round = MPD_ROUND_HALF_EVEN;44454446if (!mpd_qcopy(result, a, status)) {4447return;4448}4449result->exp -= t;44504451/*4452* At this point:4453* 1) 9 * 10**(-prec-1) < abs(a)4454* 2) 9 * 10**(-prec-t-1) < abs(r)4455* 3) log10(9) - prec - t - 1 < log10(abs(r)) < adjexp(abs(r)) + 14456* 4) - prec - t - 2 < adjexp(abs(r)) <= -14457*/4458n = _mpd_get_exp_iterations(result, workctx.prec);4459if (n == MPD_SSIZE_MAX) {4460mpd_seterror(result, MPD_Invalid_operation, status); /* GCOV_UNLIKELY */4461return; /* GCOV_UNLIKELY */4462}44634464_settriple(&sum, MPD_POS, 1, 0);44654466for (j = n-1; j >= 1; j--) {4467word.data[0] = j;4468mpd_setdigits(&word);4469mpd_qdiv(&tmp, result, &word, &workctx, &workctx.status);4470mpd_qfma(&sum, &sum, &tmp, &one, &workctx, &workctx.status);4471}44724473#ifdef CONFIG_644474_mpd_qpow_uint(result, &sum, mpd_pow10[t], MPD_POS, &workctx, status);4475#else4476if (t <= MPD_MAX_POW10) {4477_mpd_qpow_uint(result, &sum, mpd_pow10[t], MPD_POS, &workctx, status);4478}4479else {4480t -= MPD_MAX_POW10;4481_mpd_qpow_uint(&tmp, &sum, mpd_pow10[MPD_MAX_POW10], MPD_POS,4482&workctx, status);4483_mpd_qpow_uint(result, &tmp, mpd_pow10[t], MPD_POS, &workctx, status);4484}4485#endif44864487mpd_del(&tmp);4488mpd_del(&sum);4489*status |= (workctx.status&MPD_Errors);4490*status |= (MPD_Inexact|MPD_Rounded);4491}44924493/* exp(a) */4494void4495mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,4496uint32_t *status)4497{4498mpd_context_t workctx;44994500if (mpd_isspecial(a)) {4501if (mpd_qcheck_nan(result, a, ctx, status)) {4502return;4503}4504if (mpd_isnegative(a)) {4505_settriple(result, MPD_POS, 0, 0);4506}4507else {4508mpd_setspecial(result, MPD_POS, MPD_INF);4509}4510return;4511}4512if (mpd_iszerocoeff(a)) {4513_settriple(result, MPD_POS, 1, 0);4514return;4515}45164517workctx = *ctx;4518workctx.round = MPD_ROUND_HALF_EVEN;45194520if (ctx->allcr) {4521MPD_NEW_STATIC(t1, 0,0,0,0);4522MPD_NEW_STATIC(t2, 0,0,0,0);4523MPD_NEW_STATIC(ulp, 0,0,0,0);4524MPD_NEW_STATIC(aa, 0,0,0,0);4525mpd_ssize_t prec;4526mpd_ssize_t ulpexp;4527uint32_t workstatus;45284529if (result == a) {4530if (!mpd_qcopy(&aa, a, status)) {4531mpd_seterror(result, MPD_Malloc_error, status);4532return;4533}4534a = &aa;4535}45364537workctx.clamp = 0;4538prec = ctx->prec + 3;4539while (1) {4540workctx.prec = prec;4541workstatus = 0;45424543_mpd_qexp(result, a, &workctx, &workstatus);4544*status |= workstatus;45454546ulpexp = result->exp + result->digits - workctx.prec;4547if (workstatus & MPD_Underflow) {4548/* The effective work precision is result->digits. */4549ulpexp = result->exp;4550}4551_ssettriple(&ulp, MPD_POS, 1, ulpexp);45524553/*4554* At this point [1]:4555* 1) abs(result - e**x) < 0.5 * 10**(-prec) * e**x4556* 2) result - ulp < e**x < result + ulp4557* 3) result - ulp < result < result + ulp4558*4559* If round(result-ulp)==round(result+ulp), then4560* round(result)==round(e**x). Therefore the result4561* is correctly rounded.4562*4563* [1] If abs(a) <= 9 * 10**(-prec-1), use the absolute4564* error for a similar argument.4565*/4566workctx.prec = ctx->prec;4567mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status);4568mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status);4569if (mpd_isspecial(result) || mpd_iszerocoeff(result) ||4570mpd_qcmp(&t1, &t2, status) == 0) {4571workctx.clamp = ctx->clamp;4572_mpd_zeropad(result, &workctx, status);4573mpd_check_underflow(result, &workctx, status);4574mpd_qfinalize(result, &workctx, status);4575break;4576}4577prec += MPD_RDIGITS;4578}4579mpd_del(&t1);4580mpd_del(&t2);4581mpd_del(&ulp);4582mpd_del(&aa);4583}4584else {4585_mpd_qexp(result, a, &workctx, status);4586_mpd_zeropad(result, &workctx, status);4587mpd_check_underflow(result, &workctx, status);4588mpd_qfinalize(result, &workctx, status);4589}4590}45914592/* Fused multiply-add: (a * b) + c, with a single final rounding. */4593void4594mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c,4595const mpd_context_t *ctx, uint32_t *status)4596{4597uint32_t workstatus = 0;4598mpd_t *cc = NULL;45994600if (result == c) {4601if ((cc = mpd_qncopy(c)) == NULL) {4602mpd_seterror(result, MPD_Malloc_error, status);4603return;4604}4605c = cc;4606}46074608_mpd_qmul(result, a, b, ctx, &workstatus);4609if (!(workstatus&MPD_Invalid_operation)) {4610mpd_qadd(result, result, c, ctx, &workstatus);4611}46124613if (cc) mpd_del(cc);4614*status |= workstatus;4615}46164617/*4618* Schedule the optimal precision increase for the Newton iteration.4619* v := input operand4620* z_0 := initial approximation4621* initprec := natural number such that abs(log(v) - z_0) < 10**-initprec4622* maxprec := target precision4623*4624* For convenience the output klist contains the elements in reverse order:4625* klist := [k_n-1, ..., k_0], where4626* 1) k_0 <= initprec and4627* 2) abs(log(v) - result) < 10**(-2*k_n-1 + 1) <= 10**-maxprec.4628*/4629static inline int4630ln_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2], mpd_ssize_t maxprec,4631mpd_ssize_t initprec)4632{4633mpd_ssize_t k;4634int i;46354636assert(maxprec >= 2 && initprec >= 2);4637if (maxprec <= initprec) return -1;46384639i = 0; k = maxprec;4640do {4641k = (k+2) / 2;4642klist[i++] = k;4643} while (k > initprec);46444645return i-1;4646}46474648/* The constants have been verified with both decimal.py and mpfr. */4649#ifdef CONFIG_644650#if MPD_RDIGITS != 194651#error "mpdecimal.c: MPD_RDIGITS must be 19."4652#endif4653static const mpd_uint_t mpd_ln10_data[MPD_MINALLOC_MAX] = {46546983716328982174407ULL, 9089704281976336583ULL, 1515961135648465461ULL,46554416816335727555703ULL, 2900988039194170265ULL, 2307925037472986509ULL,4656107598438319191292ULL, 3466624107184669231ULL, 4450099781311469159ULL,46579807828059751193854ULL, 7713456862091670584ULL, 1492198849978748873ULL,46586528728696511086257ULL, 2385392051446341972ULL, 8692180205189339507ULL,46596518769751037497088ULL, 2375253577097505395ULL, 9095610299291824318ULL,4660982748238504564801ULL, 5438635917781170543ULL, 7547331541421808427ULL,4661752371033310119785ULL, 3171643095059950878ULL, 9785265383207606726ULL,46622932258279850258550ULL, 5497347726624257094ULL, 2976979522110718264ULL,46639221477656763693866ULL, 1979650047149510504ULL, 6674183485704422507ULL,46649702766860595249671ULL, 9278096762712757753ULL, 9314848524948644871ULL,46656826928280848118428ULL, 754403708474699401ULL, 230105703089634572ULL,46661929203337658714166ULL, 7589402567763113569ULL, 4208241314695689016ULL,46672922455440575892572ULL, 9356734206705811364ULL, 2684916746550586856ULL,4668644507064800027750ULL, 9476834636167921018ULL, 5659121373450747856ULL,46692835522011480466371ULL, 6470806855677432162ULL, 7141748003688084012ULL,46709619404400222105101ULL, 5504893431493939147ULL, 6674744042432743651ULL,46712287698219886746543ULL, 7773262884616336622ULL, 1985283935053089653ULL,46724680843799894826233ULL, 8168948290720832555ULL, 8067566662873690987ULL,46736248633409525465082ULL, 9829834196778404228ULL, 3524802359972050895ULL,46743327900967572609677ULL, 110148862877297603ULL, 179914546843642076ULL,46752302585092994045684ULL4676};4677#else4678#if MPD_RDIGITS != 94679#error "mpdecimal.c: MPD_RDIGITS must be 9."4680#endif4681static const mpd_uint_t mpd_ln10_data[MPD_MINALLOC_MAX] = {4682401682692UL, 708474699UL, 720754403UL, 30896345UL, 602301057UL, 765871416UL,4683192920333UL, 763113569UL, 589402567UL, 956890167UL, 82413146UL, 589257242UL,4684245544057UL, 811364292UL, 734206705UL, 868569356UL, 167465505UL, 775026849UL,4685706480002UL, 18064450UL, 636167921UL, 569476834UL, 734507478UL, 156591213UL,4686148046637UL, 283552201UL, 677432162UL, 470806855UL, 880840126UL, 417480036UL,4687210510171UL, 940440022UL, 939147961UL, 893431493UL, 436515504UL, 440424327UL,4688654366747UL, 821988674UL, 622228769UL, 884616336UL, 537773262UL, 350530896UL,4689319852839UL, 989482623UL, 468084379UL, 720832555UL, 168948290UL, 736909878UL,4690675666628UL, 546508280UL, 863340952UL, 404228624UL, 834196778UL, 508959829UL,469123599720UL, 967735248UL, 96757260UL, 603332790UL, 862877297UL, 760110148UL,4692468436420UL, 401799145UL, 299404568UL, 230258509UL4693};4694#endif4695/* _mpd_ln10 is used directly for precisions smaller than MINALLOC_MAX*RDIGITS.4696Otherwise, it serves as the initial approximation for calculating ln(10). */4697static const mpd_t _mpd_ln10 = {4698MPD_STATIC|MPD_CONST_DATA, -(MPD_MINALLOC_MAX*MPD_RDIGITS-1),4699MPD_MINALLOC_MAX*MPD_RDIGITS, MPD_MINALLOC_MAX, MPD_MINALLOC_MAX,4700(mpd_uint_t *)mpd_ln10_data4701};47024703/*4704* Set 'result' to log(10).4705* Ulp error: abs(result - log(10)) < ulp(log(10))4706* Relative error: abs(result - log(10)) < 5 * 10**-prec * log(10)4707*4708* NOTE: The relative error is not derived from the ulp error, but4709* calculated separately using the fact that 23/10 < log(10) < 24/10.4710*/4711void4712mpd_qln10(mpd_t *result, mpd_ssize_t prec, uint32_t *status)4713{4714mpd_context_t varcontext, maxcontext;4715MPD_NEW_STATIC(tmp, 0,0,0,0);4716MPD_NEW_CONST(static10, 0,0,2,1,1,10);4717mpd_ssize_t klist[MPD_MAX_PREC_LOG2];4718mpd_uint_t rnd;4719mpd_ssize_t shift;4720int i;47214722assert(prec >= 1);47234724shift = MPD_MINALLOC_MAX*MPD_RDIGITS-prec;4725shift = shift < 0 ? 0 : shift;47264727rnd = mpd_qshiftr(result, &_mpd_ln10, shift, status);4728if (rnd == MPD_UINT_MAX) {4729mpd_seterror(result, MPD_Malloc_error, status);4730return;4731}4732result->exp = -(result->digits-1);47334734mpd_maxcontext(&maxcontext);4735if (prec < MPD_MINALLOC_MAX*MPD_RDIGITS) {4736maxcontext.prec = prec;4737_mpd_apply_round_excess(result, rnd, &maxcontext, status);4738*status |= (MPD_Inexact|MPD_Rounded);4739return;4740}47414742mpd_maxcontext(&varcontext);4743varcontext.round = MPD_ROUND_TRUNC;47444745i = ln_schedule_prec(klist, prec+2, -result->exp);4746for (; i >= 0; i--) {4747varcontext.prec = 2*klist[i]+3;4748result->flags ^= MPD_NEG;4749_mpd_qexp(&tmp, result, &varcontext, status);4750result->flags ^= MPD_NEG;4751mpd_qmul(&tmp, &static10, &tmp, &varcontext, status);4752mpd_qsub(&tmp, &tmp, &one, &maxcontext, status);4753mpd_qadd(result, result, &tmp, &maxcontext, status);4754if (mpd_isspecial(result)) {4755break;4756}4757}47584759mpd_del(&tmp);4760maxcontext.prec = prec;4761mpd_qfinalize(result, &maxcontext, status);4762}47634764/*4765* Initial approximations for the ln() iteration. The values have the4766* following properties (established with both decimal.py and mpfr):4767*4768* Index 0 - 400, logarithms of x in [1.00, 5.00]:4769* abs(lnapprox[i] * 10**-3 - log((i+100)/100)) < 10**-24770* abs(lnapprox[i] * 10**-3 - log((i+1+100)/100)) < 10**-24771*4772* Index 401 - 899, logarithms of x in (0.500, 0.999]:4773* abs(-lnapprox[i] * 10**-3 - log((i+100)/1000)) < 10**-24774* abs(-lnapprox[i] * 10**-3 - log((i+1+100)/1000)) < 10**-24775*/4776static const uint16_t lnapprox[900] = {4777/* index 0 - 400: log((i+100)/100) * 1000 */47780, 10, 20, 30, 39, 49, 58, 68, 77, 86, 95, 104, 113, 122, 131, 140, 148, 157,4779166, 174, 182, 191, 199, 207, 215, 223, 231, 239, 247, 255, 262, 270, 278,4780285, 293, 300, 308, 315, 322, 329, 336, 344, 351, 358, 365, 372, 378, 385,4781392, 399, 406, 412, 419, 425, 432, 438, 445, 451, 457, 464, 470, 476, 482,4782489, 495, 501, 507, 513, 519, 525, 531, 536, 542, 548, 554, 560, 565, 571,4783577, 582, 588, 593, 599, 604, 610, 615, 621, 626, 631, 637, 642, 647, 652,4784658, 663, 668, 673, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728,4785732, 737, 742, 747, 751, 756, 761, 766, 770, 775, 779, 784, 788, 793, 798,4786802, 806, 811, 815, 820, 824, 829, 833, 837, 842, 846, 850, 854, 859, 863,4787867, 871, 876, 880, 884, 888, 892, 896, 900, 904, 908, 912, 916, 920, 924,4788928, 932, 936, 940, 944, 948, 952, 956, 959, 963, 967, 971, 975, 978, 982,4789986, 990, 993, 997, 1001, 1004, 1008, 1012, 1015, 1019, 1022, 1026, 1030,47901033, 1037, 1040, 1044, 1047, 1051, 1054, 1058, 1061, 1065, 1068, 1072, 1075,47911078, 1082, 1085, 1089, 1092, 1095, 1099, 1102, 1105, 1109, 1112, 1115, 1118,47921122, 1125, 1128, 1131, 1135, 1138, 1141, 1144, 1147, 1151, 1154, 1157, 1160,47931163, 1166, 1169, 1172, 1176, 1179, 1182, 1185, 1188, 1191, 1194, 1197, 1200,47941203, 1206, 1209, 1212, 1215, 1218, 1221, 1224, 1227, 1230, 1233, 1235, 1238,47951241, 1244, 1247, 1250, 1253, 1256, 1258, 1261, 1264, 1267, 1270, 1273, 1275,47961278, 1281, 1284, 1286, 1289, 1292, 1295, 1297, 1300, 1303, 1306, 1308, 1311,47971314, 1316, 1319, 1322, 1324, 1327, 1330, 1332, 1335, 1338, 1340, 1343, 1345,47981348, 1351, 1353, 1356, 1358, 1361, 1364, 1366, 1369, 1371, 1374, 1376, 1379,47991381, 1384, 1386, 1389, 1391, 1394, 1396, 1399, 1401, 1404, 1406, 1409, 1411,48001413, 1416, 1418, 1421, 1423, 1426, 1428, 1430, 1433, 1435, 1437, 1440, 1442,48011445, 1447, 1449, 1452, 1454, 1456, 1459, 1461, 1463, 1466, 1468, 1470, 1472,48021475, 1477, 1479, 1482, 1484, 1486, 1488, 1491, 1493, 1495, 1497, 1500, 1502,48031504, 1506, 1509, 1511, 1513, 1515, 1517, 1520, 1522, 1524, 1526, 1528, 1530,48041533, 1535, 1537, 1539, 1541, 1543, 1545, 1548, 1550, 1552, 1554, 1556, 1558,48051560, 1562, 1564, 1567, 1569, 1571, 1573, 1575, 1577, 1579, 1581, 1583, 1585,48061587, 1589, 1591, 1593, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1609,4807/* index 401 - 899: -log((i+100)/1000) * 1000 */4808691, 689, 687, 685, 683, 681, 679, 677, 675, 673, 671, 669, 668, 666, 664,4809662, 660, 658, 656, 654, 652, 650, 648, 646, 644, 642, 641, 639, 637, 635,4810633, 631, 629, 627, 626, 624, 622, 620, 618, 616, 614, 612, 611, 609, 607,4811605, 603, 602, 600, 598, 596, 594, 592, 591, 589, 587, 585, 583, 582, 580,4812578, 576, 574, 573, 571, 569, 567, 566, 564, 562, 560, 559, 557, 555, 553,4813552, 550, 548, 546, 545, 543, 541, 540, 538, 536, 534, 533, 531, 529, 528,4814526, 524, 523, 521, 519, 518, 516, 514, 512, 511, 509, 508, 506, 504, 502,4815501, 499, 498, 496, 494, 493, 491, 489, 488, 486, 484, 483, 481, 480, 478,4816476, 475, 473, 472, 470, 468, 467, 465, 464, 462, 460, 459, 457, 456, 454,4817453, 451, 449, 448, 446, 445, 443, 442, 440, 438, 437, 435, 434, 432, 431,4818429, 428, 426, 425, 423, 422, 420, 419, 417, 416, 414, 412, 411, 410, 408,4819406, 405, 404, 402, 400, 399, 398, 396, 394, 393, 392, 390, 389, 387, 386,4820384, 383, 381, 380, 378, 377, 375, 374, 372, 371, 370, 368, 367, 365, 364,4821362, 361, 360, 358, 357, 355, 354, 352, 351, 350, 348, 347, 345, 344, 342,4822341, 340, 338, 337, 336, 334, 333, 331, 330, 328, 327, 326, 324, 323, 322,4823320, 319, 318, 316, 315, 313, 312, 311, 309, 308, 306, 305, 304, 302, 301,4824300, 298, 297, 296, 294, 293, 292, 290, 289, 288, 286, 285, 284, 282, 281,4825280, 278, 277, 276, 274, 273, 272, 270, 269, 268, 267, 265, 264, 263, 261,4826260, 259, 258, 256, 255, 254, 252, 251, 250, 248, 247, 246, 245, 243, 242,4827241, 240, 238, 237, 236, 234, 233, 232, 231, 229, 228, 227, 226, 224, 223,4828222, 221, 219, 218, 217, 216, 214, 213, 212, 211, 210, 208, 207, 206, 205,4829203, 202, 201, 200, 198, 197, 196, 195, 194, 192, 191, 190, 189, 188, 186,4830185, 184, 183, 182, 180, 179, 178, 177, 176, 174, 173, 172, 171, 170, 168,4831167, 166, 165, 164, 162, 161, 160, 159, 158, 157, 156, 154, 153, 152, 151,4832150, 148, 147, 146, 145, 144, 143, 142, 140, 139, 138, 137, 136, 135, 134,4833132, 131, 130, 129, 128, 127, 126, 124, 123, 122, 121, 120, 119, 118, 116,4834115, 114, 113, 112, 111, 110, 109, 108, 106, 105, 104, 103, 102, 101, 100,483599, 98, 97, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 84, 83, 82, 81, 80, 79,483678, 77, 76, 75, 74, 73, 72, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59,483758, 57, 56, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39,483838, 37, 36, 35, 34, 33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19,483918, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 14840};48414842/*4843* Internal ln() function that does not check for specials, zero or one.4844* Relative error: abs(result - log(a)) < 0.1 * 10**-prec * abs(log(a))4845*/4846static void4847_mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,4848uint32_t *status)4849{4850mpd_context_t varcontext, maxcontext;4851mpd_t *z = result;4852MPD_NEW_STATIC(v,0,0,0,0);4853MPD_NEW_STATIC(vtmp,0,0,0,0);4854MPD_NEW_STATIC(tmp,0,0,0,0);4855mpd_ssize_t klist[MPD_MAX_PREC_LOG2];4856mpd_ssize_t maxprec, shift, t;4857mpd_ssize_t a_digits, a_exp;4858mpd_uint_t dummy, x;4859int i;48604861assert(!mpd_isspecial(a) && !mpd_iszerocoeff(a));48624863/*4864* We are calculating ln(a) = ln(v * 10^t) = ln(v) + t*ln(10),4865* where 0.5 < v <= 5.4866*/4867if (!mpd_qcopy(&v, a, status)) {4868mpd_seterror(result, MPD_Malloc_error, status);4869goto finish;4870}48714872/* Initial approximation: we have at least one non-zero digit */4873_mpd_get_msdigits(&dummy, &x, &v, 3);4874if (x < 10) x *= 10;4875if (x < 100) x *= 10;4876x -= 100;48774878/* a may equal z */4879a_digits = a->digits;4880a_exp = a->exp;48814882mpd_minalloc(z);4883mpd_clear_flags(z);4884z->data[0] = lnapprox[x];4885z->len = 1;4886z->exp = -3;4887mpd_setdigits(z);48884889if (x <= 400) {4890/* Reduce the input operand to 1.00 <= v <= 5.00. Let y = x + 100,4891* so 100 <= y <= 500. Since y contains the most significant digits4892* of v, y/100 <= v < (y+1)/100 and abs(z - log(v)) < 10**-2. */4893v.exp = -(a_digits - 1);4894t = a_exp + a_digits - 1;4895}4896else {4897/* Reduce the input operand to 0.500 < v <= 0.999. Let y = x + 100,4898* so 500 < y <= 999. Since y contains the most significant digits4899* of v, y/1000 <= v < (y+1)/1000 and abs(z - log(v)) < 10**-2. */4900v.exp = -a_digits;4901t = a_exp + a_digits;4902mpd_set_negative(z);4903}49044905mpd_maxcontext(&maxcontext);4906mpd_maxcontext(&varcontext);4907varcontext.round = MPD_ROUND_TRUNC;49084909maxprec = ctx->prec + 2;4910if (t == 0 && (x <= 15 || x >= 800)) {4911/* 0.900 <= v <= 1.15: Estimate the magnitude of the logarithm.4912* If ln(v) will underflow, skip the loop. Otherwise, adjust the4913* precision upwards in order to obtain a sufficient number of4914* significant digits.4915*4916* Case v > 1:4917* abs((v-1)/10) < abs((v-1)/v) < abs(ln(v)) < abs(v-1)4918* Case v < 1:4919* abs(v-1) < abs(ln(v)) < abs((v-1)/v) < abs((v-1)*10)4920*/4921int cmp = _mpd_cmp(&v, &one);49224923/* Upper bound (assume v > 1): abs(v-1), unrounded */4924_mpd_qsub(&tmp, &v, &one, &maxcontext, &maxcontext.status);4925if (maxcontext.status & MPD_Errors) {4926mpd_seterror(result, MPD_Malloc_error, status);4927goto finish;4928}49294930if (cmp < 0) {4931/* v < 1: abs((v-1)*10) */4932tmp.exp += 1;4933}4934if (mpd_adjexp(&tmp) < mpd_etiny(ctx)) {4935/* The upper bound is less than etiny: Underflow to zero */4936_settriple(result, (cmp<0), 1, mpd_etiny(ctx)-1);4937goto finish;4938}4939/* Lower bound: abs((v-1)/10) or abs(v-1) */4940tmp.exp -= 1;4941if (mpd_adjexp(&tmp) < 0) {4942/* Absolute error of the loop: abs(z - log(v)) < 10**-p. If4943* p = ctx->prec+2-adjexp(lower), then the relative error of4944* the result is (using 10**adjexp(x) <= abs(x)):4945*4946* abs(z - log(v)) / abs(log(v)) < 10**-p / abs(log(v))4947* <= 10**(-ctx->prec-2)4948*/4949maxprec = maxprec - mpd_adjexp(&tmp);4950}4951}49524953i = ln_schedule_prec(klist, maxprec, 2);4954for (; i >= 0; i--) {4955varcontext.prec = 2*klist[i]+3;4956z->flags ^= MPD_NEG;4957_mpd_qexp(&tmp, z, &varcontext, status);4958z->flags ^= MPD_NEG;49594960if (v.digits > varcontext.prec) {4961shift = v.digits - varcontext.prec;4962mpd_qshiftr(&vtmp, &v, shift, status);4963vtmp.exp += shift;4964mpd_qmul(&tmp, &vtmp, &tmp, &varcontext, status);4965}4966else {4967mpd_qmul(&tmp, &v, &tmp, &varcontext, status);4968}49694970mpd_qsub(&tmp, &tmp, &one, &maxcontext, status);4971mpd_qadd(z, z, &tmp, &maxcontext, status);4972if (mpd_isspecial(z)) {4973break;4974}4975}49764977/*4978* Case t == 0:4979* t * log(10) == 0, the result does not change and the analysis4980* above applies. If v < 0.900 or v > 1.15, the relative error is4981* less than 10**(-ctx.prec-1).4982* Case t != 0:4983* z := approx(log(v))4984* y := approx(log(10))4985* p := maxprec = ctx->prec + 24986* Absolute errors:4987* 1) abs(z - log(v)) < 10**-p4988* 2) abs(y - log(10)) < 10**-p4989* The multiplication is exact, so:4990* 3) abs(t*y - t*log(10)) < t*10**-p4991* The sum is exact, so:4992* 4) abs((z + t*y) - (log(v) + t*log(10))) < (abs(t) + 1) * 10**-p4993* Bounds for log(v) and log(10):4994* 5) -7/10 < log(v) < 17/104995* 6) 23/10 < log(10) < 24/104996* Using 4), 5), 6) and t != 0, the relative error is:4997*4998* 7) relerr < ((abs(t) + 1)*10**-p) / abs(log(v) + t*log(10))4999* < 0.5 * 10**(-p + 1) = 0.5 * 10**(-ctx->prec-1)5000*/5001mpd_qln10(&v, maxprec+1, status);5002mpd_qmul_ssize(&tmp, &v, t, &maxcontext, status);5003mpd_qadd(result, &tmp, z, &maxcontext, status);500450055006finish:5007*status |= (MPD_Inexact|MPD_Rounded);5008mpd_del(&v);5009mpd_del(&vtmp);5010mpd_del(&tmp);5011}50125013/* ln(a) */5014void5015mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,5016uint32_t *status)5017{5018mpd_context_t workctx;5019mpd_ssize_t adjexp, t;50205021if (mpd_isspecial(a)) {5022if (mpd_qcheck_nan(result, a, ctx, status)) {5023return;5024}5025if (mpd_isnegative(a)) {5026mpd_seterror(result, MPD_Invalid_operation, status);5027return;5028}5029mpd_setspecial(result, MPD_POS, MPD_INF);5030return;5031}5032if (mpd_iszerocoeff(a)) {5033mpd_setspecial(result, MPD_NEG, MPD_INF);5034return;5035}5036if (mpd_isnegative(a)) {5037mpd_seterror(result, MPD_Invalid_operation, status);5038return;5039}5040if (_mpd_cmp(a, &one) == 0) {5041_settriple(result, MPD_POS, 0, 0);5042return;5043}5044/*5045* Check if the result will overflow (0 < x, x != 1):5046* 1) log10(x) < 0 iff adjexp(x) < 05047* 2) 0 < x /\ x <= y ==> adjexp(x) <= adjexp(y)5048* 3) 0 < x /\ x != 1 ==> 2 * abs(log10(x)) < abs(log(x))5049* 4) adjexp(x) <= log10(x) < adjexp(x) + 15050*5051* Case adjexp(x) >= 0:5052* 5) 2 * adjexp(x) < abs(log(x))5053* Case adjexp(x) > 0:5054* 6) adjexp(2 * adjexp(x)) <= adjexp(abs(log(x)))5055* Case adjexp(x) == 0:5056* mpd_exp_digits(t)-1 == 0 <= emax (the shortcut is not triggered)5057*5058* Case adjexp(x) < 0:5059* 7) 2 * (-adjexp(x) - 1) < abs(log(x))5060* Case adjexp(x) < -1:5061* 8) adjexp(2 * (-adjexp(x) - 1)) <= adjexp(abs(log(x)))5062* Case adjexp(x) == -1:5063* mpd_exp_digits(t)-1 == 0 <= emax (the shortcut is not triggered)5064*/5065adjexp = mpd_adjexp(a);5066t = (adjexp < 0) ? -adjexp-1 : adjexp;5067t *= 2;5068if (mpd_exp_digits(t)-1 > ctx->emax) {5069*status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;5070mpd_setspecial(result, (adjexp<0), MPD_INF);5071return;5072}50735074workctx = *ctx;5075workctx.round = MPD_ROUND_HALF_EVEN;50765077if (ctx->allcr) {5078MPD_NEW_STATIC(t1, 0,0,0,0);5079MPD_NEW_STATIC(t2, 0,0,0,0);5080MPD_NEW_STATIC(ulp, 0,0,0,0);5081MPD_NEW_STATIC(aa, 0,0,0,0);5082mpd_ssize_t prec;50835084if (result == a) {5085if (!mpd_qcopy(&aa, a, status)) {5086mpd_seterror(result, MPD_Malloc_error, status);5087return;5088}5089a = &aa;5090}50915092workctx.clamp = 0;5093prec = ctx->prec + 3;5094while (1) {5095workctx.prec = prec;5096_mpd_qln(result, a, &workctx, status);5097_ssettriple(&ulp, MPD_POS, 1,5098result->exp + result->digits-workctx.prec);50995100workctx.prec = ctx->prec;5101mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status);5102mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status);5103if (mpd_isspecial(result) || mpd_iszerocoeff(result) ||5104mpd_qcmp(&t1, &t2, status) == 0) {5105workctx.clamp = ctx->clamp;5106mpd_check_underflow(result, &workctx, status);5107mpd_qfinalize(result, &workctx, status);5108break;5109}5110prec += MPD_RDIGITS;5111}5112mpd_del(&t1);5113mpd_del(&t2);5114mpd_del(&ulp);5115mpd_del(&aa);5116}5117else {5118_mpd_qln(result, a, &workctx, status);5119mpd_check_underflow(result, &workctx, status);5120mpd_qfinalize(result, &workctx, status);5121}5122}51235124/*5125* Internal log10() function that does not check for specials, zero or one.5126* Case SKIP_FINALIZE:5127* Relative error: abs(result - log10(a)) < 0.1 * 10**-prec * abs(log10(a))5128* Case DO_FINALIZE:5129* Ulp error: abs(result - log10(a)) < ulp(log10(a))5130*/5131enum {SKIP_FINALIZE, DO_FINALIZE};5132static void5133_mpd_qlog10(int action, mpd_t *result, const mpd_t *a,5134const mpd_context_t *ctx, uint32_t *status)5135{5136mpd_context_t workctx;5137MPD_NEW_STATIC(ln10,0,0,0,0);51385139mpd_maxcontext(&workctx);5140workctx.prec = ctx->prec + 3;5141/* relative error: 0.1 * 10**(-p-3). The specific underflow shortcut5142* in _mpd_qln() does not change the final result. */5143_mpd_qln(result, a, &workctx, status);5144/* relative error: 5 * 10**(-p-3) */5145mpd_qln10(&ln10, workctx.prec, status);51465147if (action == DO_FINALIZE) {5148workctx = *ctx;5149workctx.round = MPD_ROUND_HALF_EVEN;5150}5151/* SKIP_FINALIZE: relative error: 5 * 10**(-p-3) */5152_mpd_qdiv(NO_IDEAL_EXP, result, result, &ln10, &workctx, status);51535154mpd_del(&ln10);5155}51565157/* log10(a) */5158void5159mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,5160uint32_t *status)5161{5162mpd_context_t workctx;5163mpd_ssize_t adjexp, t;51645165workctx = *ctx;5166workctx.round = MPD_ROUND_HALF_EVEN;51675168if (mpd_isspecial(a)) {5169if (mpd_qcheck_nan(result, a, ctx, status)) {5170return;5171}5172if (mpd_isnegative(a)) {5173mpd_seterror(result, MPD_Invalid_operation, status);5174return;5175}5176mpd_setspecial(result, MPD_POS, MPD_INF);5177return;5178}5179if (mpd_iszerocoeff(a)) {5180mpd_setspecial(result, MPD_NEG, MPD_INF);5181return;5182}5183if (mpd_isnegative(a)) {5184mpd_seterror(result, MPD_Invalid_operation, status);5185return;5186}5187if (mpd_coeff_ispow10(a)) {5188uint8_t sign = 0;5189adjexp = mpd_adjexp(a);5190if (adjexp < 0) {5191sign = 1;5192adjexp = -adjexp;5193}5194_settriple(result, sign, adjexp, 0);5195mpd_qfinalize(result, &workctx, status);5196return;5197}5198/*5199* Check if the result will overflow (0 < x, x != 1):5200* 1) log10(x) < 0 iff adjexp(x) < 05201* 2) 0 < x /\ x <= y ==> adjexp(x) <= adjexp(y)5202* 3) adjexp(x) <= log10(x) < adjexp(x) + 15203*5204* Case adjexp(x) >= 0:5205* 4) adjexp(x) <= abs(log10(x))5206* Case adjexp(x) > 0:5207* 5) adjexp(adjexp(x)) <= adjexp(abs(log10(x)))5208* Case adjexp(x) == 0:5209* mpd_exp_digits(t)-1 == 0 <= emax (the shortcut is not triggered)5210*5211* Case adjexp(x) < 0:5212* 6) -adjexp(x) - 1 < abs(log10(x))5213* Case adjexp(x) < -1:5214* 7) adjexp(-adjexp(x) - 1) <= adjexp(abs(log(x)))5215* Case adjexp(x) == -1:5216* mpd_exp_digits(t)-1 == 0 <= emax (the shortcut is not triggered)5217*/5218adjexp = mpd_adjexp(a);5219t = (adjexp < 0) ? -adjexp-1 : adjexp;5220if (mpd_exp_digits(t)-1 > ctx->emax) {5221*status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;5222mpd_setspecial(result, (adjexp<0), MPD_INF);5223return;5224}52255226if (ctx->allcr) {5227MPD_NEW_STATIC(t1, 0,0,0,0);5228MPD_NEW_STATIC(t2, 0,0,0,0);5229MPD_NEW_STATIC(ulp, 0,0,0,0);5230MPD_NEW_STATIC(aa, 0,0,0,0);5231mpd_ssize_t prec;52325233if (result == a) {5234if (!mpd_qcopy(&aa, a, status)) {5235mpd_seterror(result, MPD_Malloc_error, status);5236return;5237}5238a = &aa;5239}52405241workctx.clamp = 0;5242prec = ctx->prec + 3;5243while (1) {5244workctx.prec = prec;5245_mpd_qlog10(SKIP_FINALIZE, result, a, &workctx, status);5246_ssettriple(&ulp, MPD_POS, 1,5247result->exp + result->digits-workctx.prec);52485249workctx.prec = ctx->prec;5250mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status);5251mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status);5252if (mpd_isspecial(result) || mpd_iszerocoeff(result) ||5253mpd_qcmp(&t1, &t2, status) == 0) {5254workctx.clamp = ctx->clamp;5255mpd_check_underflow(result, &workctx, status);5256mpd_qfinalize(result, &workctx, status);5257break;5258}5259prec += MPD_RDIGITS;5260}5261mpd_del(&t1);5262mpd_del(&t2);5263mpd_del(&ulp);5264mpd_del(&aa);5265}5266else {5267_mpd_qlog10(DO_FINALIZE, result, a, &workctx, status);5268mpd_check_underflow(result, &workctx, status);5269}5270}52715272/*5273* Maximum of the two operands. Attention: If one operand is a quiet NaN and the5274* other is numeric, the numeric operand is returned. This may not be what one5275* expects.5276*/5277void5278mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b,5279const mpd_context_t *ctx, uint32_t *status)5280{5281int c;52825283if (mpd_isqnan(a) && !mpd_isnan(b)) {5284mpd_qcopy(result, b, status);5285}5286else if (mpd_isqnan(b) && !mpd_isnan(a)) {5287mpd_qcopy(result, a, status);5288}5289else if (mpd_qcheck_nans(result, a, b, ctx, status)) {5290return;5291}5292else {5293c = _mpd_cmp(a, b);5294if (c == 0) {5295c = _mpd_cmp_numequal(a, b);5296}52975298if (c < 0) {5299mpd_qcopy(result, b, status);5300}5301else {5302mpd_qcopy(result, a, status);5303}5304}53055306mpd_qfinalize(result, ctx, status);5307}53085309/*5310* Maximum magnitude: Same as mpd_max(), but compares the operands with their5311* sign ignored.5312*/5313void5314mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b,5315const mpd_context_t *ctx, uint32_t *status)5316{5317int c;53185319if (mpd_isqnan(a) && !mpd_isnan(b)) {5320mpd_qcopy(result, b, status);5321}5322else if (mpd_isqnan(b) && !mpd_isnan(a)) {5323mpd_qcopy(result, a, status);5324}5325else if (mpd_qcheck_nans(result, a, b, ctx, status)) {5326return;5327}5328else {5329c = _mpd_cmp_abs(a, b);5330if (c == 0) {5331c = _mpd_cmp_numequal(a, b);5332}53335334if (c < 0) {5335mpd_qcopy(result, b, status);5336}5337else {5338mpd_qcopy(result, a, status);5339}5340}53415342mpd_qfinalize(result, ctx, status);5343}53445345/*5346* Minimum of the two operands. Attention: If one operand is a quiet NaN and the5347* other is numeric, the numeric operand is returned. This may not be what one5348* expects.5349*/5350void5351mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b,5352const mpd_context_t *ctx, uint32_t *status)5353{5354int c;53555356if (mpd_isqnan(a) && !mpd_isnan(b)) {5357mpd_qcopy(result, b, status);5358}5359else if (mpd_isqnan(b) && !mpd_isnan(a)) {5360mpd_qcopy(result, a, status);5361}5362else if (mpd_qcheck_nans(result, a, b, ctx, status)) {5363return;5364}5365else {5366c = _mpd_cmp(a, b);5367if (c == 0) {5368c = _mpd_cmp_numequal(a, b);5369}53705371if (c < 0) {5372mpd_qcopy(result, a, status);5373}5374else {5375mpd_qcopy(result, b, status);5376}5377}53785379mpd_qfinalize(result, ctx, status);5380}53815382/*5383* Minimum magnitude: Same as mpd_min(), but compares the operands with their5384* sign ignored.5385*/5386void5387mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b,5388const mpd_context_t *ctx, uint32_t *status)5389{5390int c;53915392if (mpd_isqnan(a) && !mpd_isnan(b)) {5393mpd_qcopy(result, b, status);5394}5395else if (mpd_isqnan(b) && !mpd_isnan(a)) {5396mpd_qcopy(result, a, status);5397}5398else if (mpd_qcheck_nans(result, a, b, ctx, status)) {5399return;5400}5401else {5402c = _mpd_cmp_abs(a, b);5403if (c == 0) {5404c = _mpd_cmp_numequal(a, b);5405}54065407if (c < 0) {5408mpd_qcopy(result, a, status);5409}5410else {5411mpd_qcopy(result, b, status);5412}5413}54145415mpd_qfinalize(result, ctx, status);5416}54175418/* Minimum space needed for the result array in _karatsuba_rec(). */5419static inline mpd_size_t5420_kmul_resultsize(mpd_size_t la, mpd_size_t lb)5421{5422mpd_size_t n, m;54235424n = add_size_t(la, lb);5425n = add_size_t(n, 1);54265427m = (la+1)/2 + 1;5428m = mul_size_t(m, 3);54295430return (m > n) ? m : n;5431}54325433/* Work space needed in _karatsuba_rec(). lim >= 4 */5434static inline mpd_size_t5435_kmul_worksize(mpd_size_t n, mpd_size_t lim)5436{5437mpd_size_t m;54385439if (n <= lim) {5440return 0;5441}54425443m = (n+1)/2 + 1;54445445return add_size_t(mul_size_t(m, 2), _kmul_worksize(m, lim));5446}544754485449#define MPD_KARATSUBA_BASECASE 16 /* must be >= 4 */54505451/*5452* Add the product of a and b to c.5453* c must be _kmul_resultsize(la, lb) in size.5454* w is used as a work array and must be _kmul_worksize(a, lim) in size.5455* Roman E. Maeder, Storage Allocation for the Karatsuba Integer Multiplication5456* Algorithm. In "Design and implementation of symbolic computation systems",5457* Springer, 1993, ISBN 354057235X, 9783540572350.5458*/5459static void5460_karatsuba_rec(mpd_uint_t *c, const mpd_uint_t *a, const mpd_uint_t *b,5461mpd_uint_t *w, mpd_size_t la, mpd_size_t lb)5462{5463mpd_size_t m, lt;54645465assert(la >= lb && lb > 0);5466assert(la <= MPD_KARATSUBA_BASECASE || w != NULL);54675468if (la <= MPD_KARATSUBA_BASECASE) {5469_mpd_basemul(c, a, b, la, lb);5470return;5471}54725473m = (la+1)/2; /* ceil(la/2) */54745475/* lb <= m < la */5476if (lb <= m) {54775478/* lb can now be larger than la-m */5479if (lb > la-m) {5480lt = lb + lb + 1; /* space needed for result array */5481mpd_uint_zero(w, lt); /* clear result array */5482_karatsuba_rec(w, b, a+m, w+lt, lb, la-m); /* b*ah */5483}5484else {5485lt = (la-m) + (la-m) + 1; /* space needed for result array */5486mpd_uint_zero(w, lt); /* clear result array */5487_karatsuba_rec(w, a+m, b, w+lt, la-m, lb); /* ah*b */5488}5489_mpd_baseaddto(c+m, w, (la-m)+lb); /* add ah*b*B**m */54905491lt = m + m + 1; /* space needed for the result array */5492mpd_uint_zero(w, lt); /* clear result array */5493_karatsuba_rec(w, a, b, w+lt, m, lb); /* al*b */5494_mpd_baseaddto(c, w, m+lb); /* add al*b */54955496return;5497}54985499/* la >= lb > m */5500memcpy(w, a, m * sizeof *w);5501w[m] = 0;5502_mpd_baseaddto(w, a+m, la-m);55035504memcpy(w+(m+1), b, m * sizeof *w);5505w[m+1+m] = 0;5506_mpd_baseaddto(w+(m+1), b+m, lb-m);55075508_karatsuba_rec(c+m, w, w+(m+1), w+2*(m+1), m+1, m+1);55095510lt = (la-m) + (la-m) + 1;5511mpd_uint_zero(w, lt);55125513_karatsuba_rec(w, a+m, b+m, w+lt, la-m, lb-m);55145515_mpd_baseaddto(c+2*m, w, (la-m) + (lb-m));5516_mpd_basesubfrom(c+m, w, (la-m) + (lb-m));55175518lt = m + m + 1;5519mpd_uint_zero(w, lt);55205521_karatsuba_rec(w, a, b, w+lt, m, m);5522_mpd_baseaddto(c, w, m+m);5523_mpd_basesubfrom(c+m, w, m+m);55245525return;5526}55275528/*5529* Multiply u and v, using Karatsuba multiplication. Returns a pointer5530* to the result or NULL in case of failure (malloc error).5531* Conditions: ulen >= vlen, ulen >= 45532*/5533static mpd_uint_t *5534_mpd_kmul(const mpd_uint_t *u, const mpd_uint_t *v,5535mpd_size_t ulen, mpd_size_t vlen,5536mpd_size_t *rsize)5537{5538mpd_uint_t *result = NULL, *w = NULL;5539mpd_size_t m;55405541assert(ulen >= 4);5542assert(ulen >= vlen);55435544*rsize = _kmul_resultsize(ulen, vlen);5545if ((result = mpd_calloc(*rsize, sizeof *result)) == NULL) {5546return NULL;5547}55485549m = _kmul_worksize(ulen, MPD_KARATSUBA_BASECASE);5550if (m && ((w = mpd_calloc(m, sizeof *w)) == NULL)) {5551mpd_free(result);5552return NULL;5553}55545555_karatsuba_rec(result, u, v, w, ulen, vlen);555655575558if (w) mpd_free(w);5559return result;5560}556155625563/*5564* Determine the minimum length for the number theoretic transform. Valid5565* transform lengths are 2**n or 3*2**n, where 2**n <= MPD_MAXTRANSFORM_2N.5566* The function finds the shortest length m such that rsize <= m.5567*/5568static inline mpd_size_t5569_mpd_get_transform_len(mpd_size_t rsize)5570{5571mpd_size_t log2rsize;5572mpd_size_t x, step;55735574assert(rsize >= 4);5575log2rsize = mpd_bsr(rsize);55765577if (rsize <= 1024) {5578/* 2**n is faster in this range. */5579x = ((mpd_size_t)1)<<log2rsize;5580return (rsize == x) ? x : x<<1;5581}5582else if (rsize <= MPD_MAXTRANSFORM_2N) {5583x = ((mpd_size_t)1)<<log2rsize;5584if (rsize == x) return x;5585step = x>>1;5586x += step;5587return (rsize <= x) ? x : x + step;5588}5589else if (rsize <= MPD_MAXTRANSFORM_2N+MPD_MAXTRANSFORM_2N/2) {5590return MPD_MAXTRANSFORM_2N+MPD_MAXTRANSFORM_2N/2;5591}5592else if (rsize <= 3*MPD_MAXTRANSFORM_2N) {5593return 3*MPD_MAXTRANSFORM_2N;5594}5595else {5596return MPD_SIZE_MAX;5597}5598}55995600#ifdef PPRO5601#ifndef _MSC_VER5602static inline unsigned short5603_mpd_get_control87(void)5604{5605unsigned short cw;56065607__asm__ __volatile__ ("fnstcw %0" : "=m" (cw));5608return cw;5609}56105611static inline void5612_mpd_set_control87(unsigned short cw)5613{5614__asm__ __volatile__ ("fldcw %0" : : "m" (cw));5615}5616#endif56175618static unsigned int5619mpd_set_fenv(void)5620{5621unsigned int cw;5622#ifdef _MSC_VER5623unsigned int flags =5624_EM_INVALID|_EM_DENORMAL|_EM_ZERODIVIDE|_EM_OVERFLOW|5625_EM_UNDERFLOW|_EM_INEXACT|_RC_CHOP|_PC_64;5626unsigned int mask = _MCW_EM|_MCW_RC|_MCW_PC;5627unsigned int dummy;56285629__control87_2(0, 0, &cw, NULL);5630__control87_2(flags, mask, &dummy, NULL);5631#else5632cw = _mpd_get_control87();5633_mpd_set_control87(cw|0xF3F);5634#endif5635return cw;5636}56375638static void5639mpd_restore_fenv(unsigned int cw)5640{5641#ifdef _MSC_VER5642unsigned int mask = _MCW_EM|_MCW_RC|_MCW_PC;5643unsigned int dummy;56445645__control87_2(cw, mask, &dummy, NULL);5646#else5647_mpd_set_control87((unsigned short)cw);5648#endif5649}5650#endif /* PPRO */56515652/*5653* Multiply u and v, using the fast number theoretic transform. Returns5654* a pointer to the result or NULL in case of failure (malloc error).5655*/5656static mpd_uint_t *5657_mpd_fntmul(const mpd_uint_t *u, const mpd_uint_t *v,5658mpd_size_t ulen, mpd_size_t vlen,5659mpd_size_t *rsize)5660{5661mpd_uint_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *vtmp = NULL;5662mpd_size_t n;56635664#ifdef PPRO5665unsigned int cw;5666cw = mpd_set_fenv();5667#endif56685669*rsize = add_size_t(ulen, vlen);5670if ((n = _mpd_get_transform_len(*rsize)) == MPD_SIZE_MAX) {5671goto malloc_error;5672}56735674if ((c1 = mpd_calloc(n, sizeof *c1)) == NULL) {5675goto malloc_error;5676}5677if ((c2 = mpd_calloc(n, sizeof *c2)) == NULL) {5678goto malloc_error;5679}5680if ((c3 = mpd_calloc(n, sizeof *c3)) == NULL) {5681goto malloc_error;5682}56835684memcpy(c1, u, ulen * (sizeof *c1));5685memcpy(c2, u, ulen * (sizeof *c2));5686memcpy(c3, u, ulen * (sizeof *c3));56875688if (u == v) {5689if (!fnt_autoconvolute(c1, n, P1) ||5690!fnt_autoconvolute(c2, n, P2) ||5691!fnt_autoconvolute(c3, n, P3)) {5692goto malloc_error;5693}5694}5695else {5696if ((vtmp = mpd_calloc(n, sizeof *vtmp)) == NULL) {5697goto malloc_error;5698}56995700memcpy(vtmp, v, vlen * (sizeof *vtmp));5701if (!fnt_convolute(c1, vtmp, n, P1)) {5702mpd_free(vtmp);5703goto malloc_error;5704}57055706memcpy(vtmp, v, vlen * (sizeof *vtmp));5707mpd_uint_zero(vtmp+vlen, n-vlen);5708if (!fnt_convolute(c2, vtmp, n, P2)) {5709mpd_free(vtmp);5710goto malloc_error;5711}57125713memcpy(vtmp, v, vlen * (sizeof *vtmp));5714mpd_uint_zero(vtmp+vlen, n-vlen);5715if (!fnt_convolute(c3, vtmp, n, P3)) {5716mpd_free(vtmp);5717goto malloc_error;5718}57195720mpd_free(vtmp);5721}57225723crt3(c1, c2, c3, *rsize);57245725out:5726#ifdef PPRO5727mpd_restore_fenv(cw);5728#endif5729if (c2) mpd_free(c2);5730if (c3) mpd_free(c3);5731return c1;57325733malloc_error:5734if (c1) mpd_free(c1);5735c1 = NULL;5736goto out;5737}573857395740/*5741* Karatsuba multiplication with FNT/basemul as the base case.5742*/5743static int5744_karatsuba_rec_fnt(mpd_uint_t *c, const mpd_uint_t *a, const mpd_uint_t *b,5745mpd_uint_t *w, mpd_size_t la, mpd_size_t lb)5746{5747mpd_size_t m, lt;57485749assert(la >= lb && lb > 0);5750assert(la <= 3*(MPD_MAXTRANSFORM_2N/2) || w != NULL);57515752if (la <= 3*(MPD_MAXTRANSFORM_2N/2)) {57535754if (lb <= 192) {5755_mpd_basemul(c, b, a, lb, la);5756}5757else {5758mpd_uint_t *result;5759mpd_size_t dummy;57605761if ((result = _mpd_fntmul(a, b, la, lb, &dummy)) == NULL) {5762return 0;5763}5764memcpy(c, result, (la+lb) * (sizeof *result));5765mpd_free(result);5766}5767return 1;5768}57695770m = (la+1)/2; /* ceil(la/2) */57715772/* lb <= m < la */5773if (lb <= m) {57745775/* lb can now be larger than la-m */5776if (lb > la-m) {5777lt = lb + lb + 1; /* space needed for result array */5778mpd_uint_zero(w, lt); /* clear result array */5779if (!_karatsuba_rec_fnt(w, b, a+m, w+lt, lb, la-m)) { /* b*ah */5780return 0; /* GCOV_UNLIKELY */5781}5782}5783else {5784lt = (la-m) + (la-m) + 1; /* space needed for result array */5785mpd_uint_zero(w, lt); /* clear result array */5786if (!_karatsuba_rec_fnt(w, a+m, b, w+lt, la-m, lb)) { /* ah*b */5787return 0; /* GCOV_UNLIKELY */5788}5789}5790_mpd_baseaddto(c+m, w, (la-m)+lb); /* add ah*b*B**m */57915792lt = m + m + 1; /* space needed for the result array */5793mpd_uint_zero(w, lt); /* clear result array */5794if (!_karatsuba_rec_fnt(w, a, b, w+lt, m, lb)) { /* al*b */5795return 0; /* GCOV_UNLIKELY */5796}5797_mpd_baseaddto(c, w, m+lb); /* add al*b */57985799return 1;5800}58015802/* la >= lb > m */5803memcpy(w, a, m * sizeof *w);5804w[m] = 0;5805_mpd_baseaddto(w, a+m, la-m);58065807memcpy(w+(m+1), b, m * sizeof *w);5808w[m+1+m] = 0;5809_mpd_baseaddto(w+(m+1), b+m, lb-m);58105811if (!_karatsuba_rec_fnt(c+m, w, w+(m+1), w+2*(m+1), m+1, m+1)) {5812return 0; /* GCOV_UNLIKELY */5813}58145815lt = (la-m) + (la-m) + 1;5816mpd_uint_zero(w, lt);58175818if (!_karatsuba_rec_fnt(w, a+m, b+m, w+lt, la-m, lb-m)) {5819return 0; /* GCOV_UNLIKELY */5820}58215822_mpd_baseaddto(c+2*m, w, (la-m) + (lb-m));5823_mpd_basesubfrom(c+m, w, (la-m) + (lb-m));58245825lt = m + m + 1;5826mpd_uint_zero(w, lt);58275828if (!_karatsuba_rec_fnt(w, a, b, w+lt, m, m)) {5829return 0; /* GCOV_UNLIKELY */5830}5831_mpd_baseaddto(c, w, m+m);5832_mpd_basesubfrom(c+m, w, m+m);58335834return 1;5835}58365837/*5838* Multiply u and v, using Karatsuba multiplication with the FNT as the5839* base case. Returns a pointer to the result or NULL in case of failure5840* (malloc error). Conditions: ulen >= vlen, ulen >= 4.5841*/5842static mpd_uint_t *5843_mpd_kmul_fnt(const mpd_uint_t *u, const mpd_uint_t *v,5844mpd_size_t ulen, mpd_size_t vlen,5845mpd_size_t *rsize)5846{5847mpd_uint_t *result = NULL, *w = NULL;5848mpd_size_t m;58495850assert(ulen >= 4);5851assert(ulen >= vlen);58525853*rsize = _kmul_resultsize(ulen, vlen);5854if ((result = mpd_calloc(*rsize, sizeof *result)) == NULL) {5855return NULL;5856}58575858m = _kmul_worksize(ulen, 3*(MPD_MAXTRANSFORM_2N/2));5859if (m && ((w = mpd_calloc(m, sizeof *w)) == NULL)) {5860mpd_free(result); /* GCOV_UNLIKELY */5861return NULL; /* GCOV_UNLIKELY */5862}58635864if (!_karatsuba_rec_fnt(result, u, v, w, ulen, vlen)) {5865mpd_free(result);5866result = NULL;5867}586858695870if (w) mpd_free(w);5871return result;5872}587358745875/* Deal with the special cases of multiplying infinities. */5876static void5877_mpd_qmul_inf(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status)5878{5879if (mpd_isinfinite(a)) {5880if (mpd_iszero(b)) {5881mpd_seterror(result, MPD_Invalid_operation, status);5882}5883else {5884mpd_setspecial(result, mpd_sign(a)^mpd_sign(b), MPD_INF);5885}5886return;5887}5888assert(mpd_isinfinite(b));5889if (mpd_iszero(a)) {5890mpd_seterror(result, MPD_Invalid_operation, status);5891}5892else {5893mpd_setspecial(result, mpd_sign(a)^mpd_sign(b), MPD_INF);5894}5895}58965897/*5898* Internal function: Multiply a and b. _mpd_qmul deals with specials but5899* does NOT finalize the result. This is for use in mpd_fma().5900*/5901static inline void5902_mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,5903const mpd_context_t *ctx, uint32_t *status)5904{5905const mpd_t *big = a, *small = b;5906mpd_uint_t *rdata = NULL;5907mpd_uint_t rbuf[MPD_MINALLOC_MAX];5908mpd_size_t rsize, i;590959105911if (mpd_isspecial(a) || mpd_isspecial(b)) {5912if (mpd_qcheck_nans(result, a, b, ctx, status)) {5913return;5914}5915_mpd_qmul_inf(result, a, b, status);5916return;5917}59185919if (small->len > big->len) {5920_mpd_ptrswap(&big, &small);5921}59225923rsize = big->len + small->len;59245925if (big->len == 1) {5926_mpd_singlemul(result->data, big->data[0], small->data[0]);5927goto finish;5928}5929if (rsize <= (mpd_size_t)MPD_MINALLOC_MAX) {5930if (big->len == 2) {5931_mpd_mul_2_le2(rbuf, big->data, small->data, small->len);5932}5933else {5934mpd_uint_zero(rbuf, rsize);5935if (small->len == 1) {5936_mpd_shortmul(rbuf, big->data, big->len, small->data[0]);5937}5938else {5939_mpd_basemul(rbuf, small->data, big->data, small->len, big->len);5940}5941}5942if (!mpd_qresize(result, rsize, status)) {5943return;5944}5945for(i = 0; i < rsize; i++) {5946result->data[i] = rbuf[i];5947}5948goto finish;5949}595059515952if (small->len <= 256) {5953rdata = mpd_calloc(rsize, sizeof *rdata);5954if (rdata != NULL) {5955if (small->len == 1) {5956_mpd_shortmul(rdata, big->data, big->len, small->data[0]);5957}5958else {5959_mpd_basemul(rdata, small->data, big->data, small->len, big->len);5960}5961}5962}5963else if (rsize <= 1024) {5964rdata = _mpd_kmul(big->data, small->data, big->len, small->len, &rsize);5965}5966else if (rsize <= 3*MPD_MAXTRANSFORM_2N) {5967rdata = _mpd_fntmul(big->data, small->data, big->len, small->len, &rsize);5968}5969else {5970rdata = _mpd_kmul_fnt(big->data, small->data, big->len, small->len, &rsize);5971}59725973if (rdata == NULL) {5974mpd_seterror(result, MPD_Malloc_error, status);5975return;5976}59775978if (mpd_isdynamic_data(result)) {5979mpd_free(result->data);5980}5981result->data = rdata;5982result->alloc = rsize;5983mpd_set_dynamic_data(result);598459855986finish:5987mpd_set_flags(result, mpd_sign(a)^mpd_sign(b));5988result->exp = big->exp + small->exp;5989result->len = _mpd_real_size(result->data, rsize);5990/* resize to smaller cannot fail */5991mpd_qresize(result, result->len, status);5992mpd_setdigits(result);5993}59945995/* Multiply a and b. */5996void5997mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,5998const mpd_context_t *ctx, uint32_t *status)5999{6000_mpd_qmul(result, a, b, ctx, status);6001mpd_qfinalize(result, ctx, status);6002}60036004/* Multiply a and b. Set NaN/Invalid_operation if the result is inexact. */6005static void6006_mpd_qmul_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,6007const mpd_context_t *ctx, uint32_t *status)6008{6009uint32_t workstatus = 0;60106011mpd_qmul(result, a, b, ctx, &workstatus);6012*status |= workstatus;6013if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {6014mpd_seterror(result, MPD_Invalid_operation, status);6015}6016}60176018/* Multiply decimal and mpd_ssize_t. */6019void6020mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,6021const mpd_context_t *ctx, uint32_t *status)6022{6023mpd_context_t maxcontext;6024MPD_NEW_STATIC(bb,0,0,0,0);60256026mpd_maxcontext(&maxcontext);6027mpd_qsset_ssize(&bb, b, &maxcontext, status);6028mpd_qmul(result, a, &bb, ctx, status);6029mpd_del(&bb);6030}60316032/* Multiply decimal and mpd_uint_t. */6033void6034mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,6035const mpd_context_t *ctx, uint32_t *status)6036{6037mpd_context_t maxcontext;6038MPD_NEW_STATIC(bb,0,0,0,0);60396040mpd_maxcontext(&maxcontext);6041mpd_qsset_uint(&bb, b, &maxcontext, status);6042mpd_qmul(result, a, &bb, ctx, status);6043mpd_del(&bb);6044}60456046void6047mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b,6048const mpd_context_t *ctx, uint32_t *status)6049{6050mpd_qmul_ssize(result, a, b, ctx, status);6051}60526053void6054mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b,6055const mpd_context_t *ctx, uint32_t *status)6056{6057mpd_qmul_uint(result, a, b, ctx, status);6058}60596060#ifdef CONFIG_646061void6062mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b,6063const mpd_context_t *ctx, uint32_t *status)6064{6065mpd_qmul_ssize(result, a, b, ctx, status);6066}60676068void6069mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,6070const mpd_context_t *ctx, uint32_t *status)6071{6072mpd_qmul_uint(result, a, b, ctx, status);6073}6074#elif !defined(LEGACY_COMPILER)6075/* Multiply decimal and int64_t. */6076void6077mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b,6078const mpd_context_t *ctx, uint32_t *status)6079{6080mpd_context_t maxcontext;6081MPD_NEW_STATIC(bb,0,0,0,0);60826083mpd_maxcontext(&maxcontext);6084mpd_qset_i64(&bb, b, &maxcontext, status);6085mpd_qmul(result, a, &bb, ctx, status);6086mpd_del(&bb);6087}60886089/* Multiply decimal and uint64_t. */6090void6091mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,6092const mpd_context_t *ctx, uint32_t *status)6093{6094mpd_context_t maxcontext;6095MPD_NEW_STATIC(bb,0,0,0,0);60966097mpd_maxcontext(&maxcontext);6098mpd_qset_u64(&bb, b, &maxcontext, status);6099mpd_qmul(result, a, &bb, ctx, status);6100mpd_del(&bb);6101}6102#endif61036104/* Like the minus operator. */6105void6106mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,6107uint32_t *status)6108{6109if (mpd_isspecial(a)) {6110if (mpd_qcheck_nan(result, a, ctx, status)) {6111return;6112}6113}61146115if (mpd_iszero(a) && ctx->round != MPD_ROUND_FLOOR) {6116mpd_qcopy_abs(result, a, status);6117}6118else {6119mpd_qcopy_negate(result, a, status);6120}61216122mpd_qfinalize(result, ctx, status);6123}61246125/* Like the plus operator. */6126void6127mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,6128uint32_t *status)6129{6130if (mpd_isspecial(a)) {6131if (mpd_qcheck_nan(result, a, ctx, status)) {6132return;6133}6134}61356136if (mpd_iszero(a) && ctx->round != MPD_ROUND_FLOOR) {6137mpd_qcopy_abs(result, a, status);6138}6139else {6140mpd_qcopy(result, a, status);6141}61426143mpd_qfinalize(result, ctx, status);6144}61456146/* The largest representable number that is smaller than the operand. */6147void6148mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,6149uint32_t *status)6150{6151mpd_context_t workctx;6152MPD_NEW_CONST(tiny,MPD_POS,mpd_etiny(ctx)-1,1,1,1,1);61536154if (mpd_isspecial(a)) {6155if (mpd_qcheck_nan(result, a, ctx, status)) {6156return;6157}61586159assert(mpd_isinfinite(a));6160if (mpd_isnegative(a)) {6161mpd_qcopy(result, a, status);6162return;6163}6164else {6165mpd_clear_flags(result);6166mpd_qmaxcoeff(result, ctx, status);6167if (mpd_isnan(result)) {6168return;6169}6170result->exp = mpd_etop(ctx);6171return;6172}6173}61746175mpd_workcontext(&workctx, ctx);6176workctx.round = MPD_ROUND_FLOOR;61776178if (!mpd_qcopy(result, a, status)) {6179return;6180}61816182mpd_qfinalize(result, &workctx, &workctx.status);6183if (workctx.status&(MPD_Inexact|MPD_Errors)) {6184*status |= (workctx.status&MPD_Errors);6185return;6186}61876188workctx.status = 0;6189mpd_qsub(result, a, &tiny, &workctx, &workctx.status);6190*status |= (workctx.status&MPD_Errors);6191}61926193/* The smallest representable number that is larger than the operand. */6194void6195mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,6196uint32_t *status)6197{6198mpd_context_t workctx;6199MPD_NEW_CONST(tiny,MPD_POS,mpd_etiny(ctx)-1,1,1,1,1);62006201if (mpd_isspecial(a)) {6202if (mpd_qcheck_nan(result, a, ctx, status)) {6203return;6204}62056206assert(mpd_isinfinite(a));6207if (mpd_ispositive(a)) {6208mpd_qcopy(result, a, status);6209}6210else {6211mpd_clear_flags(result);6212mpd_qmaxcoeff(result, ctx, status);6213if (mpd_isnan(result)) {6214return;6215}6216mpd_set_flags(result, MPD_NEG);6217result->exp = mpd_etop(ctx);6218}6219return;6220}62216222mpd_workcontext(&workctx, ctx);6223workctx.round = MPD_ROUND_CEILING;62246225if (!mpd_qcopy(result, a, status)) {6226return;6227}62286229mpd_qfinalize(result, &workctx, &workctx.status);6230if (workctx.status & (MPD_Inexact|MPD_Errors)) {6231*status |= (workctx.status&MPD_Errors);6232return;6233}62346235workctx.status = 0;6236mpd_qadd(result, a, &tiny, &workctx, &workctx.status);6237*status |= (workctx.status&MPD_Errors);6238}62396240/*6241* The number closest to the first operand that is in the direction towards6242* the second operand.6243*/6244void6245mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b,6246const mpd_context_t *ctx, uint32_t *status)6247{6248int c;62496250if (mpd_qcheck_nans(result, a, b, ctx, status)) {6251return;6252}62536254c = _mpd_cmp(a, b);6255if (c == 0) {6256mpd_qcopy_sign(result, a, b, status);6257return;6258}62596260if (c < 0) {6261mpd_qnext_plus(result, a, ctx, status);6262}6263else {6264mpd_qnext_minus(result, a, ctx, status);6265}62666267if (mpd_isinfinite(result)) {6268*status |= (MPD_Overflow|MPD_Rounded|MPD_Inexact);6269}6270else if (mpd_adjexp(result) < ctx->emin) {6271*status |= (MPD_Underflow|MPD_Subnormal|MPD_Rounded|MPD_Inexact);6272if (mpd_iszero(result)) {6273*status |= MPD_Clamped;6274}6275}6276}62776278/*6279* Internal function: Integer power with mpd_uint_t exponent. The function6280* can fail with MPD_Malloc_error.6281*6282* The error is equal to the error incurred in k-1 multiplications. Assuming6283* the upper bound for the relative error in each operation:6284*6285* abs(err) = 5 * 10**-prec6286* result = x**k * (1 + err)**(k-1)6287*/6288static inline void6289_mpd_qpow_uint(mpd_t *result, const mpd_t *base, mpd_uint_t exp,6290uint8_t resultsign, const mpd_context_t *ctx, uint32_t *status)6291{6292uint32_t workstatus = 0;6293mpd_uint_t n;62946295if (exp == 0) {6296_settriple(result, resultsign, 1, 0); /* GCOV_NOT_REACHED */6297return; /* GCOV_NOT_REACHED */6298}62996300if (!mpd_qcopy(result, base, status)) {6301return;6302}63036304n = mpd_bits[mpd_bsr(exp)];6305while (n >>= 1) {6306mpd_qmul(result, result, result, ctx, &workstatus);6307if (exp & n) {6308mpd_qmul(result, result, base, ctx, &workstatus);6309}6310if (mpd_isspecial(result) ||6311(mpd_iszerocoeff(result) && (workstatus & MPD_Clamped))) {6312break;6313}6314}63156316*status |= workstatus;6317mpd_set_sign(result, resultsign);6318}63196320/*6321* Internal function: Integer power with mpd_t exponent, tbase and texp6322* are modified!! Function can fail with MPD_Malloc_error.6323*6324* The error is equal to the error incurred in k multiplications. Assuming6325* the upper bound for the relative error in each operation:6326*6327* abs(err) = 5 * 10**-prec6328* result = x**k * (1 + err)**k6329*/6330static inline void6331_mpd_qpow_mpd(mpd_t *result, mpd_t *tbase, mpd_t *texp, uint8_t resultsign,6332const mpd_context_t *ctx, uint32_t *status)6333{6334uint32_t workstatus = 0;6335mpd_context_t maxctx;6336MPD_NEW_CONST(two,0,0,1,1,1,2);633763386339mpd_maxcontext(&maxctx);63406341/* resize to smaller cannot fail */6342mpd_qcopy(result, &one, status);63436344while (!mpd_iszero(texp)) {6345if (mpd_isodd(texp)) {6346mpd_qmul(result, result, tbase, ctx, &workstatus);6347*status |= workstatus;6348if (mpd_isspecial(result) ||6349(mpd_iszerocoeff(result) && (workstatus & MPD_Clamped))) {6350break;6351}6352}6353mpd_qmul(tbase, tbase, tbase, ctx, &workstatus);6354mpd_qdivint(texp, texp, &two, &maxctx, &workstatus);6355if (mpd_isnan(tbase) || mpd_isnan(texp)) {6356mpd_seterror(result, workstatus&MPD_Errors, status);6357return;6358}6359}6360mpd_set_sign(result, resultsign);6361}63626363/*6364* The power function for integer exponents. Relative error _before_ the6365* final rounding to prec:6366* abs(result - base**exp) < 0.1 * 10**-prec * abs(base**exp)6367*/6368static void6369_mpd_qpow_int(mpd_t *result, const mpd_t *base, const mpd_t *exp,6370uint8_t resultsign,6371const mpd_context_t *ctx, uint32_t *status)6372{6373mpd_context_t workctx;6374MPD_NEW_STATIC(tbase,0,0,0,0);6375MPD_NEW_STATIC(texp,0,0,0,0);6376mpd_uint_t n;637763786379mpd_workcontext(&workctx, ctx);6380workctx.prec += (exp->digits + exp->exp + 2);6381workctx.round = MPD_ROUND_HALF_EVEN;6382workctx.clamp = 0;6383if (mpd_isnegative(exp)) {6384uint32_t workstatus = 0;6385workctx.prec += 1;6386mpd_qdiv(&tbase, &one, base, &workctx, &workstatus);6387*status |= workstatus;6388if (workstatus&MPD_Errors) {6389mpd_setspecial(result, MPD_POS, MPD_NAN);6390goto finish;6391}6392}6393else {6394if (!mpd_qcopy(&tbase, base, status)) {6395mpd_setspecial(result, MPD_POS, MPD_NAN);6396goto finish;6397}6398}63996400n = mpd_qabs_uint(exp, &workctx.status);6401if (workctx.status&MPD_Invalid_operation) {6402if (!mpd_qcopy(&texp, exp, status)) {6403mpd_setspecial(result, MPD_POS, MPD_NAN); /* GCOV_UNLIKELY */6404goto finish; /* GCOV_UNLIKELY */6405}6406_mpd_qpow_mpd(result, &tbase, &texp, resultsign, &workctx, status);6407}6408else {6409_mpd_qpow_uint(result, &tbase, n, resultsign, &workctx, status);6410}64116412if (mpd_isinfinite(result)) {6413/* for ROUND_DOWN, ROUND_FLOOR, etc. */6414_settriple(result, resultsign, 1, MPD_EXP_INF);6415}64166417finish:6418mpd_del(&tbase);6419mpd_del(&texp);6420mpd_qfinalize(result, ctx, status);6421}64226423/*6424* If the exponent is infinite and base equals one, the result is one6425* with a coefficient of length prec. Otherwise, result is undefined.6426* Return the value of the comparison against one.6427*/6428static int6429_qcheck_pow_one_inf(mpd_t *result, const mpd_t *base, uint8_t resultsign,6430const mpd_context_t *ctx, uint32_t *status)6431{6432mpd_ssize_t shift;6433int cmp;64346435if ((cmp = _mpd_cmp(base, &one)) == 0) {6436shift = ctx->prec-1;6437mpd_qshiftl(result, &one, shift, status);6438result->exp = -shift;6439mpd_set_flags(result, resultsign);6440*status |= (MPD_Inexact|MPD_Rounded);6441}64426443return cmp;6444}64456446/*6447* If abs(base) equals one, calculate the correct power of one result.6448* Otherwise, result is undefined. Return the value of the comparison6449* against 1.6450*6451* This is an internal function that does not check for specials.6452*/6453static int6454_qcheck_pow_one(mpd_t *result, const mpd_t *base, const mpd_t *exp,6455uint8_t resultsign,6456const mpd_context_t *ctx, uint32_t *status)6457{6458uint32_t workstatus = 0;6459mpd_ssize_t shift;6460int cmp;64616462if ((cmp = _mpd_cmp_abs(base, &one)) == 0) {6463if (_mpd_isint(exp)) {6464if (mpd_isnegative(exp)) {6465_settriple(result, resultsign, 1, 0);6466return 0;6467}6468/* 1.000**3 = 1.000000000 */6469mpd_qmul_ssize(result, exp, -base->exp, ctx, &workstatus);6470if (workstatus&MPD_Errors) {6471*status |= (workstatus&MPD_Errors);6472return 0;6473}6474/* digits-1 after exponentiation */6475shift = mpd_qget_ssize(result, &workstatus);6476/* shift is MPD_SSIZE_MAX if result is too large */6477if (shift > ctx->prec-1) {6478shift = ctx->prec-1;6479*status |= MPD_Rounded;6480}6481}6482else if (mpd_ispositive(base)) {6483shift = ctx->prec-1;6484*status |= (MPD_Inexact|MPD_Rounded);6485}6486else {6487return -2; /* GCOV_NOT_REACHED */6488}6489if (!mpd_qshiftl(result, &one, shift, status)) {6490return 0;6491}6492result->exp = -shift;6493mpd_set_flags(result, resultsign);6494}64956496return cmp;6497}64986499/*6500* Detect certain over/underflow of x**y.6501* ACL2 proof: pow-bounds.lisp.6502*6503* Symbols:6504*6505* e: EXP_INF or EXP_CLAMP6506* x: base6507* y: exponent6508*6509* omega(e) = log10(abs(e))6510* zeta(x) = log10(abs(log10(x)))6511* theta(y) = log10(abs(y))6512*6513* Upper and lower bounds:6514*6515* ub_omega(e) = ceil(log10(abs(e)))6516* lb_theta(y) = floor(log10(abs(y)))6517*6518* | floor(log10(floor(abs(log10(x))))) if x < 1/10 or x >= 106519* lb_zeta(x) = | floor(log10(abs(x-1)/10)) if 1/10 <= x < 16520* | floor(log10(abs((x-1)/100))) if 1 < x < 106521*6522* ub_omega(e) and lb_theta(y) are obviously upper and lower bounds6523* for omega(e) and theta(y).6524*6525* lb_zeta is a lower bound for zeta(x):6526*6527* x < 1/10 or x >= 10:6528*6529* abs(log10(x)) >= 1, so the outer log10 is well defined. Since log106530* is strictly increasing, the end result is a lower bound.6531*6532* 1/10 <= x < 1:6533*6534* We use: log10(x) <= (x-1)/log(10)6535* abs(log10(x)) >= abs(x-1)/log(10)6536* abs(log10(x)) >= abs(x-1)/106537*6538* 1 < x < 10:6539*6540* We use: (x-1)/(x*log(10)) < log10(x)6541* abs((x-1)/100) < abs(log10(x))6542*6543* XXX: abs((x-1)/10) would work, need ACL2 proof.6544*6545*6546* Let (0 < x < 1 and y < 0) or (x > 1 and y > 0). (H1)6547* Let ub_omega(exp_inf) < lb_zeta(x) + lb_theta(y) (H2)6548*6549* Then:6550* log10(abs(exp_inf)) < log10(abs(log10(x))) + log10(abs(y)). (1)6551* exp_inf < log10(x) * y (2)6552* 10**exp_inf < x**y (3)6553*6554* Let (0 < x < 1 and y > 0) or (x > 1 and y < 0). (H3)6555* Let ub_omega(exp_clamp) < lb_zeta(x) + lb_theta(y) (H4)6556*6557* Then:6558* log10(abs(exp_clamp)) < log10(abs(log10(x))) + log10(abs(y)). (4)6559* log10(x) * y < exp_clamp (5)6560* x**y < 10**exp_clamp (6)6561*6562*/6563static mpd_ssize_t6564_lower_bound_zeta(const mpd_t *x, uint32_t *status)6565{6566mpd_context_t maxctx;6567MPD_NEW_STATIC(scratch,0,0,0,0);6568mpd_ssize_t t, u;65696570t = mpd_adjexp(x);6571if (t > 0) {6572/* x >= 10 -> floor(log10(floor(abs(log10(x))))) */6573return mpd_exp_digits(t) - 1;6574}6575else if (t < -1) {6576/* x < 1/10 -> floor(log10(floor(abs(log10(x))))) */6577return mpd_exp_digits(t+1) - 1;6578}6579else {6580mpd_maxcontext(&maxctx);6581mpd_qsub(&scratch, x, &one, &maxctx, status);6582if (mpd_isspecial(&scratch)) {6583mpd_del(&scratch);6584return MPD_SSIZE_MAX;6585}6586u = mpd_adjexp(&scratch);6587mpd_del(&scratch);65886589/* t == -1, 1/10 <= x < 1 -> floor(log10(abs(x-1)/10))6590* t == 0, 1 < x < 10 -> floor(log10(abs(x-1)/100)) */6591return (t == 0) ? u-2 : u-1;6592}6593}65946595/*6596* Detect cases of certain overflow/underflow in the power function.6597* Assumptions: x != 1, y != 0. The proof above is for positive x.6598* If x is negative and y is an odd integer, x**y == -(abs(x)**y),6599* so the analysis does not change.6600*/6601static int6602_qcheck_pow_bounds(mpd_t *result, const mpd_t *x, const mpd_t *y,6603uint8_t resultsign,6604const mpd_context_t *ctx, uint32_t *status)6605{6606MPD_NEW_SHARED(abs_x, x);6607mpd_ssize_t ub_omega, lb_zeta, lb_theta;6608uint8_t sign;66096610mpd_set_positive(&abs_x);66116612lb_theta = mpd_adjexp(y);6613lb_zeta = _lower_bound_zeta(&abs_x, status);6614if (lb_zeta == MPD_SSIZE_MAX) {6615mpd_seterror(result, MPD_Malloc_error, status);6616return 1;6617}66186619sign = (mpd_adjexp(&abs_x) < 0) ^ mpd_sign(y);6620if (sign == 0) {6621/* (0 < |x| < 1 and y < 0) or (|x| > 1 and y > 0) */6622ub_omega = mpd_exp_digits(ctx->emax);6623if (ub_omega < lb_zeta + lb_theta) {6624_settriple(result, resultsign, 1, MPD_EXP_INF);6625mpd_qfinalize(result, ctx, status);6626return 1;6627}6628}6629else {6630/* (0 < |x| < 1 and y > 0) or (|x| > 1 and y < 0). */6631ub_omega = mpd_exp_digits(mpd_etiny(ctx));6632if (ub_omega < lb_zeta + lb_theta) {6633_settriple(result, resultsign, 1, mpd_etiny(ctx)-1);6634mpd_qfinalize(result, ctx, status);6635return 1;6636}6637}66386639return 0;6640}66416642/*6643* TODO: Implement algorithm for computing exact powers from decimal.py.6644* In order to prevent infinite loops, this has to be called before6645* using Ziv's strategy for correct rounding.6646*/6647/*6648static int6649_mpd_qpow_exact(mpd_t *result, const mpd_t *base, const mpd_t *exp,6650const mpd_context_t *ctx, uint32_t *status)6651{6652return 0;6653}6654*/66556656/*6657* The power function for real exponents.6658* Relative error: abs(result - e**y) < e**y * 1/5 * 10**(-prec - 1)6659*/6660static void6661_mpd_qpow_real(mpd_t *result, const mpd_t *base, const mpd_t *exp,6662const mpd_context_t *ctx, uint32_t *status)6663{6664mpd_context_t workctx;6665MPD_NEW_STATIC(texp,0,0,0,0);66666667if (!mpd_qcopy(&texp, exp, status)) {6668mpd_seterror(result, MPD_Malloc_error, status);6669return;6670}66716672mpd_maxcontext(&workctx);6673workctx.prec = (base->digits > ctx->prec) ? base->digits : ctx->prec;6674workctx.prec += (4 + MPD_EXPDIGITS);6675workctx.round = MPD_ROUND_HALF_EVEN;6676workctx.allcr = ctx->allcr;66776678/*6679* extra := MPD_EXPDIGITS = MPD_EXP_MAX_T6680* wp := prec + 4 + extra6681* abs(err) < 5 * 10**-wp6682* y := log(base) * exp6683* Calculate:6684* 1) e**(y * (1 + err)**2) * (1 + err)6685* = e**y * e**(y * (2*err + err**2)) * (1 + err)6686* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^6687* Relative error of the underlined term:6688* 2) abs(e**(y * (2*err + err**2)) - 1)6689* Case abs(y) >= 10**extra:6690* 3) adjexp(y)+1 > log10(abs(y)) >= extra6691* This triggers the Overflow/Underflow shortcut in _mpd_qexp(),6692* so no further analysis is necessary.6693* Case abs(y) < 10**extra:6694* 4) abs(y * (2*err + err**2)) < 1/5 * 10**(-prec - 2)6695* Use (see _mpd_qexp):6696* 5) abs(x) <= 9/10 * 10**-p ==> abs(e**x - 1) < 10**-p6697* With 2), 4) and 5):6698* 6) abs(e**(y * (2*err + err**2)) - 1) < 10**(-prec - 2)6699* The complete relative error of 1) is:6700* 7) abs(result - e**y) < e**y * 1/5 * 10**(-prec - 1)6701*/6702mpd_qln(result, base, &workctx, &workctx.status);6703mpd_qmul(result, result, &texp, &workctx, &workctx.status);6704mpd_qexp(result, result, &workctx, status);67056706mpd_del(&texp);6707*status |= (workctx.status&MPD_Errors);6708*status |= (MPD_Inexact|MPD_Rounded);6709}67106711/* The power function: base**exp */6712void6713mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp,6714const mpd_context_t *ctx, uint32_t *status)6715{6716uint8_t resultsign = 0;6717int intexp = 0;6718int cmp;67196720if (mpd_isspecial(base) || mpd_isspecial(exp)) {6721if (mpd_qcheck_nans(result, base, exp, ctx, status)) {6722return;6723}6724}6725if (mpd_isinteger(exp)) {6726intexp = 1;6727resultsign = mpd_isnegative(base) && mpd_isodd(exp);6728}67296730if (mpd_iszero(base)) {6731if (mpd_iszero(exp)) {6732mpd_seterror(result, MPD_Invalid_operation, status);6733}6734else if (mpd_isnegative(exp)) {6735mpd_setspecial(result, resultsign, MPD_INF);6736}6737else {6738_settriple(result, resultsign, 0, 0);6739}6740return;6741}6742if (mpd_isnegative(base)) {6743if (!intexp || mpd_isinfinite(exp)) {6744mpd_seterror(result, MPD_Invalid_operation, status);6745return;6746}6747}6748if (mpd_isinfinite(exp)) {6749/* power of one */6750cmp = _qcheck_pow_one_inf(result, base, resultsign, ctx, status);6751if (cmp == 0) {6752return;6753}6754else {6755cmp *= mpd_arith_sign(exp);6756if (cmp < 0) {6757_settriple(result, resultsign, 0, 0);6758}6759else {6760mpd_setspecial(result, resultsign, MPD_INF);6761}6762}6763return;6764}6765if (mpd_isinfinite(base)) {6766if (mpd_iszero(exp)) {6767_settriple(result, resultsign, 1, 0);6768}6769else if (mpd_isnegative(exp)) {6770_settriple(result, resultsign, 0, 0);6771}6772else {6773mpd_setspecial(result, resultsign, MPD_INF);6774}6775return;6776}6777if (mpd_iszero(exp)) {6778_settriple(result, resultsign, 1, 0);6779return;6780}6781if (_qcheck_pow_one(result, base, exp, resultsign, ctx, status) == 0) {6782return;6783}6784if (_qcheck_pow_bounds(result, base, exp, resultsign, ctx, status)) {6785return;6786}67876788if (intexp) {6789_mpd_qpow_int(result, base, exp, resultsign, ctx, status);6790}6791else {6792_mpd_qpow_real(result, base, exp, ctx, status);6793if (!mpd_isspecial(result) && _mpd_cmp(result, &one) == 0) {6794mpd_ssize_t shift = ctx->prec-1;6795mpd_qshiftl(result, &one, shift, status);6796result->exp = -shift;6797}6798if (mpd_isinfinite(result)) {6799/* for ROUND_DOWN, ROUND_FLOOR, etc. */6800_settriple(result, MPD_POS, 1, MPD_EXP_INF);6801}6802mpd_qfinalize(result, ctx, status);6803}6804}68056806/*6807* Internal function: Integer powmod with mpd_uint_t exponent, base is modified!6808* Function can fail with MPD_Malloc_error.6809*/6810static inline void6811_mpd_qpowmod_uint(mpd_t *result, mpd_t *base, mpd_uint_t exp,6812const mpd_t *mod, uint32_t *status)6813{6814mpd_context_t maxcontext;68156816mpd_maxcontext(&maxcontext);68176818/* resize to smaller cannot fail */6819mpd_qcopy(result, &one, status);68206821while (exp > 0) {6822if (exp & 1) {6823_mpd_qmul_exact(result, result, base, &maxcontext, status);6824mpd_qrem(result, result, mod, &maxcontext, status);6825}6826_mpd_qmul_exact(base, base, base, &maxcontext, status);6827mpd_qrem(base, base, mod, &maxcontext, status);6828exp >>= 1;6829}6830}68316832/* The powmod function: (base**exp) % mod */6833void6834mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp,6835const mpd_t *mod,6836const mpd_context_t *ctx, uint32_t *status)6837{6838mpd_context_t maxcontext;6839MPD_NEW_STATIC(tbase,0,0,0,0);6840MPD_NEW_STATIC(texp,0,0,0,0);6841MPD_NEW_STATIC(tmod,0,0,0,0);6842MPD_NEW_STATIC(tmp,0,0,0,0);6843MPD_NEW_CONST(two,0,0,1,1,1,2);6844mpd_ssize_t tbase_exp, texp_exp;6845mpd_ssize_t i;6846mpd_t t;6847mpd_uint_t r;6848uint8_t sign;684968506851if (mpd_isspecial(base) || mpd_isspecial(exp) || mpd_isspecial(mod)) {6852if (mpd_qcheck_3nans(result, base, exp, mod, ctx, status)) {6853return;6854}6855mpd_seterror(result, MPD_Invalid_operation, status);6856return;6857}685868596860if (!_mpd_isint(base) || !_mpd_isint(exp) || !_mpd_isint(mod)) {6861mpd_seterror(result, MPD_Invalid_operation, status);6862return;6863}6864if (mpd_iszerocoeff(mod)) {6865mpd_seterror(result, MPD_Invalid_operation, status);6866return;6867}6868if (mod->digits+mod->exp > ctx->prec) {6869mpd_seterror(result, MPD_Invalid_operation, status);6870return;6871}68726873sign = (mpd_isnegative(base)) && (mpd_isodd(exp));6874if (mpd_iszerocoeff(exp)) {6875if (mpd_iszerocoeff(base)) {6876mpd_seterror(result, MPD_Invalid_operation, status);6877return;6878}6879r = (_mpd_cmp_abs(mod, &one)==0) ? 0 : 1;6880_settriple(result, sign, r, 0);6881return;6882}6883if (mpd_isnegative(exp)) {6884mpd_seterror(result, MPD_Invalid_operation, status);6885return;6886}6887if (mpd_iszerocoeff(base)) {6888_settriple(result, sign, 0, 0);6889return;6890}68916892mpd_maxcontext(&maxcontext);68936894mpd_qrescale(&tmod, mod, 0, &maxcontext, &maxcontext.status);6895if (maxcontext.status&MPD_Errors) {6896mpd_seterror(result, maxcontext.status&MPD_Errors, status);6897goto out;6898}6899maxcontext.status = 0;6900mpd_set_positive(&tmod);69016902mpd_qround_to_int(&tbase, base, &maxcontext, status);6903mpd_set_positive(&tbase);6904tbase_exp = tbase.exp;6905tbase.exp = 0;69066907mpd_qround_to_int(&texp, exp, &maxcontext, status);6908texp_exp = texp.exp;6909texp.exp = 0;69106911/* base = (base.int % modulo * pow(10, base.exp, modulo)) % modulo */6912mpd_qrem(&tbase, &tbase, &tmod, &maxcontext, status);6913mpd_qshiftl(result, &one, tbase_exp, status);6914mpd_qrem(result, result, &tmod, &maxcontext, status);6915_mpd_qmul_exact(&tbase, &tbase, result, &maxcontext, status);6916mpd_qrem(&tbase, &tbase, &tmod, &maxcontext, status);6917if (mpd_isspecial(&tbase) ||6918mpd_isspecial(&texp) ||6919mpd_isspecial(&tmod)) {6920goto mpd_errors;6921}69226923for (i = 0; i < texp_exp; i++) {6924_mpd_qpowmod_uint(&tmp, &tbase, 10, &tmod, status);6925t = tmp;6926tmp = tbase;6927tbase = t;6928}6929if (mpd_isspecial(&tbase)) {6930goto mpd_errors; /* GCOV_UNLIKELY */6931}69326933/* resize to smaller cannot fail */6934mpd_qcopy(result, &one, status);6935while (mpd_isfinite(&texp) && !mpd_iszero(&texp)) {6936if (mpd_isodd(&texp)) {6937_mpd_qmul_exact(result, result, &tbase, &maxcontext, status);6938mpd_qrem(result, result, &tmod, &maxcontext, status);6939}6940_mpd_qmul_exact(&tbase, &tbase, &tbase, &maxcontext, status);6941mpd_qrem(&tbase, &tbase, &tmod, &maxcontext, status);6942mpd_qdivint(&texp, &texp, &two, &maxcontext, status);6943}6944if (mpd_isspecial(&texp) || mpd_isspecial(&tbase) ||6945mpd_isspecial(&tmod) || mpd_isspecial(result)) {6946/* MPD_Malloc_error */6947goto mpd_errors;6948}6949else {6950mpd_set_sign(result, sign);6951}69526953out:6954mpd_del(&tbase);6955mpd_del(&texp);6956mpd_del(&tmod);6957mpd_del(&tmp);6958return;69596960mpd_errors:6961mpd_setspecial(result, MPD_POS, MPD_NAN);6962goto out;6963}69646965void6966mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b,6967const mpd_context_t *ctx, uint32_t *status)6968{6969uint32_t workstatus = 0;6970mpd_ssize_t b_exp = b->exp;6971mpd_ssize_t expdiff, shift;6972mpd_uint_t rnd;69736974if (mpd_isspecial(a) || mpd_isspecial(b)) {6975if (mpd_qcheck_nans(result, a, b, ctx, status)) {6976return;6977}6978if (mpd_isinfinite(a) && mpd_isinfinite(b)) {6979mpd_qcopy(result, a, status);6980return;6981}6982mpd_seterror(result, MPD_Invalid_operation, status);6983return;6984}69856986if (b->exp > ctx->emax || b->exp < mpd_etiny(ctx)) {6987mpd_seterror(result, MPD_Invalid_operation, status);6988return;6989}69906991if (mpd_iszero(a)) {6992_settriple(result, mpd_sign(a), 0, b->exp);6993mpd_qfinalize(result, ctx, status);6994return;6995}699669976998expdiff = a->exp - b->exp;6999if (a->digits + expdiff > ctx->prec) {7000mpd_seterror(result, MPD_Invalid_operation, status);7001return;7002}70037004if (expdiff >= 0) {7005shift = expdiff;7006if (!mpd_qshiftl(result, a, shift, status)) {7007return;7008}7009result->exp = b_exp;7010}7011else {7012/* At this point expdiff < 0 and a->digits+expdiff <= prec,7013* so the shift before an increment will fit in prec. */7014shift = -expdiff;7015rnd = mpd_qshiftr(result, a, shift, status);7016if (rnd == MPD_UINT_MAX) {7017return;7018}7019result->exp = b_exp;7020if (!_mpd_apply_round_fit(result, rnd, ctx, status)) {7021return;7022}7023workstatus |= MPD_Rounded;7024if (rnd) {7025workstatus |= MPD_Inexact;7026}7027}70287029if (mpd_adjexp(result) > ctx->emax ||7030mpd_adjexp(result) < mpd_etiny(ctx)) {7031mpd_seterror(result, MPD_Invalid_operation, status);7032return;7033}70347035*status |= workstatus;7036mpd_qfinalize(result, ctx, status);7037}70387039void7040mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7041uint32_t *status)7042{7043mpd_ssize_t shift, maxexp, maxshift;7044uint8_t sign_a = mpd_sign(a);70457046if (mpd_isspecial(a)) {7047if (mpd_qcheck_nan(result, a, ctx, status)) {7048return;7049}7050mpd_qcopy(result, a, status);7051return;7052}70537054if (!mpd_qcopy(result, a, status)) {7055return;7056}7057mpd_qfinalize(result, ctx, status);7058if (mpd_isspecial(result)) {7059return;7060}7061if (mpd_iszero(result)) {7062_settriple(result, sign_a, 0, 0);7063return;7064}70657066shift = mpd_trail_zeros(result);7067maxexp = (ctx->clamp) ? mpd_etop(ctx) : ctx->emax;7068/* After the finalizing above result->exp <= maxexp. */7069maxshift = maxexp - result->exp;7070shift = (shift > maxshift) ? maxshift : shift;70717072mpd_qshiftr_inplace(result, shift);7073result->exp += shift;7074}70757076void7077mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx,7078uint32_t *status)7079{7080MPD_NEW_STATIC(q,0,0,0,0);70817082if (mpd_isspecial(a) || mpd_isspecial(b)) {7083if (mpd_qcheck_nans(r, a, b, ctx, status)) {7084return;7085}7086if (mpd_isinfinite(a)) {7087mpd_seterror(r, MPD_Invalid_operation, status);7088return;7089}7090if (mpd_isinfinite(b)) {7091mpd_qcopy(r, a, status);7092mpd_qfinalize(r, ctx, status);7093return;7094}7095/* debug */7096abort(); /* GCOV_NOT_REACHED */7097}7098if (mpd_iszerocoeff(b)) {7099if (mpd_iszerocoeff(a)) {7100mpd_seterror(r, MPD_Division_undefined, status);7101}7102else {7103mpd_seterror(r, MPD_Invalid_operation, status);7104}7105return;7106}71077108_mpd_qdivmod(&q, r, a, b, ctx, status);7109mpd_del(&q);7110mpd_qfinalize(r, ctx, status);7111}71127113void7114mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b,7115const mpd_context_t *ctx, uint32_t *status)7116{7117mpd_context_t workctx;7118MPD_NEW_STATIC(btmp,0,0,0,0);7119MPD_NEW_STATIC(q,0,0,0,0);7120mpd_ssize_t expdiff, qdigits;7121int cmp, isodd, allnine;71227123assert(r != NULL); /* annotation for scan-build */71247125if (mpd_isspecial(a) || mpd_isspecial(b)) {7126if (mpd_qcheck_nans(r, a, b, ctx, status)) {7127return;7128}7129if (mpd_isinfinite(a)) {7130mpd_seterror(r, MPD_Invalid_operation, status);7131return;7132}7133if (mpd_isinfinite(b)) {7134mpd_qcopy(r, a, status);7135mpd_qfinalize(r, ctx, status);7136return;7137}7138/* debug */7139abort(); /* GCOV_NOT_REACHED */7140}7141if (mpd_iszerocoeff(b)) {7142if (mpd_iszerocoeff(a)) {7143mpd_seterror(r, MPD_Division_undefined, status);7144}7145else {7146mpd_seterror(r, MPD_Invalid_operation, status);7147}7148return;7149}71507151if (r == b) {7152if (!mpd_qcopy(&btmp, b, status)) {7153mpd_seterror(r, MPD_Malloc_error, status);7154return;7155}7156b = &btmp;7157}71587159_mpd_qdivmod(&q, r, a, b, ctx, status);7160if (mpd_isnan(&q) || mpd_isnan(r)) {7161goto finish;7162}7163if (mpd_iszerocoeff(r)) {7164goto finish;7165}71667167expdiff = mpd_adjexp(b) - mpd_adjexp(r);7168if (-1 <= expdiff && expdiff <= 1) {71697170allnine = mpd_coeff_isallnine(&q);7171qdigits = q.digits;7172isodd = mpd_isodd(&q);71737174mpd_maxcontext(&workctx);7175if (mpd_sign(a) == mpd_sign(b)) {7176/* sign(r) == sign(b) */7177_mpd_qsub(&q, r, b, &workctx, &workctx.status);7178}7179else {7180/* sign(r) != sign(b) */7181_mpd_qadd(&q, r, b, &workctx, &workctx.status);7182}71837184if (workctx.status&MPD_Errors) {7185mpd_seterror(r, workctx.status&MPD_Errors, status);7186goto finish;7187}71887189cmp = _mpd_cmp_abs(&q, r);7190if (cmp < 0 || (cmp == 0 && isodd)) {7191/* abs(r) > abs(b)/2 or abs(r) == abs(b)/2 and isodd(quotient) */7192if (allnine && qdigits == ctx->prec) {7193/* abs(quotient) + 1 == 10**prec */7194mpd_seterror(r, MPD_Division_impossible, status);7195goto finish;7196}7197mpd_qcopy(r, &q, status);7198}7199}720072017202finish:7203mpd_del(&btmp);7204mpd_del(&q);7205mpd_qfinalize(r, ctx, status);7206}72077208static void7209_mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,7210const mpd_context_t *ctx, uint32_t *status)7211{7212mpd_ssize_t expdiff, shift;7213mpd_uint_t rnd;72147215if (mpd_isspecial(a)) {7216mpd_qcopy(result, a, status);7217return;7218}72197220if (mpd_iszero(a)) {7221_settriple(result, mpd_sign(a), 0, exp);7222return;7223}72247225expdiff = a->exp - exp;7226if (expdiff >= 0) {7227shift = expdiff;7228if (a->digits + shift > MPD_MAX_PREC+1) {7229mpd_seterror(result, MPD_Invalid_operation, status);7230return;7231}7232if (!mpd_qshiftl(result, a, shift, status)) {7233return;7234}7235result->exp = exp;7236}7237else {7238shift = -expdiff;7239rnd = mpd_qshiftr(result, a, shift, status);7240if (rnd == MPD_UINT_MAX) {7241return;7242}7243result->exp = exp;7244_mpd_apply_round_excess(result, rnd, ctx, status);7245*status |= MPD_Rounded;7246if (rnd) {7247*status |= MPD_Inexact;7248}7249}72507251if (mpd_issubnormal(result, ctx)) {7252*status |= MPD_Subnormal;7253}7254}72557256/*7257* Rescale a number so that it has exponent 'exp'. Does not regard context7258* precision, emax, emin, but uses the rounding mode. Special numbers are7259* quietly copied. Restrictions:7260*7261* MPD_MIN_ETINY <= exp <= MPD_MAX_EMAX+17262* result->digits <= MPD_MAX_PREC+17263*/7264void7265mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,7266const mpd_context_t *ctx, uint32_t *status)7267{7268if (exp > MPD_MAX_EMAX+1 || exp < MPD_MIN_ETINY) {7269mpd_seterror(result, MPD_Invalid_operation, status);7270return;7271}72727273_mpd_qrescale(result, a, exp, ctx, status);7274}72757276/*7277* Same as mpd_qrescale, but with relaxed restrictions. The result of this7278* function should only be used for formatting a number and never as input7279* for other operations.7280*7281* MPD_MIN_ETINY-MPD_MAX_PREC <= exp <= MPD_MAX_EMAX+17282* result->digits <= MPD_MAX_PREC+17283*/7284void7285mpd_qrescale_fmt(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,7286const mpd_context_t *ctx, uint32_t *status)7287{7288if (exp > MPD_MAX_EMAX+1 || exp < MPD_MIN_ETINY-MPD_MAX_PREC) {7289mpd_seterror(result, MPD_Invalid_operation, status);7290return;7291}72927293_mpd_qrescale(result, a, exp, ctx, status);7294}72957296/* Round to an integer according to 'action' and ctx->round. */7297enum {TO_INT_EXACT, TO_INT_SILENT, TO_INT_TRUNC};7298static void7299_mpd_qround_to_integral(int action, mpd_t *result, const mpd_t *a,7300const mpd_context_t *ctx, uint32_t *status)7301{7302mpd_uint_t rnd;73037304if (mpd_isspecial(a)) {7305if (mpd_qcheck_nan(result, a, ctx, status)) {7306return;7307}7308mpd_qcopy(result, a, status);7309return;7310}7311if (a->exp >= 0) {7312mpd_qcopy(result, a, status);7313return;7314}7315if (mpd_iszerocoeff(a)) {7316_settriple(result, mpd_sign(a), 0, 0);7317return;7318}73197320rnd = mpd_qshiftr(result, a, -a->exp, status);7321if (rnd == MPD_UINT_MAX) {7322return;7323}7324result->exp = 0;73257326if (action == TO_INT_EXACT || action == TO_INT_SILENT) {7327_mpd_apply_round_excess(result, rnd, ctx, status);7328if (action == TO_INT_EXACT) {7329*status |= MPD_Rounded;7330if (rnd) {7331*status |= MPD_Inexact;7332}7333}7334}7335}73367337void7338mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7339uint32_t *status)7340{7341(void)_mpd_qround_to_integral(TO_INT_EXACT, result, a, ctx, status);7342}73437344void7345mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7346uint32_t *status)7347{7348(void)_mpd_qround_to_integral(TO_INT_SILENT, result, a, ctx, status);7349}73507351void7352mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7353uint32_t *status)7354{7355if (mpd_isspecial(a)) {7356mpd_seterror(result, MPD_Invalid_operation, status);7357return;7358}73597360(void)_mpd_qround_to_integral(TO_INT_TRUNC, result, a, ctx, status);7361}73627363void7364mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7365uint32_t *status)7366{7367mpd_context_t workctx = *ctx;73687369if (mpd_isspecial(a)) {7370mpd_seterror(result, MPD_Invalid_operation, status);7371return;7372}73737374workctx.round = MPD_ROUND_FLOOR;7375(void)_mpd_qround_to_integral(TO_INT_SILENT, result, a,7376&workctx, status);7377}73787379void7380mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7381uint32_t *status)7382{7383mpd_context_t workctx = *ctx;73847385if (mpd_isspecial(a)) {7386mpd_seterror(result, MPD_Invalid_operation, status);7387return;7388}73897390workctx.round = MPD_ROUND_CEILING;7391(void)_mpd_qround_to_integral(TO_INT_SILENT, result, a,7392&workctx, status);7393}73947395int7396mpd_same_quantum(const mpd_t *a, const mpd_t *b)7397{7398if (mpd_isspecial(a) || mpd_isspecial(b)) {7399return ((mpd_isnan(a) && mpd_isnan(b)) ||7400(mpd_isinfinite(a) && mpd_isinfinite(b)));7401}74027403return a->exp == b->exp;7404}74057406/* Schedule the increase in precision for the Newton iteration. */7407static inline int7408recpr_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2],7409mpd_ssize_t maxprec, mpd_ssize_t initprec)7410{7411mpd_ssize_t k;7412int i;74137414assert(maxprec > 0 && initprec > 0);7415if (maxprec <= initprec) return -1;74167417i = 0; k = maxprec;7418do {7419k = (k+1) / 2;7420klist[i++] = k;7421} while (k > initprec);74227423return i-1;7424}74257426/*7427* Initial approximation for the reciprocal:7428* k_0 := MPD_RDIGITS-27429* z_0 := 10**(-k_0) * floor(10**(2*k_0 + 2) / floor(v * 10**(k_0 + 2)))7430* Absolute error:7431* |1/v - z_0| < 10**(-k_0)7432* ACL2 proof: maxerror-inverse-approx7433*/7434static void7435_mpd_qreciprocal_approx(mpd_t *z, const mpd_t *v, uint32_t *status)7436{7437mpd_uint_t p10data[2] = {0, mpd_pow10[MPD_RDIGITS-2]};7438mpd_uint_t dummy, word;7439int n;74407441assert(v->exp == -v->digits);74427443_mpd_get_msdigits(&dummy, &word, v, MPD_RDIGITS);7444n = mpd_word_digits(word);7445word *= mpd_pow10[MPD_RDIGITS-n];74467447mpd_qresize(z, 2, status);7448(void)_mpd_shortdiv(z->data, p10data, 2, word);74497450mpd_clear_flags(z);7451z->exp = -(MPD_RDIGITS-2);7452z->len = (z->data[1] == 0) ? 1 : 2;7453mpd_setdigits(z);7454}74557456/*7457* Reciprocal, calculated with Newton's Method. Assumption: result != a.7458* NOTE: The comments in the function show that certain operations are7459* exact. The proof for the maximum error is too long to fit in here.7460* ACL2 proof: maxerror-inverse-complete7461*/7462static void7463_mpd_qreciprocal(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7464uint32_t *status)7465{7466mpd_context_t varcontext, maxcontext;7467mpd_t *z = result; /* current approximation */7468mpd_t *v; /* a, normalized to a number between 0.1 and 1 */7469MPD_NEW_SHARED(vtmp, a); /* v shares data with a */7470MPD_NEW_STATIC(s,0,0,0,0); /* temporary variable */7471MPD_NEW_STATIC(t,0,0,0,0); /* temporary variable */7472MPD_NEW_CONST(two,0,0,1,1,1,2); /* const 2 */7473mpd_ssize_t klist[MPD_MAX_PREC_LOG2];7474mpd_ssize_t adj, maxprec, initprec;7475uint8_t sign = mpd_sign(a);7476int i;74777478assert(result != a);74797480v = &vtmp;7481mpd_clear_flags(v);7482adj = v->digits + v->exp;7483v->exp = -v->digits;74847485/* Initial approximation */7486_mpd_qreciprocal_approx(z, v, status);74877488mpd_maxcontext(&varcontext);7489mpd_maxcontext(&maxcontext);7490varcontext.round = maxcontext.round = MPD_ROUND_TRUNC;7491varcontext.emax = maxcontext.emax = MPD_MAX_EMAX + 100;7492varcontext.emin = maxcontext.emin = MPD_MIN_EMIN - 100;7493maxcontext.prec = MPD_MAX_PREC + 100;74947495maxprec = ctx->prec;7496maxprec += 2;7497initprec = MPD_RDIGITS-3;74987499i = recpr_schedule_prec(klist, maxprec, initprec);7500for (; i >= 0; i--) {7501/* Loop invariant: z->digits <= klist[i]+7 */7502/* Let s := z**2, exact result */7503_mpd_qmul_exact(&s, z, z, &maxcontext, status);7504varcontext.prec = 2*klist[i] + 5;7505if (v->digits > varcontext.prec) {7506/* Let t := v, truncated to n >= 2*k+5 fraction digits */7507mpd_qshiftr(&t, v, v->digits-varcontext.prec, status);7508t.exp = -varcontext.prec;7509/* Let t := trunc(v)*s, truncated to n >= 2*k+1 fraction digits */7510mpd_qmul(&t, &t, &s, &varcontext, status);7511}7512else { /* v->digits <= 2*k+5 */7513/* Let t := v*s, truncated to n >= 2*k+1 fraction digits */7514mpd_qmul(&t, v, &s, &varcontext, status);7515}7516/* Let s := 2*z, exact result */7517_mpd_qmul_exact(&s, z, &two, &maxcontext, status);7518/* s.digits < t.digits <= 2*k+5, |adjexp(s)-adjexp(t)| <= 1,7519* so the subtraction generates at most 2*k+6 <= klist[i+1]+77520* digits. The loop invariant is preserved. */7521_mpd_qsub_exact(z, &s, &t, &maxcontext, status);7522}75237524if (!mpd_isspecial(z)) {7525z->exp -= adj;7526mpd_set_flags(z, sign);7527}75287529mpd_del(&s);7530mpd_del(&t);7531mpd_qfinalize(z, ctx, status);7532}75337534/*7535* Internal function for large numbers:7536*7537* q, r = divmod(coeff(a), coeff(b))7538*7539* Strategy: Multiply the dividend by the reciprocal of the divisor. The7540* inexact result is fixed by a small loop, using at most one iteration.7541*7542* ACL2 proofs:7543* ------------7544* 1) q is a natural number. (ndivmod-quotient-natp)7545* 2) r is a natural number. (ndivmod-remainder-natp)7546* 3) a = q * b + r (ndivmod-q*b+r==a)7547* 4) r < b (ndivmod-remainder-<-b)7548*/7549static void7550_mpd_base_ndivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,7551uint32_t *status)7552{7553mpd_context_t workctx;7554mpd_t *qq = q, *rr = r;7555mpd_t aa, bb;7556int k;75577558_mpd_copy_shared(&aa, a);7559_mpd_copy_shared(&bb, b);75607561mpd_set_positive(&aa);7562mpd_set_positive(&bb);7563aa.exp = 0;7564bb.exp = 0;75657566if (q == a || q == b) {7567if ((qq = mpd_qnew()) == NULL) {7568*status |= MPD_Malloc_error;7569goto nanresult;7570}7571}7572if (r == a || r == b) {7573if ((rr = mpd_qnew()) == NULL) {7574*status |= MPD_Malloc_error;7575goto nanresult;7576}7577}75787579mpd_maxcontext(&workctx);75807581/* Let prec := adigits - bdigits + 4 */7582workctx.prec = a->digits - b->digits + 1 + 3;7583if (a->digits > MPD_MAX_PREC || workctx.prec > MPD_MAX_PREC) {7584*status |= MPD_Division_impossible;7585goto nanresult;7586}75877588/* Let x := _mpd_qreciprocal(b, prec)7589* Then x is bounded by:7590* 1) 1/b - 10**(-prec - bdigits) < x < 1/b + 10**(-prec - bdigits)7591* 2) 1/b - 10**(-adigits - 4) < x < 1/b + 10**(-adigits - 4)7592*/7593_mpd_qreciprocal(rr, &bb, &workctx, &workctx.status);75947595/* Get an estimate for the quotient. Let q := a * x7596* Then q is bounded by:7597* 3) a/b - 10**-4 < q < a/b + 10**-47598*/7599_mpd_qmul(qq, &aa, rr, &workctx, &workctx.status);7600/* Truncate q to an integer:7601* 4) a/b - 2 < trunc(q) < a/b + 17602*/7603mpd_qtrunc(qq, qq, &workctx, &workctx.status);76047605workctx.prec = aa.digits + 3;7606workctx.emax = MPD_MAX_EMAX + 3;7607workctx.emin = MPD_MIN_EMIN - 3;7608/* Multiply the estimate for q by b:7609* 5) a - 2 * b < trunc(q) * b < a + b7610*/7611_mpd_qmul(rr, &bb, qq, &workctx, &workctx.status);7612/* Get the estimate for r such that a = q * b + r. */7613_mpd_qsub_exact(rr, &aa, rr, &workctx, &workctx.status);76147615/* Fix the result. At this point -b < r < 2*b, so the correction loop7616takes at most one iteration. */7617for (k = 0;; k++) {7618if (mpd_isspecial(qq) || mpd_isspecial(rr)) {7619*status |= (workctx.status&MPD_Errors);7620goto nanresult;7621}7622if (k > 2) { /* Allow two iterations despite the proof. */7623mpd_err_warn("libmpdec: internal error in " /* GCOV_NOT_REACHED */7624"_mpd_base_ndivmod: please report"); /* GCOV_NOT_REACHED */7625*status |= MPD_Invalid_operation; /* GCOV_NOT_REACHED */7626goto nanresult; /* GCOV_NOT_REACHED */7627}7628/* r < 0 */7629else if (_mpd_cmp(&zero, rr) == 1) {7630_mpd_qadd_exact(rr, rr, &bb, &workctx, &workctx.status);7631_mpd_qadd_exact(qq, qq, &minus_one, &workctx, &workctx.status);7632}7633/* 0 <= r < b */7634else if (_mpd_cmp(rr, &bb) == -1) {7635break;7636}7637/* r >= b */7638else {7639_mpd_qsub_exact(rr, rr, &bb, &workctx, &workctx.status);7640_mpd_qadd_exact(qq, qq, &one, &workctx, &workctx.status);7641}7642}76437644if (qq != q) {7645if (!mpd_qcopy(q, qq, status)) {7646goto nanresult; /* GCOV_UNLIKELY */7647}7648mpd_del(qq);7649}7650if (rr != r) {7651if (!mpd_qcopy(r, rr, status)) {7652goto nanresult; /* GCOV_UNLIKELY */7653}7654mpd_del(rr);7655}76567657*status |= (workctx.status&MPD_Errors);7658return;765976607661nanresult:7662if (qq && qq != q) mpd_del(qq);7663if (rr && rr != r) mpd_del(rr);7664mpd_setspecial(q, MPD_POS, MPD_NAN);7665mpd_setspecial(r, MPD_POS, MPD_NAN);7666}76677668/* LIBMPDEC_ONLY */7669/*7670* Schedule the optimal precision increase for the Newton iteration.7671* v := input operand7672* z_0 := initial approximation7673* initprec := natural number such that abs(sqrt(v) - z_0) < 10**-initprec7674* maxprec := target precision7675*7676* For convenience the output klist contains the elements in reverse order:7677* klist := [k_n-1, ..., k_0], where7678* 1) k_0 <= initprec and7679* 2) abs(sqrt(v) - result) < 10**(-2*k_n-1 + 2) <= 10**-maxprec.7680*/7681static inline int7682invroot_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2],7683mpd_ssize_t maxprec, mpd_ssize_t initprec)7684{7685mpd_ssize_t k;7686int i;76877688assert(maxprec >= 3 && initprec >= 3);7689if (maxprec <= initprec) return -1;76907691i = 0; k = maxprec;7692do {7693k = (k+3) / 2;7694klist[i++] = k;7695} while (k > initprec);76967697return i-1;7698}76997700/*7701* Initial approximation for the inverse square root function.7702* Input:7703* v := rational number, with 1 <= v < 1007704* vhat := floor(v * 10**6)7705* Output:7706* z := approximation to 1/sqrt(v), such that abs(z - 1/sqrt(v)) < 10**-3.7707*/7708static inline void7709_invroot_init_approx(mpd_t *z, mpd_uint_t vhat)7710{7711mpd_uint_t lo = 1000;7712mpd_uint_t hi = 10000;7713mpd_uint_t a, sq;77147715assert(lo*lo <= vhat && vhat < (hi+1)*(hi+1));77167717for(;;) {7718a = (lo + hi) / 2;7719sq = a * a;7720if (vhat >= sq) {7721if (vhat < sq + 2*a + 1) {7722break;7723}7724lo = a + 1;7725}7726else {7727hi = a - 1;7728}7729}77307731/*7732* After the binary search we have:7733* 1) a**2 <= floor(v * 10**6) < (a + 1)**27734* This implies:7735* 2) a**2 <= v * 10**6 < (a + 1)**27736* 3) a <= sqrt(v) * 10**3 < a + 17737* Since 10**3 <= a:7738* 4) 0 <= 10**prec/a - 1/sqrt(v) < 10**-prec7739* We have:7740* 5) 10**3/a - 10**-3 < floor(10**9/a) * 10**-6 <= 10**3/a7741* Merging 4) and 5):7742* 6) abs(floor(10**9/a) * 10**-6 - 1/sqrt(v)) < 10**-37743*/7744mpd_minalloc(z);7745mpd_clear_flags(z);7746z->data[0] = 1000000000UL / a;7747z->len = 1;7748z->exp = -6;7749mpd_setdigits(z);7750}77517752/*7753* Set 'result' to 1/sqrt(a).7754* Relative error: abs(result - 1/sqrt(a)) < 10**-prec * 1/sqrt(a)7755*/7756static void7757_mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7758uint32_t *status)7759{7760uint32_t workstatus = 0;7761mpd_context_t varcontext, maxcontext;7762mpd_t *z = result; /* current approximation */7763mpd_t *v; /* a, normalized to a number between 1 and 100 */7764MPD_NEW_SHARED(vtmp, a); /* by default v will share data with a */7765MPD_NEW_STATIC(s,0,0,0,0); /* temporary variable */7766MPD_NEW_STATIC(t,0,0,0,0); /* temporary variable */7767MPD_NEW_CONST(one_half,0,-1,1,1,1,5);7768MPD_NEW_CONST(three,0,0,1,1,1,3);7769mpd_ssize_t klist[MPD_MAX_PREC_LOG2];7770mpd_ssize_t ideal_exp, shift;7771mpd_ssize_t adj, tz;7772mpd_ssize_t maxprec, fracdigits;7773mpd_uint_t vhat, dummy;7774int i, n;777577767777ideal_exp = -(a->exp - (a->exp & 1)) / 2;77787779v = &vtmp;7780if (result == a) {7781if ((v = mpd_qncopy(a)) == NULL) {7782mpd_seterror(result, MPD_Malloc_error, status);7783return;7784}7785}77867787/* normalize a to 1 <= v < 100 */7788if ((v->digits+v->exp) & 1) {7789fracdigits = v->digits - 1;7790v->exp = -fracdigits;7791n = (v->digits > 7) ? 7 : (int)v->digits;7792/* Let vhat := floor(v * 10**(2*initprec)) */7793_mpd_get_msdigits(&dummy, &vhat, v, n);7794if (n < 7) {7795vhat *= mpd_pow10[7-n];7796}7797}7798else {7799fracdigits = v->digits - 2;7800v->exp = -fracdigits;7801n = (v->digits > 8) ? 8 : (int)v->digits;7802/* Let vhat := floor(v * 10**(2*initprec)) */7803_mpd_get_msdigits(&dummy, &vhat, v, n);7804if (n < 8) {7805vhat *= mpd_pow10[8-n];7806}7807}7808adj = (a->exp-v->exp) / 2;78097810/* initial approximation */7811_invroot_init_approx(z, vhat);78127813mpd_maxcontext(&maxcontext);7814mpd_maxcontext(&varcontext);7815varcontext.round = MPD_ROUND_TRUNC;7816maxprec = ctx->prec + 1;78177818/* initprec == 3 */7819i = invroot_schedule_prec(klist, maxprec, 3);7820for (; i >= 0; i--) {7821varcontext.prec = 2*klist[i]+2;7822mpd_qmul(&s, z, z, &maxcontext, &workstatus);7823if (v->digits > varcontext.prec) {7824shift = v->digits - varcontext.prec;7825mpd_qshiftr(&t, v, shift, &workstatus);7826t.exp += shift;7827mpd_qmul(&t, &t, &s, &varcontext, &workstatus);7828}7829else {7830mpd_qmul(&t, v, &s, &varcontext, &workstatus);7831}7832mpd_qsub(&t, &three, &t, &maxcontext, &workstatus);7833mpd_qmul(z, z, &t, &varcontext, &workstatus);7834mpd_qmul(z, z, &one_half, &maxcontext, &workstatus);7835}78367837z->exp -= adj;78387839tz = mpd_trail_zeros(result);7840shift = ideal_exp - result->exp;7841shift = (tz > shift) ? shift : tz;7842if (shift > 0) {7843mpd_qshiftr_inplace(result, shift);7844result->exp += shift;7845}784678477848mpd_del(&s);7849mpd_del(&t);7850if (v != &vtmp) mpd_del(v);7851*status |= (workstatus&MPD_Errors);7852*status |= (MPD_Rounded|MPD_Inexact);7853}78547855void7856mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7857uint32_t *status)7858{7859mpd_context_t workctx;78607861if (mpd_isspecial(a)) {7862if (mpd_qcheck_nan(result, a, ctx, status)) {7863return;7864}7865if (mpd_isnegative(a)) {7866mpd_seterror(result, MPD_Invalid_operation, status);7867return;7868}7869/* positive infinity */7870_settriple(result, MPD_POS, 0, mpd_etiny(ctx));7871*status |= MPD_Clamped;7872return;7873}7874if (mpd_iszero(a)) {7875mpd_setspecial(result, mpd_sign(a), MPD_INF);7876*status |= MPD_Division_by_zero;7877return;7878}7879if (mpd_isnegative(a)) {7880mpd_seterror(result, MPD_Invalid_operation, status);7881return;7882}78837884workctx = *ctx;7885workctx.prec += 2;7886workctx.round = MPD_ROUND_HALF_EVEN;7887_mpd_qinvroot(result, a, &workctx, status);7888mpd_qfinalize(result, ctx, status);7889}7890/* END LIBMPDEC_ONLY */78917892/* Algorithm from decimal.py */7893static void7894_mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,7895uint32_t *status)7896{7897mpd_context_t maxcontext;7898MPD_NEW_STATIC(c,0,0,0,0);7899MPD_NEW_STATIC(q,0,0,0,0);7900MPD_NEW_STATIC(r,0,0,0,0);7901MPD_NEW_CONST(two,0,0,1,1,1,2);7902mpd_ssize_t prec, ideal_exp;7903mpd_ssize_t l, shift;7904int exact = 0;790579067907ideal_exp = (a->exp - (a->exp & 1)) / 2;79087909if (mpd_isspecial(a)) {7910if (mpd_qcheck_nan(result, a, ctx, status)) {7911return;7912}7913if (mpd_isnegative(a)) {7914mpd_seterror(result, MPD_Invalid_operation, status);7915return;7916}7917mpd_setspecial(result, MPD_POS, MPD_INF);7918return;7919}7920if (mpd_iszero(a)) {7921_settriple(result, mpd_sign(a), 0, ideal_exp);7922mpd_qfinalize(result, ctx, status);7923return;7924}7925if (mpd_isnegative(a)) {7926mpd_seterror(result, MPD_Invalid_operation, status);7927return;7928}79297930mpd_maxcontext(&maxcontext);7931prec = ctx->prec + 1;79327933if (!mpd_qcopy(&c, a, status)) {7934goto malloc_error;7935}7936c.exp = 0;79377938if (a->exp & 1) {7939if (!mpd_qshiftl(&c, &c, 1, status)) {7940goto malloc_error;7941}7942l = (a->digits >> 1) + 1;7943}7944else {7945l = (a->digits + 1) >> 1;7946}79477948shift = prec - l;7949if (shift >= 0) {7950if (!mpd_qshiftl(&c, &c, 2*shift, status)) {7951goto malloc_error;7952}7953exact = 1;7954}7955else {7956exact = !mpd_qshiftr_inplace(&c, -2*shift);7957}79587959ideal_exp -= shift;79607961/* find result = floor(sqrt(c)) using Newton's method */7962if (!mpd_qshiftl(result, &one, prec, status)) {7963goto malloc_error;7964}79657966while (1) {7967_mpd_qdivmod(&q, &r, &c, result, &maxcontext, &maxcontext.status);7968if (mpd_isspecial(result) || mpd_isspecial(&q)) {7969mpd_seterror(result, maxcontext.status&MPD_Errors, status);7970goto out;7971}7972if (_mpd_cmp(result, &q) <= 0) {7973break;7974}7975_mpd_qadd_exact(result, result, &q, &maxcontext, &maxcontext.status);7976if (mpd_isspecial(result)) {7977mpd_seterror(result, maxcontext.status&MPD_Errors, status);7978goto out;7979}7980_mpd_qdivmod(result, &r, result, &two, &maxcontext, &maxcontext.status);7981}79827983if (exact) {7984_mpd_qmul_exact(&r, result, result, &maxcontext, &maxcontext.status);7985if (mpd_isspecial(&r)) {7986mpd_seterror(result, maxcontext.status&MPD_Errors, status);7987goto out;7988}7989exact = (_mpd_cmp(&r, &c) == 0);7990}79917992if (exact) {7993if (shift >= 0) {7994mpd_qshiftr_inplace(result, shift);7995}7996else {7997if (!mpd_qshiftl(result, result, -shift, status)) {7998goto malloc_error;7999}8000}8001ideal_exp += shift;8002}8003else {8004int lsd = (int)mpd_lsd(result->data[0]);8005if (lsd == 0 || lsd == 5) {8006result->data[0] += 1;8007}8008}80098010result->exp = ideal_exp;801180128013out:8014mpd_del(&c);8015mpd_del(&q);8016mpd_del(&r);8017maxcontext = *ctx;8018maxcontext.round = MPD_ROUND_HALF_EVEN;8019mpd_qfinalize(result, &maxcontext, status);8020return;80218022malloc_error:8023mpd_seterror(result, MPD_Malloc_error, status);8024goto out;8025}80268027void8028mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,8029uint32_t *status)8030{8031MPD_NEW_STATIC(aa,0,0,0,0);8032uint32_t xstatus = 0;80338034if (result == a) {8035if (!mpd_qcopy(&aa, a, status)) {8036mpd_seterror(result, MPD_Malloc_error, status);8037goto out;8038}8039a = &aa;8040}80418042_mpd_qsqrt(result, a, ctx, &xstatus);80438044if (xstatus & (MPD_Malloc_error|MPD_Division_impossible)) {8045/* The above conditions can occur at very high context precisions8046* if intermediate values get too large. Retry the operation with8047* a lower context precision in case the result is exact.8048*8049* If the result is exact, an upper bound for the number of digits8050* is the number of digits in the input.8051*8052* NOTE: sqrt(40e9) = 2.0e+5 /\ digits(40e9) = digits(2.0e+5) = 28053*/8054uint32_t ystatus = 0;8055mpd_context_t workctx = *ctx;80568057workctx.prec = a->digits;8058if (workctx.prec >= ctx->prec) {8059*status |= (xstatus|MPD_Errors);8060goto out; /* No point in repeating this, keep the original error. */8061}80628063_mpd_qsqrt(result, a, &workctx, &ystatus);8064if (ystatus != 0) {8065ystatus = *status | ((xstatus|ystatus)&MPD_Errors);8066mpd_seterror(result, ystatus, status);8067}8068}8069else {8070*status |= xstatus;8071}80728073out:8074mpd_del(&aa);8075}807680778078/******************************************************************************/8079/* Base conversions */8080/******************************************************************************/80818082/* Space needed to represent an integer mpd_t in base 'base'. */8083size_t8084mpd_sizeinbase(const mpd_t *a, uint32_t base)8085{8086double x;8087size_t digits;8088double upper_bound;80898090assert(mpd_isinteger(a));8091assert(base >= 2);80928093if (mpd_iszero(a)) {8094return 1;8095}80968097digits = a->digits+a->exp;80988099#ifdef CONFIG_648100/* ceil(2711437152599294 / log10(2)) + 4 == 2**53 */8101if (digits > 2711437152599294ULL) {8102return SIZE_MAX;8103}81048105upper_bound = (double)((1ULL<<53)-1);8106#else8107upper_bound = (double)(SIZE_MAX-1);8108#endif81098110x = (double)digits / log10(base);8111return (x > upper_bound) ? SIZE_MAX : (size_t)x + 1;8112}81138114/* Space needed to import a base 'base' integer of length 'srclen'. */8115static mpd_ssize_t8116_mpd_importsize(size_t srclen, uint32_t base)8117{8118double x;8119double upper_bound;81208121assert(srclen > 0);8122assert(base >= 2);81238124#if SIZE_MAX == UINT64_MAX8125if (srclen > (1ULL<<53)) {8126return MPD_SSIZE_MAX;8127}81288129assert((1ULL<<53) <= MPD_MAXIMPORT);8130upper_bound = (double)((1ULL<<53)-1);8131#else8132upper_bound = MPD_MAXIMPORT-1;8133#endif81348135x = (double)srclen * (log10(base)/MPD_RDIGITS);8136return (x > upper_bound) ? MPD_SSIZE_MAX : (mpd_ssize_t)x + 1;8137}81388139static uint8_t8140mpd_resize_u16(uint16_t **w, size_t nmemb)8141{8142uint8_t err = 0;8143*w = mpd_realloc(*w, nmemb, sizeof **w, &err);8144return !err;8145}81468147static uint8_t8148mpd_resize_u32(uint32_t **w, size_t nmemb)8149{8150uint8_t err = 0;8151*w = mpd_realloc(*w, nmemb, sizeof **w, &err);8152return !err;8153}81548155static size_t8156_baseconv_to_u16(uint16_t **w, size_t wlen, mpd_uint_t wbase,8157mpd_uint_t *u, mpd_ssize_t ulen)8158{8159size_t n = 0;81608161assert(wlen > 0 && ulen > 0);8162assert(wbase <= (1U<<16));81638164do {8165if (n >= wlen) {8166if (!mpd_resize_u16(w, n+1)) {8167return SIZE_MAX;8168}8169wlen = n+1;8170}8171(*w)[n++] = (uint16_t)_mpd_shortdiv(u, u, ulen, wbase);8172/* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */8173ulen = _mpd_real_size(u, ulen);81748175} while (u[ulen-1] != 0);81768177return n;8178}81798180static size_t8181_coeff_from_u16(mpd_t *w, mpd_ssize_t wlen,8182const mpd_uint_t *u, size_t ulen, uint32_t ubase,8183uint32_t *status)8184{8185mpd_ssize_t n = 0;8186mpd_uint_t carry;81878188assert(wlen > 0 && ulen > 0);8189assert(ubase <= (1U<<16));81908191w->data[n++] = u[--ulen];8192while (--ulen != SIZE_MAX) {8193carry = _mpd_shortmul_c(w->data, w->data, n, ubase);8194if (carry) {8195if (n >= wlen) {8196if (!mpd_qresize(w, n+1, status)) {8197return SIZE_MAX;8198}8199wlen = n+1;8200}8201w->data[n++] = carry;8202}8203carry = _mpd_shortadd(w->data, n, u[ulen]);8204if (carry) {8205if (n >= wlen) {8206if (!mpd_qresize(w, n+1, status)) {8207return SIZE_MAX;8208}8209wlen = n+1;8210}8211w->data[n++] = carry;8212}8213}82148215return n;8216}82178218/* target base wbase < source base ubase */8219static size_t8220_baseconv_to_smaller(uint32_t **w, size_t wlen, uint32_t wbase,8221mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase)8222{8223size_t n = 0;82248225assert(wlen > 0 && ulen > 0);8226assert(wbase < ubase);82278228do {8229if (n >= wlen) {8230if (!mpd_resize_u32(w, n+1)) {8231return SIZE_MAX;8232}8233wlen = n+1;8234}8235(*w)[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase);8236/* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */8237ulen = _mpd_real_size(u, ulen);82388239} while (u[ulen-1] != 0);82408241return n;8242}82438244#ifdef CONFIG_328245/* target base 'wbase' == source base 'ubase' */8246static size_t8247_copy_equal_base(uint32_t **w, size_t wlen,8248const uint32_t *u, size_t ulen)8249{8250if (wlen < ulen) {8251if (!mpd_resize_u32(w, ulen)) {8252return SIZE_MAX;8253}8254}82558256memcpy(*w, u, ulen * (sizeof **w));8257return ulen;8258}82598260/* target base 'wbase' > source base 'ubase' */8261static size_t8262_baseconv_to_larger(uint32_t **w, size_t wlen, mpd_uint_t wbase,8263const mpd_uint_t *u, size_t ulen, mpd_uint_t ubase)8264{8265size_t n = 0;8266mpd_uint_t carry;82678268assert(wlen > 0 && ulen > 0);8269assert(ubase < wbase);82708271(*w)[n++] = u[--ulen];8272while (--ulen != SIZE_MAX) {8273carry = _mpd_shortmul_b(*w, *w, n, ubase, wbase);8274if (carry) {8275if (n >= wlen) {8276if (!mpd_resize_u32(w, n+1)) {8277return SIZE_MAX;8278}8279wlen = n+1;8280}8281(*w)[n++] = carry;8282}8283carry = _mpd_shortadd_b(*w, n, u[ulen], wbase);8284if (carry) {8285if (n >= wlen) {8286if (!mpd_resize_u32(w, n+1)) {8287return SIZE_MAX;8288}8289wlen = n+1;8290}8291(*w)[n++] = carry;8292}8293}82948295return n;8296}82978298/* target base wbase < source base ubase */8299static size_t8300_coeff_from_larger_base(mpd_t *w, size_t wlen, mpd_uint_t wbase,8301mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase,8302uint32_t *status)8303{8304size_t n = 0;83058306assert(wlen > 0 && ulen > 0);8307assert(wbase < ubase);83088309do {8310if (n >= wlen) {8311if (!mpd_qresize(w, n+1, status)) {8312return SIZE_MAX;8313}8314wlen = n+1;8315}8316w->data[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase);8317/* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */8318ulen = _mpd_real_size(u, ulen);83198320} while (u[ulen-1] != 0);83218322return n;8323}8324#endif83258326/* target base 'wbase' > source base 'ubase' */8327static size_t8328_coeff_from_smaller_base(mpd_t *w, mpd_ssize_t wlen, mpd_uint_t wbase,8329const uint32_t *u, size_t ulen, mpd_uint_t ubase,8330uint32_t *status)8331{8332mpd_ssize_t n = 0;8333mpd_uint_t carry;83348335assert(wlen > 0 && ulen > 0);8336assert(wbase > ubase);83378338w->data[n++] = u[--ulen];8339while (--ulen != SIZE_MAX) {8340carry = _mpd_shortmul_b(w->data, w->data, n, ubase, wbase);8341if (carry) {8342if (n >= wlen) {8343if (!mpd_qresize(w, n+1, status)) {8344return SIZE_MAX;8345}8346wlen = n+1;8347}8348w->data[n++] = carry;8349}8350carry = _mpd_shortadd_b(w->data, n, u[ulen], wbase);8351if (carry) {8352if (n >= wlen) {8353if (!mpd_qresize(w, n+1, status)) {8354return SIZE_MAX;8355}8356wlen = n+1;8357}8358w->data[n++] = carry;8359}8360}83618362return n;8363}83648365/*8366* Convert an integer mpd_t to a multiprecision integer with base <= 2**16.8367* The least significant word of the result is (*rdata)[0].8368*8369* If rdata is NULL, space is allocated by the function and rlen is irrelevant.8370* In case of an error any allocated storage is freed and rdata is set back to8371* NULL.8372*8373* If rdata is non-NULL, it MUST be allocated by one of libmpdec's allocation8374* functions and rlen MUST be correct. If necessary, the function will resize8375* rdata. In case of an error the caller must free rdata.8376*8377* Return value: In case of success, the exact length of rdata, SIZE_MAX8378* otherwise.8379*/8380size_t8381mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t rbase,8382const mpd_t *src, uint32_t *status)8383{8384MPD_NEW_STATIC(tsrc,0,0,0,0);8385int alloc = 0; /* rdata == NULL */8386size_t n;83878388assert(rbase <= (1U<<16));83898390if (mpd_isspecial(src) || !_mpd_isint(src)) {8391*status |= MPD_Invalid_operation;8392return SIZE_MAX;8393}83948395if (*rdata == NULL) {8396rlen = mpd_sizeinbase(src, rbase);8397if (rlen == SIZE_MAX) {8398*status |= MPD_Invalid_operation;8399return SIZE_MAX;8400}8401*rdata = mpd_alloc(rlen, sizeof **rdata);8402if (*rdata == NULL) {8403goto malloc_error;8404}8405alloc = 1;8406}84078408if (mpd_iszero(src)) {8409**rdata = 0;8410return 1;8411}84128413if (src->exp >= 0) {8414if (!mpd_qshiftl(&tsrc, src, src->exp, status)) {8415goto malloc_error;8416}8417}8418else {8419if (mpd_qshiftr(&tsrc, src, -src->exp, status) == MPD_UINT_MAX) {8420goto malloc_error;8421}8422}84238424n = _baseconv_to_u16(rdata, rlen, rbase, tsrc.data, tsrc.len);8425if (n == SIZE_MAX) {8426goto malloc_error;8427}842884298430out:8431mpd_del(&tsrc);8432return n;84338434malloc_error:8435if (alloc) {8436mpd_free(*rdata);8437*rdata = NULL;8438}8439n = SIZE_MAX;8440*status |= MPD_Malloc_error;8441goto out;8442}84438444/*8445* Convert an integer mpd_t to a multiprecision integer with base<=UINT32_MAX.8446* The least significant word of the result is (*rdata)[0].8447*8448* If rdata is NULL, space is allocated by the function and rlen is irrelevant.8449* In case of an error any allocated storage is freed and rdata is set back to8450* NULL.8451*8452* If rdata is non-NULL, it MUST be allocated by one of libmpdec's allocation8453* functions and rlen MUST be correct. If necessary, the function will resize8454* rdata. In case of an error the caller must free rdata.8455*8456* Return value: In case of success, the exact length of rdata, SIZE_MAX8457* otherwise.8458*/8459size_t8460mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t rbase,8461const mpd_t *src, uint32_t *status)8462{8463MPD_NEW_STATIC(tsrc,0,0,0,0);8464int alloc = 0; /* rdata == NULL */8465size_t n;84668467if (mpd_isspecial(src) || !_mpd_isint(src)) {8468*status |= MPD_Invalid_operation;8469return SIZE_MAX;8470}84718472if (*rdata == NULL) {8473rlen = mpd_sizeinbase(src, rbase);8474if (rlen == SIZE_MAX) {8475*status |= MPD_Invalid_operation;8476return SIZE_MAX;8477}8478*rdata = mpd_alloc(rlen, sizeof **rdata);8479if (*rdata == NULL) {8480goto malloc_error;8481}8482alloc = 1;8483}84848485if (mpd_iszero(src)) {8486**rdata = 0;8487return 1;8488}84898490if (src->exp >= 0) {8491if (!mpd_qshiftl(&tsrc, src, src->exp, status)) {8492goto malloc_error;8493}8494}8495else {8496if (mpd_qshiftr(&tsrc, src, -src->exp, status) == MPD_UINT_MAX) {8497goto malloc_error;8498}8499}85008501#ifdef CONFIG_648502n = _baseconv_to_smaller(rdata, rlen, rbase,8503tsrc.data, tsrc.len, MPD_RADIX);8504#else8505if (rbase == MPD_RADIX) {8506n = _copy_equal_base(rdata, rlen, tsrc.data, tsrc.len);8507}8508else if (rbase < MPD_RADIX) {8509n = _baseconv_to_smaller(rdata, rlen, rbase,8510tsrc.data, tsrc.len, MPD_RADIX);8511}8512else {8513n = _baseconv_to_larger(rdata, rlen, rbase,8514tsrc.data, tsrc.len, MPD_RADIX);8515}8516#endif85178518if (n == SIZE_MAX) {8519goto malloc_error;8520}852185228523out:8524mpd_del(&tsrc);8525return n;85268527malloc_error:8528if (alloc) {8529mpd_free(*rdata);8530*rdata = NULL;8531}8532n = SIZE_MAX;8533*status |= MPD_Malloc_error;8534goto out;8535}853685378538/*8539* Converts a multiprecision integer with base <= UINT16_MAX+1 to an mpd_t.8540* The least significant word of the source is srcdata[0].8541*/8542void8543mpd_qimport_u16(mpd_t *result,8544const uint16_t *srcdata, size_t srclen,8545uint8_t srcsign, uint32_t srcbase,8546const mpd_context_t *ctx, uint32_t *status)8547{8548mpd_uint_t *usrc; /* uint16_t src copied to an mpd_uint_t array */8549mpd_ssize_t rlen; /* length of the result */8550size_t n;85518552assert(srclen > 0);8553assert(srcbase <= (1U<<16));85548555rlen = _mpd_importsize(srclen, srcbase);8556if (rlen == MPD_SSIZE_MAX) {8557mpd_seterror(result, MPD_Invalid_operation, status);8558return;8559}85608561usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc);8562if (usrc == NULL) {8563mpd_seterror(result, MPD_Malloc_error, status);8564return;8565}8566for (n = 0; n < srclen; n++) {8567usrc[n] = srcdata[n];8568}85698570if (!mpd_qresize(result, rlen, status)) {8571goto finish;8572}85738574n = _coeff_from_u16(result, rlen, usrc, srclen, srcbase, status);8575if (n == SIZE_MAX) {8576goto finish;8577}85788579mpd_set_flags(result, srcsign);8580result->exp = 0;8581result->len = n;8582mpd_setdigits(result);85838584mpd_qresize(result, result->len, status);8585mpd_qfinalize(result, ctx, status);858685878588finish:8589mpd_free(usrc);8590}85918592/*8593* Converts a multiprecision integer with base <= UINT32_MAX to an mpd_t.8594* The least significant word of the source is srcdata[0].8595*/8596void8597mpd_qimport_u32(mpd_t *result,8598const uint32_t *srcdata, size_t srclen,8599uint8_t srcsign, uint32_t srcbase,8600const mpd_context_t *ctx, uint32_t *status)8601{8602mpd_ssize_t rlen; /* length of the result */8603size_t n;86048605assert(srclen > 0);86068607rlen = _mpd_importsize(srclen, srcbase);8608if (rlen == MPD_SSIZE_MAX) {8609mpd_seterror(result, MPD_Invalid_operation, status);8610return;8611}86128613if (!mpd_qresize(result, rlen, status)) {8614return;8615}86168617#ifdef CONFIG_648618n = _coeff_from_smaller_base(result, rlen, MPD_RADIX,8619srcdata, srclen, srcbase,8620status);8621#else8622if (srcbase == MPD_RADIX) {8623if (!mpd_qresize(result, srclen, status)) {8624return;8625}8626memcpy(result->data, srcdata, srclen * (sizeof *srcdata));8627n = srclen;8628}8629else if (srcbase < MPD_RADIX) {8630n = _coeff_from_smaller_base(result, rlen, MPD_RADIX,8631srcdata, srclen, srcbase,8632status);8633}8634else {8635mpd_uint_t *usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc);8636if (usrc == NULL) {8637mpd_seterror(result, MPD_Malloc_error, status);8638return;8639}8640for (n = 0; n < srclen; n++) {8641usrc[n] = srcdata[n];8642}86438644n = _coeff_from_larger_base(result, rlen, MPD_RADIX,8645usrc, (mpd_ssize_t)srclen, srcbase,8646status);8647mpd_free(usrc);8648}8649#endif86508651if (n == SIZE_MAX) {8652return;8653}86548655mpd_set_flags(result, srcsign);8656result->exp = 0;8657result->len = n;8658mpd_setdigits(result);86598660mpd_qresize(result, result->len, status);8661mpd_qfinalize(result, ctx, status);8662}866386648665/******************************************************************************/8666/* From triple */8667/******************************************************************************/86688669#if defined(CONFIG_64) && defined(__SIZEOF_INT128__)8670static mpd_ssize_t8671_set_coeff(uint64_t data[3], uint64_t hi, uint64_t lo)8672{8673__uint128_t d = ((__uint128_t)hi << 64) + lo;8674__uint128_t q, r;86758676q = d / MPD_RADIX;8677r = d % MPD_RADIX;8678data[0] = (uint64_t)r;8679d = q;86808681q = d / MPD_RADIX;8682r = d % MPD_RADIX;8683data[1] = (uint64_t)r;8684d = q;86858686q = d / MPD_RADIX;8687r = d % MPD_RADIX;8688data[2] = (uint64_t)r;86898690if (q != 0) {8691abort(); /* GCOV_NOT_REACHED */8692}86938694return data[2] != 0 ? 3 : (data[1] != 0 ? 2 : 1);8695}8696#else8697static size_t8698_uint_from_u16(mpd_uint_t *w, mpd_ssize_t wlen, const uint16_t *u, size_t ulen)8699{8700const mpd_uint_t ubase = 1U<<16;8701mpd_ssize_t n = 0;8702mpd_uint_t carry;87038704assert(wlen > 0 && ulen > 0);87058706w[n++] = u[--ulen];8707while (--ulen != SIZE_MAX) {8708carry = _mpd_shortmul_c(w, w, n, ubase);8709if (carry) {8710if (n >= wlen) {8711abort(); /* GCOV_NOT_REACHED */8712}8713w[n++] = carry;8714}8715carry = _mpd_shortadd(w, n, u[ulen]);8716if (carry) {8717if (n >= wlen) {8718abort(); /* GCOV_NOT_REACHED */8719}8720w[n++] = carry;8721}8722}87238724return n;8725}87268727static mpd_ssize_t8728_set_coeff(mpd_uint_t *data, mpd_ssize_t len, uint64_t hi, uint64_t lo)8729{8730uint16_t u16[8] = {0};87318732u16[7] = (uint16_t)((hi & 0xFFFF000000000000ULL) >> 48);8733u16[6] = (uint16_t)((hi & 0x0000FFFF00000000ULL) >> 32);8734u16[5] = (uint16_t)((hi & 0x00000000FFFF0000ULL) >> 16);8735u16[4] = (uint16_t) (hi & 0x000000000000FFFFULL);87368737u16[3] = (uint16_t)((lo & 0xFFFF000000000000ULL) >> 48);8738u16[2] = (uint16_t)((lo & 0x0000FFFF00000000ULL) >> 32);8739u16[1] = (uint16_t)((lo & 0x00000000FFFF0000ULL) >> 16);8740u16[0] = (uint16_t) (lo & 0x000000000000FFFFULL);87418742return (mpd_ssize_t)_uint_from_u16(data, len, u16, 8);8743}8744#endif87458746static int8747_set_uint128_coeff_exp(mpd_t *result, uint64_t hi, uint64_t lo, mpd_ssize_t exp)8748{8749mpd_uint_t data[5] = {0};8750uint32_t status = 0;8751mpd_ssize_t len;87528753#if defined(CONFIG_64) && defined(__SIZEOF_INT128__)8754len = _set_coeff(data, hi, lo);8755#else8756len = _set_coeff(data, 5, hi, lo);8757#endif87588759if (!mpd_qresize(result, len, &status)) {8760return -1;8761}87628763for (mpd_ssize_t i = 0; i < len; i++) {8764result->data[i] = data[i];8765}87668767result->exp = exp;8768result->len = len;8769mpd_setdigits(result);87708771return 0;8772}87738774int8775mpd_from_uint128_triple(mpd_t *result, const mpd_uint128_triple_t *triple, uint32_t *status)8776{8777static const mpd_context_t maxcontext = {8778.prec=MPD_MAX_PREC,8779.emax=MPD_MAX_EMAX,8780.emin=MPD_MIN_EMIN,8781.round=MPD_ROUND_HALF_EVEN,8782.traps=MPD_Traps,8783.status=0,8784.newtrap=0,8785.clamp=0,8786.allcr=1,8787};8788const enum mpd_triple_class tag = triple->tag;8789const uint8_t sign = triple->sign;8790const uint64_t hi = triple->hi;8791const uint64_t lo = triple->lo;8792mpd_ssize_t exp;87938794#ifdef CONFIG_328795if (triple->exp < MPD_SSIZE_MIN || triple->exp > MPD_SSIZE_MAX) {8796goto conversion_error;8797}8798#endif8799exp = (mpd_ssize_t)triple->exp;88008801switch (tag) {8802case MPD_TRIPLE_QNAN: case MPD_TRIPLE_SNAN: {8803if (sign > 1 || exp != 0) {8804goto conversion_error;8805}88068807const uint8_t flags = tag == MPD_TRIPLE_QNAN ? MPD_NAN : MPD_SNAN;8808mpd_setspecial(result, sign, flags);88098810if (hi == 0 && lo == 0) { /* no payload */8811return 0;8812}88138814if (_set_uint128_coeff_exp(result, hi, lo, exp) < 0) {8815goto malloc_error;8816}88178818return 0;8819}88208821case MPD_TRIPLE_INF: {8822if (sign > 1 || hi != 0 || lo != 0 || exp != 0) {8823goto conversion_error;8824}88258826mpd_setspecial(result, sign, MPD_INF);88278828return 0;8829}88308831case MPD_TRIPLE_NORMAL: {8832if (sign > 1) {8833goto conversion_error;8834}88358836const uint8_t flags = sign ? MPD_NEG : MPD_POS;8837mpd_set_flags(result, flags);88388839if (exp > MPD_EXP_INF) {8840exp = MPD_EXP_INF;8841}8842if (exp == MPD_SSIZE_MIN) {8843exp = MPD_SSIZE_MIN+1;8844}88458846if (_set_uint128_coeff_exp(result, hi, lo, exp) < 0) {8847goto malloc_error;8848}88498850uint32_t workstatus = 0;8851mpd_qfinalize(result, &maxcontext, &workstatus);8852if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {8853goto conversion_error;8854}88558856return 0;8857}88588859default:8860goto conversion_error;8861}88628863conversion_error:8864mpd_seterror(result, MPD_Conversion_syntax, status);8865return -1;88668867malloc_error:8868mpd_seterror(result, MPD_Malloc_error, status);8869return -1;8870}887188728873/******************************************************************************/8874/* As triple */8875/******************************************************************************/88768877#if defined(CONFIG_64) && defined(__SIZEOF_INT128__)8878static void8879_get_coeff(uint64_t *hi, uint64_t *lo, const mpd_t *a)8880{8881__uint128_t u128 = 0;88828883switch (a->len) {8884case 3:8885u128 = a->data[2]; /* fall through */8886case 2:8887u128 = u128 * MPD_RADIX + a->data[1]; /* fall through */8888case 1:8889u128 = u128 * MPD_RADIX + a->data[0];8890break;8891default:8892abort(); /* GCOV_NOT_REACHED */8893}88948895*hi = u128 >> 64;8896*lo = (uint64_t)u128;8897}8898#else8899static size_t8900_uint_to_u16(uint16_t w[8], mpd_uint_t *u, mpd_ssize_t ulen)8901{8902const mpd_uint_t wbase = 1U<<16;8903size_t n = 0;89048905assert(ulen > 0);89068907do {8908if (n >= 8) {8909abort(); /* GCOV_NOT_REACHED */8910}8911w[n++] = (uint16_t)_mpd_shortdiv(u, u, ulen, wbase);8912/* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */8913ulen = _mpd_real_size(u, ulen);89148915} while (u[ulen-1] != 0);89168917return n;8918}89198920static void8921_get_coeff(uint64_t *hi, uint64_t *lo, const mpd_t *a)8922{8923uint16_t u16[8] = {0};8924mpd_uint_t data[5] = {0};89258926switch (a->len) {8927case 5:8928data[4] = a->data[4]; /* fall through */8929case 4:8930data[3] = a->data[3]; /* fall through */8931case 3:8932data[2] = a->data[2]; /* fall through */8933case 2:8934data[1] = a->data[1]; /* fall through */8935case 1:8936data[0] = a->data[0];8937break;8938default:8939abort(); /* GCOV_NOT_REACHED */8940}89418942_uint_to_u16(u16, data, a->len);89438944*hi = (uint64_t)u16[7] << 48;8945*hi |= (uint64_t)u16[6] << 32;8946*hi |= (uint64_t)u16[5] << 16;8947*hi |= (uint64_t)u16[4];89488949*lo = (uint64_t)u16[3] << 48;8950*lo |= (uint64_t)u16[2] << 32;8951*lo |= (uint64_t)u16[1] << 16;8952*lo |= (uint64_t)u16[0];8953}8954#endif89558956static enum mpd_triple_class8957_coeff_as_uint128(uint64_t *hi, uint64_t *lo, const mpd_t *a)8958{8959#ifdef CONFIG_648960static mpd_uint_t uint128_max_data[3] = { 3374607431768211455ULL, 4028236692093846346ULL, 3ULL };8961static const mpd_t uint128_max = { MPD_STATIC|MPD_CONST_DATA, 0, 39, 3, 3, uint128_max_data };8962#else8963static mpd_uint_t uint128_max_data[5] = { 768211455U, 374607431U, 938463463U, 282366920U, 340U };8964static const mpd_t uint128_max = { MPD_STATIC|MPD_CONST_DATA, 0, 39, 5, 5, uint128_max_data };8965#endif8966enum mpd_triple_class ret = MPD_TRIPLE_NORMAL;8967uint32_t status = 0;8968mpd_t coeff;89698970*hi = *lo = 0ULL;89718972if (mpd_isspecial(a)) {8973if (mpd_isinfinite(a)) {8974return MPD_TRIPLE_INF;8975}89768977ret = mpd_isqnan(a) ? MPD_TRIPLE_QNAN : MPD_TRIPLE_SNAN;8978if (a->len == 0) { /* no payload */8979return ret;8980}8981}8982else if (mpd_iszero(a)) {8983return ret;8984}89858986_mpd_copy_shared(&coeff, a);8987mpd_set_flags(&coeff, 0);8988coeff.exp = 0;89898990if (mpd_qcmp(&coeff, &uint128_max, &status) > 0) {8991return MPD_TRIPLE_ERROR;8992}89938994_get_coeff(hi, lo, &coeff);8995return ret;8996}89978998mpd_uint128_triple_t8999mpd_as_uint128_triple(const mpd_t *a)9000{9001mpd_uint128_triple_t triple = { MPD_TRIPLE_ERROR, 0, 0, 0, 0 };90029003triple.tag = _coeff_as_uint128(&triple.hi, &triple.lo, a);9004if (triple.tag == MPD_TRIPLE_ERROR) {9005return triple;9006}90079008triple.sign = !!mpd_isnegative(a);9009if (triple.tag == MPD_TRIPLE_NORMAL) {9010triple.exp = a->exp;9011}90129013return triple;9014}901590169017