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