ยปCore Development>Code coverage>Modules/_decimal/libmpdec/mpdecimal.c

Python code coverage for Modules/_decimal/libmpdec/mpdecimal.c

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