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