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