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