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