LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules/_decimal/libmpdec - mpdecimal.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 3248 0.0 %
Date: 2012-12-17 Functions: 0 261 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2008-2012 Stefan Krah. All rights reserved.
       3             :  *
       4             :  * Redistribution and use in source and binary forms, with or without
       5             :  * modification, are permitted provided that the following conditions
       6             :  * are met:
       7             :  *
       8             :  * 1. Redistributions of source code must retain the above copyright
       9             :  *    notice, this list of conditions and the following disclaimer.
      10             :  *
      11             :  * 2. Redistributions in binary form must reproduce the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer in the
      13             :  *    documentation and/or other materials provided with the distribution.
      14             :  *
      15             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
      16             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      17             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      18             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      19             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      20             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      21             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      22             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      23             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      24             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      25             :  * SUCH DAMAGE.
      26             :  */
      27             : 
      28             : 
      29             : #include "mpdecimal.h"
      30             : #include <stdio.h>
      31             : #include <stdlib.h>
      32             : #include <string.h>
      33             : #include <limits.h>
      34             : #include <math.h>
      35             : #include "basearith.h"
      36             : #include "bits.h"
      37             : #include "convolute.h"
      38             : #include "crt.h"
      39             : #include "memory.h"
      40             : #include "typearith.h"
      41             : #include "umodarith.h"
      42             : 
      43             : #ifdef PPRO
      44             :   #if defined(_MSC_VER)
      45             :     #include <float.h>
      46             :     #pragma fenv_access(on)
      47             :   #elif !defined(__OpenBSD__) && !defined(__NetBSD__)
      48             :     /* C99 */
      49             :     #include <fenv.h>
      50             :     #pragma STDC FENV_ACCESS ON
      51             :   #endif
      52             : #endif
      53             : 
      54             : 
      55             : #if defined(_MSC_VER)
      56             :   #define ALWAYS_INLINE __forceinline
      57             : #elif defined(LEGACY_COMPILER)
      58             :   #define ALWAYS_INLINE
      59             :   #undef inline
      60             :   #define inline
      61             : #else
      62             :   #ifdef TEST_COVERAGE
      63             :     #define ALWAYS_INLINE
      64             :   #else
      65             :     #define ALWAYS_INLINE inline __attribute__ ((always_inline))
      66             :   #endif
      67             : #endif
      68             : 
      69             : 
      70             : #define MPD_NEWTONDIV_CUTOFF 1024L
      71             : 
      72             : #define MPD_NEW_STATIC(name, flags, exp, digits, len) \
      73             :         mpd_uint_t name##_data[MPD_MINALLOC_MAX];                    \
      74             :         mpd_t name = {flags|MPD_STATIC|MPD_STATIC_DATA, exp, digits, \
      75             :                       len, MPD_MINALLOC_MAX, name##_data}
      76             : 
      77             : #define MPD_NEW_CONST(name, flags, exp, digits, len, alloc, initval) \
      78             :         mpd_uint_t name##_data[alloc] = {initval};                   \
      79             :         mpd_t name = {flags|MPD_STATIC|MPD_CONST_DATA, exp, digits,  \
      80             :                       len, alloc, name##_data}
      81             : 
      82             : #define MPD_NEW_SHARED(name, a) \
      83             :         mpd_t name = {(a->flags&~MPD_DATAFLAGS)|MPD_STATIC|MPD_SHARED_DATA, \
      84             :                       a->exp, a->digits, a->len, a->alloc, a->data}
      85             : 
      86             : 
      87             : static mpd_uint_t data_one[1] = {1};
      88             : static mpd_uint_t data_zero[1] = {0};
      89             : static const mpd_t one = {MPD_STATIC|MPD_CONST_DATA, 0, 1, 1, 1, data_one};
      90             : static const mpd_t minus_one = {MPD_NEG|MPD_STATIC|MPD_CONST_DATA, 0, 1, 1, 1,
      91             :                                 data_one};
      92             : static const mpd_t zero = {MPD_STATIC|MPD_CONST_DATA, 0, 1, 1, 1, data_zero};
      93             : 
      94             : static inline void _mpd_check_exp(mpd_t *dec, const mpd_context_t *ctx,
      95             :                                   uint32_t *status);
      96             : static void _settriple(mpd_t *result, uint8_t sign, mpd_uint_t a,
      97             :                        mpd_ssize_t exp);
      98             : static inline mpd_ssize_t _mpd_real_size(mpd_uint_t *data, mpd_ssize_t size);
      99             : 
     100             : static void _mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
     101             :                       const mpd_context_t *ctx, uint32_t *status);
     102             : static inline void _mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
     103             :                              const mpd_context_t *ctx, uint32_t *status);
     104             : static void _mpd_base_ndivmod(mpd_t *q, mpd_t *r, const mpd_t *a,
     105             :                               const mpd_t *b, uint32_t *status);
     106             : static inline void _mpd_qpow_uint(mpd_t *result, const mpd_t *base,
     107             :                                   mpd_uint_t exp, uint8_t resultsign,
     108             :                                   const mpd_context_t *ctx, uint32_t *status);
     109             : 
     110             : mpd_uint_t mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n);
     111             : 
     112             : 
     113             : /******************************************************************************/
     114             : /*                  Performance critical inline functions                     */
     115             : /******************************************************************************/
     116             : 
     117             : #ifdef CONFIG_64
     118             : /* Digits in a word, primarily useful for the most significant word. */
     119             : ALWAYS_INLINE int
     120             : mpd_word_digits(mpd_uint_t word)
     121             : {
     122             :     if (word < mpd_pow10[9]) {
     123             :         if (word < mpd_pow10[4]) {
     124             :             if (word < mpd_pow10[2]) {
     125             :                 return (word < mpd_pow10[1]) ? 1 : 2;
     126             :             }
     127             :             return (word < mpd_pow10[3]) ? 3 : 4;
     128             :         }
     129             :         if (word < mpd_pow10[6]) {
     130             :             return (word < mpd_pow10[5]) ? 5 : 6;
     131             :         }
     132             :         if (word < mpd_pow10[8]) {
     133             :             return (word < mpd_pow10[7]) ? 7 : 8;
     134             :         }
     135             :         return 9;
     136             :     }
     137             :     if (word < mpd_pow10[14]) {
     138             :         if (word < mpd_pow10[11]) {
     139             :             return (word < mpd_pow10[10]) ? 10 : 11;
     140             :         }
     141             :         if (word < mpd_pow10[13]) {
     142             :             return (word < mpd_pow10[12]) ? 12 : 13;
     143             :         }
     144             :         return 14;
     145             :     }
     146             :     if (word < mpd_pow10[18]) {
     147             :         if (word < mpd_pow10[16]) {
     148             :             return (word < mpd_pow10[15]) ? 15 : 16;
     149             :         }
     150             :         return (word < mpd_pow10[17]) ? 17 : 18;
     151             :     }
     152             : 
     153             :     return (word < mpd_pow10[19]) ? 19 : 20;
     154             : }
     155             : #else
     156             : ALWAYS_INLINE int
     157           0 : mpd_word_digits(mpd_uint_t word)
     158             : {
     159           0 :     if (word < mpd_pow10[4]) {
     160           0 :         if (word < mpd_pow10[2]) {
     161           0 :             return (word < mpd_pow10[1]) ? 1 : 2;
     162             :         }
     163           0 :         return (word < mpd_pow10[3]) ? 3 : 4;
     164             :     }
     165           0 :     if (word < mpd_pow10[6]) {
     166           0 :         return (word < mpd_pow10[5]) ? 5 : 6;
     167             :     }
     168           0 :     if (word < mpd_pow10[8]) {
     169           0 :         return (word < mpd_pow10[7]) ? 7 : 8;
     170             :     }
     171             : 
     172           0 :     return (word < mpd_pow10[9]) ? 9 : 10;
     173             : }
     174             : #endif
     175             : 
     176             : 
     177             : /* Adjusted exponent */
     178             : ALWAYS_INLINE mpd_ssize_t
     179           0 : mpd_adjexp(const mpd_t *dec)
     180             : {
     181           0 :     return (dec->exp + dec->digits) - 1;
     182             : }
     183             : 
     184             : /* Etiny */
     185             : ALWAYS_INLINE mpd_ssize_t
     186           0 : mpd_etiny(const mpd_context_t *ctx)
     187             : {
     188           0 :     return ctx->emin - (ctx->prec - 1);
     189             : }
     190             : 
     191             : /* Etop: used for folding down in IEEE clamping */
     192             : ALWAYS_INLINE mpd_ssize_t
     193           0 : mpd_etop(const mpd_context_t *ctx)
     194             : {
     195           0 :     return ctx->emax - (ctx->prec - 1);
     196             : }
     197             : 
     198             : /* Most significant word */
     199             : ALWAYS_INLINE mpd_uint_t
     200           0 : mpd_msword(const mpd_t *dec)
     201             : {
     202             :     assert(dec->len > 0);
     203           0 :     return dec->data[dec->len-1];
     204             : }
     205             : 
     206             : /* Most significant digit of a word */
     207             : inline mpd_uint_t
     208           0 : mpd_msd(mpd_uint_t word)
     209             : {
     210             :     int n;
     211             : 
     212           0 :     n = mpd_word_digits(word);
     213           0 :     return word / mpd_pow10[n-1];
     214             : }
     215             : 
     216             : /* Least significant digit of a word */
     217             : ALWAYS_INLINE mpd_uint_t
     218           0 : mpd_lsd(mpd_uint_t word)
     219             : {
     220           0 :     return word % 10;
     221             : }
     222             : 
     223             : /* Coefficient size needed to store 'digits' */
     224             : ALWAYS_INLINE mpd_ssize_t
     225           0 : mpd_digits_to_size(mpd_ssize_t digits)
     226             : {
     227             :     mpd_ssize_t q, r;
     228             : 
     229           0 :     _mpd_idiv_word(&q, &r, digits, MPD_RDIGITS);
     230           0 :     return (r == 0) ? q : q+1;
     231             : }
     232             : 
     233             : /* Number of digits in the exponent. Not defined for MPD_SSIZE_MIN. */
     234             : inline int
     235           0 : mpd_exp_digits(mpd_ssize_t exp)
     236             : {
     237           0 :     exp = (exp < 0) ? -exp : exp;
     238           0 :     return mpd_word_digits(exp);
     239             : }
     240             : 
     241             : /* Canonical */
     242             : ALWAYS_INLINE int
     243           0 : mpd_iscanonical(const mpd_t *dec UNUSED)
     244             : {
     245           0 :     return 1;
     246             : }
     247             : 
     248             : /* Finite */
     249             : ALWAYS_INLINE int
     250           0 : mpd_isfinite(const mpd_t *dec)
     251             : {
     252           0 :     return !(dec->flags & MPD_SPECIAL);
     253             : }
     254             : 
     255             : /* Infinite */
     256             : ALWAYS_INLINE int
     257           0 : mpd_isinfinite(const mpd_t *dec)
     258             : {
     259           0 :     return dec->flags & MPD_INF;
     260             : }
     261             : 
     262             : /* NaN */
     263             : ALWAYS_INLINE int
     264           0 : mpd_isnan(const mpd_t *dec)
     265             : {
     266           0 :     return dec->flags & (MPD_NAN|MPD_SNAN);
     267             : }
     268             : 
     269             : /* Negative */
     270             : ALWAYS_INLINE int
     271           0 : mpd_isnegative(const mpd_t *dec)
     272             : {
     273           0 :     return dec->flags & MPD_NEG;
     274             : }
     275             : 
     276             : /* Positive */
     277             : ALWAYS_INLINE int
     278           0 : mpd_ispositive(const mpd_t *dec)
     279             : {
     280           0 :     return !(dec->flags & MPD_NEG);
     281             : }
     282             : 
     283             : /* qNaN */
     284             : ALWAYS_INLINE int
     285           0 : mpd_isqnan(const mpd_t *dec)
     286             : {
     287           0 :     return dec->flags & MPD_NAN;
     288             : }
     289             : 
     290             : /* Signed */
     291             : ALWAYS_INLINE int
     292           0 : mpd_issigned(const mpd_t *dec)
     293             : {
     294           0 :     return dec->flags & MPD_NEG;
     295             : }
     296             : 
     297             : /* sNaN */
     298             : ALWAYS_INLINE int
     299           0 : mpd_issnan(const mpd_t *dec)
     300             : {
     301           0 :     return dec->flags & MPD_SNAN;
     302             : }
     303             : 
     304             : /* Special */
     305             : ALWAYS_INLINE int
     306           0 : mpd_isspecial(const mpd_t *dec)
     307             : {
     308           0 :     return dec->flags & MPD_SPECIAL;
     309             : }
     310             : 
     311             : /* Zero */
     312             : ALWAYS_INLINE int
     313           0 : mpd_iszero(const mpd_t *dec)
     314             : {
     315           0 :     return !mpd_isspecial(dec) && mpd_msword(dec) == 0;
     316             : }
     317             : 
     318             : /* Test for zero when specials have been ruled out already */
     319             : ALWAYS_INLINE int
     320           0 : mpd_iszerocoeff(const mpd_t *dec)
     321             : {
     322           0 :     return mpd_msword(dec) == 0;
     323             : }
     324             : 
     325             : /* Normal */
     326             : inline int
     327           0 : mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx)
     328             : {
     329           0 :     if (mpd_isspecial(dec)) return 0;
     330           0 :     if (mpd_iszerocoeff(dec)) return 0;
     331             : 
     332           0 :     return mpd_adjexp(dec) >= ctx->emin;
     333             : }
     334             : 
     335             : /* Subnormal */
     336             : inline int
     337           0 : mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx)
     338             : {
     339           0 :     if (mpd_isspecial(dec)) return 0;
     340           0 :     if (mpd_iszerocoeff(dec)) return 0;
     341             : 
     342           0 :     return mpd_adjexp(dec) < ctx->emin;
     343             : }
     344             : 
     345             : /* Odd word */
     346             : ALWAYS_INLINE int
     347           0 : mpd_isoddword(mpd_uint_t word)
     348             : {
     349           0 :     return word & 1;
     350             : }
     351             : 
     352             : /* Odd coefficient */
     353             : ALWAYS_INLINE int
     354           0 : mpd_isoddcoeff(const mpd_t *dec)
     355             : {
     356           0 :     return mpd_isoddword(dec->data[0]);
     357             : }
     358             : 
     359             : /* 0 if dec is positive, 1 if dec is negative */
     360             : ALWAYS_INLINE uint8_t
     361           0 : mpd_sign(const mpd_t *dec)
     362             : {
     363           0 :     return dec->flags & MPD_NEG;
     364             : }
     365             : 
     366             : /* 1 if dec is positive, -1 if dec is negative */
     367             : ALWAYS_INLINE int
     368           0 : mpd_arith_sign(const mpd_t *dec)
     369             : {
     370           0 :     return 1 - 2 * mpd_isnegative(dec);
     371             : }
     372             : 
     373             : /* Radix */
     374             : ALWAYS_INLINE long
     375           0 : mpd_radix(void)
     376             : {
     377           0 :     return 10;
     378             : }
     379             : 
     380             : /* Dynamic decimal */
     381             : ALWAYS_INLINE int
     382           0 : mpd_isdynamic(mpd_t *dec)
     383             : {
     384           0 :     return !(dec->flags & MPD_STATIC);
     385             : }
     386             : 
     387             : /* Static decimal */
     388             : ALWAYS_INLINE int
     389           0 : mpd_isstatic(mpd_t *dec)
     390             : {
     391           0 :     return dec->flags & MPD_STATIC;
     392             : }
     393             : 
     394             : /* Data of decimal is dynamic */
     395             : ALWAYS_INLINE int
     396           0 : mpd_isdynamic_data(mpd_t *dec)
     397             : {
     398           0 :     return !(dec->flags & MPD_DATAFLAGS);
     399             : }
     400             : 
     401             : /* Data of decimal is static */
     402             : ALWAYS_INLINE int
     403           0 : mpd_isstatic_data(mpd_t *dec)
     404             : {
     405           0 :     return dec->flags & MPD_STATIC_DATA;
     406             : }
     407             : 
     408             : /* Data of decimal is shared */
     409             : ALWAYS_INLINE int
     410           0 : mpd_isshared_data(mpd_t *dec)
     411             : {
     412           0 :     return dec->flags & MPD_SHARED_DATA;
     413             : }
     414             : 
     415             : /* Data of decimal is const */
     416             : ALWAYS_INLINE int
     417           0 : mpd_isconst_data(mpd_t *dec)
     418             : {
     419           0 :     return dec->flags & MPD_CONST_DATA;
     420             : }
     421             : 
     422             : 
     423             : /******************************************************************************/
     424             : /*                         Inline memory handling                             */
     425             : /******************************************************************************/
     426             : 
     427             : /* Fill destination with zeros */
     428             : ALWAYS_INLINE void
     429           0 : mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len)
     430             : {
     431             :     mpd_size_t i;
     432             : 
     433           0 :     for (i = 0; i < len; i++) {
     434           0 :         dest[i] = 0;
     435             :     }
     436           0 : }
     437             : 
     438             : /* Free a decimal */
     439             : ALWAYS_INLINE void
     440           0 : mpd_del(mpd_t *dec)
     441             : {
     442           0 :     if (mpd_isdynamic_data(dec)) {
     443           0 :         mpd_free(dec->data);
     444             :     }
     445           0 :     if (mpd_isdynamic(dec)) {
     446           0 :         mpd_free(dec);
     447             :     }
     448           0 : }
     449             : 
     450             : /*
     451             :  * Resize the coefficient. Existing data up to 'nwords' is left untouched.
     452             :  * Return 1 on success, 0 otherwise.
     453             :  *
     454             :  * Input invariant: MPD_MINALLOC <= result->alloc.
     455             :  *
     456             :  * Case nwords == result->alloc:
     457             :  *     'result' is unchanged. Return 1.
     458             :  *
     459             :  * Case nwords > result->alloc:
     460             :  *   Case realloc success:
     461             :  *     The value of 'result' does not change. Return 1.
     462             :  *   Case realloc failure:
     463             :  *     'result' is NaN, status is updated with MPD_Malloc_error. Return 0.
     464             :  *
     465             :  * Case nwords < result->alloc:
     466             :  *   Case is_static_data or realloc failure [1]:
     467             :  *     'result' is unchanged. Return 1.
     468             :  *   Case realloc success:
     469             :  *     The value of result is undefined (expected). Return 1.
     470             :  *
     471             :  *
     472             :  * [1] In that case the old (now oversized) area is still valid.
     473             :  */
     474             : ALWAYS_INLINE int
     475           0 : mpd_qresize(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
     476             : {
     477             :     assert(!mpd_isconst_data(result)); /* illegal operation for a const */
     478             :     assert(!mpd_isshared_data(result)); /* illegal operation for a shared */
     479             :     assert(MPD_MINALLOC <= result->alloc);
     480             : 
     481           0 :     nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords;
     482           0 :     if (nwords == result->alloc) {
     483           0 :         return 1;
     484             :     }
     485           0 :     if (mpd_isstatic_data(result)) {
     486           0 :         if (nwords > result->alloc) {
     487           0 :             return mpd_switch_to_dyn(result, nwords, status);
     488             :         }
     489           0 :         return 1;
     490             :     }
     491             : 
     492           0 :     return mpd_realloc_dyn(result, nwords, status);
     493             : }
     494             : 
     495             : /* Same as mpd_qresize, but the complete coefficient (including the old
     496             :  * memory area!) is initialized to zero. */
     497             : ALWAYS_INLINE int
     498           0 : mpd_qresize_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
     499             : {
     500             :     assert(!mpd_isconst_data(result)); /* illegal operation for a const */
     501             :     assert(!mpd_isshared_data(result)); /* illegal operation for a shared */
     502             :     assert(MPD_MINALLOC <= result->alloc);
     503             : 
     504           0 :     nwords = (nwords <= MPD_MINALLOC) ? MPD_MINALLOC : nwords;
     505           0 :     if (nwords != result->alloc) {
     506           0 :         if (mpd_isstatic_data(result)) {
     507           0 :             if (nwords > result->alloc) {
     508           0 :                 return mpd_switch_to_dyn_zero(result, nwords, status);
     509             :             }
     510             :         }
     511           0 :         else if (!mpd_realloc_dyn(result, nwords, status)) {
     512           0 :             return 0;
     513             :         }
     514             :     }
     515             : 
     516           0 :     mpd_uint_zero(result->data, nwords);
     517           0 :     return 1;
     518             : }
     519             : 
     520             : /*
     521             :  * Reduce memory size for the coefficient to MPD_MINALLOC. In theory,
     522             :  * realloc may fail even when reducing the memory size. But in that case
     523             :  * the old memory area is always big enough, so checking for MPD_Malloc_error
     524             :  * is not imperative.
     525             :  */
     526             : ALWAYS_INLINE void
     527           0 : mpd_minalloc(mpd_t *result)
     528             : {
     529             :     assert(!mpd_isconst_data(result)); /* illegal operation for a const */
     530             :     assert(!mpd_isshared_data(result)); /* illegal operation for a shared */
     531             : 
     532           0 :     if (!mpd_isstatic_data(result) && result->alloc > MPD_MINALLOC) {
     533           0 :         uint8_t err = 0;
     534           0 :         result->data = mpd_realloc(result->data, MPD_MINALLOC,
     535             :                                    sizeof *result->data, &err);
     536           0 :         if (!err) {
     537           0 :             result->alloc = MPD_MINALLOC;
     538             :         }
     539             :     }
     540           0 : }
     541             : 
     542             : int
     543           0 : mpd_resize(mpd_t *result, mpd_ssize_t nwords, mpd_context_t *ctx)
     544             : {
     545           0 :     uint32_t status = 0;
     546           0 :     if (!mpd_qresize(result, nwords, &status)) {
     547           0 :         mpd_addstatus_raise(ctx, status);
     548           0 :         return 0;
     549             :     }
     550           0 :     return 1;
     551             : }
     552             : 
     553             : int
     554           0 : mpd_resize_zero(mpd_t *result, mpd_ssize_t nwords, mpd_context_t *ctx)
     555             : {
     556           0 :     uint32_t status = 0;
     557           0 :     if (!mpd_qresize_zero(result, nwords, &status)) {
     558           0 :         mpd_addstatus_raise(ctx, status);
     559           0 :         return 0;
     560             :     }
     561           0 :     return 1;
     562             : }
     563             : 
     564             : 
     565             : /******************************************************************************/
     566             : /*                       Set attributes of a decimal                          */
     567             : /******************************************************************************/
     568             : 
     569             : /* Set digits. Assumption: result->len is initialized and > 0. */
     570             : inline void
     571           0 : mpd_setdigits(mpd_t *result)
     572             : {
     573           0 :     mpd_ssize_t wdigits = mpd_word_digits(mpd_msword(result));
     574           0 :     result->digits = wdigits + (result->len-1) * MPD_RDIGITS;
     575           0 : }
     576             : 
     577             : /* Set sign */
     578             : ALWAYS_INLINE void
     579           0 : mpd_set_sign(mpd_t *result, uint8_t sign)
     580             : {
     581           0 :     result->flags &= ~MPD_NEG;
     582           0 :     result->flags |= sign;
     583           0 : }
     584             : 
     585             : /* Copy sign from another decimal */
     586             : ALWAYS_INLINE void
     587           0 : mpd_signcpy(mpd_t *result, mpd_t *a)
     588             : {
     589           0 :     uint8_t sign = a->flags&MPD_NEG;
     590             : 
     591           0 :     result->flags &= ~MPD_NEG;
     592           0 :     result->flags |= sign;
     593           0 : }
     594             : 
     595             : /* Set infinity */
     596             : ALWAYS_INLINE void
     597           0 : mpd_set_infinity(mpd_t *result)
     598             : {
     599           0 :     result->flags &= ~MPD_SPECIAL;
     600           0 :     result->flags |= MPD_INF;
     601           0 : }
     602             : 
     603             : /* Set qNaN */
     604             : ALWAYS_INLINE void
     605           0 : mpd_set_qnan(mpd_t *result)
     606             : {
     607           0 :     result->flags &= ~MPD_SPECIAL;
     608           0 :     result->flags |= MPD_NAN;
     609           0 : }
     610             : 
     611             : /* Set sNaN */
     612             : ALWAYS_INLINE void
     613           0 : mpd_set_snan(mpd_t *result)
     614             : {
     615           0 :     result->flags &= ~MPD_SPECIAL;
     616           0 :     result->flags |= MPD_SNAN;
     617           0 : }
     618             : 
     619             : /* Set to negative */
     620             : ALWAYS_INLINE void
     621           0 : mpd_set_negative(mpd_t *result)
     622             : {
     623           0 :     result->flags |= MPD_NEG;
     624           0 : }
     625             : 
     626             : /* Set to positive */
     627             : ALWAYS_INLINE void
     628           0 : mpd_set_positive(mpd_t *result)
     629             : {
     630           0 :     result->flags &= ~MPD_NEG;
     631           0 : }
     632             : 
     633             : /* Set to dynamic */
     634             : ALWAYS_INLINE void
     635           0 : mpd_set_dynamic(mpd_t *result)
     636             : {
     637           0 :     result->flags &= ~MPD_STATIC;
     638           0 : }
     639             : 
     640             : /* Set to static */
     641             : ALWAYS_INLINE void
     642           0 : mpd_set_static(mpd_t *result)
     643             : {
     644           0 :     result->flags |= MPD_STATIC;
     645           0 : }
     646             : 
     647             : /* Set data to dynamic */
     648             : ALWAYS_INLINE void
     649           0 : mpd_set_dynamic_data(mpd_t *result)
     650             : {
     651           0 :     result->flags &= ~MPD_DATAFLAGS;
     652           0 : }
     653             : 
     654             : /* Set data to static */
     655             : ALWAYS_INLINE void
     656           0 : mpd_set_static_data(mpd_t *result)
     657             : {
     658           0 :     result->flags &= ~MPD_DATAFLAGS;
     659           0 :     result->flags |= MPD_STATIC_DATA;
     660           0 : }
     661             : 
     662             : /* Set data to shared */
     663             : ALWAYS_INLINE void
     664           0 : mpd_set_shared_data(mpd_t *result)
     665             : {
     666           0 :     result->flags &= ~MPD_DATAFLAGS;
     667           0 :     result->flags |= MPD_SHARED_DATA;
     668           0 : }
     669             : 
     670             : /* Set data to const */
     671             : ALWAYS_INLINE void
     672           0 : mpd_set_const_data(mpd_t *result)
     673             : {
     674           0 :     result->flags &= ~MPD_DATAFLAGS;
     675           0 :     result->flags |= MPD_CONST_DATA;
     676           0 : }
     677             : 
     678             : /* Clear flags, preserving memory attributes. */
     679             : ALWAYS_INLINE void
     680           0 : mpd_clear_flags(mpd_t *result)
     681             : {
     682           0 :     result->flags &= (MPD_STATIC|MPD_DATAFLAGS);
     683           0 : }
     684             : 
     685             : /* Set flags, preserving memory attributes. */
     686             : ALWAYS_INLINE void
     687           0 : mpd_set_flags(mpd_t *result, uint8_t flags)
     688             : {
     689           0 :     result->flags &= (MPD_STATIC|MPD_DATAFLAGS);
     690           0 :     result->flags |= flags;
     691           0 : }
     692             : 
     693             : /* Copy flags, preserving memory attributes of result. */
     694             : ALWAYS_INLINE void
     695           0 : mpd_copy_flags(mpd_t *result, const mpd_t *a)
     696             : {
     697           0 :     uint8_t aflags = a->flags;
     698           0 :     result->flags &= (MPD_STATIC|MPD_DATAFLAGS);
     699           0 :     result->flags |= (aflags & ~(MPD_STATIC|MPD_DATAFLAGS));
     700           0 : }
     701             : 
     702             : /* Initialize a workcontext from ctx. Set traps, flags and newtrap to 0. */
     703             : static inline void
     704           0 : mpd_workcontext(mpd_context_t *workctx, const mpd_context_t *ctx)
     705             : {
     706           0 :     workctx->prec = ctx->prec;
     707           0 :     workctx->emax = ctx->emax;
     708           0 :     workctx->emin = ctx->emin;
     709           0 :     workctx->round = ctx->round;
     710           0 :     workctx->traps = 0;
     711           0 :     workctx->status = 0;
     712           0 :     workctx->newtrap = 0;
     713           0 :     workctx->clamp = ctx->clamp;
     714           0 :     workctx->allcr = ctx->allcr;
     715           0 : }
     716             : 
     717             : 
     718             : /******************************************************************************/
     719             : /*                  Getting and setting parts of decimals                     */
     720             : /******************************************************************************/
     721             : 
     722             : /* Flip the sign of a decimal */
     723             : static inline void
     724           0 : _mpd_negate(mpd_t *dec)
     725             : {
     726           0 :     dec->flags ^= MPD_NEG;
     727           0 : }
     728             : 
     729             : /* Set coefficient to zero */
     730             : void
     731           0 : mpd_zerocoeff(mpd_t *result)
     732             : {
     733             :     mpd_minalloc(result);
     734           0 :     result->digits = 1;
     735           0 :     result->len = 1;
     736           0 :     result->data[0] = 0;
     737           0 : }
     738             : 
     739             : /* Set the coefficient to all nines. */
     740             : void
     741           0 : mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)
     742             : {
     743             :     mpd_ssize_t len, r;
     744             : 
     745           0 :     _mpd_idiv_word(&len, &r, ctx->prec, MPD_RDIGITS);
     746           0 :     len = (r == 0) ? len : len+1;
     747             : 
     748           0 :     if (!mpd_qresize(result, len, status)) {
     749           0 :         return;
     750             :     }
     751             : 
     752           0 :     result->len = len;
     753           0 :     result->digits = ctx->prec;
     754             : 
     755           0 :     --len;
     756           0 :     if (r > 0) {
     757           0 :         result->data[len--] = mpd_pow10[r]-1;
     758             :     }
     759           0 :     for (; len >= 0; --len) {
     760           0 :         result->data[len] = MPD_RADIX-1;
     761             :     }
     762             : }
     763             : 
     764             : /*
     765             :  * Cut off the most significant digits so that the rest fits in ctx->prec.
     766             :  * Cannot fail.
     767             :  */
     768             : static void
     769           0 : _mpd_cap(mpd_t *result, const mpd_context_t *ctx)
     770             : {
     771             :     uint32_t dummy;
     772             :     mpd_ssize_t len, r;
     773             : 
     774           0 :     if (result->len > 0 && result->digits > ctx->prec) {
     775           0 :         _mpd_idiv_word(&len, &r, ctx->prec, MPD_RDIGITS);
     776           0 :         len = (r == 0) ? len : len+1;
     777             : 
     778           0 :         if (r != 0) {
     779           0 :             result->data[len-1] %= mpd_pow10[r];
     780             :         }
     781             : 
     782           0 :         len = _mpd_real_size(result->data, len);
     783             :         /* resize to fewer words cannot fail */
     784           0 :         mpd_qresize(result, len, &dummy);
     785           0 :         result->len = len;
     786           0 :         mpd_setdigits(result);
     787             :     }
     788           0 :     if (mpd_iszero(result)) {
     789           0 :         _settriple(result, mpd_sign(result), 0, result->exp);
     790             :     }
     791           0 : }
     792             : 
     793             : /*
     794             :  * Cut off the most significant digits of a NaN payload so that the rest
     795             :  * fits in ctx->prec - ctx->clamp. Cannot fail.
     796             :  */
     797             : static void
     798           0 : _mpd_fix_nan(mpd_t *result, const mpd_context_t *ctx)
     799             : {
     800             :     uint32_t dummy;
     801             :     mpd_ssize_t prec;
     802             :     mpd_ssize_t len, r;
     803             : 
     804           0 :     prec = ctx->prec - ctx->clamp;
     805           0 :     if (result->len > 0 && result->digits > prec) {
     806           0 :         if (prec == 0) {
     807             :             mpd_minalloc(result);
     808           0 :             result->len = result->digits = 0;
     809             :         }
     810             :         else {
     811           0 :             _mpd_idiv_word(&len, &r, prec, MPD_RDIGITS);
     812           0 :             len = (r == 0) ? len : len+1;
     813             : 
     814           0 :             if (r != 0) {
     815           0 :                  result->data[len-1] %= mpd_pow10[r];
     816             :             }
     817             : 
     818           0 :             len = _mpd_real_size(result->data, len);
     819             :             /* resize to fewer words cannot fail */
     820           0 :             mpd_qresize(result, len, &dummy);
     821           0 :             result->len = len;
     822           0 :             mpd_setdigits(result);
     823           0 :             if (mpd_iszerocoeff(result)) {
     824             :                 /* NaN0 is not a valid representation */
     825           0 :                 result->len = result->digits = 0;
     826             :             }
     827             :         }
     828             :     }
     829           0 : }
     830             : 
     831             : /*
     832             :  * Get n most significant digits from a decimal, where 0 < n <= MPD_UINT_DIGITS.
     833             :  * Assumes MPD_UINT_DIGITS == MPD_RDIGITS+1, which is true for 32 and 64 bit
     834             :  * machines.
     835             :  *
     836             :  * The result of the operation will be in lo. If the operation is impossible,
     837             :  * hi will be nonzero. This is used to indicate an error.
     838             :  */
     839             : static inline void
     840           0 : _mpd_get_msdigits(mpd_uint_t *hi, mpd_uint_t *lo, const mpd_t *dec,
     841             :                   unsigned int n)
     842             : {
     843             :     mpd_uint_t r, tmp;
     844             : 
     845             :     assert(0 < n && n <= MPD_RDIGITS+1);
     846             : 
     847           0 :     _mpd_div_word(&tmp, &r, dec->digits, MPD_RDIGITS);
     848           0 :     r = (r == 0) ? MPD_RDIGITS : r; /* digits in the most significant word */
     849             : 
     850           0 :     *hi = 0;
     851           0 :     *lo = dec->data[dec->len-1];
     852           0 :     if (n <= r) {
     853           0 :         *lo /= mpd_pow10[r-n];
     854             :     }
     855           0 :     else if (dec->len > 1) {
     856             :         /* at this point 1 <= r < n <= MPD_RDIGITS+1 */
     857           0 :         _mpd_mul_words(hi, lo, *lo, mpd_pow10[n-r]);
     858           0 :         tmp = dec->data[dec->len-2] / mpd_pow10[MPD_RDIGITS-(n-r)];
     859           0 :         *lo = *lo + tmp;
     860           0 :         if (*lo < tmp) (*hi)++;
     861             :     }
     862           0 : }
     863             : 
     864             : 
     865             : /******************************************************************************/
     866             : /*                   Gathering information about a decimal                    */
     867             : /******************************************************************************/
     868             : 
     869             : /* The real size of the coefficient without leading zero words. */
     870             : static inline mpd_ssize_t
     871           0 : _mpd_real_size(mpd_uint_t *data, mpd_ssize_t size)
     872             : {
     873           0 :     while (size > 1 && data[size-1] == 0) {
     874           0 :         size--;
     875             :     }
     876             : 
     877           0 :     return size;
     878             : }
     879             : 
     880             : /* Return number of trailing zeros. No errors are possible. */
     881             : mpd_ssize_t
     882           0 : mpd_trail_zeros(const mpd_t *dec)
     883             : {
     884             :     mpd_uint_t word;
     885           0 :     mpd_ssize_t i, tz = 0;
     886             : 
     887           0 :     for (i=0; i < dec->len; ++i) {
     888           0 :         if (dec->data[i] != 0) {
     889           0 :             word = dec->data[i];
     890           0 :             tz = i * MPD_RDIGITS;
     891           0 :             while (word % 10 == 0) {
     892           0 :                 word /= 10;
     893           0 :                 tz++;
     894             :             }
     895           0 :             break;
     896             :         }
     897             :     }
     898             : 
     899           0 :     return tz;
     900             : }
     901             : 
     902             : /* Integer: Undefined for specials */
     903             : static int
     904           0 : _mpd_isint(const mpd_t *dec)
     905             : {
     906             :     mpd_ssize_t tz;
     907             : 
     908           0 :     if (mpd_iszerocoeff(dec)) {
     909           0 :         return 1;
     910             :     }
     911             : 
     912           0 :     tz = mpd_trail_zeros(dec);
     913           0 :     return (dec->exp + tz >= 0);
     914             : }
     915             : 
     916             : /* Integer */
     917             : int
     918           0 : mpd_isinteger(const mpd_t *dec)
     919             : {
     920           0 :     if (mpd_isspecial(dec)) {
     921           0 :         return 0;
     922             :     }
     923           0 :     return _mpd_isint(dec);
     924             : }
     925             : 
     926             : /* Word is a power of 10 */
     927             : static int
     928           0 : mpd_word_ispow10(mpd_uint_t word)
     929             : {
     930             :     int n;
     931             : 
     932           0 :     n = mpd_word_digits(word);
     933           0 :     if (word == mpd_pow10[n-1]) {
     934           0 :         return 1;
     935             :     }
     936             : 
     937           0 :     return 0;
     938             : }
     939             : 
     940             : /* Coefficient is a power of 10 */
     941             : static int
     942           0 : mpd_coeff_ispow10(const mpd_t *dec)
     943             : {
     944           0 :     if (mpd_word_ispow10(mpd_msword(dec))) {
     945           0 :         if (_mpd_isallzero(dec->data, dec->len-1)) {
     946           0 :             return 1;
     947             :         }
     948             :     }
     949             : 
     950           0 :     return 0;
     951             : }
     952             : 
     953             : /* All digits of a word are nines */
     954             : static int
     955           0 : mpd_word_isallnine(mpd_uint_t word)
     956             : {
     957             :     int n;
     958             : 
     959           0 :     n = mpd_word_digits(word);
     960           0 :     if (word == mpd_pow10[n]-1) {
     961           0 :         return 1;
     962             :     }
     963             : 
     964           0 :     return 0;
     965             : }
     966             : 
     967             : /* All digits of the coefficient are nines */
     968             : static int
     969           0 : mpd_coeff_isallnine(const mpd_t *dec)
     970             : {
     971           0 :     if (mpd_word_isallnine(mpd_msword(dec))) {
     972           0 :         if (_mpd_isallnine(dec->data, dec->len-1)) {
     973           0 :             return 1;
     974             :         }
     975             :     }
     976             : 
     977           0 :     return 0;
     978             : }
     979             : 
     980             : /* Odd decimal: Undefined for non-integers! */
     981             : int
     982           0 : mpd_isodd(const mpd_t *dec)
     983             : {
     984             :     mpd_uint_t q, r;
     985             :     assert(mpd_isinteger(dec));
     986           0 :     if (mpd_iszerocoeff(dec)) return 0;
     987           0 :     if (dec->exp < 0) {
     988           0 :         _mpd_div_word(&q, &r, -dec->exp, MPD_RDIGITS);
     989           0 :         q = dec->data[q] / mpd_pow10[r];
     990           0 :         return mpd_isoddword(q);
     991             :     }
     992           0 :     return dec->exp == 0 && mpd_isoddword(dec->data[0]);
     993             : }
     994             : 
     995             : /* Even: Undefined for non-integers! */
     996             : int
     997           0 : mpd_iseven(const mpd_t *dec)
     998             : {
     999           0 :     return !mpd_isodd(dec);
    1000             : }
    1001             : 
    1002             : /******************************************************************************/
    1003             : /*                      Getting and setting decimals                          */
    1004             : /******************************************************************************/
    1005             : 
    1006             : /* Internal function: Set a static decimal from a triple, no error checking. */
    1007             : static void
    1008           0 : _ssettriple(mpd_t *result, uint8_t sign, mpd_uint_t a, mpd_ssize_t exp)
    1009             : {
    1010           0 :     mpd_set_flags(result, sign);
    1011           0 :     result->exp = exp;
    1012           0 :     _mpd_div_word(&result->data[1], &result->data[0], a, MPD_RADIX);
    1013           0 :     result->len = (result->data[1] == 0) ? 1 : 2;
    1014           0 :     mpd_setdigits(result);
    1015           0 : }
    1016             : 
    1017             : /* Internal function: Set a decimal from a triple, no error checking. */
    1018             : static void
    1019           0 : _settriple(mpd_t *result, uint8_t sign, mpd_uint_t a, mpd_ssize_t exp)
    1020             : {
    1021             :     mpd_minalloc(result);
    1022           0 :     mpd_set_flags(result, sign);
    1023           0 :     result->exp = exp;
    1024           0 :     _mpd_div_word(&result->data[1], &result->data[0], a, MPD_RADIX);
    1025           0 :     result->len = (result->data[1] == 0) ? 1 : 2;
    1026           0 :     mpd_setdigits(result);
    1027           0 : }
    1028             : 
    1029             : /* Set a special number from a triple */
    1030             : void
    1031           0 : mpd_setspecial(mpd_t *result, uint8_t sign, uint8_t type)
    1032             : {
    1033             :     mpd_minalloc(result);
    1034           0 :     result->flags &= ~(MPD_NEG|MPD_SPECIAL);
    1035           0 :     result->flags |= (sign|type);
    1036           0 :     result->exp = result->digits = result->len = 0;
    1037           0 : }
    1038             : 
    1039             : /* Set result of NaN with an error status */
    1040             : void
    1041           0 : mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status)
    1042             : {
    1043             :     mpd_minalloc(result);
    1044             :     mpd_set_qnan(result);
    1045             :     mpd_set_positive(result);
    1046           0 :     result->exp = result->digits = result->len = 0;
    1047           0 :     *status |= flags;
    1048           0 : }
    1049             : 
    1050             : /* quietly set a static decimal from an mpd_ssize_t */
    1051             : void
    1052           0 : mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx,
    1053             :                 uint32_t *status)
    1054             : {
    1055             :     mpd_uint_t u;
    1056           0 :     uint8_t sign = MPD_POS;
    1057             : 
    1058           0 :     if (a < 0) {
    1059           0 :         if (a == MPD_SSIZE_MIN) {
    1060           0 :             u = (mpd_uint_t)MPD_SSIZE_MAX +
    1061             :                 (-(MPD_SSIZE_MIN+MPD_SSIZE_MAX));
    1062             :         }
    1063             :         else {
    1064           0 :             u = -a;
    1065             :         }
    1066           0 :         sign = MPD_NEG;
    1067             :     }
    1068             :     else {
    1069           0 :         u = a;
    1070             :     }
    1071           0 :     _ssettriple(result, sign, u, 0);
    1072           0 :     mpd_qfinalize(result, ctx, status);
    1073           0 : }
    1074             : 
    1075             : /* quietly set a static decimal from an mpd_uint_t */
    1076             : void
    1077           0 : mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx,
    1078             :                uint32_t *status)
    1079             : {
    1080           0 :     _ssettriple(result, MPD_POS, a, 0);
    1081           0 :     mpd_qfinalize(result, ctx, status);
    1082           0 : }
    1083             : 
    1084             : /* quietly set a static decimal from an int32_t */
    1085             : void
    1086           0 : mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx,
    1087             :               uint32_t *status)
    1088             : {
    1089           0 :     mpd_qsset_ssize(result, a, ctx, status);
    1090           0 : }
    1091             : 
    1092             : /* quietly set a static decimal from a uint32_t */
    1093             : void
    1094           0 : mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx,
    1095             :               uint32_t *status)
    1096             : {
    1097           0 :     mpd_qsset_uint(result, a, ctx, status);
    1098           0 : }
    1099             : 
    1100             : #ifdef CONFIG_64
    1101             : /* quietly set a static decimal from an int64_t */
    1102             : void
    1103             : mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,
    1104             :               uint32_t *status)
    1105             : {
    1106             :     mpd_qsset_ssize(result, a, ctx, status);
    1107             : }
    1108             : 
    1109             : /* quietly set a static decimal from a uint64_t */
    1110             : void
    1111             : mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,
    1112             :               uint32_t *status)
    1113             : {
    1114             :     mpd_qsset_uint(result, a, ctx, status);
    1115             : }
    1116             : #endif
    1117             : 
    1118             : /* quietly set a decimal from an mpd_ssize_t */
    1119             : void
    1120           0 : mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx,
    1121             :                uint32_t *status)
    1122             : {
    1123             :     mpd_minalloc(result);
    1124           0 :     mpd_qsset_ssize(result, a, ctx, status);
    1125           0 : }
    1126             : 
    1127             : /* quietly set a decimal from an mpd_uint_t */
    1128             : void
    1129           0 : mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx,
    1130             :               uint32_t *status)
    1131             : {
    1132           0 :     _settriple(result, MPD_POS, a, 0);
    1133           0 :     mpd_qfinalize(result, ctx, status);
    1134           0 : }
    1135             : 
    1136             : /* quietly set a decimal from an int32_t */
    1137             : void
    1138           0 : mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx,
    1139             :              uint32_t *status)
    1140             : {
    1141           0 :     mpd_qset_ssize(result, a, ctx, status);
    1142           0 : }
    1143             : 
    1144             : /* quietly set a decimal from a uint32_t */
    1145             : void
    1146           0 : mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx,
    1147             :              uint32_t *status)
    1148             : {
    1149           0 :     mpd_qset_uint(result, a, ctx, status);
    1150           0 : }
    1151             : 
    1152             : #if defined(CONFIG_32) && !defined(LEGACY_COMPILER)
    1153             : /* set a decimal from a uint64_t */
    1154             : static void
    1155           0 : _c32setu64(mpd_t *result, uint64_t u, uint8_t sign, uint32_t *status)
    1156             : {
    1157             :     mpd_uint_t w[3];
    1158             :     uint64_t q;
    1159             :     int i, len;
    1160             : 
    1161           0 :     len = 0;
    1162             :     do {
    1163           0 :         q = u / MPD_RADIX;
    1164           0 :         w[len] = (mpd_uint_t)(u - q * MPD_RADIX);
    1165           0 :         u = q; len++;
    1166           0 :     } while (u != 0);
    1167             : 
    1168           0 :     if (!mpd_qresize(result, len, status)) {
    1169           0 :         return;
    1170             :     }
    1171           0 :     for (i = 0; i < len; i++) {
    1172           0 :         result->data[i] = w[i];
    1173             :     }
    1174             : 
    1175           0 :     mpd_set_sign(result, sign);
    1176           0 :     result->exp = 0;
    1177           0 :     result->len = len;
    1178           0 :     mpd_setdigits(result);
    1179             : }
    1180             : 
    1181             : static void
    1182           0 : _c32_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,
    1183             :               uint32_t *status)
    1184             : {
    1185           0 :     _c32setu64(result, a, MPD_POS, status);
    1186           0 :     mpd_qfinalize(result, ctx, status);
    1187           0 : }
    1188             : 
    1189             : /* set a decimal from an int64_t */
    1190             : static void
    1191           0 : _c32_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,
    1192             :               uint32_t *status)
    1193             : {
    1194             :     uint64_t u;
    1195           0 :     uint8_t sign = MPD_POS;
    1196             : 
    1197           0 :     if (a < 0) {
    1198           0 :         if (a == INT64_MIN) {
    1199           0 :             u = (uint64_t)INT64_MAX + (-(INT64_MIN+INT64_MAX));
    1200             :         }
    1201             :         else {
    1202           0 :             u = -a;
    1203             :         }
    1204           0 :         sign = MPD_NEG;
    1205             :     }
    1206             :     else {
    1207           0 :         u = a;
    1208             :     }
    1209           0 :     _c32setu64(result, u, sign, status);
    1210           0 :     mpd_qfinalize(result, ctx, status);
    1211           0 : }
    1212             : #endif /* CONFIG_32 && !LEGACY_COMPILER */
    1213             : 
    1214             : #ifndef LEGACY_COMPILER
    1215             : /* quietly set a decimal from an int64_t */
    1216             : void
    1217           0 : mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx,
    1218             :              uint32_t *status)
    1219             : {
    1220             : #ifdef CONFIG_64
    1221             :     mpd_qset_ssize(result, a, ctx, status);
    1222             : #else
    1223           0 :     _c32_qset_i64(result, a, ctx, status);
    1224             : #endif
    1225           0 : }
    1226             : 
    1227             : /* quietly set a decimal from a uint64_t */
    1228             : void
    1229           0 : mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx,
    1230             :              uint32_t *status)
    1231             : {
    1232             : #ifdef CONFIG_64
    1233             :     mpd_qset_uint(result, a, ctx, status);
    1234             : #else
    1235           0 :     _c32_qset_u64(result, a, ctx, status);
    1236             : #endif
    1237           0 : }
    1238             : #endif /* !LEGACY_COMPILER */
    1239             : 
    1240             : 
    1241             : /*
    1242             :  * Quietly get an mpd_uint_t from a decimal. Assumes
    1243             :  * MPD_UINT_DIGITS == MPD_RDIGITS+1, which is true for
    1244             :  * 32 and 64 bit machines.
    1245             :  *
    1246             :  * If the operation is impossible, MPD_Invalid_operation is set.
    1247             :  */
    1248             : static mpd_uint_t
    1249           0 : _mpd_qget_uint(int use_sign, const mpd_t *a, uint32_t *status)
    1250             : {
    1251             :     mpd_t tmp;
    1252             :     mpd_uint_t tmp_data[2];
    1253             :     mpd_uint_t lo, hi;
    1254             : 
    1255           0 :     if (mpd_isspecial(a)) {
    1256           0 :         *status |= MPD_Invalid_operation;
    1257           0 :         return MPD_UINT_MAX;
    1258             :     }
    1259           0 :     if (mpd_iszero(a)) {
    1260           0 :         return 0;
    1261             :     }
    1262           0 :     if (use_sign && mpd_isnegative(a)) {
    1263           0 :         *status |= MPD_Invalid_operation;
    1264           0 :         return MPD_UINT_MAX;
    1265             :     }
    1266             : 
    1267           0 :     if (a->digits+a->exp > MPD_RDIGITS+1) {
    1268           0 :         *status |= MPD_Invalid_operation;
    1269           0 :         return MPD_UINT_MAX;
    1270             :     }
    1271             : 
    1272           0 :     if (a->exp < 0) {
    1273           0 :         if (!_mpd_isint(a)) {
    1274           0 :             *status |= MPD_Invalid_operation;
    1275           0 :             return MPD_UINT_MAX;
    1276             :         }
    1277             :         /* At this point a->digits+a->exp <= MPD_RDIGITS+1,
    1278             :          * so the shift fits. */
    1279           0 :         tmp.data = tmp_data;
    1280           0 :         tmp.flags = MPD_STATIC|MPD_STATIC_DATA;
    1281           0 :         tmp.alloc = 2;
    1282           0 :         mpd_qsshiftr(&tmp, a, -a->exp);
    1283           0 :         tmp.exp = 0;
    1284           0 :         a = &tmp;
    1285             :     }
    1286             : 
    1287           0 :     _mpd_get_msdigits(&hi, &lo, a, MPD_RDIGITS+1);
    1288           0 :     if (hi) {
    1289           0 :         *status |= MPD_Invalid_operation;
    1290           0 :         return MPD_UINT_MAX;
    1291             :     }
    1292             : 
    1293           0 :     if (a->exp > 0) {
    1294           0 :         _mpd_mul_words(&hi, &lo, lo, mpd_pow10[a->exp]);
    1295           0 :         if (hi) {
    1296           0 :             *status |= MPD_Invalid_operation;
    1297           0 :             return MPD_UINT_MAX;
    1298             :         }
    1299             :     }
    1300             : 
    1301           0 :     return lo;
    1302             : }
    1303             : 
    1304             : /*
    1305             :  * Sets Invalid_operation for:
    1306             :  *   - specials
    1307             :  *   - negative numbers (except negative zero)
    1308             :  *   - non-integers
    1309             :  *   - overflow
    1310             :  */
    1311             : mpd_uint_t
    1312           0 : mpd_qget_uint(const mpd_t *a, uint32_t *status)
    1313             : {
    1314           0 :     return _mpd_qget_uint(1, a, status);
    1315             : }
    1316             : 
    1317             : /* Same as above, but gets the absolute value, i.e. the sign is ignored. */
    1318             : mpd_uint_t
    1319           0 : mpd_qabs_uint(const mpd_t *a, uint32_t *status)
    1320             : {
    1321           0 :     return _mpd_qget_uint(0, a, status);
    1322             : }
    1323             : 
    1324             : /* quietly get an mpd_ssize_t from a decimal */
    1325             : mpd_ssize_t
    1326           0 : mpd_qget_ssize(const mpd_t *a, uint32_t *status)
    1327             : {
    1328             :     mpd_uint_t u;
    1329             :     int isneg;
    1330             : 
    1331           0 :     u = mpd_qabs_uint(a, status);
    1332           0 :     if (*status&MPD_Invalid_operation) {
    1333           0 :         return MPD_SSIZE_MAX;
    1334             :     }
    1335             : 
    1336           0 :     isneg = mpd_isnegative(a);
    1337           0 :     if (u <= MPD_SSIZE_MAX) {
    1338           0 :         return isneg ? -((mpd_ssize_t)u) : (mpd_ssize_t)u;
    1339             :     }
    1340           0 :     else if (isneg && u+(MPD_SSIZE_MIN+MPD_SSIZE_MAX) == MPD_SSIZE_MAX) {
    1341           0 :         return MPD_SSIZE_MIN;
    1342             :     }
    1343             : 
    1344           0 :     *status |= MPD_Invalid_operation;
    1345           0 :     return MPD_SSIZE_MAX;
    1346             : }
    1347             : 
    1348             : #ifdef CONFIG_64
    1349             : /* quietly get a uint64_t from a decimal */
    1350             : uint64_t
    1351             : mpd_qget_u64(const mpd_t *a, uint32_t *status)
    1352             : {
    1353             :     return mpd_qget_uint(a, status);
    1354             : }
    1355             : 
    1356             : /* quietly get an int64_t from a decimal */
    1357             : int64_t
    1358             : mpd_qget_i64(const mpd_t *a, uint32_t *status)
    1359             : {
    1360             :     return mpd_qget_ssize(a, status);
    1361             : }
    1362             : #else
    1363             : /* quietly get a uint32_t from a decimal */
    1364             : uint32_t
    1365           0 : mpd_qget_u32(const mpd_t *a, uint32_t *status)
    1366             : {
    1367           0 :     return mpd_qget_uint(a, status);
    1368             : }
    1369             : 
    1370             : /* quietly get an int32_t from a decimal */
    1371             : int32_t
    1372           0 : mpd_qget_i32(const mpd_t *a, uint32_t *status)
    1373             : {
    1374           0 :     return mpd_qget_ssize(a, status);
    1375             : }
    1376             : #endif
    1377             : 
    1378             : 
    1379             : /******************************************************************************/
    1380             : /*         Filtering input of functions, finalizing output of functions       */
    1381             : /******************************************************************************/
    1382             : 
    1383             : /*
    1384             :  * Check if the operand is NaN, copy to result and return 1 if this is
    1385             :  * the case. Copying can fail since NaNs are allowed to have a payload that
    1386             :  * does not fit in MPD_MINALLOC.
    1387             :  */
    1388             : int
    1389           0 : mpd_qcheck_nan(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    1390             :                uint32_t *status)
    1391             : {
    1392           0 :     if (mpd_isnan(a)) {
    1393           0 :         *status |= mpd_issnan(a) ? MPD_Invalid_operation : 0;
    1394           0 :         mpd_qcopy(result, a, status);
    1395             :         mpd_set_qnan(result);
    1396           0 :         _mpd_fix_nan(result, ctx);
    1397           0 :         return 1;
    1398             :     }
    1399           0 :     return 0;
    1400             : }
    1401             : 
    1402             : /*
    1403             :  * Check if either operand is NaN, copy to result and return 1 if this
    1404             :  * is the case. Copying can fail since NaNs are allowed to have a payload
    1405             :  * that does not fit in MPD_MINALLOC.
    1406             :  */
    1407             : int
    1408           0 : mpd_qcheck_nans(mpd_t *result, const mpd_t *a, const mpd_t *b,
    1409             :                 const mpd_context_t *ctx, uint32_t *status)
    1410             : {
    1411           0 :     if ((a->flags|b->flags)&(MPD_NAN|MPD_SNAN)) {
    1412           0 :         const mpd_t *choice = b;
    1413           0 :         if (mpd_issnan(a)) {
    1414           0 :             choice = a;
    1415           0 :             *status |= MPD_Invalid_operation;
    1416             :         }
    1417           0 :         else if (mpd_issnan(b)) {
    1418           0 :             *status |= MPD_Invalid_operation;
    1419             :         }
    1420           0 :         else if (mpd_isqnan(a)) {
    1421           0 :             choice = a;
    1422             :         }
    1423           0 :         mpd_qcopy(result, choice, status);
    1424             :         mpd_set_qnan(result);
    1425           0 :         _mpd_fix_nan(result, ctx);
    1426           0 :         return 1;
    1427             :     }
    1428           0 :     return 0;
    1429             : }
    1430             : 
    1431             : /*
    1432             :  * Check if one of the operands is NaN, copy to result and return 1 if this
    1433             :  * is the case. Copying can fail since NaNs are allowed to have a payload
    1434             :  * that does not fit in MPD_MINALLOC.
    1435             :  */
    1436             : static int
    1437           0 : mpd_qcheck_3nans(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c,
    1438             :                  const mpd_context_t *ctx, uint32_t *status)
    1439             : {
    1440           0 :     if ((a->flags|b->flags|c->flags)&(MPD_NAN|MPD_SNAN)) {
    1441           0 :         const mpd_t *choice = c;
    1442           0 :         if (mpd_issnan(a)) {
    1443           0 :             choice = a;
    1444           0 :             *status |= MPD_Invalid_operation;
    1445             :         }
    1446           0 :         else if (mpd_issnan(b)) {
    1447           0 :             choice = b;
    1448           0 :             *status |= MPD_Invalid_operation;
    1449             :         }
    1450           0 :         else if (mpd_issnan(c)) {
    1451           0 :             *status |= MPD_Invalid_operation;
    1452             :         }
    1453           0 :         else if (mpd_isqnan(a)) {
    1454           0 :             choice = a;
    1455             :         }
    1456           0 :         else if (mpd_isqnan(b)) {
    1457           0 :             choice = b;
    1458             :         }
    1459           0 :         mpd_qcopy(result, choice, status);
    1460             :         mpd_set_qnan(result);
    1461           0 :         _mpd_fix_nan(result, ctx);
    1462           0 :         return 1;
    1463             :     }
    1464           0 :     return 0;
    1465             : }
    1466             : 
    1467             : /* Check if rounding digit 'rnd' leads to an increment. */
    1468             : static inline int
    1469           0 : _mpd_rnd_incr(const mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx)
    1470             : {
    1471             :     int ld;
    1472             : 
    1473           0 :     switch (ctx->round) {
    1474             :     case MPD_ROUND_DOWN: case MPD_ROUND_TRUNC:
    1475           0 :         return 0;
    1476             :     case MPD_ROUND_HALF_UP:
    1477           0 :         return (rnd >= 5);
    1478             :     case MPD_ROUND_HALF_EVEN:
    1479           0 :         return (rnd > 5) || ((rnd == 5) && mpd_isoddcoeff(dec));
    1480             :     case MPD_ROUND_CEILING:
    1481           0 :         return !(rnd == 0 || mpd_isnegative(dec));
    1482             :     case MPD_ROUND_FLOOR:
    1483           0 :         return !(rnd == 0 || mpd_ispositive(dec));
    1484             :     case MPD_ROUND_HALF_DOWN:
    1485           0 :         return (rnd > 5);
    1486             :     case MPD_ROUND_UP:
    1487           0 :         return !(rnd == 0);
    1488             :     case MPD_ROUND_05UP:
    1489           0 :         ld = (int)mpd_lsd(dec->data[0]);
    1490           0 :         return (!(rnd == 0) && (ld == 0 || ld == 5));
    1491             :     default:
    1492             :         /* Without a valid context, further results will be undefined. */
    1493           0 :         return 0; /* GCOV_NOT_REACHED */
    1494             :     }
    1495             : }
    1496             : 
    1497             : /*
    1498             :  * Apply rounding to a decimal that has been right-shifted into a full
    1499             :  * precision decimal. If an increment leads to an overflow of the precision,
    1500             :  * adjust the coefficient and the exponent and check the new exponent for
    1501             :  * overflow.
    1502             :  */
    1503             : static inline void
    1504           0 : _mpd_apply_round(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,
    1505             :                  uint32_t *status)
    1506             : {
    1507           0 :     if (_mpd_rnd_incr(dec, rnd, ctx)) {
    1508             :         /* We have a number with exactly ctx->prec digits. The increment
    1509             :          * can only lead to an overflow if the decimal is all nines. In
    1510             :          * that case, the result is a power of ten with prec+1 digits.
    1511             :          *
    1512             :          * If the precision is a multiple of MPD_RDIGITS, this situation is
    1513             :          * detected by _mpd_baseincr returning a carry.
    1514             :          * If the precision is not a multiple of MPD_RDIGITS, we have to
    1515             :          * check if the result has one digit too many.
    1516             :          */
    1517           0 :         mpd_uint_t carry = _mpd_baseincr(dec->data, dec->len);
    1518           0 :         if (carry) {
    1519           0 :             dec->data[dec->len-1] = mpd_pow10[MPD_RDIGITS-1];
    1520           0 :             dec->exp += 1;
    1521           0 :             _mpd_check_exp(dec, ctx, status);
    1522           0 :             return;
    1523             :         }
    1524           0 :         mpd_setdigits(dec);
    1525           0 :         if (dec->digits > ctx->prec) {
    1526           0 :             mpd_qshiftr_inplace(dec, 1);
    1527           0 :             dec->exp += 1;
    1528           0 :             dec->digits = ctx->prec;
    1529           0 :             _mpd_check_exp(dec, ctx, status);
    1530             :         }
    1531             :     }
    1532             : }
    1533             : 
    1534             : /*
    1535             :  * Apply rounding to a decimal. Allow overflow of the precision.
    1536             :  */
    1537             : static inline void
    1538           0 : _mpd_apply_round_excess(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,
    1539             :                         uint32_t *status)
    1540             : {
    1541           0 :     if (_mpd_rnd_incr(dec, rnd, ctx)) {
    1542           0 :         mpd_uint_t carry = _mpd_baseincr(dec->data, dec->len);
    1543           0 :         if (carry) {
    1544           0 :             if (!mpd_qresize(dec, dec->len+1, status)) {
    1545           0 :                 return;
    1546             :             }
    1547           0 :             dec->data[dec->len] = 1;
    1548           0 :             dec->len += 1;
    1549             :         }
    1550           0 :         mpd_setdigits(dec);
    1551             :     }
    1552             : }
    1553             : 
    1554             : /*
    1555             :  * Apply rounding to a decimal that has been right-shifted into a decimal
    1556             :  * with full precision or less. Return failure if an increment would
    1557             :  * overflow the precision.
    1558             :  */
    1559             : static inline int
    1560           0 : _mpd_apply_round_fit(mpd_t *dec, mpd_uint_t rnd, const mpd_context_t *ctx,
    1561             :                      uint32_t *status)
    1562             : {
    1563           0 :     if (_mpd_rnd_incr(dec, rnd, ctx)) {
    1564           0 :         mpd_uint_t carry = _mpd_baseincr(dec->data, dec->len);
    1565           0 :         if (carry) {
    1566           0 :             if (!mpd_qresize(dec, dec->len+1, status)) {
    1567           0 :                 return 0;
    1568             :             }
    1569           0 :             dec->data[dec->len] = 1;
    1570           0 :             dec->len += 1;
    1571             :         }
    1572           0 :         mpd_setdigits(dec);
    1573           0 :         if (dec->digits > ctx->prec) {
    1574           0 :             mpd_seterror(dec, MPD_Invalid_operation, status);
    1575           0 :             return 0;
    1576             :         }
    1577             :     }
    1578           0 :     return 1;
    1579             : }
    1580             : 
    1581             : /* Check a normal number for overflow, underflow, clamping. If the operand
    1582             :    is modified, it will be zero, special or (sub)normal with a coefficient
    1583             :    that fits into the current context precision. */
    1584             : static inline void
    1585           0 : _mpd_check_exp(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)
    1586             : {
    1587             :     mpd_ssize_t adjexp, etiny, shift;
    1588             :     int rnd;
    1589             : 
    1590           0 :     adjexp = mpd_adjexp(dec);
    1591           0 :     if (adjexp > ctx->emax) {
    1592             : 
    1593           0 :         if (mpd_iszerocoeff(dec)) {
    1594           0 :             dec->exp = ctx->emax;
    1595           0 :             if (ctx->clamp) {
    1596           0 :                 dec->exp -= (ctx->prec-1);
    1597             :             }
    1598           0 :             mpd_zerocoeff(dec);
    1599           0 :             *status |= MPD_Clamped;
    1600           0 :             return;
    1601             :         }
    1602             : 
    1603           0 :         switch (ctx->round) {
    1604             :         case MPD_ROUND_HALF_UP: case MPD_ROUND_HALF_EVEN:
    1605             :         case MPD_ROUND_HALF_DOWN: case MPD_ROUND_UP:
    1606             :         case MPD_ROUND_TRUNC:
    1607           0 :             mpd_setspecial(dec, mpd_sign(dec), MPD_INF);
    1608           0 :             break;
    1609             :         case MPD_ROUND_DOWN: case MPD_ROUND_05UP:
    1610           0 :             mpd_qmaxcoeff(dec, ctx, status);
    1611           0 :             dec->exp = ctx->emax - ctx->prec + 1;
    1612           0 :             break;
    1613             :         case MPD_ROUND_CEILING:
    1614           0 :             if (mpd_isnegative(dec)) {
    1615           0 :                 mpd_qmaxcoeff(dec, ctx, status);
    1616           0 :                 dec->exp = ctx->emax - ctx->prec + 1;
    1617             :             }
    1618             :             else {
    1619           0 :                 mpd_setspecial(dec, MPD_POS, MPD_INF);
    1620             :             }
    1621           0 :             break;
    1622             :         case MPD_ROUND_FLOOR:
    1623           0 :             if (mpd_ispositive(dec)) {
    1624           0 :                 mpd_qmaxcoeff(dec, ctx, status);
    1625           0 :                 dec->exp = ctx->emax - ctx->prec + 1;
    1626             :             }
    1627             :             else {
    1628           0 :                 mpd_setspecial(dec, MPD_NEG, MPD_INF);
    1629             :             }
    1630           0 :             break;
    1631             :         default: /* debug */
    1632           0 :             abort(); /* GCOV_NOT_REACHED */
    1633             :         }
    1634             : 
    1635           0 :         *status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;
    1636             : 
    1637             :     } /* fold down */
    1638           0 :     else if (ctx->clamp && dec->exp > mpd_etop(ctx)) {
    1639             :         /* At this point adjexp=exp+digits-1 <= emax and exp > etop=emax-prec+1:
    1640             :          *   (1) shift = exp -emax+prec-1 > 0
    1641             :          *   (2) digits+shift = exp+digits-1 - emax + prec <= prec */
    1642           0 :         shift = dec->exp - mpd_etop(ctx);
    1643           0 :         if (!mpd_qshiftl(dec, dec, shift, status)) {
    1644           0 :             return;
    1645             :         }
    1646           0 :         dec->exp -= shift;
    1647           0 :         *status |= MPD_Clamped;
    1648           0 :         if (!mpd_iszerocoeff(dec) && adjexp < ctx->emin) {
    1649             :             /* Underflow is impossible, since exp < etiny=emin-prec+1
    1650             :              * and exp > etop=emax-prec+1 would imply emax < emin. */
    1651           0 :             *status |= MPD_Subnormal;
    1652             :         }
    1653             :     }
    1654           0 :     else if (adjexp < ctx->emin) {
    1655             : 
    1656           0 :         etiny = mpd_etiny(ctx);
    1657             : 
    1658           0 :         if (mpd_iszerocoeff(dec)) {
    1659           0 :             if (dec->exp < etiny) {
    1660           0 :                 dec->exp = etiny;
    1661           0 :                 mpd_zerocoeff(dec);
    1662           0 :                 *status |= MPD_Clamped;
    1663             :             }
    1664           0 :             return;
    1665             :         }
    1666             : 
    1667           0 :         *status |= MPD_Subnormal;
    1668           0 :         if (dec->exp < etiny) {
    1669             :             /* At this point adjexp=exp+digits-1 < emin and exp < etiny=emin-prec+1:
    1670             :              *   (1) shift = emin-prec+1 - exp > 0
    1671             :              *   (2) digits-shift = exp+digits-1 - emin + prec < prec */
    1672           0 :             shift = etiny - dec->exp;
    1673           0 :             rnd = (int)mpd_qshiftr_inplace(dec, shift);
    1674           0 :             dec->exp = etiny;
    1675             :             /* We always have a spare digit in case of an increment. */
    1676           0 :             _mpd_apply_round_excess(dec, rnd, ctx, status);
    1677           0 :             *status |= MPD_Rounded;
    1678           0 :             if (rnd) {
    1679           0 :                 *status |= (MPD_Inexact|MPD_Underflow);
    1680           0 :                 if (mpd_iszerocoeff(dec)) {
    1681           0 :                     mpd_zerocoeff(dec);
    1682           0 :                     *status |= MPD_Clamped;
    1683             :                 }
    1684             :             }
    1685             :         }
    1686             :         /* Case exp >= etiny=emin-prec+1:
    1687             :          *   (1) adjexp=exp+digits-1 < emin
    1688             :          *   (2) digits < emin-exp+1 <= prec */
    1689             :     }
    1690             : }
    1691             : 
    1692             : /* Transcendental functions do not always set Underflow reliably,
    1693             :  * since they only use as much precision as is necessary for correct
    1694             :  * rounding. If a result like 1.0000000000e-101 is finalized, there
    1695             :  * is no rounding digit that would trigger Underflow. But we can
    1696             :  * assume Inexact, so a short check suffices. */
    1697             : static inline void
    1698           0 : mpd_check_underflow(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)
    1699             : {
    1700           0 :     if (mpd_adjexp(dec) < ctx->emin && !mpd_iszero(dec) &&
    1701           0 :         dec->exp < mpd_etiny(ctx)) {
    1702           0 :         *status |= MPD_Underflow;
    1703             :     }
    1704           0 : }
    1705             : 
    1706             : /* Check if a normal number must be rounded after the exponent has been checked. */
    1707             : static inline void
    1708           0 : _mpd_check_round(mpd_t *dec, const mpd_context_t *ctx, uint32_t *status)
    1709             : {
    1710             :     mpd_uint_t rnd;
    1711             :     mpd_ssize_t shift;
    1712             : 
    1713             :     /* must handle specials: _mpd_check_exp() can produce infinities or NaNs */
    1714           0 :     if (mpd_isspecial(dec)) {
    1715           0 :         return;
    1716             :     }
    1717             : 
    1718           0 :     if (dec->digits > ctx->prec) {
    1719           0 :         shift = dec->digits - ctx->prec;
    1720           0 :         rnd = mpd_qshiftr_inplace(dec, shift);
    1721           0 :         dec->exp += shift;
    1722           0 :         _mpd_apply_round(dec, rnd, ctx, status);
    1723           0 :         *status |= MPD_Rounded;
    1724           0 :         if (rnd) {
    1725           0 :             *status |= MPD_Inexact;
    1726             :         }
    1727             :     }
    1728             : }
    1729             : 
    1730             : /* Finalize all operations. */
    1731             : void
    1732           0 : mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)
    1733             : {
    1734           0 :     if (mpd_isspecial(result)) {
    1735           0 :         if (mpd_isnan(result)) {
    1736           0 :             _mpd_fix_nan(result, ctx);
    1737             :         }
    1738           0 :         return;
    1739             :     }
    1740             : 
    1741           0 :     _mpd_check_exp(result, ctx, status);
    1742           0 :     _mpd_check_round(result, ctx, status);
    1743             : }
    1744             : 
    1745             : 
    1746             : /******************************************************************************/
    1747             : /*                                 Copying                                    */
    1748             : /******************************************************************************/
    1749             : 
    1750             : /* Internal function: Copy a decimal, share data with src: USE WITH CARE! */
    1751             : static inline void
    1752           0 : _mpd_copy_shared(mpd_t *dest, const mpd_t *src)
    1753             : {
    1754           0 :     dest->flags = src->flags;
    1755           0 :     dest->exp = src->exp;
    1756           0 :     dest->digits = src->digits;
    1757           0 :     dest->len = src->len;
    1758           0 :     dest->alloc = src->alloc;
    1759           0 :     dest->data = src->data;
    1760             : 
    1761             :     mpd_set_shared_data(dest);
    1762           0 : }
    1763             : 
    1764             : /*
    1765             :  * Copy a decimal. In case of an error, status is set to MPD_Malloc_error.
    1766             :  */
    1767             : int
    1768           0 : mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status)
    1769             : {
    1770           0 :     if (result == a) return 1;
    1771             : 
    1772           0 :     if (!mpd_qresize(result, a->len, status)) {
    1773           0 :         return 0;
    1774             :     }
    1775             : 
    1776             :     mpd_copy_flags(result, a);
    1777           0 :     result->exp = a->exp;
    1778           0 :     result->digits = a->digits;
    1779           0 :     result->len = a->len;
    1780           0 :     memcpy(result->data, a->data, a->len * (sizeof *result->data));
    1781             : 
    1782           0 :     return 1;
    1783             : }
    1784             : 
    1785             : /*
    1786             :  * Copy to a decimal with a static buffer. The caller has to make sure that
    1787             :  * the buffer is big enough. Cannot fail.
    1788             :  */
    1789             : static void
    1790           0 : mpd_qcopy_static(mpd_t *result, const mpd_t *a)
    1791             : {
    1792           0 :     if (result == a) return;
    1793             : 
    1794           0 :     memcpy(result->data, a->data, a->len * (sizeof *result->data));
    1795             : 
    1796             :     mpd_copy_flags(result, a);
    1797           0 :     result->exp = a->exp;
    1798           0 :     result->digits = a->digits;
    1799           0 :     result->len = a->len;
    1800             : }
    1801             : 
    1802             : /*
    1803             :  * Return a newly allocated copy of the operand. In case of an error,
    1804             :  * status is set to MPD_Malloc_error and the return value is NULL.
    1805             :  */
    1806             : mpd_t *
    1807           0 : mpd_qncopy(const mpd_t *a)
    1808             : {
    1809             :     mpd_t *result;
    1810             : 
    1811           0 :     if ((result = mpd_qnew_size(a->len)) == NULL) {
    1812           0 :         return NULL;
    1813             :     }
    1814           0 :     memcpy(result->data, a->data, a->len * (sizeof *result->data));
    1815             :     mpd_copy_flags(result, a);
    1816           0 :     result->exp = a->exp;
    1817           0 :     result->digits = a->digits;
    1818           0 :     result->len = a->len;
    1819             : 
    1820           0 :     return result;
    1821             : }
    1822             : 
    1823             : /*
    1824             :  * Copy a decimal and set the sign to positive. In case of an error, the
    1825             :  * status is set to MPD_Malloc_error.
    1826             :  */
    1827             : int
    1828           0 : mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status)
    1829             : {
    1830           0 :     if (!mpd_qcopy(result, a, status)) {
    1831           0 :         return 0;
    1832             :     }
    1833             :     mpd_set_positive(result);
    1834           0 :     return 1;
    1835             : }
    1836             : 
    1837             : /*
    1838             :  * Copy a decimal and negate the sign. In case of an error, the
    1839             :  * status is set to MPD_Malloc_error.
    1840             :  */
    1841             : int
    1842           0 : mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status)
    1843             : {
    1844           0 :     if (!mpd_qcopy(result, a, status)) {
    1845           0 :         return 0;
    1846             :     }
    1847           0 :     _mpd_negate(result);
    1848           0 :     return 1;
    1849             : }
    1850             : 
    1851             : /*
    1852             :  * Copy a decimal, setting the sign of the first operand to the sign of the
    1853             :  * second operand. In case of an error, the status is set to MPD_Malloc_error.
    1854             :  */
    1855             : int
    1856           0 : mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status)
    1857             : {
    1858           0 :     uint8_t sign_b = mpd_sign(b); /* result may equal b! */
    1859             : 
    1860           0 :     if (!mpd_qcopy(result, a, status)) {
    1861           0 :         return 0;
    1862             :     }
    1863           0 :     mpd_set_sign(result, sign_b);
    1864           0 :     return 1;
    1865             : }
    1866             : 
    1867             : 
    1868             : /******************************************************************************/
    1869             : /*                                Comparisons                                 */
    1870             : /******************************************************************************/
    1871             : 
    1872             : /*
    1873             :  * For all functions that compare two operands and return an int the usual
    1874             :  * convention applies to the return value:
    1875             :  *
    1876             :  * -1 if op1 < op2
    1877             :  *  0 if op1 == op2
    1878             :  *  1 if op1 > op2
    1879             :  *
    1880             :  *  INT_MAX for error
    1881             :  */
    1882             : 
    1883             : 
    1884             : /* Convenience macro. If a and b are not equal, return from the calling
    1885             :  * function with the correct comparison value. */
    1886             : #define CMP_EQUAL_OR_RETURN(a, b)  \
    1887             :         if (a != b) {              \
    1888             :                 if (a < b) {       \
    1889             :                         return -1; \
    1890             :                 }                  \
    1891             :                 return 1;          \
    1892             :         }
    1893             : 
    1894             : /*
    1895             :  * Compare the data of big and small. This function does the equivalent
    1896             :  * of first shifting small to the left and then comparing the data of
    1897             :  * big and small, except that no allocation for the left shift is needed.
    1898             :  */
    1899             : static int
    1900           0 : _mpd_basecmp(mpd_uint_t *big, mpd_uint_t *small, mpd_size_t n, mpd_size_t m,
    1901             :              mpd_size_t shift)
    1902             : {
    1903             : #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
    1904             :     /* spurious uninitialized warnings */
    1905           0 :     mpd_uint_t l=l, lprev=lprev, h=h;
    1906             : #else
    1907             :     mpd_uint_t l, lprev, h;
    1908             : #endif
    1909             :     mpd_uint_t q, r;
    1910             :     mpd_uint_t ph, x;
    1911             : 
    1912             :     assert(m > 0 && n >= m && shift > 0);
    1913             : 
    1914           0 :     _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
    1915             : 
    1916           0 :     if (r != 0) {
    1917             : 
    1918           0 :         ph = mpd_pow10[r];
    1919             : 
    1920           0 :         --m; --n;
    1921           0 :         _mpd_divmod_pow10(&h, &lprev, small[m--], MPD_RDIGITS-r);
    1922           0 :         if (h != 0) {
    1923           0 :             CMP_EQUAL_OR_RETURN(big[n], h)
    1924           0 :             --n;
    1925             :         }
    1926           0 :         for (; m != MPD_SIZE_MAX; m--,n--) {
    1927           0 :             _mpd_divmod_pow10(&h, &l, small[m], MPD_RDIGITS-r);
    1928           0 :             x = ph * lprev + h;
    1929           0 :             CMP_EQUAL_OR_RETURN(big[n], x)
    1930           0 :             lprev = l;
    1931             :         }
    1932           0 :         x = ph * lprev;
    1933           0 :         CMP_EQUAL_OR_RETURN(big[q], x)
    1934             :     }
    1935             :     else {
    1936           0 :         while (--m != MPD_SIZE_MAX) {
    1937           0 :             CMP_EQUAL_OR_RETURN(big[m+q], small[m])
    1938             :         }
    1939             :     }
    1940             : 
    1941           0 :     return !_mpd_isallzero(big, q);
    1942             : }
    1943             : 
    1944             : /* Compare two decimals with the same adjusted exponent. */
    1945             : static int
    1946           0 : _mpd_cmp_same_adjexp(const mpd_t *a, const mpd_t *b)
    1947             : {
    1948             :     mpd_ssize_t shift, i;
    1949             : 
    1950           0 :     if (a->exp != b->exp) {
    1951             :         /* Cannot wrap: a->exp + a->digits = b->exp + b->digits, so
    1952             :          * a->exp - b->exp = b->digits - a->digits. */
    1953           0 :         shift = a->exp - b->exp;
    1954           0 :         if (shift > 0) {
    1955           0 :             return -1 * _mpd_basecmp(b->data, a->data, b->len, a->len, shift);
    1956             :         }
    1957             :         else {
    1958           0 :             return _mpd_basecmp(a->data, b->data, a->len, b->len, -shift);
    1959             :         }
    1960             :     }
    1961             : 
    1962             :     /*
    1963             :      * At this point adjexp(a) == adjexp(b) and a->exp == b->exp,
    1964             :      * so a->digits == b->digits, therefore a->len == b->len.
    1965             :      */
    1966           0 :     for (i = a->len-1; i >= 0; --i) {
    1967           0 :         CMP_EQUAL_OR_RETURN(a->data[i], b->data[i])
    1968             :     }
    1969             : 
    1970           0 :     return 0;
    1971             : }
    1972             : 
    1973             : /* Compare two numerical values. */
    1974             : static int
    1975           0 : _mpd_cmp(const mpd_t *a, const mpd_t *b)
    1976             : {
    1977             :     mpd_ssize_t adjexp_a, adjexp_b;
    1978             : 
    1979             :     /* equal pointers */
    1980           0 :     if (a == b) {
    1981           0 :         return 0;
    1982             :     }
    1983             : 
    1984             :     /* infinities */
    1985           0 :     if (mpd_isinfinite(a)) {
    1986           0 :         if (mpd_isinfinite(b)) {
    1987           0 :             return mpd_isnegative(b) - mpd_isnegative(a);
    1988             :         }
    1989           0 :         return mpd_arith_sign(a);
    1990             :     }
    1991           0 :     if (mpd_isinfinite(b)) {
    1992           0 :         return -mpd_arith_sign(b);
    1993             :     }
    1994             : 
    1995             :     /* zeros */
    1996           0 :     if (mpd_iszerocoeff(a)) {
    1997           0 :         if (mpd_iszerocoeff(b)) {
    1998           0 :             return 0;
    1999             :         }
    2000           0 :         return -mpd_arith_sign(b);
    2001             :     }
    2002           0 :     if (mpd_iszerocoeff(b)) {
    2003           0 :         return mpd_arith_sign(a);
    2004             :     }
    2005             : 
    2006             :     /* different signs */
    2007           0 :     if (mpd_sign(a) != mpd_sign(b)) {
    2008           0 :         return mpd_sign(b) - mpd_sign(a);
    2009             :     }
    2010             : 
    2011             :     /* different adjusted exponents */
    2012           0 :     adjexp_a = mpd_adjexp(a);
    2013           0 :     adjexp_b = mpd_adjexp(b);
    2014           0 :     if (adjexp_a != adjexp_b) {
    2015           0 :         if (adjexp_a < adjexp_b) {
    2016           0 :             return -1 * mpd_arith_sign(a);
    2017             :         }
    2018           0 :         return mpd_arith_sign(a);
    2019             :     }
    2020             : 
    2021             :     /* same adjusted exponents */
    2022           0 :     return _mpd_cmp_same_adjexp(a, b) * mpd_arith_sign(a);
    2023             : }
    2024             : 
    2025             : /* Compare the absolutes of two numerical values. */
    2026             : static int
    2027           0 : _mpd_cmp_abs(const mpd_t *a, const mpd_t *b)
    2028             : {
    2029             :     mpd_ssize_t adjexp_a, adjexp_b;
    2030             : 
    2031             :     /* equal pointers */
    2032           0 :     if (a == b) {
    2033           0 :         return 0;
    2034             :     }
    2035             : 
    2036             :     /* infinities */
    2037           0 :     if (mpd_isinfinite(a)) {
    2038           0 :         if (mpd_isinfinite(b)) {
    2039           0 :             return 0;
    2040             :         }
    2041           0 :         return 1;
    2042             :     }
    2043           0 :     if (mpd_isinfinite(b)) {
    2044           0 :         return -1;
    2045             :     }
    2046             : 
    2047             :     /* zeros */
    2048           0 :     if (mpd_iszerocoeff(a)) {
    2049           0 :         if (mpd_iszerocoeff(b)) {
    2050           0 :             return 0;
    2051             :         }
    2052           0 :         return -1;
    2053             :     }
    2054           0 :     if (mpd_iszerocoeff(b)) {
    2055           0 :         return 1;
    2056             :     }
    2057             : 
    2058             :     /* different adjusted exponents */
    2059           0 :     adjexp_a = mpd_adjexp(a);
    2060           0 :     adjexp_b = mpd_adjexp(b);
    2061           0 :     if (adjexp_a != adjexp_b) {
    2062           0 :         if (adjexp_a < adjexp_b) {
    2063           0 :             return -1;
    2064             :         }
    2065           0 :         return 1;
    2066             :     }
    2067             : 
    2068             :     /* same adjusted exponents */
    2069           0 :     return _mpd_cmp_same_adjexp(a, b);
    2070             : }
    2071             : 
    2072             : /* Compare two values and return an integer result. */
    2073             : int
    2074           0 : mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status)
    2075             : {
    2076           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    2077           0 :         if (mpd_isnan(a) || mpd_isnan(b)) {
    2078           0 :             *status |= MPD_Invalid_operation;
    2079           0 :             return INT_MAX;
    2080             :         }
    2081             :     }
    2082             : 
    2083           0 :     return _mpd_cmp(a, b);
    2084             : }
    2085             : 
    2086             : /*
    2087             :  * Compare a and b, convert the the usual integer result to a decimal and
    2088             :  * store it in 'result'. For convenience, the integer result of the comparison
    2089             :  * is returned. Comparisons involving NaNs return NaN/INT_MAX.
    2090             :  */
    2091             : int
    2092           0 : mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b,
    2093             :              const mpd_context_t *ctx, uint32_t *status)
    2094             : {
    2095             :     int c;
    2096             : 
    2097           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    2098           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    2099           0 :             return INT_MAX;
    2100             :         }
    2101             :     }
    2102             : 
    2103           0 :     c = _mpd_cmp(a, b);
    2104           0 :     _settriple(result, (c < 0), (c != 0), 0);
    2105           0 :     return c;
    2106             : }
    2107             : 
    2108             : /* Same as mpd_compare(), but signal for all NaNs, i.e. also for quiet NaNs. */
    2109             : int
    2110           0 : mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b,
    2111             :                     const mpd_context_t *ctx, uint32_t *status)
    2112             : {
    2113             :     int c;
    2114             : 
    2115           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    2116           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    2117           0 :             *status |= MPD_Invalid_operation;
    2118           0 :             return INT_MAX;
    2119             :         }
    2120             :     }
    2121             : 
    2122           0 :     c = _mpd_cmp(a, b);
    2123           0 :     _settriple(result, (c < 0), (c != 0), 0);
    2124           0 :     return c;
    2125             : }
    2126             : 
    2127             : /* Compare the operands using a total order. */
    2128             : int
    2129           0 : mpd_cmp_total(const mpd_t *a, const mpd_t *b)
    2130             : {
    2131             :     mpd_t aa, bb;
    2132             :     int nan_a, nan_b;
    2133             :     int c;
    2134             : 
    2135           0 :     if (mpd_sign(a) != mpd_sign(b)) {
    2136           0 :         return mpd_sign(b) - mpd_sign(a);
    2137             :     }
    2138             : 
    2139             : 
    2140           0 :     if (mpd_isnan(a)) {
    2141           0 :         c = 1;
    2142           0 :         if (mpd_isnan(b)) {
    2143           0 :             nan_a = (mpd_isqnan(a)) ? 1 : 0;
    2144           0 :             nan_b = (mpd_isqnan(b)) ? 1 : 0;
    2145           0 :             if (nan_b == nan_a) {
    2146           0 :                 if (a->len > 0 && b->len > 0) {
    2147           0 :                     _mpd_copy_shared(&aa, a);
    2148           0 :                     _mpd_copy_shared(&bb, b);
    2149           0 :                     aa.exp = bb.exp = 0;
    2150             :                     /* compare payload */
    2151           0 :                     c = _mpd_cmp_abs(&aa, &bb);
    2152             :                 }
    2153             :                 else {
    2154           0 :                     c = (a->len > 0) - (b->len > 0);
    2155             :                 }
    2156             :             }
    2157             :             else {
    2158           0 :                 c = nan_a - nan_b;
    2159             :             }
    2160             :         }
    2161             :     }
    2162           0 :     else if (mpd_isnan(b)) {
    2163           0 :         c = -1;
    2164             :     }
    2165             :     else {
    2166           0 :         c = _mpd_cmp_abs(a, b);
    2167           0 :         if (c == 0 && a->exp != b->exp) {
    2168           0 :             c = (a->exp < b->exp) ? -1 : 1;
    2169             :         }
    2170             :     }
    2171             : 
    2172           0 :     return c * mpd_arith_sign(a);
    2173             : }
    2174             : 
    2175             : /*
    2176             :  * Compare a and b according to a total order, convert the usual integer result
    2177             :  * to a decimal and store it in 'result'. For convenience, the integer result
    2178             :  * of the comparison is returned.
    2179             :  */
    2180             : int
    2181           0 : mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b)
    2182             : {
    2183             :     int c;
    2184             : 
    2185           0 :     c = mpd_cmp_total(a, b);
    2186           0 :     _settriple(result, (c < 0), (c != 0), 0);
    2187           0 :     return c;
    2188             : }
    2189             : 
    2190             : /* Compare the magnitude of the operands using a total order. */
    2191             : int
    2192           0 : mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b)
    2193             : {
    2194             :     mpd_t aa, bb;
    2195             : 
    2196           0 :     _mpd_copy_shared(&aa, a);
    2197           0 :     _mpd_copy_shared(&bb, b);
    2198             : 
    2199             :     mpd_set_positive(&aa);
    2200             :     mpd_set_positive(&bb);
    2201             : 
    2202           0 :     return mpd_cmp_total(&aa, &bb);
    2203             : }
    2204             : 
    2205             : /*
    2206             :  * Compare the magnitude of a and b according to a total order, convert the
    2207             :  * the usual integer result to a decimal and store it in 'result'.
    2208             :  * For convenience, the integer result of the comparison is returned.
    2209             :  */
    2210             : int
    2211           0 : mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b)
    2212             : {
    2213             :     int c;
    2214             : 
    2215           0 :     c = mpd_cmp_total_mag(a, b);
    2216           0 :     _settriple(result, (c < 0), (c != 0), 0);
    2217           0 :     return c;
    2218             : }
    2219             : 
    2220             : /* Determine an ordering for operands that are numerically equal. */
    2221             : static inline int
    2222           0 : _mpd_cmp_numequal(const mpd_t *a, const mpd_t *b)
    2223             : {
    2224             :     int sign_a, sign_b;
    2225             :     int c;
    2226             : 
    2227           0 :     sign_a = mpd_sign(a);
    2228           0 :     sign_b = mpd_sign(b);
    2229           0 :     if (sign_a != sign_b) {
    2230           0 :         c = sign_b - sign_a;
    2231             :     }
    2232             :     else {
    2233           0 :         c = (a->exp < b->exp) ? -1 : 1;
    2234           0 :         c *= mpd_arith_sign(a);
    2235             :     }
    2236             : 
    2237           0 :     return c;
    2238             : }
    2239             : 
    2240             : 
    2241             : /******************************************************************************/
    2242             : /*                         Shifting the coefficient                           */
    2243             : /******************************************************************************/
    2244             : 
    2245             : /*
    2246             :  * Shift the coefficient of the operand to the left, no check for specials.
    2247             :  * Both operands may be the same pointer. If the result length has to be
    2248             :  * increased, mpd_qresize() might fail with MPD_Malloc_error.
    2249             :  */
    2250             : int
    2251           0 : mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status)
    2252             : {
    2253             :     mpd_ssize_t size;
    2254             : 
    2255             :     assert(!mpd_isspecial(a));
    2256             :     assert(n >= 0);
    2257             : 
    2258           0 :     if (mpd_iszerocoeff(a) || n == 0) {
    2259           0 :         return mpd_qcopy(result, a, status);
    2260             :     }
    2261             : 
    2262           0 :     size = mpd_digits_to_size(a->digits+n);
    2263           0 :     if (!mpd_qresize(result, size, status)) {
    2264           0 :         return 0; /* result is NaN */
    2265             :     }
    2266             : 
    2267           0 :     _mpd_baseshiftl(result->data, a->data, size, a->len, n);
    2268             : 
    2269             :     mpd_copy_flags(result, a);
    2270           0 :     result->exp = a->exp;
    2271           0 :     result->digits = a->digits+n;
    2272           0 :     result->len = size;
    2273             : 
    2274           0 :     return 1;
    2275             : }
    2276             : 
    2277             : /* Determine the rounding indicator if all digits of the coefficient are shifted
    2278             :  * out of the picture. */
    2279             : static mpd_uint_t
    2280           0 : _mpd_get_rnd(const mpd_uint_t *data, mpd_ssize_t len, int use_msd)
    2281             : {
    2282           0 :     mpd_uint_t rnd = 0, rest = 0, word;
    2283             : 
    2284           0 :     word = data[len-1];
    2285             :     /* special treatment for the most significant digit if shift == digits */
    2286           0 :     if (use_msd) {
    2287           0 :         _mpd_divmod_pow10(&rnd, &rest, word, mpd_word_digits(word)-1);
    2288           0 :         if (len > 1 && rest == 0) {
    2289           0 :              rest = !_mpd_isallzero(data, len-1);
    2290             :         }
    2291             :     }
    2292             :     else {
    2293           0 :         rest = !_mpd_isallzero(data, len);
    2294             :     }
    2295             : 
    2296           0 :     return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd;
    2297             : }
    2298             : 
    2299             : /*
    2300             :  * Same as mpd_qshiftr(), but 'result' is an mpd_t with a static coefficient.
    2301             :  * It is the caller's responsibility to ensure that the coefficient is big
    2302             :  * enough. The function cannot fail.
    2303             :  */
    2304             : mpd_uint_t
    2305           0 : mpd_qsshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n)
    2306             : {
    2307             :     mpd_uint_t rnd;
    2308             :     mpd_ssize_t size;
    2309             : 
    2310             :     assert(!mpd_isspecial(a));
    2311             :     assert(n >= 0);
    2312             : 
    2313           0 :     if (mpd_iszerocoeff(a) || n == 0) {
    2314           0 :         mpd_qcopy_static(result, a);
    2315           0 :         return 0;
    2316             :     }
    2317             : 
    2318           0 :     if (n >= a->digits) {
    2319           0 :         rnd = _mpd_get_rnd(a->data, a->len, (n==a->digits));
    2320           0 :         mpd_zerocoeff(result);
    2321             :     }
    2322             :     else {
    2323           0 :         result->digits = a->digits-n;
    2324           0 :         size = mpd_digits_to_size(result->digits);
    2325           0 :         rnd = _mpd_baseshiftr(result->data, a->data, a->len, n);
    2326           0 :         result->len = size;
    2327             :     }
    2328             : 
    2329             :     mpd_copy_flags(result, a);
    2330           0 :     result->exp = a->exp;
    2331             : 
    2332           0 :     return rnd;
    2333             : }
    2334             : 
    2335             : /*
    2336             :  * Inplace shift of the coefficient to the right, no check for specials.
    2337             :  * Returns the rounding indicator for mpd_rnd_incr().
    2338             :  * The function cannot fail.
    2339             :  */
    2340             : mpd_uint_t
    2341           0 : mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n)
    2342             : {
    2343             :     uint32_t dummy;
    2344             :     mpd_uint_t rnd;
    2345             :     mpd_ssize_t size;
    2346             : 
    2347             :     assert(!mpd_isspecial(result));
    2348             :     assert(n >= 0);
    2349             : 
    2350           0 :     if (mpd_iszerocoeff(result) || n == 0) {
    2351           0 :         return 0;
    2352             :     }
    2353             : 
    2354           0 :     if (n >= result->digits) {
    2355           0 :         rnd = _mpd_get_rnd(result->data, result->len, (n==result->digits));
    2356           0 :         mpd_zerocoeff(result);
    2357             :     }
    2358             :     else {
    2359           0 :         rnd = _mpd_baseshiftr(result->data, result->data, result->len, n);
    2360           0 :         result->digits -= n;
    2361           0 :         size = mpd_digits_to_size(result->digits);
    2362             :         /* reducing the size cannot fail */
    2363             :         mpd_qresize(result, size, &dummy);
    2364           0 :         result->len = size;
    2365             :     }
    2366             : 
    2367           0 :     return rnd;
    2368             : }
    2369             : 
    2370             : /*
    2371             :  * Shift the coefficient of the operand to the right, no check for specials.
    2372             :  * Both operands may be the same pointer. Returns the rounding indicator to
    2373             :  * be used by mpd_rnd_incr(). If the result length has to be increased,
    2374             :  * mpd_qcopy() or mpd_qresize() might fail with MPD_Malloc_error. In those
    2375             :  * cases, MPD_UINT_MAX is returned.
    2376             :  */
    2377             : mpd_uint_t
    2378           0 : mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status)
    2379             : {
    2380             :     mpd_uint_t rnd;
    2381             :     mpd_ssize_t size;
    2382             : 
    2383             :     assert(!mpd_isspecial(a));
    2384             :     assert(n >= 0);
    2385             : 
    2386           0 :     if (mpd_iszerocoeff(a) || n == 0) {
    2387           0 :         if (!mpd_qcopy(result, a, status)) {
    2388           0 :             return MPD_UINT_MAX;
    2389             :         }
    2390           0 :         return 0;
    2391             :     }
    2392             : 
    2393           0 :     if (n >= a->digits) {
    2394           0 :         rnd = _mpd_get_rnd(a->data, a->len, (n==a->digits));
    2395           0 :         mpd_zerocoeff(result);
    2396             :     }
    2397             :     else {
    2398           0 :         result->digits = a->digits-n;
    2399           0 :         size = mpd_digits_to_size(result->digits);
    2400           0 :         if (result == a) {
    2401           0 :             rnd = _mpd_baseshiftr(result->data, a->data, a->len, n);
    2402             :             /* reducing the size cannot fail */
    2403             :             mpd_qresize(result, size, status);
    2404             :         }
    2405             :         else {
    2406           0 :             if (!mpd_qresize(result, size, status)) {
    2407           0 :                 return MPD_UINT_MAX;
    2408             :             }
    2409           0 :             rnd = _mpd_baseshiftr(result->data, a->data, a->len, n);
    2410             :         }
    2411           0 :         result->len = size;
    2412             :     }
    2413             : 
    2414             :     mpd_copy_flags(result, a);
    2415           0 :     result->exp = a->exp;
    2416             : 
    2417           0 :     return rnd;
    2418             : }
    2419             : 
    2420             : 
    2421             : /******************************************************************************/
    2422             : /*                         Miscellaneous operations                           */
    2423             : /******************************************************************************/
    2424             : 
    2425             : /* Logical And */
    2426             : void
    2427           0 : mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b,
    2428             :          const mpd_context_t *ctx, uint32_t *status)
    2429             : {
    2430           0 :     const mpd_t *big = a, *small = b;
    2431             :     mpd_uint_t x, y, z, xbit, ybit;
    2432             :     int k, mswdigits;
    2433             :     mpd_ssize_t i;
    2434             : 
    2435           0 :     if (mpd_isspecial(a) || mpd_isspecial(b) ||
    2436           0 :         mpd_isnegative(a) || mpd_isnegative(b) ||
    2437           0 :         a->exp != 0 || b->exp != 0) {
    2438           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2439           0 :         return;
    2440             :     }
    2441           0 :     if (b->digits > a->digits) {
    2442           0 :         big = b;
    2443           0 :         small = a;
    2444             :     }
    2445           0 :     if (!mpd_qresize(result, big->len, status)) {
    2446           0 :         return;
    2447             :     }
    2448             : 
    2449             : 
    2450             :     /* full words */
    2451           0 :     for (i = 0; i < small->len-1; i++) {
    2452           0 :         x = small->data[i];
    2453           0 :         y = big->data[i];
    2454           0 :         z = 0;
    2455           0 :         for (k = 0; k < MPD_RDIGITS; k++) {
    2456           0 :             xbit = x % 10;
    2457           0 :             x /= 10;
    2458           0 :             ybit = y % 10;
    2459           0 :             y /= 10;
    2460           0 :             if (xbit > 1 || ybit > 1) {
    2461             :                 goto invalid_operation;
    2462             :             }
    2463           0 :             z += (xbit&ybit) ? mpd_pow10[k] : 0;
    2464             :         }
    2465           0 :         result->data[i] = z;
    2466             :     }
    2467             :     /* most significant word of small */
    2468           0 :     x = small->data[i];
    2469           0 :     y = big->data[i];
    2470           0 :     z = 0;
    2471           0 :     mswdigits = mpd_word_digits(x);
    2472           0 :     for (k = 0; k < mswdigits; k++) {
    2473           0 :         xbit = x % 10;
    2474           0 :         x /= 10;
    2475           0 :         ybit = y % 10;
    2476           0 :         y /= 10;
    2477           0 :         if (xbit > 1 || ybit > 1) {
    2478             :             goto invalid_operation;
    2479             :         }
    2480           0 :         z += (xbit&ybit) ? mpd_pow10[k] : 0;
    2481             :     }
    2482           0 :     result->data[i++] = z;
    2483             : 
    2484             :     /* scan the rest of y for digits > 1 */
    2485           0 :     for (; k < MPD_RDIGITS; k++) {
    2486           0 :         ybit = y % 10;
    2487           0 :         y /= 10;
    2488           0 :         if (ybit > 1) {
    2489           0 :             goto invalid_operation;
    2490             :         }
    2491             :     }
    2492             :     /* scan the rest of big for digits > 1 */
    2493           0 :     for (; i < big->len; i++) {
    2494           0 :         y = big->data[i];
    2495           0 :         for (k = 0; k < MPD_RDIGITS; k++) {
    2496           0 :             ybit = y % 10;
    2497           0 :             y /= 10;
    2498           0 :             if (ybit > 1) {
    2499           0 :                 goto invalid_operation;
    2500             :             }
    2501             :         }
    2502             :     }
    2503             : 
    2504             :     mpd_clear_flags(result);
    2505           0 :     result->exp = 0;
    2506           0 :     result->len = _mpd_real_size(result->data, small->len);
    2507           0 :     mpd_qresize(result, result->len, status);
    2508           0 :     mpd_setdigits(result);
    2509           0 :     _mpd_cap(result, ctx);
    2510           0 :     return;
    2511             : 
    2512             : invalid_operation:
    2513           0 :     mpd_seterror(result, MPD_Invalid_operation, status);
    2514             : }
    2515             : 
    2516             : /* Class of an operand. Returns a pointer to the constant name. */
    2517             : const char *
    2518           0 : mpd_class(const mpd_t *a, const mpd_context_t *ctx)
    2519             : {
    2520           0 :     if (mpd_isnan(a)) {
    2521           0 :         if (mpd_isqnan(a))
    2522           0 :             return "NaN";
    2523             :         else
    2524           0 :             return "sNaN";
    2525             :     }
    2526           0 :     else if (mpd_ispositive(a)) {
    2527           0 :         if (mpd_isinfinite(a))
    2528           0 :             return "+Infinity";
    2529           0 :         else if (mpd_iszero(a))
    2530           0 :             return "+Zero";
    2531           0 :         else if (mpd_isnormal(a, ctx))
    2532           0 :             return "+Normal";
    2533             :         else
    2534           0 :             return "+Subnormal";
    2535             :     }
    2536             :     else {
    2537           0 :         if (mpd_isinfinite(a))
    2538           0 :             return "-Infinity";
    2539           0 :         else if (mpd_iszero(a))
    2540           0 :             return "-Zero";
    2541           0 :         else if (mpd_isnormal(a, ctx))
    2542           0 :             return "-Normal";
    2543             :         else
    2544           0 :             return "-Subnormal";
    2545             :     }
    2546             : }
    2547             : 
    2548             : /* Logical Xor */
    2549             : void
    2550           0 : mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    2551             :             uint32_t *status)
    2552             : {
    2553             :     mpd_uint_t x, z, xbit;
    2554             :     mpd_ssize_t i, digits, len;
    2555             :     mpd_ssize_t q, r;
    2556             :     int k;
    2557             : 
    2558           0 :     if (mpd_isspecial(a) || mpd_isnegative(a) || a->exp != 0) {
    2559           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2560             :         return;
    2561             :     }
    2562             : 
    2563           0 :     digits = (a->digits < ctx->prec) ? ctx->prec : a->digits;
    2564           0 :     _mpd_idiv_word(&q, &r, digits, MPD_RDIGITS);
    2565           0 :     len = (r == 0) ? q : q+1;
    2566           0 :     if (!mpd_qresize(result, len, status)) {
    2567             :         return;
    2568             :     }
    2569             : 
    2570           0 :     for (i = 0; i < len; i++) {
    2571           0 :         x = (i < a->len) ? a->data[i] : 0;
    2572           0 :         z = 0;
    2573           0 :         for (k = 0; k < MPD_RDIGITS; k++) {
    2574           0 :             xbit = x % 10;
    2575           0 :             x /= 10;
    2576           0 :             if (xbit > 1) {
    2577           0 :                 goto invalid_operation;
    2578             :             }
    2579           0 :             z += !xbit ? mpd_pow10[k] : 0;
    2580             :         }
    2581           0 :         result->data[i] = z;
    2582             :     }
    2583             : 
    2584             :     mpd_clear_flags(result);
    2585           0 :     result->exp = 0;
    2586           0 :     result->len = _mpd_real_size(result->data, len);
    2587           0 :     mpd_qresize(result, result->len, status);
    2588           0 :     mpd_setdigits(result);
    2589           0 :     _mpd_cap(result, ctx);
    2590             :     return;
    2591             : 
    2592             : invalid_operation:
    2593           0 :     mpd_seterror(result, MPD_Invalid_operation, status);
    2594             : }
    2595             : 
    2596             : /* Exponent of the magnitude of the most significant digit of the operand. */
    2597             : void
    2598           0 : mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    2599             :           uint32_t *status)
    2600             : {
    2601           0 :     if (mpd_isspecial(a)) {
    2602           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    2603           0 :             return;
    2604             :         }
    2605           0 :         mpd_setspecial(result, MPD_POS, MPD_INF);
    2606             :     }
    2607           0 :     else if (mpd_iszerocoeff(a)) {
    2608           0 :         mpd_setspecial(result, MPD_NEG, MPD_INF);
    2609           0 :         *status |= MPD_Division_by_zero;
    2610             :     }
    2611             :     else {
    2612           0 :         mpd_qset_ssize(result, mpd_adjexp(a), ctx, status);
    2613             :     }
    2614             : }
    2615             : 
    2616             : /* Logical Or */
    2617             : void
    2618           0 : mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b,
    2619             :         const mpd_context_t *ctx, uint32_t *status)
    2620             : {
    2621           0 :     const mpd_t *big = a, *small = b;
    2622             :     mpd_uint_t x, y, z, xbit, ybit;
    2623             :     int k, mswdigits;
    2624             :     mpd_ssize_t i;
    2625             : 
    2626           0 :     if (mpd_isspecial(a) || mpd_isspecial(b) ||
    2627           0 :         mpd_isnegative(a) || mpd_isnegative(b) ||
    2628           0 :         a->exp != 0 || b->exp != 0) {
    2629           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2630           0 :         return;
    2631             :     }
    2632           0 :     if (b->digits > a->digits) {
    2633           0 :         big = b;
    2634           0 :         small = a;
    2635             :     }
    2636           0 :     if (!mpd_qresize(result, big->len, status)) {
    2637           0 :         return;
    2638             :     }
    2639             : 
    2640             : 
    2641             :     /* full words */
    2642           0 :     for (i = 0; i < small->len-1; i++) {
    2643           0 :         x = small->data[i];
    2644           0 :         y = big->data[i];
    2645           0 :         z = 0;
    2646           0 :         for (k = 0; k < MPD_RDIGITS; k++) {
    2647           0 :             xbit = x % 10;
    2648           0 :             x /= 10;
    2649           0 :             ybit = y % 10;
    2650           0 :             y /= 10;
    2651           0 :             if (xbit > 1 || ybit > 1) {
    2652             :                 goto invalid_operation;
    2653             :             }
    2654           0 :             z += (xbit|ybit) ? mpd_pow10[k] : 0;
    2655             :         }
    2656           0 :         result->data[i] = z;
    2657             :     }
    2658             :     /* most significant word of small */
    2659           0 :     x = small->data[i];
    2660           0 :     y = big->data[i];
    2661           0 :     z = 0;
    2662           0 :     mswdigits = mpd_word_digits(x);
    2663           0 :     for (k = 0; k < mswdigits; k++) {
    2664           0 :         xbit = x % 10;
    2665           0 :         x /= 10;
    2666           0 :         ybit = y % 10;
    2667           0 :         y /= 10;
    2668           0 :         if (xbit > 1 || ybit > 1) {
    2669             :             goto invalid_operation;
    2670             :         }
    2671           0 :         z += (xbit|ybit) ? mpd_pow10[k] : 0;
    2672             :     }
    2673             : 
    2674             :     /* scan for digits > 1 and copy the rest of y */
    2675           0 :     for (; k < MPD_RDIGITS; k++) {
    2676           0 :         ybit = y % 10;
    2677           0 :         y /= 10;
    2678           0 :         if (ybit > 1) {
    2679           0 :             goto invalid_operation;
    2680             :         }
    2681           0 :         z += ybit*mpd_pow10[k];
    2682             :     }
    2683           0 :     result->data[i++] = z;
    2684             :     /* scan for digits > 1 and copy the rest of big */
    2685           0 :     for (; i < big->len; i++) {
    2686           0 :         y = big->data[i];
    2687           0 :         for (k = 0; k < MPD_RDIGITS; k++) {
    2688           0 :             ybit = y % 10;
    2689           0 :             y /= 10;
    2690           0 :             if (ybit > 1) {
    2691           0 :                 goto invalid_operation;
    2692             :             }
    2693             :         }
    2694           0 :         result->data[i] = big->data[i];
    2695             :     }
    2696             : 
    2697             :     mpd_clear_flags(result);
    2698           0 :     result->exp = 0;
    2699           0 :     result->len = _mpd_real_size(result->data, big->len);
    2700           0 :     mpd_qresize(result, result->len, status);
    2701           0 :     mpd_setdigits(result);
    2702           0 :     _mpd_cap(result, ctx);
    2703           0 :     return;
    2704             : 
    2705             : invalid_operation:
    2706           0 :     mpd_seterror(result, MPD_Invalid_operation, status);
    2707             : }
    2708             : 
    2709             : /*
    2710             :  * Rotate the coefficient of 'a' by 'b' digits. 'b' must be an integer with
    2711             :  * exponent 0.
    2712             :  */
    2713             : void
    2714           0 : mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b,
    2715             :             const mpd_context_t *ctx, uint32_t *status)
    2716             : {
    2717           0 :     uint32_t workstatus = 0;
    2718           0 :     MPD_NEW_STATIC(tmp,0,0,0,0);
    2719           0 :     MPD_NEW_STATIC(big,0,0,0,0);
    2720           0 :     MPD_NEW_STATIC(small,0,0,0,0);
    2721             :     mpd_ssize_t n, lshift, rshift;
    2722             : 
    2723           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    2724           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    2725             :             return;
    2726             :         }
    2727             :     }
    2728           0 :     if (b->exp != 0 || mpd_isinfinite(b)) {
    2729           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2730             :         return;
    2731             :     }
    2732             : 
    2733           0 :     n = mpd_qget_ssize(b, &workstatus);
    2734           0 :     if (workstatus&MPD_Invalid_operation) {
    2735           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2736             :         return;
    2737             :     }
    2738           0 :     if (n > ctx->prec || n < -ctx->prec) {
    2739           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2740             :         return;
    2741             :     }
    2742           0 :     if (mpd_isinfinite(a)) {
    2743           0 :         mpd_qcopy(result, a, status);
    2744             :         return;
    2745             :     }
    2746             : 
    2747           0 :     if (n >= 0) {
    2748           0 :         lshift = n;
    2749           0 :         rshift = ctx->prec-n;
    2750             :     }
    2751             :     else {
    2752           0 :         lshift = ctx->prec+n;
    2753           0 :         rshift = -n;
    2754             :     }
    2755             : 
    2756           0 :     if (a->digits > ctx->prec) {
    2757           0 :         if (!mpd_qcopy(&tmp, a, status)) {
    2758           0 :             mpd_seterror(result, MPD_Malloc_error, status);
    2759           0 :             goto finish;
    2760             :         }
    2761           0 :         _mpd_cap(&tmp, ctx);
    2762           0 :         a = &tmp;
    2763             :     }
    2764             : 
    2765           0 :     if (!mpd_qshiftl(&big, a, lshift, status)) {
    2766           0 :         mpd_seterror(result, MPD_Malloc_error, status);
    2767           0 :         goto finish;
    2768             :     }
    2769           0 :     _mpd_cap(&big, ctx);
    2770             : 
    2771           0 :     if (mpd_qshiftr(&small, a, rshift, status) == MPD_UINT_MAX) {
    2772           0 :         mpd_seterror(result, MPD_Malloc_error, status);
    2773           0 :         goto finish;
    2774             :     }
    2775           0 :     _mpd_qadd(result, &big, &small, ctx, status);
    2776             : 
    2777             : 
    2778             : finish:
    2779             :     mpd_del(&tmp);
    2780             :     mpd_del(&big);
    2781             :     mpd_del(&small);
    2782             : }
    2783             : 
    2784             : /*
    2785             :  * b must be an integer with exponent 0 and in the range +-2*(emax + prec).
    2786             :  * XXX: In my opinion +-(2*emax + prec) would be more sensible.
    2787             :  * The result is a with the value of b added to its exponent.
    2788             :  */
    2789             : void
    2790           0 : mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b,
    2791             :             const mpd_context_t *ctx, uint32_t *status)
    2792             : {
    2793           0 :     uint32_t workstatus = 0;
    2794             :     mpd_uint_t n, maxjump;
    2795             : #ifndef LEGACY_COMPILER
    2796             :     int64_t exp;
    2797             : #else
    2798             :     mpd_uint_t x;
    2799             :     int x_sign, n_sign;
    2800             :     mpd_ssize_t exp;
    2801             : #endif
    2802             : 
    2803           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    2804           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    2805             :             return;
    2806             :         }
    2807             :     }
    2808           0 :     if (b->exp != 0 || mpd_isinfinite(b)) {
    2809           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2810             :         return;
    2811             :     }
    2812             : 
    2813           0 :     n = mpd_qabs_uint(b, &workstatus);
    2814             :     /* the spec demands this */
    2815           0 :     maxjump = 2 * (mpd_uint_t)(ctx->emax + ctx->prec);
    2816             : 
    2817           0 :     if (n > maxjump || workstatus&MPD_Invalid_operation) {
    2818           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2819             :         return;
    2820             :     }
    2821           0 :     if (mpd_isinfinite(a)) {
    2822           0 :         mpd_qcopy(result, a, status);
    2823             :         return;
    2824             :     }
    2825             : 
    2826             : #ifndef LEGACY_COMPILER
    2827           0 :     exp = a->exp + (int64_t)n * mpd_arith_sign(b);
    2828           0 :     exp = (exp > MPD_EXP_INF) ? MPD_EXP_INF : exp;
    2829           0 :     exp = (exp < MPD_EXP_CLAMP) ? MPD_EXP_CLAMP : exp;
    2830             : #else
    2831             :     x = (a->exp < 0) ? -a->exp : a->exp;
    2832             :     x_sign = (a->exp < 0) ? 1 : 0;
    2833             :     n_sign = mpd_isnegative(b) ? 1 : 0;
    2834             : 
    2835             :     if (x_sign == n_sign) {
    2836             :         x = x + n;
    2837             :         if (x < n) x = MPD_UINT_MAX;
    2838             :     }
    2839             :     else {
    2840             :         x_sign = (x >= n) ? x_sign : n_sign;
    2841             :         x = (x >= n) ? x - n : n - x;
    2842             :     }
    2843             :     if (!x_sign && x > MPD_EXP_INF) x = MPD_EXP_INF;
    2844             :     if (x_sign && x > -MPD_EXP_CLAMP) x = -MPD_EXP_CLAMP;
    2845             :     exp = x_sign ? -((mpd_ssize_t)x) : (mpd_ssize_t)x;
    2846             : #endif
    2847             : 
    2848           0 :     mpd_qcopy(result, a, status);
    2849           0 :     result->exp = (mpd_ssize_t)exp;
    2850             : 
    2851           0 :     mpd_qfinalize(result, ctx, status);
    2852             : }
    2853             : 
    2854             : /*
    2855             :  * Shift the coefficient by n digits, positive n is a left shift. In the case
    2856             :  * of a left shift, the result is decapitated to fit the context precision. If
    2857             :  * you don't want that, use mpd_shiftl().
    2858             :  */
    2859             : void
    2860           0 : mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx,
    2861             :             uint32_t *status)
    2862             : {
    2863           0 :     if (mpd_isspecial(a)) {
    2864           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    2865           0 :             return;
    2866             :         }
    2867           0 :         mpd_qcopy(result, a, status);
    2868           0 :         return;
    2869             :     }
    2870             : 
    2871           0 :     if (n >= 0 && n <= ctx->prec) {
    2872           0 :         mpd_qshiftl(result, a, n, status);
    2873           0 :         _mpd_cap(result, ctx);
    2874             :     }
    2875           0 :     else if (n < 0 && n >= -ctx->prec) {
    2876           0 :         if (!mpd_qcopy(result, a, status)) {
    2877           0 :             return;
    2878             :         }
    2879           0 :         _mpd_cap(result, ctx);
    2880           0 :         mpd_qshiftr_inplace(result, -n);
    2881             :     }
    2882             :     else {
    2883           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2884             :     }
    2885             : }
    2886             : 
    2887             : /*
    2888             :  * Same as mpd_shiftn(), but the shift is specified by the decimal b, which
    2889             :  * must be an integer with a zero exponent. Infinities remain infinities.
    2890             :  */
    2891             : void
    2892           0 : mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx,
    2893             :            uint32_t *status)
    2894             : {
    2895           0 :     uint32_t workstatus = 0;
    2896             :     mpd_ssize_t n;
    2897             : 
    2898           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    2899           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    2900             :             return;
    2901             :         }
    2902             :     }
    2903           0 :     if (b->exp != 0 || mpd_isinfinite(b)) {
    2904           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2905             :         return;
    2906             :     }
    2907             : 
    2908           0 :     n = mpd_qget_ssize(b, &workstatus);
    2909           0 :     if (workstatus&MPD_Invalid_operation) {
    2910           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2911             :         return;
    2912             :     }
    2913           0 :     if (n > ctx->prec || n < -ctx->prec) {
    2914           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2915             :         return;
    2916             :     }
    2917           0 :     if (mpd_isinfinite(a)) {
    2918           0 :         mpd_qcopy(result, a, status);
    2919             :         return;
    2920             :     }
    2921             : 
    2922           0 :     if (n >= 0) {
    2923           0 :         mpd_qshiftl(result, a, n, status);
    2924           0 :         _mpd_cap(result, ctx);
    2925             :     }
    2926             :     else {
    2927           0 :         if (!mpd_qcopy(result, a, status)) {
    2928             :             return;
    2929             :         }
    2930           0 :         _mpd_cap(result, ctx);
    2931           0 :         mpd_qshiftr_inplace(result, -n);
    2932             :     }
    2933             : }
    2934             : 
    2935             : /* Logical Xor */
    2936             : void
    2937           0 : mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b,
    2938             :         const mpd_context_t *ctx, uint32_t *status)
    2939             : {
    2940           0 :     const mpd_t *big = a, *small = b;
    2941             :     mpd_uint_t x, y, z, xbit, ybit;
    2942             :     int k, mswdigits;
    2943             :     mpd_ssize_t i;
    2944             : 
    2945           0 :     if (mpd_isspecial(a) || mpd_isspecial(b) ||
    2946           0 :         mpd_isnegative(a) || mpd_isnegative(b) ||
    2947           0 :         a->exp != 0 || b->exp != 0) {
    2948           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    2949           0 :         return;
    2950             :     }
    2951           0 :     if (b->digits > a->digits) {
    2952           0 :         big = b;
    2953           0 :         small = a;
    2954             :     }
    2955           0 :     if (!mpd_qresize(result, big->len, status)) {
    2956           0 :         return;
    2957             :     }
    2958             : 
    2959             : 
    2960             :     /* full words */
    2961           0 :     for (i = 0; i < small->len-1; i++) {
    2962           0 :         x = small->data[i];
    2963           0 :         y = big->data[i];
    2964           0 :         z = 0;
    2965           0 :         for (k = 0; k < MPD_RDIGITS; k++) {
    2966           0 :             xbit = x % 10;
    2967           0 :             x /= 10;
    2968           0 :             ybit = y % 10;
    2969           0 :             y /= 10;
    2970           0 :             if (xbit > 1 || ybit > 1) {
    2971             :                 goto invalid_operation;
    2972             :             }
    2973           0 :             z += (xbit^ybit) ? mpd_pow10[k] : 0;
    2974             :         }
    2975           0 :         result->data[i] = z;
    2976             :     }
    2977             :     /* most significant word of small */
    2978           0 :     x = small->data[i];
    2979           0 :     y = big->data[i];
    2980           0 :     z = 0;
    2981           0 :     mswdigits = mpd_word_digits(x);
    2982           0 :     for (k = 0; k < mswdigits; k++) {
    2983           0 :         xbit = x % 10;
    2984           0 :         x /= 10;
    2985           0 :         ybit = y % 10;
    2986           0 :         y /= 10;
    2987           0 :         if (xbit > 1 || ybit > 1) {
    2988             :             goto invalid_operation;
    2989             :         }
    2990           0 :         z += (xbit^ybit) ? mpd_pow10[k] : 0;
    2991             :     }
    2992             : 
    2993             :     /* scan for digits > 1 and copy the rest of y */
    2994           0 :     for (; k < MPD_RDIGITS; k++) {
    2995           0 :         ybit = y % 10;
    2996           0 :         y /= 10;
    2997           0 :         if (ybit > 1) {
    2998           0 :             goto invalid_operation;
    2999             :         }
    3000           0 :         z += ybit*mpd_pow10[k];
    3001             :     }
    3002           0 :     result->data[i++] = z;
    3003             :     /* scan for digits > 1 and copy the rest of big */
    3004           0 :     for (; i < big->len; i++) {
    3005           0 :         y = big->data[i];
    3006           0 :         for (k = 0; k < MPD_RDIGITS; k++) {
    3007           0 :             ybit = y % 10;
    3008           0 :             y /= 10;
    3009           0 :             if (ybit > 1) {
    3010           0 :                 goto invalid_operation;
    3011             :             }
    3012             :         }
    3013           0 :         result->data[i] = big->data[i];
    3014             :     }
    3015             : 
    3016             :     mpd_clear_flags(result);
    3017           0 :     result->exp = 0;
    3018           0 :     result->len = _mpd_real_size(result->data, big->len);
    3019           0 :     mpd_qresize(result, result->len, status);
    3020           0 :     mpd_setdigits(result);
    3021           0 :     _mpd_cap(result, ctx);
    3022           0 :     return;
    3023             : 
    3024             : invalid_operation:
    3025           0 :     mpd_seterror(result, MPD_Invalid_operation, status);
    3026             : }
    3027             : 
    3028             : 
    3029             : /******************************************************************************/
    3030             : /*                         Arithmetic operations                              */
    3031             : /******************************************************************************/
    3032             : 
    3033             : /*
    3034             :  * The absolute value of a. If a is negative, the result is the same
    3035             :  * as the result of the minus operation. Otherwise, the result is the
    3036             :  * result of the plus operation.
    3037             :  */
    3038             : void
    3039           0 : mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    3040             :          uint32_t *status)
    3041             : {
    3042           0 :     if (mpd_isspecial(a)) {
    3043           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    3044           0 :             return;
    3045             :         }
    3046             :     }
    3047             : 
    3048           0 :     if (mpd_isnegative(a)) {
    3049           0 :         mpd_qminus(result, a, ctx, status);
    3050             :     }
    3051             :     else {
    3052           0 :         mpd_qplus(result, a, ctx, status);
    3053             :     }
    3054             : }
    3055             : 
    3056             : static inline void
    3057           0 : _mpd_ptrswap(mpd_t **a, mpd_t **b)
    3058             : {
    3059           0 :     mpd_t *t = *a;
    3060           0 :     *a = *b;
    3061           0 :     *b = t;
    3062           0 : }
    3063             : 
    3064             : /* Add or subtract infinities. */
    3065             : static void
    3066           0 : _mpd_qaddsub_inf(mpd_t *result, const mpd_t *a, const mpd_t *b, uint8_t sign_b,
    3067             :                  uint32_t *status)
    3068             : {
    3069           0 :     if (mpd_isinfinite(a)) {
    3070           0 :         if (mpd_sign(a) != sign_b && mpd_isinfinite(b)) {
    3071           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    3072             :         }
    3073             :         else {
    3074           0 :             mpd_setspecial(result, mpd_sign(a), MPD_INF);
    3075             :         }
    3076           0 :         return;
    3077             :     }
    3078             :     assert(mpd_isinfinite(b));
    3079           0 :     mpd_setspecial(result, sign_b, MPD_INF);
    3080             : }
    3081             : 
    3082             : /* Add or subtract non-special numbers. */
    3083             : static void
    3084           0 : _mpd_qaddsub(mpd_t *result, const mpd_t *a, const mpd_t *b, uint8_t sign_b,
    3085             :              const mpd_context_t *ctx, uint32_t *status)
    3086             : {
    3087             :     mpd_t *big, *small;
    3088           0 :     MPD_NEW_STATIC(big_aligned,0,0,0,0);
    3089           0 :     MPD_NEW_CONST(tiny,0,0,1,1,1,1);
    3090             :     mpd_uint_t carry;
    3091             :     mpd_ssize_t newsize, shift;
    3092             :     mpd_ssize_t exp, i;
    3093           0 :     int swap = 0;
    3094             : 
    3095             : 
    3096             :     /* compare exponents */
    3097           0 :     big = (mpd_t *)a; small = (mpd_t *)b;
    3098           0 :     if (big->exp != small->exp) {
    3099           0 :         if (small->exp > big->exp) {
    3100           0 :             _mpd_ptrswap(&big, &small);
    3101           0 :             swap++;
    3102             :         }
    3103             :         /* align the coefficients */
    3104           0 :         if (!mpd_iszerocoeff(big)) {
    3105           0 :             exp = big->exp - 1;
    3106           0 :             exp += (big->digits > ctx->prec) ? 0 : big->digits-ctx->prec-1;
    3107           0 :             if (mpd_adjexp(small) < exp) {
    3108             :                 /*
    3109             :                  * Avoid huge shifts by substituting a value for small that is
    3110             :                  * guaranteed to produce the same results.
    3111             :                  *
    3112             :                  * adjexp(small) < exp if and only if:
    3113             :                  *
    3114             :                  *   bdigits <= prec AND
    3115             :                  *   bdigits+shift >= prec+2+sdigits AND
    3116             :                  *   exp = bexp+bdigits-prec-2
    3117             :                  *
    3118             :                  *     1234567000000000  ->  bdigits + shift
    3119             :                  *     ----------XX1234  ->  sdigits
    3120             :                  *     ----------X1      ->  tiny-digits
    3121             :                  *     |- prec -|
    3122             :                  *     
    3123             :                  *      OR
    3124             :                  *
    3125             :                  *   bdigits > prec AND
    3126             :                  *   shift > sdigits AND
    3127             :                  *   exp = bexp-1
    3128             :                  *
    3129             :                  *     1234567892100000  ->  bdigits + shift
    3130             :                  *     ----------XX1234  ->  sdigits
    3131             :                  *     ----------X1      ->  tiny-digits
    3132             :                  *     |- prec -|
    3133             :                  *
    3134             :                  * If tiny is zero, adding or subtracting is a no-op.
    3135             :                  * Otherwise, adding tiny generates a non-zero digit either
    3136             :                  * below the rounding digit or the least significant digit
    3137             :                  * of big. When subtracting, tiny is in the same position as
    3138             :                  * the carry that would be generated by subtracting sdigits.
    3139             :                  */
    3140           0 :                 mpd_copy_flags(&tiny, small);
    3141           0 :                 tiny.exp = exp;
    3142           0 :                 tiny.digits = 1;
    3143           0 :                 tiny.len = 1;
    3144           0 :                 tiny.data[0] = mpd_iszerocoeff(small) ? 0 : 1;
    3145           0 :                 small = &tiny;
    3146             :             }
    3147             :             /* This cannot wrap: the difference is positive and <= maxprec */
    3148           0 :             shift = big->exp - small->exp;
    3149           0 :             if (!mpd_qshiftl(&big_aligned, big, shift, status)) {
    3150           0 :                 mpd_seterror(result, MPD_Malloc_error, status);
    3151           0 :                 goto finish;
    3152             :             }
    3153           0 :             big = &big_aligned;
    3154             :         }
    3155             :     }
    3156           0 :     result->exp = small->exp;
    3157             : 
    3158             : 
    3159             :     /* compare length of coefficients */
    3160           0 :     if (big->len < small->len) {
    3161           0 :         _mpd_ptrswap(&big, &small);
    3162           0 :         swap++;
    3163             :     }
    3164             : 
    3165           0 :     newsize = big->len;
    3166           0 :     if (!mpd_qresize(result, newsize, status)) {
    3167           0 :         goto finish;
    3168             :     }
    3169             : 
    3170           0 :     if (mpd_sign(a) == sign_b) {
    3171             : 
    3172           0 :         carry = _mpd_baseadd(result->data, big->data, small->data,
    3173           0 :                              big->len, small->len);
    3174             : 
    3175           0 :         if (carry) {
    3176           0 :             newsize = big->len + 1;
    3177           0 :             if (!mpd_qresize(result, newsize, status)) {
    3178           0 :                 goto finish;
    3179             :             }
    3180           0 :             result->data[newsize-1] = carry;
    3181             :         }
    3182             : 
    3183           0 :         result->len = newsize;
    3184           0 :         mpd_set_flags(result, sign_b);
    3185             :     }
    3186             :     else {
    3187           0 :         if (big->len == small->len) {
    3188           0 :             for (i=big->len-1; i >= 0; --i) {
    3189           0 :                 if (big->data[i] != small->data[i]) {
    3190           0 :                     if (big->data[i] < small->data[i]) {
    3191           0 :                         _mpd_ptrswap(&big, &small);
    3192           0 :                         swap++;
    3193             :                     }
    3194           0 :                     break;
    3195             :                 }
    3196             :             }
    3197             :         }
    3198             : 
    3199           0 :         _mpd_basesub(result->data, big->data, small->data,
    3200           0 :                      big->len, small->len);
    3201           0 :         newsize = _mpd_real_size(result->data, big->len);
    3202             :         /* resize to smaller cannot fail */
    3203             :         (void)mpd_qresize(result, newsize, status);
    3204             : 
    3205           0 :         result->len = newsize;
    3206           0 :         sign_b = (swap & 1) ? sign_b : mpd_sign(a);
    3207           0 :         mpd_set_flags(result, sign_b);
    3208             : 
    3209           0 :         if (mpd_iszerocoeff(result)) {
    3210             :             mpd_set_positive(result);
    3211           0 :             if (ctx->round == MPD_ROUND_FLOOR) {
    3212             :                 mpd_set_negative(result);
    3213             :             }
    3214             :         }
    3215             :     }
    3216             : 
    3217           0 :     mpd_setdigits(result);
    3218             : 
    3219             : finish:
    3220             :     mpd_del(&big_aligned);
    3221           0 : }
    3222             : 
    3223             : /* Add a and b. No specials, no finalizing. */
    3224             : static void
    3225           0 : _mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
    3226             :           const mpd_context_t *ctx, uint32_t *status)
    3227             : {
    3228           0 :     _mpd_qaddsub(result, a, b, mpd_sign(b), ctx, status);
    3229           0 : }
    3230             : 
    3231             : /* Subtract b from a. No specials, no finalizing. */
    3232             : static void
    3233           0 : _mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b,
    3234             :           const mpd_context_t *ctx, uint32_t *status)
    3235             : {
    3236           0 :      _mpd_qaddsub(result, a, b, !mpd_sign(b), ctx, status);
    3237           0 : }
    3238             : 
    3239             : /* Add a and b. */
    3240             : void
    3241           0 : mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b,
    3242             :          const mpd_context_t *ctx, uint32_t *status)
    3243             : {
    3244           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    3245           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    3246           0 :             return;
    3247             :         }
    3248           0 :         _mpd_qaddsub_inf(result, a, b, mpd_sign(b), status);
    3249           0 :         return;
    3250             :     }
    3251             : 
    3252           0 :     _mpd_qaddsub(result, a, b, mpd_sign(b), ctx, status);
    3253           0 :     mpd_qfinalize(result, ctx, status);
    3254             : }
    3255             : 
    3256             : /* Add a and b. Set NaN/Invalid_operation if the result is inexact. */
    3257             : static void
    3258           0 : _mpd_qadd_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,
    3259             :                 const mpd_context_t *ctx, uint32_t *status)
    3260             : {
    3261           0 :     uint32_t workstatus = 0;
    3262             : 
    3263           0 :     mpd_qadd(result, a, b, ctx, &workstatus);
    3264           0 :     *status |= workstatus;
    3265           0 :     if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
    3266           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    3267             :     }
    3268           0 : }
    3269             : 
    3270             : /* Subtract b from a. */
    3271             : void
    3272           0 : mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b,
    3273             :          const mpd_context_t *ctx, uint32_t *status)
    3274             : {
    3275           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    3276           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    3277           0 :             return;
    3278             :         }
    3279           0 :         _mpd_qaddsub_inf(result, a, b, !mpd_sign(b), status);
    3280           0 :         return;
    3281             :     }
    3282             : 
    3283           0 :     _mpd_qaddsub(result, a, b, !mpd_sign(b), ctx, status);
    3284           0 :     mpd_qfinalize(result, ctx, status);
    3285             : }
    3286             : 
    3287             : /* Subtract b from a. Set NaN/Invalid_operation if the result is inexact. */
    3288             : static void
    3289           0 : _mpd_qsub_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,
    3290             :                 const mpd_context_t *ctx, uint32_t *status)
    3291             : {
    3292           0 :     uint32_t workstatus = 0;
    3293             : 
    3294           0 :     mpd_qsub(result, a, b, ctx, &workstatus);
    3295           0 :     *status |= workstatus;
    3296           0 :     if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
    3297           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    3298             :     }
    3299           0 : }
    3300             : 
    3301             : /* Add decimal and mpd_ssize_t. */
    3302             : void
    3303           0 : mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,
    3304             :                const mpd_context_t *ctx, uint32_t *status)
    3305             : {
    3306             :     mpd_context_t maxcontext;
    3307           0 :     MPD_NEW_STATIC(bb,0,0,0,0);
    3308             : 
    3309           0 :     mpd_maxcontext(&maxcontext);
    3310           0 :     mpd_qsset_ssize(&bb, b, &maxcontext, status);
    3311           0 :     mpd_qadd(result, a, &bb, ctx, status);
    3312             :     mpd_del(&bb);
    3313           0 : }
    3314             : 
    3315             : /* Add decimal and mpd_uint_t. */
    3316             : void
    3317           0 : mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,
    3318             :               const mpd_context_t *ctx, uint32_t *status)
    3319             : {
    3320             :     mpd_context_t maxcontext;
    3321           0 :     MPD_NEW_STATIC(bb,0,0,0,0);
    3322             : 
    3323           0 :     mpd_maxcontext(&maxcontext);
    3324           0 :     mpd_qsset_uint(&bb, b, &maxcontext, status);
    3325           0 :     mpd_qadd(result, a, &bb, ctx, status);
    3326             :     mpd_del(&bb);
    3327           0 : }
    3328             : 
    3329             : /* Subtract mpd_ssize_t from decimal. */
    3330             : void
    3331           0 : mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,
    3332             :                const mpd_context_t *ctx, uint32_t *status)
    3333             : {
    3334             :     mpd_context_t maxcontext;
    3335           0 :     MPD_NEW_STATIC(bb,0,0,0,0);
    3336             : 
    3337           0 :     mpd_maxcontext(&maxcontext);
    3338           0 :     mpd_qsset_ssize(&bb, b, &maxcontext, status);
    3339           0 :     mpd_qsub(result, a, &bb, ctx, status);
    3340             :     mpd_del(&bb);
    3341           0 : }
    3342             : 
    3343             : /* Subtract mpd_uint_t from decimal. */
    3344             : void
    3345           0 : mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,
    3346             :               const mpd_context_t *ctx, uint32_t *status)
    3347             : {
    3348             :     mpd_context_t maxcontext;
    3349           0 :     MPD_NEW_STATIC(bb,0,0,0,0);
    3350             : 
    3351           0 :     mpd_maxcontext(&maxcontext);
    3352           0 :     mpd_qsset_uint(&bb, b, &maxcontext, status);
    3353           0 :     mpd_qsub(result, a, &bb, ctx, status);
    3354             :     mpd_del(&bb);
    3355           0 : }
    3356             : 
    3357             : /* Add decimal and int32_t. */
    3358             : void
    3359           0 : mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b,
    3360             :              const mpd_context_t *ctx, uint32_t *status)
    3361             : {
    3362           0 :     mpd_qadd_ssize(result, a, b, ctx, status);
    3363           0 : }
    3364             : 
    3365             : /* Add decimal and uint32_t. */
    3366             : void
    3367           0 : mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b,
    3368             :              const mpd_context_t *ctx, uint32_t *status)
    3369             : {
    3370           0 :     mpd_qadd_uint(result, a, b, ctx, status);
    3371           0 : }
    3372             : 
    3373             : #ifdef CONFIG_64
    3374             : /* Add decimal and int64_t. */
    3375             : void
    3376             : mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b,
    3377             :              const mpd_context_t *ctx, uint32_t *status)
    3378             : {
    3379             :     mpd_qadd_ssize(result, a, b, ctx, status);
    3380             : }
    3381             : 
    3382             : /* Add decimal and uint64_t. */
    3383             : void
    3384             : mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b,
    3385             :              const mpd_context_t *ctx, uint32_t *status)
    3386             : {
    3387             :     mpd_qadd_uint(result, a, b, ctx, status);
    3388             : }
    3389             : #endif
    3390             : 
    3391             : /* Subtract int32_t from decimal. */
    3392             : void
    3393           0 : mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b,
    3394             :              const mpd_context_t *ctx, uint32_t *status)
    3395             : {
    3396           0 :     mpd_qsub_ssize(result, a, b, ctx, status);
    3397           0 : }
    3398             : 
    3399             : /* Subtract uint32_t from decimal. */
    3400             : void
    3401           0 : mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b,
    3402             :              const mpd_context_t *ctx, uint32_t *status)
    3403             : {
    3404           0 :     mpd_qsub_uint(result, a, b, ctx, status);
    3405           0 : }
    3406             : 
    3407             : #ifdef CONFIG_64
    3408             : /* Subtract int64_t from decimal. */
    3409             : void
    3410             : mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b,
    3411             :              const mpd_context_t *ctx, uint32_t *status)
    3412             : {
    3413             :     mpd_qsub_ssize(result, a, b, ctx, status);
    3414             : }
    3415             : 
    3416             : /* Subtract uint64_t from decimal. */
    3417             : void
    3418             : mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b,
    3419             :              const mpd_context_t *ctx, uint32_t *status)
    3420             : {
    3421             :     mpd_qsub_uint(result, a, b, ctx, status);
    3422             : }
    3423             : #endif
    3424             : 
    3425             : 
    3426             : /* Divide infinities. */
    3427             : static void
    3428           0 : _mpd_qdiv_inf(mpd_t *result, const mpd_t *a, const mpd_t *b,
    3429             :               const mpd_context_t *ctx, uint32_t *status)
    3430             : {
    3431           0 :     if (mpd_isinfinite(a)) {
    3432           0 :         if (mpd_isinfinite(b)) {
    3433           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    3434           0 :             return;
    3435             :         }
    3436           0 :         mpd_setspecial(result, mpd_sign(a)^mpd_sign(b), MPD_INF);
    3437           0 :         return;
    3438             :     }
    3439             :     assert(mpd_isinfinite(b));
    3440           0 :     _settriple(result, mpd_sign(a)^mpd_sign(b), 0, mpd_etiny(ctx));
    3441           0 :     *status |= MPD_Clamped;
    3442             : }
    3443             : 
    3444             : enum {NO_IDEAL_EXP, SET_IDEAL_EXP};
    3445             : /* Divide a by b. */
    3446             : static void
    3447           0 : _mpd_qdiv(int action, mpd_t *q, const mpd_t *a, const mpd_t *b,
    3448             :           const mpd_context_t *ctx, uint32_t *status)
    3449             : {
    3450           0 :     MPD_NEW_STATIC(aligned,0,0,0,0);
    3451             :     mpd_uint_t ld;
    3452             :     mpd_ssize_t shift, exp, tz;
    3453             :     mpd_ssize_t newsize;
    3454             :     mpd_ssize_t ideal_exp;
    3455             :     mpd_uint_t rem;
    3456           0 :     uint8_t sign_a = mpd_sign(a);
    3457           0 :     uint8_t sign_b = mpd_sign(b);
    3458             : 
    3459             : 
    3460           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    3461           0 :         if (mpd_qcheck_nans(q, a, b, ctx, status)) {
    3462             :             return;
    3463             :         }
    3464           0 :         _mpd_qdiv_inf(q, a, b, ctx, status);
    3465             :         return;
    3466             :     }
    3467           0 :     if (mpd_iszerocoeff(b)) {
    3468           0 :         if (mpd_iszerocoeff(a)) {
    3469           0 :             mpd_seterror(q, MPD_Division_undefined, status);
    3470             :         }
    3471             :         else {
    3472           0 :             mpd_setspecial(q, sign_a^sign_b, MPD_INF);
    3473           0 :             *status |= MPD_Division_by_zero;
    3474             :         }
    3475             :         return;
    3476             :     }
    3477           0 :     if (mpd_iszerocoeff(a)) {
    3478           0 :         exp = a->exp - b->exp;
    3479           0 :         _settriple(q, sign_a^sign_b, 0, exp);
    3480           0 :         mpd_qfinalize(q, ctx, status);
    3481             :         return;
    3482             :     }
    3483             : 
    3484           0 :     shift = (b->digits - a->digits) + ctx->prec + 1;
    3485           0 :     ideal_exp = a->exp - b->exp;
    3486           0 :     exp = ideal_exp - shift;
    3487           0 :     if (shift > 0) {
    3488           0 :         if (!mpd_qshiftl(&aligned, a, shift, status)) {
    3489           0 :             mpd_seterror(q, MPD_Malloc_error, status);
    3490           0 :             goto finish;
    3491             :         }
    3492           0 :         a = &aligned;
    3493             :     }
    3494           0 :     else if (shift < 0) {
    3495           0 :         shift = -shift;
    3496           0 :         if (!mpd_qshiftl(&aligned, b, shift, status)) {
    3497           0 :             mpd_seterror(q, MPD_Malloc_error, status);
    3498           0 :             goto finish;
    3499             :         }
    3500           0 :         b = &aligned;
    3501             :     }
    3502             : 
    3503             : 
    3504           0 :     newsize = a->len - b->len + 1;
    3505           0 :     if ((q != b && q != a) || (q == b && newsize > b->len)) {
    3506           0 :         if (!mpd_qresize(q, newsize, status)) {
    3507           0 :             mpd_seterror(q, MPD_Malloc_error, status);
    3508           0 :             goto finish;
    3509             :         }
    3510             :     }
    3511             : 
    3512             : 
    3513           0 :     if (b->len == 1) {
    3514           0 :         rem = _mpd_shortdiv(q->data, a->data, a->len, b->data[0]);
    3515             :     }
    3516           0 :     else if (b->len <= MPD_NEWTONDIV_CUTOFF) {
    3517           0 :         int ret = _mpd_basedivmod(q->data, NULL, a->data, b->data,
    3518           0 :                                   a->len, b->len);
    3519           0 :         if (ret < 0) {
    3520           0 :             mpd_seterror(q, MPD_Malloc_error, status);
    3521           0 :             goto finish;
    3522             :         }
    3523           0 :         rem = ret;
    3524             :     }
    3525             :     else {
    3526           0 :         MPD_NEW_STATIC(r,0,0,0,0);
    3527           0 :         _mpd_base_ndivmod(q, &r, a, b, status);
    3528           0 :         if (mpd_isspecial(q) || mpd_isspecial(&r)) {
    3529           0 :             mpd_setspecial(q, MPD_POS, MPD_NAN);
    3530             :             mpd_del(&r);
    3531             :             goto finish;
    3532             :         }
    3533           0 :         rem = !mpd_iszerocoeff(&r);
    3534             :         mpd_del(&r);
    3535           0 :         newsize = q->len;
    3536             :     }
    3537             : 
    3538           0 :     newsize = _mpd_real_size(q->data, newsize);
    3539             :     /* resize to smaller cannot fail */
    3540             :     mpd_qresize(q, newsize, status);
    3541           0 :     mpd_set_flags(q, sign_a^sign_b);
    3542           0 :     q->len = newsize;
    3543           0 :     mpd_setdigits(q);
    3544             : 
    3545           0 :     shift = ideal_exp - exp;
    3546           0 :     if (rem) {
    3547           0 :         ld = mpd_lsd(q->data[0]);
    3548           0 :         if (ld == 0 || ld == 5) {
    3549           0 :             q->data[0] += 1;
    3550             :         }
    3551             :     }
    3552           0 :     else if (action == SET_IDEAL_EXP && shift > 0) {
    3553           0 :         tz = mpd_trail_zeros(q);
    3554           0 :         shift = (tz > shift) ? shift : tz;
    3555           0 :         mpd_qshiftr_inplace(q, shift);
    3556           0 :         exp += shift;
    3557             :     }
    3558             : 
    3559           0 :     q->exp = exp;
    3560             : 
    3561             : 
    3562             : finish:
    3563             :     mpd_del(&aligned);
    3564           0 :     mpd_qfinalize(q, ctx, status);
    3565             : }
    3566             : 
    3567             : /* Divide a by b. */
    3568             : void
    3569           0 : mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b,
    3570             :          const mpd_context_t *ctx, uint32_t *status)
    3571             : {
    3572           0 :     _mpd_qdiv(SET_IDEAL_EXP, q, a, b, ctx, status);
    3573           0 : }
    3574             : 
    3575             : /* Internal function. */
    3576             : static void
    3577           0 : _mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,
    3578             :              const mpd_context_t *ctx, uint32_t *status)
    3579             : {
    3580           0 :     MPD_NEW_STATIC(aligned,0,0,0,0);
    3581             :     mpd_ssize_t qsize, rsize;
    3582             :     mpd_ssize_t ideal_exp, expdiff, shift;
    3583           0 :     uint8_t sign_a = mpd_sign(a);
    3584           0 :     uint8_t sign_ab = mpd_sign(a)^mpd_sign(b);
    3585             : 
    3586             : 
    3587           0 :     ideal_exp = (a->exp > b->exp) ?  b->exp : a->exp;
    3588           0 :     if (mpd_iszerocoeff(a)) {
    3589           0 :         if (!mpd_qcopy(r, a, status)) {
    3590           0 :             goto nanresult; /* GCOV_NOT_REACHED */
    3591             :         }
    3592           0 :         r->exp = ideal_exp;
    3593           0 :         _settriple(q, sign_ab, 0, 0);
    3594             :         return;
    3595             :     }
    3596             : 
    3597           0 :     expdiff = mpd_adjexp(a) - mpd_adjexp(b);
    3598           0 :     if (expdiff < 0) {
    3599           0 :         if (a->exp > b->exp) {
    3600             :             /* positive and less than b->digits - a->digits */
    3601           0 :             shift = a->exp - b->exp;
    3602           0 :             if (!mpd_qshiftl(r, a, shift, status)) {
    3603           0 :                 goto nanresult;
    3604             :             }
    3605           0 :             r->exp = ideal_exp;
    3606             :         }
    3607             :         else {
    3608           0 :             if (!mpd_qcopy(r, a, status)) {
    3609           0 :                 goto nanresult;
    3610             :             }
    3611             :         }
    3612           0 :         _settriple(q, sign_ab, 0, 0);
    3613             :         return;
    3614             :     }
    3615           0 :     if (expdiff > ctx->prec) {
    3616           0 :         *status |= MPD_Division_impossible;
    3617           0 :         goto nanresult;
    3618             :     }
    3619             : 
    3620             : 
    3621             :     /*
    3622             :      * At this point we have:
    3623             :      *   (1) 0 <= a->exp + a->digits - b->exp - b->digits <= prec
    3624             :      *   (2) a->exp - b->exp >= b->digits - a->digits
    3625             :      *   (3) a->exp - b->exp <= prec + b->digits - a->digits
    3626             :      */
    3627           0 :     if (a->exp != b->exp) {
    3628           0 :         shift = a->exp - b->exp;
    3629           0 :         if (shift > 0) {
    3630             :             /* by (3), after the shift a->digits <= prec + b->digits */
    3631           0 :             if (!mpd_qshiftl(&aligned, a, shift, status)) {
    3632           0 :                 goto nanresult;
    3633             :             }
    3634           0 :             a = &aligned;
    3635             :         }
    3636             :         else  {
    3637           0 :             shift = -shift;
    3638             :             /* by (2), after the shift b->digits <= a->digits */
    3639           0 :             if (!mpd_qshiftl(&aligned, b, shift, status)) {
    3640           0 :                 goto nanresult;
    3641             :             }
    3642           0 :             b = &aligned;
    3643             :         }
    3644             :     }
    3645             : 
    3646             : 
    3647           0 :     qsize = a->len - b->len + 1;
    3648           0 :     if (!(q == a && qsize < a->len) && !(q == b && qsize < b->len)) {
    3649           0 :         if (!mpd_qresize(q, qsize, status)) {
    3650           0 :             goto nanresult;
    3651             :         }
    3652             :     }
    3653             : 
    3654           0 :     rsize = b->len;
    3655           0 :     if (!(r == a && rsize < a->len)) {
    3656           0 :         if (!mpd_qresize(r, rsize, status)) {
    3657           0 :             goto nanresult;
    3658             :         }
    3659             :     }
    3660             : 
    3661           0 :     if (b->len == 1) {
    3662           0 :         if (a->len == 1) {
    3663           0 :             _mpd_div_word(&q->data[0], &r->data[0], a->data[0], b->data[0]);
    3664             :         }
    3665             :         else {
    3666           0 :             r->data[0] = _mpd_shortdiv(q->data, a->data, a->len, b->data[0]);
    3667             :         }
    3668             :     }
    3669           0 :     else if (b->len <= MPD_NEWTONDIV_CUTOFF) {
    3670             :         int ret;
    3671           0 :         ret = _mpd_basedivmod(q->data, r->data, a->data, b->data,
    3672           0 :                               a->len, b->len);
    3673           0 :         if (ret == -1) {
    3674           0 :             *status |= MPD_Malloc_error;
    3675           0 :             goto nanresult;
    3676             :         }
    3677             :     }
    3678             :     else {
    3679           0 :         _mpd_base_ndivmod(q, r, a, b, status);
    3680           0 :         if (mpd_isspecial(q) || mpd_isspecial(r)) {
    3681             :             goto nanresult;
    3682             :         }
    3683           0 :         qsize = q->len;
    3684           0 :         rsize = r->len;
    3685             :     }
    3686             : 
    3687           0 :     qsize = _mpd_real_size(q->data, qsize);
    3688             :     /* resize to smaller cannot fail */
    3689             :     mpd_qresize(q, qsize, status);
    3690           0 :     q->len = qsize;
    3691           0 :     mpd_setdigits(q);
    3692           0 :     mpd_set_flags(q, sign_ab);
    3693           0 :     q->exp = 0;
    3694           0 :     if (q->digits > ctx->prec) {
    3695           0 :         *status |= MPD_Division_impossible;
    3696           0 :         goto nanresult;
    3697             :     }
    3698             : 
    3699           0 :     rsize = _mpd_real_size(r->data, rsize);
    3700             :     /* resize to smaller cannot fail */
    3701             :     mpd_qresize(r, rsize, status);
    3702           0 :     r->len = rsize;
    3703           0 :     mpd_setdigits(r);
    3704           0 :     mpd_set_flags(r, sign_a);
    3705           0 :     r->exp = ideal_exp;
    3706             : 
    3707             : out:
    3708             :     mpd_del(&aligned);
    3709             :     return;
    3710             : 
    3711             : nanresult:
    3712           0 :     mpd_setspecial(q, MPD_POS, MPD_NAN);
    3713           0 :     mpd_setspecial(r, MPD_POS, MPD_NAN);
    3714           0 :     goto out;
    3715             : }
    3716             : 
    3717             : /* Integer division with remainder. */
    3718             : void
    3719           0 : mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,
    3720             :             const mpd_context_t *ctx, uint32_t *status)
    3721             : {
    3722           0 :     uint8_t sign = mpd_sign(a)^mpd_sign(b);
    3723             : 
    3724           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    3725           0 :         if (mpd_qcheck_nans(q, a, b, ctx, status)) {
    3726           0 :             mpd_qcopy(r, q, status);
    3727           0 :             return;
    3728             :         }
    3729           0 :         if (mpd_isinfinite(a)) {
    3730           0 :             if (mpd_isinfinite(b)) {
    3731           0 :                 mpd_setspecial(q, MPD_POS, MPD_NAN);
    3732             :             }
    3733             :             else {
    3734           0 :                 mpd_setspecial(q, sign, MPD_INF);
    3735             :             }
    3736           0 :             mpd_setspecial(r, MPD_POS, MPD_NAN);
    3737           0 :             *status |= MPD_Invalid_operation;
    3738           0 :             return;
    3739             :         }
    3740           0 :         if (mpd_isinfinite(b)) {
    3741           0 :             if (!mpd_qcopy(r, a, status)) {
    3742           0 :                 mpd_seterror(q, MPD_Malloc_error, status);
    3743           0 :                 return;
    3744             :             }
    3745           0 :             mpd_qfinalize(r, ctx, status);
    3746           0 :             _settriple(q, sign, 0, 0);
    3747           0 :             return;
    3748             :         }
    3749             :         /* debug */
    3750           0 :         abort(); /* GCOV_NOT_REACHED */
    3751             :     }
    3752           0 :     if (mpd_iszerocoeff(b)) {
    3753           0 :         if (mpd_iszerocoeff(a)) {
    3754           0 :             mpd_setspecial(q, MPD_POS, MPD_NAN);
    3755           0 :             mpd_setspecial(r, MPD_POS, MPD_NAN);
    3756           0 :             *status |= MPD_Division_undefined;
    3757             :         }
    3758             :         else {
    3759           0 :             mpd_setspecial(q, sign, MPD_INF);
    3760           0 :             mpd_setspecial(r, MPD_POS, MPD_NAN);
    3761           0 :             *status |= (MPD_Division_by_zero|MPD_Invalid_operation);
    3762             :         }
    3763           0 :         return;
    3764             :     }
    3765             : 
    3766           0 :     _mpd_qdivmod(q, r, a, b, ctx, status);
    3767           0 :     mpd_qfinalize(q, ctx, status);
    3768           0 :     mpd_qfinalize(r, ctx, status);
    3769             : }
    3770             : 
    3771             : void
    3772           0 : mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b,
    3773             :             const mpd_context_t *ctx, uint32_t *status)
    3774             : {
    3775           0 :     MPD_NEW_STATIC(r,0,0,0,0);
    3776           0 :     uint8_t sign = mpd_sign(a)^mpd_sign(b);
    3777             : 
    3778           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    3779           0 :         if (mpd_qcheck_nans(q, a, b, ctx, status)) {
    3780             :             return;
    3781             :         }
    3782           0 :         if (mpd_isinfinite(a) && mpd_isinfinite(b)) {
    3783           0 :             mpd_seterror(q, MPD_Invalid_operation, status);
    3784             :             return;
    3785             :         }
    3786           0 :         if (mpd_isinfinite(a)) {
    3787           0 :             mpd_setspecial(q, sign, MPD_INF);
    3788             :             return;
    3789             :         }
    3790           0 :         if (mpd_isinfinite(b)) {
    3791           0 :             _settriple(q, sign, 0, 0);
    3792             :             return;
    3793             :         }
    3794             :         /* debug */
    3795           0 :         abort(); /* GCOV_NOT_REACHED */
    3796             :     }
    3797           0 :     if (mpd_iszerocoeff(b)) {
    3798           0 :         if (mpd_iszerocoeff(a)) {
    3799           0 :             mpd_seterror(q, MPD_Division_undefined, status);
    3800             :         }
    3801             :         else {
    3802           0 :             mpd_setspecial(q, sign, MPD_INF);
    3803           0 :             *status |= MPD_Division_by_zero;
    3804             :         }
    3805             :         return;
    3806             :     }
    3807             : 
    3808             : 
    3809           0 :     _mpd_qdivmod(q, &r, a, b, ctx, status);
    3810             :     mpd_del(&r);
    3811           0 :     mpd_qfinalize(q, ctx, status);
    3812             : }
    3813             : 
    3814             : /* Divide decimal by mpd_ssize_t. */
    3815             : void
    3816           0 : mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,
    3817             :                const mpd_context_t *ctx, uint32_t *status)
    3818             : {
    3819             :     mpd_context_t maxcontext;
    3820           0 :     MPD_NEW_STATIC(bb,0,0,0,0);
    3821             : 
    3822           0 :     mpd_maxcontext(&maxcontext);
    3823           0 :     mpd_qsset_ssize(&bb, b, &maxcontext, status);
    3824           0 :     mpd_qdiv(result, a, &bb, ctx, status);
    3825             :     mpd_del(&bb);
    3826           0 : }
    3827             : 
    3828             : /* Divide decimal by mpd_uint_t. */
    3829             : void
    3830           0 : mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,
    3831             :               const mpd_context_t *ctx, uint32_t *status)
    3832             : {
    3833             :     mpd_context_t maxcontext;
    3834           0 :     MPD_NEW_STATIC(bb,0,0,0,0);
    3835             : 
    3836           0 :     mpd_maxcontext(&maxcontext);
    3837           0 :     mpd_qsset_uint(&bb, b, &maxcontext, status);
    3838           0 :     mpd_qdiv(result, a, &bb, ctx, status);
    3839             :     mpd_del(&bb);
    3840           0 : }
    3841             : 
    3842             : /* Divide decimal by int32_t. */
    3843             : void
    3844           0 : mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b,
    3845             :              const mpd_context_t *ctx, uint32_t *status)
    3846             : {
    3847           0 :     mpd_qdiv_ssize(result, a, b, ctx, status);
    3848           0 : }
    3849             : 
    3850             : /* Divide decimal by uint32_t. */
    3851             : void
    3852           0 : mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b,
    3853             :              const mpd_context_t *ctx, uint32_t *status)
    3854             : {
    3855           0 :     mpd_qdiv_uint(result, a, b, ctx, status);
    3856           0 : }
    3857             : 
    3858             : #ifdef CONFIG_64
    3859             : /* Divide decimal by int64_t. */
    3860             : void
    3861             : mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b,
    3862             :              const mpd_context_t *ctx, uint32_t *status)
    3863             : {
    3864             :     mpd_qdiv_ssize(result, a, b, ctx, status);
    3865             : }
    3866             : 
    3867             : /* Divide decimal by uint64_t. */
    3868             : void
    3869             : mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b,
    3870             :              const mpd_context_t *ctx, uint32_t *status)
    3871             : {
    3872             :     mpd_qdiv_uint(result, a, b, ctx, status);
    3873             : }
    3874             : #endif
    3875             : 
    3876             : /* Pad the result with trailing zeros if it has fewer digits than prec. */
    3877             : static void
    3878           0 : _mpd_zeropad(mpd_t *result, const mpd_context_t *ctx, uint32_t *status)
    3879             : {
    3880           0 :     if (!mpd_isspecial(result) && !mpd_iszero(result) &&
    3881           0 :         result->digits < ctx->prec) {
    3882           0 :        mpd_ssize_t shift = ctx->prec - result->digits;
    3883           0 :        mpd_qshiftl(result, result, shift, status);
    3884           0 :        result->exp -= shift;
    3885             :     }
    3886           0 : }
    3887             : 
    3888             : /* Check if the result is guaranteed to be one. */
    3889             : static int
    3890           0 : _mpd_qexp_check_one(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    3891             :                     uint32_t *status)
    3892             : {
    3893           0 :     MPD_NEW_CONST(lim,0,-(ctx->prec+1),1,1,1,9);
    3894           0 :     MPD_NEW_SHARED(aa, a);
    3895             : 
    3896             :     mpd_set_positive(&aa);
    3897             : 
    3898             :     /* abs(a) <= 9 * 10**(-prec-1) */
    3899           0 :     if (_mpd_cmp(&aa, &lim) <= 0) {
    3900           0 :         _settriple(result, 0, 1, 0);
    3901           0 :         *status |= MPD_Rounded|MPD_Inexact;
    3902           0 :         return 1;
    3903             :     }
    3904             : 
    3905           0 :     return 0;
    3906             : }
    3907             : 
    3908             : /*
    3909             :  * Get the number of iterations for the Horner scheme in _mpd_qexp().
    3910             :  */
    3911             : static inline mpd_ssize_t
    3912           0 : _mpd_get_exp_iterations(const mpd_t *r, mpd_ssize_t p)
    3913             : {
    3914             :     mpd_ssize_t log10pbyr; /* lower bound for log10(p / abs(r)) */
    3915             :     mpd_ssize_t n;
    3916             : 
    3917             :     assert(p >= 10);
    3918             :     assert(!mpd_iszero(r));
    3919             :     assert(-p < mpd_adjexp(r) && mpd_adjexp(r) <= -1);
    3920             : 
    3921             : #ifdef CONFIG_64
    3922             :     if (p > (mpd_ssize_t)(1ULL<<52)) {
    3923             :         return MPD_SSIZE_MAX;
    3924             :     }
    3925             : #endif
    3926             : 
    3927             :     /*
    3928             :      * Lower bound for log10(p / abs(r)): adjexp(p) - (adjexp(r) + 1)
    3929             :      * At this point (for CONFIG_64, CONFIG_32 is not problematic):
    3930             :      *    1) 10 <= p <= 2**52
    3931             :      *    2) -p < adjexp(r) <= -1
    3932             :      *    3) 1 <= log10pbyr <= 2**52 + 14
    3933             :      */
    3934           0 :     log10pbyr = (mpd_word_digits(p)-1) - (mpd_adjexp(r)+1);
    3935             : 
    3936             :     /*
    3937             :      * The numerator in the paper is 1.435 * p - 1.182, calculated
    3938             :      * exactly. We compensate for rounding errors by using 1.43503.
    3939             :      * ACL2 proofs:
    3940             :      *    1) exp-iter-approx-lower-bound: The term below evaluated
    3941             :      *       in 53-bit floating point arithmetic is greater than or
    3942             :      *       equal to the exact term used in the paper.
    3943             :      *    2) exp-iter-approx-upper-bound: The term below is less than
    3944             :      *       or equal to 3/2 * p <= 3/2 * 2**52.
    3945             :      */
    3946           0 :     n = (mpd_ssize_t)ceil((1.43503*(double)p - 1.182) / (double)log10pbyr);
    3947           0 :     return n >= 3 ? n : 3;
    3948             : }
    3949             : 
    3950             : /*
    3951             :  * Internal function, specials have been dealt with. Apart from Overflow
    3952             :  * and Underflow, two cases must be considered for the error of the result:
    3953             :  *
    3954             :  *   1) abs(a) <= 9 * 10**(-prec-1)  ==>  result == 1
    3955             :  *
    3956             :  *      Absolute error: abs(1 - e**x) < 10**(-prec)
    3957             :  *      -------------------------------------------
    3958             :  *
    3959             :  *   2) abs(a) > 9 * 10**(-prec-1)
    3960             :  *
    3961             :  *      Relative error: abs(result - e**x) < 0.5 * 10**(-prec) * e**x
    3962             :  *      -------------------------------------------------------------
    3963             :  *
    3964             :  * The algorithm is from Hull&Abrham, Variable Precision Exponential Function,
    3965             :  * ACM Transactions on Mathematical Software, Vol. 12, No. 2, June 1986.
    3966             :  *
    3967             :  * Main differences:
    3968             :  *
    3969             :  *  - The number of iterations for the Horner scheme is calculated using
    3970             :  *    53-bit floating point arithmetic.
    3971             :  *
    3972             :  *  - In the error analysis for ER (relative error accumulated in the
    3973             :  *    evaluation of the truncated series) the reduced operand r may
    3974             :  *    have any number of digits.
    3975             :  *    ACL2 proof: exponent-relative-error
    3976             :  *
    3977             :  *  - The analysis for early abortion has been adapted for the mpd_t
    3978             :  *    ranges.
    3979             :  */
    3980             : static void
    3981           0 : _mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    3982             :           uint32_t *status)
    3983             : {
    3984             :     mpd_context_t workctx;
    3985           0 :     MPD_NEW_STATIC(tmp,0,0,0,0);
    3986           0 :     MPD_NEW_STATIC(sum,0,0,0,0);
    3987           0 :     MPD_NEW_CONST(word,0,0,1,1,1,1);
    3988             :     mpd_ssize_t j, n, t;
    3989             : 
    3990             :     assert(!mpd_isspecial(a));
    3991             : 
    3992           0 :     if (mpd_iszerocoeff(a)) {
    3993           0 :         _settriple(result, MPD_POS, 1, 0);
    3994             :         return;
    3995             :     }
    3996             : 
    3997             :     /*
    3998             :      * We are calculating e^x = e^(r*10^t) = (e^r)^(10^t), where abs(r) < 1 and t >= 0.
    3999             :      *
    4000             :      * If t > 0, we have:
    4001             :      *
    4002             :      *   (1) 0.1 <= r < 1, so e^0.1 <= e^r. If t > MAX_T, overflow occurs:
    4003             :      *
    4004             :      *     MAX-EMAX+1 < log10(e^(0.1*10*t)) <= log10(e^(r*10^t)) < adjexp(e^(r*10^t))+1
    4005             :      *
    4006             :      *   (2) -1 < r <= -0.1, so e^r <= e^-0.1. If t > MAX_T, underflow occurs:
    4007             :      *
    4008             :      *     adjexp(e^(r*10^t)) <= log10(e^(r*10^t)) <= log10(e^(-0.1*10^t)) < MIN-ETINY
    4009             :      */
    4010             : #if defined(CONFIG_64)
    4011             :     #define MPD_EXP_MAX_T 19
    4012             : #elif defined(CONFIG_32)
    4013             :     #define MPD_EXP_MAX_T 10
    4014             : #endif
    4015           0 :     t = a->digits + a->exp;
    4016           0 :     t = (t > 0) ? t : 0;
    4017           0 :     if (t > MPD_EXP_MAX_T) {
    4018           0 :         if (mpd_ispositive(a)) {
    4019           0 :             mpd_setspecial(result, MPD_POS, MPD_INF);
    4020           0 :             *status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;
    4021             :         }
    4022             :         else {
    4023           0 :             _settriple(result, MPD_POS, 0, mpd_etiny(ctx));
    4024           0 :             *status |= (MPD_Inexact|MPD_Rounded|MPD_Subnormal|
    4025             :                         MPD_Underflow|MPD_Clamped);
    4026             :         }
    4027             :         return;
    4028             :     }
    4029             : 
    4030             :     /* abs(a) <= 9 * 10**(-prec-1) */
    4031           0 :     if (_mpd_qexp_check_one(result, a, ctx, status)) {
    4032             :         return;
    4033             :     }
    4034             : 
    4035           0 :     mpd_maxcontext(&workctx);
    4036           0 :     workctx.prec = ctx->prec + t + 2;
    4037           0 :     workctx.prec = (workctx.prec < 10) ? 10 : workctx.prec;
    4038           0 :     workctx.round = MPD_ROUND_HALF_EVEN;
    4039             : 
    4040           0 :     if (!mpd_qcopy(result, a, status)) {
    4041             :         return;
    4042             :     }
    4043           0 :     result->exp -= t;
    4044             : 
    4045             :     /*
    4046             :      * At this point:
    4047             :      *    1) 9 * 10**(-prec-1) < abs(a)
    4048             :      *    2) 9 * 10**(-prec-t-1) < abs(r)
    4049             :      *    3) log10(9) - prec - t - 1 < log10(abs(r)) < adjexp(abs(r)) + 1
    4050             :      *    4) - prec - t - 2 < adjexp(abs(r)) <= -1
    4051             :      */
    4052           0 :     n = _mpd_get_exp_iterations(result, workctx.prec);
    4053           0 :     if (n == MPD_SSIZE_MAX) {
    4054           0 :         mpd_seterror(result, MPD_Invalid_operation, status); /* GCOV_UNLIKELY */
    4055             :         return; /* GCOV_UNLIKELY */
    4056             :     }
    4057             : 
    4058           0 :     _settriple(&sum, MPD_POS, 1, 0);
    4059             : 
    4060           0 :     for (j = n-1; j >= 1; j--) {
    4061           0 :         word.data[0] = j;
    4062           0 :         mpd_setdigits(&word);
    4063           0 :         mpd_qdiv(&tmp, result, &word, &workctx, &workctx.status);
    4064           0 :         mpd_qfma(&sum, &sum, &tmp, &one, &workctx, &workctx.status);
    4065             :     }
    4066             : 
    4067             : #ifdef CONFIG_64
    4068             :     _mpd_qpow_uint(result, &sum, mpd_pow10[t], MPD_POS, &workctx, status);
    4069             : #else
    4070           0 :     if (t <= MPD_MAX_POW10) {
    4071           0 :         _mpd_qpow_uint(result, &sum, mpd_pow10[t], MPD_POS, &workctx, status);
    4072             :     }
    4073             :     else {
    4074           0 :         t -= MPD_MAX_POW10;
    4075           0 :         _mpd_qpow_uint(&tmp, &sum, mpd_pow10[MPD_MAX_POW10], MPD_POS,
    4076             :                        &workctx, status);
    4077           0 :         _mpd_qpow_uint(result, &tmp, mpd_pow10[t], MPD_POS, &workctx, status);
    4078             :     }
    4079             : #endif
    4080             : 
    4081             :     mpd_del(&tmp);
    4082             :     mpd_del(&sum);
    4083           0 :     *status |= (workctx.status&MPD_Errors);
    4084           0 :     *status |= (MPD_Inexact|MPD_Rounded);
    4085             : }
    4086             : 
    4087             : /* exp(a) */
    4088             : void
    4089           0 : mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    4090             :          uint32_t *status)
    4091             : {
    4092             :     mpd_context_t workctx;
    4093             : 
    4094           0 :     if (mpd_isspecial(a)) {
    4095           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    4096             :             return;
    4097             :         }
    4098           0 :         if (mpd_isnegative(a)) {
    4099           0 :             _settriple(result, MPD_POS, 0, 0);
    4100             :         }
    4101             :         else {
    4102           0 :             mpd_setspecial(result, MPD_POS, MPD_INF);
    4103             :         }
    4104             :         return;
    4105             :     }
    4106           0 :     if (mpd_iszerocoeff(a)) {
    4107           0 :         _settriple(result, MPD_POS, 1, 0);
    4108             :         return;
    4109             :     }
    4110             : 
    4111           0 :     workctx = *ctx;
    4112           0 :     workctx.round = MPD_ROUND_HALF_EVEN;
    4113             : 
    4114           0 :     if (ctx->allcr) {
    4115           0 :         MPD_NEW_STATIC(t1, 0,0,0,0);
    4116           0 :         MPD_NEW_STATIC(t2, 0,0,0,0);
    4117           0 :         MPD_NEW_STATIC(ulp, 0,0,0,0);
    4118           0 :         MPD_NEW_STATIC(aa, 0,0,0,0);
    4119             :         mpd_ssize_t prec;
    4120             :         mpd_ssize_t ulpexp;
    4121             :         uint32_t workstatus;
    4122             : 
    4123           0 :         if (result == a) {
    4124           0 :             if (!mpd_qcopy(&aa, a, status)) {
    4125           0 :                 mpd_seterror(result, MPD_Malloc_error, status);
    4126             :                 return;
    4127             :             }
    4128           0 :             a = &aa;
    4129             :         }
    4130             : 
    4131           0 :         workctx.clamp = 0;
    4132           0 :         prec = ctx->prec + 3;
    4133             :         while (1) {
    4134           0 :             workctx.prec = prec;
    4135           0 :             workstatus = 0;
    4136             : 
    4137           0 :             _mpd_qexp(result, a, &workctx, &workstatus);
    4138           0 :             *status |= workstatus;
    4139             : 
    4140           0 :             ulpexp = result->exp + result->digits - workctx.prec;
    4141           0 :             if (workstatus & MPD_Underflow) {
    4142             :                 /* The effective work precision is result->digits. */
    4143           0 :                 ulpexp = result->exp;
    4144             :             }
    4145           0 :             _ssettriple(&ulp, MPD_POS, 1, ulpexp);
    4146             : 
    4147             :             /*
    4148             :              * At this point [1]:
    4149             :              *   1) abs(result - e**x) < 0.5 * 10**(-prec) * e**x
    4150             :              *   2) result - ulp < e**x < result + ulp
    4151             :              *   3) result - ulp < result < result + ulp
    4152             :              *
    4153             :              * If round(result-ulp)==round(result+ulp), then
    4154             :              * round(result)==round(e**x). Therefore the result
    4155             :              * is correctly rounded.
    4156             :              *
    4157             :              * [1] If abs(a) <= 9 * 10**(-prec-1), use the absolute
    4158             :              *     error for a similar argument.
    4159             :              */
    4160           0 :             workctx.prec = ctx->prec;
    4161           0 :             mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status);
    4162           0 :             mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status);
    4163           0 :             if (mpd_isspecial(result) || mpd_iszerocoeff(result) ||
    4164           0 :                 mpd_qcmp(&t1, &t2, status) == 0) {
    4165           0 :                 workctx.clamp = ctx->clamp;
    4166           0 :                 _mpd_zeropad(result, &workctx, status);
    4167           0 :                 mpd_check_underflow(result, &workctx, status);
    4168           0 :                 mpd_qfinalize(result, &workctx, status);
    4169           0 :                 break;
    4170             :             }
    4171           0 :             prec += MPD_RDIGITS;
    4172           0 :         }
    4173             :         mpd_del(&t1);
    4174             :         mpd_del(&t2);
    4175             :         mpd_del(&ulp);
    4176             :         mpd_del(&aa);
    4177             :     }
    4178             :     else {
    4179           0 :         _mpd_qexp(result, a, &workctx, status);
    4180           0 :         _mpd_zeropad(result, &workctx, status);
    4181           0 :         mpd_check_underflow(result, &workctx, status);
    4182           0 :         mpd_qfinalize(result, &workctx, status);
    4183             :     }
    4184             : }
    4185             : 
    4186             : /* Fused multiply-add: (a * b) + c, with a single final rounding. */
    4187             : void
    4188           0 : mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c,
    4189             :          const mpd_context_t *ctx, uint32_t *status)
    4190             : {
    4191           0 :     uint32_t workstatus = 0;
    4192           0 :     mpd_t *cc = (mpd_t *)c;
    4193             : 
    4194           0 :     if (result == c) {
    4195           0 :         if ((cc = mpd_qncopy(c)) == NULL) {
    4196           0 :             mpd_seterror(result, MPD_Malloc_error, status);
    4197           0 :             return;
    4198             :         }
    4199             :     }
    4200             : 
    4201           0 :     _mpd_qmul(result, a, b, ctx, &workstatus);
    4202           0 :     if (!(workstatus&MPD_Invalid_operation)) {
    4203           0 :         mpd_qadd(result, result, cc, ctx, &workstatus);
    4204             :     }
    4205             : 
    4206           0 :     if (cc != c) mpd_del(cc);
    4207           0 :     *status |= workstatus;
    4208             : }
    4209             : 
    4210             : /*
    4211             :  * Schedule the optimal precision increase for the Newton iteration.
    4212             :  *   v := input operand
    4213             :  *   z_0 := initial approximation
    4214             :  *   initprec := natural number such that abs(log(v) - z_0) < 10**-initprec
    4215             :  *   maxprec := target precision
    4216             :  *
    4217             :  * For convenience the output klist contains the elements in reverse order:
    4218             :  *   klist := [k_n-1, ..., k_0], where
    4219             :  *     1) k_0 <= initprec and
    4220             :  *     2) abs(log(v) - result) < 10**(-2*k_n-1 + 1) <= 10**-maxprec.
    4221             :  */
    4222             : static inline int
    4223           0 : ln_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2], mpd_ssize_t maxprec,
    4224             :                  mpd_ssize_t initprec)
    4225             : {
    4226             :     mpd_ssize_t k;
    4227             :     int i;
    4228             : 
    4229             :     assert(maxprec >= 2 && initprec >= 2);
    4230           0 :     if (maxprec <= initprec) return -1;
    4231             : 
    4232           0 :     i = 0; k = maxprec;
    4233             :     do {
    4234           0 :         k = (k+2) / 2;
    4235           0 :         klist[i++] = k;
    4236           0 :     } while (k > initprec);
    4237             : 
    4238           0 :     return i-1;
    4239             : }
    4240             : 
    4241             : /* The constants have been verified with both decimal.py and mpfr. */
    4242             : #ifdef CONFIG_64
    4243             : #if MPD_RDIGITS != 19
    4244             :   #error "mpdecimal.c: MPD_RDIGITS must be 19."
    4245             : #endif
    4246             : static const mpd_uint_t mpd_ln10_data[MPD_MINALLOC_MAX] = {
    4247             :   6983716328982174407ULL, 9089704281976336583ULL, 1515961135648465461ULL,
    4248             :   4416816335727555703ULL, 2900988039194170265ULL, 2307925037472986509ULL,
    4249             :    107598438319191292ULL, 3466624107184669231ULL, 4450099781311469159ULL,
    4250             :   9807828059751193854ULL, 7713456862091670584ULL, 1492198849978748873ULL,
    4251             :   6528728696511086257ULL, 2385392051446341972ULL, 8692180205189339507ULL,
    4252             :   6518769751037497088ULL, 2375253577097505395ULL, 9095610299291824318ULL,
    4253             :    982748238504564801ULL, 5438635917781170543ULL, 7547331541421808427ULL,
    4254             :    752371033310119785ULL, 3171643095059950878ULL, 9785265383207606726ULL,
    4255             :   2932258279850258550ULL, 5497347726624257094ULL, 2976979522110718264ULL,
    4256             :   9221477656763693866ULL, 1979650047149510504ULL, 6674183485704422507ULL,
    4257             :   9702766860595249671ULL, 9278096762712757753ULL, 9314848524948644871ULL,
    4258             :   6826928280848118428ULL,  754403708474699401ULL,  230105703089634572ULL,
    4259             :   1929203337658714166ULL, 7589402567763113569ULL, 4208241314695689016ULL,
    4260             :   2922455440575892572ULL, 9356734206705811364ULL, 2684916746550586856ULL,
    4261             :    644507064800027750ULL, 9476834636167921018ULL, 5659121373450747856ULL,
    4262             :   2835522011480466371ULL, 6470806855677432162ULL, 7141748003688084012ULL,
    4263             :   9619404400222105101ULL, 5504893431493939147ULL, 6674744042432743651ULL,
    4264             :   2287698219886746543ULL, 7773262884616336622ULL, 1985283935053089653ULL,
    4265             :   4680843799894826233ULL, 8168948290720832555ULL, 8067566662873690987ULL,
    4266             :   6248633409525465082ULL, 9829834196778404228ULL, 3524802359972050895ULL,
    4267             :   3327900967572609677ULL,  110148862877297603ULL,  179914546843642076ULL,
    4268             :   2302585092994045684ULL
    4269             : };
    4270             : #else
    4271             : #if MPD_RDIGITS != 9
    4272             :   #error "mpdecimal.c: MPD_RDIGITS must be 9."
    4273             : #endif
    4274             : static const mpd_uint_t mpd_ln10_data[MPD_MINALLOC_MAX] = {
    4275             :   401682692UL, 708474699UL, 720754403UL,  30896345UL, 602301057UL, 765871416UL,
    4276             :   192920333UL, 763113569UL, 589402567UL, 956890167UL,  82413146UL, 589257242UL,
    4277             :   245544057UL, 811364292UL, 734206705UL, 868569356UL, 167465505UL, 775026849UL,
    4278             :   706480002UL,  18064450UL, 636167921UL, 569476834UL, 734507478UL, 156591213UL,
    4279             :   148046637UL, 283552201UL, 677432162UL, 470806855UL, 880840126UL, 417480036UL,
    4280             :   210510171UL, 940440022UL, 939147961UL, 893431493UL, 436515504UL, 440424327UL,
    4281             :   654366747UL, 821988674UL, 622228769UL, 884616336UL, 537773262UL, 350530896UL,
    4282             :   319852839UL, 989482623UL, 468084379UL, 720832555UL, 168948290UL, 736909878UL,
    4283             :   675666628UL, 546508280UL, 863340952UL, 404228624UL, 834196778UL, 508959829UL,
    4284             :    23599720UL, 967735248UL,  96757260UL, 603332790UL, 862877297UL, 760110148UL,
    4285             :   468436420UL, 401799145UL, 299404568UL, 230258509UL
    4286             : };
    4287             : #endif
    4288             : /* _mpd_ln10 is used directly for precisions smaller than MINALLOC_MAX*RDIGITS.
    4289             :    Otherwise, it serves as the initial approximation for calculating ln(10). */
    4290             : static const mpd_t _mpd_ln10 = {
    4291             :   MPD_STATIC|MPD_CONST_DATA, -(MPD_MINALLOC_MAX*MPD_RDIGITS-1),
    4292             :   MPD_MINALLOC_MAX*MPD_RDIGITS, MPD_MINALLOC_MAX, MPD_MINALLOC_MAX,
    4293             :   (mpd_uint_t *)mpd_ln10_data
    4294             : };
    4295             : 
    4296             : /*
    4297             :  * Set 'result' to log(10).
    4298             :  *   Ulp error: abs(result - log(10)) < ulp(log(10))
    4299             :  *   Relative error: abs(result - log(10)) < 5 * 10**-prec * log(10)
    4300             :  *
    4301             :  * NOTE: The relative error is not derived from the ulp error, but
    4302             :  * calculated separately using the fact that 23/10 < log(10) < 24/10.
    4303             :  */
    4304             : void
    4305           0 : mpd_qln10(mpd_t *result, mpd_ssize_t prec, uint32_t *status)
    4306             : {
    4307             :     mpd_context_t varcontext, maxcontext;
    4308           0 :     MPD_NEW_STATIC(tmp, 0,0,0,0);
    4309           0 :     MPD_NEW_CONST(static10, 0,0,2,1,1,10);
    4310             :     mpd_ssize_t klist[MPD_MAX_PREC_LOG2];
    4311             :     mpd_uint_t rnd;
    4312             :     mpd_ssize_t shift;
    4313             :     int i;
    4314             : 
    4315             :     assert(prec >= 1);
    4316             : 
    4317           0 :     shift = MPD_MINALLOC_MAX*MPD_RDIGITS-prec;
    4318           0 :     shift = shift < 0 ? 0 : shift;
    4319             : 
    4320           0 :     rnd = mpd_qshiftr(result, &_mpd_ln10, shift, status);
    4321           0 :     if (rnd == MPD_UINT_MAX) {
    4322           0 :         mpd_seterror(result, MPD_Malloc_error, status);
    4323             :         return;
    4324             :     }
    4325           0 :     result->exp = -(result->digits-1);
    4326             : 
    4327           0 :     mpd_maxcontext(&maxcontext);
    4328           0 :     if (prec < MPD_MINALLOC_MAX*MPD_RDIGITS) {
    4329           0 :         maxcontext.prec = prec;
    4330           0 :         _mpd_apply_round_excess(result, rnd, &maxcontext, status);
    4331           0 :         *status |= (MPD_Inexact|MPD_Rounded);
    4332             :         return;
    4333             :     }
    4334             : 
    4335           0 :     mpd_maxcontext(&varcontext);
    4336           0 :     varcontext.round = MPD_ROUND_TRUNC;
    4337             : 
    4338           0 :     i = ln_schedule_prec(klist, prec+2, -result->exp);
    4339           0 :     for (; i >= 0; i--) {
    4340           0 :         varcontext.prec = 2*klist[i]+3;
    4341           0 :         result->flags ^= MPD_NEG;
    4342           0 :         _mpd_qexp(&tmp, result, &varcontext, status);
    4343           0 :         result->flags ^= MPD_NEG;
    4344           0 :         mpd_qmul(&tmp, &static10, &tmp, &varcontext, status);
    4345           0 :         mpd_qsub(&tmp, &tmp, &one, &maxcontext, status);
    4346           0 :         mpd_qadd(result, result, &tmp, &maxcontext, status);
    4347           0 :         if (mpd_isspecial(result)) {
    4348           0 :             break;
    4349             :         }
    4350             :     }
    4351             : 
    4352             :     mpd_del(&tmp);
    4353           0 :     maxcontext.prec = prec;
    4354           0 :     mpd_qfinalize(result, &maxcontext, status);
    4355             : }
    4356             : 
    4357             : /*
    4358             :  * Initial approximations for the ln() iteration. The values have the
    4359             :  * following properties (established with both decimal.py and mpfr):
    4360             :  *
    4361             :  * Index 0 - 400, logarithms of x in [1.00, 5.00]:
    4362             :  *   abs(lnapprox[i] * 10**-3 - log((i+100)/100)) < 10**-2
    4363             :  *   abs(lnapprox[i] * 10**-3 - log((i+1+100)/100)) < 10**-2
    4364             :  *
    4365             :  * Index 401 - 899, logarithms of x in (0.500, 0.999]:
    4366             :  *   abs(-lnapprox[i] * 10**-3 - log((i+100)/1000)) < 10**-2
    4367             :  *   abs(-lnapprox[i] * 10**-3 - log((i+1+100)/1000)) < 10**-2
    4368             :  */
    4369             : static const uint16_t lnapprox[900] = {
    4370             :   /* index 0 - 400: log((i+100)/100) * 1000 */
    4371             :   0, 10, 20, 30, 39, 49, 58, 68, 77, 86, 95, 104, 113, 122, 131, 140, 148, 157,
    4372             :   166, 174, 182, 191, 199, 207, 215, 223, 231, 239, 247, 255, 262, 270, 278,
    4373             :   285, 293, 300, 308, 315, 322, 329, 336, 344, 351, 358, 365, 372, 378, 385,
    4374             :   392, 399, 406, 412, 419, 425, 432, 438, 445, 451, 457, 464, 470, 476, 482,
    4375             :   489, 495, 501, 507, 513, 519, 525, 531, 536, 542, 548, 554, 560, 565, 571,
    4376             :   577, 582, 588, 593, 599, 604, 610, 615, 621, 626, 631, 637, 642, 647, 652,
    4377             :   658, 663, 668, 673, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728,
    4378             :   732, 737, 742, 747, 751, 756, 761, 766, 770, 775, 779, 784, 788, 793, 798,
    4379             :   802, 806, 811, 815, 820, 824, 829, 833, 837, 842, 846, 850, 854, 859, 863,
    4380             :   867, 871, 876, 880, 884, 888, 892, 896, 900, 904, 908, 912, 916, 920, 924,
    4381             :   928, 932, 936, 940, 944, 948, 952, 956, 959, 963, 967, 971, 975, 978, 982,
    4382             :   986, 990, 993, 997, 1001, 1004, 1008, 1012, 1015, 1019, 1022, 1026, 1030,
    4383             :   1033, 1037, 1040, 1044, 1047, 1051, 1054, 1058, 1061, 1065, 1068, 1072, 1075,
    4384             :   1078, 1082, 1085, 1089, 1092, 1095, 1099, 1102, 1105, 1109, 1112, 1115, 1118,
    4385             :   1122, 1125, 1128, 1131, 1135, 1138, 1141, 1144, 1147, 1151, 1154, 1157, 1160,
    4386             :   1163, 1166, 1169, 1172, 1176, 1179, 1182, 1185, 1188, 1191, 1194, 1197, 1200,
    4387             :   1203, 1206, 1209, 1212, 1215, 1218, 1221, 1224, 1227, 1230, 1233, 1235, 1238,
    4388             :   1241, 1244, 1247, 1250, 1253, 1256, 1258, 1261, 1264, 1267, 1270, 1273, 1275,
    4389             :   1278, 1281, 1284, 1286, 1289, 1292, 1295, 1297, 1300, 1303, 1306, 1308, 1311,
    4390             :   1314, 1316, 1319, 1322, 1324, 1327, 1330, 1332, 1335, 1338, 1340, 1343, 1345,
    4391             :   1348, 1351, 1353, 1356, 1358, 1361, 1364, 1366, 1369, 1371, 1374, 1376, 1379,
    4392             :   1381, 1384, 1386, 1389, 1391, 1394, 1396, 1399, 1401, 1404, 1406, 1409, 1411,
    4393             :   1413, 1416, 1418, 1421, 1423, 1426, 1428, 1430, 1433, 1435, 1437, 1440, 1442,
    4394             :   1445, 1447, 1449, 1452, 1454, 1456, 1459, 1461, 1463, 1466, 1468, 1470, 1472,
    4395             :   1475, 1477, 1479, 1482, 1484, 1486, 1488, 1491, 1493, 1495, 1497, 1500, 1502,
    4396             :   1504, 1506, 1509, 1511, 1513, 1515, 1517, 1520, 1522, 1524, 1526, 1528, 1530,
    4397             :   1533, 1535, 1537, 1539, 1541, 1543, 1545, 1548, 1550, 1552, 1554, 1556, 1558,
    4398             :   1560, 1562, 1564, 1567, 1569, 1571, 1573, 1575, 1577, 1579, 1581, 1583, 1585,
    4399             :   1587, 1589, 1591, 1593, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1609,
    4400             :   /* index 401 - 899: -log((i+100)/1000) * 1000 */
    4401             :   691, 689, 687, 685, 683, 681, 679, 677, 675, 673, 671, 669, 668, 666, 664,
    4402             :   662, 660, 658, 656, 654, 652, 650, 648, 646, 644, 642, 641, 639, 637, 635,
    4403             :   633, 631, 629, 627, 626, 624, 622, 620, 618, 616, 614, 612, 611, 609, 607,
    4404             :   605, 603, 602, 600, 598, 596, 594, 592, 591, 589, 587, 585, 583, 582, 580,
    4405             :   578, 576, 574, 573, 571, 569, 567, 566, 564, 562, 560, 559, 557, 555, 553,
    4406             :   552, 550, 548, 546, 545, 543, 541, 540, 538, 536, 534, 533, 531, 529, 528,
    4407             :   526, 524, 523, 521, 519, 518, 516, 514, 512, 511, 509, 508, 506, 504, 502,
    4408             :   501, 499, 498, 496, 494, 493, 491, 489, 488, 486, 484, 483, 481, 480, 478,
    4409             :   476, 475, 473, 472, 470, 468, 467, 465, 464, 462, 460, 459, 457, 456, 454,
    4410             :   453, 451, 449, 448, 446, 445, 443, 442, 440, 438, 437, 435, 434, 432, 431,
    4411             :   429, 428, 426, 425, 423, 422, 420, 419, 417, 416, 414, 412, 411, 410, 408,
    4412             :   406, 405, 404, 402, 400, 399, 398, 396, 394, 393, 392, 390, 389, 387, 386,
    4413             :   384, 383, 381, 380, 378, 377, 375, 374, 372, 371, 370, 368, 367, 365, 364,
    4414             :   362, 361, 360, 358, 357, 355, 354, 352, 351, 350, 348, 347, 345, 344, 342,
    4415             :   341, 340, 338, 337, 336, 334, 333, 331, 330, 328, 327, 326, 324, 323, 322,
    4416             :   320, 319, 318, 316, 315, 313, 312, 311, 309, 308, 306, 305, 304, 302, 301,
    4417             :   300, 298, 297, 296, 294, 293, 292, 290, 289, 288, 286, 285, 284, 282, 281,
    4418             :   280, 278, 277, 276, 274, 273, 272, 270, 269, 268, 267, 265, 264, 263, 261,
    4419             :   260, 259, 258, 256, 255, 254, 252, 251, 250, 248, 247, 246, 245, 243, 242,
    4420             :   241, 240, 238, 237, 236, 234, 233, 232, 231, 229, 228, 227, 226, 224, 223,
    4421             :   222, 221, 219, 218, 217, 216, 214, 213, 212, 211, 210, 208, 207, 206, 205,
    4422             :   203, 202, 201, 200, 198, 197, 196, 195, 194, 192, 191, 190, 189, 188, 186,
    4423             :   185, 184, 183, 182, 180, 179, 178, 177, 176, 174, 173, 172, 171, 170, 168,
    4424             :   167, 166, 165, 164, 162, 161, 160, 159, 158, 157, 156, 154, 153, 152, 151,
    4425             :   150, 148, 147, 146, 145, 144, 143, 142, 140, 139, 138, 137, 136, 135, 134,
    4426             :   132, 131, 130, 129, 128, 127, 126, 124, 123, 122, 121, 120, 119, 118, 116,
    4427             :   115, 114, 113, 112, 111, 110, 109, 108, 106, 105, 104, 103, 102, 101, 100,
    4428             :   99, 98, 97, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 84, 83, 82, 81, 80, 79,
    4429             :   78, 77, 76, 75, 74, 73, 72, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59,
    4430             :   58, 57, 56, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39,
    4431             :   38, 37, 36, 35, 34, 33, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19,
    4432             :   18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
    4433             : };
    4434             : 
    4435             : /*
    4436             :  * Internal ln() function that does not check for specials, zero or one.
    4437             :  * Relative error: abs(result - log(a)) < 0.1 * 10**-prec * abs(log(a))
    4438             :  */
    4439             : static void
    4440           0 : _mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    4441             :          uint32_t *status)
    4442             : {
    4443             :     mpd_context_t varcontext, maxcontext;
    4444           0 :     mpd_t *z = (mpd_t *) result;
    4445           0 :     MPD_NEW_STATIC(v,0,0,0,0);
    4446           0 :     MPD_NEW_STATIC(vtmp,0,0,0,0);
    4447           0 :     MPD_NEW_STATIC(tmp,0,0,0,0);
    4448             :     mpd_ssize_t klist[MPD_MAX_PREC_LOG2];
    4449             :     mpd_ssize_t maxprec, shift, t;
    4450             :     mpd_ssize_t a_digits, a_exp;
    4451             :     mpd_uint_t dummy, x;
    4452             :     int i;
    4453             : 
    4454             :     assert(!mpd_isspecial(a) && !mpd_iszerocoeff(a));
    4455             : 
    4456             :     /*
    4457             :      * We are calculating ln(a) = ln(v * 10^t) = ln(v) + t*ln(10),
    4458             :      * where 0.5 < v <= 5.
    4459             :      */
    4460           0 :     if (!mpd_qcopy(&v, a, status)) {
    4461           0 :         mpd_seterror(result, MPD_Malloc_error, status);
    4462           0 :         goto finish;
    4463             :     }
    4464             : 
    4465             :     /* Initial approximation: we have at least one non-zero digit */
    4466           0 :     _mpd_get_msdigits(&dummy, &x, &v, 3);
    4467           0 :     if (x < 10) x *= 10;
    4468           0 :     if (x < 100) x *= 10;
    4469           0 :     x -= 100;
    4470             : 
    4471             :     /* a may equal z */
    4472           0 :     a_digits = a->digits;
    4473           0 :     a_exp = a->exp;
    4474             : 
    4475             :     mpd_minalloc(z);
    4476             :     mpd_clear_flags(z);
    4477           0 :     z->data[0] = lnapprox[x];
    4478           0 :     z->len = 1;
    4479           0 :     z->exp = -3;
    4480           0 :     mpd_setdigits(z);
    4481             : 
    4482           0 :     if (x <= 400) {
    4483             :         /* Reduce the input operand to 1.00 <= v <= 5.00. Let y = x + 100,
    4484             :          * so 100 <= y <= 500. Since y contains the most significant digits
    4485             :          * of v, y/100 <= v < (y+1)/100 and abs(z - log(v)) < 10**-2. */
    4486           0 :         v.exp = -(a_digits - 1);
    4487           0 :         t = a_exp + a_digits - 1;
    4488             :     }
    4489             :     else {
    4490             :         /* Reduce the input operand to 0.500 < v <= 0.999. Let y = x + 100,
    4491             :          * so 500 < y <= 999. Since y contains the most significant digits
    4492             :          * of v, y/1000 <= v < (y+1)/1000 and abs(z - log(v)) < 10**-2. */
    4493           0 :         v.exp = -a_digits;
    4494           0 :         t = a_exp + a_digits;
    4495             :         mpd_set_negative(z);
    4496             :     }
    4497             : 
    4498           0 :     mpd_maxcontext(&maxcontext);
    4499           0 :     mpd_maxcontext(&varcontext);
    4500           0 :     varcontext.round = MPD_ROUND_TRUNC;
    4501             : 
    4502           0 :     maxprec = ctx->prec + 2;
    4503           0 :     if (t == 0 && (x <= 15 || x >= 800)) {
    4504             :         /* 0.900 <= v <= 1.15: Estimate the magnitude of the logarithm.
    4505             :          * If ln(v) will underflow, skip the loop. Otherwise, adjust the
    4506             :          * precision upwards in order to obtain a sufficient number of
    4507             :          * significant digits.
    4508             :          *
    4509             :          *   Case v > 1:
    4510             :          *      abs((v-1)/10) < abs((v-1)/v) < abs(ln(v)) < abs(v-1)
    4511             :          *   Case v < 1:
    4512             :          *      abs(v-1) < abs(ln(v)) < abs((v-1)/v) < abs((v-1)*10)
    4513             :          */
    4514           0 :         int cmp = _mpd_cmp(&v, &one);
    4515             : 
    4516             :         /* Upper bound (assume v > 1): abs(v-1), unrounded */
    4517           0 :         _mpd_qsub(&tmp, &v, &one, &maxcontext, &maxcontext.status);
    4518           0 :         if (maxcontext.status & MPD_Errors) {
    4519           0 :             mpd_seterror(result, MPD_Malloc_error, status);
    4520           0 :             goto finish;
    4521             :         }
    4522             : 
    4523           0 :         if (cmp < 0) {
    4524             :             /* v < 1: abs((v-1)*10) */
    4525           0 :             tmp.exp += 1;
    4526             :         }
    4527           0 :         if (mpd_adjexp(&tmp) < mpd_etiny(ctx)) {
    4528             :             /* The upper bound is less than etiny: Underflow to zero */
    4529           0 :             _settriple(result, (cmp<0), 1, mpd_etiny(ctx)-1);
    4530           0 :             goto finish;
    4531             :         }
    4532             :         /* Lower bound: abs((v-1)/10) or abs(v-1) */
    4533           0 :         tmp.exp -= 1;
    4534           0 :         if (mpd_adjexp(&tmp) < 0) {
    4535             :             /* Absolute error of the loop: abs(z - log(v)) < 10**-p. If
    4536             :              * p = ctx->prec+2-adjexp(lower), then the relative error of
    4537             :              * the result is (using 10**adjexp(x) <= abs(x)):
    4538             :              *
    4539             :              *   abs(z - log(v)) / abs(log(v)) < 10**-p / abs(log(v))
    4540             :              *                                 <= 10**(-ctx->prec-2)
    4541             :              */
    4542           0 :             maxprec = maxprec - mpd_adjexp(&tmp);
    4543             :         }
    4544             :     }
    4545             : 
    4546           0 :     i = ln_schedule_prec(klist, maxprec, 2);
    4547           0 :     for (; i >= 0; i--) {
    4548           0 :         varcontext.prec = 2*klist[i]+3;
    4549           0 :         z->flags ^= MPD_NEG;
    4550           0 :         _mpd_qexp(&tmp, z, &varcontext, status);
    4551           0 :         z->flags ^= MPD_NEG;
    4552             : 
    4553           0 :         if (v.digits > varcontext.prec) {
    4554           0 :             shift = v.digits - varcontext.prec;
    4555           0 :             mpd_qshiftr(&vtmp, &v, shift, status);
    4556           0 :             vtmp.exp += shift;
    4557           0 :             mpd_qmul(&tmp, &vtmp, &tmp, &varcontext, status);
    4558             :         }
    4559             :         else {
    4560           0 :             mpd_qmul(&tmp, &v, &tmp, &varcontext, status);
    4561             :         }
    4562             : 
    4563           0 :         mpd_qsub(&tmp, &tmp, &one, &maxcontext, status);
    4564           0 :         mpd_qadd(z, z, &tmp, &maxcontext, status);
    4565           0 :         if (mpd_isspecial(z)) {
    4566           0 :             break;
    4567             :         }
    4568             :     }
    4569             : 
    4570             :     /*
    4571             :      * Case t == 0:
    4572             :      *    t * log(10) == 0, the result does not change and the analysis
    4573             :      *    above applies. If v < 0.900 or v > 1.15, the relative error is
    4574             :      *    less than 10**(-ctx.prec-1).
    4575             :      * Case t != 0:
    4576             :      *      z := approx(log(v))
    4577             :      *      y := approx(log(10))
    4578             :      *      p := maxprec = ctx->prec + 2
    4579             :      *   Absolute errors:
    4580             :      *      1) abs(z - log(v)) < 10**-p
    4581             :      *      2) abs(y - log(10)) < 10**-p
    4582             :      *   The multiplication is exact, so:
    4583             :      *      3) abs(t*y - t*log(10)) < t*10**-p
    4584             :      *   The sum is exact, so:
    4585             :      *      4) abs((z + t*y) - (log(v) + t*log(10))) < (abs(t) + 1) * 10**-p
    4586             :      *   Bounds for log(v) and log(10):
    4587             :      *      5) -7/10 < log(v) < 17/10
    4588             :      *      6) 23/10 < log(10) < 24/10
    4589             :      *   Using 4), 5), 6) and t != 0, the relative error is:
    4590             :      *
    4591             :      *      7) relerr < ((abs(t) + 1)*10**-p) / abs(log(v) + t*log(10))
    4592             :      *                < 0.5 * 10**(-p + 1) = 0.5 * 10**(-ctx->prec-1)
    4593             :      */
    4594           0 :     mpd_qln10(&v, maxprec+1, status);
    4595           0 :     mpd_qmul_ssize(&tmp, &v, t, &maxcontext, status);
    4596           0 :     mpd_qadd(result, &tmp, z, &maxcontext, status);
    4597             : 
    4598             : 
    4599             : finish:
    4600           0 :     *status |= (MPD_Inexact|MPD_Rounded);
    4601             :     mpd_del(&v);
    4602             :     mpd_del(&vtmp);
    4603             :     mpd_del(&tmp);
    4604           0 : }
    4605             : 
    4606             : /* ln(a) */
    4607             : void
    4608           0 : mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    4609             :         uint32_t *status)
    4610             : {
    4611             :     mpd_context_t workctx;
    4612             :     mpd_ssize_t adjexp, t;
    4613             : 
    4614           0 :     if (mpd_isspecial(a)) {
    4615           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    4616             :             return;
    4617             :         }
    4618           0 :         if (mpd_isnegative(a)) {
    4619           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    4620             :             return;
    4621             :         }
    4622           0 :         mpd_setspecial(result, MPD_POS, MPD_INF);
    4623             :         return;
    4624             :     }
    4625           0 :     if (mpd_iszerocoeff(a)) {
    4626           0 :         mpd_setspecial(result, MPD_NEG, MPD_INF);
    4627             :         return;
    4628             :     }
    4629           0 :     if (mpd_isnegative(a)) {
    4630           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    4631             :         return;
    4632             :     }
    4633           0 :     if (_mpd_cmp(a, &one) == 0) {
    4634           0 :         _settriple(result, MPD_POS, 0, 0);
    4635             :         return;
    4636             :     }
    4637             :     /*
    4638             :      * Check if the result will overflow (0 < x, x != 1):
    4639             :      *   1) log10(x) < 0 iff adjexp(x) < 0
    4640             :      *   2) 0 < x /\ x <= y ==> adjexp(x) <= adjexp(y)
    4641             :      *   3) 0 < x /\ x != 1 ==> 2 * abs(log10(x)) < abs(log(x))
    4642             :      *   4) adjexp(x) <= log10(x) < adjexp(x) + 1
    4643             :      *
    4644             :      * Case adjexp(x) >= 0:
    4645             :      *   5) 2 * adjexp(x) < abs(log(x))
    4646             :      *   Case adjexp(x) > 0:
    4647             :      *     6) adjexp(2 * adjexp(x)) <= adjexp(abs(log(x)))
    4648             :      *   Case adjexp(x) == 0:
    4649             :      *     mpd_exp_digits(t)-1 == 0 <= emax (the shortcut is not triggered)
    4650             :      *
    4651             :      * Case adjexp(x) < 0:
    4652             :      *   7) 2 * (-adjexp(x) - 1) < abs(log(x))
    4653             :      *   Case adjexp(x) < -1:
    4654             :      *     8) adjexp(2 * (-adjexp(x) - 1)) <= adjexp(abs(log(x)))
    4655             :      *   Case adjexp(x) == -1:
    4656             :      *     mpd_exp_digits(t)-1 == 0 <= emax (the shortcut is not triggered)
    4657             :      */
    4658           0 :     adjexp = mpd_adjexp(a);
    4659           0 :     t = (adjexp < 0) ? -adjexp-1 : adjexp;
    4660           0 :     t *= 2;
    4661           0 :     if (mpd_exp_digits(t)-1 > ctx->emax) {
    4662           0 :         *status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;
    4663           0 :         mpd_setspecial(result, (adjexp<0), MPD_INF);
    4664             :         return;
    4665             :     }
    4666             : 
    4667           0 :     workctx = *ctx;
    4668           0 :     workctx.round = MPD_ROUND_HALF_EVEN;
    4669             : 
    4670           0 :     if (ctx->allcr) {
    4671           0 :         MPD_NEW_STATIC(t1, 0,0,0,0);
    4672           0 :         MPD_NEW_STATIC(t2, 0,0,0,0);
    4673           0 :         MPD_NEW_STATIC(ulp, 0,0,0,0);
    4674           0 :         MPD_NEW_STATIC(aa, 0,0,0,0);
    4675             :         mpd_ssize_t prec;
    4676             : 
    4677           0 :         if (result == a) {
    4678           0 :             if (!mpd_qcopy(&aa, a, status)) {
    4679           0 :                 mpd_seterror(result, MPD_Malloc_error, status);
    4680             :                 return;
    4681             :             }
    4682           0 :             a = &aa;
    4683             :         }
    4684             : 
    4685           0 :         workctx.clamp = 0;
    4686           0 :         prec = ctx->prec + 3;
    4687             :         while (1) {
    4688           0 :             workctx.prec = prec;
    4689           0 :             _mpd_qln(result, a, &workctx, status);
    4690           0 :             _ssettriple(&ulp, MPD_POS, 1,
    4691           0 :                         result->exp + result->digits-workctx.prec);
    4692             : 
    4693           0 :             workctx.prec = ctx->prec;
    4694           0 :             mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status);
    4695           0 :             mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status);
    4696           0 :             if (mpd_isspecial(result) || mpd_iszerocoeff(result) ||
    4697           0 :                 mpd_qcmp(&t1, &t2, status) == 0) {
    4698           0 :                 workctx.clamp = ctx->clamp;
    4699           0 :                 mpd_check_underflow(result, &workctx, status);
    4700           0 :                 mpd_qfinalize(result, &workctx, status);
    4701           0 :                 break;
    4702             :             }
    4703           0 :             prec += MPD_RDIGITS;
    4704           0 :         }
    4705             :         mpd_del(&t1);
    4706             :         mpd_del(&t2);
    4707             :         mpd_del(&ulp);
    4708             :         mpd_del(&aa);
    4709             :     }
    4710             :     else {
    4711           0 :         _mpd_qln(result, a, &workctx, status);
    4712           0 :         mpd_check_underflow(result, &workctx, status);
    4713           0 :         mpd_qfinalize(result, &workctx, status);
    4714             :     }
    4715             : }
    4716             : 
    4717             : /*
    4718             :  * Internal log10() function that does not check for specials, zero or one.
    4719             :  * Case SKIP_FINALIZE:
    4720             :  *   Relative error: abs(result - log10(a)) < 0.1 * 10**-prec * abs(log10(a))
    4721             :  * Case DO_FINALIZE:
    4722             :  *   Ulp error: abs(result - log10(a)) < ulp(log10(a))
    4723             :  */
    4724             : enum {SKIP_FINALIZE, DO_FINALIZE};
    4725             : static void
    4726           0 : _mpd_qlog10(int action, mpd_t *result, const mpd_t *a,
    4727             :             const mpd_context_t *ctx, uint32_t *status)
    4728             : {
    4729             :     mpd_context_t workctx;
    4730           0 :     MPD_NEW_STATIC(ln10,0,0,0,0);
    4731             : 
    4732           0 :     mpd_maxcontext(&workctx);
    4733           0 :     workctx.prec = ctx->prec + 3;
    4734             :     /* relative error: 0.1 * 10**(-p-3). The specific underflow shortcut
    4735             :      * in _mpd_qln() does not change the final result. */
    4736           0 :     _mpd_qln(result, a, &workctx, status);
    4737             :     /* relative error: 5 * 10**(-p-3) */
    4738           0 :     mpd_qln10(&ln10, workctx.prec, status);
    4739             : 
    4740           0 :     if (action == DO_FINALIZE) {
    4741           0 :         workctx = *ctx;
    4742           0 :         workctx.round = MPD_ROUND_HALF_EVEN;
    4743             :     }
    4744             :     /* SKIP_FINALIZE: relative error: 5 * 10**(-p-3) */
    4745           0 :     _mpd_qdiv(NO_IDEAL_EXP, result, result, &ln10, &workctx, status);
    4746             : 
    4747             :     mpd_del(&ln10);
    4748           0 : }
    4749             : 
    4750             : /* log10(a) */
    4751             : void
    4752           0 : mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    4753             :            uint32_t *status)
    4754             : {
    4755             :     mpd_context_t workctx;
    4756             :     mpd_ssize_t adjexp, t;
    4757             : 
    4758           0 :     workctx = *ctx;
    4759           0 :     workctx.round = MPD_ROUND_HALF_EVEN;
    4760             : 
    4761           0 :     if (mpd_isspecial(a)) {
    4762           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    4763             :             return;
    4764             :         }
    4765           0 :         if (mpd_isnegative(a)) {
    4766           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    4767             :             return;
    4768             :         }
    4769           0 :         mpd_setspecial(result, MPD_POS, MPD_INF);
    4770             :         return;
    4771             :     }
    4772           0 :     if (mpd_iszerocoeff(a)) {
    4773           0 :         mpd_setspecial(result, MPD_NEG, MPD_INF);
    4774             :         return;
    4775             :     }
    4776           0 :     if (mpd_isnegative(a)) {
    4777           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    4778             :         return;
    4779             :     }
    4780           0 :     if (mpd_coeff_ispow10(a)) {
    4781           0 :         uint8_t sign = 0;
    4782           0 :         adjexp = mpd_adjexp(a);
    4783           0 :         if (adjexp < 0) {
    4784           0 :             sign = 1;
    4785           0 :             adjexp = -adjexp;
    4786             :         }
    4787           0 :         _settriple(result, sign, adjexp, 0);
    4788           0 :         mpd_qfinalize(result, &workctx, status);
    4789             :         return;
    4790             :     }
    4791             :     /*
    4792             :      * Check if the result will overflow (0 < x, x != 1):
    4793             :      *   1) log10(x) < 0 iff adjexp(x) < 0
    4794             :      *   2) 0 < x /\ x <= y ==> adjexp(x) <= adjexp(y)
    4795             :      *   3) adjexp(x) <= log10(x) < adjexp(x) + 1
    4796             :      *
    4797             :      * Case adjexp(x) >= 0:
    4798             :      *   4) adjexp(x) <= abs(log10(x))
    4799             :      *   Case adjexp(x) > 0:
    4800             :      *     5) adjexp(adjexp(x)) <= adjexp(abs(log10(x)))
    4801             :      *   Case adjexp(x) == 0:
    4802             :      *     mpd_exp_digits(t)-1 == 0 <= emax (the shortcut is not triggered)
    4803             :      *
    4804             :      * Case adjexp(x) < 0:
    4805             :      *   6) -adjexp(x) - 1 < abs(log10(x))
    4806             :      *   Case adjexp(x) < -1:
    4807             :      *     7) adjexp(-adjexp(x) - 1) <= adjexp(abs(log(x)))
    4808             :      *   Case adjexp(x) == -1:
    4809             :      *     mpd_exp_digits(t)-1 == 0 <= emax (the shortcut is not triggered)
    4810             :      */
    4811           0 :     adjexp = mpd_adjexp(a);
    4812           0 :     t = (adjexp < 0) ? -adjexp-1 : adjexp;
    4813           0 :     if (mpd_exp_digits(t)-1 > ctx->emax) {
    4814           0 :         *status |= MPD_Overflow|MPD_Inexact|MPD_Rounded;
    4815           0 :         mpd_setspecial(result, (adjexp<0), MPD_INF);
    4816             :         return;
    4817             :     }
    4818             : 
    4819           0 :     if (ctx->allcr) {
    4820           0 :         MPD_NEW_STATIC(t1, 0,0,0,0);
    4821           0 :         MPD_NEW_STATIC(t2, 0,0,0,0);
    4822           0 :         MPD_NEW_STATIC(ulp, 0,0,0,0);
    4823           0 :         MPD_NEW_STATIC(aa, 0,0,0,0);
    4824             :         mpd_ssize_t prec;
    4825             : 
    4826           0 :         if (result == a) {
    4827           0 :             if (!mpd_qcopy(&aa, a, status)) {
    4828           0 :                 mpd_seterror(result, MPD_Malloc_error, status);
    4829             :                 return;
    4830             :             }
    4831           0 :             a = &aa;
    4832             :         }
    4833             : 
    4834           0 :         workctx.clamp = 0;
    4835           0 :         prec = ctx->prec + 3;
    4836             :         while (1) {
    4837           0 :             workctx.prec = prec;
    4838           0 :             _mpd_qlog10(SKIP_FINALIZE, result, a, &workctx, status);
    4839           0 :             _ssettriple(&ulp, MPD_POS, 1,
    4840           0 :                         result->exp + result->digits-workctx.prec);
    4841             : 
    4842           0 :             workctx.prec = ctx->prec;
    4843           0 :             mpd_qadd(&t1, result, &ulp, &workctx, &workctx.status);
    4844           0 :             mpd_qsub(&t2, result, &ulp, &workctx, &workctx.status);
    4845           0 :             if (mpd_isspecial(result) || mpd_iszerocoeff(result) ||
    4846           0 :                 mpd_qcmp(&t1, &t2, status) == 0) {
    4847           0 :                 workctx.clamp = ctx->clamp;
    4848           0 :                 mpd_check_underflow(result, &workctx, status);
    4849           0 :                 mpd_qfinalize(result, &workctx, status);
    4850           0 :                 break;
    4851             :             }
    4852           0 :             prec += MPD_RDIGITS;
    4853           0 :         }
    4854             :         mpd_del(&t1);
    4855             :         mpd_del(&t2);
    4856             :         mpd_del(&ulp);
    4857             :         mpd_del(&aa);
    4858             :     }
    4859             :     else {
    4860           0 :         _mpd_qlog10(DO_FINALIZE, result, a, &workctx, status);
    4861           0 :         mpd_check_underflow(result, &workctx, status);
    4862             :     }
    4863             : }
    4864             : 
    4865             : /*
    4866             :  * Maximum of the two operands. Attention: If one operand is a quiet NaN and the
    4867             :  * other is numeric, the numeric operand is returned. This may not be what one
    4868             :  * expects.
    4869             :  */
    4870             : void
    4871           0 : mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b,
    4872             :          const mpd_context_t *ctx, uint32_t *status)
    4873             : {
    4874             :     int c;
    4875             : 
    4876           0 :     if (mpd_isqnan(a) && !mpd_isnan(b)) {
    4877           0 :         mpd_qcopy(result, b, status);
    4878             :     }
    4879           0 :     else if (mpd_isqnan(b) && !mpd_isnan(a)) {
    4880           0 :         mpd_qcopy(result, a, status);
    4881             :     }
    4882           0 :     else if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    4883           0 :         return;
    4884             :     }
    4885             :     else {
    4886           0 :         c = _mpd_cmp(a, b);
    4887           0 :         if (c == 0) {
    4888           0 :             c = _mpd_cmp_numequal(a, b);
    4889             :         }
    4890             : 
    4891           0 :         if (c < 0) {
    4892           0 :             mpd_qcopy(result, b, status);
    4893             :         }
    4894             :         else {
    4895           0 :             mpd_qcopy(result, a, status);
    4896             :         }
    4897             :     }
    4898             : 
    4899           0 :     mpd_qfinalize(result, ctx, status);
    4900             : }
    4901             : 
    4902             : /*
    4903             :  * Maximum magnitude: Same as mpd_max(), but compares the operands with their
    4904             :  * sign ignored.
    4905             :  */
    4906             : void
    4907           0 : mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b,
    4908             :              const mpd_context_t *ctx, uint32_t *status)
    4909             : {
    4910             :     int c;
    4911             : 
    4912           0 :     if (mpd_isqnan(a) && !mpd_isnan(b)) {
    4913           0 :         mpd_qcopy(result, b, status);
    4914             :     }
    4915           0 :     else if (mpd_isqnan(b) && !mpd_isnan(a)) {
    4916           0 :         mpd_qcopy(result, a, status);
    4917             :     }
    4918           0 :     else if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    4919           0 :         return;
    4920             :     }
    4921             :     else {
    4922           0 :         c = _mpd_cmp_abs(a, b);
    4923           0 :         if (c == 0) {
    4924           0 :             c = _mpd_cmp_numequal(a, b);
    4925             :         }
    4926             : 
    4927           0 :         if (c < 0) {
    4928           0 :             mpd_qcopy(result, b, status);
    4929             :         }
    4930             :         else {
    4931           0 :             mpd_qcopy(result, a, status);
    4932             :         }
    4933             :     }
    4934             : 
    4935           0 :     mpd_qfinalize(result, ctx, status);
    4936             : }
    4937             : 
    4938             : /*
    4939             :  * Minimum of the two operands. Attention: If one operand is a quiet NaN and the
    4940             :  * other is numeric, the numeric operand is returned. This may not be what one
    4941             :  * expects.
    4942             :  */
    4943             : void
    4944           0 : mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b,
    4945             :          const mpd_context_t *ctx, uint32_t *status)
    4946             : {
    4947             :     int c;
    4948             : 
    4949           0 :     if (mpd_isqnan(a) && !mpd_isnan(b)) {
    4950           0 :         mpd_qcopy(result, b, status);
    4951             :     }
    4952           0 :     else if (mpd_isqnan(b) && !mpd_isnan(a)) {
    4953           0 :         mpd_qcopy(result, a, status);
    4954             :     }
    4955           0 :     else if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    4956           0 :         return;
    4957             :     }
    4958             :     else {
    4959           0 :         c = _mpd_cmp(a, b);
    4960           0 :         if (c == 0) {
    4961           0 :             c = _mpd_cmp_numequal(a, b);
    4962             :         }
    4963             : 
    4964           0 :         if (c < 0) {
    4965           0 :             mpd_qcopy(result, a, status);
    4966             :         }
    4967             :         else {
    4968           0 :             mpd_qcopy(result, b, status);
    4969             :         }
    4970             :     }
    4971             : 
    4972           0 :     mpd_qfinalize(result, ctx, status);
    4973             : }
    4974             : 
    4975             : /*
    4976             :  * Minimum magnitude: Same as mpd_min(), but compares the operands with their
    4977             :  * sign ignored.
    4978             :  */
    4979             : void
    4980           0 : mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b,
    4981             :              const mpd_context_t *ctx, uint32_t *status)
    4982             : {
    4983             :     int c;
    4984             : 
    4985           0 :     if (mpd_isqnan(a) && !mpd_isnan(b)) {
    4986           0 :         mpd_qcopy(result, b, status);
    4987             :     }
    4988           0 :     else if (mpd_isqnan(b) && !mpd_isnan(a)) {
    4989           0 :         mpd_qcopy(result, a, status);
    4990             :     }
    4991           0 :     else if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    4992           0 :         return;
    4993             :     }
    4994             :     else {
    4995           0 :         c = _mpd_cmp_abs(a, b);
    4996           0 :         if (c == 0) {
    4997           0 :             c = _mpd_cmp_numequal(a, b);
    4998             :         }
    4999             : 
    5000           0 :         if (c < 0) {
    5001           0 :             mpd_qcopy(result, a, status);
    5002             :         }
    5003             :         else {
    5004           0 :             mpd_qcopy(result, b, status);
    5005             :         }
    5006             :     }
    5007             : 
    5008           0 :     mpd_qfinalize(result, ctx, status);
    5009             : }
    5010             : 
    5011             : /* Minimum space needed for the result array in _karatsuba_rec(). */
    5012             : static inline mpd_size_t
    5013           0 : _kmul_resultsize(mpd_size_t la, mpd_size_t lb)
    5014             : {
    5015             :     mpd_size_t n, m;
    5016             : 
    5017           0 :     n = add_size_t(la, lb);
    5018           0 :     n = add_size_t(n, 1);
    5019             : 
    5020           0 :     m = (la+1)/2 + 1;
    5021           0 :     m = mul_size_t(m, 3);
    5022             : 
    5023           0 :     return (m > n) ? m : n;
    5024             : }
    5025             : 
    5026             : /* Work space needed in _karatsuba_rec(). lim >= 4 */
    5027             : static inline mpd_size_t
    5028           0 : _kmul_worksize(mpd_size_t n, mpd_size_t lim)
    5029             : {
    5030             :     mpd_size_t m;
    5031             : 
    5032           0 :     if (n <= lim) {
    5033           0 :         return 0;
    5034             :     }
    5035             : 
    5036           0 :     m = (n+1)/2 + 1;
    5037             : 
    5038           0 :     return add_size_t(mul_size_t(m, 2), _kmul_worksize(m, lim));
    5039             : }
    5040             : 
    5041             : 
    5042             : #define MPD_KARATSUBA_BASECASE 16  /* must be >= 4 */
    5043             : 
    5044             : /*
    5045             :  * Add the product of a and b to c.
    5046             :  * c must be _kmul_resultsize(la, lb) in size.
    5047             :  * w is used as a work array and must be _kmul_worksize(a, lim) in size.
    5048             :  * Roman E. Maeder, Storage Allocation for the Karatsuba Integer Multiplication
    5049             :  * Algorithm. In "Design and implementation of symbolic computation systems",
    5050             :  * Springer, 1993, ISBN 354057235X, 9783540572350.
    5051             :  */
    5052             : static void
    5053           0 : _karatsuba_rec(mpd_uint_t *c, const mpd_uint_t *a, const mpd_uint_t *b,
    5054             :                mpd_uint_t *w, mpd_size_t la, mpd_size_t lb)
    5055             : {
    5056             :     mpd_size_t m, lt;
    5057             : 
    5058             :     assert(la >= lb && lb > 0);
    5059             :     assert(la <= MPD_KARATSUBA_BASECASE || w != NULL);
    5060             : 
    5061           0 :     if (la <= MPD_KARATSUBA_BASECASE) {
    5062           0 :         _mpd_basemul(c, a, b, la, lb);
    5063           0 :         return;
    5064             :     }
    5065             : 
    5066           0 :     m = (la+1)/2;  /* ceil(la/2) */
    5067             : 
    5068             :     /* lb <= m < la */
    5069           0 :     if (lb <= m) {
    5070             : 
    5071             :         /* lb can now be larger than la-m */
    5072           0 :         if (lb > la-m) {
    5073           0 :             lt = lb + lb + 1;       /* space needed for result array */
    5074             :             mpd_uint_zero(w, lt);   /* clear result array */
    5075           0 :             _karatsuba_rec(w, b, a+m, w+lt, lb, la-m); /* b*ah */
    5076             :         }
    5077             :         else {
    5078           0 :             lt = (la-m) + (la-m) + 1;  /* space needed for result array */
    5079             :             mpd_uint_zero(w, lt);      /* clear result array */
    5080           0 :             _karatsuba_rec(w, a+m, b, w+lt, la-m, lb); /* ah*b */
    5081             :         }
    5082           0 :         _mpd_baseaddto(c+m, w, (la-m)+lb);      /* add ah*b*B**m */
    5083             : 
    5084           0 :         lt = m + m + 1;         /* space needed for the result array */
    5085             :         mpd_uint_zero(w, lt);   /* clear result array */
    5086           0 :         _karatsuba_rec(w, a, b, w+lt, m, lb);  /* al*b */
    5087           0 :         _mpd_baseaddto(c, w, m+lb);    /* add al*b */
    5088             : 
    5089           0 :         return;
    5090             :     }
    5091             : 
    5092             :     /* la >= lb > m */
    5093           0 :     memcpy(w, a, m * sizeof *w);
    5094           0 :     w[m] = 0;
    5095           0 :     _mpd_baseaddto(w, a+m, la-m);
    5096             : 
    5097           0 :     memcpy(w+(m+1), b, m * sizeof *w);
    5098           0 :     w[m+1+m] = 0;
    5099           0 :     _mpd_baseaddto(w+(m+1), b+m, lb-m);
    5100             : 
    5101           0 :     _karatsuba_rec(c+m, w, w+(m+1), w+2*(m+1), m+1, m+1);
    5102             : 
    5103           0 :     lt = (la-m) + (la-m) + 1;
    5104             :     mpd_uint_zero(w, lt);
    5105             : 
    5106           0 :     _karatsuba_rec(w, a+m, b+m, w+lt, la-m, lb-m);
    5107             : 
    5108           0 :     _mpd_baseaddto(c+2*m, w, (la-m) + (lb-m));
    5109           0 :     _mpd_basesubfrom(c+m, w, (la-m) + (lb-m));
    5110             : 
    5111           0 :     lt = m + m + 1;
    5112             :     mpd_uint_zero(w, lt);
    5113             : 
    5114           0 :     _karatsuba_rec(w, a, b, w+lt, m, m);
    5115           0 :     _mpd_baseaddto(c, w, m+m);
    5116           0 :     _mpd_basesubfrom(c+m, w, m+m);
    5117             : 
    5118           0 :     return;
    5119             : }
    5120             : 
    5121             : /*
    5122             :  * Multiply u and v, using Karatsuba multiplication. Returns a pointer
    5123             :  * to the result or NULL in case of failure (malloc error).
    5124             :  * Conditions: ulen >= vlen, ulen >= 4
    5125             :  */
    5126             : mpd_uint_t *
    5127           0 : _mpd_kmul(const mpd_uint_t *u, const mpd_uint_t *v,
    5128             :           mpd_size_t ulen, mpd_size_t vlen,
    5129             :           mpd_size_t *rsize)
    5130             : {
    5131           0 :     mpd_uint_t *result = NULL, *w = NULL;
    5132             :     mpd_size_t m;
    5133             : 
    5134             :     assert(ulen >= 4);
    5135             :     assert(ulen >= vlen);
    5136             : 
    5137           0 :     *rsize = _kmul_resultsize(ulen, vlen);
    5138           0 :     if ((result = mpd_calloc(*rsize, sizeof *result)) == NULL) {
    5139           0 :         return NULL;
    5140             :     }
    5141             : 
    5142           0 :     m = _kmul_worksize(ulen, MPD_KARATSUBA_BASECASE);
    5143           0 :     if (m && ((w = mpd_calloc(m, sizeof *w)) == NULL)) {
    5144           0 :         mpd_free(result);
    5145           0 :         return NULL;
    5146             :     }
    5147             : 
    5148           0 :     _karatsuba_rec(result, u, v, w, ulen, vlen);
    5149             : 
    5150             : 
    5151           0 :     if (w) mpd_free(w);
    5152           0 :     return result;
    5153             : }
    5154             : 
    5155             : 
    5156             : /*
    5157             :  * Determine the minimum length for the number theoretic transform. Valid
    5158             :  * transform lengths are 2**n or 3*2**n, where 2**n <= MPD_MAXTRANSFORM_2N.
    5159             :  * The function finds the shortest length m such that rsize <= m.
    5160             :  */
    5161             : static inline mpd_size_t
    5162           0 : _mpd_get_transform_len(mpd_size_t rsize)
    5163             : {
    5164             :     mpd_size_t log2rsize;
    5165             :     mpd_size_t x, step;
    5166             : 
    5167             :     assert(rsize >= 4);
    5168           0 :     log2rsize = mpd_bsr(rsize);
    5169             : 
    5170           0 :     if (rsize <= 1024) {
    5171             :         /* 2**n is faster in this range. */
    5172           0 :         x = ((mpd_size_t)1)<<log2rsize;
    5173           0 :         return (rsize == x) ? x : x<<1;
    5174             :     }
    5175           0 :     else if (rsize <= MPD_MAXTRANSFORM_2N) {
    5176           0 :         x = ((mpd_size_t)1)<<log2rsize;
    5177           0 :         if (rsize == x) return x;
    5178           0 :         step = x>>1;
    5179           0 :         x += step;
    5180           0 :         return (rsize <= x) ? x : x + step;
    5181             :     }
    5182           0 :     else if (rsize <= MPD_MAXTRANSFORM_2N+MPD_MAXTRANSFORM_2N/2) {
    5183           0 :         return MPD_MAXTRANSFORM_2N+MPD_MAXTRANSFORM_2N/2;
    5184             :     }
    5185           0 :     else if (rsize <= 3*MPD_MAXTRANSFORM_2N) {
    5186           0 :         return 3*MPD_MAXTRANSFORM_2N;
    5187             :     }
    5188             :     else {
    5189           0 :         return MPD_SIZE_MAX;
    5190             :     }
    5191             : }
    5192             : 
    5193             : #ifdef PPRO
    5194             : #ifndef _MSC_VER
    5195             : static inline unsigned short
    5196           0 : _mpd_get_control87(void)
    5197             : {
    5198             :     unsigned short cw;
    5199             : 
    5200           0 :     __asm__ __volatile__ ("fnstcw %0" : "=m" (cw));
    5201           0 :     return cw;
    5202             : }
    5203             : 
    5204             : static inline void
    5205           0 : _mpd_set_control87(unsigned short cw)
    5206             : {
    5207           0 :     __asm__ __volatile__ ("fldcw %0" : : "m" (cw));
    5208           0 : }
    5209             : #endif
    5210             : 
    5211             : unsigned int
    5212           0 : mpd_set_fenv(void)
    5213             : {
    5214             :     unsigned int cw;
    5215             : #ifdef _MSC_VER
    5216             :     unsigned int flags =
    5217             :         _EM_INVALID|_EM_DENORMAL|_EM_ZERODIVIDE|_EM_OVERFLOW|
    5218             :         _EM_UNDERFLOW|_EM_INEXACT|_RC_CHOP|_PC_64;
    5219             :     unsigned int mask = _MCW_EM|_MCW_RC|_MCW_PC;
    5220             :     unsigned int dummy;
    5221             : 
    5222             :     __control87_2(0, 0, &cw, NULL);
    5223             :     __control87_2(flags, mask, &dummy, NULL);
    5224             : #else
    5225           0 :     cw = _mpd_get_control87();
    5226           0 :     _mpd_set_control87(cw|0xF3F);
    5227             : #endif
    5228           0 :     return cw;
    5229             : }
    5230             : 
    5231             : void
    5232           0 : mpd_restore_fenv(unsigned int cw)
    5233             : {
    5234             : #ifdef _MSC_VER
    5235             :     unsigned int mask = _MCW_EM|_MCW_RC|_MCW_PC;
    5236             :     unsigned int dummy;
    5237             : 
    5238             :     __control87_2(cw, mask, &dummy, NULL);
    5239             : #else
    5240           0 :     _mpd_set_control87((unsigned short)cw);
    5241             : #endif
    5242           0 : }
    5243             : #endif /* PPRO */
    5244             : 
    5245             : /*
    5246             :  * Multiply u and v, using the fast number theoretic transform. Returns
    5247             :  * a pointer to the result or NULL in case of failure (malloc error).
    5248             :  */
    5249             : mpd_uint_t *
    5250           0 : _mpd_fntmul(const mpd_uint_t *u, const mpd_uint_t *v,
    5251             :             mpd_size_t ulen, mpd_size_t vlen,
    5252             :             mpd_size_t *rsize)
    5253             : {
    5254           0 :     mpd_uint_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *vtmp = NULL;
    5255             :     mpd_size_t n;
    5256             : 
    5257             : #ifdef PPRO
    5258             :     unsigned int cw;
    5259           0 :     cw = mpd_set_fenv();
    5260             : #endif
    5261             : 
    5262           0 :     *rsize = add_size_t(ulen, vlen);
    5263           0 :     if ((n = _mpd_get_transform_len(*rsize)) == MPD_SIZE_MAX) {
    5264           0 :         goto malloc_error;
    5265             :     }
    5266             : 
    5267           0 :     if ((c1 = mpd_calloc(n, sizeof *c1)) == NULL) {
    5268           0 :         goto malloc_error;
    5269             :     }
    5270           0 :     if ((c2 = mpd_calloc(n, sizeof *c2)) == NULL) {
    5271           0 :         goto malloc_error;
    5272             :     }
    5273           0 :     if ((c3 = mpd_calloc(n, sizeof *c3)) == NULL) {
    5274           0 :         goto malloc_error;
    5275             :     }
    5276             : 
    5277           0 :     memcpy(c1, u, ulen * (sizeof *c1));
    5278           0 :     memcpy(c2, u, ulen * (sizeof *c2));
    5279           0 :     memcpy(c3, u, ulen * (sizeof *c3));
    5280             : 
    5281           0 :     if (u == v) {
    5282           0 :         if (!fnt_autoconvolute(c1, n, P1) ||
    5283           0 :             !fnt_autoconvolute(c2, n, P2) ||
    5284           0 :             !fnt_autoconvolute(c3, n, P3)) {
    5285             :             goto malloc_error;
    5286             :         }
    5287             :     }
    5288             :     else {
    5289           0 :         if ((vtmp = mpd_calloc(n, sizeof *vtmp)) == NULL) {
    5290           0 :             goto malloc_error;
    5291             :         }
    5292             : 
    5293           0 :         memcpy(vtmp, v, vlen * (sizeof *vtmp));
    5294           0 :         if (!fnt_convolute(c1, vtmp, n, P1)) {
    5295           0 :             mpd_free(vtmp);
    5296           0 :             goto malloc_error;
    5297             :         }
    5298             : 
    5299           0 :         memcpy(vtmp, v, vlen * (sizeof *vtmp));
    5300           0 :         mpd_uint_zero(vtmp+vlen, n-vlen);
    5301           0 :         if (!fnt_convolute(c2, vtmp, n, P2)) {
    5302           0 :             mpd_free(vtmp);
    5303           0 :             goto malloc_error;
    5304             :         }
    5305             : 
    5306           0 :         memcpy(vtmp, v, vlen * (sizeof *vtmp));
    5307           0 :         mpd_uint_zero(vtmp+vlen, n-vlen);
    5308           0 :         if (!fnt_convolute(c3, vtmp, n, P3)) {
    5309           0 :             mpd_free(vtmp);
    5310           0 :             goto malloc_error;
    5311             :         }
    5312             : 
    5313           0 :         mpd_free(vtmp);
    5314             :     }
    5315             : 
    5316           0 :     crt3(c1, c2, c3, *rsize);
    5317             : 
    5318             : out:
    5319             : #ifdef PPRO
    5320           0 :     mpd_restore_fenv(cw);
    5321             : #endif
    5322           0 :     if (c2) mpd_free(c2);
    5323           0 :     if (c3) mpd_free(c3);
    5324           0 :     return c1;
    5325             : 
    5326             : malloc_error:
    5327           0 :     if (c1) mpd_free(c1);
    5328           0 :     c1 = NULL;
    5329           0 :     goto out;
    5330             : }
    5331             : 
    5332             : 
    5333             : /*
    5334             :  * Karatsuba multiplication with FNT/basemul as the base case.
    5335             :  */
    5336             : static int
    5337           0 : _karatsuba_rec_fnt(mpd_uint_t *c, const mpd_uint_t *a, const mpd_uint_t *b,
    5338             :                    mpd_uint_t *w, mpd_size_t la, mpd_size_t lb)
    5339             : {
    5340             :     mpd_size_t m, lt;
    5341             : 
    5342             :     assert(la >= lb && lb > 0);
    5343             :     assert(la <= 3*(MPD_MAXTRANSFORM_2N/2) || w != NULL);
    5344             : 
    5345           0 :     if (la <= 3*(MPD_MAXTRANSFORM_2N/2)) {
    5346             : 
    5347           0 :         if (lb <= 192) {
    5348           0 :             _mpd_basemul(c, b, a, lb, la);
    5349             :         }
    5350             :         else {
    5351             :             mpd_uint_t *result;
    5352             :             mpd_size_t dummy;
    5353             : 
    5354           0 :             if ((result = _mpd_fntmul(a, b, la, lb, &dummy)) == NULL) {
    5355           0 :                 return 0;
    5356             :             }
    5357           0 :             memcpy(c, result, (la+lb) * (sizeof *result));
    5358           0 :             mpd_free(result);
    5359             :         }
    5360           0 :         return 1;
    5361             :     }
    5362             : 
    5363           0 :     m = (la+1)/2;  /* ceil(la/2) */
    5364             : 
    5365             :     /* lb <= m < la */
    5366           0 :     if (lb <= m) {
    5367             : 
    5368             :         /* lb can now be larger than la-m */
    5369           0 :         if (lb > la-m) {
    5370           0 :             lt = lb + lb + 1;       /* space needed for result array */
    5371             :             mpd_uint_zero(w, lt);   /* clear result array */
    5372           0 :             if (!_karatsuba_rec_fnt(w, b, a+m, w+lt, lb, la-m)) { /* b*ah */
    5373           0 :                 return 0; /* GCOV_UNLIKELY */
    5374             :             }
    5375             :         }
    5376             :         else {
    5377           0 :             lt = (la-m) + (la-m) + 1;  /* space needed for result array */
    5378             :             mpd_uint_zero(w, lt);      /* clear result array */
    5379           0 :             if (!_karatsuba_rec_fnt(w, a+m, b, w+lt, la-m, lb)) { /* ah*b */
    5380           0 :                 return 0; /* GCOV_UNLIKELY */
    5381             :             }
    5382             :         }
    5383           0 :         _mpd_baseaddto(c+m, w, (la-m)+lb); /* add ah*b*B**m */
    5384             : 
    5385           0 :         lt = m + m + 1;         /* space needed for the result array */
    5386             :         mpd_uint_zero(w, lt);   /* clear result array */
    5387           0 :         if (!_karatsuba_rec_fnt(w, a, b, w+lt, m, lb)) {  /* al*b */
    5388           0 :             return 0; /* GCOV_UNLIKELY */
    5389             :         }
    5390           0 :         _mpd_baseaddto(c, w, m+lb);       /* add al*b */
    5391             : 
    5392           0 :         return 1;
    5393             :     }
    5394             : 
    5395             :     /* la >= lb > m */
    5396           0 :     memcpy(w, a, m * sizeof *w);
    5397           0 :     w[m] = 0;
    5398           0 :     _mpd_baseaddto(w, a+m, la-m);
    5399             : 
    5400           0 :     memcpy(w+(m+1), b, m * sizeof *w);
    5401           0 :     w[m+1+m] = 0;
    5402           0 :     _mpd_baseaddto(w+(m+1), b+m, lb-m);
    5403             : 
    5404           0 :     if (!_karatsuba_rec_fnt(c+m, w, w+(m+1), w+2*(m+1), m+1, m+1)) {
    5405           0 :         return 0; /* GCOV_UNLIKELY */
    5406             :     }
    5407             : 
    5408           0 :     lt = (la-m) + (la-m) + 1;
    5409             :     mpd_uint_zero(w, lt);
    5410             : 
    5411           0 :     if (!_karatsuba_rec_fnt(w, a+m, b+m, w+lt, la-m, lb-m)) {
    5412           0 :         return 0; /* GCOV_UNLIKELY */
    5413             :     }
    5414             : 
    5415           0 :     _mpd_baseaddto(c+2*m, w, (la-m) + (lb-m));
    5416           0 :     _mpd_basesubfrom(c+m, w, (la-m) + (lb-m));
    5417             : 
    5418           0 :     lt = m + m + 1;
    5419             :     mpd_uint_zero(w, lt);
    5420             : 
    5421           0 :     if (!_karatsuba_rec_fnt(w, a, b, w+lt, m, m)) {
    5422           0 :         return 0; /* GCOV_UNLIKELY */
    5423             :     }
    5424           0 :     _mpd_baseaddto(c, w, m+m);
    5425           0 :     _mpd_basesubfrom(c+m, w, m+m);
    5426             : 
    5427           0 :     return 1;
    5428             : }
    5429             : 
    5430             : /*
    5431             :  * Multiply u and v, using Karatsuba multiplication with the FNT as the
    5432             :  * base case. Returns a pointer to the result or NULL in case of failure
    5433             :  * (malloc error). Conditions: ulen >= vlen, ulen >= 4.
    5434             :  */
    5435             : mpd_uint_t *
    5436           0 : _mpd_kmul_fnt(const mpd_uint_t *u, const mpd_uint_t *v,
    5437             :               mpd_size_t ulen, mpd_size_t vlen,
    5438             :               mpd_size_t *rsize)
    5439             : {
    5440           0 :     mpd_uint_t *result = NULL, *w = NULL;
    5441             :     mpd_size_t m;
    5442             : 
    5443             :     assert(ulen >= 4);
    5444             :     assert(ulen >= vlen);
    5445             : 
    5446           0 :     *rsize = _kmul_resultsize(ulen, vlen);
    5447           0 :     if ((result = mpd_calloc(*rsize, sizeof *result)) == NULL) {
    5448           0 :         return NULL;
    5449             :     }
    5450             : 
    5451           0 :     m = _kmul_worksize(ulen, 3*(MPD_MAXTRANSFORM_2N/2));
    5452           0 :     if (m && ((w = mpd_calloc(m, sizeof *w)) == NULL)) {
    5453           0 :         mpd_free(result); /* GCOV_UNLIKELY */
    5454           0 :         return NULL; /* GCOV_UNLIKELY */
    5455             :     }
    5456             : 
    5457           0 :     if (!_karatsuba_rec_fnt(result, u, v, w, ulen, vlen)) {
    5458           0 :         mpd_free(result);
    5459           0 :         result = NULL;
    5460             :     }
    5461             : 
    5462             : 
    5463           0 :     if (w) mpd_free(w);
    5464           0 :     return result;
    5465             : }
    5466             : 
    5467             : 
    5468             : /* Deal with the special cases of multiplying infinities. */
    5469             : static void
    5470           0 : _mpd_qmul_inf(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status)
    5471             : {
    5472           0 :     if (mpd_isinfinite(a)) {
    5473           0 :         if (mpd_iszero(b)) {
    5474           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    5475             :         }
    5476             :         else {
    5477           0 :             mpd_setspecial(result, mpd_sign(a)^mpd_sign(b), MPD_INF);
    5478             :         }
    5479           0 :         return;
    5480             :     }
    5481             :     assert(mpd_isinfinite(b));
    5482           0 :     if (mpd_iszero(a)) {
    5483           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    5484             :     }
    5485             :     else {
    5486           0 :         mpd_setspecial(result, mpd_sign(a)^mpd_sign(b), MPD_INF);
    5487             :     }
    5488             : }
    5489             : 
    5490             : /*
    5491             :  * Internal function: Multiply a and b. _mpd_qmul deals with specials but
    5492             :  * does NOT finalize the result. This is for use in mpd_fma().
    5493             :  */
    5494             : static inline void
    5495           0 : _mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
    5496             :           const mpd_context_t *ctx, uint32_t *status)
    5497             : {
    5498           0 :     mpd_t *big = (mpd_t *)a, *small = (mpd_t *)b;
    5499           0 :     mpd_uint_t *rdata = NULL;
    5500             :     mpd_uint_t rbuf[MPD_MINALLOC_MAX];
    5501             :     mpd_size_t rsize, i;
    5502             : 
    5503             : 
    5504           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    5505           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    5506             :             return;
    5507             :         }
    5508           0 :         _mpd_qmul_inf(result, a, b, status);
    5509             :         return;
    5510             :     }
    5511             : 
    5512           0 :     if (small->len > big->len) {
    5513           0 :         _mpd_ptrswap(&big, &small);
    5514             :     }
    5515             : 
    5516           0 :     rsize = big->len + small->len;
    5517             : 
    5518           0 :     if (big->len == 1) {
    5519           0 :         _mpd_singlemul(result->data, big->data[0], small->data[0]);
    5520           0 :         goto finish;
    5521             :     }
    5522           0 :     if (rsize <= (mpd_size_t)MPD_MINALLOC_MAX) {
    5523           0 :         if (big->len == 2) {
    5524           0 :             _mpd_mul_2_le2(rbuf, big->data, small->data, small->len);
    5525             :         }
    5526             :         else {
    5527           0 :             mpd_uint_zero(rbuf, rsize);
    5528           0 :             if (small->len == 1) {
    5529           0 :                 _mpd_shortmul(rbuf, big->data, big->len, small->data[0]);
    5530             :             }
    5531             :             else {
    5532           0 :                 _mpd_basemul(rbuf, small->data, big->data, small->len, big->len);
    5533             :             }
    5534             :         }
    5535           0 :         if (!mpd_qresize(result, rsize, status)) {
    5536             :             return;
    5537             :         }
    5538           0 :         for(i = 0; i < rsize; i++) {
    5539           0 :             result->data[i] = rbuf[i];
    5540             :         }
    5541           0 :         goto finish;
    5542             :     }
    5543             : 
    5544             : 
    5545           0 :     if (small->len <= 256) {
    5546           0 :         rdata = mpd_calloc(rsize, sizeof *rdata);
    5547           0 :         if (rdata != NULL) {
    5548           0 :             if (small->len == 1) {
    5549           0 :                 _mpd_shortmul(rdata, big->data, big->len, small->data[0]);
    5550             :             }
    5551             :             else {
    5552           0 :                 _mpd_basemul(rdata, small->data, big->data, small->len, big->len);
    5553             :             }
    5554             :         }
    5555             :     }
    5556           0 :     else if (rsize <= 1024) {
    5557           0 :         rdata = _mpd_kmul(big->data, small->data, big->len, small->len, &rsize);
    5558             :     }
    5559           0 :     else if (rsize <= 3*MPD_MAXTRANSFORM_2N) {
    5560           0 :         rdata = _mpd_fntmul(big->data, small->data, big->len, small->len, &rsize);
    5561             :     }
    5562             :     else {
    5563           0 :         rdata = _mpd_kmul_fnt(big->data, small->data, big->len, small->len, &rsize);
    5564             :     }
    5565             : 
    5566           0 :     if (rdata == NULL) {
    5567           0 :         mpd_seterror(result, MPD_Malloc_error, status);
    5568             :         return;
    5569             :     }
    5570             : 
    5571           0 :     if (mpd_isdynamic_data(result)) {
    5572           0 :         mpd_free(result->data);
    5573             :     }
    5574           0 :     result->data = rdata;
    5575           0 :     result->alloc = rsize;
    5576             :     mpd_set_dynamic_data(result);
    5577             : 
    5578             : 
    5579             : finish:
    5580           0 :     mpd_set_flags(result, mpd_sign(a)^mpd_sign(b));
    5581           0 :     result->exp = big->exp + small->exp;
    5582           0 :     result->len = _mpd_real_size(result->data, rsize);
    5583             :     /* resize to smaller cannot fail */
    5584           0 :     mpd_qresize(result, result->len, status);
    5585           0 :     mpd_setdigits(result);
    5586             : }
    5587             : 
    5588             : /* Multiply a and b. */
    5589             : void
    5590           0 : mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b,
    5591             :          const mpd_context_t *ctx, uint32_t *status)
    5592             : {
    5593           0 :     _mpd_qmul(result, a, b, ctx, status);
    5594           0 :     mpd_qfinalize(result, ctx, status);
    5595           0 : }
    5596             : 
    5597             : /* Multiply a and b. Set NaN/Invalid_operation if the result is inexact. */
    5598             : static void
    5599           0 : _mpd_qmul_exact(mpd_t *result, const mpd_t *a, const mpd_t *b,
    5600             :                 const mpd_context_t *ctx, uint32_t *status)
    5601             : {
    5602           0 :     uint32_t workstatus = 0;
    5603             : 
    5604           0 :     mpd_qmul(result, a, b, ctx, &workstatus);
    5605           0 :     *status |= workstatus;
    5606           0 :     if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
    5607           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    5608             :     }
    5609           0 : }
    5610             : 
    5611             : /* Multiply decimal and mpd_ssize_t. */
    5612             : void
    5613           0 : mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b,
    5614             :                const mpd_context_t *ctx, uint32_t *status)
    5615             : {
    5616             :     mpd_context_t maxcontext;
    5617           0 :     MPD_NEW_STATIC(bb,0,0,0,0);
    5618             : 
    5619           0 :     mpd_maxcontext(&maxcontext);
    5620           0 :     mpd_qsset_ssize(&bb, b, &maxcontext, status);
    5621           0 :     mpd_qmul(result, a, &bb, ctx, status);
    5622             :     mpd_del(&bb);
    5623           0 : }
    5624             : 
    5625             : /* Multiply decimal and mpd_uint_t. */
    5626             : void
    5627           0 : mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b,
    5628             :               const mpd_context_t *ctx, uint32_t *status)
    5629             : {
    5630             :     mpd_context_t maxcontext;
    5631           0 :     MPD_NEW_STATIC(bb,0,0,0,0);
    5632             : 
    5633           0 :     mpd_maxcontext(&maxcontext);
    5634           0 :     mpd_qsset_uint(&bb, b, &maxcontext, status);
    5635           0 :     mpd_qmul(result, a, &bb, ctx, status);
    5636             :     mpd_del(&bb);
    5637           0 : }
    5638             : 
    5639             : void
    5640           0 : mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b,
    5641             :              const mpd_context_t *ctx, uint32_t *status)
    5642             : {
    5643           0 :     mpd_qmul_ssize(result, a, b, ctx, status);
    5644           0 : }
    5645             : 
    5646             : void
    5647           0 : mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b,
    5648             :              const mpd_context_t *ctx, uint32_t *status)
    5649             : {
    5650           0 :     mpd_qmul_uint(result, a, b, ctx, status);
    5651           0 : }
    5652             : 
    5653             : #ifdef CONFIG_64
    5654             : void
    5655             : mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b,
    5656             :              const mpd_context_t *ctx, uint32_t *status)
    5657             : {
    5658             :     mpd_qmul_ssize(result, a, b, ctx, status);
    5659             : }
    5660             : 
    5661             : void
    5662             : mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b,
    5663             :              const mpd_context_t *ctx, uint32_t *status)
    5664             : {
    5665             :     mpd_qmul_uint(result, a, b, ctx, status);
    5666             : }
    5667             : #endif
    5668             : 
    5669             : /* Like the minus operator. */
    5670             : void
    5671           0 : mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    5672             :            uint32_t *status)
    5673             : {
    5674           0 :     if (mpd_isspecial(a)) {
    5675           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    5676           0 :             return;
    5677             :         }
    5678             :     }
    5679             : 
    5680           0 :     if (mpd_iszero(a) && ctx->round != MPD_ROUND_FLOOR) {
    5681           0 :         mpd_qcopy_abs(result, a, status);
    5682             :     }
    5683             :     else {
    5684           0 :         mpd_qcopy_negate(result, a, status);
    5685             :     }
    5686             : 
    5687           0 :     mpd_qfinalize(result, ctx, status);
    5688             : }
    5689             : 
    5690             : /* Like the plus operator. */
    5691             : void
    5692           0 : mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    5693             :           uint32_t *status)
    5694             : {
    5695           0 :     if (mpd_isspecial(a)) {
    5696           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    5697           0 :             return;
    5698             :         }
    5699             :     }
    5700             : 
    5701           0 :     if (mpd_iszero(a) && ctx->round != MPD_ROUND_FLOOR) {
    5702           0 :         mpd_qcopy_abs(result, a, status);
    5703             :     }
    5704             :     else {
    5705           0 :         mpd_qcopy(result, a, status);
    5706             :     }
    5707             : 
    5708           0 :     mpd_qfinalize(result, ctx, status);
    5709             : }
    5710             : 
    5711             : /* The largest representable number that is smaller than the operand. */
    5712             : void
    5713           0 : mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    5714             :                 uint32_t *status)
    5715             : {
    5716             :     mpd_context_t workctx;
    5717           0 :     MPD_NEW_CONST(tiny,MPD_POS,mpd_etiny(ctx)-1,1,1,1,1);
    5718             : 
    5719           0 :     if (mpd_isspecial(a)) {
    5720           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    5721             :             return;
    5722             :         }
    5723             : 
    5724             :         assert(mpd_isinfinite(a));
    5725           0 :         if (mpd_isnegative(a)) {
    5726           0 :             mpd_qcopy(result, a, status);
    5727             :             return;
    5728             :         }
    5729             :         else {
    5730             :             mpd_clear_flags(result);
    5731           0 :             mpd_qmaxcoeff(result, ctx, status);
    5732           0 :             if (mpd_isnan(result)) {
    5733             :                 return;
    5734             :             }
    5735           0 :             result->exp = mpd_etop(ctx);
    5736             :             return;
    5737             :         }
    5738             :     }
    5739             : 
    5740           0 :     mpd_workcontext(&workctx, ctx);
    5741           0 :     workctx.round = MPD_ROUND_FLOOR;
    5742             : 
    5743           0 :     if (!mpd_qcopy(result, a, status)) {
    5744             :         return;
    5745             :     }
    5746             : 
    5747           0 :     mpd_qfinalize(result, &workctx, &workctx.status);
    5748           0 :     if (workctx.status&(MPD_Inexact|MPD_Errors)) {
    5749           0 :         *status |= (workctx.status&MPD_Errors);
    5750             :         return;
    5751             :     }
    5752             : 
    5753           0 :     workctx.status = 0;
    5754           0 :     mpd_qsub(result, a, &tiny, &workctx, &workctx.status);
    5755           0 :     *status |= (workctx.status&MPD_Errors);
    5756             : }
    5757             : 
    5758             : /* The smallest representable number that is larger than the operand. */
    5759             : void
    5760           0 : mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    5761             :                uint32_t *status)
    5762             : {
    5763             :     mpd_context_t workctx;
    5764           0 :     MPD_NEW_CONST(tiny,MPD_POS,mpd_etiny(ctx)-1,1,1,1,1);
    5765             : 
    5766           0 :     if (mpd_isspecial(a)) {
    5767           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    5768             :             return;
    5769             :         }
    5770             : 
    5771             :         assert(mpd_isinfinite(a));
    5772           0 :         if (mpd_ispositive(a)) {
    5773           0 :             mpd_qcopy(result, a, status);
    5774             :         }
    5775             :         else {
    5776             :             mpd_clear_flags(result);
    5777           0 :             mpd_qmaxcoeff(result, ctx, status);
    5778           0 :             if (mpd_isnan(result)) {
    5779             :                 return;
    5780             :             }
    5781             :             mpd_set_flags(result, MPD_NEG);
    5782           0 :             result->exp = mpd_etop(ctx);
    5783             :         }
    5784             :         return;
    5785             :     }
    5786             : 
    5787           0 :     mpd_workcontext(&workctx, ctx);
    5788           0 :     workctx.round = MPD_ROUND_CEILING;
    5789             : 
    5790           0 :     if (!mpd_qcopy(result, a, status)) {
    5791             :         return;
    5792             :     }
    5793             : 
    5794           0 :     mpd_qfinalize(result, &workctx, &workctx.status);
    5795           0 :     if (workctx.status & (MPD_Inexact|MPD_Errors)) {
    5796           0 :         *status |= (workctx.status&MPD_Errors);
    5797             :         return;
    5798             :     }
    5799             : 
    5800           0 :     workctx.status = 0;
    5801           0 :     mpd_qadd(result, a, &tiny, &workctx, &workctx.status);
    5802           0 :     *status |= (workctx.status&MPD_Errors);
    5803             : }
    5804             : 
    5805             : /*
    5806             :  * The number closest to the first operand that is in the direction towards
    5807             :  * the second operand.
    5808             :  */
    5809             : void
    5810           0 : mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b,
    5811             :                  const mpd_context_t *ctx, uint32_t *status)
    5812             : {
    5813             :     int c;
    5814             : 
    5815           0 :     if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    5816           0 :         return;
    5817             :     }
    5818             : 
    5819           0 :     c = _mpd_cmp(a, b);
    5820           0 :     if (c == 0) {
    5821           0 :         mpd_qcopy_sign(result, a, b, status);
    5822           0 :         return;
    5823             :     }
    5824             : 
    5825           0 :     if (c < 0) {
    5826           0 :         mpd_qnext_plus(result, a, ctx, status);
    5827             :     }
    5828             :     else {
    5829           0 :         mpd_qnext_minus(result, a, ctx, status);
    5830             :     }
    5831             : 
    5832           0 :     if (mpd_isinfinite(result)) {
    5833           0 :         *status |= (MPD_Overflow|MPD_Rounded|MPD_Inexact);
    5834             :     }
    5835           0 :     else if (mpd_adjexp(result) < ctx->emin) {
    5836           0 :         *status |= (MPD_Underflow|MPD_Subnormal|MPD_Rounded|MPD_Inexact);
    5837           0 :         if (mpd_iszero(result)) {
    5838           0 :             *status |= MPD_Clamped;
    5839             :         }
    5840             :     }
    5841             : }
    5842             : 
    5843             : /*
    5844             :  * Internal function: Integer power with mpd_uint_t exponent. The function
    5845             :  * can fail with MPD_Malloc_error.
    5846             :  *
    5847             :  * The error is equal to the error incurred in k-1 multiplications. Assuming
    5848             :  * the upper bound for the relative error in each operation:
    5849             :  *
    5850             :  *   abs(err) = 5 * 10**-prec
    5851             :  *   result = x**k * (1 + err)**(k-1)
    5852             :  */
    5853             : static inline void
    5854           0 : _mpd_qpow_uint(mpd_t *result, const mpd_t *base, mpd_uint_t exp,
    5855             :                uint8_t resultsign, const mpd_context_t *ctx, uint32_t *status)
    5856             : {
    5857           0 :     uint32_t workstatus = 0;
    5858             :     mpd_uint_t n;
    5859             : 
    5860           0 :     if (exp == 0) {
    5861           0 :         _settriple(result, resultsign, 1, 0); /* GCOV_NOT_REACHED */
    5862             :         return; /* GCOV_NOT_REACHED */
    5863             :     }
    5864             : 
    5865           0 :     if (!mpd_qcopy(result, base, status)) {
    5866             :         return;
    5867             :     }
    5868             : 
    5869           0 :     n = mpd_bits[mpd_bsr(exp)];
    5870           0 :     while (n >>= 1) {
    5871           0 :         mpd_qmul(result, result, result, ctx, &workstatus);
    5872           0 :         if (exp & n) {
    5873           0 :             mpd_qmul(result, result, base, ctx, &workstatus);
    5874             :         }
    5875           0 :         if (mpd_isspecial(result) ||
    5876           0 :             (mpd_iszerocoeff(result) && (workstatus & MPD_Clamped))) {
    5877             :             break;
    5878             :         }
    5879             :     }
    5880             : 
    5881           0 :     *status |= workstatus;
    5882           0 :     mpd_set_sign(result, resultsign);
    5883             : }
    5884             : 
    5885             : /*
    5886             :  * Internal function: Integer power with mpd_t exponent, tbase and texp
    5887             :  * are modified!! Function can fail with MPD_Malloc_error.
    5888             :  *
    5889             :  * The error is equal to the error incurred in k multiplications. Assuming
    5890             :  * the upper bound for the relative error in each operation:
    5891             :  *
    5892             :  *   abs(err) = 5 * 10**-prec
    5893             :  *   result = x**k * (1 + err)**k
    5894             :  */
    5895             : static inline void
    5896           0 : _mpd_qpow_mpd(mpd_t *result, mpd_t *tbase, mpd_t *texp, uint8_t resultsign,
    5897             :               const mpd_context_t *ctx, uint32_t *status)
    5898             : {
    5899           0 :     uint32_t workstatus = 0;
    5900             :     mpd_context_t maxctx;
    5901           0 :     MPD_NEW_CONST(two,0,0,1,1,1,2);
    5902             : 
    5903             : 
    5904           0 :     mpd_maxcontext(&maxctx);
    5905             : 
    5906             :     /* resize to smaller cannot fail */
    5907           0 :     mpd_qcopy(result, &one, status);
    5908             : 
    5909           0 :     while (!mpd_iszero(texp)) {
    5910           0 :         if (mpd_isodd(texp)) {
    5911           0 :             mpd_qmul(result, result, tbase, ctx, &workstatus);
    5912           0 :             *status |= workstatus;
    5913           0 :             if (mpd_isspecial(result) ||
    5914           0 :                 (mpd_iszerocoeff(result) && (workstatus & MPD_Clamped))) {
    5915             :                 break;
    5916             :             }
    5917             :         }
    5918           0 :         mpd_qmul(tbase, tbase, tbase, ctx, &workstatus);
    5919           0 :         mpd_qdivint(texp, texp, &two, &maxctx, &workstatus);
    5920           0 :         if (mpd_isnan(tbase) || mpd_isnan(texp)) {
    5921           0 :             mpd_seterror(result, workstatus&MPD_Errors, status);
    5922           0 :             return;
    5923             :         }
    5924             :     }
    5925           0 :     mpd_set_sign(result, resultsign);
    5926             : }
    5927             : 
    5928             : /*
    5929             :  * The power function for integer exponents. Relative error _before_ the
    5930             :  * final rounding to prec:
    5931             :  *   abs(result - base**exp) < 0.1 * 10**-prec * abs(base**exp)
    5932             :  */
    5933             : static void
    5934           0 : _mpd_qpow_int(mpd_t *result, const mpd_t *base, const mpd_t *exp,
    5935             :               uint8_t resultsign,
    5936             :               const mpd_context_t *ctx, uint32_t *status)
    5937             : {
    5938             :     mpd_context_t workctx;
    5939           0 :     MPD_NEW_STATIC(tbase,0,0,0,0);
    5940           0 :     MPD_NEW_STATIC(texp,0,0,0,0);
    5941             :     mpd_ssize_t n;
    5942             : 
    5943             : 
    5944           0 :     mpd_workcontext(&workctx, ctx);
    5945           0 :     workctx.prec += (exp->digits + exp->exp + 2);
    5946           0 :     workctx.round = MPD_ROUND_HALF_EVEN;
    5947           0 :     workctx.clamp = 0;
    5948           0 :     if (mpd_isnegative(exp)) {
    5949           0 :         workctx.prec += 1;
    5950           0 :         mpd_qdiv(&tbase, &one, base, &workctx, status);
    5951           0 :         if (*status&MPD_Errors) {
    5952           0 :             mpd_setspecial(result, MPD_POS, MPD_NAN);
    5953           0 :             goto finish;
    5954             :         }
    5955             :     }
    5956             :     else {
    5957           0 :         if (!mpd_qcopy(&tbase, base, status)) {
    5958           0 :             mpd_setspecial(result, MPD_POS, MPD_NAN);
    5959           0 :             goto finish;
    5960             :         }
    5961             :     }
    5962             : 
    5963           0 :     n = mpd_qabs_uint(exp, &workctx.status);
    5964           0 :     if (workctx.status&MPD_Invalid_operation) {
    5965           0 :         if (!mpd_qcopy(&texp, exp, status)) {
    5966           0 :             mpd_setspecial(result, MPD_POS, MPD_NAN); /* GCOV_UNLIKELY */
    5967           0 :             goto finish; /* GCOV_UNLIKELY */
    5968             :         }
    5969           0 :         _mpd_qpow_mpd(result, &tbase, &texp, resultsign, &workctx, status);
    5970             :     }
    5971             :     else {
    5972           0 :         _mpd_qpow_uint(result, &tbase, n, resultsign, &workctx, status);
    5973             :     }
    5974             : 
    5975           0 :     if (mpd_isinfinite(result)) {
    5976             :         /* for ROUND_DOWN, ROUND_FLOOR, etc. */
    5977           0 :         _settriple(result, resultsign, 1, MPD_EXP_INF);
    5978             :     }
    5979             : 
    5980             : finish:
    5981             :     mpd_del(&tbase);
    5982             :     mpd_del(&texp);
    5983           0 :     mpd_qfinalize(result, ctx, status);
    5984           0 : }
    5985             : 
    5986             : /* 
    5987             :  * If the exponent is infinite and base equals one, the result is one
    5988             :  * with a coefficient of length prec. Otherwise, result is undefined.
    5989             :  * Return the value of the comparison against one.
    5990             :  */
    5991             : static int
    5992           0 : _qcheck_pow_one_inf(mpd_t *result, const mpd_t *base, uint8_t resultsign,
    5993             :                     const mpd_context_t *ctx, uint32_t *status)
    5994             : {
    5995             :     mpd_ssize_t shift;
    5996             :     int cmp;
    5997             : 
    5998           0 :     if ((cmp = _mpd_cmp(base, &one)) == 0) {
    5999           0 :         shift = ctx->prec-1;
    6000           0 :         mpd_qshiftl(result, &one, shift, status);
    6001           0 :         result->exp = -shift;
    6002           0 :         mpd_set_flags(result, resultsign);
    6003           0 :         *status |= (MPD_Inexact|MPD_Rounded);
    6004             :     }
    6005             : 
    6006           0 :     return cmp;
    6007             : }
    6008             : 
    6009             : /*
    6010             :  * If abs(base) equals one, calculate the correct power of one result.
    6011             :  * Otherwise, result is undefined. Return the value of the comparison
    6012             :  * against 1.
    6013             :  *
    6014             :  * This is an internal function that does not check for specials.
    6015             :  */
    6016             : static int
    6017           0 : _qcheck_pow_one(mpd_t *result, const mpd_t *base, const mpd_t *exp,
    6018             :                 uint8_t resultsign,
    6019             :                 const mpd_context_t *ctx, uint32_t *status)
    6020             : {
    6021           0 :     uint32_t workstatus = 0;
    6022             :     mpd_ssize_t shift;
    6023             :     int cmp;
    6024             : 
    6025           0 :     if ((cmp = _mpd_cmp_abs(base, &one)) == 0) {
    6026           0 :         if (_mpd_isint(exp)) {
    6027           0 :             if (mpd_isnegative(exp)) {
    6028           0 :                 _settriple(result, resultsign, 1, 0);
    6029           0 :                 return 0;
    6030             :             }
    6031             :             /* 1.000**3 = 1.000000000 */
    6032           0 :             mpd_qmul_ssize(result, exp, -base->exp, ctx, &workstatus);
    6033           0 :             if (workstatus&MPD_Errors) {
    6034           0 :                 *status |= (workstatus&MPD_Errors);
    6035           0 :                 return 0;
    6036             :             }
    6037             :             /* digits-1 after exponentiation */
    6038           0 :             shift = mpd_qget_ssize(result, &workstatus);
    6039             :             /* shift is MPD_SSIZE_MAX if result is too large */
    6040           0 :             if (shift > ctx->prec-1) {
    6041           0 :                 shift = ctx->prec-1;
    6042           0 :                 *status |= MPD_Rounded;
    6043             :             }
    6044             :         }
    6045           0 :         else if (mpd_ispositive(base)) {
    6046           0 :             shift = ctx->prec-1;
    6047           0 :             *status |= (MPD_Inexact|MPD_Rounded);
    6048             :         }
    6049             :         else {
    6050           0 :             return -2; /* GCOV_NOT_REACHED */
    6051             :         }
    6052           0 :         if (!mpd_qshiftl(result, &one, shift, status)) {
    6053           0 :             return 0;
    6054             :         }
    6055           0 :         result->exp = -shift;
    6056           0 :         mpd_set_flags(result, resultsign);
    6057             :     }
    6058             : 
    6059           0 :     return cmp;
    6060             : }
    6061             : 
    6062             : /*
    6063             :  * Detect certain over/underflow of x**y.
    6064             :  * ACL2 proof: pow-bounds.lisp.
    6065             :  *
    6066             :  *   Symbols:
    6067             :  *
    6068             :  *     e: EXP_INF or EXP_CLAMP
    6069             :  *     x: base
    6070             :  *     y: exponent
    6071             :  *
    6072             :  *     omega(e) = log10(abs(e))
    6073             :  *     zeta(x)  = log10(abs(log10(x)))
    6074             :  *     theta(y) = log10(abs(y))
    6075             :  *
    6076             :  *   Upper and lower bounds:
    6077             :  *
    6078             :  *     ub_omega(e) = ceil(log10(abs(e)))
    6079             :  *     lb_theta(y) = floor(log10(abs(y)))
    6080             :  *
    6081             :  *                  | floor(log10(floor(abs(log10(x))))) if x < 1/10 or x >= 10
    6082             :  *     lb_zeta(x) = | floor(log10(abs(x-1)/10)) if 1/10 <= x < 1
    6083             :  *                  | floor(log10(abs((x-1)/100))) if 1 < x < 10
    6084             :  *
    6085             :  *   ub_omega(e) and lb_theta(y) are obviously upper and lower bounds
    6086             :  *   for omega(e) and theta(y).
    6087             :  *
    6088             :  *   lb_zeta is a lower bound for zeta(x):
    6089             :  *
    6090             :  *     x < 1/10 or x >= 10:
    6091             :  *
    6092             :  *       abs(log10(x)) >= 1, so the outer log10 is well defined. Since log10
    6093             :  *       is strictly increasing, the end result is a lower bound.
    6094             :  *
    6095             :  *     1/10 <= x < 1:
    6096             :  *
    6097             :  *       We use: log10(x) <= (x-1)/log(10)
    6098             :  *               abs(log10(x)) >= abs(x-1)/log(10)
    6099             :  *               abs(log10(x)) >= abs(x-1)/10
    6100             :  *
    6101             :  *     1 < x < 10:
    6102             :  *
    6103             :  *       We use: (x-1)/(x*log(10)) < log10(x)
    6104             :  *               abs((x-1)/100) < abs(log10(x))
    6105             :  *
    6106             :  *       XXX: abs((x-1)/10) would work, need ACL2 proof.
    6107             :  *
    6108             :  *
    6109             :  *   Let (0 < x < 1 and y < 0) or (x > 1 and y > 0).                  (H1)
    6110             :  *   Let ub_omega(exp_inf) < lb_zeta(x) + lb_theta(y)                 (H2)
    6111             :  *
    6112             :  *   Then:
    6113             :  *       log10(abs(exp_inf)) < log10(abs(log10(x))) + log10(abs(y)).   (1)
    6114             :  *                   exp_inf < log10(x) * y                            (2)
    6115             :  *               10**exp_inf < x**y                                    (3)
    6116             :  *
    6117             :  *   Let (0 < x < 1 and y > 0) or (x > 1 and y < 0).                  (H3)
    6118             :  *   Let ub_omega(exp_clamp) < lb_zeta(x) + lb_theta(y)               (H4)
    6119             :  *
    6120             :  *   Then:
    6121             :  *     log10(abs(exp_clamp)) < log10(abs(log10(x))) + log10(abs(y)).   (4)
    6122             :  *              log10(x) * y < exp_clamp                               (5)
    6123             :  *                      x**y < 10**exp_clamp                           (6)
    6124             :  *
    6125             :  */
    6126             : static mpd_ssize_t
    6127           0 : _lower_bound_zeta(const mpd_t *x, uint32_t *status)
    6128             : {
    6129             :     mpd_context_t maxctx;
    6130           0 :     MPD_NEW_STATIC(scratch,0,0,0,0);
    6131             :     mpd_ssize_t t, u;
    6132             : 
    6133           0 :     t = mpd_adjexp(x);
    6134           0 :     if (t > 0) {
    6135             :         /* x >= 10 -> floor(log10(floor(abs(log10(x))))) */
    6136           0 :         return mpd_exp_digits(t) - 1;
    6137             :     }
    6138           0 :     else if (t < -1) {
    6139             :         /* x < 1/10 -> floor(log10(floor(abs(log10(x))))) */
    6140           0 :         return mpd_exp_digits(t+1) - 1;
    6141             :     }
    6142             :     else {
    6143           0 :         mpd_maxcontext(&maxctx);
    6144           0 :         mpd_qsub(&scratch, x, &one, &maxctx, status);
    6145           0 :         if (mpd_isspecial(&scratch)) {
    6146             :             mpd_del(&scratch);
    6147           0 :             return MPD_SSIZE_MAX;
    6148             :         }
    6149           0 :         u = mpd_adjexp(&scratch);
    6150             :         mpd_del(&scratch);
    6151             : 
    6152             :         /* t == -1, 1/10 <= x < 1 -> floor(log10(abs(x-1)/10))
    6153             :          * t == 0,  1 < x < 10    -> floor(log10(abs(x-1)/100)) */
    6154           0 :         return (t == 0) ? u-2 : u-1;
    6155             :     }
    6156             : }
    6157             : 
    6158             : /*
    6159             :  * Detect cases of certain overflow/underflow in the power function.
    6160             :  * Assumptions: x != 1, y != 0. The proof above is for positive x.
    6161             :  * If x is negative and y is an odd integer, x**y == -(abs(x)**y),
    6162             :  * so the analysis does not change.
    6163             :  */
    6164             : static int
    6165           0 : _qcheck_pow_bounds(mpd_t *result, const mpd_t *x, const mpd_t *y,
    6166             :                    uint8_t resultsign,
    6167             :                    const mpd_context_t *ctx, uint32_t *status)
    6168             : {
    6169           0 :     MPD_NEW_SHARED(abs_x, x);
    6170             :     mpd_ssize_t ub_omega, lb_zeta, lb_theta;
    6171             :     uint8_t sign;
    6172             : 
    6173             :     mpd_set_positive(&abs_x);
    6174             : 
    6175           0 :     lb_theta = mpd_adjexp(y);
    6176           0 :     lb_zeta = _lower_bound_zeta(&abs_x, status);
    6177           0 :     if (lb_zeta == MPD_SSIZE_MAX) {
    6178           0 :         mpd_seterror(result, MPD_Malloc_error, status);
    6179           0 :         return 1;
    6180             :     }
    6181             : 
    6182           0 :     sign = (mpd_adjexp(&abs_x) < 0) ^ mpd_sign(y);
    6183           0 :     if (sign == 0) {
    6184             :         /* (0 < |x| < 1 and y < 0) or (|x| > 1 and y > 0) */
    6185           0 :         ub_omega = mpd_exp_digits(ctx->emax);
    6186           0 :         if (ub_omega < lb_zeta + lb_theta) {
    6187           0 :             _settriple(result, resultsign, 1, MPD_EXP_INF);
    6188           0 :             mpd_qfinalize(result, ctx, status);
    6189           0 :             return 1;
    6190             :         }
    6191             :     }
    6192             :     else {
    6193             :         /* (0 < |x| < 1 and y > 0) or (|x| > 1 and y < 0). */
    6194           0 :         ub_omega = mpd_exp_digits(mpd_etiny(ctx));
    6195           0 :         if (ub_omega < lb_zeta + lb_theta) {
    6196           0 :             _settriple(result, resultsign, 1, mpd_etiny(ctx)-1);
    6197           0 :             mpd_qfinalize(result, ctx, status);
    6198           0 :             return 1;
    6199             :         }
    6200             :     }
    6201             : 
    6202           0 :     return 0;
    6203             : }
    6204             : 
    6205             : /*
    6206             :  * TODO: Implement algorithm for computing exact powers from decimal.py.
    6207             :  * In order to prevent infinite loops, this has to be called before
    6208             :  * using Ziv's strategy for correct rounding.
    6209             :  */
    6210             : /*
    6211             : static int
    6212             : _mpd_qpow_exact(mpd_t *result, const mpd_t *base, const mpd_t *exp,
    6213             :                 const mpd_context_t *ctx, uint32_t *status)
    6214             : {
    6215             :     return 0;
    6216             : }
    6217             : */
    6218             : 
    6219             : /*
    6220             :  * The power function for real exponents.
    6221             :  *   Relative error: abs(result - e**y) < e**y * 1/5 * 10**(-prec - 1)
    6222             :  */
    6223             : static void
    6224           0 : _mpd_qpow_real(mpd_t *result, const mpd_t *base, const mpd_t *exp,
    6225             :                const mpd_context_t *ctx, uint32_t *status)
    6226             : {
    6227             :     mpd_context_t workctx;
    6228           0 :     MPD_NEW_STATIC(texp,0,0,0,0);
    6229             : 
    6230           0 :     if (!mpd_qcopy(&texp, exp, status)) {
    6231           0 :         mpd_seterror(result, MPD_Malloc_error, status);
    6232           0 :         return;
    6233             :     }
    6234             : 
    6235           0 :     mpd_maxcontext(&workctx);
    6236           0 :     workctx.prec = (base->digits > ctx->prec) ? base->digits : ctx->prec;
    6237           0 :     workctx.prec += (4 + MPD_EXPDIGITS);
    6238           0 :     workctx.round = MPD_ROUND_HALF_EVEN;
    6239           0 :     workctx.allcr = ctx->allcr;
    6240             : 
    6241             :     /*
    6242             :      * extra := MPD_EXPDIGITS = MPD_EXP_MAX_T
    6243             :      * wp := prec + 4 + extra
    6244             :      * abs(err) < 5 * 10**-wp
    6245             :      * y := log(base) * exp
    6246             :      * Calculate:
    6247             :      *   1)   e**(y * (1 + err)**2) * (1 + err)
    6248             :      *      = e**y * e**(y * (2*err + err**2)) * (1 + err)
    6249             :      *        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    6250             :      * Relative error of the underlined term:
    6251             :      *   2) abs(e**(y * (2*err + err**2)) - 1)
    6252             :      * Case abs(y) >= 10**extra:
    6253             :      *   3) adjexp(y)+1 > log10(abs(y)) >= extra
    6254             :      *   This triggers the Overflow/Underflow shortcut in _mpd_qexp(),
    6255             :      *   so no further analysis is necessary.
    6256             :      * Case abs(y) < 10**extra:
    6257             :      *   4) abs(y * (2*err + err**2)) < 1/5 * 10**(-prec - 2)
    6258             :      *   Use (see _mpd_qexp):
    6259             :      *     5) abs(x) <= 9/10 * 10**-p ==> abs(e**x - 1) < 10**-p
    6260             :      *   With 2), 4) and 5):
    6261             :      *     6) abs(e**(y * (2*err + err**2)) - 1) < 10**(-prec - 2)
    6262             :      *   The complete relative error of 1) is:
    6263             :      *     7) abs(result - e**y) < e**y * 1/5 * 10**(-prec - 1)
    6264             :      */
    6265           0 :     mpd_qln(result, base, &workctx, &workctx.status);
    6266           0 :     mpd_qmul(result, result, &texp, &workctx, &workctx.status);
    6267           0 :     mpd_qexp(result, result, &workctx, status);
    6268             : 
    6269             :     mpd_del(&texp);
    6270           0 :     *status |= (workctx.status&MPD_Errors);
    6271           0 :     *status |= (MPD_Inexact|MPD_Rounded);
    6272             : }
    6273             : 
    6274             : /* The power function: base**exp */
    6275             : void
    6276           0 : mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp,
    6277             :          const mpd_context_t *ctx, uint32_t *status)
    6278             : {
    6279           0 :     uint8_t resultsign = 0;
    6280           0 :     int intexp = 0;
    6281             :     int cmp;
    6282             : 
    6283           0 :     if (mpd_isspecial(base) || mpd_isspecial(exp)) {
    6284           0 :         if (mpd_qcheck_nans(result, base, exp, ctx, status)) {
    6285           0 :             return;
    6286             :         }
    6287             :     }
    6288           0 :     if (mpd_isinteger(exp)) {
    6289           0 :         intexp = 1;
    6290           0 :         resultsign = mpd_isnegative(base) && mpd_isodd(exp);
    6291             :     }
    6292             : 
    6293           0 :     if (mpd_iszero(base)) {
    6294           0 :         if (mpd_iszero(exp)) {
    6295           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    6296             :         }
    6297           0 :         else if (mpd_isnegative(exp)) {
    6298           0 :             mpd_setspecial(result, resultsign, MPD_INF);
    6299             :         }
    6300             :         else {
    6301           0 :             _settriple(result, resultsign, 0, 0);
    6302             :         }
    6303           0 :         return;
    6304             :     }
    6305           0 :     if (mpd_isnegative(base)) {
    6306           0 :         if (!intexp || mpd_isinfinite(exp)) {
    6307           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    6308           0 :             return;
    6309             :         }
    6310             :     }
    6311           0 :     if (mpd_isinfinite(exp)) {
    6312             :         /* power of one */
    6313           0 :         cmp = _qcheck_pow_one_inf(result, base, resultsign, ctx, status);
    6314           0 :         if (cmp == 0) {
    6315           0 :             return;
    6316             :         }
    6317             :         else {
    6318           0 :             cmp *= mpd_arith_sign(exp);
    6319           0 :             if (cmp < 0) {
    6320           0 :                 _settriple(result, resultsign, 0, 0);
    6321             :             }
    6322             :             else {
    6323           0 :                 mpd_setspecial(result, resultsign, MPD_INF);
    6324             :             }
    6325             :         }
    6326           0 :         return;
    6327             :     }
    6328           0 :     if (mpd_isinfinite(base)) {
    6329           0 :         if (mpd_iszero(exp)) {
    6330           0 :             _settriple(result, resultsign, 1, 0);
    6331             :         }
    6332           0 :         else if (mpd_isnegative(exp)) {
    6333           0 :             _settriple(result, resultsign, 0, 0);
    6334             :         }
    6335             :         else {
    6336           0 :             mpd_setspecial(result, resultsign, MPD_INF);
    6337             :         }
    6338           0 :         return;
    6339             :     }
    6340           0 :     if (mpd_iszero(exp)) {
    6341           0 :         _settriple(result, resultsign, 1, 0);
    6342           0 :         return;
    6343             :     }
    6344           0 :     if (_qcheck_pow_one(result, base, exp, resultsign, ctx, status) == 0) {
    6345           0 :         return;
    6346             :     }
    6347           0 :     if (_qcheck_pow_bounds(result, base, exp, resultsign, ctx, status)) {
    6348           0 :         return;
    6349             :     }
    6350             : 
    6351           0 :     if (intexp) {
    6352           0 :         _mpd_qpow_int(result, base, exp, resultsign, ctx, status);
    6353             :     }
    6354             :     else {
    6355           0 :         _mpd_qpow_real(result, base, exp, ctx, status);
    6356           0 :         if (!mpd_isspecial(result) && _mpd_cmp(result, &one) == 0) {
    6357           0 :             mpd_ssize_t shift = ctx->prec-1;
    6358           0 :             mpd_qshiftl(result, &one, shift, status);
    6359           0 :             result->exp = -shift;
    6360             :         }
    6361           0 :         if (mpd_isinfinite(result)) {
    6362             :             /* for ROUND_DOWN, ROUND_FLOOR, etc. */
    6363           0 :             _settriple(result, MPD_POS, 1, MPD_EXP_INF);
    6364             :         }
    6365           0 :         mpd_qfinalize(result, ctx, status);
    6366             :     }
    6367             : }
    6368             : 
    6369             : /*
    6370             :  * Internal function: Integer powmod with mpd_uint_t exponent, base is modified!
    6371             :  * Function can fail with MPD_Malloc_error.
    6372             :  */
    6373             : static inline void
    6374           0 : _mpd_qpowmod_uint(mpd_t *result, mpd_t *base, mpd_uint_t exp,
    6375             :                   const mpd_t *mod, uint32_t *status)
    6376             : {
    6377             :     mpd_context_t maxcontext;
    6378             : 
    6379           0 :     mpd_maxcontext(&maxcontext);
    6380             : 
    6381             :     /* resize to smaller cannot fail */
    6382           0 :     mpd_qcopy(result, &one, status);
    6383             : 
    6384           0 :     while (exp > 0) {
    6385           0 :         if (exp & 1) {
    6386           0 :             _mpd_qmul_exact(result, result, base, &maxcontext, status);
    6387           0 :             mpd_qrem(result, result, mod, &maxcontext, status);
    6388             :         }
    6389           0 :         _mpd_qmul_exact(base, base, base, &maxcontext, status);
    6390           0 :         mpd_qrem(base, base, mod, &maxcontext, status);
    6391           0 :         exp >>= 1;
    6392             :     }
    6393           0 : }
    6394             : 
    6395             : /* The powmod function: (base**exp) % mod */
    6396             : void
    6397           0 : mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp,
    6398             :             const mpd_t *mod,
    6399             :             const mpd_context_t *ctx, uint32_t *status)
    6400             : {
    6401             :     mpd_context_t maxcontext;
    6402           0 :     MPD_NEW_STATIC(tbase,0,0,0,0);
    6403           0 :     MPD_NEW_STATIC(texp,0,0,0,0);
    6404           0 :     MPD_NEW_STATIC(tmod,0,0,0,0);
    6405           0 :     MPD_NEW_STATIC(tmp,0,0,0,0);
    6406           0 :     MPD_NEW_CONST(two,0,0,1,1,1,2);
    6407             :     mpd_ssize_t tbase_exp, texp_exp;
    6408             :     mpd_ssize_t i;
    6409             :     mpd_t t;
    6410             :     mpd_uint_t r;
    6411             :     uint8_t sign;
    6412             : 
    6413             : 
    6414           0 :     if (mpd_isspecial(base) || mpd_isspecial(exp) || mpd_isspecial(mod)) {
    6415           0 :         if (mpd_qcheck_3nans(result, base, exp, mod, ctx, status)) {
    6416             :             return;
    6417             :         }
    6418           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6419             :         return;
    6420             :     }
    6421             : 
    6422             : 
    6423           0 :     if (!_mpd_isint(base) || !_mpd_isint(exp) || !_mpd_isint(mod)) {
    6424           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6425             :         return;
    6426             :     }
    6427           0 :     if (mpd_iszerocoeff(mod)) {
    6428           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6429             :         return;
    6430             :     }
    6431           0 :     if (mod->digits+mod->exp > ctx->prec) {
    6432           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6433             :         return;
    6434             :     }
    6435             : 
    6436           0 :     sign = (mpd_isnegative(base)) && (mpd_isodd(exp));
    6437           0 :     if (mpd_iszerocoeff(exp)) {
    6438           0 :         if (mpd_iszerocoeff(base)) {
    6439           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    6440             :             return;
    6441             :         }
    6442           0 :         r = (_mpd_cmp_abs(mod, &one)==0) ? 0 : 1;
    6443           0 :         _settriple(result, sign, r, 0);
    6444             :         return;
    6445             :     }
    6446           0 :     if (mpd_isnegative(exp)) {
    6447           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6448             :         return;
    6449             :     }
    6450           0 :     if (mpd_iszerocoeff(base)) {
    6451           0 :         _settriple(result, sign, 0, 0);
    6452             :         return;
    6453             :     }
    6454             : 
    6455           0 :     mpd_maxcontext(&maxcontext);
    6456             : 
    6457           0 :     mpd_qrescale(&tmod, mod, 0, &maxcontext, &maxcontext.status);
    6458           0 :     if (maxcontext.status&MPD_Errors) {
    6459           0 :         mpd_seterror(result, maxcontext.status&MPD_Errors, status);
    6460           0 :         goto out;
    6461             :     }
    6462           0 :     maxcontext.status = 0;
    6463             :     mpd_set_positive(&tmod);
    6464             : 
    6465           0 :     mpd_qround_to_int(&tbase, base, &maxcontext, status);
    6466             :     mpd_set_positive(&tbase);
    6467           0 :     tbase_exp = tbase.exp;
    6468           0 :     tbase.exp = 0;
    6469             : 
    6470           0 :     mpd_qround_to_int(&texp, exp, &maxcontext, status);
    6471           0 :     texp_exp = texp.exp;
    6472           0 :     texp.exp = 0;
    6473             : 
    6474             :     /* base = (base.int % modulo * pow(10, base.exp, modulo)) % modulo */
    6475           0 :     mpd_qrem(&tbase, &tbase, &tmod, &maxcontext, status);
    6476           0 :     mpd_qshiftl(result, &one, tbase_exp, status);
    6477           0 :     mpd_qrem(result, result, &tmod, &maxcontext, status);
    6478           0 :     _mpd_qmul_exact(&tbase, &tbase, result, &maxcontext, status);
    6479           0 :     mpd_qrem(&tbase, &tbase, &tmod, &maxcontext, status);
    6480           0 :     if (mpd_isspecial(&tbase) ||
    6481           0 :         mpd_isspecial(&texp) ||
    6482           0 :         mpd_isspecial(&tmod)) {
    6483             :         goto mpd_errors;
    6484             :     }
    6485             : 
    6486           0 :     for (i = 0; i < texp_exp; i++) {
    6487           0 :         _mpd_qpowmod_uint(&tmp, &tbase, 10, &tmod, status);
    6488           0 :         t = tmp;
    6489           0 :         tmp = tbase;
    6490           0 :         tbase = t;
    6491             :     }
    6492           0 :     if (mpd_isspecial(&tbase)) {
    6493           0 :         goto mpd_errors; /* GCOV_UNLIKELY */
    6494             :     }
    6495             : 
    6496             :     /* resize to smaller cannot fail */
    6497           0 :     mpd_qcopy(result, &one, status);
    6498           0 :     while (mpd_isfinite(&texp) && !mpd_iszero(&texp)) {
    6499           0 :         if (mpd_isodd(&texp)) {
    6500           0 :             _mpd_qmul_exact(result, result, &tbase, &maxcontext, status);
    6501           0 :             mpd_qrem(result, result, &tmod, &maxcontext, status);
    6502             :         }
    6503           0 :         _mpd_qmul_exact(&tbase, &tbase, &tbase, &maxcontext, status);
    6504           0 :         mpd_qrem(&tbase, &tbase, &tmod, &maxcontext, status);
    6505           0 :         mpd_qdivint(&texp, &texp, &two, &maxcontext, status);
    6506             :     }
    6507           0 :     if (mpd_isspecial(&texp) || mpd_isspecial(&tbase) ||
    6508           0 :         mpd_isspecial(&tmod) || mpd_isspecial(result)) {
    6509             :         /* MPD_Malloc_error */
    6510             :         goto mpd_errors;
    6511             :     }
    6512             :     else {
    6513           0 :         mpd_set_sign(result, sign);
    6514             :     }
    6515             : 
    6516             : out:
    6517             :     mpd_del(&tbase);
    6518             :     mpd_del(&texp);
    6519             :     mpd_del(&tmod);
    6520             :     mpd_del(&tmp);
    6521             :     return;
    6522             : 
    6523             : mpd_errors:
    6524           0 :     mpd_setspecial(result, MPD_POS, MPD_NAN);
    6525           0 :     goto out;
    6526             : }
    6527             : 
    6528             : void
    6529           0 : mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b,
    6530             :               const mpd_context_t *ctx, uint32_t *status)
    6531             : {
    6532           0 :     uint32_t workstatus = 0;
    6533           0 :     mpd_ssize_t b_exp = b->exp;
    6534             :     mpd_ssize_t expdiff, shift;
    6535             :     mpd_uint_t rnd;
    6536             : 
    6537           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    6538           0 :         if (mpd_qcheck_nans(result, a, b, ctx, status)) {
    6539           0 :             return;
    6540             :         }
    6541           0 :         if (mpd_isinfinite(a) && mpd_isinfinite(b)) {
    6542           0 :             mpd_qcopy(result, a, status);
    6543           0 :             return;
    6544             :         }
    6545           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6546           0 :         return;
    6547             :     }
    6548             : 
    6549           0 :     if (b->exp > ctx->emax || b->exp < mpd_etiny(ctx)) {
    6550           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6551           0 :         return;
    6552             :     }
    6553             : 
    6554           0 :     if (mpd_iszero(a)) {
    6555           0 :         _settriple(result, mpd_sign(a), 0, b->exp);
    6556           0 :         mpd_qfinalize(result, ctx, status);
    6557           0 :         return;
    6558             :     }
    6559             : 
    6560             : 
    6561           0 :     expdiff = a->exp - b->exp;
    6562           0 :     if (a->digits + expdiff > ctx->prec) {
    6563           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6564           0 :         return;
    6565             :     }
    6566             : 
    6567           0 :     if (expdiff >= 0) {
    6568           0 :         shift = expdiff;
    6569           0 :         if (!mpd_qshiftl(result, a, shift, status)) {
    6570           0 :             return;
    6571             :         }
    6572           0 :         result->exp = b_exp;
    6573             :     }
    6574             :     else {
    6575             :         /* At this point expdiff < 0 and a->digits+expdiff <= prec,
    6576             :          * so the shift before an increment will fit in prec. */
    6577           0 :         shift = -expdiff;
    6578           0 :         rnd = mpd_qshiftr(result, a, shift, status);
    6579           0 :         if (rnd == MPD_UINT_MAX) {
    6580           0 :             return;
    6581             :         }
    6582           0 :         result->exp = b_exp;
    6583           0 :         if (!_mpd_apply_round_fit(result, rnd, ctx, status)) {
    6584           0 :             return;
    6585             :         }
    6586           0 :         workstatus |= MPD_Rounded;
    6587           0 :         if (rnd) {
    6588           0 :             workstatus |= MPD_Inexact;
    6589             :         }
    6590             :     }
    6591             : 
    6592           0 :     if (mpd_adjexp(result) > ctx->emax ||
    6593           0 :         mpd_adjexp(result) < mpd_etiny(ctx)) {
    6594           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6595           0 :         return;
    6596             :     }
    6597             : 
    6598           0 :     *status |= workstatus;
    6599           0 :     mpd_qfinalize(result, ctx, status);
    6600             : }
    6601             : 
    6602             : void
    6603           0 : mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    6604             :             uint32_t *status)
    6605             : {
    6606             :     mpd_ssize_t shift, maxexp, maxshift;
    6607           0 :     uint8_t sign_a = mpd_sign(a);
    6608             : 
    6609           0 :     if (mpd_isspecial(a)) {
    6610           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    6611           0 :             return;
    6612             :         }
    6613           0 :         mpd_qcopy(result, a, status);
    6614           0 :         return;
    6615             :     }
    6616             : 
    6617           0 :     if (!mpd_qcopy(result, a, status)) {
    6618           0 :         return;
    6619             :     }
    6620           0 :     mpd_qfinalize(result, ctx, status);
    6621           0 :     if (mpd_isspecial(result)) {
    6622           0 :         return;
    6623             :     }
    6624           0 :     if (mpd_iszero(result)) {
    6625           0 :         _settriple(result, sign_a, 0, 0);
    6626           0 :         return;
    6627             :     }
    6628             : 
    6629           0 :     shift = mpd_trail_zeros(result);
    6630           0 :     maxexp = (ctx->clamp) ? mpd_etop(ctx) : ctx->emax;
    6631             :     /* After the finalizing above result->exp <= maxexp. */
    6632           0 :     maxshift = maxexp - result->exp;
    6633           0 :     shift = (shift > maxshift) ? maxshift : shift;
    6634             : 
    6635           0 :     mpd_qshiftr_inplace(result, shift);
    6636           0 :     result->exp += shift;
    6637             : }
    6638             : 
    6639             : void
    6640           0 : mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx,
    6641             :          uint32_t *status)
    6642             : {
    6643           0 :     MPD_NEW_STATIC(q,0,0,0,0);
    6644             : 
    6645           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    6646           0 :         if (mpd_qcheck_nans(r, a, b, ctx, status)) {
    6647             :             return;
    6648             :         }
    6649           0 :         if (mpd_isinfinite(a)) {
    6650           0 :             mpd_seterror(r, MPD_Invalid_operation, status);
    6651             :             return;
    6652             :         }
    6653           0 :         if (mpd_isinfinite(b)) {
    6654           0 :             mpd_qcopy(r, a, status);
    6655           0 :             mpd_qfinalize(r, ctx, status);
    6656             :             return;
    6657             :         }
    6658             :         /* debug */
    6659           0 :         abort(); /* GCOV_NOT_REACHED */
    6660             :     }
    6661           0 :     if (mpd_iszerocoeff(b)) {
    6662           0 :         if (mpd_iszerocoeff(a)) {
    6663           0 :             mpd_seterror(r, MPD_Division_undefined, status);
    6664             :         }
    6665             :         else {
    6666           0 :             mpd_seterror(r, MPD_Invalid_operation, status);
    6667             :         }
    6668             :         return;
    6669             :     }
    6670             : 
    6671           0 :     _mpd_qdivmod(&q, r, a, b, ctx, status);
    6672             :     mpd_del(&q);
    6673           0 :     mpd_qfinalize(r, ctx, status);
    6674             : }
    6675             : 
    6676             : void
    6677           0 : mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b,
    6678             :               const mpd_context_t *ctx, uint32_t *status)
    6679             : {
    6680             :     mpd_context_t workctx;
    6681           0 :     MPD_NEW_STATIC(btmp,0,0,0,0);
    6682           0 :     MPD_NEW_STATIC(q,0,0,0,0);
    6683             :     mpd_ssize_t expdiff, qdigits;
    6684             :     int cmp, isodd, allnine;
    6685             : 
    6686           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    6687           0 :         if (mpd_qcheck_nans(r, a, b, ctx, status)) {
    6688             :             return;
    6689             :         }
    6690           0 :         if (mpd_isinfinite(a)) {
    6691           0 :             mpd_seterror(r, MPD_Invalid_operation, status);
    6692             :             return;
    6693             :         }
    6694           0 :         if (mpd_isinfinite(b)) {
    6695           0 :             mpd_qcopy(r, a, status);
    6696           0 :             mpd_qfinalize(r, ctx, status);
    6697             :             return;
    6698             :         }
    6699             :         /* debug */
    6700           0 :         abort(); /* GCOV_NOT_REACHED */
    6701             :     }
    6702           0 :     if (mpd_iszerocoeff(b)) {
    6703           0 :         if (mpd_iszerocoeff(a)) {
    6704           0 :             mpd_seterror(r,  MPD_Division_undefined, status);
    6705             :         }
    6706             :         else {
    6707           0 :             mpd_seterror(r,  MPD_Invalid_operation, status);
    6708             :         }
    6709             :         return;
    6710             :     }
    6711             : 
    6712           0 :     if (r == b) {
    6713           0 :         if (!mpd_qcopy(&btmp, b, status)) {
    6714           0 :             mpd_seterror(r, MPD_Malloc_error, status);
    6715             :             return;
    6716             :         }
    6717           0 :         b = &btmp;
    6718             :     }
    6719             : 
    6720           0 :     _mpd_qdivmod(&q, r, a, b, ctx, status);
    6721           0 :     if (mpd_isnan(&q) || mpd_isnan(r)) {
    6722             :         goto finish;
    6723             :     }
    6724           0 :     if (mpd_iszerocoeff(r)) {
    6725           0 :         goto finish;
    6726             :     }
    6727             : 
    6728           0 :     expdiff = mpd_adjexp(b) - mpd_adjexp(r);
    6729           0 :     if (-1 <= expdiff && expdiff <= 1) {
    6730             : 
    6731           0 :         allnine = mpd_coeff_isallnine(&q);
    6732           0 :         qdigits = q.digits;
    6733           0 :         isodd = mpd_isodd(&q);
    6734             : 
    6735           0 :         mpd_maxcontext(&workctx);
    6736           0 :         if (mpd_sign(a) == mpd_sign(b)) {
    6737             :             /* sign(r) == sign(b) */
    6738           0 :             _mpd_qsub(&q, r, b, &workctx, &workctx.status);
    6739             :         }
    6740             :         else {
    6741             :             /* sign(r) != sign(b) */
    6742           0 :             _mpd_qadd(&q, r, b, &workctx, &workctx.status);
    6743             :         }
    6744             : 
    6745           0 :         if (workctx.status&MPD_Errors) {
    6746           0 :             mpd_seterror(r, workctx.status&MPD_Errors, status);
    6747           0 :             goto finish;
    6748             :         }
    6749             : 
    6750           0 :         cmp = _mpd_cmp_abs(&q, r);
    6751           0 :         if (cmp < 0 || (cmp == 0 && isodd)) {
    6752             :             /* abs(r) > abs(b)/2 or abs(r) == abs(b)/2 and isodd(quotient) */
    6753           0 :             if (allnine && qdigits == ctx->prec) {
    6754             :                 /* abs(quotient) + 1 == 10**prec */
    6755           0 :                 mpd_seterror(r, MPD_Division_impossible, status);
    6756           0 :                 goto finish;
    6757             :             }
    6758           0 :             mpd_qcopy(r, &q, status);
    6759             :         }
    6760             :     }
    6761             : 
    6762             : 
    6763             : finish:
    6764             :     mpd_del(&btmp);
    6765             :     mpd_del(&q);
    6766           0 :     mpd_qfinalize(r, ctx, status);
    6767             : }
    6768             : 
    6769             : static void
    6770           0 : _mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,
    6771             :               const mpd_context_t *ctx, uint32_t *status)
    6772             : {
    6773             :     mpd_ssize_t expdiff, shift;
    6774             :     mpd_uint_t rnd;
    6775             : 
    6776           0 :     if (mpd_isspecial(a)) {
    6777           0 :         mpd_qcopy(result, a, status);
    6778           0 :         return;
    6779             :     }
    6780             : 
    6781           0 :     if (mpd_iszero(a)) {
    6782           0 :         _settriple(result, mpd_sign(a), 0, exp);
    6783           0 :         return;
    6784             :     }
    6785             : 
    6786           0 :     expdiff = a->exp - exp;
    6787           0 :     if (expdiff >= 0) {
    6788           0 :         shift = expdiff;
    6789           0 :         if (a->digits + shift > MPD_MAX_PREC+1) {
    6790           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    6791           0 :             return;
    6792             :         }
    6793           0 :         if (!mpd_qshiftl(result, a, shift, status)) {
    6794           0 :             return;
    6795             :         }
    6796           0 :         result->exp = exp;
    6797             :     }
    6798             :     else {
    6799           0 :         shift = -expdiff;
    6800           0 :         rnd = mpd_qshiftr(result, a, shift, status);
    6801           0 :         if (rnd == MPD_UINT_MAX) {
    6802           0 :             return;
    6803             :         }
    6804           0 :         result->exp = exp;
    6805           0 :         _mpd_apply_round_excess(result, rnd, ctx, status);
    6806           0 :         *status |= MPD_Rounded;
    6807           0 :         if (rnd) {
    6808           0 :             *status |= MPD_Inexact;
    6809             :         }
    6810             :     }
    6811             : 
    6812           0 :     if (mpd_issubnormal(result, ctx)) {
    6813           0 :         *status |= MPD_Subnormal;
    6814             :     }
    6815             : }
    6816             : 
    6817             : /*
    6818             :  * Rescale a number so that it has exponent 'exp'. Does not regard context
    6819             :  * precision, emax, emin, but uses the rounding mode. Special numbers are
    6820             :  * quietly copied. Restrictions:
    6821             :  *
    6822             :  *     MPD_MIN_ETINY <= exp <= MPD_MAX_EMAX+1
    6823             :  *     result->digits <= MPD_MAX_PREC+1
    6824             :  */
    6825             : void
    6826           0 : mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,
    6827             :              const mpd_context_t *ctx, uint32_t *status)
    6828             : {
    6829           0 :     if (exp > MPD_MAX_EMAX+1 || exp < MPD_MIN_ETINY) {
    6830           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6831           0 :         return;
    6832             :     }
    6833             : 
    6834           0 :     _mpd_qrescale(result, a, exp, ctx, status);
    6835             : }
    6836             : 
    6837             : /*
    6838             :  * Same as mpd_qrescale, but with relaxed restrictions. The result of this
    6839             :  * function should only be used for formatting a number and never as input
    6840             :  * for other operations.
    6841             :  *
    6842             :  *     MPD_MIN_ETINY-MPD_MAX_PREC <= exp <= MPD_MAX_EMAX+1
    6843             :  *     result->digits <= MPD_MAX_PREC+1
    6844             :  */
    6845             : void
    6846           0 : mpd_qrescale_fmt(mpd_t *result, const mpd_t *a, mpd_ssize_t exp,
    6847             :                  const mpd_context_t *ctx, uint32_t *status)
    6848             : {
    6849           0 :     if (exp > MPD_MAX_EMAX+1 || exp < MPD_MIN_ETINY-MPD_MAX_PREC) {
    6850           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    6851           0 :         return;
    6852             :     }
    6853             : 
    6854           0 :     _mpd_qrescale(result, a, exp, ctx, status);
    6855             : }
    6856             : 
    6857             : /* Round to an integer according to 'action' and ctx->round. */
    6858             : enum {TO_INT_EXACT, TO_INT_SILENT, TO_INT_TRUNC};
    6859             : static void
    6860           0 : _mpd_qround_to_integral(int action, mpd_t *result, const mpd_t *a,
    6861             :                         const mpd_context_t *ctx, uint32_t *status)
    6862             : {
    6863             :     mpd_uint_t rnd;
    6864             : 
    6865           0 :     if (mpd_isspecial(a)) {
    6866           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    6867           0 :             return;
    6868             :         }
    6869           0 :         mpd_qcopy(result, a, status);
    6870           0 :         return;
    6871             :     }
    6872           0 :     if (a->exp >= 0) {
    6873           0 :         mpd_qcopy(result, a, status);
    6874           0 :         return;
    6875             :     }
    6876           0 :     if (mpd_iszerocoeff(a)) {
    6877           0 :         _settriple(result, mpd_sign(a), 0, 0);
    6878           0 :         return;
    6879             :     }
    6880             : 
    6881           0 :     rnd = mpd_qshiftr(result, a, -a->exp, status);
    6882           0 :     if (rnd == MPD_UINT_MAX) {
    6883           0 :         return;
    6884             :     }
    6885           0 :     result->exp = 0;
    6886             : 
    6887           0 :     if (action == TO_INT_EXACT || action == TO_INT_SILENT) {
    6888           0 :         _mpd_apply_round_excess(result, rnd, ctx, status);
    6889           0 :         if (action == TO_INT_EXACT) {
    6890           0 :             *status |= MPD_Rounded;
    6891           0 :             if (rnd) {
    6892           0 :                 *status |= MPD_Inexact;
    6893             :             }
    6894             :         }
    6895             :     }
    6896             : }
    6897             : 
    6898             : void
    6899           0 : mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    6900             :                    uint32_t *status)
    6901             : {
    6902           0 :     (void)_mpd_qround_to_integral(TO_INT_EXACT, result, a, ctx, status);
    6903           0 : }
    6904             : 
    6905             : void
    6906           0 : mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    6907             :                   uint32_t *status)
    6908             : {
    6909           0 :     (void)_mpd_qround_to_integral(TO_INT_SILENT, result, a, ctx, status);
    6910           0 : }
    6911             : 
    6912             : void
    6913           0 : mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    6914             :            uint32_t *status)
    6915             : {
    6916           0 :     (void)_mpd_qround_to_integral(TO_INT_TRUNC, result, a, ctx, status);
    6917           0 : }
    6918             : 
    6919             : void
    6920           0 : mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    6921             :            uint32_t *status)
    6922             : {
    6923           0 :     mpd_context_t workctx = *ctx;
    6924           0 :     workctx.round = MPD_ROUND_FLOOR;
    6925           0 :     (void)_mpd_qround_to_integral(TO_INT_SILENT, result, a,
    6926             :                                   &workctx, status);
    6927           0 : }
    6928             : 
    6929             : void
    6930           0 : mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    6931             :           uint32_t *status)
    6932             : {
    6933           0 :     mpd_context_t workctx = *ctx;
    6934           0 :     workctx.round = MPD_ROUND_CEILING;
    6935           0 :     (void)_mpd_qround_to_integral(TO_INT_SILENT, result, a,
    6936             :                                   &workctx, status);
    6937           0 : }
    6938             : 
    6939             : int
    6940           0 : mpd_same_quantum(const mpd_t *a, const mpd_t *b)
    6941             : {
    6942           0 :     if (mpd_isspecial(a) || mpd_isspecial(b)) {
    6943           0 :         return ((mpd_isnan(a) && mpd_isnan(b)) ||
    6944           0 :                 (mpd_isinfinite(a) && mpd_isinfinite(b)));
    6945             :     }
    6946             : 
    6947           0 :     return a->exp == b->exp;
    6948             : }
    6949             : 
    6950             : /* Schedule the increase in precision for the Newton iteration. */
    6951             : static inline int
    6952           0 : recpr_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2],
    6953             :                     mpd_ssize_t maxprec, mpd_ssize_t initprec)
    6954             : {
    6955             :     mpd_ssize_t k;
    6956             :     int i;
    6957             : 
    6958             :     assert(maxprec > 0 && initprec > 0);
    6959           0 :     if (maxprec <= initprec) return -1;
    6960             : 
    6961           0 :     i = 0; k = maxprec;
    6962             :     do {
    6963           0 :         k = (k+1) / 2;
    6964           0 :         klist[i++] = k;
    6965           0 :     } while (k > initprec);
    6966             : 
    6967           0 :     return i-1;
    6968             : }
    6969             : 
    6970             : /*
    6971             :  * Initial approximation for the reciprocal:
    6972             :  *    k_0 := MPD_RDIGITS-2
    6973             :  *    z_0 := 10**(-k_0) * floor(10**(2*k_0 + 2) / floor(v * 10**(k_0 + 2)))
    6974             :  * Absolute error:
    6975             :  *    |1/v - z_0| < 10**(-k_0)
    6976             :  * ACL2 proof: maxerror-inverse-approx
    6977             :  */
    6978             : static void
    6979           0 : _mpd_qreciprocal_approx(mpd_t *z, const mpd_t *v, uint32_t *status)
    6980             : {
    6981           0 :     mpd_uint_t p10data[2] = {0, mpd_pow10[MPD_RDIGITS-2]};
    6982             :     mpd_uint_t dummy, word;
    6983             :     int n;
    6984             : 
    6985             :     assert(v->exp == -v->digits);
    6986             : 
    6987           0 :     _mpd_get_msdigits(&dummy, &word, v, MPD_RDIGITS);
    6988           0 :     n = mpd_word_digits(word);
    6989           0 :     word *= mpd_pow10[MPD_RDIGITS-n];
    6990             : 
    6991             :     mpd_qresize(z, 2, status);
    6992           0 :     (void)_mpd_shortdiv(z->data, p10data, 2, word);
    6993             : 
    6994             :     mpd_clear_flags(z);
    6995           0 :     z->exp = -(MPD_RDIGITS-2);
    6996           0 :     z->len = (z->data[1] == 0) ? 1 : 2;
    6997           0 :     mpd_setdigits(z);
    6998           0 : }
    6999             : 
    7000             : /*
    7001             :  * Reciprocal, calculated with Newton's Method. Assumption: result != a.
    7002             :  * NOTE: The comments in the function show that certain operations are
    7003             :  * exact. The proof for the maximum error is too long to fit in here.
    7004             :  * ACL2 proof: maxerror-inverse-complete
    7005             :  */
    7006             : static void
    7007           0 : _mpd_qreciprocal(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    7008             :                  uint32_t *status)
    7009             : {
    7010             :     mpd_context_t varcontext, maxcontext;
    7011           0 :     mpd_t *z = result;         /* current approximation */
    7012             :     mpd_t *v;                  /* a, normalized to a number between 0.1 and 1 */
    7013           0 :     MPD_NEW_SHARED(vtmp, a);   /* v shares data with a */
    7014           0 :     MPD_NEW_STATIC(s,0,0,0,0); /* temporary variable */
    7015           0 :     MPD_NEW_STATIC(t,0,0,0,0); /* temporary variable */
    7016           0 :     MPD_NEW_CONST(two,0,0,1,1,1,2); /* const 2 */
    7017             :     mpd_ssize_t klist[MPD_MAX_PREC_LOG2];
    7018             :     mpd_ssize_t adj, maxprec, initprec;
    7019           0 :     uint8_t sign = mpd_sign(a);
    7020             :     int i;
    7021             : 
    7022             :     assert(result != a);
    7023             : 
    7024           0 :     v = &vtmp;
    7025             :     mpd_clear_flags(v);
    7026           0 :     adj = v->digits + v->exp;
    7027           0 :     v->exp = -v->digits;
    7028             : 
    7029             :     /* Initial approximation */
    7030           0 :     _mpd_qreciprocal_approx(z, v, status);
    7031             : 
    7032           0 :     mpd_maxcontext(&varcontext);
    7033           0 :     mpd_maxcontext(&maxcontext);
    7034           0 :     varcontext.round = maxcontext.round = MPD_ROUND_TRUNC;
    7035           0 :     varcontext.emax = maxcontext.emax = MPD_MAX_EMAX + 100;
    7036           0 :     varcontext.emin = maxcontext.emin = MPD_MIN_EMIN - 100;
    7037           0 :     maxcontext.prec = MPD_MAX_PREC + 100;
    7038             : 
    7039           0 :     maxprec = ctx->prec;
    7040           0 :     maxprec += 2;
    7041           0 :     initprec = MPD_RDIGITS-3;
    7042             : 
    7043           0 :     i = recpr_schedule_prec(klist, maxprec, initprec);
    7044           0 :     for (; i >= 0; i--) {
    7045             :          /* Loop invariant: z->digits <= klist[i]+7 */
    7046             :          /* Let s := z**2, exact result */
    7047           0 :         _mpd_qmul_exact(&s, z, z, &maxcontext, status);
    7048           0 :         varcontext.prec = 2*klist[i] + 5;
    7049           0 :         if (v->digits > varcontext.prec) {
    7050             :             /* Let t := v, truncated to n >= 2*k+5 fraction digits */
    7051           0 :             mpd_qshiftr(&t, v, v->digits-varcontext.prec, status);
    7052           0 :             t.exp = -varcontext.prec;
    7053             :             /* Let t := trunc(v)*s, truncated to n >= 2*k+1 fraction digits */
    7054           0 :             mpd_qmul(&t, &t, &s, &varcontext, status);
    7055             :         }
    7056             :         else { /* v->digits <= 2*k+5 */
    7057             :             /* Let t := v*s, truncated to n >= 2*k+1 fraction digits */
    7058           0 :             mpd_qmul(&t, v, &s, &varcontext, status);
    7059             :         }
    7060             :         /* Let s := 2*z, exact result */
    7061           0 :         _mpd_qmul_exact(&s, z, &two, &maxcontext, status);
    7062             :         /* s.digits < t.digits <= 2*k+5, |adjexp(s)-adjexp(t)| <= 1,
    7063             :          * so the subtraction generates at most 2*k+6 <= klist[i+1]+7
    7064             :          * digits. The loop invariant is preserved. */
    7065           0 :         _mpd_qsub_exact(z, &s, &t, &maxcontext, status);
    7066             :     }
    7067             : 
    7068           0 :     if (!mpd_isspecial(z)) {
    7069           0 :         z->exp -= adj;
    7070           0 :         mpd_set_flags(z, sign);
    7071             :     }
    7072             : 
    7073             :     mpd_del(&s);
    7074             :     mpd_del(&t);
    7075           0 :     mpd_qfinalize(z, ctx, status);
    7076           0 : }
    7077             : 
    7078             : /*
    7079             :  * Internal function for large numbers:
    7080             :  *
    7081             :  *     q, r = divmod(coeff(a), coeff(b))
    7082             :  *
    7083             :  * Strategy: Multiply the dividend by the reciprocal of the divisor. The
    7084             :  * inexact result is fixed by a small loop, using at most one iteration.
    7085             :  *
    7086             :  * ACL2 proofs:
    7087             :  * ------------
    7088             :  *    1) q is a natural number.  (ndivmod-quotient-natp)
    7089             :  *    2) r is a natural number.  (ndivmod-remainder-natp)
    7090             :  *    3) a = q * b + r           (ndivmod-q*b+r==a)
    7091             :  *    4) r < b                   (ndivmod-remainder-<-b)
    7092             :  */
    7093             : static void
    7094           0 : _mpd_base_ndivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b,
    7095             :                   uint32_t *status)
    7096             : {
    7097             :     mpd_context_t workctx;
    7098           0 :     mpd_t *qq = q, *rr = r;
    7099             :     mpd_t aa, bb;
    7100             :     int k;
    7101             : 
    7102           0 :     _mpd_copy_shared(&aa, a);
    7103           0 :     _mpd_copy_shared(&bb, b);
    7104             : 
    7105             :     mpd_set_positive(&aa);
    7106             :     mpd_set_positive(&bb);
    7107           0 :     aa.exp = 0;
    7108           0 :     bb.exp = 0;
    7109             : 
    7110           0 :     if (q == a || q == b) {
    7111           0 :         if ((qq = mpd_qnew()) == NULL) {
    7112           0 :             *status |= MPD_Malloc_error;
    7113           0 :             goto nanresult;
    7114             :         }
    7115             :     }
    7116           0 :     if (r == a || r == b) {
    7117           0 :         if ((rr = mpd_qnew()) == NULL) {
    7118           0 :             *status |= MPD_Malloc_error;
    7119           0 :             goto nanresult;
    7120             :         }
    7121             :     }
    7122             : 
    7123           0 :     mpd_maxcontext(&workctx);
    7124             : 
    7125             :     /* Let prec := adigits - bdigits + 4 */
    7126           0 :     workctx.prec = a->digits - b->digits + 1 + 3;
    7127           0 :     if (a->digits > MPD_MAX_PREC || workctx.prec > MPD_MAX_PREC) {
    7128           0 :         *status |= MPD_Division_impossible;
    7129           0 :         goto nanresult;
    7130             :     }
    7131             : 
    7132             :     /* Let x := _mpd_qreciprocal(b, prec) 
    7133             :      * Then x is bounded by:
    7134             :      *    1) 1/b - 10**(-prec - bdigits) < x < 1/b + 10**(-prec - bdigits)
    7135             :      *    2) 1/b - 10**(-adigits - 4) < x < 1/b + 10**(-adigits - 4)
    7136             :      */
    7137           0 :     _mpd_qreciprocal(rr, &bb, &workctx, &workctx.status);
    7138             : 
    7139             :     /* Get an estimate for the quotient. Let q := a * x
    7140             :      * Then q is bounded by:
    7141             :      *    3) a/b - 10**-4 < q < a/b + 10**-4
    7142             :      */
    7143           0 :     _mpd_qmul(qq, &aa, rr, &workctx, &workctx.status);
    7144             :     /* Truncate q to an integer:
    7145             :      *    4) a/b - 2 < trunc(q) < a/b + 1
    7146             :      */
    7147           0 :     mpd_qtrunc(qq, qq, &workctx, &workctx.status);
    7148             : 
    7149           0 :     workctx.prec = aa.digits + 3;
    7150           0 :     workctx.emax = MPD_MAX_EMAX + 3;
    7151           0 :     workctx.emin = MPD_MIN_EMIN - 3;
    7152             :     /* Multiply the estimate for q by b:
    7153             :      *    5) a - 2 * b < trunc(q) * b < a + b
    7154             :      */
    7155           0 :     _mpd_qmul(rr, &bb, qq, &workctx, &workctx.status);
    7156             :     /* Get the estimate for r such that a = q * b + r. */
    7157           0 :     _mpd_qsub_exact(rr, &aa, rr, &workctx, &workctx.status);
    7158             : 
    7159             :     /* Fix the result. At this point -b < r < 2*b, so the correction loop
    7160             :        takes at most one iteration. */
    7161           0 :     for (k = 0;; k++) {
    7162           0 :         if (mpd_isspecial(qq) || mpd_isspecial(rr)) {
    7163           0 :             *status |= (workctx.status&MPD_Errors);
    7164           0 :             goto nanresult;
    7165             :         }
    7166           0 :         if (k > 2) { /* Allow two iterations despite the proof. */
    7167           0 :             mpd_err_warn("libmpdec: internal error in "       /* GCOV_NOT_REACHED */
    7168             :                          "_mpd_base_ndivmod: please report"); /* GCOV_NOT_REACHED */
    7169           0 :             *status |= MPD_Invalid_operation;                 /* GCOV_NOT_REACHED */
    7170           0 :             goto nanresult;                                   /* GCOV_NOT_REACHED */
    7171             :         }
    7172             :         /* r < 0 */
    7173           0 :         else if (_mpd_cmp(&zero, rr) == 1) {
    7174           0 :             _mpd_qadd_exact(rr, rr, &bb, &workctx, &workctx.status);
    7175           0 :             _mpd_qadd_exact(qq, qq, &minus_one, &workctx, &workctx.status);
    7176             :         }
    7177             :         /* 0 <= r < b */
    7178           0 :         else if (_mpd_cmp(rr, &bb) == -1) {
    7179           0 :             break;
    7180             :         }
    7181             :         /* r >= b */
    7182             :         else {
    7183           0 :             _mpd_qsub_exact(rr, rr, &bb, &workctx, &workctx.status);
    7184           0 :             _mpd_qadd_exact(qq, qq, &one, &workctx, &workctx.status);
    7185             :         }
    7186           0 :     }
    7187             : 
    7188           0 :     if (qq != q) {
    7189           0 :         if (!mpd_qcopy(q, qq, status)) {
    7190           0 :             goto nanresult; /* GCOV_UNLIKELY */
    7191             :         }
    7192             :         mpd_del(qq);
    7193             :     }
    7194           0 :     if (rr != r) {
    7195           0 :         if (!mpd_qcopy(r, rr, status)) {
    7196           0 :             goto nanresult; /* GCOV_UNLIKELY */
    7197             :         }
    7198             :         mpd_del(rr);
    7199             :     }
    7200             : 
    7201           0 :     *status |= (workctx.status&MPD_Errors);
    7202           0 :     return;
    7203             : 
    7204             : 
    7205             : nanresult:
    7206           0 :     if (qq && qq != q) mpd_del(qq);
    7207           0 :     if (rr && rr != r) mpd_del(rr);
    7208           0 :     mpd_setspecial(q, MPD_POS, MPD_NAN);
    7209           0 :     mpd_setspecial(r, MPD_POS, MPD_NAN);
    7210             : }
    7211             : 
    7212             : /* LIBMPDEC_ONLY */
    7213             : /*
    7214             :  * Schedule the optimal precision increase for the Newton iteration.
    7215             :  *   v := input operand
    7216             :  *   z_0 := initial approximation
    7217             :  *   initprec := natural number such that abs(sqrt(v) - z_0) < 10**-initprec
    7218             :  *   maxprec := target precision
    7219             :  *
    7220             :  * For convenience the output klist contains the elements in reverse order:
    7221             :  *   klist := [k_n-1, ..., k_0], where
    7222             :  *     1) k_0 <= initprec and
    7223             :  *     2) abs(sqrt(v) - result) < 10**(-2*k_n-1 + 2) <= 10**-maxprec.
    7224             :  */
    7225             : static inline int
    7226           0 : invroot_schedule_prec(mpd_ssize_t klist[MPD_MAX_PREC_LOG2],
    7227             :                       mpd_ssize_t maxprec, mpd_ssize_t initprec)
    7228             : {
    7229             :     mpd_ssize_t k;
    7230             :     int i;
    7231             : 
    7232             :     assert(maxprec >= 3 && initprec >= 3);
    7233           0 :     if (maxprec <= initprec) return -1;
    7234             : 
    7235           0 :     i = 0; k = maxprec;
    7236             :     do {
    7237           0 :         k = (k+3) / 2;
    7238           0 :         klist[i++] = k;
    7239           0 :     } while (k > initprec);
    7240             : 
    7241           0 :     return i-1;
    7242             : }
    7243             : 
    7244             : /*
    7245             :  * Initial approximation for the inverse square root function.
    7246             :  *   Input:
    7247             :  *     v := rational number, with 1 <= v < 100
    7248             :  *     vhat := floor(v * 10**6)
    7249             :  *   Output:
    7250             :  *     z := approximation to 1/sqrt(v), such that abs(z - 1/sqrt(v)) < 10**-3.
    7251             :  */
    7252             : static inline void
    7253           0 : _invroot_init_approx(mpd_t *z, mpd_uint_t vhat)
    7254             : {
    7255           0 :     mpd_uint_t lo = 1000;
    7256           0 :     mpd_uint_t hi = 10000;
    7257             :     mpd_uint_t a, sq;
    7258             : 
    7259             :     assert(lo*lo <= vhat && vhat < (hi+1)*(hi+1));
    7260             : 
    7261             :     for(;;) {
    7262           0 :         a = (lo + hi) / 2;
    7263           0 :         sq = a * a;
    7264           0 :         if (vhat >= sq) {
    7265           0 :             if (vhat < sq + 2*a + 1) {
    7266           0 :                 break;
    7267             :             }
    7268           0 :             lo = a + 1;
    7269             :         }
    7270             :         else {
    7271           0 :             hi = a - 1;
    7272             :         }
    7273           0 :     }
    7274             : 
    7275             :     /*
    7276             :      * After the binary search we have:
    7277             :      *  1) a**2 <= floor(v * 10**6) < (a + 1)**2
    7278             :      * This implies:
    7279             :      *  2) a**2 <= v * 10**6 < (a + 1)**2
    7280             :      *  3) a <= sqrt(v) * 10**3 < a + 1
    7281             :      * Since 10**3 <= a:
    7282             :      *  4) 0 <= 10**prec/a - 1/sqrt(v) < 10**-prec
    7283             :      * We have:
    7284             :      *  5) 10**3/a - 10**-3 < floor(10**9/a) * 10**-6 <= 10**3/a
    7285             :      * Merging 4) and 5):
    7286             :      *  6) abs(floor(10**9/a) * 10**-6 - 1/sqrt(v)) < 10**-3
    7287             :      */
    7288             :     mpd_minalloc(z);
    7289             :     mpd_clear_flags(z);
    7290           0 :     z->data[0] = 1000000000UL / a;
    7291           0 :     z->len = 1;
    7292           0 :     z->exp = -6;
    7293           0 :     mpd_setdigits(z);
    7294           0 : }
    7295             : 
    7296             : /*
    7297             :  * Set 'result' to 1/sqrt(a).
    7298             :  *   Relative error: abs(result - 1/sqrt(a)) < 10**-prec * 1/sqrt(a)
    7299             :  */
    7300             : static void
    7301           0 : _mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    7302             :               uint32_t *status)
    7303             : {
    7304           0 :     uint32_t workstatus = 0;
    7305             :     mpd_context_t varcontext, maxcontext;
    7306           0 :     mpd_t *z = result;         /* current approximation */
    7307             :     mpd_t *v;                  /* a, normalized to a number between 1 and 100 */
    7308           0 :     MPD_NEW_SHARED(vtmp, a);   /* by default v will share data with a */
    7309           0 :     MPD_NEW_STATIC(s,0,0,0,0); /* temporary variable */
    7310           0 :     MPD_NEW_STATIC(t,0,0,0,0); /* temporary variable */
    7311           0 :     MPD_NEW_CONST(one_half,0,-1,1,1,1,5);
    7312           0 :     MPD_NEW_CONST(three,0,0,1,1,1,3);
    7313             :     mpd_ssize_t klist[MPD_MAX_PREC_LOG2];
    7314             :     mpd_ssize_t ideal_exp, shift;
    7315             :     mpd_ssize_t adj, tz;
    7316             :     mpd_ssize_t maxprec, fracdigits;
    7317             :     mpd_uint_t vhat, dummy;
    7318             :     int i, n;
    7319             : 
    7320             : 
    7321           0 :     ideal_exp = -(a->exp - (a->exp & 1)) / 2;
    7322             : 
    7323           0 :     v = &vtmp;
    7324           0 :     if (result == a) {
    7325           0 :         if ((v = mpd_qncopy(a)) == NULL) {
    7326           0 :             mpd_seterror(result, MPD_Malloc_error, status);
    7327           0 :             return;
    7328             :         }
    7329             :     }
    7330             : 
    7331             :     /* normalize a to 1 <= v < 100 */
    7332           0 :     if ((v->digits+v->exp) & 1) {
    7333           0 :         fracdigits = v->digits - 1;
    7334           0 :         v->exp = -fracdigits;
    7335           0 :         n = (v->digits > 7) ? 7 : (int)v->digits;
    7336             :         /* Let vhat := floor(v * 10**(2*initprec)) */
    7337           0 :         _mpd_get_msdigits(&dummy, &vhat, v, n);
    7338           0 :         if (n < 7) {
    7339           0 :             vhat *= mpd_pow10[7-n];
    7340             :         }
    7341             :     }
    7342             :     else {
    7343           0 :         fracdigits = v->digits - 2;
    7344           0 :         v->exp = -fracdigits;
    7345           0 :         n = (v->digits > 8) ? 8 : (int)v->digits;
    7346             :         /* Let vhat := floor(v * 10**(2*initprec)) */
    7347           0 :         _mpd_get_msdigits(&dummy, &vhat, v, n);
    7348           0 :         if (n < 8) {
    7349           0 :             vhat *= mpd_pow10[8-n];
    7350             :         }
    7351             :     }
    7352           0 :     adj = (a->exp-v->exp) / 2;
    7353             : 
    7354             :     /* initial approximation */
    7355           0 :     _invroot_init_approx(z, vhat);
    7356             : 
    7357           0 :     mpd_maxcontext(&maxcontext);
    7358           0 :     mpd_maxcontext(&varcontext);
    7359           0 :     varcontext.round = MPD_ROUND_TRUNC;
    7360           0 :     maxprec = ctx->prec + 1;
    7361             : 
    7362             :     /* initprec == 3 */
    7363           0 :     i = invroot_schedule_prec(klist, maxprec, 3);
    7364           0 :     for (; i >= 0; i--) {
    7365           0 :         varcontext.prec = 2*klist[i]+2;
    7366           0 :         mpd_qmul(&s, z, z, &maxcontext, &workstatus);
    7367           0 :         if (v->digits > varcontext.prec) {
    7368           0 :             shift = v->digits - varcontext.prec;
    7369           0 :             mpd_qshiftr(&t, v, shift, &workstatus);
    7370           0 :             t.exp += shift;
    7371           0 :             mpd_qmul(&t, &t, &s, &varcontext, &workstatus);
    7372             :         }
    7373             :         else {
    7374           0 :             mpd_qmul(&t, v, &s, &varcontext, &workstatus);
    7375             :         }
    7376           0 :         mpd_qsub(&t, &three, &t, &maxcontext, &workstatus);
    7377           0 :         mpd_qmul(z, z, &t, &varcontext, &workstatus);
    7378           0 :         mpd_qmul(z, z, &one_half, &maxcontext, &workstatus);
    7379             :     }
    7380             : 
    7381           0 :     z->exp -= adj;
    7382             : 
    7383           0 :     tz = mpd_trail_zeros(result);
    7384           0 :     shift = ideal_exp - result->exp;
    7385           0 :     shift = (tz > shift) ? shift : tz;
    7386           0 :     if (shift > 0) {
    7387           0 :         mpd_qshiftr_inplace(result, shift);
    7388           0 :         result->exp += shift;
    7389             :     }
    7390             : 
    7391             : 
    7392             :     mpd_del(&s);
    7393             :     mpd_del(&t);
    7394           0 :     if (v != &vtmp) mpd_del(v);
    7395           0 :     *status |= (workstatus&MPD_Errors);
    7396           0 :     *status |= (MPD_Rounded|MPD_Inexact);
    7397             : }
    7398             : 
    7399             : void
    7400           0 : mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    7401             :              uint32_t *status)
    7402             : {
    7403             :     mpd_context_t workctx;
    7404             : 
    7405           0 :     if (mpd_isspecial(a)) {
    7406           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    7407             :             return;
    7408             :         }
    7409           0 :         if (mpd_isnegative(a)) {
    7410           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    7411             :             return;
    7412             :         }
    7413             :         /* positive infinity */
    7414           0 :         _settriple(result, MPD_POS, 0, mpd_etiny(ctx));
    7415           0 :         *status |= MPD_Clamped;
    7416             :         return;
    7417             :     }
    7418           0 :     if (mpd_iszero(a)) {
    7419           0 :         mpd_setspecial(result, mpd_sign(a), MPD_INF);
    7420           0 :         *status |= MPD_Division_by_zero;
    7421             :         return;
    7422             :     }
    7423           0 :     if (mpd_isnegative(a)) {
    7424           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    7425             :         return;
    7426             :     }
    7427             : 
    7428           0 :     workctx = *ctx;
    7429           0 :     workctx.prec += 2;
    7430           0 :     workctx.round = MPD_ROUND_HALF_EVEN;
    7431           0 :     _mpd_qinvroot(result, a, &workctx, status);
    7432           0 :     mpd_qfinalize(result, ctx, status);
    7433             : }
    7434             : /* END LIBMPDEC_ONLY */
    7435             : 
    7436             : /* Algorithm from decimal.py */
    7437             : void
    7438           0 : mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx,
    7439             :           uint32_t *status)
    7440             : {
    7441             :     mpd_context_t maxcontext;
    7442           0 :     MPD_NEW_STATIC(c,0,0,0,0);
    7443           0 :     MPD_NEW_STATIC(q,0,0,0,0);
    7444           0 :     MPD_NEW_STATIC(r,0,0,0,0);
    7445           0 :     MPD_NEW_CONST(two,0,0,1,1,1,2);
    7446             :     mpd_ssize_t prec, ideal_exp;
    7447             :     mpd_ssize_t l, shift;
    7448           0 :     int exact = 0;
    7449             : 
    7450             : 
    7451           0 :     ideal_exp = (a->exp - (a->exp & 1)) / 2;
    7452             : 
    7453           0 :     if (mpd_isspecial(a)) {
    7454           0 :         if (mpd_qcheck_nan(result, a, ctx, status)) {
    7455             :             return;
    7456             :         }
    7457           0 :         if (mpd_isnegative(a)) {
    7458           0 :             mpd_seterror(result, MPD_Invalid_operation, status);
    7459             :             return;
    7460             :         }
    7461           0 :         mpd_setspecial(result, MPD_POS, MPD_INF);
    7462             :         return;
    7463             :     }
    7464           0 :     if (mpd_iszero(a)) {
    7465           0 :         _settriple(result, mpd_sign(a), 0, ideal_exp);
    7466           0 :         mpd_qfinalize(result, ctx, status);
    7467             :         return;
    7468             :     }
    7469           0 :     if (mpd_isnegative(a)) {
    7470           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    7471             :         return;
    7472             :     }
    7473             : 
    7474           0 :     mpd_maxcontext(&maxcontext);
    7475           0 :     prec = ctx->prec + 1;
    7476             : 
    7477           0 :     if (!mpd_qcopy(&c, a, status)) {
    7478           0 :         goto malloc_error;
    7479             :     }
    7480           0 :     c.exp = 0;
    7481             : 
    7482           0 :     if (a->exp & 1) {
    7483           0 :         if (!mpd_qshiftl(&c, &c, 1, status)) {
    7484           0 :             goto malloc_error;
    7485             :         }
    7486           0 :         l = (a->digits >> 1) + 1;
    7487             :     }
    7488             :     else {
    7489           0 :         l = (a->digits + 1) >> 1;
    7490             :     }
    7491             : 
    7492           0 :     shift = prec - l;
    7493           0 :     if (shift >= 0) {
    7494           0 :         if (!mpd_qshiftl(&c, &c, 2*shift, status)) {
    7495           0 :             goto malloc_error;
    7496             :         }
    7497           0 :         exact = 1;
    7498             :     }
    7499             :     else {
    7500           0 :         exact = !mpd_qshiftr_inplace(&c, -2*shift);
    7501             :     }
    7502             : 
    7503           0 :     ideal_exp -= shift;
    7504             : 
    7505             :     /* find result = floor(sqrt(c)) using Newton's method */
    7506           0 :     if (!mpd_qshiftl(result, &one, prec, status)) {
    7507           0 :         goto malloc_error;
    7508             :     }
    7509             : 
    7510             :     while (1) {
    7511           0 :         _mpd_qdivmod(&q, &r, &c, result, &maxcontext, &maxcontext.status);
    7512           0 :         if (mpd_isspecial(result) || mpd_isspecial(&q)) {
    7513           0 :             mpd_seterror(result, maxcontext.status&MPD_Errors, status);
    7514           0 :             goto out;
    7515             :         }
    7516           0 :         if (_mpd_cmp(result, &q) <= 0) {
    7517           0 :             break;
    7518             :         }
    7519           0 :         _mpd_qadd_exact(result, result, &q, &maxcontext, &maxcontext.status);
    7520           0 :         if (mpd_isspecial(result)) {
    7521           0 :             mpd_seterror(result, maxcontext.status&MPD_Errors, status);
    7522           0 :             goto out;
    7523             :         }
    7524           0 :         _mpd_qdivmod(result, &r, result, &two, &maxcontext, &maxcontext.status);
    7525           0 :     }
    7526             : 
    7527           0 :     if (exact) {
    7528           0 :         _mpd_qmul_exact(&r, result, result, &maxcontext, &maxcontext.status);
    7529           0 :         if (mpd_isspecial(&r)) {
    7530           0 :             mpd_seterror(result, maxcontext.status&MPD_Errors, status);
    7531           0 :             goto out;
    7532             :         }
    7533           0 :         exact = (_mpd_cmp(&r, &c) == 0);
    7534             :     }
    7535             : 
    7536           0 :     if (exact) {
    7537           0 :         if (shift >= 0) {
    7538           0 :             mpd_qshiftr_inplace(result, shift);
    7539             :         }
    7540             :         else {
    7541           0 :             if (!mpd_qshiftl(result, result, -shift, status)) {
    7542           0 :                 goto malloc_error;
    7543             :             }
    7544             :         }
    7545           0 :         ideal_exp += shift;
    7546             :     }
    7547             :     else {
    7548           0 :         int lsd = (int)mpd_lsd(result->data[0]);
    7549           0 :         if (lsd == 0 || lsd == 5) {
    7550           0 :             result->data[0] += 1;
    7551             :         }
    7552             :     }
    7553             : 
    7554           0 :     result->exp = ideal_exp;
    7555             : 
    7556             : 
    7557             : out:
    7558             :     mpd_del(&c);
    7559             :     mpd_del(&q);
    7560             :     mpd_del(&r);
    7561           0 :     maxcontext = *ctx;
    7562           0 :     maxcontext.round = MPD_ROUND_HALF_EVEN;
    7563           0 :     mpd_qfinalize(result, &maxcontext, status);
    7564             :     return;
    7565             : 
    7566             : malloc_error:
    7567           0 :     mpd_seterror(result, MPD_Malloc_error, status);
    7568           0 :     goto out;
    7569             : }
    7570             : 
    7571             : 
    7572             : /******************************************************************************/
    7573             : /*                              Base conversions                              */
    7574             : /******************************************************************************/
    7575             : 
    7576             : /* Space needed to represent an integer mpd_t in base 'base'. */
    7577             : size_t
    7578           0 : mpd_sizeinbase(const mpd_t *a, uint32_t base)
    7579             : {
    7580             :     double x;
    7581             :     size_t digits;
    7582             : 
    7583             :     assert(mpd_isinteger(a));
    7584             :     assert(base >= 2);
    7585             : 
    7586           0 :     if (mpd_iszero(a)) {
    7587           0 :         return 1;
    7588             :     }
    7589             : 
    7590           0 :     digits = a->digits+a->exp;
    7591             :     assert(digits > 0);
    7592             : 
    7593             : #ifdef CONFIG_64
    7594             :     /* ceil(2711437152599294 / log10(2)) + 4 == 2**53 */
    7595             :     if (digits > 2711437152599294ULL) {
    7596             :         return SIZE_MAX;
    7597             :     }
    7598             : #endif
    7599             : 
    7600           0 :     x = (double)digits / log10(base);
    7601           0 :     return (x > SIZE_MAX-1) ? SIZE_MAX : (size_t)x + 1;
    7602             : }
    7603             : 
    7604             : /* Space needed to import a base 'base' integer of length 'srclen'. */
    7605             : static mpd_ssize_t
    7606           0 : _mpd_importsize(size_t srclen, uint32_t base)
    7607             : {
    7608             :     double x;
    7609             : 
    7610             :     assert(srclen > 0);
    7611             :     assert(base >= 2);
    7612             : 
    7613             : #if SIZE_MAX == UINT64_MAX
    7614             :     if (srclen > (1ULL<<53)) {
    7615             :         return MPD_SSIZE_MAX;
    7616             :     }
    7617             : #endif
    7618             : 
    7619           0 :     x = (double)srclen * (log10(base)/MPD_RDIGITS);
    7620           0 :     return (x >= MPD_MAXIMPORT) ? MPD_SSIZE_MAX : (mpd_ssize_t)x + 1;
    7621             : }
    7622             : 
    7623             : static uint8_t
    7624           0 : mpd_resize_u16(uint16_t **w, size_t nmemb)
    7625             : {
    7626           0 :     uint8_t err = 0;
    7627           0 :     *w = mpd_realloc(*w, nmemb, sizeof **w, &err);
    7628           0 :     return !err;
    7629             : }
    7630             : 
    7631             : static uint8_t
    7632           0 : mpd_resize_u32(uint32_t **w, size_t nmemb)
    7633             : {
    7634           0 :     uint8_t err = 0;
    7635           0 :     *w = mpd_realloc(*w, nmemb, sizeof **w, &err);
    7636           0 :     return !err;
    7637             : }
    7638             : 
    7639             : static size_t
    7640           0 : _baseconv_to_u16(uint16_t **w, size_t wlen, mpd_uint_t wbase,
    7641             :                  mpd_uint_t *u, mpd_ssize_t ulen)
    7642             : {
    7643           0 :     size_t n = 0;
    7644             : 
    7645             :     assert(wlen > 0 && ulen > 0);
    7646             :     assert(wbase <= (1U<<16));
    7647             : 
    7648             :     do {
    7649           0 :         if (n >= wlen) {
    7650           0 :             if (!mpd_resize_u16(w, n+1)) {
    7651           0 :                 return SIZE_MAX;
    7652             :             }
    7653           0 :             wlen = n+1;
    7654             :         }
    7655           0 :         (*w)[n++] = (uint16_t)_mpd_shortdiv(u, u, ulen, wbase);
    7656             :         /* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */
    7657           0 :         ulen = _mpd_real_size(u, ulen);
    7658             : 
    7659           0 :     } while (u[ulen-1] != 0);
    7660             : 
    7661           0 :     return n;
    7662             : }
    7663             : 
    7664             : static size_t
    7665           0 : _coeff_from_u16(mpd_t *w, mpd_ssize_t wlen,
    7666             :                 const mpd_uint_t *u, size_t ulen, uint32_t ubase,
    7667             :                 uint32_t *status)
    7668             : {
    7669           0 :     mpd_ssize_t n = 0;
    7670             :     mpd_uint_t carry;
    7671             : 
    7672             :     assert(wlen > 0 && ulen > 0);
    7673             :     assert(ubase <= (1U<<16));
    7674             : 
    7675           0 :     w->data[n++] = u[--ulen];
    7676           0 :     while (--ulen != SIZE_MAX) {
    7677           0 :         carry = _mpd_shortmul_c(w->data, w->data, n, ubase);
    7678           0 :         if (carry) {
    7679           0 :             if (n >= wlen) {
    7680           0 :                 if (!mpd_qresize(w, n+1, status)) {
    7681           0 :                     return SIZE_MAX;
    7682             :                 }
    7683           0 :                 wlen = n+1;
    7684             :             }
    7685           0 :             w->data[n++] = carry;
    7686             :         }
    7687           0 :         carry = _mpd_shortadd(w->data, n, u[ulen]);
    7688           0 :         if (carry) {
    7689           0 :             if (n >= wlen) {
    7690           0 :                 if (!mpd_qresize(w, n+1, status)) {
    7691           0 :                     return SIZE_MAX;
    7692             :                 }
    7693           0 :                 wlen = n+1;
    7694             :             }
    7695           0 :             w->data[n++] = carry;
    7696             :         }
    7697             :     }
    7698             : 
    7699           0 :     return n;
    7700             : }
    7701             : 
    7702             : /* target base wbase < source base ubase */
    7703             : static size_t
    7704           0 : _baseconv_to_smaller(uint32_t **w, size_t wlen, uint32_t wbase,
    7705             :                      mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase)
    7706             : {
    7707           0 :     size_t n = 0;
    7708             : 
    7709             :     assert(wlen > 0 && ulen > 0);
    7710             :     assert(wbase < ubase);
    7711             : 
    7712             :     do {
    7713           0 :         if (n >= wlen) {
    7714           0 :             if (!mpd_resize_u32(w, n+1)) {
    7715           0 :                 return SIZE_MAX;
    7716             :             }
    7717           0 :             wlen = n+1;
    7718             :         }
    7719           0 :         (*w)[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase);
    7720             :         /* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */
    7721           0 :         ulen = _mpd_real_size(u, ulen);
    7722             : 
    7723           0 :     } while (u[ulen-1] != 0);
    7724             : 
    7725           0 :     return n;
    7726             : }
    7727             : 
    7728             : #ifdef CONFIG_32
    7729             : /* target base 'wbase' == source base 'ubase' */
    7730             : static size_t
    7731           0 : _copy_equal_base(uint32_t **w, size_t wlen,
    7732             :                  const uint32_t *u, size_t ulen)
    7733             : {
    7734           0 :     if (wlen < ulen) {
    7735           0 :         if (!mpd_resize_u32(w, ulen)) {
    7736           0 :             return SIZE_MAX;
    7737             :         }
    7738             :     }
    7739             : 
    7740           0 :     memcpy(*w, u, ulen * (sizeof **w));
    7741           0 :     return ulen;
    7742             : }
    7743             : 
    7744             : /* target base 'wbase' > source base 'ubase' */
    7745             : static size_t
    7746           0 : _baseconv_to_larger(uint32_t **w, size_t wlen, mpd_uint_t wbase,
    7747             :                     const mpd_uint_t *u, size_t ulen, mpd_uint_t ubase)
    7748             : {
    7749           0 :     size_t n = 0;
    7750             :     mpd_uint_t carry;
    7751             : 
    7752             :     assert(wlen > 0 && ulen > 0);
    7753             :     assert(ubase < wbase);
    7754             : 
    7755           0 :     (*w)[n++] = u[--ulen];
    7756           0 :     while (--ulen != SIZE_MAX) {
    7757           0 :         carry = _mpd_shortmul_b(*w, *w, n, ubase, wbase);
    7758           0 :         if (carry) {
    7759           0 :             if (n >= wlen) {
    7760           0 :                 if (!mpd_resize_u32(w, n+1)) {
    7761           0 :                     return SIZE_MAX;
    7762             :                 }
    7763           0 :                 wlen = n+1;
    7764             :             }
    7765           0 :             (*w)[n++] = carry;
    7766             :         }
    7767           0 :         carry = _mpd_shortadd_b(*w, n, u[ulen], wbase);
    7768           0 :         if (carry) {
    7769           0 :             if (n >= wlen) {
    7770           0 :                 if (!mpd_resize_u32(w, n+1)) {
    7771           0 :                     return SIZE_MAX;
    7772             :                 }
    7773           0 :                 wlen = n+1;
    7774             :             }
    7775           0 :             (*w)[n++] = carry;
    7776             :         }
    7777             :     }
    7778             : 
    7779           0 :     return n;
    7780             : }
    7781             : 
    7782             : /* target base wbase < source base ubase */
    7783             : static size_t
    7784           0 : _coeff_from_larger_base(mpd_t *w, size_t wlen, mpd_uint_t wbase,
    7785             :                         mpd_uint_t *u, mpd_ssize_t ulen, mpd_uint_t ubase,
    7786             :                         uint32_t *status)
    7787             : {
    7788           0 :     size_t n = 0;
    7789             : 
    7790             :     assert(wlen > 0 && ulen > 0);
    7791             :     assert(wbase < ubase);
    7792             : 
    7793             :     do {
    7794           0 :         if (n >= wlen) {
    7795           0 :             if (!mpd_qresize(w, n+1, status)) {
    7796           0 :                 return SIZE_MAX;
    7797             :             }
    7798           0 :             wlen = n+1;
    7799             :         }
    7800           0 :         w->data[n++] = (uint32_t)_mpd_shortdiv_b(u, u, ulen, wbase, ubase);
    7801             :         /* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */
    7802           0 :         ulen = _mpd_real_size(u, ulen);
    7803             : 
    7804           0 :     } while (u[ulen-1] != 0);
    7805             : 
    7806           0 :     return n;
    7807             : }
    7808             : #endif
    7809             : 
    7810             : /* target base 'wbase' > source base 'ubase' */
    7811             : static size_t
    7812           0 : _coeff_from_smaller_base(mpd_t *w, mpd_ssize_t wlen, mpd_uint_t wbase,
    7813             :                          const uint32_t *u, size_t ulen, mpd_uint_t ubase,
    7814             :                          uint32_t *status)
    7815             : {
    7816           0 :     mpd_ssize_t n = 0;
    7817             :     mpd_uint_t carry;
    7818             : 
    7819             :     assert(wlen > 0 && ulen > 0);
    7820             :     assert(wbase > ubase);
    7821             : 
    7822           0 :     w->data[n++] = u[--ulen];
    7823           0 :     while (--ulen != SIZE_MAX) {
    7824           0 :         carry = _mpd_shortmul_b(w->data, w->data, n, ubase, wbase);
    7825           0 :         if (carry) {
    7826           0 :             if (n >= wlen) {
    7827           0 :                 if (!mpd_qresize(w, n+1, status)) {
    7828           0 :                     return SIZE_MAX;
    7829             :                 }
    7830           0 :                 wlen = n+1;
    7831             :             }
    7832           0 :             w->data[n++] = carry;
    7833             :         }
    7834           0 :         carry = _mpd_shortadd_b(w->data, n, u[ulen], wbase);
    7835           0 :         if (carry) {
    7836           0 :             if (n >= wlen) {
    7837           0 :                 if (!mpd_qresize(w, n+1, status)) {
    7838           0 :                     return SIZE_MAX;
    7839             :                 }
    7840           0 :                 wlen = n+1;
    7841             :             }
    7842           0 :             w->data[n++] = carry;
    7843             :         }
    7844             :     }
    7845             : 
    7846           0 :     return n;
    7847             : }
    7848             : 
    7849             : /*
    7850             :  * Convert an integer mpd_t to a multiprecision integer with base <= 2**16.
    7851             :  * The least significant word of the result is (*rdata)[0].
    7852             :  *
    7853             :  * If rdata is NULL, space is allocated by the function and rlen is irrelevant.
    7854             :  * In case of an error any allocated storage is freed and rdata is set back to
    7855             :  * NULL.
    7856             :  *
    7857             :  * If rdata is non-NULL, it MUST be allocated by one of libmpdec's allocation
    7858             :  * functions and rlen MUST be correct. If necessary, the function will resize
    7859             :  * rdata. In case of an error the caller must free rdata.
    7860             :  *
    7861             :  * Return value: In case of success, the exact length of rdata, SIZE_MAX
    7862             :  * otherwise.
    7863             :  */
    7864             : size_t
    7865           0 : mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t rbase,
    7866             :                 const mpd_t *src, uint32_t *status)
    7867             : {
    7868           0 :     MPD_NEW_STATIC(tsrc,0,0,0,0);
    7869           0 :     int alloc = 0; /* rdata == NULL */
    7870             :     size_t n;
    7871             : 
    7872             :     assert(rbase <= (1U<<16));
    7873             : 
    7874           0 :     if (mpd_isspecial(src) || !_mpd_isint(src)) {
    7875           0 :         *status |= MPD_Invalid_operation;
    7876           0 :         return SIZE_MAX;
    7877             :     }
    7878             : 
    7879           0 :     if (*rdata == NULL) {
    7880           0 :         rlen = mpd_sizeinbase(src, rbase);
    7881           0 :         if (rlen == SIZE_MAX) {
    7882           0 :             *status |= MPD_Invalid_operation;
    7883           0 :             return SIZE_MAX;
    7884             :         }
    7885           0 :         *rdata = mpd_alloc(rlen, sizeof **rdata);
    7886           0 :         if (*rdata == NULL) {
    7887           0 :             goto malloc_error;
    7888             :         }
    7889           0 :         alloc = 1;
    7890             :     }
    7891             : 
    7892           0 :     if (mpd_iszero(src)) {
    7893           0 :         **rdata = 0;
    7894           0 :         return 1;
    7895             :     }
    7896             : 
    7897           0 :     if (src->exp >= 0) {
    7898           0 :         if (!mpd_qshiftl(&tsrc, src, src->exp, status)) {
    7899           0 :             goto malloc_error;
    7900             :         }
    7901             :     }
    7902             :     else {
    7903           0 :         if (mpd_qshiftr(&tsrc, src, -src->exp, status) == MPD_UINT_MAX) {
    7904           0 :             goto malloc_error;
    7905             :         }
    7906             :     }
    7907             : 
    7908           0 :     n = _baseconv_to_u16(rdata, rlen, rbase, tsrc.data, tsrc.len);
    7909           0 :     if (n == SIZE_MAX) {
    7910           0 :         goto malloc_error;
    7911             :     }
    7912             : 
    7913             : 
    7914             : out:
    7915             :     mpd_del(&tsrc);
    7916           0 :     return n;
    7917             : 
    7918             : malloc_error:
    7919           0 :     if (alloc) {
    7920           0 :         mpd_free(*rdata);
    7921           0 :         *rdata = NULL;
    7922             :     }
    7923           0 :     n = SIZE_MAX;
    7924           0 :     *status |= MPD_Malloc_error;
    7925           0 :     goto out;
    7926             : }
    7927             : 
    7928             : /*
    7929             :  * Convert an integer mpd_t to a multiprecision integer with base<=UINT32_MAX.
    7930             :  * The least significant word of the result is (*rdata)[0].
    7931             :  *
    7932             :  * If rdata is NULL, space is allocated by the function and rlen is irrelevant.
    7933             :  * In case of an error any allocated storage is freed and rdata is set back to
    7934             :  * NULL.
    7935             :  *
    7936             :  * If rdata is non-NULL, it MUST be allocated by one of libmpdec's allocation
    7937             :  * functions and rlen MUST be correct. If necessary, the function will resize
    7938             :  * rdata. In case of an error the caller must free rdata.
    7939             :  *
    7940             :  * Return value: In case of success, the exact length of rdata, SIZE_MAX
    7941             :  * otherwise.
    7942             :  */
    7943             : size_t
    7944           0 : mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t rbase,
    7945             :                 const mpd_t *src, uint32_t *status)
    7946             : {
    7947           0 :     MPD_NEW_STATIC(tsrc,0,0,0,0);
    7948           0 :     int alloc = 0; /* rdata == NULL */
    7949             :     size_t n;
    7950             : 
    7951           0 :     if (mpd_isspecial(src) || !_mpd_isint(src)) {
    7952           0 :         *status |= MPD_Invalid_operation;
    7953           0 :         return SIZE_MAX;
    7954             :     }
    7955             : 
    7956           0 :     if (*rdata == NULL) {
    7957           0 :         rlen = mpd_sizeinbase(src, rbase);
    7958           0 :         if (rlen == SIZE_MAX) {
    7959           0 :             *status |= MPD_Invalid_operation;
    7960           0 :             return SIZE_MAX;
    7961             :         }
    7962           0 :         *rdata = mpd_alloc(rlen, sizeof **rdata);
    7963           0 :         if (*rdata == NULL) {
    7964           0 :             goto malloc_error;
    7965             :         }
    7966           0 :         alloc = 1;
    7967             :     }
    7968             : 
    7969           0 :     if (mpd_iszero(src)) {
    7970           0 :         **rdata = 0;
    7971           0 :         return 1;
    7972             :     }
    7973             : 
    7974           0 :     if (src->exp >= 0) {
    7975           0 :         if (!mpd_qshiftl(&tsrc, src, src->exp, status)) {
    7976           0 :             goto malloc_error;
    7977             :         }
    7978             :     }
    7979             :     else {
    7980           0 :         if (mpd_qshiftr(&tsrc, src, -src->exp, status) == MPD_UINT_MAX) {
    7981           0 :             goto malloc_error;
    7982             :         }
    7983             :     }
    7984             : 
    7985             : #ifdef CONFIG_64
    7986             :     n = _baseconv_to_smaller(rdata, rlen, rbase,
    7987             :                              tsrc.data, tsrc.len, MPD_RADIX);
    7988             : #else
    7989           0 :     if (rbase == MPD_RADIX) {
    7990           0 :         n = _copy_equal_base(rdata, rlen, tsrc.data, tsrc.len);
    7991             :     }
    7992           0 :     else if (rbase < MPD_RADIX) {
    7993           0 :         n = _baseconv_to_smaller(rdata, rlen, rbase,
    7994             :                                  tsrc.data, tsrc.len, MPD_RADIX);
    7995             :     }
    7996             :     else {
    7997           0 :         n = _baseconv_to_larger(rdata, rlen, rbase,
    7998           0 :                                 tsrc.data, tsrc.len, MPD_RADIX);
    7999             :     }
    8000             : #endif
    8001             : 
    8002           0 :     if (n == SIZE_MAX) {
    8003           0 :         goto malloc_error;
    8004             :     }
    8005             : 
    8006             : 
    8007             : out:
    8008             :     mpd_del(&tsrc);
    8009           0 :     return n;
    8010             : 
    8011             : malloc_error:
    8012           0 :     if (alloc) {
    8013           0 :         mpd_free(*rdata);
    8014           0 :         *rdata = NULL;
    8015             :     }
    8016           0 :     n = SIZE_MAX;
    8017           0 :     *status |= MPD_Malloc_error;
    8018           0 :     goto out;
    8019             : }
    8020             : 
    8021             : 
    8022             : /*
    8023             :  * Converts a multiprecision integer with base <= UINT16_MAX+1 to an mpd_t.
    8024             :  * The least significant word of the source is srcdata[0].
    8025             :  */
    8026             : void
    8027           0 : mpd_qimport_u16(mpd_t *result,
    8028             :                 const uint16_t *srcdata, size_t srclen,
    8029             :                 uint8_t srcsign, uint32_t srcbase,
    8030             :                 const mpd_context_t *ctx, uint32_t *status)
    8031             : {
    8032             :     mpd_uint_t *usrc; /* uint16_t src copied to an mpd_uint_t array */
    8033             :     mpd_ssize_t rlen; /* length of the result */
    8034             :     size_t n;
    8035             : 
    8036             :     assert(srclen > 0);
    8037             :     assert(srcbase <= (1U<<16));
    8038             : 
    8039           0 :     rlen = _mpd_importsize(srclen, srcbase);
    8040           0 :     if (rlen == MPD_SSIZE_MAX) {
    8041           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    8042           0 :         return;
    8043             :     }
    8044             : 
    8045           0 :     usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc);
    8046           0 :     if (usrc == NULL) {
    8047           0 :         mpd_seterror(result, MPD_Malloc_error, status);
    8048           0 :         return;
    8049             :     }
    8050           0 :     for (n = 0; n < srclen; n++) {
    8051           0 :         usrc[n] = srcdata[n];
    8052             :     }
    8053             : 
    8054           0 :     if (!mpd_qresize(result, rlen, status)) {
    8055           0 :         goto finish;
    8056             :     }
    8057             : 
    8058           0 :     n = _coeff_from_u16(result, rlen, usrc, srclen, srcbase, status);
    8059           0 :     if (n == SIZE_MAX) {
    8060           0 :         goto finish;
    8061             :     }
    8062             : 
    8063           0 :     mpd_set_flags(result, srcsign);
    8064           0 :     result->exp = 0;
    8065           0 :     result->len = n;
    8066           0 :     mpd_setdigits(result);
    8067             : 
    8068           0 :     mpd_qresize(result, result->len, status);
    8069           0 :     mpd_qfinalize(result, ctx, status);
    8070             : 
    8071             : 
    8072             : finish:
    8073           0 :     mpd_free(usrc);
    8074             : }
    8075             : 
    8076             : /*
    8077             :  * Converts a multiprecision integer with base <= UINT32_MAX to an mpd_t.
    8078             :  * The least significant word of the source is srcdata[0].
    8079             :  */
    8080             : void
    8081           0 : mpd_qimport_u32(mpd_t *result,
    8082             :                 const uint32_t *srcdata, size_t srclen,
    8083             :                 uint8_t srcsign, uint32_t srcbase,
    8084             :                 const mpd_context_t *ctx, uint32_t *status)
    8085             : {
    8086             :     mpd_ssize_t rlen; /* length of the result */
    8087             :     size_t n;
    8088             : 
    8089             :     assert(srclen > 0);
    8090             : 
    8091           0 :     rlen = _mpd_importsize(srclen, srcbase);
    8092           0 :     if (rlen == MPD_SSIZE_MAX) {
    8093           0 :         mpd_seterror(result, MPD_Invalid_operation, status);
    8094           0 :         return;
    8095             :     }
    8096             : 
    8097           0 :     if (!mpd_qresize(result, rlen, status)) {
    8098           0 :         return;
    8099             :     }
    8100             : 
    8101             : #ifdef CONFIG_64
    8102             :     n = _coeff_from_smaller_base(result, rlen, MPD_RADIX,
    8103             :                                  srcdata, srclen, srcbase,
    8104             :                                  status);
    8105             : #else
    8106           0 :     if (srcbase == MPD_RADIX) {
    8107           0 :         if (!mpd_qresize(result, srclen, status)) {
    8108           0 :             return;
    8109             :         }
    8110           0 :         memcpy(result->data, srcdata, srclen * (sizeof *srcdata));
    8111           0 :         n = srclen;
    8112             :     }
    8113           0 :     else if (srcbase < MPD_RADIX) {
    8114           0 :         n = _coeff_from_smaller_base(result, rlen, MPD_RADIX,
    8115             :                                      srcdata, srclen, srcbase,
    8116             :                                      status);
    8117             :     }
    8118             :     else {
    8119           0 :         mpd_uint_t *usrc = mpd_alloc((mpd_size_t)srclen, sizeof *usrc);
    8120           0 :         if (usrc == NULL) {
    8121           0 :             mpd_seterror(result, MPD_Malloc_error, status);
    8122           0 :             return;
    8123             :         }
    8124           0 :         for (n = 0; n < srclen; n++) {
    8125           0 :             usrc[n] = srcdata[n];
    8126             :         }
    8127             : 
    8128           0 :         n = _coeff_from_larger_base(result, rlen, MPD_RADIX,
    8129             :                                     usrc, (mpd_ssize_t)srclen, srcbase,
    8130             :                                     status);
    8131           0 :         mpd_free(usrc);
    8132             :     }
    8133             : #endif
    8134             : 
    8135           0 :     if (n == SIZE_MAX) {
    8136           0 :         return;
    8137             :     }
    8138             : 
    8139           0 :     mpd_set_flags(result, srcsign);
    8140           0 :     result->exp = 0;
    8141           0 :     result->len = n;
    8142           0 :     mpd_setdigits(result);
    8143             : 
    8144           0 :     mpd_qresize(result, result->len, status);
    8145           0 :     mpd_qfinalize(result, ctx, status);
    8146             : }
    8147             : 
    8148             : 
    8149             : 

Generated by: LCOV version 1.10