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