15796c8dcSSimon Schubert /* Decimal number arithmetic module for the decNumber C Library.
2*ef5ccd6cSJohn Marino Copyright (C) 2005-2013 Free Software Foundation, Inc.
35796c8dcSSimon Schubert Contributed by IBM Corporation. Author Mike Cowlishaw.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GCC.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert GCC is free software; you can redistribute it and/or modify it under
85796c8dcSSimon Schubert the terms of the GNU General Public License as published by the Free
95796c8dcSSimon Schubert Software Foundation; either version 3, or (at your option) any later
105796c8dcSSimon Schubert version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert GCC is distributed in the hope that it will be useful, but WITHOUT ANY
135796c8dcSSimon Schubert WARRANTY; without even the implied warranty of MERCHANTABILITY or
145796c8dcSSimon Schubert FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
155796c8dcSSimon Schubert for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert Under Section 7 of GPL version 3, you are granted additional
185796c8dcSSimon Schubert permissions described in the GCC Runtime Library Exception, version
195796c8dcSSimon Schubert 3.1, as published by the Free Software Foundation.
205796c8dcSSimon Schubert
215796c8dcSSimon Schubert You should have received a copy of the GNU General Public License and
225796c8dcSSimon Schubert a copy of the GCC Runtime Library Exception along with this program;
235796c8dcSSimon Schubert see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
245796c8dcSSimon Schubert <http://www.gnu.org/licenses/>. */
255796c8dcSSimon Schubert
265796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
275796c8dcSSimon Schubert /* Decimal Number arithmetic module */
285796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
295796c8dcSSimon Schubert /* This module comprises the routines for arbitrary-precision General */
305796c8dcSSimon Schubert /* Decimal Arithmetic as defined in the specification which may be */
315796c8dcSSimon Schubert /* found on the General Decimal Arithmetic pages. It implements both */
325796c8dcSSimon Schubert /* the full ('extended') arithmetic and the simpler ('subset') */
335796c8dcSSimon Schubert /* arithmetic. */
345796c8dcSSimon Schubert /* */
355796c8dcSSimon Schubert /* Usage notes: */
365796c8dcSSimon Schubert /* */
375796c8dcSSimon Schubert /* 1. This code is ANSI C89 except: */
385796c8dcSSimon Schubert /* */
395796c8dcSSimon Schubert /* a) C99 line comments (double forward slash) are used. (Most C */
405796c8dcSSimon Schubert /* compilers accept these. If yours does not, a simple script */
415796c8dcSSimon Schubert /* can be used to convert them to ANSI C comments.) */
425796c8dcSSimon Schubert /* */
435796c8dcSSimon Schubert /* b) Types from C99 stdint.h are used. If you do not have this */
445796c8dcSSimon Schubert /* header file, see the User's Guide section of the decNumber */
455796c8dcSSimon Schubert /* documentation; this lists the necessary definitions. */
465796c8dcSSimon Schubert /* */
475796c8dcSSimon Schubert /* c) If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and */
485796c8dcSSimon Schubert /* uint64_t types may be used. To avoid these, set DECUSE64=0 */
495796c8dcSSimon Schubert /* and DECDPUN<=4 (see documentation). */
505796c8dcSSimon Schubert /* */
515796c8dcSSimon Schubert /* The code also conforms to C99 restrictions; in particular, */
525796c8dcSSimon Schubert /* strict aliasing rules are observed. */
535796c8dcSSimon Schubert /* */
545796c8dcSSimon Schubert /* 2. The decNumber format which this library uses is optimized for */
555796c8dcSSimon Schubert /* efficient processing of relatively short numbers; in particular */
565796c8dcSSimon Schubert /* it allows the use of fixed sized structures and minimizes copy */
575796c8dcSSimon Schubert /* and move operations. It does, however, support arbitrary */
585796c8dcSSimon Schubert /* precision (up to 999,999,999 digits) and arbitrary exponent */
595796c8dcSSimon Schubert /* range (Emax in the range 0 through 999,999,999 and Emin in the */
605796c8dcSSimon Schubert /* range -999,999,999 through 0). Mathematical functions (for */
615796c8dcSSimon Schubert /* example decNumberExp) as identified below are restricted more */
625796c8dcSSimon Schubert /* tightly: digits, emax, and -emin in the context must be <= */
635796c8dcSSimon Schubert /* DEC_MAX_MATH (999999), and their operand(s) must be within */
645796c8dcSSimon Schubert /* these bounds. */
655796c8dcSSimon Schubert /* */
665796c8dcSSimon Schubert /* 3. Logical functions are further restricted; their operands must */
675796c8dcSSimon Schubert /* be finite, positive, have an exponent of zero, and all digits */
685796c8dcSSimon Schubert /* must be either 0 or 1. The result will only contain digits */
695796c8dcSSimon Schubert /* which are 0 or 1 (and will have exponent=0 and a sign of 0). */
705796c8dcSSimon Schubert /* */
715796c8dcSSimon Schubert /* 4. Operands to operator functions are never modified unless they */
725796c8dcSSimon Schubert /* are also specified to be the result number (which is always */
735796c8dcSSimon Schubert /* permitted). Other than that case, operands must not overlap. */
745796c8dcSSimon Schubert /* */
755796c8dcSSimon Schubert /* 5. Error handling: the type of the error is ORed into the status */
765796c8dcSSimon Schubert /* flags in the current context (decContext structure). The */
775796c8dcSSimon Schubert /* SIGFPE signal is then raised if the corresponding trap-enabler */
785796c8dcSSimon Schubert /* flag in the decContext is set (is 1). */
795796c8dcSSimon Schubert /* */
805796c8dcSSimon Schubert /* It is the responsibility of the caller to clear the status */
815796c8dcSSimon Schubert /* flags as required. */
825796c8dcSSimon Schubert /* */
835796c8dcSSimon Schubert /* The result of any routine which returns a number will always */
845796c8dcSSimon Schubert /* be a valid number (which may be a special value, such as an */
855796c8dcSSimon Schubert /* Infinity or NaN). */
865796c8dcSSimon Schubert /* */
875796c8dcSSimon Schubert /* 6. The decNumber format is not an exchangeable concrete */
885796c8dcSSimon Schubert /* representation as it comprises fields which may be machine- */
895796c8dcSSimon Schubert /* dependent (packed or unpacked, or special length, for example). */
905796c8dcSSimon Schubert /* Canonical conversions to and from strings are provided; other */
915796c8dcSSimon Schubert /* conversions are available in separate modules. */
925796c8dcSSimon Schubert /* */
935796c8dcSSimon Schubert /* 7. Normally, input operands are assumed to be valid. Set DECCHECK */
945796c8dcSSimon Schubert /* to 1 for extended operand checking (including NULL operands). */
955796c8dcSSimon Schubert /* Results are undefined if a badly-formed structure (or a NULL */
965796c8dcSSimon Schubert /* pointer to a structure) is provided, though with DECCHECK */
975796c8dcSSimon Schubert /* enabled the operator routines are protected against exceptions. */
985796c8dcSSimon Schubert /* (Except if the result pointer is NULL, which is unrecoverable.) */
995796c8dcSSimon Schubert /* */
1005796c8dcSSimon Schubert /* However, the routines will never cause exceptions if they are */
1015796c8dcSSimon Schubert /* given well-formed operands, even if the value of the operands */
1025796c8dcSSimon Schubert /* is inappropriate for the operation and DECCHECK is not set. */
1035796c8dcSSimon Schubert /* (Except for SIGFPE, as and where documented.) */
1045796c8dcSSimon Schubert /* */
1055796c8dcSSimon Schubert /* 8. Subset arithmetic is available only if DECSUBSET is set to 1. */
1065796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
1075796c8dcSSimon Schubert /* Implementation notes for maintenance of this module: */
1085796c8dcSSimon Schubert /* */
1095796c8dcSSimon Schubert /* 1. Storage leak protection: Routines which use malloc are not */
1105796c8dcSSimon Schubert /* permitted to use return for fastpath or error exits (i.e., */
1115796c8dcSSimon Schubert /* they follow strict structured programming conventions). */
1125796c8dcSSimon Schubert /* Instead they have a do{}while(0); construct surrounding the */
1135796c8dcSSimon Schubert /* code which is protected -- break may be used to exit this. */
1145796c8dcSSimon Schubert /* Other routines can safely use the return statement inline. */
1155796c8dcSSimon Schubert /* */
1165796c8dcSSimon Schubert /* Storage leak accounting can be enabled using DECALLOC. */
1175796c8dcSSimon Schubert /* */
1185796c8dcSSimon Schubert /* 2. All loops use the for(;;) construct. Any do construct does */
1195796c8dcSSimon Schubert /* not loop; it is for allocation protection as just described. */
1205796c8dcSSimon Schubert /* */
1215796c8dcSSimon Schubert /* 3. Setting status in the context must always be the very last */
1225796c8dcSSimon Schubert /* action in a routine, as non-0 status may raise a trap and hence */
1235796c8dcSSimon Schubert /* the call to set status may not return (if the handler uses long */
1245796c8dcSSimon Schubert /* jump). Therefore all cleanup must be done first. In general, */
1255796c8dcSSimon Schubert /* to achieve this status is accumulated and is only applied just */
1265796c8dcSSimon Schubert /* before return by calling decContextSetStatus (via decStatus). */
1275796c8dcSSimon Schubert /* */
1285796c8dcSSimon Schubert /* Routines which allocate storage cannot, in general, use the */
1295796c8dcSSimon Schubert /* 'top level' routines which could cause a non-returning */
1305796c8dcSSimon Schubert /* transfer of control. The decXxxxOp routines are safe (do not */
1315796c8dcSSimon Schubert /* call decStatus even if traps are set in the context) and should */
1325796c8dcSSimon Schubert /* be used instead (they are also a little faster). */
1335796c8dcSSimon Schubert /* */
1345796c8dcSSimon Schubert /* 4. Exponent checking is minimized by allowing the exponent to */
1355796c8dcSSimon Schubert /* grow outside its limits during calculations, provided that */
1365796c8dcSSimon Schubert /* the decFinalize function is called later. Multiplication and */
1375796c8dcSSimon Schubert /* division, and intermediate calculations in exponentiation, */
1385796c8dcSSimon Schubert /* require more careful checks because of the risk of 31-bit */
1395796c8dcSSimon Schubert /* overflow (the most negative valid exponent is -1999999997, for */
1405796c8dcSSimon Schubert /* a 999999999-digit number with adjusted exponent of -999999999). */
1415796c8dcSSimon Schubert /* */
1425796c8dcSSimon Schubert /* 5. Rounding is deferred until finalization of results, with any */
1435796c8dcSSimon Schubert /* 'off to the right' data being represented as a single digit */
1445796c8dcSSimon Schubert /* residue (in the range -1 through 9). This avoids any double- */
1455796c8dcSSimon Schubert /* rounding when more than one shortening takes place (for */
1465796c8dcSSimon Schubert /* example, when a result is subnormal). */
1475796c8dcSSimon Schubert /* */
1485796c8dcSSimon Schubert /* 6. The digits count is allowed to rise to a multiple of DECDPUN */
1495796c8dcSSimon Schubert /* during many operations, so whole Units are handled and exact */
1505796c8dcSSimon Schubert /* accounting of digits is not needed. The correct digits value */
1515796c8dcSSimon Schubert /* is found by decGetDigits, which accounts for leading zeros. */
1525796c8dcSSimon Schubert /* This must be called before any rounding if the number of digits */
1535796c8dcSSimon Schubert /* is not known exactly. */
1545796c8dcSSimon Schubert /* */
1555796c8dcSSimon Schubert /* 7. The multiply-by-reciprocal 'trick' is used for partitioning */
1565796c8dcSSimon Schubert /* numbers up to four digits, using appropriate constants. This */
1575796c8dcSSimon Schubert /* is not useful for longer numbers because overflow of 32 bits */
1585796c8dcSSimon Schubert /* would lead to 4 multiplies, which is almost as expensive as */
1595796c8dcSSimon Schubert /* a divide (unless a floating-point or 64-bit multiply is */
1605796c8dcSSimon Schubert /* assumed to be available). */
1615796c8dcSSimon Schubert /* */
1625796c8dcSSimon Schubert /* 8. Unusual abbreviations that may be used in the commentary: */
1635796c8dcSSimon Schubert /* lhs -- left hand side (operand, of an operation) */
1645796c8dcSSimon Schubert /* lsd -- least significant digit (of coefficient) */
1655796c8dcSSimon Schubert /* lsu -- least significant Unit (of coefficient) */
1665796c8dcSSimon Schubert /* msd -- most significant digit (of coefficient) */
1675796c8dcSSimon Schubert /* msi -- most significant item (in an array) */
1685796c8dcSSimon Schubert /* msu -- most significant Unit (of coefficient) */
1695796c8dcSSimon Schubert /* rhs -- right hand side (operand, of an operation) */
1705796c8dcSSimon Schubert /* +ve -- positive */
1715796c8dcSSimon Schubert /* -ve -- negative */
1725796c8dcSSimon Schubert /* ** -- raise to the power */
1735796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
1745796c8dcSSimon Schubert
1755796c8dcSSimon Schubert #include <stdlib.h> /* for malloc, free, etc. */
1765796c8dcSSimon Schubert #include <stdio.h> /* for printf [if needed] */
1775796c8dcSSimon Schubert #include <string.h> /* for strcpy */
1785796c8dcSSimon Schubert #include <ctype.h> /* for lower */
1795796c8dcSSimon Schubert #include "dconfig.h" /* for GCC definitions */
1805796c8dcSSimon Schubert #include "decNumber.h" /* base number library */
1815796c8dcSSimon Schubert #include "decNumberLocal.h" /* decNumber local types, etc. */
1825796c8dcSSimon Schubert
1835796c8dcSSimon Schubert /* Constants */
1845796c8dcSSimon Schubert /* Public lookup table used by the D2U macro */
1855796c8dcSSimon Schubert const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
1865796c8dcSSimon Schubert
1875796c8dcSSimon Schubert #define DECVERB 1 /* set to 1 for verbose DECCHECK */
1885796c8dcSSimon Schubert #define powers DECPOWERS /* old internal name */
1895796c8dcSSimon Schubert
1905796c8dcSSimon Schubert /* Local constants */
1915796c8dcSSimon Schubert #define DIVIDE 0x80 /* Divide operators */
1925796c8dcSSimon Schubert #define REMAINDER 0x40 /* .. */
1935796c8dcSSimon Schubert #define DIVIDEINT 0x20 /* .. */
1945796c8dcSSimon Schubert #define REMNEAR 0x10 /* .. */
1955796c8dcSSimon Schubert #define COMPARE 0x01 /* Compare operators */
1965796c8dcSSimon Schubert #define COMPMAX 0x02 /* .. */
1975796c8dcSSimon Schubert #define COMPMIN 0x03 /* .. */
1985796c8dcSSimon Schubert #define COMPTOTAL 0x04 /* .. */
1995796c8dcSSimon Schubert #define COMPNAN 0x05 /* .. [NaN processing] */
2005796c8dcSSimon Schubert #define COMPSIG 0x06 /* .. [signaling COMPARE] */
2015796c8dcSSimon Schubert #define COMPMAXMAG 0x07 /* .. */
2025796c8dcSSimon Schubert #define COMPMINMAG 0x08 /* .. */
2035796c8dcSSimon Schubert
2045796c8dcSSimon Schubert #define DEC_sNaN 0x40000000 /* local status: sNaN signal */
2055796c8dcSSimon Schubert #define BADINT (Int)0x80000000 /* most-negative Int; error indicator */
2065796c8dcSSimon Schubert /* Next two indicate an integer >= 10**6, and its parity (bottom bit) */
2075796c8dcSSimon Schubert #define BIGEVEN (Int)0x80000002
2085796c8dcSSimon Schubert #define BIGODD (Int)0x80000003
2095796c8dcSSimon Schubert
2105796c8dcSSimon Schubert static Unit uarrone[1]={1}; /* Unit array of 1, used for incrementing */
2115796c8dcSSimon Schubert
2125796c8dcSSimon Schubert /* Granularity-dependent code */
2135796c8dcSSimon Schubert #if DECDPUN<=4
2145796c8dcSSimon Schubert #define eInt Int /* extended integer */
2155796c8dcSSimon Schubert #define ueInt uInt /* unsigned extended integer */
2165796c8dcSSimon Schubert /* Constant multipliers for divide-by-power-of five using reciprocal */
2175796c8dcSSimon Schubert /* multiply, after removing powers of 2 by shifting, and final shift */
2185796c8dcSSimon Schubert /* of 17 [we only need up to **4] */
2195796c8dcSSimon Schubert static const uInt multies[]={131073, 26215, 5243, 1049, 210};
2205796c8dcSSimon Schubert /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */
2215796c8dcSSimon Schubert #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
2225796c8dcSSimon Schubert #else
2235796c8dcSSimon Schubert /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */
2245796c8dcSSimon Schubert #if !DECUSE64
2255796c8dcSSimon Schubert #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4
2265796c8dcSSimon Schubert #endif
2275796c8dcSSimon Schubert #define eInt Long /* extended integer */
2285796c8dcSSimon Schubert #define ueInt uLong /* unsigned extended integer */
2295796c8dcSSimon Schubert #endif
2305796c8dcSSimon Schubert
2315796c8dcSSimon Schubert /* Local routines */
2325796c8dcSSimon Schubert static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *,
2335796c8dcSSimon Schubert decContext *, uByte, uInt *);
2345796c8dcSSimon Schubert static Flag decBiStr(const char *, const char *, const char *);
2355796c8dcSSimon Schubert static uInt decCheckMath(const decNumber *, decContext *, uInt *);
2365796c8dcSSimon Schubert static void decApplyRound(decNumber *, decContext *, Int, uInt *);
2375796c8dcSSimon Schubert static Int decCompare(const decNumber *lhs, const decNumber *rhs, Flag);
2385796c8dcSSimon Schubert static decNumber * decCompareOp(decNumber *, const decNumber *,
2395796c8dcSSimon Schubert const decNumber *, decContext *,
2405796c8dcSSimon Schubert Flag, uInt *);
2415796c8dcSSimon Schubert static void decCopyFit(decNumber *, const decNumber *, decContext *,
2425796c8dcSSimon Schubert Int *, uInt *);
2435796c8dcSSimon Schubert static decNumber * decDecap(decNumber *, Int);
2445796c8dcSSimon Schubert static decNumber * decDivideOp(decNumber *, const decNumber *,
2455796c8dcSSimon Schubert const decNumber *, decContext *, Flag, uInt *);
2465796c8dcSSimon Schubert static decNumber * decExpOp(decNumber *, const decNumber *,
2475796c8dcSSimon Schubert decContext *, uInt *);
2485796c8dcSSimon Schubert static void decFinalize(decNumber *, decContext *, Int *, uInt *);
2495796c8dcSSimon Schubert static Int decGetDigits(Unit *, Int);
2505796c8dcSSimon Schubert static Int decGetInt(const decNumber *);
2515796c8dcSSimon Schubert static decNumber * decLnOp(decNumber *, const decNumber *,
2525796c8dcSSimon Schubert decContext *, uInt *);
2535796c8dcSSimon Schubert static decNumber * decMultiplyOp(decNumber *, const decNumber *,
2545796c8dcSSimon Schubert const decNumber *, decContext *,
2555796c8dcSSimon Schubert uInt *);
2565796c8dcSSimon Schubert static decNumber * decNaNs(decNumber *, const decNumber *,
2575796c8dcSSimon Schubert const decNumber *, decContext *, uInt *);
2585796c8dcSSimon Schubert static decNumber * decQuantizeOp(decNumber *, const decNumber *,
2595796c8dcSSimon Schubert const decNumber *, decContext *, Flag,
2605796c8dcSSimon Schubert uInt *);
2615796c8dcSSimon Schubert static void decReverse(Unit *, Unit *);
2625796c8dcSSimon Schubert static void decSetCoeff(decNumber *, decContext *, const Unit *,
2635796c8dcSSimon Schubert Int, Int *, uInt *);
2645796c8dcSSimon Schubert static void decSetMaxValue(decNumber *, decContext *);
2655796c8dcSSimon Schubert static void decSetOverflow(decNumber *, decContext *, uInt *);
2665796c8dcSSimon Schubert static void decSetSubnormal(decNumber *, decContext *, Int *, uInt *);
2675796c8dcSSimon Schubert static Int decShiftToLeast(Unit *, Int, Int);
2685796c8dcSSimon Schubert static Int decShiftToMost(Unit *, Int, Int);
2695796c8dcSSimon Schubert static void decStatus(decNumber *, uInt, decContext *);
2705796c8dcSSimon Schubert static void decToString(const decNumber *, char[], Flag);
2715796c8dcSSimon Schubert static decNumber * decTrim(decNumber *, decContext *, Flag, Flag, Int *);
2725796c8dcSSimon Schubert static Int decUnitAddSub(const Unit *, Int, const Unit *, Int, Int,
2735796c8dcSSimon Schubert Unit *, Int);
2745796c8dcSSimon Schubert static Int decUnitCompare(const Unit *, Int, const Unit *, Int, Int);
2755796c8dcSSimon Schubert
2765796c8dcSSimon Schubert #if !DECSUBSET
2775796c8dcSSimon Schubert /* decFinish == decFinalize when no subset arithmetic needed */
2785796c8dcSSimon Schubert #define decFinish(a,b,c,d) decFinalize(a,b,c,d)
2795796c8dcSSimon Schubert #else
2805796c8dcSSimon Schubert static void decFinish(decNumber *, decContext *, Int *, uInt *);
2815796c8dcSSimon Schubert static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *);
2825796c8dcSSimon Schubert #endif
2835796c8dcSSimon Schubert
2845796c8dcSSimon Schubert /* Local macros */
2855796c8dcSSimon Schubert /* masked special-values bits */
2865796c8dcSSimon Schubert #define SPECIALARG (rhs->bits & DECSPECIAL)
2875796c8dcSSimon Schubert #define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL)
2885796c8dcSSimon Schubert
2895796c8dcSSimon Schubert /* Diagnostic macros, etc. */
2905796c8dcSSimon Schubert #if DECALLOC
2915796c8dcSSimon Schubert /* Handle malloc/free accounting. If enabled, our accountable routines */
2925796c8dcSSimon Schubert /* are used; otherwise the code just goes straight to the system malloc */
2935796c8dcSSimon Schubert /* and free routines. */
2945796c8dcSSimon Schubert #define malloc(a) decMalloc(a)
2955796c8dcSSimon Schubert #define free(a) decFree(a)
2965796c8dcSSimon Schubert #define DECFENCE 0x5a /* corruption detector */
2975796c8dcSSimon Schubert /* 'Our' malloc and free: */
2985796c8dcSSimon Schubert static void *decMalloc(size_t);
2995796c8dcSSimon Schubert static void decFree(void *);
3005796c8dcSSimon Schubert uInt decAllocBytes=0; /* count of bytes allocated */
3015796c8dcSSimon Schubert /* Note that DECALLOC code only checks for storage buffer overflow. */
3025796c8dcSSimon Schubert /* To check for memory leaks, the decAllocBytes variable must be */
3035796c8dcSSimon Schubert /* checked to be 0 at appropriate times (e.g., after the test */
3045796c8dcSSimon Schubert /* harness completes a set of tests). This checking may be unreliable */
3055796c8dcSSimon Schubert /* if the testing is done in a multi-thread environment. */
3065796c8dcSSimon Schubert #endif
3075796c8dcSSimon Schubert
3085796c8dcSSimon Schubert #if DECCHECK
3095796c8dcSSimon Schubert /* Optional checking routines. Enabling these means that decNumber */
3105796c8dcSSimon Schubert /* and decContext operands to operator routines are checked for */
3115796c8dcSSimon Schubert /* correctness. This roughly doubles the execution time of the */
3125796c8dcSSimon Schubert /* fastest routines (and adds 600+ bytes), so should not normally be */
3135796c8dcSSimon Schubert /* used in 'production'. */
3145796c8dcSSimon Schubert /* decCheckInexact is used to check that inexact results have a full */
3155796c8dcSSimon Schubert /* complement of digits (where appropriate -- this is not the case */
3165796c8dcSSimon Schubert /* for Quantize, for example) */
3175796c8dcSSimon Schubert #define DECUNRESU ((decNumber *)(void *)0xffffffff)
3185796c8dcSSimon Schubert #define DECUNUSED ((const decNumber *)(void *)0xffffffff)
3195796c8dcSSimon Schubert #define DECUNCONT ((decContext *)(void *)(0xffffffff))
3205796c8dcSSimon Schubert static Flag decCheckOperands(decNumber *, const decNumber *,
3215796c8dcSSimon Schubert const decNumber *, decContext *);
3225796c8dcSSimon Schubert static Flag decCheckNumber(const decNumber *);
3235796c8dcSSimon Schubert static void decCheckInexact(const decNumber *, decContext *);
3245796c8dcSSimon Schubert #endif
3255796c8dcSSimon Schubert
3265796c8dcSSimon Schubert #if DECTRACE || DECCHECK
3275796c8dcSSimon Schubert /* Optional trace/debugging routines (may or may not be used) */
3285796c8dcSSimon Schubert void decNumberShow(const decNumber *); /* displays the components of a number */
3295796c8dcSSimon Schubert static void decDumpAr(char, const Unit *, Int);
3305796c8dcSSimon Schubert #endif
3315796c8dcSSimon Schubert
3325796c8dcSSimon Schubert /* ================================================================== */
3335796c8dcSSimon Schubert /* Conversions */
3345796c8dcSSimon Schubert /* ================================================================== */
3355796c8dcSSimon Schubert
3365796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
3375796c8dcSSimon Schubert /* from-int32 -- conversion from Int or uInt */
3385796c8dcSSimon Schubert /* */
3395796c8dcSSimon Schubert /* dn is the decNumber to receive the integer */
3405796c8dcSSimon Schubert /* in or uin is the integer to be converted */
3415796c8dcSSimon Schubert /* returns dn */
3425796c8dcSSimon Schubert /* */
3435796c8dcSSimon Schubert /* No error is possible. */
3445796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberFromInt32(decNumber * dn,Int in)3455796c8dcSSimon Schubert decNumber * decNumberFromInt32(decNumber *dn, Int in) {
3465796c8dcSSimon Schubert uInt unsig;
3475796c8dcSSimon Schubert if (in>=0) unsig=in;
3485796c8dcSSimon Schubert else { /* negative (possibly BADINT) */
3495796c8dcSSimon Schubert if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */
3505796c8dcSSimon Schubert else unsig=-in; /* invert */
3515796c8dcSSimon Schubert }
3525796c8dcSSimon Schubert /* in is now positive */
3535796c8dcSSimon Schubert decNumberFromUInt32(dn, unsig);
3545796c8dcSSimon Schubert if (in<0) dn->bits=DECNEG; /* sign needed */
3555796c8dcSSimon Schubert return dn;
3565796c8dcSSimon Schubert } /* decNumberFromInt32 */
3575796c8dcSSimon Schubert
decNumberFromUInt32(decNumber * dn,uInt uin)3585796c8dcSSimon Schubert decNumber * decNumberFromUInt32(decNumber *dn, uInt uin) {
3595796c8dcSSimon Schubert Unit *up; /* work pointer */
3605796c8dcSSimon Schubert decNumberZero(dn); /* clean */
3615796c8dcSSimon Schubert if (uin==0) return dn; /* [or decGetDigits bad call] */
3625796c8dcSSimon Schubert for (up=dn->lsu; uin>0; up++) {
3635796c8dcSSimon Schubert *up=(Unit)(uin%(DECDPUNMAX+1));
3645796c8dcSSimon Schubert uin=uin/(DECDPUNMAX+1);
3655796c8dcSSimon Schubert }
3665796c8dcSSimon Schubert dn->digits=decGetDigits(dn->lsu, up-dn->lsu);
3675796c8dcSSimon Schubert return dn;
3685796c8dcSSimon Schubert } /* decNumberFromUInt32 */
3695796c8dcSSimon Schubert
3705796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
3715796c8dcSSimon Schubert /* to-int32 -- conversion to Int or uInt */
3725796c8dcSSimon Schubert /* */
3735796c8dcSSimon Schubert /* dn is the decNumber to convert */
3745796c8dcSSimon Schubert /* set is the context for reporting errors */
3755796c8dcSSimon Schubert /* returns the converted decNumber, or 0 if Invalid is set */
3765796c8dcSSimon Schubert /* */
3775796c8dcSSimon Schubert /* Invalid is set if the decNumber does not have exponent==0 or if */
3785796c8dcSSimon Schubert /* it is a NaN, Infinite, or out-of-range. */
3795796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberToInt32(const decNumber * dn,decContext * set)3805796c8dcSSimon Schubert Int decNumberToInt32(const decNumber *dn, decContext *set) {
3815796c8dcSSimon Schubert #if DECCHECK
3825796c8dcSSimon Schubert if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
3835796c8dcSSimon Schubert #endif
3845796c8dcSSimon Schubert
3855796c8dcSSimon Schubert /* special or too many digits, or bad exponent */
3865796c8dcSSimon Schubert if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */
3875796c8dcSSimon Schubert else { /* is a finite integer with 10 or fewer digits */
3885796c8dcSSimon Schubert Int d; /* work */
3895796c8dcSSimon Schubert const Unit *up; /* .. */
3905796c8dcSSimon Schubert uInt hi=0, lo; /* .. */
3915796c8dcSSimon Schubert up=dn->lsu; /* -> lsu */
3925796c8dcSSimon Schubert lo=*up; /* get 1 to 9 digits */
3935796c8dcSSimon Schubert #if DECDPUN>1 /* split to higher */
3945796c8dcSSimon Schubert hi=lo/10;
3955796c8dcSSimon Schubert lo=lo%10;
3965796c8dcSSimon Schubert #endif
3975796c8dcSSimon Schubert up++;
3985796c8dcSSimon Schubert /* collect remaining Units, if any, into hi */
3995796c8dcSSimon Schubert for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
4005796c8dcSSimon Schubert /* now low has the lsd, hi the remainder */
4015796c8dcSSimon Schubert if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */
4025796c8dcSSimon Schubert /* most-negative is a reprieve */
4035796c8dcSSimon Schubert if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000;
4045796c8dcSSimon Schubert /* bad -- drop through */
4055796c8dcSSimon Schubert }
4065796c8dcSSimon Schubert else { /* in-range always */
4075796c8dcSSimon Schubert Int i=X10(hi)+lo;
4085796c8dcSSimon Schubert if (dn->bits&DECNEG) return -i;
4095796c8dcSSimon Schubert return i;
4105796c8dcSSimon Schubert }
4115796c8dcSSimon Schubert } /* integer */
4125796c8dcSSimon Schubert decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
4135796c8dcSSimon Schubert return 0;
4145796c8dcSSimon Schubert } /* decNumberToInt32 */
4155796c8dcSSimon Schubert
decNumberToUInt32(const decNumber * dn,decContext * set)4165796c8dcSSimon Schubert uInt decNumberToUInt32(const decNumber *dn, decContext *set) {
4175796c8dcSSimon Schubert #if DECCHECK
4185796c8dcSSimon Schubert if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
4195796c8dcSSimon Schubert #endif
4205796c8dcSSimon Schubert /* special or too many digits, or bad exponent, or negative (<0) */
4215796c8dcSSimon Schubert if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0
4225796c8dcSSimon Schubert || (dn->bits&DECNEG && !ISZERO(dn))); /* bad */
4235796c8dcSSimon Schubert else { /* is a finite integer with 10 or fewer digits */
4245796c8dcSSimon Schubert Int d; /* work */
4255796c8dcSSimon Schubert const Unit *up; /* .. */
4265796c8dcSSimon Schubert uInt hi=0, lo; /* .. */
4275796c8dcSSimon Schubert up=dn->lsu; /* -> lsu */
4285796c8dcSSimon Schubert lo=*up; /* get 1 to 9 digits */
4295796c8dcSSimon Schubert #if DECDPUN>1 /* split to higher */
4305796c8dcSSimon Schubert hi=lo/10;
4315796c8dcSSimon Schubert lo=lo%10;
4325796c8dcSSimon Schubert #endif
4335796c8dcSSimon Schubert up++;
4345796c8dcSSimon Schubert /* collect remaining Units, if any, into hi */
4355796c8dcSSimon Schubert for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
4365796c8dcSSimon Schubert
4375796c8dcSSimon Schubert /* now low has the lsd, hi the remainder */
4385796c8dcSSimon Schubert if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */
4395796c8dcSSimon Schubert else return X10(hi)+lo;
4405796c8dcSSimon Schubert } /* integer */
4415796c8dcSSimon Schubert decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
4425796c8dcSSimon Schubert return 0;
4435796c8dcSSimon Schubert } /* decNumberToUInt32 */
4445796c8dcSSimon Schubert
4455796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4465796c8dcSSimon Schubert /* to-scientific-string -- conversion to numeric string */
4475796c8dcSSimon Schubert /* to-engineering-string -- conversion to numeric string */
4485796c8dcSSimon Schubert /* */
4495796c8dcSSimon Schubert /* decNumberToString(dn, string); */
4505796c8dcSSimon Schubert /* decNumberToEngString(dn, string); */
4515796c8dcSSimon Schubert /* */
4525796c8dcSSimon Schubert /* dn is the decNumber to convert */
4535796c8dcSSimon Schubert /* string is the string where the result will be laid out */
4545796c8dcSSimon Schubert /* */
4555796c8dcSSimon Schubert /* string must be at least dn->digits+14 characters long */
4565796c8dcSSimon Schubert /* */
4575796c8dcSSimon Schubert /* No error is possible, and no status can be set. */
4585796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberToString(const decNumber * dn,char * string)4595796c8dcSSimon Schubert char * decNumberToString(const decNumber *dn, char *string){
4605796c8dcSSimon Schubert decToString(dn, string, 0);
4615796c8dcSSimon Schubert return string;
4625796c8dcSSimon Schubert } /* DecNumberToString */
4635796c8dcSSimon Schubert
decNumberToEngString(const decNumber * dn,char * string)4645796c8dcSSimon Schubert char * decNumberToEngString(const decNumber *dn, char *string){
4655796c8dcSSimon Schubert decToString(dn, string, 1);
4665796c8dcSSimon Schubert return string;
4675796c8dcSSimon Schubert } /* DecNumberToEngString */
4685796c8dcSSimon Schubert
4695796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4705796c8dcSSimon Schubert /* to-number -- conversion from numeric string */
4715796c8dcSSimon Schubert /* */
4725796c8dcSSimon Schubert /* decNumberFromString -- convert string to decNumber */
4735796c8dcSSimon Schubert /* dn -- the number structure to fill */
4745796c8dcSSimon Schubert /* chars[] -- the string to convert ('\0' terminated) */
4755796c8dcSSimon Schubert /* set -- the context used for processing any error, */
4765796c8dcSSimon Schubert /* determining the maximum precision available */
4775796c8dcSSimon Schubert /* (set.digits), determining the maximum and minimum */
4785796c8dcSSimon Schubert /* exponent (set.emax and set.emin), determining if */
4795796c8dcSSimon Schubert /* extended values are allowed, and checking the */
4805796c8dcSSimon Schubert /* rounding mode if overflow occurs or rounding is */
4815796c8dcSSimon Schubert /* needed. */
4825796c8dcSSimon Schubert /* */
4835796c8dcSSimon Schubert /* The length of the coefficient and the size of the exponent are */
4845796c8dcSSimon Schubert /* checked by this routine, so the correct error (Underflow or */
4855796c8dcSSimon Schubert /* Overflow) can be reported or rounding applied, as necessary. */
4865796c8dcSSimon Schubert /* */
4875796c8dcSSimon Schubert /* If bad syntax is detected, the result will be a quiet NaN. */
4885796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberFromString(decNumber * dn,const char chars[],decContext * set)4895796c8dcSSimon Schubert decNumber * decNumberFromString(decNumber *dn, const char chars[],
4905796c8dcSSimon Schubert decContext *set) {
4915796c8dcSSimon Schubert Int exponent=0; /* working exponent [assume 0] */
4925796c8dcSSimon Schubert uByte bits=0; /* working flags [assume +ve] */
4935796c8dcSSimon Schubert Unit *res; /* where result will be built */
4945796c8dcSSimon Schubert Unit resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */
4955796c8dcSSimon Schubert /* [+9 allows for ln() constants] */
4965796c8dcSSimon Schubert Unit *allocres=NULL; /* -> allocated result, iff allocated */
4975796c8dcSSimon Schubert Int d=0; /* count of digits found in decimal part */
4985796c8dcSSimon Schubert const char *dotchar=NULL; /* where dot was found */
4995796c8dcSSimon Schubert const char *cfirst=chars; /* -> first character of decimal part */
5005796c8dcSSimon Schubert const char *last=NULL; /* -> last digit of decimal part */
5015796c8dcSSimon Schubert const char *c; /* work */
5025796c8dcSSimon Schubert Unit *up; /* .. */
5035796c8dcSSimon Schubert #if DECDPUN>1
5045796c8dcSSimon Schubert Int cut, out; /* .. */
5055796c8dcSSimon Schubert #endif
5065796c8dcSSimon Schubert Int residue; /* rounding residue */
5075796c8dcSSimon Schubert uInt status=0; /* error code */
5085796c8dcSSimon Schubert
5095796c8dcSSimon Schubert #if DECCHECK
5105796c8dcSSimon Schubert if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set))
5115796c8dcSSimon Schubert return decNumberZero(dn);
5125796c8dcSSimon Schubert #endif
5135796c8dcSSimon Schubert
5145796c8dcSSimon Schubert do { /* status & malloc protection */
5155796c8dcSSimon Schubert for (c=chars;; c++) { /* -> input character */
5165796c8dcSSimon Schubert if (*c>='0' && *c<='9') { /* test for Arabic digit */
5175796c8dcSSimon Schubert last=c;
5185796c8dcSSimon Schubert d++; /* count of real digits */
5195796c8dcSSimon Schubert continue; /* still in decimal part */
5205796c8dcSSimon Schubert }
5215796c8dcSSimon Schubert if (*c=='.' && dotchar==NULL) { /* first '.' */
5225796c8dcSSimon Schubert dotchar=c; /* record offset into decimal part */
5235796c8dcSSimon Schubert if (c==cfirst) cfirst++; /* first digit must follow */
5245796c8dcSSimon Schubert continue;}
5255796c8dcSSimon Schubert if (c==chars) { /* first in string... */
5265796c8dcSSimon Schubert if (*c=='-') { /* valid - sign */
5275796c8dcSSimon Schubert cfirst++;
5285796c8dcSSimon Schubert bits=DECNEG;
5295796c8dcSSimon Schubert continue;}
5305796c8dcSSimon Schubert if (*c=='+') { /* valid + sign */
5315796c8dcSSimon Schubert cfirst++;
5325796c8dcSSimon Schubert continue;}
5335796c8dcSSimon Schubert }
5345796c8dcSSimon Schubert /* *c is not a digit, or a valid +, -, or '.' */
5355796c8dcSSimon Schubert break;
5365796c8dcSSimon Schubert } /* c */
5375796c8dcSSimon Schubert
5385796c8dcSSimon Schubert if (last==NULL) { /* no digits yet */
5395796c8dcSSimon Schubert status=DEC_Conversion_syntax;/* assume the worst */
5405796c8dcSSimon Schubert if (*c=='\0') break; /* and no more to come... */
5415796c8dcSSimon Schubert #if DECSUBSET
5425796c8dcSSimon Schubert /* if subset then infinities and NaNs are not allowed */
5435796c8dcSSimon Schubert if (!set->extended) break; /* hopeless */
5445796c8dcSSimon Schubert #endif
5455796c8dcSSimon Schubert /* Infinities and NaNs are possible, here */
5465796c8dcSSimon Schubert if (dotchar!=NULL) break; /* .. unless had a dot */
5475796c8dcSSimon Schubert decNumberZero(dn); /* be optimistic */
5485796c8dcSSimon Schubert if (decBiStr(c, "infinity", "INFINITY")
5495796c8dcSSimon Schubert || decBiStr(c, "inf", "INF")) {
5505796c8dcSSimon Schubert dn->bits=bits | DECINF;
5515796c8dcSSimon Schubert status=0; /* is OK */
5525796c8dcSSimon Schubert break; /* all done */
5535796c8dcSSimon Schubert }
5545796c8dcSSimon Schubert /* a NaN expected */
5555796c8dcSSimon Schubert /* 2003.09.10 NaNs are now permitted to have a sign */
5565796c8dcSSimon Schubert dn->bits=bits | DECNAN; /* assume simple NaN */
5575796c8dcSSimon Schubert if (*c=='s' || *c=='S') { /* looks like an sNaN */
5585796c8dcSSimon Schubert c++;
5595796c8dcSSimon Schubert dn->bits=bits | DECSNAN;
5605796c8dcSSimon Schubert }
5615796c8dcSSimon Schubert if (*c!='n' && *c!='N') break; /* check caseless "NaN" */
5625796c8dcSSimon Schubert c++;
5635796c8dcSSimon Schubert if (*c!='a' && *c!='A') break; /* .. */
5645796c8dcSSimon Schubert c++;
5655796c8dcSSimon Schubert if (*c!='n' && *c!='N') break; /* .. */
5665796c8dcSSimon Schubert c++;
5675796c8dcSSimon Schubert /* now either nothing, or nnnn payload, expected */
5685796c8dcSSimon Schubert /* -> start of integer and skip leading 0s [including plain 0] */
5695796c8dcSSimon Schubert for (cfirst=c; *cfirst=='0';) cfirst++;
5705796c8dcSSimon Schubert if (*cfirst=='\0') { /* "NaN" or "sNaN", maybe with all 0s */
5715796c8dcSSimon Schubert status=0; /* it's good */
5725796c8dcSSimon Schubert break; /* .. */
5735796c8dcSSimon Schubert }
5745796c8dcSSimon Schubert /* something other than 0s; setup last and d as usual [no dots] */
5755796c8dcSSimon Schubert for (c=cfirst;; c++, d++) {
5765796c8dcSSimon Schubert if (*c<'0' || *c>'9') break; /* test for Arabic digit */
5775796c8dcSSimon Schubert last=c;
5785796c8dcSSimon Schubert }
5795796c8dcSSimon Schubert if (*c!='\0') break; /* not all digits */
5805796c8dcSSimon Schubert if (d>set->digits-1) {
5815796c8dcSSimon Schubert /* [NB: payload in a decNumber can be full length unless */
5825796c8dcSSimon Schubert /* clamped, in which case can only be digits-1] */
5835796c8dcSSimon Schubert if (set->clamp) break;
5845796c8dcSSimon Schubert if (d>set->digits) break;
5855796c8dcSSimon Schubert } /* too many digits? */
5865796c8dcSSimon Schubert /* good; drop through to convert the integer to coefficient */
5875796c8dcSSimon Schubert status=0; /* syntax is OK */
5885796c8dcSSimon Schubert bits=dn->bits; /* for copy-back */
5895796c8dcSSimon Schubert } /* last==NULL */
5905796c8dcSSimon Schubert
5915796c8dcSSimon Schubert else if (*c!='\0') { /* more to process... */
5925796c8dcSSimon Schubert /* had some digits; exponent is only valid sequence now */
5935796c8dcSSimon Schubert Flag nege; /* 1=negative exponent */
5945796c8dcSSimon Schubert const char *firstexp; /* -> first significant exponent digit */
5955796c8dcSSimon Schubert status=DEC_Conversion_syntax;/* assume the worst */
5965796c8dcSSimon Schubert if (*c!='e' && *c!='E') break;
5975796c8dcSSimon Schubert /* Found 'e' or 'E' -- now process explicit exponent */
5985796c8dcSSimon Schubert /* 1998.07.11: sign no longer required */
5995796c8dcSSimon Schubert nege=0;
6005796c8dcSSimon Schubert c++; /* to (possible) sign */
6015796c8dcSSimon Schubert if (*c=='-') {nege=1; c++;}
6025796c8dcSSimon Schubert else if (*c=='+') c++;
6035796c8dcSSimon Schubert if (*c=='\0') break;
6045796c8dcSSimon Schubert
6055796c8dcSSimon Schubert for (; *c=='0' && *(c+1)!='\0';) c++; /* strip insignificant zeros */
6065796c8dcSSimon Schubert firstexp=c; /* save exponent digit place */
6075796c8dcSSimon Schubert for (; ;c++) {
6085796c8dcSSimon Schubert if (*c<'0' || *c>'9') break; /* not a digit */
6095796c8dcSSimon Schubert exponent=X10(exponent)+(Int)*c-(Int)'0';
6105796c8dcSSimon Schubert } /* c */
6115796c8dcSSimon Schubert /* if not now on a '\0', *c must not be a digit */
6125796c8dcSSimon Schubert if (*c!='\0') break;
6135796c8dcSSimon Schubert
6145796c8dcSSimon Schubert /* (this next test must be after the syntax checks) */
6155796c8dcSSimon Schubert /* if it was too long the exponent may have wrapped, so check */
6165796c8dcSSimon Schubert /* carefully and set it to a certain overflow if wrap possible */
6175796c8dcSSimon Schubert if (c>=firstexp+9+1) {
6185796c8dcSSimon Schubert if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2;
6195796c8dcSSimon Schubert /* [up to 1999999999 is OK, for example 1E-1000000998] */
6205796c8dcSSimon Schubert }
6215796c8dcSSimon Schubert if (nege) exponent=-exponent; /* was negative */
6225796c8dcSSimon Schubert status=0; /* is OK */
6235796c8dcSSimon Schubert } /* stuff after digits */
6245796c8dcSSimon Schubert
6255796c8dcSSimon Schubert /* Here when whole string has been inspected; syntax is good */
6265796c8dcSSimon Schubert /* cfirst->first digit (never dot), last->last digit (ditto) */
6275796c8dcSSimon Schubert
6285796c8dcSSimon Schubert /* strip leading zeros/dot [leave final 0 if all 0's] */
6295796c8dcSSimon Schubert if (*cfirst=='0') { /* [cfirst has stepped over .] */
6305796c8dcSSimon Schubert for (c=cfirst; c<last; c++, cfirst++) {
6315796c8dcSSimon Schubert if (*c=='.') continue; /* ignore dots */
6325796c8dcSSimon Schubert if (*c!='0') break; /* non-zero found */
6335796c8dcSSimon Schubert d--; /* 0 stripped */
6345796c8dcSSimon Schubert } /* c */
6355796c8dcSSimon Schubert #if DECSUBSET
6365796c8dcSSimon Schubert /* make a rapid exit for easy zeros if !extended */
6375796c8dcSSimon Schubert if (*cfirst=='0' && !set->extended) {
6385796c8dcSSimon Schubert decNumberZero(dn); /* clean result */
6395796c8dcSSimon Schubert break; /* [could be return] */
6405796c8dcSSimon Schubert }
6415796c8dcSSimon Schubert #endif
6425796c8dcSSimon Schubert } /* at least one leading 0 */
6435796c8dcSSimon Schubert
6445796c8dcSSimon Schubert /* Handle decimal point... */
6455796c8dcSSimon Schubert if (dotchar!=NULL && dotchar<last) /* non-trailing '.' found? */
6465796c8dcSSimon Schubert exponent-=(last-dotchar); /* adjust exponent */
6475796c8dcSSimon Schubert /* [we can now ignore the .] */
6485796c8dcSSimon Schubert
6495796c8dcSSimon Schubert /* OK, the digits string is good. Assemble in the decNumber, or in */
6505796c8dcSSimon Schubert /* a temporary units array if rounding is needed */
6515796c8dcSSimon Schubert if (d<=set->digits) res=dn->lsu; /* fits into supplied decNumber */
6525796c8dcSSimon Schubert else { /* rounding needed */
6535796c8dcSSimon Schubert Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */
6545796c8dcSSimon Schubert res=resbuff; /* assume use local buffer */
6555796c8dcSSimon Schubert if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */
6565796c8dcSSimon Schubert allocres=(Unit *)malloc(needbytes);
6575796c8dcSSimon Schubert if (allocres==NULL) {status|=DEC_Insufficient_storage; break;}
6585796c8dcSSimon Schubert res=allocres;
6595796c8dcSSimon Schubert }
6605796c8dcSSimon Schubert }
6615796c8dcSSimon Schubert /* res now -> number lsu, buffer, or allocated storage for Unit array */
6625796c8dcSSimon Schubert
6635796c8dcSSimon Schubert /* Place the coefficient into the selected Unit array */
6645796c8dcSSimon Schubert /* [this is often 70% of the cost of this function when DECDPUN>1] */
6655796c8dcSSimon Schubert #if DECDPUN>1
6665796c8dcSSimon Schubert out=0; /* accumulator */
6675796c8dcSSimon Schubert up=res+D2U(d)-1; /* -> msu */
6685796c8dcSSimon Schubert cut=d-(up-res)*DECDPUN; /* digits in top unit */
6695796c8dcSSimon Schubert for (c=cfirst;; c++) { /* along the digits */
6705796c8dcSSimon Schubert if (*c=='.') continue; /* ignore '.' [don't decrement cut] */
6715796c8dcSSimon Schubert out=X10(out)+(Int)*c-(Int)'0';
6725796c8dcSSimon Schubert if (c==last) break; /* done [never get to trailing '.'] */
6735796c8dcSSimon Schubert cut--;
6745796c8dcSSimon Schubert if (cut>0) continue; /* more for this unit */
6755796c8dcSSimon Schubert *up=(Unit)out; /* write unit */
6765796c8dcSSimon Schubert up--; /* prepare for unit below.. */
6775796c8dcSSimon Schubert cut=DECDPUN; /* .. */
6785796c8dcSSimon Schubert out=0; /* .. */
6795796c8dcSSimon Schubert } /* c */
6805796c8dcSSimon Schubert *up=(Unit)out; /* write lsu */
6815796c8dcSSimon Schubert
6825796c8dcSSimon Schubert #else
6835796c8dcSSimon Schubert /* DECDPUN==1 */
6845796c8dcSSimon Schubert up=res; /* -> lsu */
6855796c8dcSSimon Schubert for (c=last; c>=cfirst; c--) { /* over each character, from least */
6865796c8dcSSimon Schubert if (*c=='.') continue; /* ignore . [don't step up] */
6875796c8dcSSimon Schubert *up=(Unit)((Int)*c-(Int)'0');
6885796c8dcSSimon Schubert up++;
6895796c8dcSSimon Schubert } /* c */
6905796c8dcSSimon Schubert #endif
6915796c8dcSSimon Schubert
6925796c8dcSSimon Schubert dn->bits=bits;
6935796c8dcSSimon Schubert dn->exponent=exponent;
6945796c8dcSSimon Schubert dn->digits=d;
6955796c8dcSSimon Schubert
6965796c8dcSSimon Schubert /* if not in number (too long) shorten into the number */
6975796c8dcSSimon Schubert if (d>set->digits) {
6985796c8dcSSimon Schubert residue=0;
6995796c8dcSSimon Schubert decSetCoeff(dn, set, res, d, &residue, &status);
7005796c8dcSSimon Schubert /* always check for overflow or subnormal and round as needed */
7015796c8dcSSimon Schubert decFinalize(dn, set, &residue, &status);
7025796c8dcSSimon Schubert }
7035796c8dcSSimon Schubert else { /* no rounding, but may still have overflow or subnormal */
7045796c8dcSSimon Schubert /* [these tests are just for performance; finalize repeats them] */
7055796c8dcSSimon Schubert if ((dn->exponent-1<set->emin-dn->digits)
7065796c8dcSSimon Schubert || (dn->exponent-1>set->emax-set->digits)) {
7075796c8dcSSimon Schubert residue=0;
7085796c8dcSSimon Schubert decFinalize(dn, set, &residue, &status);
7095796c8dcSSimon Schubert }
7105796c8dcSSimon Schubert }
7115796c8dcSSimon Schubert /* decNumberShow(dn); */
7125796c8dcSSimon Schubert } while(0); /* [for break] */
7135796c8dcSSimon Schubert
714a45ae5f8SJohn Marino free(allocres); /* drop any storage used */
7155796c8dcSSimon Schubert if (status!=0) decStatus(dn, status, set);
7165796c8dcSSimon Schubert return dn;
7175796c8dcSSimon Schubert } /* decNumberFromString */
7185796c8dcSSimon Schubert
7195796c8dcSSimon Schubert /* ================================================================== */
7205796c8dcSSimon Schubert /* Operators */
7215796c8dcSSimon Schubert /* ================================================================== */
7225796c8dcSSimon Schubert
7235796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
7245796c8dcSSimon Schubert /* decNumberAbs -- absolute value operator */
7255796c8dcSSimon Schubert /* */
7265796c8dcSSimon Schubert /* This computes C = abs(A) */
7275796c8dcSSimon Schubert /* */
7285796c8dcSSimon Schubert /* res is C, the result. C may be A */
7295796c8dcSSimon Schubert /* rhs is A */
7305796c8dcSSimon Schubert /* set is the context */
7315796c8dcSSimon Schubert /* */
7325796c8dcSSimon Schubert /* See also decNumberCopyAbs for a quiet bitwise version of this. */
7335796c8dcSSimon Schubert /* C must have space for set->digits digits. */
7345796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
7355796c8dcSSimon Schubert /* This has the same effect as decNumberPlus unless A is negative, */
7365796c8dcSSimon Schubert /* in which case it has the same effect as decNumberMinus. */
7375796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberAbs(decNumber * res,const decNumber * rhs,decContext * set)7385796c8dcSSimon Schubert decNumber * decNumberAbs(decNumber *res, const decNumber *rhs,
7395796c8dcSSimon Schubert decContext *set) {
7405796c8dcSSimon Schubert decNumber dzero; /* for 0 */
7415796c8dcSSimon Schubert uInt status=0; /* accumulator */
7425796c8dcSSimon Schubert
7435796c8dcSSimon Schubert #if DECCHECK
7445796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
7455796c8dcSSimon Schubert #endif
7465796c8dcSSimon Schubert
7475796c8dcSSimon Schubert decNumberZero(&dzero); /* set 0 */
7485796c8dcSSimon Schubert dzero.exponent=rhs->exponent; /* [no coefficient expansion] */
7495796c8dcSSimon Schubert decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status);
7505796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
7515796c8dcSSimon Schubert #if DECCHECK
7525796c8dcSSimon Schubert decCheckInexact(res, set);
7535796c8dcSSimon Schubert #endif
7545796c8dcSSimon Schubert return res;
7555796c8dcSSimon Schubert } /* decNumberAbs */
7565796c8dcSSimon Schubert
7575796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
7585796c8dcSSimon Schubert /* decNumberAdd -- add two Numbers */
7595796c8dcSSimon Schubert /* */
7605796c8dcSSimon Schubert /* This computes C = A + B */
7615796c8dcSSimon Schubert /* */
7625796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
7635796c8dcSSimon Schubert /* lhs is A */
7645796c8dcSSimon Schubert /* rhs is B */
7655796c8dcSSimon Schubert /* set is the context */
7665796c8dcSSimon Schubert /* */
7675796c8dcSSimon Schubert /* C must have space for set->digits digits. */
7685796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
7695796c8dcSSimon Schubert /* This just calls the routine shared with Subtract */
decNumberAdd(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)7705796c8dcSSimon Schubert decNumber * decNumberAdd(decNumber *res, const decNumber *lhs,
7715796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
7725796c8dcSSimon Schubert uInt status=0; /* accumulator */
7735796c8dcSSimon Schubert decAddOp(res, lhs, rhs, set, 0, &status);
7745796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
7755796c8dcSSimon Schubert #if DECCHECK
7765796c8dcSSimon Schubert decCheckInexact(res, set);
7775796c8dcSSimon Schubert #endif
7785796c8dcSSimon Schubert return res;
7795796c8dcSSimon Schubert } /* decNumberAdd */
7805796c8dcSSimon Schubert
7815796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
7825796c8dcSSimon Schubert /* decNumberAnd -- AND two Numbers, digitwise */
7835796c8dcSSimon Schubert /* */
7845796c8dcSSimon Schubert /* This computes C = A & B */
7855796c8dcSSimon Schubert /* */
7865796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X&X) */
7875796c8dcSSimon Schubert /* lhs is A */
7885796c8dcSSimon Schubert /* rhs is B */
7895796c8dcSSimon Schubert /* set is the context (used for result length and error report) */
7905796c8dcSSimon Schubert /* */
7915796c8dcSSimon Schubert /* C must have space for set->digits digits. */
7925796c8dcSSimon Schubert /* */
7935796c8dcSSimon Schubert /* Logical function restrictions apply (see above); a NaN is */
7945796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
7955796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberAnd(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)7965796c8dcSSimon Schubert decNumber * decNumberAnd(decNumber *res, const decNumber *lhs,
7975796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
7985796c8dcSSimon Schubert const Unit *ua, *ub; /* -> operands */
7995796c8dcSSimon Schubert const Unit *msua, *msub; /* -> operand msus */
8005796c8dcSSimon Schubert Unit *uc, *msuc; /* -> result and its msu */
8015796c8dcSSimon Schubert Int msudigs; /* digits in res msu */
8025796c8dcSSimon Schubert #if DECCHECK
8035796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
8045796c8dcSSimon Schubert #endif
8055796c8dcSSimon Schubert
8065796c8dcSSimon Schubert if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
8075796c8dcSSimon Schubert || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
8085796c8dcSSimon Schubert decStatus(res, DEC_Invalid_operation, set);
8095796c8dcSSimon Schubert return res;
8105796c8dcSSimon Schubert }
8115796c8dcSSimon Schubert
8125796c8dcSSimon Schubert /* operands are valid */
8135796c8dcSSimon Schubert ua=lhs->lsu; /* bottom-up */
8145796c8dcSSimon Schubert ub=rhs->lsu; /* .. */
8155796c8dcSSimon Schubert uc=res->lsu; /* .. */
8165796c8dcSSimon Schubert msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */
8175796c8dcSSimon Schubert msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */
8185796c8dcSSimon Schubert msuc=uc+D2U(set->digits)-1; /* -> msu of result */
8195796c8dcSSimon Schubert msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */
8205796c8dcSSimon Schubert for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
8215796c8dcSSimon Schubert Unit a, b; /* extract units */
8225796c8dcSSimon Schubert if (ua>msua) a=0;
8235796c8dcSSimon Schubert else a=*ua;
8245796c8dcSSimon Schubert if (ub>msub) b=0;
8255796c8dcSSimon Schubert else b=*ub;
8265796c8dcSSimon Schubert *uc=0; /* can now write back */
8275796c8dcSSimon Schubert if (a|b) { /* maybe 1 bits to examine */
8285796c8dcSSimon Schubert Int i, j;
8295796c8dcSSimon Schubert *uc=0; /* can now write back */
8305796c8dcSSimon Schubert /* This loop could be unrolled and/or use BIN2BCD tables */
8315796c8dcSSimon Schubert for (i=0; i<DECDPUN; i++) {
8325796c8dcSSimon Schubert if (a&b&1) *uc=*uc+(Unit)powers[i]; /* effect AND */
8335796c8dcSSimon Schubert j=a%10;
8345796c8dcSSimon Schubert a=a/10;
8355796c8dcSSimon Schubert j|=b%10;
8365796c8dcSSimon Schubert b=b/10;
8375796c8dcSSimon Schubert if (j>1) {
8385796c8dcSSimon Schubert decStatus(res, DEC_Invalid_operation, set);
8395796c8dcSSimon Schubert return res;
8405796c8dcSSimon Schubert }
8415796c8dcSSimon Schubert if (uc==msuc && i==msudigs-1) break; /* just did final digit */
8425796c8dcSSimon Schubert } /* each digit */
8435796c8dcSSimon Schubert } /* both OK */
8445796c8dcSSimon Schubert } /* each unit */
8455796c8dcSSimon Schubert /* [here uc-1 is the msu of the result] */
8465796c8dcSSimon Schubert res->digits=decGetDigits(res->lsu, uc-res->lsu);
8475796c8dcSSimon Schubert res->exponent=0; /* integer */
8485796c8dcSSimon Schubert res->bits=0; /* sign=0 */
8495796c8dcSSimon Schubert return res; /* [no status to set] */
8505796c8dcSSimon Schubert } /* decNumberAnd */
8515796c8dcSSimon Schubert
8525796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
8535796c8dcSSimon Schubert /* decNumberCompare -- compare two Numbers */
8545796c8dcSSimon Schubert /* */
8555796c8dcSSimon Schubert /* This computes C = A ? B */
8565796c8dcSSimon Schubert /* */
8575796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
8585796c8dcSSimon Schubert /* lhs is A */
8595796c8dcSSimon Schubert /* rhs is B */
8605796c8dcSSimon Schubert /* set is the context */
8615796c8dcSSimon Schubert /* */
8625796c8dcSSimon Schubert /* C must have space for one digit (or NaN). */
8635796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberCompare(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)8645796c8dcSSimon Schubert decNumber * decNumberCompare(decNumber *res, const decNumber *lhs,
8655796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
8665796c8dcSSimon Schubert uInt status=0; /* accumulator */
8675796c8dcSSimon Schubert decCompareOp(res, lhs, rhs, set, COMPARE, &status);
8685796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
8695796c8dcSSimon Schubert return res;
8705796c8dcSSimon Schubert } /* decNumberCompare */
8715796c8dcSSimon Schubert
8725796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
8735796c8dcSSimon Schubert /* decNumberCompareSignal -- compare, signalling on all NaNs */
8745796c8dcSSimon Schubert /* */
8755796c8dcSSimon Schubert /* This computes C = A ? B */
8765796c8dcSSimon Schubert /* */
8775796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
8785796c8dcSSimon Schubert /* lhs is A */
8795796c8dcSSimon Schubert /* rhs is B */
8805796c8dcSSimon Schubert /* set is the context */
8815796c8dcSSimon Schubert /* */
8825796c8dcSSimon Schubert /* C must have space for one digit (or NaN). */
8835796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberCompareSignal(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)8845796c8dcSSimon Schubert decNumber * decNumberCompareSignal(decNumber *res, const decNumber *lhs,
8855796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
8865796c8dcSSimon Schubert uInt status=0; /* accumulator */
8875796c8dcSSimon Schubert decCompareOp(res, lhs, rhs, set, COMPSIG, &status);
8885796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
8895796c8dcSSimon Schubert return res;
8905796c8dcSSimon Schubert } /* decNumberCompareSignal */
8915796c8dcSSimon Schubert
8925796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
8935796c8dcSSimon Schubert /* decNumberCompareTotal -- compare two Numbers, using total ordering */
8945796c8dcSSimon Schubert /* */
8955796c8dcSSimon Schubert /* This computes C = A ? B, under total ordering */
8965796c8dcSSimon Schubert /* */
8975796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
8985796c8dcSSimon Schubert /* lhs is A */
8995796c8dcSSimon Schubert /* rhs is B */
9005796c8dcSSimon Schubert /* set is the context */
9015796c8dcSSimon Schubert /* */
9025796c8dcSSimon Schubert /* C must have space for one digit; the result will always be one of */
9035796c8dcSSimon Schubert /* -1, 0, or 1. */
9045796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberCompareTotal(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)9055796c8dcSSimon Schubert decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs,
9065796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
9075796c8dcSSimon Schubert uInt status=0; /* accumulator */
9085796c8dcSSimon Schubert decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
9095796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
9105796c8dcSSimon Schubert return res;
9115796c8dcSSimon Schubert } /* decNumberCompareTotal */
9125796c8dcSSimon Schubert
9135796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
9145796c8dcSSimon Schubert /* decNumberCompareTotalMag -- compare, total ordering of magnitudes */
9155796c8dcSSimon Schubert /* */
9165796c8dcSSimon Schubert /* This computes C = |A| ? |B|, under total ordering */
9175796c8dcSSimon Schubert /* */
9185796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
9195796c8dcSSimon Schubert /* lhs is A */
9205796c8dcSSimon Schubert /* rhs is B */
9215796c8dcSSimon Schubert /* set is the context */
9225796c8dcSSimon Schubert /* */
9235796c8dcSSimon Schubert /* C must have space for one digit; the result will always be one of */
9245796c8dcSSimon Schubert /* -1, 0, or 1. */
9255796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberCompareTotalMag(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)9265796c8dcSSimon Schubert decNumber * decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
9275796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
9285796c8dcSSimon Schubert uInt status=0; /* accumulator */
9295796c8dcSSimon Schubert uInt needbytes; /* for space calculations */
9305796c8dcSSimon Schubert decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */
9315796c8dcSSimon Schubert decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
9325796c8dcSSimon Schubert decNumber bufb[D2N(DECBUFFER+1)];
9335796c8dcSSimon Schubert decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */
9345796c8dcSSimon Schubert decNumber *a, *b; /* temporary pointers */
9355796c8dcSSimon Schubert
9365796c8dcSSimon Schubert #if DECCHECK
9375796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
9385796c8dcSSimon Schubert #endif
9395796c8dcSSimon Schubert
9405796c8dcSSimon Schubert do { /* protect allocated storage */
9415796c8dcSSimon Schubert /* if either is negative, take a copy and absolute */
9425796c8dcSSimon Schubert if (decNumberIsNegative(lhs)) { /* lhs<0 */
9435796c8dcSSimon Schubert a=bufa;
9445796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit);
9455796c8dcSSimon Schubert if (needbytes>sizeof(bufa)) { /* need malloc space */
9465796c8dcSSimon Schubert allocbufa=(decNumber *)malloc(needbytes);
9475796c8dcSSimon Schubert if (allocbufa==NULL) { /* hopeless -- abandon */
9485796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
9495796c8dcSSimon Schubert break;}
9505796c8dcSSimon Schubert a=allocbufa; /* use the allocated space */
9515796c8dcSSimon Schubert }
9525796c8dcSSimon Schubert decNumberCopy(a, lhs); /* copy content */
9535796c8dcSSimon Schubert a->bits&=~DECNEG; /* .. and clear the sign */
9545796c8dcSSimon Schubert lhs=a; /* use copy from here on */
9555796c8dcSSimon Schubert }
9565796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) { /* rhs<0 */
9575796c8dcSSimon Schubert b=bufb;
9585796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
9595796c8dcSSimon Schubert if (needbytes>sizeof(bufb)) { /* need malloc space */
9605796c8dcSSimon Schubert allocbufb=(decNumber *)malloc(needbytes);
9615796c8dcSSimon Schubert if (allocbufb==NULL) { /* hopeless -- abandon */
9625796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
9635796c8dcSSimon Schubert break;}
9645796c8dcSSimon Schubert b=allocbufb; /* use the allocated space */
9655796c8dcSSimon Schubert }
9665796c8dcSSimon Schubert decNumberCopy(b, rhs); /* copy content */
9675796c8dcSSimon Schubert b->bits&=~DECNEG; /* .. and clear the sign */
9685796c8dcSSimon Schubert rhs=b; /* use copy from here on */
9695796c8dcSSimon Schubert }
9705796c8dcSSimon Schubert decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
9715796c8dcSSimon Schubert } while(0); /* end protected */
9725796c8dcSSimon Schubert
973a45ae5f8SJohn Marino free(allocbufa); /* drop any storage used */
974a45ae5f8SJohn Marino free(allocbufb); /* .. */
9755796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
9765796c8dcSSimon Schubert return res;
9775796c8dcSSimon Schubert } /* decNumberCompareTotalMag */
9785796c8dcSSimon Schubert
9795796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
9805796c8dcSSimon Schubert /* decNumberDivide -- divide one number by another */
9815796c8dcSSimon Schubert /* */
9825796c8dcSSimon Schubert /* This computes C = A / B */
9835796c8dcSSimon Schubert /* */
9845796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X/X) */
9855796c8dcSSimon Schubert /* lhs is A */
9865796c8dcSSimon Schubert /* rhs is B */
9875796c8dcSSimon Schubert /* set is the context */
9885796c8dcSSimon Schubert /* */
9895796c8dcSSimon Schubert /* C must have space for set->digits digits. */
9905796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberDivide(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)9915796c8dcSSimon Schubert decNumber * decNumberDivide(decNumber *res, const decNumber *lhs,
9925796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
9935796c8dcSSimon Schubert uInt status=0; /* accumulator */
9945796c8dcSSimon Schubert decDivideOp(res, lhs, rhs, set, DIVIDE, &status);
9955796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
9965796c8dcSSimon Schubert #if DECCHECK
9975796c8dcSSimon Schubert decCheckInexact(res, set);
9985796c8dcSSimon Schubert #endif
9995796c8dcSSimon Schubert return res;
10005796c8dcSSimon Schubert } /* decNumberDivide */
10015796c8dcSSimon Schubert
10025796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
10035796c8dcSSimon Schubert /* decNumberDivideInteger -- divide and return integer quotient */
10045796c8dcSSimon Schubert /* */
10055796c8dcSSimon Schubert /* This computes C = A # B, where # is the integer divide operator */
10065796c8dcSSimon Schubert /* */
10075796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X#X) */
10085796c8dcSSimon Schubert /* lhs is A */
10095796c8dcSSimon Schubert /* rhs is B */
10105796c8dcSSimon Schubert /* set is the context */
10115796c8dcSSimon Schubert /* */
10125796c8dcSSimon Schubert /* C must have space for set->digits digits. */
10135796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberDivideInteger(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)10145796c8dcSSimon Schubert decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs,
10155796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
10165796c8dcSSimon Schubert uInt status=0; /* accumulator */
10175796c8dcSSimon Schubert decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status);
10185796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
10195796c8dcSSimon Schubert return res;
10205796c8dcSSimon Schubert } /* decNumberDivideInteger */
10215796c8dcSSimon Schubert
10225796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
10235796c8dcSSimon Schubert /* decNumberExp -- exponentiation */
10245796c8dcSSimon Schubert /* */
10255796c8dcSSimon Schubert /* This computes C = exp(A) */
10265796c8dcSSimon Schubert /* */
10275796c8dcSSimon Schubert /* res is C, the result. C may be A */
10285796c8dcSSimon Schubert /* rhs is A */
10295796c8dcSSimon Schubert /* set is the context; note that rounding mode has no effect */
10305796c8dcSSimon Schubert /* */
10315796c8dcSSimon Schubert /* C must have space for set->digits digits. */
10325796c8dcSSimon Schubert /* */
10335796c8dcSSimon Schubert /* Mathematical function restrictions apply (see above); a NaN is */
10345796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
10355796c8dcSSimon Schubert /* */
10365796c8dcSSimon Schubert /* Finite results will always be full precision and Inexact, except */
10375796c8dcSSimon Schubert /* when A is a zero or -Infinity (giving 1 or 0 respectively). */
10385796c8dcSSimon Schubert /* */
10395796c8dcSSimon Schubert /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
10405796c8dcSSimon Schubert /* almost always be correctly rounded, but may be up to 1 ulp in */
10415796c8dcSSimon Schubert /* error in rare cases. */
10425796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
10435796c8dcSSimon Schubert /* This is a wrapper for decExpOp which can handle the slightly wider */
10445796c8dcSSimon Schubert /* (double) range needed by Ln (which has to be able to calculate */
10455796c8dcSSimon Schubert /* exp(-a) where a can be the tiniest number (Ntiny). */
10465796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberExp(decNumber * res,const decNumber * rhs,decContext * set)10475796c8dcSSimon Schubert decNumber * decNumberExp(decNumber *res, const decNumber *rhs,
10485796c8dcSSimon Schubert decContext *set) {
10495796c8dcSSimon Schubert uInt status=0; /* accumulator */
10505796c8dcSSimon Schubert #if DECSUBSET
10515796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
10525796c8dcSSimon Schubert #endif
10535796c8dcSSimon Schubert
10545796c8dcSSimon Schubert #if DECCHECK
10555796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
10565796c8dcSSimon Schubert #endif
10575796c8dcSSimon Schubert
10585796c8dcSSimon Schubert /* Check restrictions; these restrictions ensure that if h=8 (see */
10595796c8dcSSimon Schubert /* decExpOp) then the result will either overflow or underflow to 0. */
10605796c8dcSSimon Schubert /* Other math functions restrict the input range, too, for inverses. */
10615796c8dcSSimon Schubert /* If not violated then carry out the operation. */
10625796c8dcSSimon Schubert if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
10635796c8dcSSimon Schubert #if DECSUBSET
10645796c8dcSSimon Schubert if (!set->extended) {
10655796c8dcSSimon Schubert /* reduce operand and set lostDigits status, as needed */
10665796c8dcSSimon Schubert if (rhs->digits>set->digits) {
10675796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, &status);
10685796c8dcSSimon Schubert if (allocrhs==NULL) break;
10695796c8dcSSimon Schubert rhs=allocrhs;
10705796c8dcSSimon Schubert }
10715796c8dcSSimon Schubert }
10725796c8dcSSimon Schubert #endif
10735796c8dcSSimon Schubert decExpOp(res, rhs, set, &status);
10745796c8dcSSimon Schubert } while(0); /* end protected */
10755796c8dcSSimon Schubert
10765796c8dcSSimon Schubert #if DECSUBSET
1077a45ae5f8SJohn Marino free(allocrhs); /* drop any storage used */
10785796c8dcSSimon Schubert #endif
10795796c8dcSSimon Schubert /* apply significant status */
10805796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
10815796c8dcSSimon Schubert #if DECCHECK
10825796c8dcSSimon Schubert decCheckInexact(res, set);
10835796c8dcSSimon Schubert #endif
10845796c8dcSSimon Schubert return res;
10855796c8dcSSimon Schubert } /* decNumberExp */
10865796c8dcSSimon Schubert
10875796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
10885796c8dcSSimon Schubert /* decNumberFMA -- fused multiply add */
10895796c8dcSSimon Schubert /* */
10905796c8dcSSimon Schubert /* This computes D = (A * B) + C with only one rounding */
10915796c8dcSSimon Schubert /* */
10925796c8dcSSimon Schubert /* res is D, the result. D may be A or B or C (e.g., X=FMA(X,X,X)) */
10935796c8dcSSimon Schubert /* lhs is A */
10945796c8dcSSimon Schubert /* rhs is B */
10955796c8dcSSimon Schubert /* fhs is C [far hand side] */
10965796c8dcSSimon Schubert /* set is the context */
10975796c8dcSSimon Schubert /* */
10985796c8dcSSimon Schubert /* Mathematical function restrictions apply (see above); a NaN is */
10995796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
11005796c8dcSSimon Schubert /* */
11015796c8dcSSimon Schubert /* C must have space for set->digits digits. */
11025796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberFMA(decNumber * res,const decNumber * lhs,const decNumber * rhs,const decNumber * fhs,decContext * set)11035796c8dcSSimon Schubert decNumber * decNumberFMA(decNumber *res, const decNumber *lhs,
11045796c8dcSSimon Schubert const decNumber *rhs, const decNumber *fhs,
11055796c8dcSSimon Schubert decContext *set) {
11065796c8dcSSimon Schubert uInt status=0; /* accumulator */
11075796c8dcSSimon Schubert decContext dcmul; /* context for the multiplication */
11085796c8dcSSimon Schubert uInt needbytes; /* for space calculations */
11095796c8dcSSimon Schubert decNumber bufa[D2N(DECBUFFER*2+1)];
11105796c8dcSSimon Schubert decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
11115796c8dcSSimon Schubert decNumber *acc; /* accumulator pointer */
11125796c8dcSSimon Schubert decNumber dzero; /* work */
11135796c8dcSSimon Schubert
11145796c8dcSSimon Schubert #if DECCHECK
11155796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
11165796c8dcSSimon Schubert if (decCheckOperands(res, fhs, DECUNUSED, set)) return res;
11175796c8dcSSimon Schubert #endif
11185796c8dcSSimon Schubert
11195796c8dcSSimon Schubert do { /* protect allocated storage */
11205796c8dcSSimon Schubert #if DECSUBSET
11215796c8dcSSimon Schubert if (!set->extended) { /* [undefined if subset] */
11225796c8dcSSimon Schubert status|=DEC_Invalid_operation;
11235796c8dcSSimon Schubert break;}
11245796c8dcSSimon Schubert #endif
11255796c8dcSSimon Schubert /* Check math restrictions [these ensure no overflow or underflow] */
11265796c8dcSSimon Schubert if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status))
11275796c8dcSSimon Schubert || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status))
11285796c8dcSSimon Schubert || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break;
11295796c8dcSSimon Schubert /* set up context for multiply */
11305796c8dcSSimon Schubert dcmul=*set;
11315796c8dcSSimon Schubert dcmul.digits=lhs->digits+rhs->digits; /* just enough */
11325796c8dcSSimon Schubert /* [The above may be an over-estimate for subset arithmetic, but that's OK] */
11335796c8dcSSimon Schubert dcmul.emax=DEC_MAX_EMAX; /* effectively unbounded .. */
11345796c8dcSSimon Schubert dcmul.emin=DEC_MIN_EMIN; /* [thanks to Math restrictions] */
11355796c8dcSSimon Schubert /* set up decNumber space to receive the result of the multiply */
11365796c8dcSSimon Schubert acc=bufa; /* may fit */
11375796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit);
11385796c8dcSSimon Schubert if (needbytes>sizeof(bufa)) { /* need malloc space */
11395796c8dcSSimon Schubert allocbufa=(decNumber *)malloc(needbytes);
11405796c8dcSSimon Schubert if (allocbufa==NULL) { /* hopeless -- abandon */
11415796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
11425796c8dcSSimon Schubert break;}
11435796c8dcSSimon Schubert acc=allocbufa; /* use the allocated space */
11445796c8dcSSimon Schubert }
11455796c8dcSSimon Schubert /* multiply with extended range and necessary precision */
11465796c8dcSSimon Schubert /*printf("emin=%ld\n", dcmul.emin); */
11475796c8dcSSimon Schubert decMultiplyOp(acc, lhs, rhs, &dcmul, &status);
11485796c8dcSSimon Schubert /* Only Invalid operation (from sNaN or Inf * 0) is possible in */
11495796c8dcSSimon Schubert /* status; if either is seen than ignore fhs (in case it is */
11505796c8dcSSimon Schubert /* another sNaN) and set acc to NaN unless we had an sNaN */
11515796c8dcSSimon Schubert /* [decMultiplyOp leaves that to caller] */
11525796c8dcSSimon Schubert /* Note sNaN has to go through addOp to shorten payload if */
11535796c8dcSSimon Schubert /* necessary */
11545796c8dcSSimon Schubert if ((status&DEC_Invalid_operation)!=0) {
11555796c8dcSSimon Schubert if (!(status&DEC_sNaN)) { /* but be true invalid */
11565796c8dcSSimon Schubert decNumberZero(res); /* acc not yet set */
11575796c8dcSSimon Schubert res->bits=DECNAN;
11585796c8dcSSimon Schubert break;
11595796c8dcSSimon Schubert }
11605796c8dcSSimon Schubert decNumberZero(&dzero); /* make 0 (any non-NaN would do) */
11615796c8dcSSimon Schubert fhs=&dzero; /* use that */
11625796c8dcSSimon Schubert }
11635796c8dcSSimon Schubert #if DECCHECK
11645796c8dcSSimon Schubert else { /* multiply was OK */
11655796c8dcSSimon Schubert if (status!=0) printf("Status=%08lx after FMA multiply\n", (LI)status);
11665796c8dcSSimon Schubert }
11675796c8dcSSimon Schubert #endif
11685796c8dcSSimon Schubert /* add the third operand and result -> res, and all is done */
11695796c8dcSSimon Schubert decAddOp(res, acc, fhs, set, 0, &status);
11705796c8dcSSimon Schubert } while(0); /* end protected */
11715796c8dcSSimon Schubert
1172a45ae5f8SJohn Marino free(allocbufa); /* drop any storage used */
11735796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
11745796c8dcSSimon Schubert #if DECCHECK
11755796c8dcSSimon Schubert decCheckInexact(res, set);
11765796c8dcSSimon Schubert #endif
11775796c8dcSSimon Schubert return res;
11785796c8dcSSimon Schubert } /* decNumberFMA */
11795796c8dcSSimon Schubert
11805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
11815796c8dcSSimon Schubert /* decNumberInvert -- invert a Number, digitwise */
11825796c8dcSSimon Schubert /* */
11835796c8dcSSimon Schubert /* This computes C = ~A */
11845796c8dcSSimon Schubert /* */
11855796c8dcSSimon Schubert /* res is C, the result. C may be A (e.g., X=~X) */
11865796c8dcSSimon Schubert /* rhs is A */
11875796c8dcSSimon Schubert /* set is the context (used for result length and error report) */
11885796c8dcSSimon Schubert /* */
11895796c8dcSSimon Schubert /* C must have space for set->digits digits. */
11905796c8dcSSimon Schubert /* */
11915796c8dcSSimon Schubert /* Logical function restrictions apply (see above); a NaN is */
11925796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
11935796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberInvert(decNumber * res,const decNumber * rhs,decContext * set)11945796c8dcSSimon Schubert decNumber * decNumberInvert(decNumber *res, const decNumber *rhs,
11955796c8dcSSimon Schubert decContext *set) {
11965796c8dcSSimon Schubert const Unit *ua, *msua; /* -> operand and its msu */
11975796c8dcSSimon Schubert Unit *uc, *msuc; /* -> result and its msu */
11985796c8dcSSimon Schubert Int msudigs; /* digits in res msu */
11995796c8dcSSimon Schubert #if DECCHECK
12005796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
12015796c8dcSSimon Schubert #endif
12025796c8dcSSimon Schubert
12035796c8dcSSimon Schubert if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
12045796c8dcSSimon Schubert decStatus(res, DEC_Invalid_operation, set);
12055796c8dcSSimon Schubert return res;
12065796c8dcSSimon Schubert }
12075796c8dcSSimon Schubert /* operand is valid */
12085796c8dcSSimon Schubert ua=rhs->lsu; /* bottom-up */
12095796c8dcSSimon Schubert uc=res->lsu; /* .. */
12105796c8dcSSimon Schubert msua=ua+D2U(rhs->digits)-1; /* -> msu of rhs */
12115796c8dcSSimon Schubert msuc=uc+D2U(set->digits)-1; /* -> msu of result */
12125796c8dcSSimon Schubert msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */
12135796c8dcSSimon Schubert for (; uc<=msuc; ua++, uc++) { /* Unit loop */
12145796c8dcSSimon Schubert Unit a; /* extract unit */
12155796c8dcSSimon Schubert Int i, j; /* work */
12165796c8dcSSimon Schubert if (ua>msua) a=0;
12175796c8dcSSimon Schubert else a=*ua;
12185796c8dcSSimon Schubert *uc=0; /* can now write back */
12195796c8dcSSimon Schubert /* always need to examine all bits in rhs */
12205796c8dcSSimon Schubert /* This loop could be unrolled and/or use BIN2BCD tables */
12215796c8dcSSimon Schubert for (i=0; i<DECDPUN; i++) {
12225796c8dcSSimon Schubert if ((~a)&1) *uc=*uc+(Unit)powers[i]; /* effect INVERT */
12235796c8dcSSimon Schubert j=a%10;
12245796c8dcSSimon Schubert a=a/10;
12255796c8dcSSimon Schubert if (j>1) {
12265796c8dcSSimon Schubert decStatus(res, DEC_Invalid_operation, set);
12275796c8dcSSimon Schubert return res;
12285796c8dcSSimon Schubert }
12295796c8dcSSimon Schubert if (uc==msuc && i==msudigs-1) break; /* just did final digit */
12305796c8dcSSimon Schubert } /* each digit */
12315796c8dcSSimon Schubert } /* each unit */
12325796c8dcSSimon Schubert /* [here uc-1 is the msu of the result] */
12335796c8dcSSimon Schubert res->digits=decGetDigits(res->lsu, uc-res->lsu);
12345796c8dcSSimon Schubert res->exponent=0; /* integer */
12355796c8dcSSimon Schubert res->bits=0; /* sign=0 */
12365796c8dcSSimon Schubert return res; /* [no status to set] */
12375796c8dcSSimon Schubert } /* decNumberInvert */
12385796c8dcSSimon Schubert
12395796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
12405796c8dcSSimon Schubert /* decNumberLn -- natural logarithm */
12415796c8dcSSimon Schubert /* */
12425796c8dcSSimon Schubert /* This computes C = ln(A) */
12435796c8dcSSimon Schubert /* */
12445796c8dcSSimon Schubert /* res is C, the result. C may be A */
12455796c8dcSSimon Schubert /* rhs is A */
12465796c8dcSSimon Schubert /* set is the context; note that rounding mode has no effect */
12475796c8dcSSimon Schubert /* */
12485796c8dcSSimon Schubert /* C must have space for set->digits digits. */
12495796c8dcSSimon Schubert /* */
12505796c8dcSSimon Schubert /* Notable cases: */
12515796c8dcSSimon Schubert /* A<0 -> Invalid */
12525796c8dcSSimon Schubert /* A=0 -> -Infinity (Exact) */
12535796c8dcSSimon Schubert /* A=+Infinity -> +Infinity (Exact) */
12545796c8dcSSimon Schubert /* A=1 exactly -> 0 (Exact) */
12555796c8dcSSimon Schubert /* */
12565796c8dcSSimon Schubert /* Mathematical function restrictions apply (see above); a NaN is */
12575796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
12585796c8dcSSimon Schubert /* */
12595796c8dcSSimon Schubert /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
12605796c8dcSSimon Schubert /* almost always be correctly rounded, but may be up to 1 ulp in */
12615796c8dcSSimon Schubert /* error in rare cases. */
12625796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
12635796c8dcSSimon Schubert /* This is a wrapper for decLnOp which can handle the slightly wider */
12645796c8dcSSimon Schubert /* (+11) range needed by Ln, Log10, etc. (which may have to be able */
12655796c8dcSSimon Schubert /* to calculate at p+e+2). */
12665796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberLn(decNumber * res,const decNumber * rhs,decContext * set)12675796c8dcSSimon Schubert decNumber * decNumberLn(decNumber *res, const decNumber *rhs,
12685796c8dcSSimon Schubert decContext *set) {
12695796c8dcSSimon Schubert uInt status=0; /* accumulator */
12705796c8dcSSimon Schubert #if DECSUBSET
12715796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
12725796c8dcSSimon Schubert #endif
12735796c8dcSSimon Schubert
12745796c8dcSSimon Schubert #if DECCHECK
12755796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
12765796c8dcSSimon Schubert #endif
12775796c8dcSSimon Schubert
12785796c8dcSSimon Schubert /* Check restrictions; this is a math function; if not violated */
12795796c8dcSSimon Schubert /* then carry out the operation. */
12805796c8dcSSimon Schubert if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
12815796c8dcSSimon Schubert #if DECSUBSET
12825796c8dcSSimon Schubert if (!set->extended) {
12835796c8dcSSimon Schubert /* reduce operand and set lostDigits status, as needed */
12845796c8dcSSimon Schubert if (rhs->digits>set->digits) {
12855796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, &status);
12865796c8dcSSimon Schubert if (allocrhs==NULL) break;
12875796c8dcSSimon Schubert rhs=allocrhs;
12885796c8dcSSimon Schubert }
12895796c8dcSSimon Schubert /* special check in subset for rhs=0 */
12905796c8dcSSimon Schubert if (ISZERO(rhs)) { /* +/- zeros -> error */
12915796c8dcSSimon Schubert status|=DEC_Invalid_operation;
12925796c8dcSSimon Schubert break;}
12935796c8dcSSimon Schubert } /* extended=0 */
12945796c8dcSSimon Schubert #endif
12955796c8dcSSimon Schubert decLnOp(res, rhs, set, &status);
12965796c8dcSSimon Schubert } while(0); /* end protected */
12975796c8dcSSimon Schubert
12985796c8dcSSimon Schubert #if DECSUBSET
1299a45ae5f8SJohn Marino free(allocrhs); /* drop any storage used */
13005796c8dcSSimon Schubert #endif
13015796c8dcSSimon Schubert /* apply significant status */
13025796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
13035796c8dcSSimon Schubert #if DECCHECK
13045796c8dcSSimon Schubert decCheckInexact(res, set);
13055796c8dcSSimon Schubert #endif
13065796c8dcSSimon Schubert return res;
13075796c8dcSSimon Schubert } /* decNumberLn */
13085796c8dcSSimon Schubert
13095796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
13105796c8dcSSimon Schubert /* decNumberLogB - get adjusted exponent, by 754 rules */
13115796c8dcSSimon Schubert /* */
13125796c8dcSSimon Schubert /* This computes C = adjustedexponent(A) */
13135796c8dcSSimon Schubert /* */
13145796c8dcSSimon Schubert /* res is C, the result. C may be A */
13155796c8dcSSimon Schubert /* rhs is A */
13165796c8dcSSimon Schubert /* set is the context, used only for digits and status */
13175796c8dcSSimon Schubert /* */
13185796c8dcSSimon Schubert /* C must have space for 10 digits (A might have 10**9 digits and */
13195796c8dcSSimon Schubert /* an exponent of +999999999, or one digit and an exponent of */
13205796c8dcSSimon Schubert /* -1999999999). */
13215796c8dcSSimon Schubert /* */
13225796c8dcSSimon Schubert /* This returns the adjusted exponent of A after (in theory) padding */
13235796c8dcSSimon Schubert /* with zeros on the right to set->digits digits while keeping the */
13245796c8dcSSimon Schubert /* same value. The exponent is not limited by emin/emax. */
13255796c8dcSSimon Schubert /* */
13265796c8dcSSimon Schubert /* Notable cases: */
13275796c8dcSSimon Schubert /* A<0 -> Use |A| */
13285796c8dcSSimon Schubert /* A=0 -> -Infinity (Division by zero) */
13295796c8dcSSimon Schubert /* A=Infinite -> +Infinity (Exact) */
13305796c8dcSSimon Schubert /* A=1 exactly -> 0 (Exact) */
13315796c8dcSSimon Schubert /* NaNs are propagated as usual */
13325796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberLogB(decNumber * res,const decNumber * rhs,decContext * set)13335796c8dcSSimon Schubert decNumber * decNumberLogB(decNumber *res, const decNumber *rhs,
13345796c8dcSSimon Schubert decContext *set) {
13355796c8dcSSimon Schubert uInt status=0; /* accumulator */
13365796c8dcSSimon Schubert
13375796c8dcSSimon Schubert #if DECCHECK
13385796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
13395796c8dcSSimon Schubert #endif
13405796c8dcSSimon Schubert
13415796c8dcSSimon Schubert /* NaNs as usual; Infinities return +Infinity; 0->oops */
13425796c8dcSSimon Schubert if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status);
13435796c8dcSSimon Schubert else if (decNumberIsInfinite(rhs)) decNumberCopyAbs(res, rhs);
13445796c8dcSSimon Schubert else if (decNumberIsZero(rhs)) {
13455796c8dcSSimon Schubert decNumberZero(res); /* prepare for Infinity */
13465796c8dcSSimon Schubert res->bits=DECNEG|DECINF; /* -Infinity */
13475796c8dcSSimon Schubert status|=DEC_Division_by_zero; /* as per 754 */
13485796c8dcSSimon Schubert }
13495796c8dcSSimon Schubert else { /* finite non-zero */
13505796c8dcSSimon Schubert Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */
13515796c8dcSSimon Schubert decNumberFromInt32(res, ae); /* lay it out */
13525796c8dcSSimon Schubert }
13535796c8dcSSimon Schubert
13545796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
13555796c8dcSSimon Schubert return res;
13565796c8dcSSimon Schubert } /* decNumberLogB */
13575796c8dcSSimon Schubert
13585796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
13595796c8dcSSimon Schubert /* decNumberLog10 -- logarithm in base 10 */
13605796c8dcSSimon Schubert /* */
13615796c8dcSSimon Schubert /* This computes C = log10(A) */
13625796c8dcSSimon Schubert /* */
13635796c8dcSSimon Schubert /* res is C, the result. C may be A */
13645796c8dcSSimon Schubert /* rhs is A */
13655796c8dcSSimon Schubert /* set is the context; note that rounding mode has no effect */
13665796c8dcSSimon Schubert /* */
13675796c8dcSSimon Schubert /* C must have space for set->digits digits. */
13685796c8dcSSimon Schubert /* */
13695796c8dcSSimon Schubert /* Notable cases: */
13705796c8dcSSimon Schubert /* A<0 -> Invalid */
13715796c8dcSSimon Schubert /* A=0 -> -Infinity (Exact) */
13725796c8dcSSimon Schubert /* A=+Infinity -> +Infinity (Exact) */
13735796c8dcSSimon Schubert /* A=10**n (if n is an integer) -> n (Exact) */
13745796c8dcSSimon Schubert /* */
13755796c8dcSSimon Schubert /* Mathematical function restrictions apply (see above); a NaN is */
13765796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
13775796c8dcSSimon Schubert /* */
13785796c8dcSSimon Schubert /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will */
13795796c8dcSSimon Schubert /* almost always be correctly rounded, but may be up to 1 ulp in */
13805796c8dcSSimon Schubert /* error in rare cases. */
13815796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
13825796c8dcSSimon Schubert /* This calculates ln(A)/ln(10) using appropriate precision. For */
13835796c8dcSSimon Schubert /* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the */
13845796c8dcSSimon Schubert /* requested digits and t is the number of digits in the exponent */
13855796c8dcSSimon Schubert /* (maximum 6). For ln(10) it is p + 3; this is often handled by the */
13865796c8dcSSimon Schubert /* fastpath in decLnOp. The final division is done to the requested */
13875796c8dcSSimon Schubert /* precision. */
13885796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberLog10(decNumber * res,const decNumber * rhs,decContext * set)13895796c8dcSSimon Schubert decNumber * decNumberLog10(decNumber *res, const decNumber *rhs,
13905796c8dcSSimon Schubert decContext *set) {
13915796c8dcSSimon Schubert uInt status=0, ignore=0; /* status accumulators */
13925796c8dcSSimon Schubert uInt needbytes; /* for space calculations */
13935796c8dcSSimon Schubert Int p; /* working precision */
13945796c8dcSSimon Schubert Int t; /* digits in exponent of A */
13955796c8dcSSimon Schubert
13965796c8dcSSimon Schubert /* buffers for a and b working decimals */
13975796c8dcSSimon Schubert /* (adjustment calculator, same size) */
13985796c8dcSSimon Schubert decNumber bufa[D2N(DECBUFFER+2)];
13995796c8dcSSimon Schubert decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
14005796c8dcSSimon Schubert decNumber *a=bufa; /* temporary a */
14015796c8dcSSimon Schubert decNumber bufb[D2N(DECBUFFER+2)];
14025796c8dcSSimon Schubert decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */
14035796c8dcSSimon Schubert decNumber *b=bufb; /* temporary b */
14045796c8dcSSimon Schubert decNumber bufw[D2N(10)]; /* working 2-10 digit number */
14055796c8dcSSimon Schubert decNumber *w=bufw; /* .. */
14065796c8dcSSimon Schubert #if DECSUBSET
14075796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
14085796c8dcSSimon Schubert #endif
14095796c8dcSSimon Schubert
14105796c8dcSSimon Schubert decContext aset; /* working context */
14115796c8dcSSimon Schubert
14125796c8dcSSimon Schubert #if DECCHECK
14135796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
14145796c8dcSSimon Schubert #endif
14155796c8dcSSimon Schubert
14165796c8dcSSimon Schubert /* Check restrictions; this is a math function; if not violated */
14175796c8dcSSimon Schubert /* then carry out the operation. */
14185796c8dcSSimon Schubert if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */
14195796c8dcSSimon Schubert #if DECSUBSET
14205796c8dcSSimon Schubert if (!set->extended) {
14215796c8dcSSimon Schubert /* reduce operand and set lostDigits status, as needed */
14225796c8dcSSimon Schubert if (rhs->digits>set->digits) {
14235796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, &status);
14245796c8dcSSimon Schubert if (allocrhs==NULL) break;
14255796c8dcSSimon Schubert rhs=allocrhs;
14265796c8dcSSimon Schubert }
14275796c8dcSSimon Schubert /* special check in subset for rhs=0 */
14285796c8dcSSimon Schubert if (ISZERO(rhs)) { /* +/- zeros -> error */
14295796c8dcSSimon Schubert status|=DEC_Invalid_operation;
14305796c8dcSSimon Schubert break;}
14315796c8dcSSimon Schubert } /* extended=0 */
14325796c8dcSSimon Schubert #endif
14335796c8dcSSimon Schubert
14345796c8dcSSimon Schubert decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
14355796c8dcSSimon Schubert
14365796c8dcSSimon Schubert /* handle exact powers of 10; only check if +ve finite */
14375796c8dcSSimon Schubert if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) {
14385796c8dcSSimon Schubert Int residue=0; /* (no residue) */
14395796c8dcSSimon Schubert uInt copystat=0; /* clean status */
14405796c8dcSSimon Schubert
14415796c8dcSSimon Schubert /* round to a single digit... */
14425796c8dcSSimon Schubert aset.digits=1;
14435796c8dcSSimon Schubert decCopyFit(w, rhs, &aset, &residue, ©stat); /* copy & shorten */
14445796c8dcSSimon Schubert /* if exact and the digit is 1, rhs is a power of 10 */
14455796c8dcSSimon Schubert if (!(copystat&DEC_Inexact) && w->lsu[0]==1) {
14465796c8dcSSimon Schubert /* the exponent, conveniently, is the power of 10; making */
14475796c8dcSSimon Schubert /* this the result needs a little care as it might not fit, */
14485796c8dcSSimon Schubert /* so first convert it into the working number, and then move */
14495796c8dcSSimon Schubert /* to res */
14505796c8dcSSimon Schubert decNumberFromInt32(w, w->exponent);
14515796c8dcSSimon Schubert residue=0;
14525796c8dcSSimon Schubert decCopyFit(res, w, set, &residue, &status); /* copy & round */
14535796c8dcSSimon Schubert decFinish(res, set, &residue, &status); /* cleanup/set flags */
14545796c8dcSSimon Schubert break;
14555796c8dcSSimon Schubert } /* not a power of 10 */
14565796c8dcSSimon Schubert } /* not a candidate for exact */
14575796c8dcSSimon Schubert
14585796c8dcSSimon Schubert /* simplify the information-content calculation to use 'total */
14595796c8dcSSimon Schubert /* number of digits in a, including exponent' as compared to the */
14605796c8dcSSimon Schubert /* requested digits, as increasing this will only rarely cost an */
14615796c8dcSSimon Schubert /* iteration in ln(a) anyway */
14625796c8dcSSimon Schubert t=6; /* it can never be >6 */
14635796c8dcSSimon Schubert
14645796c8dcSSimon Schubert /* allocate space when needed... */
14655796c8dcSSimon Schubert p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3;
14665796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
14675796c8dcSSimon Schubert if (needbytes>sizeof(bufa)) { /* need malloc space */
14685796c8dcSSimon Schubert allocbufa=(decNumber *)malloc(needbytes);
14695796c8dcSSimon Schubert if (allocbufa==NULL) { /* hopeless -- abandon */
14705796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
14715796c8dcSSimon Schubert break;}
14725796c8dcSSimon Schubert a=allocbufa; /* use the allocated space */
14735796c8dcSSimon Schubert }
14745796c8dcSSimon Schubert aset.digits=p; /* as calculated */
14755796c8dcSSimon Schubert aset.emax=DEC_MAX_MATH; /* usual bounds */
14765796c8dcSSimon Schubert aset.emin=-DEC_MAX_MATH; /* .. */
14775796c8dcSSimon Schubert aset.clamp=0; /* and no concrete format */
14785796c8dcSSimon Schubert decLnOp(a, rhs, &aset, &status); /* a=ln(rhs) */
14795796c8dcSSimon Schubert
14805796c8dcSSimon Schubert /* skip the division if the result so far is infinite, NaN, or */
14815796c8dcSSimon Schubert /* zero, or there was an error; note NaN from sNaN needs copy */
14825796c8dcSSimon Schubert if (status&DEC_NaNs && !(status&DEC_sNaN)) break;
14835796c8dcSSimon Schubert if (a->bits&DECSPECIAL || ISZERO(a)) {
14845796c8dcSSimon Schubert decNumberCopy(res, a); /* [will fit] */
14855796c8dcSSimon Schubert break;}
14865796c8dcSSimon Schubert
14875796c8dcSSimon Schubert /* for ln(10) an extra 3 digits of precision are needed */
14885796c8dcSSimon Schubert p=set->digits+3;
14895796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
14905796c8dcSSimon Schubert if (needbytes>sizeof(bufb)) { /* need malloc space */
14915796c8dcSSimon Schubert allocbufb=(decNumber *)malloc(needbytes);
14925796c8dcSSimon Schubert if (allocbufb==NULL) { /* hopeless -- abandon */
14935796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
14945796c8dcSSimon Schubert break;}
14955796c8dcSSimon Schubert b=allocbufb; /* use the allocated space */
14965796c8dcSSimon Schubert }
14975796c8dcSSimon Schubert decNumberZero(w); /* set up 10... */
14985796c8dcSSimon Schubert #if DECDPUN==1
14995796c8dcSSimon Schubert w->lsu[1]=1; w->lsu[0]=0; /* .. */
15005796c8dcSSimon Schubert #else
15015796c8dcSSimon Schubert w->lsu[0]=10; /* .. */
15025796c8dcSSimon Schubert #endif
15035796c8dcSSimon Schubert w->digits=2; /* .. */
15045796c8dcSSimon Schubert
15055796c8dcSSimon Schubert aset.digits=p;
15065796c8dcSSimon Schubert decLnOp(b, w, &aset, &ignore); /* b=ln(10) */
15075796c8dcSSimon Schubert
15085796c8dcSSimon Schubert aset.digits=set->digits; /* for final divide */
15095796c8dcSSimon Schubert decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */
15105796c8dcSSimon Schubert } while(0); /* [for break] */
15115796c8dcSSimon Schubert
1512a45ae5f8SJohn Marino free(allocbufa); /* drop any storage used */
1513a45ae5f8SJohn Marino free(allocbufb); /* .. */
15145796c8dcSSimon Schubert #if DECSUBSET
1515a45ae5f8SJohn Marino free(allocrhs); /* .. */
15165796c8dcSSimon Schubert #endif
15175796c8dcSSimon Schubert /* apply significant status */
15185796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
15195796c8dcSSimon Schubert #if DECCHECK
15205796c8dcSSimon Schubert decCheckInexact(res, set);
15215796c8dcSSimon Schubert #endif
15225796c8dcSSimon Schubert return res;
15235796c8dcSSimon Schubert } /* decNumberLog10 */
15245796c8dcSSimon Schubert
15255796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
15265796c8dcSSimon Schubert /* decNumberMax -- compare two Numbers and return the maximum */
15275796c8dcSSimon Schubert /* */
15285796c8dcSSimon Schubert /* This computes C = A ? B, returning the maximum by 754 rules */
15295796c8dcSSimon Schubert /* */
15305796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
15315796c8dcSSimon Schubert /* lhs is A */
15325796c8dcSSimon Schubert /* rhs is B */
15335796c8dcSSimon Schubert /* set is the context */
15345796c8dcSSimon Schubert /* */
15355796c8dcSSimon Schubert /* C must have space for set->digits digits. */
15365796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberMax(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)15375796c8dcSSimon Schubert decNumber * decNumberMax(decNumber *res, const decNumber *lhs,
15385796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
15395796c8dcSSimon Schubert uInt status=0; /* accumulator */
15405796c8dcSSimon Schubert decCompareOp(res, lhs, rhs, set, COMPMAX, &status);
15415796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
15425796c8dcSSimon Schubert #if DECCHECK
15435796c8dcSSimon Schubert decCheckInexact(res, set);
15445796c8dcSSimon Schubert #endif
15455796c8dcSSimon Schubert return res;
15465796c8dcSSimon Schubert } /* decNumberMax */
15475796c8dcSSimon Schubert
15485796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
15495796c8dcSSimon Schubert /* decNumberMaxMag -- compare and return the maximum by magnitude */
15505796c8dcSSimon Schubert /* */
15515796c8dcSSimon Schubert /* This computes C = A ? B, returning the maximum by 754 rules */
15525796c8dcSSimon Schubert /* */
15535796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
15545796c8dcSSimon Schubert /* lhs is A */
15555796c8dcSSimon Schubert /* rhs is B */
15565796c8dcSSimon Schubert /* set is the context */
15575796c8dcSSimon Schubert /* */
15585796c8dcSSimon Schubert /* C must have space for set->digits digits. */
15595796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberMaxMag(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)15605796c8dcSSimon Schubert decNumber * decNumberMaxMag(decNumber *res, const decNumber *lhs,
15615796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
15625796c8dcSSimon Schubert uInt status=0; /* accumulator */
15635796c8dcSSimon Schubert decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status);
15645796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
15655796c8dcSSimon Schubert #if DECCHECK
15665796c8dcSSimon Schubert decCheckInexact(res, set);
15675796c8dcSSimon Schubert #endif
15685796c8dcSSimon Schubert return res;
15695796c8dcSSimon Schubert } /* decNumberMaxMag */
15705796c8dcSSimon Schubert
15715796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
15725796c8dcSSimon Schubert /* decNumberMin -- compare two Numbers and return the minimum */
15735796c8dcSSimon Schubert /* */
15745796c8dcSSimon Schubert /* This computes C = A ? B, returning the minimum by 754 rules */
15755796c8dcSSimon Schubert /* */
15765796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
15775796c8dcSSimon Schubert /* lhs is A */
15785796c8dcSSimon Schubert /* rhs is B */
15795796c8dcSSimon Schubert /* set is the context */
15805796c8dcSSimon Schubert /* */
15815796c8dcSSimon Schubert /* C must have space for set->digits digits. */
15825796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberMin(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)15835796c8dcSSimon Schubert decNumber * decNumberMin(decNumber *res, const decNumber *lhs,
15845796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
15855796c8dcSSimon Schubert uInt status=0; /* accumulator */
15865796c8dcSSimon Schubert decCompareOp(res, lhs, rhs, set, COMPMIN, &status);
15875796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
15885796c8dcSSimon Schubert #if DECCHECK
15895796c8dcSSimon Schubert decCheckInexact(res, set);
15905796c8dcSSimon Schubert #endif
15915796c8dcSSimon Schubert return res;
15925796c8dcSSimon Schubert } /* decNumberMin */
15935796c8dcSSimon Schubert
15945796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
15955796c8dcSSimon Schubert /* decNumberMinMag -- compare and return the minimum by magnitude */
15965796c8dcSSimon Schubert /* */
15975796c8dcSSimon Schubert /* This computes C = A ? B, returning the minimum by 754 rules */
15985796c8dcSSimon Schubert /* */
15995796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
16005796c8dcSSimon Schubert /* lhs is A */
16015796c8dcSSimon Schubert /* rhs is B */
16025796c8dcSSimon Schubert /* set is the context */
16035796c8dcSSimon Schubert /* */
16045796c8dcSSimon Schubert /* C must have space for set->digits digits. */
16055796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberMinMag(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)16065796c8dcSSimon Schubert decNumber * decNumberMinMag(decNumber *res, const decNumber *lhs,
16075796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
16085796c8dcSSimon Schubert uInt status=0; /* accumulator */
16095796c8dcSSimon Schubert decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status);
16105796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
16115796c8dcSSimon Schubert #if DECCHECK
16125796c8dcSSimon Schubert decCheckInexact(res, set);
16135796c8dcSSimon Schubert #endif
16145796c8dcSSimon Schubert return res;
16155796c8dcSSimon Schubert } /* decNumberMinMag */
16165796c8dcSSimon Schubert
16175796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
16185796c8dcSSimon Schubert /* decNumberMinus -- prefix minus operator */
16195796c8dcSSimon Schubert /* */
16205796c8dcSSimon Schubert /* This computes C = 0 - A */
16215796c8dcSSimon Schubert /* */
16225796c8dcSSimon Schubert /* res is C, the result. C may be A */
16235796c8dcSSimon Schubert /* rhs is A */
16245796c8dcSSimon Schubert /* set is the context */
16255796c8dcSSimon Schubert /* */
16265796c8dcSSimon Schubert /* See also decNumberCopyNegate for a quiet bitwise version of this. */
16275796c8dcSSimon Schubert /* C must have space for set->digits digits. */
16285796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
16295796c8dcSSimon Schubert /* Simply use AddOp for the subtract, which will do the necessary. */
16305796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberMinus(decNumber * res,const decNumber * rhs,decContext * set)16315796c8dcSSimon Schubert decNumber * decNumberMinus(decNumber *res, const decNumber *rhs,
16325796c8dcSSimon Schubert decContext *set) {
16335796c8dcSSimon Schubert decNumber dzero;
16345796c8dcSSimon Schubert uInt status=0; /* accumulator */
16355796c8dcSSimon Schubert
16365796c8dcSSimon Schubert #if DECCHECK
16375796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
16385796c8dcSSimon Schubert #endif
16395796c8dcSSimon Schubert
16405796c8dcSSimon Schubert decNumberZero(&dzero); /* make 0 */
16415796c8dcSSimon Schubert dzero.exponent=rhs->exponent; /* [no coefficient expansion] */
16425796c8dcSSimon Schubert decAddOp(res, &dzero, rhs, set, DECNEG, &status);
16435796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
16445796c8dcSSimon Schubert #if DECCHECK
16455796c8dcSSimon Schubert decCheckInexact(res, set);
16465796c8dcSSimon Schubert #endif
16475796c8dcSSimon Schubert return res;
16485796c8dcSSimon Schubert } /* decNumberMinus */
16495796c8dcSSimon Schubert
16505796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
16515796c8dcSSimon Schubert /* decNumberNextMinus -- next towards -Infinity */
16525796c8dcSSimon Schubert /* */
16535796c8dcSSimon Schubert /* This computes C = A - infinitesimal, rounded towards -Infinity */
16545796c8dcSSimon Schubert /* */
16555796c8dcSSimon Schubert /* res is C, the result. C may be A */
16565796c8dcSSimon Schubert /* rhs is A */
16575796c8dcSSimon Schubert /* set is the context */
16585796c8dcSSimon Schubert /* */
16595796c8dcSSimon Schubert /* This is a generalization of 754 NextDown. */
16605796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberNextMinus(decNumber * res,const decNumber * rhs,decContext * set)16615796c8dcSSimon Schubert decNumber * decNumberNextMinus(decNumber *res, const decNumber *rhs,
16625796c8dcSSimon Schubert decContext *set) {
16635796c8dcSSimon Schubert decNumber dtiny; /* constant */
16645796c8dcSSimon Schubert decContext workset=*set; /* work */
16655796c8dcSSimon Schubert uInt status=0; /* accumulator */
16665796c8dcSSimon Schubert #if DECCHECK
16675796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
16685796c8dcSSimon Schubert #endif
16695796c8dcSSimon Schubert
16705796c8dcSSimon Schubert /* +Infinity is the special case */
16715796c8dcSSimon Schubert if ((rhs->bits&(DECINF|DECNEG))==DECINF) {
16725796c8dcSSimon Schubert decSetMaxValue(res, set); /* is +ve */
16735796c8dcSSimon Schubert /* there is no status to set */
16745796c8dcSSimon Schubert return res;
16755796c8dcSSimon Schubert }
16765796c8dcSSimon Schubert decNumberZero(&dtiny); /* start with 0 */
16775796c8dcSSimon Schubert dtiny.lsu[0]=1; /* make number that is .. */
16785796c8dcSSimon Schubert dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */
16795796c8dcSSimon Schubert workset.round=DEC_ROUND_FLOOR;
16805796c8dcSSimon Schubert decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status);
16815796c8dcSSimon Schubert status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */
16825796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
16835796c8dcSSimon Schubert return res;
16845796c8dcSSimon Schubert } /* decNumberNextMinus */
16855796c8dcSSimon Schubert
16865796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
16875796c8dcSSimon Schubert /* decNumberNextPlus -- next towards +Infinity */
16885796c8dcSSimon Schubert /* */
16895796c8dcSSimon Schubert /* This computes C = A + infinitesimal, rounded towards +Infinity */
16905796c8dcSSimon Schubert /* */
16915796c8dcSSimon Schubert /* res is C, the result. C may be A */
16925796c8dcSSimon Schubert /* rhs is A */
16935796c8dcSSimon Schubert /* set is the context */
16945796c8dcSSimon Schubert /* */
16955796c8dcSSimon Schubert /* This is a generalization of 754 NextUp. */
16965796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberNextPlus(decNumber * res,const decNumber * rhs,decContext * set)16975796c8dcSSimon Schubert decNumber * decNumberNextPlus(decNumber *res, const decNumber *rhs,
16985796c8dcSSimon Schubert decContext *set) {
16995796c8dcSSimon Schubert decNumber dtiny; /* constant */
17005796c8dcSSimon Schubert decContext workset=*set; /* work */
17015796c8dcSSimon Schubert uInt status=0; /* accumulator */
17025796c8dcSSimon Schubert #if DECCHECK
17035796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
17045796c8dcSSimon Schubert #endif
17055796c8dcSSimon Schubert
17065796c8dcSSimon Schubert /* -Infinity is the special case */
17075796c8dcSSimon Schubert if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
17085796c8dcSSimon Schubert decSetMaxValue(res, set);
17095796c8dcSSimon Schubert res->bits=DECNEG; /* negative */
17105796c8dcSSimon Schubert /* there is no status to set */
17115796c8dcSSimon Schubert return res;
17125796c8dcSSimon Schubert }
17135796c8dcSSimon Schubert decNumberZero(&dtiny); /* start with 0 */
17145796c8dcSSimon Schubert dtiny.lsu[0]=1; /* make number that is .. */
17155796c8dcSSimon Schubert dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */
17165796c8dcSSimon Schubert workset.round=DEC_ROUND_CEILING;
17175796c8dcSSimon Schubert decAddOp(res, rhs, &dtiny, &workset, 0, &status);
17185796c8dcSSimon Schubert status&=DEC_Invalid_operation|DEC_sNaN; /* only sNaN Invalid please */
17195796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
17205796c8dcSSimon Schubert return res;
17215796c8dcSSimon Schubert } /* decNumberNextPlus */
17225796c8dcSSimon Schubert
17235796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
17245796c8dcSSimon Schubert /* decNumberNextToward -- next towards rhs */
17255796c8dcSSimon Schubert /* */
17265796c8dcSSimon Schubert /* This computes C = A +/- infinitesimal, rounded towards */
17275796c8dcSSimon Schubert /* +/-Infinity in the direction of B, as per 754-1985 nextafter */
17285796c8dcSSimon Schubert /* modified during revision but dropped from 754-2008. */
17295796c8dcSSimon Schubert /* */
17305796c8dcSSimon Schubert /* res is C, the result. C may be A or B. */
17315796c8dcSSimon Schubert /* lhs is A */
17325796c8dcSSimon Schubert /* rhs is B */
17335796c8dcSSimon Schubert /* set is the context */
17345796c8dcSSimon Schubert /* */
17355796c8dcSSimon Schubert /* This is a generalization of 754-1985 NextAfter. */
17365796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberNextToward(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)17375796c8dcSSimon Schubert decNumber * decNumberNextToward(decNumber *res, const decNumber *lhs,
17385796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
17395796c8dcSSimon Schubert decNumber dtiny; /* constant */
17405796c8dcSSimon Schubert decContext workset=*set; /* work */
17415796c8dcSSimon Schubert Int result; /* .. */
17425796c8dcSSimon Schubert uInt status=0; /* accumulator */
17435796c8dcSSimon Schubert #if DECCHECK
17445796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
17455796c8dcSSimon Schubert #endif
17465796c8dcSSimon Schubert
17475796c8dcSSimon Schubert if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) {
17485796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, &status);
17495796c8dcSSimon Schubert }
17505796c8dcSSimon Schubert else { /* Is numeric, so no chance of sNaN Invalid, etc. */
17515796c8dcSSimon Schubert result=decCompare(lhs, rhs, 0); /* sign matters */
17525796c8dcSSimon Schubert if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */
17535796c8dcSSimon Schubert else { /* valid compare */
17545796c8dcSSimon Schubert if (result==0) decNumberCopySign(res, lhs, rhs); /* easy */
17555796c8dcSSimon Schubert else { /* differ: need NextPlus or NextMinus */
17565796c8dcSSimon Schubert uByte sub; /* add or subtract */
17575796c8dcSSimon Schubert if (result<0) { /* lhs<rhs, do nextplus */
17585796c8dcSSimon Schubert /* -Infinity is the special case */
17595796c8dcSSimon Schubert if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
17605796c8dcSSimon Schubert decSetMaxValue(res, set);
17615796c8dcSSimon Schubert res->bits=DECNEG; /* negative */
17625796c8dcSSimon Schubert return res; /* there is no status to set */
17635796c8dcSSimon Schubert }
17645796c8dcSSimon Schubert workset.round=DEC_ROUND_CEILING;
17655796c8dcSSimon Schubert sub=0; /* add, please */
17665796c8dcSSimon Schubert } /* plus */
17675796c8dcSSimon Schubert else { /* lhs>rhs, do nextminus */
17685796c8dcSSimon Schubert /* +Infinity is the special case */
17695796c8dcSSimon Schubert if ((lhs->bits&(DECINF|DECNEG))==DECINF) {
17705796c8dcSSimon Schubert decSetMaxValue(res, set);
17715796c8dcSSimon Schubert return res; /* there is no status to set */
17725796c8dcSSimon Schubert }
17735796c8dcSSimon Schubert workset.round=DEC_ROUND_FLOOR;
17745796c8dcSSimon Schubert sub=DECNEG; /* subtract, please */
17755796c8dcSSimon Schubert } /* minus */
17765796c8dcSSimon Schubert decNumberZero(&dtiny); /* start with 0 */
17775796c8dcSSimon Schubert dtiny.lsu[0]=1; /* make number that is .. */
17785796c8dcSSimon Schubert dtiny.exponent=DEC_MIN_EMIN-1; /* .. smaller than tiniest */
17795796c8dcSSimon Schubert decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */
17805796c8dcSSimon Schubert /* turn off exceptions if the result is a normal number */
17815796c8dcSSimon Schubert /* (including Nmin), otherwise let all status through */
17825796c8dcSSimon Schubert if (decNumberIsNormal(res, set)) status=0;
17835796c8dcSSimon Schubert } /* unequal */
17845796c8dcSSimon Schubert } /* compare OK */
17855796c8dcSSimon Schubert } /* numeric */
17865796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
17875796c8dcSSimon Schubert return res;
17885796c8dcSSimon Schubert } /* decNumberNextToward */
17895796c8dcSSimon Schubert
17905796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
17915796c8dcSSimon Schubert /* decNumberOr -- OR two Numbers, digitwise */
17925796c8dcSSimon Schubert /* */
17935796c8dcSSimon Schubert /* This computes C = A | B */
17945796c8dcSSimon Schubert /* */
17955796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X|X) */
17965796c8dcSSimon Schubert /* lhs is A */
17975796c8dcSSimon Schubert /* rhs is B */
17985796c8dcSSimon Schubert /* set is the context (used for result length and error report) */
17995796c8dcSSimon Schubert /* */
18005796c8dcSSimon Schubert /* C must have space for set->digits digits. */
18015796c8dcSSimon Schubert /* */
18025796c8dcSSimon Schubert /* Logical function restrictions apply (see above); a NaN is */
18035796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
18045796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberOr(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)18055796c8dcSSimon Schubert decNumber * decNumberOr(decNumber *res, const decNumber *lhs,
18065796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
18075796c8dcSSimon Schubert const Unit *ua, *ub; /* -> operands */
18085796c8dcSSimon Schubert const Unit *msua, *msub; /* -> operand msus */
18095796c8dcSSimon Schubert Unit *uc, *msuc; /* -> result and its msu */
18105796c8dcSSimon Schubert Int msudigs; /* digits in res msu */
18115796c8dcSSimon Schubert #if DECCHECK
18125796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
18135796c8dcSSimon Schubert #endif
18145796c8dcSSimon Schubert
18155796c8dcSSimon Schubert if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
18165796c8dcSSimon Schubert || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
18175796c8dcSSimon Schubert decStatus(res, DEC_Invalid_operation, set);
18185796c8dcSSimon Schubert return res;
18195796c8dcSSimon Schubert }
18205796c8dcSSimon Schubert /* operands are valid */
18215796c8dcSSimon Schubert ua=lhs->lsu; /* bottom-up */
18225796c8dcSSimon Schubert ub=rhs->lsu; /* .. */
18235796c8dcSSimon Schubert uc=res->lsu; /* .. */
18245796c8dcSSimon Schubert msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */
18255796c8dcSSimon Schubert msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */
18265796c8dcSSimon Schubert msuc=uc+D2U(set->digits)-1; /* -> msu of result */
18275796c8dcSSimon Schubert msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */
18285796c8dcSSimon Schubert for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
18295796c8dcSSimon Schubert Unit a, b; /* extract units */
18305796c8dcSSimon Schubert if (ua>msua) a=0;
18315796c8dcSSimon Schubert else a=*ua;
18325796c8dcSSimon Schubert if (ub>msub) b=0;
18335796c8dcSSimon Schubert else b=*ub;
18345796c8dcSSimon Schubert *uc=0; /* can now write back */
18355796c8dcSSimon Schubert if (a|b) { /* maybe 1 bits to examine */
18365796c8dcSSimon Schubert Int i, j;
18375796c8dcSSimon Schubert /* This loop could be unrolled and/or use BIN2BCD tables */
18385796c8dcSSimon Schubert for (i=0; i<DECDPUN; i++) {
18395796c8dcSSimon Schubert if ((a|b)&1) *uc=*uc+(Unit)powers[i]; /* effect OR */
18405796c8dcSSimon Schubert j=a%10;
18415796c8dcSSimon Schubert a=a/10;
18425796c8dcSSimon Schubert j|=b%10;
18435796c8dcSSimon Schubert b=b/10;
18445796c8dcSSimon Schubert if (j>1) {
18455796c8dcSSimon Schubert decStatus(res, DEC_Invalid_operation, set);
18465796c8dcSSimon Schubert return res;
18475796c8dcSSimon Schubert }
18485796c8dcSSimon Schubert if (uc==msuc && i==msudigs-1) break; /* just did final digit */
18495796c8dcSSimon Schubert } /* each digit */
18505796c8dcSSimon Schubert } /* non-zero */
18515796c8dcSSimon Schubert } /* each unit */
18525796c8dcSSimon Schubert /* [here uc-1 is the msu of the result] */
18535796c8dcSSimon Schubert res->digits=decGetDigits(res->lsu, uc-res->lsu);
18545796c8dcSSimon Schubert res->exponent=0; /* integer */
18555796c8dcSSimon Schubert res->bits=0; /* sign=0 */
18565796c8dcSSimon Schubert return res; /* [no status to set] */
18575796c8dcSSimon Schubert } /* decNumberOr */
18585796c8dcSSimon Schubert
18595796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
18605796c8dcSSimon Schubert /* decNumberPlus -- prefix plus operator */
18615796c8dcSSimon Schubert /* */
18625796c8dcSSimon Schubert /* This computes C = 0 + A */
18635796c8dcSSimon Schubert /* */
18645796c8dcSSimon Schubert /* res is C, the result. C may be A */
18655796c8dcSSimon Schubert /* rhs is A */
18665796c8dcSSimon Schubert /* set is the context */
18675796c8dcSSimon Schubert /* */
18685796c8dcSSimon Schubert /* See also decNumberCopy for a quiet bitwise version of this. */
18695796c8dcSSimon Schubert /* C must have space for set->digits digits. */
18705796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
18715796c8dcSSimon Schubert /* This simply uses AddOp; Add will take fast path after preparing A. */
18725796c8dcSSimon Schubert /* Performance is a concern here, as this routine is often used to */
18735796c8dcSSimon Schubert /* check operands and apply rounding and overflow/underflow testing. */
18745796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberPlus(decNumber * res,const decNumber * rhs,decContext * set)18755796c8dcSSimon Schubert decNumber * decNumberPlus(decNumber *res, const decNumber *rhs,
18765796c8dcSSimon Schubert decContext *set) {
18775796c8dcSSimon Schubert decNumber dzero;
18785796c8dcSSimon Schubert uInt status=0; /* accumulator */
18795796c8dcSSimon Schubert #if DECCHECK
18805796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
18815796c8dcSSimon Schubert #endif
18825796c8dcSSimon Schubert
18835796c8dcSSimon Schubert decNumberZero(&dzero); /* make 0 */
18845796c8dcSSimon Schubert dzero.exponent=rhs->exponent; /* [no coefficient expansion] */
18855796c8dcSSimon Schubert decAddOp(res, &dzero, rhs, set, 0, &status);
18865796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
18875796c8dcSSimon Schubert #if DECCHECK
18885796c8dcSSimon Schubert decCheckInexact(res, set);
18895796c8dcSSimon Schubert #endif
18905796c8dcSSimon Schubert return res;
18915796c8dcSSimon Schubert } /* decNumberPlus */
18925796c8dcSSimon Schubert
18935796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
18945796c8dcSSimon Schubert /* decNumberMultiply -- multiply two Numbers */
18955796c8dcSSimon Schubert /* */
18965796c8dcSSimon Schubert /* This computes C = A x B */
18975796c8dcSSimon Schubert /* */
18985796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
18995796c8dcSSimon Schubert /* lhs is A */
19005796c8dcSSimon Schubert /* rhs is B */
19015796c8dcSSimon Schubert /* set is the context */
19025796c8dcSSimon Schubert /* */
19035796c8dcSSimon Schubert /* C must have space for set->digits digits. */
19045796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberMultiply(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)19055796c8dcSSimon Schubert decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs,
19065796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
19075796c8dcSSimon Schubert uInt status=0; /* accumulator */
19085796c8dcSSimon Schubert decMultiplyOp(res, lhs, rhs, set, &status);
19095796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
19105796c8dcSSimon Schubert #if DECCHECK
19115796c8dcSSimon Schubert decCheckInexact(res, set);
19125796c8dcSSimon Schubert #endif
19135796c8dcSSimon Schubert return res;
19145796c8dcSSimon Schubert } /* decNumberMultiply */
19155796c8dcSSimon Schubert
19165796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
19175796c8dcSSimon Schubert /* decNumberPower -- raise a number to a power */
19185796c8dcSSimon Schubert /* */
19195796c8dcSSimon Schubert /* This computes C = A ** B */
19205796c8dcSSimon Schubert /* */
19215796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X**X) */
19225796c8dcSSimon Schubert /* lhs is A */
19235796c8dcSSimon Schubert /* rhs is B */
19245796c8dcSSimon Schubert /* set is the context */
19255796c8dcSSimon Schubert /* */
19265796c8dcSSimon Schubert /* C must have space for set->digits digits. */
19275796c8dcSSimon Schubert /* */
19285796c8dcSSimon Schubert /* Mathematical function restrictions apply (see above); a NaN is */
19295796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
19305796c8dcSSimon Schubert /* */
19315796c8dcSSimon Schubert /* However, if 1999999997<=B<=999999999 and B is an integer then the */
19325796c8dcSSimon Schubert /* restrictions on A and the context are relaxed to the usual bounds, */
19335796c8dcSSimon Schubert /* for compatibility with the earlier (integer power only) version */
19345796c8dcSSimon Schubert /* of this function. */
19355796c8dcSSimon Schubert /* */
19365796c8dcSSimon Schubert /* When B is an integer, the result may be exact, even if rounded. */
19375796c8dcSSimon Schubert /* */
19385796c8dcSSimon Schubert /* The final result is rounded according to the context; it will */
19395796c8dcSSimon Schubert /* almost always be correctly rounded, but may be up to 1 ulp in */
19405796c8dcSSimon Schubert /* error in rare cases. */
19415796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberPower(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)19425796c8dcSSimon Schubert decNumber * decNumberPower(decNumber *res, const decNumber *lhs,
19435796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
19445796c8dcSSimon Schubert #if DECSUBSET
19455796c8dcSSimon Schubert decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
19465796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* .., rhs */
19475796c8dcSSimon Schubert #endif
19485796c8dcSSimon Schubert decNumber *allocdac=NULL; /* -> allocated acc buffer, iff used */
19495796c8dcSSimon Schubert decNumber *allocinv=NULL; /* -> allocated 1/x buffer, iff used */
19505796c8dcSSimon Schubert Int reqdigits=set->digits; /* requested DIGITS */
19515796c8dcSSimon Schubert Int n; /* rhs in binary */
19525796c8dcSSimon Schubert Flag rhsint=0; /* 1 if rhs is an integer */
19535796c8dcSSimon Schubert Flag useint=0; /* 1 if can use integer calculation */
19545796c8dcSSimon Schubert Flag isoddint=0; /* 1 if rhs is an integer and odd */
19555796c8dcSSimon Schubert Int i; /* work */
19565796c8dcSSimon Schubert #if DECSUBSET
19575796c8dcSSimon Schubert Int dropped; /* .. */
19585796c8dcSSimon Schubert #endif
19595796c8dcSSimon Schubert uInt needbytes; /* buffer size needed */
19605796c8dcSSimon Schubert Flag seenbit; /* seen a bit while powering */
19615796c8dcSSimon Schubert Int residue=0; /* rounding residue */
19625796c8dcSSimon Schubert uInt status=0; /* accumulators */
19635796c8dcSSimon Schubert uByte bits=0; /* result sign if errors */
19645796c8dcSSimon Schubert decContext aset; /* working context */
19655796c8dcSSimon Schubert decNumber dnOne; /* work value 1... */
19665796c8dcSSimon Schubert /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */
19675796c8dcSSimon Schubert decNumber dacbuff[D2N(DECBUFFER+9)];
19685796c8dcSSimon Schubert decNumber *dac=dacbuff; /* -> result accumulator */
19695796c8dcSSimon Schubert /* same again for possible 1/lhs calculation */
19705796c8dcSSimon Schubert decNumber invbuff[D2N(DECBUFFER+9)];
19715796c8dcSSimon Schubert
19725796c8dcSSimon Schubert #if DECCHECK
19735796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
19745796c8dcSSimon Schubert #endif
19755796c8dcSSimon Schubert
19765796c8dcSSimon Schubert do { /* protect allocated storage */
19775796c8dcSSimon Schubert #if DECSUBSET
19785796c8dcSSimon Schubert if (!set->extended) { /* reduce operands and set status, as needed */
19795796c8dcSSimon Schubert if (lhs->digits>reqdigits) {
19805796c8dcSSimon Schubert alloclhs=decRoundOperand(lhs, set, &status);
19815796c8dcSSimon Schubert if (alloclhs==NULL) break;
19825796c8dcSSimon Schubert lhs=alloclhs;
19835796c8dcSSimon Schubert }
19845796c8dcSSimon Schubert if (rhs->digits>reqdigits) {
19855796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, &status);
19865796c8dcSSimon Schubert if (allocrhs==NULL) break;
19875796c8dcSSimon Schubert rhs=allocrhs;
19885796c8dcSSimon Schubert }
19895796c8dcSSimon Schubert }
19905796c8dcSSimon Schubert #endif
19915796c8dcSSimon Schubert /* [following code does not require input rounding] */
19925796c8dcSSimon Schubert
19935796c8dcSSimon Schubert /* handle NaNs and rhs Infinity (lhs infinity is harder) */
19945796c8dcSSimon Schubert if (SPECIALARGS) {
19955796c8dcSSimon Schubert if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */
19965796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, &status);
19975796c8dcSSimon Schubert break;}
19985796c8dcSSimon Schubert if (decNumberIsInfinite(rhs)) { /* rhs Infinity */
19995796c8dcSSimon Schubert Flag rhsneg=rhs->bits&DECNEG; /* save rhs sign */
20005796c8dcSSimon Schubert if (decNumberIsNegative(lhs) /* lhs<0 */
20015796c8dcSSimon Schubert && !decNumberIsZero(lhs)) /* .. */
20025796c8dcSSimon Schubert status|=DEC_Invalid_operation;
20035796c8dcSSimon Schubert else { /* lhs >=0 */
20045796c8dcSSimon Schubert decNumberZero(&dnOne); /* set up 1 */
20055796c8dcSSimon Schubert dnOne.lsu[0]=1;
20065796c8dcSSimon Schubert decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */
20075796c8dcSSimon Schubert decNumberZero(res); /* prepare for 0/1/Infinity */
20085796c8dcSSimon Schubert if (decNumberIsNegative(dac)) { /* lhs<1 */
20095796c8dcSSimon Schubert if (rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */
20105796c8dcSSimon Schubert }
20115796c8dcSSimon Schubert else if (dac->lsu[0]==0) { /* lhs=1 */
20125796c8dcSSimon Schubert /* 1**Infinity is inexact, so return fully-padded 1.0000 */
20135796c8dcSSimon Schubert Int shift=set->digits-1;
20145796c8dcSSimon Schubert *res->lsu=1; /* was 0, make int 1 */
20155796c8dcSSimon Schubert res->digits=decShiftToMost(res->lsu, 1, shift);
20165796c8dcSSimon Schubert res->exponent=-shift; /* make 1.0000... */
20175796c8dcSSimon Schubert status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */
20185796c8dcSSimon Schubert }
20195796c8dcSSimon Schubert else { /* lhs>1 */
20205796c8dcSSimon Schubert if (!rhsneg) res->bits|=DECINF; /* +Infinity [else is +0] */
20215796c8dcSSimon Schubert }
20225796c8dcSSimon Schubert } /* lhs>=0 */
20235796c8dcSSimon Schubert break;}
20245796c8dcSSimon Schubert /* [lhs infinity drops through] */
20255796c8dcSSimon Schubert } /* specials */
20265796c8dcSSimon Schubert
20275796c8dcSSimon Schubert /* Original rhs may be an integer that fits and is in range */
20285796c8dcSSimon Schubert n=decGetInt(rhs);
20295796c8dcSSimon Schubert if (n!=BADINT) { /* it is an integer */
20305796c8dcSSimon Schubert rhsint=1; /* record the fact for 1**n */
20315796c8dcSSimon Schubert isoddint=(Flag)n&1; /* [works even if big] */
20325796c8dcSSimon Schubert if (n!=BIGEVEN && n!=BIGODD) /* can use integer path? */
20335796c8dcSSimon Schubert useint=1; /* looks good */
20345796c8dcSSimon Schubert }
20355796c8dcSSimon Schubert
20365796c8dcSSimon Schubert if (decNumberIsNegative(lhs) /* -x .. */
20375796c8dcSSimon Schubert && isoddint) bits=DECNEG; /* .. to an odd power */
20385796c8dcSSimon Schubert
20395796c8dcSSimon Schubert /* handle LHS infinity */
20405796c8dcSSimon Schubert if (decNumberIsInfinite(lhs)) { /* [NaNs already handled] */
20415796c8dcSSimon Schubert uByte rbits=rhs->bits; /* save */
20425796c8dcSSimon Schubert decNumberZero(res); /* prepare */
20435796c8dcSSimon Schubert if (n==0) *res->lsu=1; /* [-]Inf**0 => 1 */
20445796c8dcSSimon Schubert else {
20455796c8dcSSimon Schubert /* -Inf**nonint -> error */
20465796c8dcSSimon Schubert if (!rhsint && decNumberIsNegative(lhs)) {
20475796c8dcSSimon Schubert status|=DEC_Invalid_operation; /* -Inf**nonint is error */
20485796c8dcSSimon Schubert break;}
20495796c8dcSSimon Schubert if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */
20505796c8dcSSimon Schubert /* [otherwise will be 0 or -0] */
20515796c8dcSSimon Schubert res->bits=bits;
20525796c8dcSSimon Schubert }
20535796c8dcSSimon Schubert break;}
20545796c8dcSSimon Schubert
20555796c8dcSSimon Schubert /* similarly handle LHS zero */
20565796c8dcSSimon Schubert if (decNumberIsZero(lhs)) {
20575796c8dcSSimon Schubert if (n==0) { /* 0**0 => Error */
20585796c8dcSSimon Schubert #if DECSUBSET
20595796c8dcSSimon Schubert if (!set->extended) { /* [unless subset] */
20605796c8dcSSimon Schubert decNumberZero(res);
20615796c8dcSSimon Schubert *res->lsu=1; /* return 1 */
20625796c8dcSSimon Schubert break;}
20635796c8dcSSimon Schubert #endif
20645796c8dcSSimon Schubert status|=DEC_Invalid_operation;
20655796c8dcSSimon Schubert }
20665796c8dcSSimon Schubert else { /* 0**x */
20675796c8dcSSimon Schubert uByte rbits=rhs->bits; /* save */
20685796c8dcSSimon Schubert if (rbits & DECNEG) { /* was a 0**(-n) */
20695796c8dcSSimon Schubert #if DECSUBSET
20705796c8dcSSimon Schubert if (!set->extended) { /* [bad if subset] */
20715796c8dcSSimon Schubert status|=DEC_Invalid_operation;
20725796c8dcSSimon Schubert break;}
20735796c8dcSSimon Schubert #endif
20745796c8dcSSimon Schubert bits|=DECINF;
20755796c8dcSSimon Schubert }
20765796c8dcSSimon Schubert decNumberZero(res); /* prepare */
20775796c8dcSSimon Schubert /* [otherwise will be 0 or -0] */
20785796c8dcSSimon Schubert res->bits=bits;
20795796c8dcSSimon Schubert }
20805796c8dcSSimon Schubert break;}
20815796c8dcSSimon Schubert
20825796c8dcSSimon Schubert /* here both lhs and rhs are finite; rhs==0 is handled in the */
20835796c8dcSSimon Schubert /* integer path. Next handle the non-integer cases */
20845796c8dcSSimon Schubert if (!useint) { /* non-integral rhs */
20855796c8dcSSimon Schubert /* any -ve lhs is bad, as is either operand or context out of */
20865796c8dcSSimon Schubert /* bounds */
20875796c8dcSSimon Schubert if (decNumberIsNegative(lhs)) {
20885796c8dcSSimon Schubert status|=DEC_Invalid_operation;
20895796c8dcSSimon Schubert break;}
20905796c8dcSSimon Schubert if (decCheckMath(lhs, set, &status)
20915796c8dcSSimon Schubert || decCheckMath(rhs, set, &status)) break; /* variable status */
20925796c8dcSSimon Schubert
20935796c8dcSSimon Schubert decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
20945796c8dcSSimon Schubert aset.emax=DEC_MAX_MATH; /* usual bounds */
20955796c8dcSSimon Schubert aset.emin=-DEC_MAX_MATH; /* .. */
20965796c8dcSSimon Schubert aset.clamp=0; /* and no concrete format */
20975796c8dcSSimon Schubert
20985796c8dcSSimon Schubert /* calculate the result using exp(ln(lhs)*rhs), which can */
20995796c8dcSSimon Schubert /* all be done into the accumulator, dac. The precision needed */
21005796c8dcSSimon Schubert /* is enough to contain the full information in the lhs (which */
21015796c8dcSSimon Schubert /* is the total digits, including exponent), or the requested */
21025796c8dcSSimon Schubert /* precision, if larger, + 4; 6 is used for the exponent */
21035796c8dcSSimon Schubert /* maximum length, and this is also used when it is shorter */
21045796c8dcSSimon Schubert /* than the requested digits as it greatly reduces the >0.5 ulp */
21055796c8dcSSimon Schubert /* cases at little cost (because Ln doubles digits each */
21065796c8dcSSimon Schubert /* iteration so a few extra digits rarely causes an extra */
21075796c8dcSSimon Schubert /* iteration) */
21085796c8dcSSimon Schubert aset.digits=MAXI(lhs->digits, set->digits)+6+4;
21095796c8dcSSimon Schubert } /* non-integer rhs */
21105796c8dcSSimon Schubert
21115796c8dcSSimon Schubert else { /* rhs is in-range integer */
21125796c8dcSSimon Schubert if (n==0) { /* x**0 = 1 */
21135796c8dcSSimon Schubert /* (0**0 was handled above) */
21145796c8dcSSimon Schubert decNumberZero(res); /* result=1 */
21155796c8dcSSimon Schubert *res->lsu=1; /* .. */
21165796c8dcSSimon Schubert break;}
21175796c8dcSSimon Schubert /* rhs is a non-zero integer */
21185796c8dcSSimon Schubert if (n<0) n=-n; /* use abs(n) */
21195796c8dcSSimon Schubert
21205796c8dcSSimon Schubert aset=*set; /* clone the context */
21215796c8dcSSimon Schubert aset.round=DEC_ROUND_HALF_EVEN; /* internally use balanced */
21225796c8dcSSimon Schubert /* calculate the working DIGITS */
21235796c8dcSSimon Schubert aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2;
21245796c8dcSSimon Schubert #if DECSUBSET
21255796c8dcSSimon Schubert if (!set->extended) aset.digits--; /* use classic precision */
21265796c8dcSSimon Schubert #endif
21275796c8dcSSimon Schubert /* it's an error if this is more than can be handled */
21285796c8dcSSimon Schubert if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;}
21295796c8dcSSimon Schubert } /* integer path */
21305796c8dcSSimon Schubert
21315796c8dcSSimon Schubert /* aset.digits is the count of digits for the accumulator needed */
21325796c8dcSSimon Schubert /* if accumulator is too long for local storage, then allocate */
21335796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit);
21345796c8dcSSimon Schubert /* [needbytes also used below if 1/lhs needed] */
21355796c8dcSSimon Schubert if (needbytes>sizeof(dacbuff)) {
21365796c8dcSSimon Schubert allocdac=(decNumber *)malloc(needbytes);
21375796c8dcSSimon Schubert if (allocdac==NULL) { /* hopeless -- abandon */
21385796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
21395796c8dcSSimon Schubert break;}
21405796c8dcSSimon Schubert dac=allocdac; /* use the allocated space */
21415796c8dcSSimon Schubert }
21425796c8dcSSimon Schubert /* here, aset is set up and accumulator is ready for use */
21435796c8dcSSimon Schubert
21445796c8dcSSimon Schubert if (!useint) { /* non-integral rhs */
21455796c8dcSSimon Schubert /* x ** y; special-case x=1 here as it will otherwise always */
21465796c8dcSSimon Schubert /* reduce to integer 1; decLnOp has a fastpath which detects */
21475796c8dcSSimon Schubert /* the case of x=1 */
21485796c8dcSSimon Schubert decLnOp(dac, lhs, &aset, &status); /* dac=ln(lhs) */
21495796c8dcSSimon Schubert /* [no error possible, as lhs 0 already handled] */
21505796c8dcSSimon Schubert if (ISZERO(dac)) { /* x==1, 1.0, etc. */
21515796c8dcSSimon Schubert /* need to return fully-padded 1.0000 etc., but rhsint->1 */
21525796c8dcSSimon Schubert *dac->lsu=1; /* was 0, make int 1 */
21535796c8dcSSimon Schubert if (!rhsint) { /* add padding */
21545796c8dcSSimon Schubert Int shift=set->digits-1;
21555796c8dcSSimon Schubert dac->digits=decShiftToMost(dac->lsu, 1, shift);
21565796c8dcSSimon Schubert dac->exponent=-shift; /* make 1.0000... */
21575796c8dcSSimon Schubert status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */
21585796c8dcSSimon Schubert }
21595796c8dcSSimon Schubert }
21605796c8dcSSimon Schubert else {
21615796c8dcSSimon Schubert decMultiplyOp(dac, dac, rhs, &aset, &status); /* dac=dac*rhs */
21625796c8dcSSimon Schubert decExpOp(dac, dac, &aset, &status); /* dac=exp(dac) */
21635796c8dcSSimon Schubert }
21645796c8dcSSimon Schubert /* and drop through for final rounding */
21655796c8dcSSimon Schubert } /* non-integer rhs */
21665796c8dcSSimon Schubert
21675796c8dcSSimon Schubert else { /* carry on with integer */
21685796c8dcSSimon Schubert decNumberZero(dac); /* acc=1 */
21695796c8dcSSimon Schubert *dac->lsu=1; /* .. */
21705796c8dcSSimon Schubert
21715796c8dcSSimon Schubert /* if a negative power the constant 1 is needed, and if not subset */
21725796c8dcSSimon Schubert /* invert the lhs now rather than inverting the result later */
21735796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */
21745796c8dcSSimon Schubert decNumber *inv=invbuff; /* asssume use fixed buffer */
21755796c8dcSSimon Schubert decNumberCopy(&dnOne, dac); /* dnOne=1; [needed now or later] */
21765796c8dcSSimon Schubert #if DECSUBSET
21775796c8dcSSimon Schubert if (set->extended) { /* need to calculate 1/lhs */
21785796c8dcSSimon Schubert #endif
21795796c8dcSSimon Schubert /* divide lhs into 1, putting result in dac [dac=1/dac] */
21805796c8dcSSimon Schubert decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status);
21815796c8dcSSimon Schubert /* now locate or allocate space for the inverted lhs */
21825796c8dcSSimon Schubert if (needbytes>sizeof(invbuff)) {
21835796c8dcSSimon Schubert allocinv=(decNumber *)malloc(needbytes);
21845796c8dcSSimon Schubert if (allocinv==NULL) { /* hopeless -- abandon */
21855796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
21865796c8dcSSimon Schubert break;}
21875796c8dcSSimon Schubert inv=allocinv; /* use the allocated space */
21885796c8dcSSimon Schubert }
21895796c8dcSSimon Schubert /* [inv now points to big-enough buffer or allocated storage] */
21905796c8dcSSimon Schubert decNumberCopy(inv, dac); /* copy the 1/lhs */
21915796c8dcSSimon Schubert decNumberCopy(dac, &dnOne); /* restore acc=1 */
21925796c8dcSSimon Schubert lhs=inv; /* .. and go forward with new lhs */
21935796c8dcSSimon Schubert #if DECSUBSET
21945796c8dcSSimon Schubert }
21955796c8dcSSimon Schubert #endif
21965796c8dcSSimon Schubert }
21975796c8dcSSimon Schubert
21985796c8dcSSimon Schubert /* Raise-to-the-power loop... */
21995796c8dcSSimon Schubert seenbit=0; /* set once a 1-bit is encountered */
22005796c8dcSSimon Schubert for (i=1;;i++){ /* for each bit [top bit ignored] */
22015796c8dcSSimon Schubert /* abandon if had overflow or terminal underflow */
22025796c8dcSSimon Schubert if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
22035796c8dcSSimon Schubert if (status&DEC_Overflow || ISZERO(dac)) break;
22045796c8dcSSimon Schubert }
22055796c8dcSSimon Schubert /* [the following two lines revealed an optimizer bug in a C++ */
22065796c8dcSSimon Schubert /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */
22075796c8dcSSimon Schubert n=n<<1; /* move next bit to testable position */
22085796c8dcSSimon Schubert if (n<0) { /* top bit is set */
22095796c8dcSSimon Schubert seenbit=1; /* OK, significant bit seen */
22105796c8dcSSimon Schubert decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */
22115796c8dcSSimon Schubert }
22125796c8dcSSimon Schubert if (i==31) break; /* that was the last bit */
22135796c8dcSSimon Schubert if (!seenbit) continue; /* no need to square 1 */
22145796c8dcSSimon Schubert decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */
22155796c8dcSSimon Schubert } /*i*/ /* 32 bits */
22165796c8dcSSimon Schubert
22175796c8dcSSimon Schubert /* complete internal overflow or underflow processing */
22185796c8dcSSimon Schubert if (status & (DEC_Overflow|DEC_Underflow)) {
22195796c8dcSSimon Schubert #if DECSUBSET
22205796c8dcSSimon Schubert /* If subset, and power was negative, reverse the kind of -erflow */
22215796c8dcSSimon Schubert /* [1/x not yet done] */
22225796c8dcSSimon Schubert if (!set->extended && decNumberIsNegative(rhs)) {
22235796c8dcSSimon Schubert if (status & DEC_Overflow)
22245796c8dcSSimon Schubert status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal;
22255796c8dcSSimon Schubert else { /* trickier -- Underflow may or may not be set */
22265796c8dcSSimon Schubert status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */
22275796c8dcSSimon Schubert status|=DEC_Overflow;
22285796c8dcSSimon Schubert }
22295796c8dcSSimon Schubert }
22305796c8dcSSimon Schubert #endif
22315796c8dcSSimon Schubert dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */
22325796c8dcSSimon Schubert /* round subnormals [to set.digits rather than aset.digits] */
22335796c8dcSSimon Schubert /* or set overflow result similarly as required */
22345796c8dcSSimon Schubert decFinalize(dac, set, &residue, &status);
22355796c8dcSSimon Schubert decNumberCopy(res, dac); /* copy to result (is now OK length) */
22365796c8dcSSimon Schubert break;
22375796c8dcSSimon Schubert }
22385796c8dcSSimon Schubert
22395796c8dcSSimon Schubert #if DECSUBSET
22405796c8dcSSimon Schubert if (!set->extended && /* subset math */
22415796c8dcSSimon Schubert decNumberIsNegative(rhs)) { /* was a **-n [hence digits>0] */
22425796c8dcSSimon Schubert /* so divide result into 1 [dac=1/dac] */
22435796c8dcSSimon Schubert decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status);
22445796c8dcSSimon Schubert }
22455796c8dcSSimon Schubert #endif
22465796c8dcSSimon Schubert } /* rhs integer path */
22475796c8dcSSimon Schubert
22485796c8dcSSimon Schubert /* reduce result to the requested length and copy to result */
22495796c8dcSSimon Schubert decCopyFit(res, dac, set, &residue, &status);
22505796c8dcSSimon Schubert decFinish(res, set, &residue, &status); /* final cleanup */
22515796c8dcSSimon Schubert #if DECSUBSET
22525796c8dcSSimon Schubert if (!set->extended) decTrim(res, set, 0, 1, &dropped); /* trailing zeros */
22535796c8dcSSimon Schubert #endif
22545796c8dcSSimon Schubert } while(0); /* end protected */
22555796c8dcSSimon Schubert
2256a45ae5f8SJohn Marino free(allocdac); /* drop any storage used */
2257a45ae5f8SJohn Marino free(allocinv); /* .. */
22585796c8dcSSimon Schubert #if DECSUBSET
2259a45ae5f8SJohn Marino free(alloclhs); /* .. */
2260a45ae5f8SJohn Marino free(allocrhs); /* .. */
22615796c8dcSSimon Schubert #endif
22625796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
22635796c8dcSSimon Schubert #if DECCHECK
22645796c8dcSSimon Schubert decCheckInexact(res, set);
22655796c8dcSSimon Schubert #endif
22665796c8dcSSimon Schubert return res;
22675796c8dcSSimon Schubert } /* decNumberPower */
22685796c8dcSSimon Schubert
22695796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
22705796c8dcSSimon Schubert /* decNumberQuantize -- force exponent to requested value */
22715796c8dcSSimon Schubert /* */
22725796c8dcSSimon Schubert /* This computes C = op(A, B), where op adjusts the coefficient */
22735796c8dcSSimon Schubert /* of C (by rounding or shifting) such that the exponent (-scale) */
22745796c8dcSSimon Schubert /* of C has exponent of B. The numerical value of C will equal A, */
22755796c8dcSSimon Schubert /* except for the effects of any rounding that occurred. */
22765796c8dcSSimon Schubert /* */
22775796c8dcSSimon Schubert /* res is C, the result. C may be A or B */
22785796c8dcSSimon Schubert /* lhs is A, the number to adjust */
22795796c8dcSSimon Schubert /* rhs is B, the number with exponent to match */
22805796c8dcSSimon Schubert /* set is the context */
22815796c8dcSSimon Schubert /* */
22825796c8dcSSimon Schubert /* C must have space for set->digits digits. */
22835796c8dcSSimon Schubert /* */
22845796c8dcSSimon Schubert /* Unless there is an error or the result is infinite, the exponent */
22855796c8dcSSimon Schubert /* after the operation is guaranteed to be equal to that of B. */
22865796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberQuantize(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)22875796c8dcSSimon Schubert decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs,
22885796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
22895796c8dcSSimon Schubert uInt status=0; /* accumulator */
22905796c8dcSSimon Schubert decQuantizeOp(res, lhs, rhs, set, 1, &status);
22915796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
22925796c8dcSSimon Schubert return res;
22935796c8dcSSimon Schubert } /* decNumberQuantize */
22945796c8dcSSimon Schubert
22955796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
22965796c8dcSSimon Schubert /* decNumberReduce -- remove trailing zeros */
22975796c8dcSSimon Schubert /* */
22985796c8dcSSimon Schubert /* This computes C = 0 + A, and normalizes the result */
22995796c8dcSSimon Schubert /* */
23005796c8dcSSimon Schubert /* res is C, the result. C may be A */
23015796c8dcSSimon Schubert /* rhs is A */
23025796c8dcSSimon Schubert /* set is the context */
23035796c8dcSSimon Schubert /* */
23045796c8dcSSimon Schubert /* C must have space for set->digits digits. */
23055796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
23065796c8dcSSimon Schubert /* Previously known as Normalize */
decNumberNormalize(decNumber * res,const decNumber * rhs,decContext * set)23075796c8dcSSimon Schubert decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs,
23085796c8dcSSimon Schubert decContext *set) {
23095796c8dcSSimon Schubert return decNumberReduce(res, rhs, set);
23105796c8dcSSimon Schubert } /* decNumberNormalize */
23115796c8dcSSimon Schubert
decNumberReduce(decNumber * res,const decNumber * rhs,decContext * set)23125796c8dcSSimon Schubert decNumber * decNumberReduce(decNumber *res, const decNumber *rhs,
23135796c8dcSSimon Schubert decContext *set) {
23145796c8dcSSimon Schubert #if DECSUBSET
23155796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
23165796c8dcSSimon Schubert #endif
23175796c8dcSSimon Schubert uInt status=0; /* as usual */
23185796c8dcSSimon Schubert Int residue=0; /* as usual */
23195796c8dcSSimon Schubert Int dropped; /* work */
23205796c8dcSSimon Schubert
23215796c8dcSSimon Schubert #if DECCHECK
23225796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
23235796c8dcSSimon Schubert #endif
23245796c8dcSSimon Schubert
23255796c8dcSSimon Schubert do { /* protect allocated storage */
23265796c8dcSSimon Schubert #if DECSUBSET
23275796c8dcSSimon Schubert if (!set->extended) {
23285796c8dcSSimon Schubert /* reduce operand and set lostDigits status, as needed */
23295796c8dcSSimon Schubert if (rhs->digits>set->digits) {
23305796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, &status);
23315796c8dcSSimon Schubert if (allocrhs==NULL) break;
23325796c8dcSSimon Schubert rhs=allocrhs;
23335796c8dcSSimon Schubert }
23345796c8dcSSimon Schubert }
23355796c8dcSSimon Schubert #endif
23365796c8dcSSimon Schubert /* [following code does not require input rounding] */
23375796c8dcSSimon Schubert
23385796c8dcSSimon Schubert /* Infinities copy through; NaNs need usual treatment */
23395796c8dcSSimon Schubert if (decNumberIsNaN(rhs)) {
23405796c8dcSSimon Schubert decNaNs(res, rhs, NULL, set, &status);
23415796c8dcSSimon Schubert break;
23425796c8dcSSimon Schubert }
23435796c8dcSSimon Schubert
23445796c8dcSSimon Schubert /* reduce result to the requested length and copy to result */
23455796c8dcSSimon Schubert decCopyFit(res, rhs, set, &residue, &status); /* copy & round */
23465796c8dcSSimon Schubert decFinish(res, set, &residue, &status); /* cleanup/set flags */
23475796c8dcSSimon Schubert decTrim(res, set, 1, 0, &dropped); /* normalize in place */
23485796c8dcSSimon Schubert /* [may clamp] */
23495796c8dcSSimon Schubert } while(0); /* end protected */
23505796c8dcSSimon Schubert
23515796c8dcSSimon Schubert #if DECSUBSET
2352a45ae5f8SJohn Marino free(allocrhs); /* .. */
23535796c8dcSSimon Schubert #endif
23545796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);/* then report status */
23555796c8dcSSimon Schubert return res;
23565796c8dcSSimon Schubert } /* decNumberReduce */
23575796c8dcSSimon Schubert
23585796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
23595796c8dcSSimon Schubert /* decNumberRescale -- force exponent to requested value */
23605796c8dcSSimon Schubert /* */
23615796c8dcSSimon Schubert /* This computes C = op(A, B), where op adjusts the coefficient */
23625796c8dcSSimon Schubert /* of C (by rounding or shifting) such that the exponent (-scale) */
23635796c8dcSSimon Schubert /* of C has the value B. The numerical value of C will equal A, */
23645796c8dcSSimon Schubert /* except for the effects of any rounding that occurred. */
23655796c8dcSSimon Schubert /* */
23665796c8dcSSimon Schubert /* res is C, the result. C may be A or B */
23675796c8dcSSimon Schubert /* lhs is A, the number to adjust */
23685796c8dcSSimon Schubert /* rhs is B, the requested exponent */
23695796c8dcSSimon Schubert /* set is the context */
23705796c8dcSSimon Schubert /* */
23715796c8dcSSimon Schubert /* C must have space for set->digits digits. */
23725796c8dcSSimon Schubert /* */
23735796c8dcSSimon Schubert /* Unless there is an error or the result is infinite, the exponent */
23745796c8dcSSimon Schubert /* after the operation is guaranteed to be equal to B. */
23755796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberRescale(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)23765796c8dcSSimon Schubert decNumber * decNumberRescale(decNumber *res, const decNumber *lhs,
23775796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
23785796c8dcSSimon Schubert uInt status=0; /* accumulator */
23795796c8dcSSimon Schubert decQuantizeOp(res, lhs, rhs, set, 0, &status);
23805796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
23815796c8dcSSimon Schubert return res;
23825796c8dcSSimon Schubert } /* decNumberRescale */
23835796c8dcSSimon Schubert
23845796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
23855796c8dcSSimon Schubert /* decNumberRemainder -- divide and return remainder */
23865796c8dcSSimon Schubert /* */
23875796c8dcSSimon Schubert /* This computes C = A % B */
23885796c8dcSSimon Schubert /* */
23895796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X%X) */
23905796c8dcSSimon Schubert /* lhs is A */
23915796c8dcSSimon Schubert /* rhs is B */
23925796c8dcSSimon Schubert /* set is the context */
23935796c8dcSSimon Schubert /* */
23945796c8dcSSimon Schubert /* C must have space for set->digits digits. */
23955796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberRemainder(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)23965796c8dcSSimon Schubert decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs,
23975796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
23985796c8dcSSimon Schubert uInt status=0; /* accumulator */
23995796c8dcSSimon Schubert decDivideOp(res, lhs, rhs, set, REMAINDER, &status);
24005796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
24015796c8dcSSimon Schubert #if DECCHECK
24025796c8dcSSimon Schubert decCheckInexact(res, set);
24035796c8dcSSimon Schubert #endif
24045796c8dcSSimon Schubert return res;
24055796c8dcSSimon Schubert } /* decNumberRemainder */
24065796c8dcSSimon Schubert
24075796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
24085796c8dcSSimon Schubert /* decNumberRemainderNear -- divide and return remainder from nearest */
24095796c8dcSSimon Schubert /* */
24105796c8dcSSimon Schubert /* This computes C = A % B, where % is the IEEE remainder operator */
24115796c8dcSSimon Schubert /* */
24125796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X%X) */
24135796c8dcSSimon Schubert /* lhs is A */
24145796c8dcSSimon Schubert /* rhs is B */
24155796c8dcSSimon Schubert /* set is the context */
24165796c8dcSSimon Schubert /* */
24175796c8dcSSimon Schubert /* C must have space for set->digits digits. */
24185796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberRemainderNear(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)24195796c8dcSSimon Schubert decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs,
24205796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
24215796c8dcSSimon Schubert uInt status=0; /* accumulator */
24225796c8dcSSimon Schubert decDivideOp(res, lhs, rhs, set, REMNEAR, &status);
24235796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
24245796c8dcSSimon Schubert #if DECCHECK
24255796c8dcSSimon Schubert decCheckInexact(res, set);
24265796c8dcSSimon Schubert #endif
24275796c8dcSSimon Schubert return res;
24285796c8dcSSimon Schubert } /* decNumberRemainderNear */
24295796c8dcSSimon Schubert
24305796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
24315796c8dcSSimon Schubert /* decNumberRotate -- rotate the coefficient of a Number left/right */
24325796c8dcSSimon Schubert /* */
24335796c8dcSSimon Schubert /* This computes C = A rot B (in base ten and rotating set->digits */
24345796c8dcSSimon Schubert /* digits). */
24355796c8dcSSimon Schubert /* */
24365796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=XrotX) */
24375796c8dcSSimon Schubert /* lhs is A */
24385796c8dcSSimon Schubert /* rhs is B, the number of digits to rotate (-ve to right) */
24395796c8dcSSimon Schubert /* set is the context */
24405796c8dcSSimon Schubert /* */
24415796c8dcSSimon Schubert /* The digits of the coefficient of A are rotated to the left (if B */
24425796c8dcSSimon Schubert /* is positive) or to the right (if B is negative) without adjusting */
24435796c8dcSSimon Schubert /* the exponent or the sign of A. If lhs->digits is less than */
24445796c8dcSSimon Schubert /* set->digits the coefficient is padded with zeros on the left */
24455796c8dcSSimon Schubert /* before the rotate. Any leading zeros in the result are removed */
24465796c8dcSSimon Schubert /* as usual. */
24475796c8dcSSimon Schubert /* */
24485796c8dcSSimon Schubert /* B must be an integer (q=0) and in the range -set->digits through */
24495796c8dcSSimon Schubert /* +set->digits. */
24505796c8dcSSimon Schubert /* C must have space for set->digits digits. */
24515796c8dcSSimon Schubert /* NaNs are propagated as usual. Infinities are unaffected (but */
24525796c8dcSSimon Schubert /* B must be valid). No status is set unless B is invalid or an */
24535796c8dcSSimon Schubert /* operand is an sNaN. */
24545796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberRotate(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)24555796c8dcSSimon Schubert decNumber * decNumberRotate(decNumber *res, const decNumber *lhs,
24565796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
24575796c8dcSSimon Schubert uInt status=0; /* accumulator */
24585796c8dcSSimon Schubert Int rotate; /* rhs as an Int */
24595796c8dcSSimon Schubert
24605796c8dcSSimon Schubert #if DECCHECK
24615796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
24625796c8dcSSimon Schubert #endif
24635796c8dcSSimon Schubert
24645796c8dcSSimon Schubert /* NaNs propagate as normal */
24655796c8dcSSimon Schubert if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
24665796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, &status);
24675796c8dcSSimon Schubert /* rhs must be an integer */
24685796c8dcSSimon Schubert else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
24695796c8dcSSimon Schubert status=DEC_Invalid_operation;
24705796c8dcSSimon Schubert else { /* both numeric, rhs is an integer */
24715796c8dcSSimon Schubert rotate=decGetInt(rhs); /* [cannot fail] */
24725796c8dcSSimon Schubert if (rotate==BADINT /* something bad .. */
24735796c8dcSSimon Schubert || rotate==BIGODD || rotate==BIGEVEN /* .. very big .. */
24745796c8dcSSimon Schubert || abs(rotate)>set->digits) /* .. or out of range */
24755796c8dcSSimon Schubert status=DEC_Invalid_operation;
24765796c8dcSSimon Schubert else { /* rhs is OK */
24775796c8dcSSimon Schubert decNumberCopy(res, lhs);
24785796c8dcSSimon Schubert /* convert -ve rotate to equivalent positive rotation */
24795796c8dcSSimon Schubert if (rotate<0) rotate=set->digits+rotate;
24805796c8dcSSimon Schubert if (rotate!=0 && rotate!=set->digits /* zero or full rotation */
24815796c8dcSSimon Schubert && !decNumberIsInfinite(res)) { /* lhs was infinite */
24825796c8dcSSimon Schubert /* left-rotate to do; 0 < rotate < set->digits */
24835796c8dcSSimon Schubert uInt units, shift; /* work */
24845796c8dcSSimon Schubert uInt msudigits; /* digits in result msu */
24855796c8dcSSimon Schubert Unit *msu=res->lsu+D2U(res->digits)-1; /* current msu */
24865796c8dcSSimon Schubert Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */
24875796c8dcSSimon Schubert for (msu++; msu<=msumax; msu++) *msu=0; /* ensure high units=0 */
24885796c8dcSSimon Schubert res->digits=set->digits; /* now full-length */
24895796c8dcSSimon Schubert msudigits=MSUDIGITS(res->digits); /* actual digits in msu */
24905796c8dcSSimon Schubert
24915796c8dcSSimon Schubert /* rotation here is done in-place, in three steps */
24925796c8dcSSimon Schubert /* 1. shift all to least up to one unit to unit-align final */
24935796c8dcSSimon Schubert /* lsd [any digits shifted out are rotated to the left, */
24945796c8dcSSimon Schubert /* abutted to the original msd (which may require split)] */
24955796c8dcSSimon Schubert /* */
24965796c8dcSSimon Schubert /* [if there are no whole units left to rotate, the */
24975796c8dcSSimon Schubert /* rotation is now complete] */
24985796c8dcSSimon Schubert /* */
24995796c8dcSSimon Schubert /* 2. shift to least, from below the split point only, so that */
25005796c8dcSSimon Schubert /* the final msd is in the right place in its Unit [any */
25015796c8dcSSimon Schubert /* digits shifted out will fit exactly in the current msu, */
25025796c8dcSSimon Schubert /* left aligned, no split required] */
25035796c8dcSSimon Schubert /* */
25045796c8dcSSimon Schubert /* 3. rotate all the units by reversing left part, right */
25055796c8dcSSimon Schubert /* part, and then whole */
25065796c8dcSSimon Schubert /* */
25075796c8dcSSimon Schubert /* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */
25085796c8dcSSimon Schubert /* */
25095796c8dcSSimon Schubert /* start: 00a bcd efg hij klm npq */
25105796c8dcSSimon Schubert /* */
25115796c8dcSSimon Schubert /* 1a 000 0ab cde fgh|ijk lmn [pq saved] */
25125796c8dcSSimon Schubert /* 1b 00p qab cde fgh|ijk lmn */
25135796c8dcSSimon Schubert /* */
25145796c8dcSSimon Schubert /* 2a 00p qab cde fgh|00i jkl [mn saved] */
25155796c8dcSSimon Schubert /* 2b mnp qab cde fgh|00i jkl */
25165796c8dcSSimon Schubert /* */
25175796c8dcSSimon Schubert /* 3a fgh cde qab mnp|00i jkl */
25185796c8dcSSimon Schubert /* 3b fgh cde qab mnp|jkl 00i */
25195796c8dcSSimon Schubert /* 3c 00i jkl mnp qab cde fgh */
25205796c8dcSSimon Schubert
25215796c8dcSSimon Schubert /* Step 1: amount to shift is the partial right-rotate count */
25225796c8dcSSimon Schubert rotate=set->digits-rotate; /* make it right-rotate */
25235796c8dcSSimon Schubert units=rotate/DECDPUN; /* whole units to rotate */
25245796c8dcSSimon Schubert shift=rotate%DECDPUN; /* left-over digits count */
25255796c8dcSSimon Schubert if (shift>0) { /* not an exact number of units */
25265796c8dcSSimon Schubert uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */
25275796c8dcSSimon Schubert decShiftToLeast(res->lsu, D2U(res->digits), shift);
25285796c8dcSSimon Schubert if (shift>msudigits) { /* msumax-1 needs >0 digits */
25295796c8dcSSimon Schubert uInt rem=save%powers[shift-msudigits];/* split save */
25305796c8dcSSimon Schubert *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */
25315796c8dcSSimon Schubert *(msumax-1)=*(msumax-1)
25325796c8dcSSimon Schubert +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */
25335796c8dcSSimon Schubert }
25345796c8dcSSimon Schubert else { /* all fits in msumax */
25355796c8dcSSimon Schubert *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */
25365796c8dcSSimon Schubert }
25375796c8dcSSimon Schubert } /* digits shift needed */
25385796c8dcSSimon Schubert
25395796c8dcSSimon Schubert /* If whole units to rotate... */
25405796c8dcSSimon Schubert if (units>0) { /* some to do */
25415796c8dcSSimon Schubert /* Step 2: the units to touch are the whole ones in rotate, */
25425796c8dcSSimon Schubert /* if any, and the shift is DECDPUN-msudigits (which may be */
25435796c8dcSSimon Schubert /* 0, again) */
25445796c8dcSSimon Schubert shift=DECDPUN-msudigits;
25455796c8dcSSimon Schubert if (shift>0) { /* not an exact number of units */
25465796c8dcSSimon Schubert uInt save=res->lsu[0]%powers[shift]; /* save low digit(s) */
25475796c8dcSSimon Schubert decShiftToLeast(res->lsu, units, shift);
25485796c8dcSSimon Schubert *msumax=*msumax+(Unit)(save*powers[msudigits]);
25495796c8dcSSimon Schubert } /* partial shift needed */
25505796c8dcSSimon Schubert
25515796c8dcSSimon Schubert /* Step 3: rotate the units array using triple reverse */
25525796c8dcSSimon Schubert /* (reversing is easy and fast) */
25535796c8dcSSimon Schubert decReverse(res->lsu+units, msumax); /* left part */
25545796c8dcSSimon Schubert decReverse(res->lsu, res->lsu+units-1); /* right part */
25555796c8dcSSimon Schubert decReverse(res->lsu, msumax); /* whole */
25565796c8dcSSimon Schubert } /* whole units to rotate */
25575796c8dcSSimon Schubert /* the rotation may have left an undetermined number of zeros */
25585796c8dcSSimon Schubert /* on the left, so true length needs to be calculated */
25595796c8dcSSimon Schubert res->digits=decGetDigits(res->lsu, msumax-res->lsu+1);
25605796c8dcSSimon Schubert } /* rotate needed */
25615796c8dcSSimon Schubert } /* rhs OK */
25625796c8dcSSimon Schubert } /* numerics */
25635796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
25645796c8dcSSimon Schubert return res;
25655796c8dcSSimon Schubert } /* decNumberRotate */
25665796c8dcSSimon Schubert
25675796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
25685796c8dcSSimon Schubert /* decNumberSameQuantum -- test for equal exponents */
25695796c8dcSSimon Schubert /* */
25705796c8dcSSimon Schubert /* res is the result number, which will contain either 0 or 1 */
25715796c8dcSSimon Schubert /* lhs is a number to test */
25725796c8dcSSimon Schubert /* rhs is the second (usually a pattern) */
25735796c8dcSSimon Schubert /* */
25745796c8dcSSimon Schubert /* No errors are possible and no context is needed. */
25755796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberSameQuantum(decNumber * res,const decNumber * lhs,const decNumber * rhs)25765796c8dcSSimon Schubert decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs,
25775796c8dcSSimon Schubert const decNumber *rhs) {
25785796c8dcSSimon Schubert Unit ret=0; /* return value */
25795796c8dcSSimon Schubert
25805796c8dcSSimon Schubert #if DECCHECK
25815796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res;
25825796c8dcSSimon Schubert #endif
25835796c8dcSSimon Schubert
25845796c8dcSSimon Schubert if (SPECIALARGS) {
25855796c8dcSSimon Schubert if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1;
25865796c8dcSSimon Schubert else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1;
25875796c8dcSSimon Schubert /* [anything else with a special gives 0] */
25885796c8dcSSimon Schubert }
25895796c8dcSSimon Schubert else if (lhs->exponent==rhs->exponent) ret=1;
25905796c8dcSSimon Schubert
25915796c8dcSSimon Schubert decNumberZero(res); /* OK to overwrite an operand now */
25925796c8dcSSimon Schubert *res->lsu=ret;
25935796c8dcSSimon Schubert return res;
25945796c8dcSSimon Schubert } /* decNumberSameQuantum */
25955796c8dcSSimon Schubert
25965796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
25975796c8dcSSimon Schubert /* decNumberScaleB -- multiply by a power of 10 */
25985796c8dcSSimon Schubert /* */
25995796c8dcSSimon Schubert /* This computes C = A x 10**B where B is an integer (q=0) with */
26005796c8dcSSimon Schubert /* maximum magnitude 2*(emax+digits) */
26015796c8dcSSimon Schubert /* */
26025796c8dcSSimon Schubert /* res is C, the result. C may be A or B */
26035796c8dcSSimon Schubert /* lhs is A, the number to adjust */
26045796c8dcSSimon Schubert /* rhs is B, the requested power of ten to use */
26055796c8dcSSimon Schubert /* set is the context */
26065796c8dcSSimon Schubert /* */
26075796c8dcSSimon Schubert /* C must have space for set->digits digits. */
26085796c8dcSSimon Schubert /* */
26095796c8dcSSimon Schubert /* The result may underflow or overflow. */
26105796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberScaleB(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)26115796c8dcSSimon Schubert decNumber * decNumberScaleB(decNumber *res, const decNumber *lhs,
26125796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
26135796c8dcSSimon Schubert Int reqexp; /* requested exponent change [B] */
26145796c8dcSSimon Schubert uInt status=0; /* accumulator */
26155796c8dcSSimon Schubert Int residue; /* work */
26165796c8dcSSimon Schubert
26175796c8dcSSimon Schubert #if DECCHECK
26185796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
26195796c8dcSSimon Schubert #endif
26205796c8dcSSimon Schubert
26215796c8dcSSimon Schubert /* Handle special values except lhs infinite */
26225796c8dcSSimon Schubert if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
26235796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, &status);
26245796c8dcSSimon Schubert /* rhs must be an integer */
26255796c8dcSSimon Schubert else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
26265796c8dcSSimon Schubert status=DEC_Invalid_operation;
26275796c8dcSSimon Schubert else {
26285796c8dcSSimon Schubert /* lhs is a number; rhs is a finite with q==0 */
26295796c8dcSSimon Schubert reqexp=decGetInt(rhs); /* [cannot fail] */
26305796c8dcSSimon Schubert if (reqexp==BADINT /* something bad .. */
26315796c8dcSSimon Schubert || reqexp==BIGODD || reqexp==BIGEVEN /* .. very big .. */
26325796c8dcSSimon Schubert || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */
26335796c8dcSSimon Schubert status=DEC_Invalid_operation;
26345796c8dcSSimon Schubert else { /* rhs is OK */
26355796c8dcSSimon Schubert decNumberCopy(res, lhs); /* all done if infinite lhs */
26365796c8dcSSimon Schubert if (!decNumberIsInfinite(res)) { /* prepare to scale */
26375796c8dcSSimon Schubert res->exponent+=reqexp; /* adjust the exponent */
26385796c8dcSSimon Schubert residue=0;
26395796c8dcSSimon Schubert decFinalize(res, set, &residue, &status); /* .. and check */
26405796c8dcSSimon Schubert } /* finite LHS */
26415796c8dcSSimon Schubert } /* rhs OK */
26425796c8dcSSimon Schubert } /* rhs finite */
26435796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
26445796c8dcSSimon Schubert return res;
26455796c8dcSSimon Schubert } /* decNumberScaleB */
26465796c8dcSSimon Schubert
26475796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
26485796c8dcSSimon Schubert /* decNumberShift -- shift the coefficient of a Number left or right */
26495796c8dcSSimon Schubert /* */
26505796c8dcSSimon Schubert /* This computes C = A << B or C = A >> -B (in base ten). */
26515796c8dcSSimon Schubert /* */
26525796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X<<X) */
26535796c8dcSSimon Schubert /* lhs is A */
26545796c8dcSSimon Schubert /* rhs is B, the number of digits to shift (-ve to right) */
26555796c8dcSSimon Schubert /* set is the context */
26565796c8dcSSimon Schubert /* */
26575796c8dcSSimon Schubert /* The digits of the coefficient of A are shifted to the left (if B */
26585796c8dcSSimon Schubert /* is positive) or to the right (if B is negative) without adjusting */
26595796c8dcSSimon Schubert /* the exponent or the sign of A. */
26605796c8dcSSimon Schubert /* */
26615796c8dcSSimon Schubert /* B must be an integer (q=0) and in the range -set->digits through */
26625796c8dcSSimon Schubert /* +set->digits. */
26635796c8dcSSimon Schubert /* C must have space for set->digits digits. */
26645796c8dcSSimon Schubert /* NaNs are propagated as usual. Infinities are unaffected (but */
26655796c8dcSSimon Schubert /* B must be valid). No status is set unless B is invalid or an */
26665796c8dcSSimon Schubert /* operand is an sNaN. */
26675796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberShift(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)26685796c8dcSSimon Schubert decNumber * decNumberShift(decNumber *res, const decNumber *lhs,
26695796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
26705796c8dcSSimon Schubert uInt status=0; /* accumulator */
26715796c8dcSSimon Schubert Int shift; /* rhs as an Int */
26725796c8dcSSimon Schubert
26735796c8dcSSimon Schubert #if DECCHECK
26745796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
26755796c8dcSSimon Schubert #endif
26765796c8dcSSimon Schubert
26775796c8dcSSimon Schubert /* NaNs propagate as normal */
26785796c8dcSSimon Schubert if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
26795796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, &status);
26805796c8dcSSimon Schubert /* rhs must be an integer */
26815796c8dcSSimon Schubert else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
26825796c8dcSSimon Schubert status=DEC_Invalid_operation;
26835796c8dcSSimon Schubert else { /* both numeric, rhs is an integer */
26845796c8dcSSimon Schubert shift=decGetInt(rhs); /* [cannot fail] */
26855796c8dcSSimon Schubert if (shift==BADINT /* something bad .. */
26865796c8dcSSimon Schubert || shift==BIGODD || shift==BIGEVEN /* .. very big .. */
26875796c8dcSSimon Schubert || abs(shift)>set->digits) /* .. or out of range */
26885796c8dcSSimon Schubert status=DEC_Invalid_operation;
26895796c8dcSSimon Schubert else { /* rhs is OK */
26905796c8dcSSimon Schubert decNumberCopy(res, lhs);
26915796c8dcSSimon Schubert if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */
26925796c8dcSSimon Schubert if (shift>0) { /* to left */
26935796c8dcSSimon Schubert if (shift==set->digits) { /* removing all */
26945796c8dcSSimon Schubert *res->lsu=0; /* so place 0 */
26955796c8dcSSimon Schubert res->digits=1; /* .. */
26965796c8dcSSimon Schubert }
26975796c8dcSSimon Schubert else { /* */
26985796c8dcSSimon Schubert /* first remove leading digits if necessary */
26995796c8dcSSimon Schubert if (res->digits+shift>set->digits) {
27005796c8dcSSimon Schubert decDecap(res, res->digits+shift-set->digits);
27015796c8dcSSimon Schubert /* that updated res->digits; may have gone to 1 (for a */
27025796c8dcSSimon Schubert /* single digit or for zero */
27035796c8dcSSimon Schubert }
27045796c8dcSSimon Schubert if (res->digits>1 || *res->lsu) /* if non-zero.. */
27055796c8dcSSimon Schubert res->digits=decShiftToMost(res->lsu, res->digits, shift);
27065796c8dcSSimon Schubert } /* partial left */
27075796c8dcSSimon Schubert } /* left */
27085796c8dcSSimon Schubert else { /* to right */
27095796c8dcSSimon Schubert if (-shift>=res->digits) { /* discarding all */
27105796c8dcSSimon Schubert *res->lsu=0; /* so place 0 */
27115796c8dcSSimon Schubert res->digits=1; /* .. */
27125796c8dcSSimon Schubert }
27135796c8dcSSimon Schubert else {
27145796c8dcSSimon Schubert decShiftToLeast(res->lsu, D2U(res->digits), -shift);
27155796c8dcSSimon Schubert res->digits-=(-shift);
27165796c8dcSSimon Schubert }
27175796c8dcSSimon Schubert } /* to right */
27185796c8dcSSimon Schubert } /* non-0 non-Inf shift */
27195796c8dcSSimon Schubert } /* rhs OK */
27205796c8dcSSimon Schubert } /* numerics */
27215796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
27225796c8dcSSimon Schubert return res;
27235796c8dcSSimon Schubert } /* decNumberShift */
27245796c8dcSSimon Schubert
27255796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
27265796c8dcSSimon Schubert /* decNumberSquareRoot -- square root operator */
27275796c8dcSSimon Schubert /* */
27285796c8dcSSimon Schubert /* This computes C = squareroot(A) */
27295796c8dcSSimon Schubert /* */
27305796c8dcSSimon Schubert /* res is C, the result. C may be A */
27315796c8dcSSimon Schubert /* rhs is A */
27325796c8dcSSimon Schubert /* set is the context; note that rounding mode has no effect */
27335796c8dcSSimon Schubert /* */
27345796c8dcSSimon Schubert /* C must have space for set->digits digits. */
27355796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
27365796c8dcSSimon Schubert /* This uses the following varying-precision algorithm in: */
27375796c8dcSSimon Schubert /* */
27385796c8dcSSimon Schubert /* Properly Rounded Variable Precision Square Root, T. E. Hull and */
27395796c8dcSSimon Schubert /* A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */
27405796c8dcSSimon Schubert /* pp229-237, ACM, September 1985. */
27415796c8dcSSimon Schubert /* */
27425796c8dcSSimon Schubert /* The square-root is calculated using Newton's method, after which */
27435796c8dcSSimon Schubert /* a check is made to ensure the result is correctly rounded. */
27445796c8dcSSimon Schubert /* */
27455796c8dcSSimon Schubert /* % [Reformatted original Numerical Turing source code follows.] */
27465796c8dcSSimon Schubert /* function sqrt(x : real) : real */
27475796c8dcSSimon Schubert /* % sqrt(x) returns the properly rounded approximation to the square */
27485796c8dcSSimon Schubert /* % root of x, in the precision of the calling environment, or it */
27495796c8dcSSimon Schubert /* % fails if x < 0. */
27505796c8dcSSimon Schubert /* % t e hull and a abrham, august, 1984 */
27515796c8dcSSimon Schubert /* if x <= 0 then */
27525796c8dcSSimon Schubert /* if x < 0 then */
27535796c8dcSSimon Schubert /* assert false */
27545796c8dcSSimon Schubert /* else */
27555796c8dcSSimon Schubert /* result 0 */
27565796c8dcSSimon Schubert /* end if */
27575796c8dcSSimon Schubert /* end if */
27585796c8dcSSimon Schubert /* var f := setexp(x, 0) % fraction part of x [0.1 <= x < 1] */
27595796c8dcSSimon Schubert /* var e := getexp(x) % exponent part of x */
27605796c8dcSSimon Schubert /* var approx : real */
27615796c8dcSSimon Schubert /* if e mod 2 = 0 then */
27625796c8dcSSimon Schubert /* approx := .259 + .819 * f % approx to root of f */
27635796c8dcSSimon Schubert /* else */
27645796c8dcSSimon Schubert /* f := f/l0 % adjustments */
27655796c8dcSSimon Schubert /* e := e + 1 % for odd */
27665796c8dcSSimon Schubert /* approx := .0819 + 2.59 * f % exponent */
27675796c8dcSSimon Schubert /* end if */
27685796c8dcSSimon Schubert /* */
27695796c8dcSSimon Schubert /* var p:= 3 */
27705796c8dcSSimon Schubert /* const maxp := currentprecision + 2 */
27715796c8dcSSimon Schubert /* loop */
27725796c8dcSSimon Schubert /* p := min(2*p - 2, maxp) % p = 4,6,10, . . . , maxp */
27735796c8dcSSimon Schubert /* precision p */
27745796c8dcSSimon Schubert /* approx := .5 * (approx + f/approx) */
27755796c8dcSSimon Schubert /* exit when p = maxp */
27765796c8dcSSimon Schubert /* end loop */
27775796c8dcSSimon Schubert /* */
27785796c8dcSSimon Schubert /* % approx is now within 1 ulp of the properly rounded square root */
27795796c8dcSSimon Schubert /* % of f; to ensure proper rounding, compare squares of (approx - */
27805796c8dcSSimon Schubert /* % l/2 ulp) and (approx + l/2 ulp) with f. */
27815796c8dcSSimon Schubert /* p := currentprecision */
27825796c8dcSSimon Schubert /* begin */
27835796c8dcSSimon Schubert /* precision p + 2 */
27845796c8dcSSimon Schubert /* const approxsubhalf := approx - setexp(.5, -p) */
27855796c8dcSSimon Schubert /* if mulru(approxsubhalf, approxsubhalf) > f then */
27865796c8dcSSimon Schubert /* approx := approx - setexp(.l, -p + 1) */
27875796c8dcSSimon Schubert /* else */
27885796c8dcSSimon Schubert /* const approxaddhalf := approx + setexp(.5, -p) */
27895796c8dcSSimon Schubert /* if mulrd(approxaddhalf, approxaddhalf) < f then */
27905796c8dcSSimon Schubert /* approx := approx + setexp(.l, -p + 1) */
27915796c8dcSSimon Schubert /* end if */
27925796c8dcSSimon Schubert /* end if */
27935796c8dcSSimon Schubert /* end */
27945796c8dcSSimon Schubert /* result setexp(approx, e div 2) % fix exponent */
27955796c8dcSSimon Schubert /* end sqrt */
27965796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberSquareRoot(decNumber * res,const decNumber * rhs,decContext * set)27975796c8dcSSimon Schubert decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs,
27985796c8dcSSimon Schubert decContext *set) {
27995796c8dcSSimon Schubert decContext workset, approxset; /* work contexts */
28005796c8dcSSimon Schubert decNumber dzero; /* used for constant zero */
28015796c8dcSSimon Schubert Int maxp; /* largest working precision */
28025796c8dcSSimon Schubert Int workp; /* working precision */
28035796c8dcSSimon Schubert Int residue=0; /* rounding residue */
28045796c8dcSSimon Schubert uInt status=0, ignore=0; /* status accumulators */
28055796c8dcSSimon Schubert uInt rstatus; /* .. */
28065796c8dcSSimon Schubert Int exp; /* working exponent */
28075796c8dcSSimon Schubert Int ideal; /* ideal (preferred) exponent */
28085796c8dcSSimon Schubert Int needbytes; /* work */
28095796c8dcSSimon Schubert Int dropped; /* .. */
28105796c8dcSSimon Schubert
28115796c8dcSSimon Schubert #if DECSUBSET
28125796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* non-NULL if rounded rhs allocated */
28135796c8dcSSimon Schubert #endif
28145796c8dcSSimon Schubert /* buffer for f [needs +1 in case DECBUFFER 0] */
28155796c8dcSSimon Schubert decNumber buff[D2N(DECBUFFER+1)];
28165796c8dcSSimon Schubert /* buffer for a [needs +2 to match likely maxp] */
28175796c8dcSSimon Schubert decNumber bufa[D2N(DECBUFFER+2)];
28185796c8dcSSimon Schubert /* buffer for temporary, b [must be same size as a] */
28195796c8dcSSimon Schubert decNumber bufb[D2N(DECBUFFER+2)];
28205796c8dcSSimon Schubert decNumber *allocbuff=NULL; /* -> allocated buff, iff allocated */
28215796c8dcSSimon Schubert decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
28225796c8dcSSimon Schubert decNumber *allocbufb=NULL; /* -> allocated bufb, iff allocated */
28235796c8dcSSimon Schubert decNumber *f=buff; /* reduced fraction */
28245796c8dcSSimon Schubert decNumber *a=bufa; /* approximation to result */
28255796c8dcSSimon Schubert decNumber *b=bufb; /* intermediate result */
28265796c8dcSSimon Schubert /* buffer for temporary variable, up to 3 digits */
28275796c8dcSSimon Schubert decNumber buft[D2N(3)];
28285796c8dcSSimon Schubert decNumber *t=buft; /* up-to-3-digit constant or work */
28295796c8dcSSimon Schubert
28305796c8dcSSimon Schubert #if DECCHECK
28315796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
28325796c8dcSSimon Schubert #endif
28335796c8dcSSimon Schubert
28345796c8dcSSimon Schubert do { /* protect allocated storage */
28355796c8dcSSimon Schubert #if DECSUBSET
28365796c8dcSSimon Schubert if (!set->extended) {
28375796c8dcSSimon Schubert /* reduce operand and set lostDigits status, as needed */
28385796c8dcSSimon Schubert if (rhs->digits>set->digits) {
28395796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, &status);
28405796c8dcSSimon Schubert if (allocrhs==NULL) break;
28415796c8dcSSimon Schubert /* [Note: 'f' allocation below could reuse this buffer if */
28425796c8dcSSimon Schubert /* used, but as this is rare they are kept separate for clarity.] */
28435796c8dcSSimon Schubert rhs=allocrhs;
28445796c8dcSSimon Schubert }
28455796c8dcSSimon Schubert }
28465796c8dcSSimon Schubert #endif
28475796c8dcSSimon Schubert /* [following code does not require input rounding] */
28485796c8dcSSimon Schubert
28495796c8dcSSimon Schubert /* handle infinities and NaNs */
28505796c8dcSSimon Schubert if (SPECIALARG) {
28515796c8dcSSimon Schubert if (decNumberIsInfinite(rhs)) { /* an infinity */
28525796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation;
28535796c8dcSSimon Schubert else decNumberCopy(res, rhs); /* +Infinity */
28545796c8dcSSimon Schubert }
28555796c8dcSSimon Schubert else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
28565796c8dcSSimon Schubert break;
28575796c8dcSSimon Schubert }
28585796c8dcSSimon Schubert
28595796c8dcSSimon Schubert /* calculate the ideal (preferred) exponent [floor(exp/2)] */
28605796c8dcSSimon Schubert /* [It would be nicer to write: ideal=rhs->exponent>>1, but this */
28615796c8dcSSimon Schubert /* generates a compiler warning. Generated code is the same.] */
28625796c8dcSSimon Schubert ideal=(rhs->exponent&~1)/2; /* target */
28635796c8dcSSimon Schubert
28645796c8dcSSimon Schubert /* handle zeros */
28655796c8dcSSimon Schubert if (ISZERO(rhs)) {
28665796c8dcSSimon Schubert decNumberCopy(res, rhs); /* could be 0 or -0 */
28675796c8dcSSimon Schubert res->exponent=ideal; /* use the ideal [safe] */
28685796c8dcSSimon Schubert /* use decFinish to clamp any out-of-range exponent, etc. */
28695796c8dcSSimon Schubert decFinish(res, set, &residue, &status);
28705796c8dcSSimon Schubert break;
28715796c8dcSSimon Schubert }
28725796c8dcSSimon Schubert
28735796c8dcSSimon Schubert /* any other -x is an oops */
28745796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) {
28755796c8dcSSimon Schubert status|=DEC_Invalid_operation;
28765796c8dcSSimon Schubert break;
28775796c8dcSSimon Schubert }
28785796c8dcSSimon Schubert
28795796c8dcSSimon Schubert /* space is needed for three working variables */
28805796c8dcSSimon Schubert /* f -- the same precision as the RHS, reduced to 0.01->0.99... */
28815796c8dcSSimon Schubert /* a -- Hull's approximation -- precision, when assigned, is */
28825796c8dcSSimon Schubert /* currentprecision+1 or the input argument precision, */
28835796c8dcSSimon Schubert /* whichever is larger (+2 for use as temporary) */
28845796c8dcSSimon Schubert /* b -- intermediate temporary result (same size as a) */
28855796c8dcSSimon Schubert /* if any is too long for local storage, then allocate */
28865796c8dcSSimon Schubert workp=MAXI(set->digits+1, rhs->digits); /* actual rounding precision */
28875796c8dcSSimon Schubert workp=MAXI(workp, 7); /* at least 7 for low cases */
28885796c8dcSSimon Schubert maxp=workp+2; /* largest working precision */
28895796c8dcSSimon Schubert
28905796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
28915796c8dcSSimon Schubert if (needbytes>(Int)sizeof(buff)) {
28925796c8dcSSimon Schubert allocbuff=(decNumber *)malloc(needbytes);
28935796c8dcSSimon Schubert if (allocbuff==NULL) { /* hopeless -- abandon */
28945796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
28955796c8dcSSimon Schubert break;}
28965796c8dcSSimon Schubert f=allocbuff; /* use the allocated space */
28975796c8dcSSimon Schubert }
28985796c8dcSSimon Schubert /* a and b both need to be able to hold a maxp-length number */
28995796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit);
29005796c8dcSSimon Schubert if (needbytes>(Int)sizeof(bufa)) { /* [same applies to b] */
29015796c8dcSSimon Schubert allocbufa=(decNumber *)malloc(needbytes);
29025796c8dcSSimon Schubert allocbufb=(decNumber *)malloc(needbytes);
29035796c8dcSSimon Schubert if (allocbufa==NULL || allocbufb==NULL) { /* hopeless */
29045796c8dcSSimon Schubert status|=DEC_Insufficient_storage;
29055796c8dcSSimon Schubert break;}
29065796c8dcSSimon Schubert a=allocbufa; /* use the allocated spaces */
29075796c8dcSSimon Schubert b=allocbufb; /* .. */
29085796c8dcSSimon Schubert }
29095796c8dcSSimon Schubert
29105796c8dcSSimon Schubert /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */
29115796c8dcSSimon Schubert decNumberCopy(f, rhs);
29125796c8dcSSimon Schubert exp=f->exponent+f->digits; /* adjusted to Hull rules */
29135796c8dcSSimon Schubert f->exponent=-(f->digits); /* to range */
29145796c8dcSSimon Schubert
29155796c8dcSSimon Schubert /* set up working context */
29165796c8dcSSimon Schubert decContextDefault(&workset, DEC_INIT_DECIMAL64);
29175796c8dcSSimon Schubert workset.emax=DEC_MAX_EMAX;
29185796c8dcSSimon Schubert workset.emin=DEC_MIN_EMIN;
29195796c8dcSSimon Schubert
29205796c8dcSSimon Schubert /* [Until further notice, no error is possible and status bits */
29215796c8dcSSimon Schubert /* (Rounded, etc.) should be ignored, not accumulated.] */
29225796c8dcSSimon Schubert
29235796c8dcSSimon Schubert /* Calculate initial approximation, and allow for odd exponent */
29245796c8dcSSimon Schubert workset.digits=workp; /* p for initial calculation */
29255796c8dcSSimon Schubert t->bits=0; t->digits=3;
29265796c8dcSSimon Schubert a->bits=0; a->digits=3;
29275796c8dcSSimon Schubert if ((exp & 1)==0) { /* even exponent */
29285796c8dcSSimon Schubert /* Set t=0.259, a=0.819 */
29295796c8dcSSimon Schubert t->exponent=-3;
29305796c8dcSSimon Schubert a->exponent=-3;
29315796c8dcSSimon Schubert #if DECDPUN>=3
29325796c8dcSSimon Schubert t->lsu[0]=259;
29335796c8dcSSimon Schubert a->lsu[0]=819;
29345796c8dcSSimon Schubert #elif DECDPUN==2
29355796c8dcSSimon Schubert t->lsu[0]=59; t->lsu[1]=2;
29365796c8dcSSimon Schubert a->lsu[0]=19; a->lsu[1]=8;
29375796c8dcSSimon Schubert #else
29385796c8dcSSimon Schubert t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2;
29395796c8dcSSimon Schubert a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8;
29405796c8dcSSimon Schubert #endif
29415796c8dcSSimon Schubert }
29425796c8dcSSimon Schubert else { /* odd exponent */
29435796c8dcSSimon Schubert /* Set t=0.0819, a=2.59 */
29445796c8dcSSimon Schubert f->exponent--; /* f=f/10 */
29455796c8dcSSimon Schubert exp++; /* e=e+1 */
29465796c8dcSSimon Schubert t->exponent=-4;
29475796c8dcSSimon Schubert a->exponent=-2;
29485796c8dcSSimon Schubert #if DECDPUN>=3
29495796c8dcSSimon Schubert t->lsu[0]=819;
29505796c8dcSSimon Schubert a->lsu[0]=259;
29515796c8dcSSimon Schubert #elif DECDPUN==2
29525796c8dcSSimon Schubert t->lsu[0]=19; t->lsu[1]=8;
29535796c8dcSSimon Schubert a->lsu[0]=59; a->lsu[1]=2;
29545796c8dcSSimon Schubert #else
29555796c8dcSSimon Schubert t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8;
29565796c8dcSSimon Schubert a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2;
29575796c8dcSSimon Schubert #endif
29585796c8dcSSimon Schubert }
29595796c8dcSSimon Schubert
29605796c8dcSSimon Schubert decMultiplyOp(a, a, f, &workset, &ignore); /* a=a*f */
29615796c8dcSSimon Schubert decAddOp(a, a, t, &workset, 0, &ignore); /* ..+t */
29625796c8dcSSimon Schubert /* [a is now the initial approximation for sqrt(f), calculated with */
29635796c8dcSSimon Schubert /* currentprecision, which is also a's precision.] */
29645796c8dcSSimon Schubert
29655796c8dcSSimon Schubert /* the main calculation loop */
29665796c8dcSSimon Schubert decNumberZero(&dzero); /* make 0 */
29675796c8dcSSimon Schubert decNumberZero(t); /* set t = 0.5 */
29685796c8dcSSimon Schubert t->lsu[0]=5; /* .. */
29695796c8dcSSimon Schubert t->exponent=-1; /* .. */
29705796c8dcSSimon Schubert workset.digits=3; /* initial p */
29715796c8dcSSimon Schubert for (; workset.digits<maxp;) {
29725796c8dcSSimon Schubert /* set p to min(2*p - 2, maxp) [hence 3; or: 4, 6, 10, ... , maxp] */
29735796c8dcSSimon Schubert workset.digits=MINI(workset.digits*2-2, maxp);
29745796c8dcSSimon Schubert /* a = 0.5 * (a + f/a) */
29755796c8dcSSimon Schubert /* [calculated at p then rounded to currentprecision] */
29765796c8dcSSimon Schubert decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */
29775796c8dcSSimon Schubert decAddOp(b, b, a, &workset, 0, &ignore); /* b=b+a */
29785796c8dcSSimon Schubert decMultiplyOp(a, b, t, &workset, &ignore); /* a=b*0.5 */
29795796c8dcSSimon Schubert } /* loop */
29805796c8dcSSimon Schubert
29815796c8dcSSimon Schubert /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */
29825796c8dcSSimon Schubert /* now reduce to length, etc.; this needs to be done with a */
29835796c8dcSSimon Schubert /* having the correct exponent so as to handle subnormals */
29845796c8dcSSimon Schubert /* correctly */
29855796c8dcSSimon Schubert approxset=*set; /* get emin, emax, etc. */
29865796c8dcSSimon Schubert approxset.round=DEC_ROUND_HALF_EVEN;
29875796c8dcSSimon Schubert a->exponent+=exp/2; /* set correct exponent */
29885796c8dcSSimon Schubert rstatus=0; /* clear status */
29895796c8dcSSimon Schubert residue=0; /* .. and accumulator */
29905796c8dcSSimon Schubert decCopyFit(a, a, &approxset, &residue, &rstatus); /* reduce (if needed) */
29915796c8dcSSimon Schubert decFinish(a, &approxset, &residue, &rstatus); /* clean and finalize */
29925796c8dcSSimon Schubert
29935796c8dcSSimon Schubert /* Overflow was possible if the input exponent was out-of-range, */
29945796c8dcSSimon Schubert /* in which case quit */
29955796c8dcSSimon Schubert if (rstatus&DEC_Overflow) {
29965796c8dcSSimon Schubert status=rstatus; /* use the status as-is */
29975796c8dcSSimon Schubert decNumberCopy(res, a); /* copy to result */
29985796c8dcSSimon Schubert break;
29995796c8dcSSimon Schubert }
30005796c8dcSSimon Schubert
30015796c8dcSSimon Schubert /* Preserve status except Inexact/Rounded */
30025796c8dcSSimon Schubert status|=(rstatus & ~(DEC_Rounded|DEC_Inexact));
30035796c8dcSSimon Schubert
30045796c8dcSSimon Schubert /* Carry out the Hull correction */
30055796c8dcSSimon Schubert a->exponent-=exp/2; /* back to 0.1->1 */
30065796c8dcSSimon Schubert
30075796c8dcSSimon Schubert /* a is now at final precision and within 1 ulp of the properly */
30085796c8dcSSimon Schubert /* rounded square root of f; to ensure proper rounding, compare */
30095796c8dcSSimon Schubert /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */
30105796c8dcSSimon Schubert /* Here workset.digits=maxp and t=0.5, and a->digits determines */
30115796c8dcSSimon Schubert /* the ulp */
30125796c8dcSSimon Schubert workset.digits--; /* maxp-1 is OK now */
30135796c8dcSSimon Schubert t->exponent=-a->digits-1; /* make 0.5 ulp */
30145796c8dcSSimon Schubert decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */
30155796c8dcSSimon Schubert workset.round=DEC_ROUND_UP;
30165796c8dcSSimon Schubert decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulru(b, b) */
30175796c8dcSSimon Schubert decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */
30185796c8dcSSimon Schubert if (decNumberIsNegative(b)) { /* f < b [i.e., b > f] */
30195796c8dcSSimon Schubert /* this is the more common adjustment, though both are rare */
30205796c8dcSSimon Schubert t->exponent++; /* make 1.0 ulp */
30215796c8dcSSimon Schubert t->lsu[0]=1; /* .. */
30225796c8dcSSimon Schubert decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */
30235796c8dcSSimon Schubert /* assign to approx [round to length] */
30245796c8dcSSimon Schubert approxset.emin-=exp/2; /* adjust to match a */
30255796c8dcSSimon Schubert approxset.emax-=exp/2;
30265796c8dcSSimon Schubert decAddOp(a, &dzero, a, &approxset, 0, &ignore);
30275796c8dcSSimon Schubert }
30285796c8dcSSimon Schubert else {
30295796c8dcSSimon Schubert decAddOp(b, a, t, &workset, 0, &ignore); /* b = a + 0.5 ulp */
30305796c8dcSSimon Schubert workset.round=DEC_ROUND_DOWN;
30315796c8dcSSimon Schubert decMultiplyOp(b, b, b, &workset, &ignore); /* b = mulrd(b, b) */
30325796c8dcSSimon Schubert decCompareOp(b, b, f, &workset, COMPARE, &ignore); /* b ? f */
30335796c8dcSSimon Schubert if (decNumberIsNegative(b)) { /* b < f */
30345796c8dcSSimon Schubert t->exponent++; /* make 1.0 ulp */
30355796c8dcSSimon Schubert t->lsu[0]=1; /* .. */
30365796c8dcSSimon Schubert decAddOp(a, a, t, &workset, 0, &ignore); /* a = a + 1 ulp */
30375796c8dcSSimon Schubert /* assign to approx [round to length] */
30385796c8dcSSimon Schubert approxset.emin-=exp/2; /* adjust to match a */
30395796c8dcSSimon Schubert approxset.emax-=exp/2;
30405796c8dcSSimon Schubert decAddOp(a, &dzero, a, &approxset, 0, &ignore);
30415796c8dcSSimon Schubert }
30425796c8dcSSimon Schubert }
30435796c8dcSSimon Schubert /* [no errors are possible in the above, and rounding/inexact during */
30445796c8dcSSimon Schubert /* estimation are irrelevant, so status was not accumulated] */
30455796c8dcSSimon Schubert
30465796c8dcSSimon Schubert /* Here, 0.1 <= a < 1 (still), so adjust back */
30475796c8dcSSimon Schubert a->exponent+=exp/2; /* set correct exponent */
30485796c8dcSSimon Schubert
30495796c8dcSSimon Schubert /* count droppable zeros [after any subnormal rounding] by */
30505796c8dcSSimon Schubert /* trimming a copy */
30515796c8dcSSimon Schubert decNumberCopy(b, a);
30525796c8dcSSimon Schubert decTrim(b, set, 1, 1, &dropped); /* [drops trailing zeros] */
30535796c8dcSSimon Schubert
30545796c8dcSSimon Schubert /* Set Inexact and Rounded. The answer can only be exact if */
30555796c8dcSSimon Schubert /* it is short enough so that squaring it could fit in workp */
30565796c8dcSSimon Schubert /* digits, so this is the only (relatively rare) condition that */
30575796c8dcSSimon Schubert /* a careful check is needed */
30585796c8dcSSimon Schubert if (b->digits*2-1 > workp) { /* cannot fit */
30595796c8dcSSimon Schubert status|=DEC_Inexact|DEC_Rounded;
30605796c8dcSSimon Schubert }
30615796c8dcSSimon Schubert else { /* could be exact/unrounded */
30625796c8dcSSimon Schubert uInt mstatus=0; /* local status */
30635796c8dcSSimon Schubert decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */
30645796c8dcSSimon Schubert if (mstatus&DEC_Overflow) { /* result just won't fit */
30655796c8dcSSimon Schubert status|=DEC_Inexact|DEC_Rounded;
30665796c8dcSSimon Schubert }
30675796c8dcSSimon Schubert else { /* plausible */
30685796c8dcSSimon Schubert decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */
30695796c8dcSSimon Schubert if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */
30705796c8dcSSimon Schubert else { /* is Exact */
30715796c8dcSSimon Schubert /* here, dropped is the count of trailing zeros in 'a' */
30725796c8dcSSimon Schubert /* use closest exponent to ideal... */
30735796c8dcSSimon Schubert Int todrop=ideal-a->exponent; /* most that can be dropped */
30745796c8dcSSimon Schubert if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */
30755796c8dcSSimon Schubert else { /* unrounded */
30765796c8dcSSimon Schubert /* there are some to drop, but emax may not allow all */
30775796c8dcSSimon Schubert Int maxexp=set->emax-set->digits+1;
30785796c8dcSSimon Schubert Int maxdrop=maxexp-a->exponent;
30795796c8dcSSimon Schubert if (todrop>maxdrop && set->clamp) { /* apply clamping */
30805796c8dcSSimon Schubert todrop=maxdrop;
30815796c8dcSSimon Schubert status|=DEC_Clamped;
30825796c8dcSSimon Schubert }
30835796c8dcSSimon Schubert if (dropped<todrop) { /* clamp to those available */
30845796c8dcSSimon Schubert todrop=dropped;
30855796c8dcSSimon Schubert status|=DEC_Clamped;
30865796c8dcSSimon Schubert }
30875796c8dcSSimon Schubert if (todrop>0) { /* have some to drop */
30885796c8dcSSimon Schubert decShiftToLeast(a->lsu, D2U(a->digits), todrop);
30895796c8dcSSimon Schubert a->exponent+=todrop; /* maintain numerical value */
30905796c8dcSSimon Schubert a->digits-=todrop; /* new length */
30915796c8dcSSimon Schubert }
30925796c8dcSSimon Schubert }
30935796c8dcSSimon Schubert }
30945796c8dcSSimon Schubert }
30955796c8dcSSimon Schubert }
30965796c8dcSSimon Schubert
30975796c8dcSSimon Schubert /* double-check Underflow, as perhaps the result could not have */
30985796c8dcSSimon Schubert /* been subnormal (initial argument too big), or it is now Exact */
30995796c8dcSSimon Schubert if (status&DEC_Underflow) {
31005796c8dcSSimon Schubert Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */
31015796c8dcSSimon Schubert /* check if truly subnormal */
31025796c8dcSSimon Schubert #if DECEXTFLAG /* DEC_Subnormal too */
31035796c8dcSSimon Schubert if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow);
31045796c8dcSSimon Schubert #else
31055796c8dcSSimon Schubert if (ae>=set->emin*2) status&=~DEC_Underflow;
31065796c8dcSSimon Schubert #endif
31075796c8dcSSimon Schubert /* check if truly inexact */
31085796c8dcSSimon Schubert if (!(status&DEC_Inexact)) status&=~DEC_Underflow;
31095796c8dcSSimon Schubert }
31105796c8dcSSimon Schubert
31115796c8dcSSimon Schubert decNumberCopy(res, a); /* a is now the result */
31125796c8dcSSimon Schubert } while(0); /* end protected */
31135796c8dcSSimon Schubert
3114a45ae5f8SJohn Marino free(allocbuff); /* drop any storage used */
3115a45ae5f8SJohn Marino free(allocbufa); /* .. */
3116a45ae5f8SJohn Marino free(allocbufb); /* .. */
31175796c8dcSSimon Schubert #if DECSUBSET
3118a45ae5f8SJohn Marino free(allocrhs); /* .. */
31195796c8dcSSimon Schubert #endif
31205796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);/* then report status */
31215796c8dcSSimon Schubert #if DECCHECK
31225796c8dcSSimon Schubert decCheckInexact(res, set);
31235796c8dcSSimon Schubert #endif
31245796c8dcSSimon Schubert return res;
31255796c8dcSSimon Schubert } /* decNumberSquareRoot */
31265796c8dcSSimon Schubert
31275796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
31285796c8dcSSimon Schubert /* decNumberSubtract -- subtract two Numbers */
31295796c8dcSSimon Schubert /* */
31305796c8dcSSimon Schubert /* This computes C = A - B */
31315796c8dcSSimon Schubert /* */
31325796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X-X) */
31335796c8dcSSimon Schubert /* lhs is A */
31345796c8dcSSimon Schubert /* rhs is B */
31355796c8dcSSimon Schubert /* set is the context */
31365796c8dcSSimon Schubert /* */
31375796c8dcSSimon Schubert /* C must have space for set->digits digits. */
31385796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberSubtract(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)31395796c8dcSSimon Schubert decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs,
31405796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
31415796c8dcSSimon Schubert uInt status=0; /* accumulator */
31425796c8dcSSimon Schubert
31435796c8dcSSimon Schubert decAddOp(res, lhs, rhs, set, DECNEG, &status);
31445796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
31455796c8dcSSimon Schubert #if DECCHECK
31465796c8dcSSimon Schubert decCheckInexact(res, set);
31475796c8dcSSimon Schubert #endif
31485796c8dcSSimon Schubert return res;
31495796c8dcSSimon Schubert } /* decNumberSubtract */
31505796c8dcSSimon Schubert
31515796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
31525796c8dcSSimon Schubert /* decNumberToIntegralExact -- round-to-integral-value with InExact */
31535796c8dcSSimon Schubert /* decNumberToIntegralValue -- round-to-integral-value */
31545796c8dcSSimon Schubert /* */
31555796c8dcSSimon Schubert /* res is the result */
31565796c8dcSSimon Schubert /* rhs is input number */
31575796c8dcSSimon Schubert /* set is the context */
31585796c8dcSSimon Schubert /* */
31595796c8dcSSimon Schubert /* res must have space for any value of rhs. */
31605796c8dcSSimon Schubert /* */
31615796c8dcSSimon Schubert /* This implements the IEEE special operators and therefore treats */
31625796c8dcSSimon Schubert /* special values as valid. For finite numbers it returns */
31635796c8dcSSimon Schubert /* rescale(rhs, 0) if rhs->exponent is <0. */
31645796c8dcSSimon Schubert /* Otherwise the result is rhs (so no error is possible, except for */
31655796c8dcSSimon Schubert /* sNaN). */
31665796c8dcSSimon Schubert /* */
31675796c8dcSSimon Schubert /* The context is used for rounding mode and status after sNaN, but */
31685796c8dcSSimon Schubert /* the digits setting is ignored. The Exact version will signal */
31695796c8dcSSimon Schubert /* Inexact if the result differs numerically from rhs; the other */
31705796c8dcSSimon Schubert /* never signals Inexact. */
31715796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberToIntegralExact(decNumber * res,const decNumber * rhs,decContext * set)31725796c8dcSSimon Schubert decNumber * decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
31735796c8dcSSimon Schubert decContext *set) {
31745796c8dcSSimon Schubert decNumber dn;
31755796c8dcSSimon Schubert decContext workset; /* working context */
31765796c8dcSSimon Schubert uInt status=0; /* accumulator */
31775796c8dcSSimon Schubert
31785796c8dcSSimon Schubert #if DECCHECK
31795796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
31805796c8dcSSimon Schubert #endif
31815796c8dcSSimon Schubert
31825796c8dcSSimon Schubert /* handle infinities and NaNs */
31835796c8dcSSimon Schubert if (SPECIALARG) {
31845796c8dcSSimon Schubert if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); /* an Infinity */
31855796c8dcSSimon Schubert else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
31865796c8dcSSimon Schubert }
31875796c8dcSSimon Schubert else { /* finite */
31885796c8dcSSimon Schubert /* have a finite number; no error possible (res must be big enough) */
31895796c8dcSSimon Schubert if (rhs->exponent>=0) return decNumberCopy(res, rhs);
31905796c8dcSSimon Schubert /* that was easy, but if negative exponent there is work to do... */
31915796c8dcSSimon Schubert workset=*set; /* clone rounding, etc. */
31925796c8dcSSimon Schubert workset.digits=rhs->digits; /* no length rounding */
31935796c8dcSSimon Schubert workset.traps=0; /* no traps */
31945796c8dcSSimon Schubert decNumberZero(&dn); /* make a number with exponent 0 */
31955796c8dcSSimon Schubert decNumberQuantize(res, rhs, &dn, &workset);
31965796c8dcSSimon Schubert status|=workset.status;
31975796c8dcSSimon Schubert }
31985796c8dcSSimon Schubert if (status!=0) decStatus(res, status, set);
31995796c8dcSSimon Schubert return res;
32005796c8dcSSimon Schubert } /* decNumberToIntegralExact */
32015796c8dcSSimon Schubert
decNumberToIntegralValue(decNumber * res,const decNumber * rhs,decContext * set)32025796c8dcSSimon Schubert decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
32035796c8dcSSimon Schubert decContext *set) {
32045796c8dcSSimon Schubert decContext workset=*set; /* working context */
32055796c8dcSSimon Schubert workset.traps=0; /* no traps */
32065796c8dcSSimon Schubert decNumberToIntegralExact(res, rhs, &workset);
32075796c8dcSSimon Schubert /* this never affects set, except for sNaNs; NaN will have been set */
32085796c8dcSSimon Schubert /* or propagated already, so no need to call decStatus */
32095796c8dcSSimon Schubert set->status|=workset.status&DEC_Invalid_operation;
32105796c8dcSSimon Schubert return res;
32115796c8dcSSimon Schubert } /* decNumberToIntegralValue */
32125796c8dcSSimon Schubert
32135796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
32145796c8dcSSimon Schubert /* decNumberXor -- XOR two Numbers, digitwise */
32155796c8dcSSimon Schubert /* */
32165796c8dcSSimon Schubert /* This computes C = A ^ B */
32175796c8dcSSimon Schubert /* */
32185796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X^X) */
32195796c8dcSSimon Schubert /* lhs is A */
32205796c8dcSSimon Schubert /* rhs is B */
32215796c8dcSSimon Schubert /* set is the context (used for result length and error report) */
32225796c8dcSSimon Schubert /* */
32235796c8dcSSimon Schubert /* C must have space for set->digits digits. */
32245796c8dcSSimon Schubert /* */
32255796c8dcSSimon Schubert /* Logical function restrictions apply (see above); a NaN is */
32265796c8dcSSimon Schubert /* returned with Invalid_operation if a restriction is violated. */
32275796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberXor(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)32285796c8dcSSimon Schubert decNumber * decNumberXor(decNumber *res, const decNumber *lhs,
32295796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
32305796c8dcSSimon Schubert const Unit *ua, *ub; /* -> operands */
32315796c8dcSSimon Schubert const Unit *msua, *msub; /* -> operand msus */
32325796c8dcSSimon Schubert Unit *uc, *msuc; /* -> result and its msu */
32335796c8dcSSimon Schubert Int msudigs; /* digits in res msu */
32345796c8dcSSimon Schubert #if DECCHECK
32355796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
32365796c8dcSSimon Schubert #endif
32375796c8dcSSimon Schubert
32385796c8dcSSimon Schubert if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
32395796c8dcSSimon Schubert || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
32405796c8dcSSimon Schubert decStatus(res, DEC_Invalid_operation, set);
32415796c8dcSSimon Schubert return res;
32425796c8dcSSimon Schubert }
32435796c8dcSSimon Schubert /* operands are valid */
32445796c8dcSSimon Schubert ua=lhs->lsu; /* bottom-up */
32455796c8dcSSimon Schubert ub=rhs->lsu; /* .. */
32465796c8dcSSimon Schubert uc=res->lsu; /* .. */
32475796c8dcSSimon Schubert msua=ua+D2U(lhs->digits)-1; /* -> msu of lhs */
32485796c8dcSSimon Schubert msub=ub+D2U(rhs->digits)-1; /* -> msu of rhs */
32495796c8dcSSimon Schubert msuc=uc+D2U(set->digits)-1; /* -> msu of result */
32505796c8dcSSimon Schubert msudigs=MSUDIGITS(set->digits); /* [faster than remainder] */
32515796c8dcSSimon Schubert for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
32525796c8dcSSimon Schubert Unit a, b; /* extract units */
32535796c8dcSSimon Schubert if (ua>msua) a=0;
32545796c8dcSSimon Schubert else a=*ua;
32555796c8dcSSimon Schubert if (ub>msub) b=0;
32565796c8dcSSimon Schubert else b=*ub;
32575796c8dcSSimon Schubert *uc=0; /* can now write back */
32585796c8dcSSimon Schubert if (a|b) { /* maybe 1 bits to examine */
32595796c8dcSSimon Schubert Int i, j;
32605796c8dcSSimon Schubert /* This loop could be unrolled and/or use BIN2BCD tables */
32615796c8dcSSimon Schubert for (i=0; i<DECDPUN; i++) {
32625796c8dcSSimon Schubert if ((a^b)&1) *uc=*uc+(Unit)powers[i]; /* effect XOR */
32635796c8dcSSimon Schubert j=a%10;
32645796c8dcSSimon Schubert a=a/10;
32655796c8dcSSimon Schubert j|=b%10;
32665796c8dcSSimon Schubert b=b/10;
32675796c8dcSSimon Schubert if (j>1) {
32685796c8dcSSimon Schubert decStatus(res, DEC_Invalid_operation, set);
32695796c8dcSSimon Schubert return res;
32705796c8dcSSimon Schubert }
32715796c8dcSSimon Schubert if (uc==msuc && i==msudigs-1) break; /* just did final digit */
32725796c8dcSSimon Schubert } /* each digit */
32735796c8dcSSimon Schubert } /* non-zero */
32745796c8dcSSimon Schubert } /* each unit */
32755796c8dcSSimon Schubert /* [here uc-1 is the msu of the result] */
32765796c8dcSSimon Schubert res->digits=decGetDigits(res->lsu, uc-res->lsu);
32775796c8dcSSimon Schubert res->exponent=0; /* integer */
32785796c8dcSSimon Schubert res->bits=0; /* sign=0 */
32795796c8dcSSimon Schubert return res; /* [no status to set] */
32805796c8dcSSimon Schubert } /* decNumberXor */
32815796c8dcSSimon Schubert
32825796c8dcSSimon Schubert
32835796c8dcSSimon Schubert /* ================================================================== */
32845796c8dcSSimon Schubert /* Utility routines */
32855796c8dcSSimon Schubert /* ================================================================== */
32865796c8dcSSimon Schubert
32875796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
32885796c8dcSSimon Schubert /* decNumberClass -- return the decClass of a decNumber */
32895796c8dcSSimon Schubert /* dn -- the decNumber to test */
32905796c8dcSSimon Schubert /* set -- the context to use for Emin */
32915796c8dcSSimon Schubert /* returns the decClass enum */
32925796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberClass(const decNumber * dn,decContext * set)32935796c8dcSSimon Schubert enum decClass decNumberClass(const decNumber *dn, decContext *set) {
32945796c8dcSSimon Schubert if (decNumberIsSpecial(dn)) {
32955796c8dcSSimon Schubert if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN;
32965796c8dcSSimon Schubert if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN;
32975796c8dcSSimon Schubert /* must be an infinity */
32985796c8dcSSimon Schubert if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF;
32995796c8dcSSimon Schubert return DEC_CLASS_POS_INF;
33005796c8dcSSimon Schubert }
33015796c8dcSSimon Schubert /* is finite */
33025796c8dcSSimon Schubert if (decNumberIsNormal(dn, set)) { /* most common */
33035796c8dcSSimon Schubert if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL;
33045796c8dcSSimon Schubert return DEC_CLASS_POS_NORMAL;
33055796c8dcSSimon Schubert }
33065796c8dcSSimon Schubert /* is subnormal or zero */
33075796c8dcSSimon Schubert if (decNumberIsZero(dn)) { /* most common */
33085796c8dcSSimon Schubert if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO;
33095796c8dcSSimon Schubert return DEC_CLASS_POS_ZERO;
33105796c8dcSSimon Schubert }
33115796c8dcSSimon Schubert if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL;
33125796c8dcSSimon Schubert return DEC_CLASS_POS_SUBNORMAL;
33135796c8dcSSimon Schubert } /* decNumberClass */
33145796c8dcSSimon Schubert
33155796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
33165796c8dcSSimon Schubert /* decNumberClassToString -- convert decClass to a string */
33175796c8dcSSimon Schubert /* */
33185796c8dcSSimon Schubert /* eclass is a valid decClass */
33195796c8dcSSimon Schubert /* returns a constant string describing the class (max 13+1 chars) */
33205796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberClassToString(enum decClass eclass)33215796c8dcSSimon Schubert const char *decNumberClassToString(enum decClass eclass) {
33225796c8dcSSimon Schubert if (eclass==DEC_CLASS_POS_NORMAL) return DEC_ClassString_PN;
33235796c8dcSSimon Schubert if (eclass==DEC_CLASS_NEG_NORMAL) return DEC_ClassString_NN;
33245796c8dcSSimon Schubert if (eclass==DEC_CLASS_POS_ZERO) return DEC_ClassString_PZ;
33255796c8dcSSimon Schubert if (eclass==DEC_CLASS_NEG_ZERO) return DEC_ClassString_NZ;
33265796c8dcSSimon Schubert if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS;
33275796c8dcSSimon Schubert if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS;
33285796c8dcSSimon Schubert if (eclass==DEC_CLASS_POS_INF) return DEC_ClassString_PI;
33295796c8dcSSimon Schubert if (eclass==DEC_CLASS_NEG_INF) return DEC_ClassString_NI;
33305796c8dcSSimon Schubert if (eclass==DEC_CLASS_QNAN) return DEC_ClassString_QN;
33315796c8dcSSimon Schubert if (eclass==DEC_CLASS_SNAN) return DEC_ClassString_SN;
33325796c8dcSSimon Schubert return DEC_ClassString_UN; /* Unknown */
33335796c8dcSSimon Schubert } /* decNumberClassToString */
33345796c8dcSSimon Schubert
33355796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
33365796c8dcSSimon Schubert /* decNumberCopy -- copy a number */
33375796c8dcSSimon Schubert /* */
33385796c8dcSSimon Schubert /* dest is the target decNumber */
33395796c8dcSSimon Schubert /* src is the source decNumber */
33405796c8dcSSimon Schubert /* returns dest */
33415796c8dcSSimon Schubert /* */
33425796c8dcSSimon Schubert /* (dest==src is allowed and is a no-op) */
33435796c8dcSSimon Schubert /* All fields are updated as required. This is a utility operation, */
33445796c8dcSSimon Schubert /* so special values are unchanged and no error is possible. */
33455796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberCopy(decNumber * dest,const decNumber * src)33465796c8dcSSimon Schubert decNumber * decNumberCopy(decNumber *dest, const decNumber *src) {
33475796c8dcSSimon Schubert
33485796c8dcSSimon Schubert #if DECCHECK
33495796c8dcSSimon Schubert if (src==NULL) return decNumberZero(dest);
33505796c8dcSSimon Schubert #endif
33515796c8dcSSimon Schubert
33525796c8dcSSimon Schubert if (dest==src) return dest; /* no copy required */
33535796c8dcSSimon Schubert
33545796c8dcSSimon Schubert /* Use explicit assignments here as structure assignment could copy */
33555796c8dcSSimon Schubert /* more than just the lsu (for small DECDPUN). This would not affect */
33565796c8dcSSimon Schubert /* the value of the results, but could disturb test harness spill */
33575796c8dcSSimon Schubert /* checking. */
33585796c8dcSSimon Schubert dest->bits=src->bits;
33595796c8dcSSimon Schubert dest->exponent=src->exponent;
33605796c8dcSSimon Schubert dest->digits=src->digits;
33615796c8dcSSimon Schubert dest->lsu[0]=src->lsu[0];
33625796c8dcSSimon Schubert if (src->digits>DECDPUN) { /* more Units to come */
33635796c8dcSSimon Schubert const Unit *smsup, *s; /* work */
33645796c8dcSSimon Schubert Unit *d; /* .. */
33655796c8dcSSimon Schubert /* memcpy for the remaining Units would be safe as they cannot */
33665796c8dcSSimon Schubert /* overlap. However, this explicit loop is faster in short cases. */
33675796c8dcSSimon Schubert d=dest->lsu+1; /* -> first destination */
33685796c8dcSSimon Schubert smsup=src->lsu+D2U(src->digits); /* -> source msu+1 */
33695796c8dcSSimon Schubert for (s=src->lsu+1; s<smsup; s++, d++) *d=*s;
33705796c8dcSSimon Schubert }
33715796c8dcSSimon Schubert return dest;
33725796c8dcSSimon Schubert } /* decNumberCopy */
33735796c8dcSSimon Schubert
33745796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
33755796c8dcSSimon Schubert /* decNumberCopyAbs -- quiet absolute value operator */
33765796c8dcSSimon Schubert /* */
33775796c8dcSSimon Schubert /* This sets C = abs(A) */
33785796c8dcSSimon Schubert /* */
33795796c8dcSSimon Schubert /* res is C, the result. C may be A */
33805796c8dcSSimon Schubert /* rhs is A */
33815796c8dcSSimon Schubert /* */
33825796c8dcSSimon Schubert /* C must have space for set->digits digits. */
33835796c8dcSSimon Schubert /* No exception or error can occur; this is a quiet bitwise operation.*/
33845796c8dcSSimon Schubert /* See also decNumberAbs for a checking version of this. */
33855796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberCopyAbs(decNumber * res,const decNumber * rhs)33865796c8dcSSimon Schubert decNumber * decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
33875796c8dcSSimon Schubert #if DECCHECK
33885796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
33895796c8dcSSimon Schubert #endif
33905796c8dcSSimon Schubert decNumberCopy(res, rhs);
33915796c8dcSSimon Schubert res->bits&=~DECNEG; /* turn off sign */
33925796c8dcSSimon Schubert return res;
33935796c8dcSSimon Schubert } /* decNumberCopyAbs */
33945796c8dcSSimon Schubert
33955796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
33965796c8dcSSimon Schubert /* decNumberCopyNegate -- quiet negate value operator */
33975796c8dcSSimon Schubert /* */
33985796c8dcSSimon Schubert /* This sets C = negate(A) */
33995796c8dcSSimon Schubert /* */
34005796c8dcSSimon Schubert /* res is C, the result. C may be A */
34015796c8dcSSimon Schubert /* rhs is A */
34025796c8dcSSimon Schubert /* */
34035796c8dcSSimon Schubert /* C must have space for set->digits digits. */
34045796c8dcSSimon Schubert /* No exception or error can occur; this is a quiet bitwise operation.*/
34055796c8dcSSimon Schubert /* See also decNumberMinus for a checking version of this. */
34065796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberCopyNegate(decNumber * res,const decNumber * rhs)34075796c8dcSSimon Schubert decNumber * decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
34085796c8dcSSimon Schubert #if DECCHECK
34095796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
34105796c8dcSSimon Schubert #endif
34115796c8dcSSimon Schubert decNumberCopy(res, rhs);
34125796c8dcSSimon Schubert res->bits^=DECNEG; /* invert the sign */
34135796c8dcSSimon Schubert return res;
34145796c8dcSSimon Schubert } /* decNumberCopyNegate */
34155796c8dcSSimon Schubert
34165796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
34175796c8dcSSimon Schubert /* decNumberCopySign -- quiet copy and set sign operator */
34185796c8dcSSimon Schubert /* */
34195796c8dcSSimon Schubert /* This sets C = A with the sign of B */
34205796c8dcSSimon Schubert /* */
34215796c8dcSSimon Schubert /* res is C, the result. C may be A */
34225796c8dcSSimon Schubert /* lhs is A */
34235796c8dcSSimon Schubert /* rhs is B */
34245796c8dcSSimon Schubert /* */
34255796c8dcSSimon Schubert /* C must have space for set->digits digits. */
34265796c8dcSSimon Schubert /* No exception or error can occur; this is a quiet bitwise operation.*/
34275796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberCopySign(decNumber * res,const decNumber * lhs,const decNumber * rhs)34285796c8dcSSimon Schubert decNumber * decNumberCopySign(decNumber *res, const decNumber *lhs,
34295796c8dcSSimon Schubert const decNumber *rhs) {
34305796c8dcSSimon Schubert uByte sign; /* rhs sign */
34315796c8dcSSimon Schubert #if DECCHECK
34325796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
34335796c8dcSSimon Schubert #endif
34345796c8dcSSimon Schubert sign=rhs->bits & DECNEG; /* save sign bit */
34355796c8dcSSimon Schubert decNumberCopy(res, lhs);
34365796c8dcSSimon Schubert res->bits&=~DECNEG; /* clear the sign */
34375796c8dcSSimon Schubert res->bits|=sign; /* set from rhs */
34385796c8dcSSimon Schubert return res;
34395796c8dcSSimon Schubert } /* decNumberCopySign */
34405796c8dcSSimon Schubert
34415796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
34425796c8dcSSimon Schubert /* decNumberGetBCD -- get the coefficient in BCD8 */
34435796c8dcSSimon Schubert /* dn is the source decNumber */
34445796c8dcSSimon Schubert /* bcd is the uInt array that will receive dn->digits BCD bytes, */
34455796c8dcSSimon Schubert /* most-significant at offset 0 */
34465796c8dcSSimon Schubert /* returns bcd */
34475796c8dcSSimon Schubert /* */
34485796c8dcSSimon Schubert /* bcd must have at least dn->digits bytes. No error is possible; if */
34495796c8dcSSimon Schubert /* dn is a NaN or Infinite, digits must be 1 and the coefficient 0. */
34505796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberGetBCD(const decNumber * dn,uByte * bcd)34515796c8dcSSimon Schubert uByte * decNumberGetBCD(const decNumber *dn, uByte *bcd) {
34525796c8dcSSimon Schubert uByte *ub=bcd+dn->digits-1; /* -> lsd */
34535796c8dcSSimon Schubert const Unit *up=dn->lsu; /* Unit pointer, -> lsu */
34545796c8dcSSimon Schubert
34555796c8dcSSimon Schubert #if DECDPUN==1 /* trivial simple copy */
34565796c8dcSSimon Schubert for (; ub>=bcd; ub--, up++) *ub=*up;
34575796c8dcSSimon Schubert #else /* chopping needed */
34585796c8dcSSimon Schubert uInt u=*up; /* work */
34595796c8dcSSimon Schubert uInt cut=DECDPUN; /* downcounter through unit */
34605796c8dcSSimon Schubert for (; ub>=bcd; ub--) {
34615796c8dcSSimon Schubert *ub=(uByte)(u%10); /* [*6554 trick inhibits, here] */
34625796c8dcSSimon Schubert u=u/10;
34635796c8dcSSimon Schubert cut--;
34645796c8dcSSimon Schubert if (cut>0) continue; /* more in this unit */
34655796c8dcSSimon Schubert up++;
34665796c8dcSSimon Schubert u=*up;
34675796c8dcSSimon Schubert cut=DECDPUN;
34685796c8dcSSimon Schubert }
34695796c8dcSSimon Schubert #endif
34705796c8dcSSimon Schubert return bcd;
34715796c8dcSSimon Schubert } /* decNumberGetBCD */
34725796c8dcSSimon Schubert
34735796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
34745796c8dcSSimon Schubert /* decNumberSetBCD -- set (replace) the coefficient from BCD8 */
34755796c8dcSSimon Schubert /* dn is the target decNumber */
34765796c8dcSSimon Schubert /* bcd is the uInt array that will source n BCD bytes, most- */
34775796c8dcSSimon Schubert /* significant at offset 0 */
34785796c8dcSSimon Schubert /* n is the number of digits in the source BCD array (bcd) */
34795796c8dcSSimon Schubert /* returns dn */
34805796c8dcSSimon Schubert /* */
34815796c8dcSSimon Schubert /* dn must have space for at least n digits. No error is possible; */
34825796c8dcSSimon Schubert /* if dn is a NaN, or Infinite, or is to become a zero, n must be 1 */
34835796c8dcSSimon Schubert /* and bcd[0] zero. */
34845796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberSetBCD(decNumber * dn,const uByte * bcd,uInt n)34855796c8dcSSimon Schubert decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
34865796c8dcSSimon Schubert Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [target pointer] */
34875796c8dcSSimon Schubert const uByte *ub=bcd; /* -> source msd */
34885796c8dcSSimon Schubert
34895796c8dcSSimon Schubert #if DECDPUN==1 /* trivial simple copy */
34905796c8dcSSimon Schubert for (; ub<bcd+n; ub++, up--) *up=*ub;
34915796c8dcSSimon Schubert #else /* some assembly needed */
34925796c8dcSSimon Schubert /* calculate how many digits in msu, and hence first cut */
34935796c8dcSSimon Schubert Int cut=MSUDIGITS(n); /* [faster than remainder] */
34945796c8dcSSimon Schubert for (;up>=dn->lsu; up--) { /* each Unit from msu */
34955796c8dcSSimon Schubert *up=0; /* will take <=DECDPUN digits */
34965796c8dcSSimon Schubert for (; cut>0; ub++, cut--) *up=X10(*up)+*ub;
34975796c8dcSSimon Schubert cut=DECDPUN; /* next Unit has all digits */
34985796c8dcSSimon Schubert }
34995796c8dcSSimon Schubert #endif
35005796c8dcSSimon Schubert dn->digits=n; /* set digit count */
35015796c8dcSSimon Schubert return dn;
35025796c8dcSSimon Schubert } /* decNumberSetBCD */
35035796c8dcSSimon Schubert
35045796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
35055796c8dcSSimon Schubert /* decNumberIsNormal -- test normality of a decNumber */
35065796c8dcSSimon Schubert /* dn is the decNumber to test */
35075796c8dcSSimon Schubert /* set is the context to use for Emin */
35085796c8dcSSimon Schubert /* returns 1 if |dn| is finite and >=Nmin, 0 otherwise */
35095796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberIsNormal(const decNumber * dn,decContext * set)35105796c8dcSSimon Schubert Int decNumberIsNormal(const decNumber *dn, decContext *set) {
35115796c8dcSSimon Schubert Int ae; /* adjusted exponent */
35125796c8dcSSimon Schubert #if DECCHECK
35135796c8dcSSimon Schubert if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
35145796c8dcSSimon Schubert #endif
35155796c8dcSSimon Schubert
35165796c8dcSSimon Schubert if (decNumberIsSpecial(dn)) return 0; /* not finite */
35175796c8dcSSimon Schubert if (decNumberIsZero(dn)) return 0; /* not non-zero */
35185796c8dcSSimon Schubert
35195796c8dcSSimon Schubert ae=dn->exponent+dn->digits-1; /* adjusted exponent */
35205796c8dcSSimon Schubert if (ae<set->emin) return 0; /* is subnormal */
35215796c8dcSSimon Schubert return 1;
35225796c8dcSSimon Schubert } /* decNumberIsNormal */
35235796c8dcSSimon Schubert
35245796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
35255796c8dcSSimon Schubert /* decNumberIsSubnormal -- test subnormality of a decNumber */
35265796c8dcSSimon Schubert /* dn is the decNumber to test */
35275796c8dcSSimon Schubert /* set is the context to use for Emin */
35285796c8dcSSimon Schubert /* returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise */
35295796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberIsSubnormal(const decNumber * dn,decContext * set)35305796c8dcSSimon Schubert Int decNumberIsSubnormal(const decNumber *dn, decContext *set) {
35315796c8dcSSimon Schubert Int ae; /* adjusted exponent */
35325796c8dcSSimon Schubert #if DECCHECK
35335796c8dcSSimon Schubert if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
35345796c8dcSSimon Schubert #endif
35355796c8dcSSimon Schubert
35365796c8dcSSimon Schubert if (decNumberIsSpecial(dn)) return 0; /* not finite */
35375796c8dcSSimon Schubert if (decNumberIsZero(dn)) return 0; /* not non-zero */
35385796c8dcSSimon Schubert
35395796c8dcSSimon Schubert ae=dn->exponent+dn->digits-1; /* adjusted exponent */
35405796c8dcSSimon Schubert if (ae<set->emin) return 1; /* is subnormal */
35415796c8dcSSimon Schubert return 0;
35425796c8dcSSimon Schubert } /* decNumberIsSubnormal */
35435796c8dcSSimon Schubert
35445796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
35455796c8dcSSimon Schubert /* decNumberTrim -- remove insignificant zeros */
35465796c8dcSSimon Schubert /* */
35475796c8dcSSimon Schubert /* dn is the number to trim */
35485796c8dcSSimon Schubert /* returns dn */
35495796c8dcSSimon Schubert /* */
35505796c8dcSSimon Schubert /* All fields are updated as required. This is a utility operation, */
35515796c8dcSSimon Schubert /* so special values are unchanged and no error is possible. The */
35525796c8dcSSimon Schubert /* zeros are removed unconditionally. */
35535796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberTrim(decNumber * dn)35545796c8dcSSimon Schubert decNumber * decNumberTrim(decNumber *dn) {
35555796c8dcSSimon Schubert Int dropped; /* work */
35565796c8dcSSimon Schubert decContext set; /* .. */
35575796c8dcSSimon Schubert #if DECCHECK
35585796c8dcSSimon Schubert if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn;
35595796c8dcSSimon Schubert #endif
35605796c8dcSSimon Schubert decContextDefault(&set, DEC_INIT_BASE); /* clamp=0 */
35615796c8dcSSimon Schubert return decTrim(dn, &set, 0, 1, &dropped);
35625796c8dcSSimon Schubert } /* decNumberTrim */
35635796c8dcSSimon Schubert
35645796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
35655796c8dcSSimon Schubert /* decNumberVersion -- return the name and version of this module */
35665796c8dcSSimon Schubert /* */
35675796c8dcSSimon Schubert /* No error is possible. */
35685796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decNumberVersion(void)35695796c8dcSSimon Schubert const char * decNumberVersion(void) {
35705796c8dcSSimon Schubert return DECVERSION;
35715796c8dcSSimon Schubert } /* decNumberVersion */
35725796c8dcSSimon Schubert
35735796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
35745796c8dcSSimon Schubert /* decNumberZero -- set a number to 0 */
35755796c8dcSSimon Schubert /* */
35765796c8dcSSimon Schubert /* dn is the number to set, with space for one digit */
35775796c8dcSSimon Schubert /* returns dn */
35785796c8dcSSimon Schubert /* */
35795796c8dcSSimon Schubert /* No error is possible. */
35805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
35815796c8dcSSimon Schubert /* Memset is not used as it is much slower in some environments. */
decNumberZero(decNumber * dn)35825796c8dcSSimon Schubert decNumber * decNumberZero(decNumber *dn) {
35835796c8dcSSimon Schubert
35845796c8dcSSimon Schubert #if DECCHECK
35855796c8dcSSimon Schubert if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
35865796c8dcSSimon Schubert #endif
35875796c8dcSSimon Schubert
35885796c8dcSSimon Schubert dn->bits=0;
35895796c8dcSSimon Schubert dn->exponent=0;
35905796c8dcSSimon Schubert dn->digits=1;
35915796c8dcSSimon Schubert dn->lsu[0]=0;
35925796c8dcSSimon Schubert return dn;
35935796c8dcSSimon Schubert } /* decNumberZero */
35945796c8dcSSimon Schubert
35955796c8dcSSimon Schubert /* ================================================================== */
35965796c8dcSSimon Schubert /* Local routines */
35975796c8dcSSimon Schubert /* ================================================================== */
35985796c8dcSSimon Schubert
35995796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
36005796c8dcSSimon Schubert /* decToString -- lay out a number into a string */
36015796c8dcSSimon Schubert /* */
36025796c8dcSSimon Schubert /* dn is the number to lay out */
36035796c8dcSSimon Schubert /* string is where to lay out the number */
36045796c8dcSSimon Schubert /* eng is 1 if Engineering, 0 if Scientific */
36055796c8dcSSimon Schubert /* */
36065796c8dcSSimon Schubert /* string must be at least dn->digits+14 characters long */
36075796c8dcSSimon Schubert /* No error is possible. */
36085796c8dcSSimon Schubert /* */
36095796c8dcSSimon Schubert /* Note that this routine can generate a -0 or 0.000. These are */
36105796c8dcSSimon Schubert /* never generated in subset to-number or arithmetic, but can occur */
36115796c8dcSSimon Schubert /* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234). */
36125796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
36135796c8dcSSimon Schubert /* If DECCHECK is enabled the string "?" is returned if a number is */
36145796c8dcSSimon Schubert /* invalid. */
decToString(const decNumber * dn,char * string,Flag eng)36155796c8dcSSimon Schubert static void decToString(const decNumber *dn, char *string, Flag eng) {
36165796c8dcSSimon Schubert Int exp=dn->exponent; /* local copy */
36175796c8dcSSimon Schubert Int e; /* E-part value */
36185796c8dcSSimon Schubert Int pre; /* digits before the '.' */
36195796c8dcSSimon Schubert Int cut; /* for counting digits in a Unit */
36205796c8dcSSimon Schubert char *c=string; /* work [output pointer] */
36215796c8dcSSimon Schubert const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */
36225796c8dcSSimon Schubert uInt u, pow; /* work */
36235796c8dcSSimon Schubert
36245796c8dcSSimon Schubert #if DECCHECK
36255796c8dcSSimon Schubert if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) {
36265796c8dcSSimon Schubert strcpy(string, "?");
36275796c8dcSSimon Schubert return;}
36285796c8dcSSimon Schubert #endif
36295796c8dcSSimon Schubert
36305796c8dcSSimon Schubert if (decNumberIsNegative(dn)) { /* Negatives get a minus */
36315796c8dcSSimon Schubert *c='-';
36325796c8dcSSimon Schubert c++;
36335796c8dcSSimon Schubert }
36345796c8dcSSimon Schubert if (dn->bits&DECSPECIAL) { /* Is a special value */
36355796c8dcSSimon Schubert if (decNumberIsInfinite(dn)) {
36365796c8dcSSimon Schubert strcpy(c, "Inf");
36375796c8dcSSimon Schubert strcpy(c+3, "inity");
36385796c8dcSSimon Schubert return;}
36395796c8dcSSimon Schubert /* a NaN */
36405796c8dcSSimon Schubert if (dn->bits&DECSNAN) { /* signalling NaN */
36415796c8dcSSimon Schubert *c='s';
36425796c8dcSSimon Schubert c++;
36435796c8dcSSimon Schubert }
36445796c8dcSSimon Schubert strcpy(c, "NaN");
36455796c8dcSSimon Schubert c+=3; /* step past */
36465796c8dcSSimon Schubert /* if not a clean non-zero coefficient, that's all there is in a */
36475796c8dcSSimon Schubert /* NaN string */
36485796c8dcSSimon Schubert if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return;
36495796c8dcSSimon Schubert /* [drop through to add integer] */
36505796c8dcSSimon Schubert }
36515796c8dcSSimon Schubert
36525796c8dcSSimon Schubert /* calculate how many digits in msu, and hence first cut */
36535796c8dcSSimon Schubert cut=MSUDIGITS(dn->digits); /* [faster than remainder] */
36545796c8dcSSimon Schubert cut--; /* power of ten for digit */
36555796c8dcSSimon Schubert
36565796c8dcSSimon Schubert if (exp==0) { /* simple integer [common fastpath] */
36575796c8dcSSimon Schubert for (;up>=dn->lsu; up--) { /* each Unit from msu */
36585796c8dcSSimon Schubert u=*up; /* contains DECDPUN digits to lay out */
36595796c8dcSSimon Schubert for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow);
36605796c8dcSSimon Schubert cut=DECDPUN-1; /* next Unit has all digits */
36615796c8dcSSimon Schubert }
36625796c8dcSSimon Schubert *c='\0'; /* terminate the string */
36635796c8dcSSimon Schubert return;}
36645796c8dcSSimon Schubert
36655796c8dcSSimon Schubert /* non-0 exponent -- assume plain form */
36665796c8dcSSimon Schubert pre=dn->digits+exp; /* digits before '.' */
36675796c8dcSSimon Schubert e=0; /* no E */
36685796c8dcSSimon Schubert if ((exp>0) || (pre<-5)) { /* need exponential form */
36695796c8dcSSimon Schubert e=exp+dn->digits-1; /* calculate E value */
36705796c8dcSSimon Schubert pre=1; /* assume one digit before '.' */
36715796c8dcSSimon Schubert if (eng && (e!=0)) { /* engineering: may need to adjust */
36725796c8dcSSimon Schubert Int adj; /* adjustment */
36735796c8dcSSimon Schubert /* The C remainder operator is undefined for negative numbers, so */
36745796c8dcSSimon Schubert /* a positive remainder calculation must be used here */
36755796c8dcSSimon Schubert if (e<0) {
36765796c8dcSSimon Schubert adj=(-e)%3;
36775796c8dcSSimon Schubert if (adj!=0) adj=3-adj;
36785796c8dcSSimon Schubert }
36795796c8dcSSimon Schubert else { /* e>0 */
36805796c8dcSSimon Schubert adj=e%3;
36815796c8dcSSimon Schubert }
36825796c8dcSSimon Schubert e=e-adj;
36835796c8dcSSimon Schubert /* if dealing with zero still produce an exponent which is a */
36845796c8dcSSimon Schubert /* multiple of three, as expected, but there will only be the */
36855796c8dcSSimon Schubert /* one zero before the E, still. Otherwise note the padding. */
36865796c8dcSSimon Schubert if (!ISZERO(dn)) pre+=adj;
36875796c8dcSSimon Schubert else { /* is zero */
36885796c8dcSSimon Schubert if (adj!=0) { /* 0.00Esnn needed */
36895796c8dcSSimon Schubert e=e+3;
36905796c8dcSSimon Schubert pre=-(2-adj);
36915796c8dcSSimon Schubert }
36925796c8dcSSimon Schubert } /* zero */
36935796c8dcSSimon Schubert } /* eng */
36945796c8dcSSimon Schubert } /* need exponent */
36955796c8dcSSimon Schubert
36965796c8dcSSimon Schubert /* lay out the digits of the coefficient, adding 0s and . as needed */
36975796c8dcSSimon Schubert u=*up;
36985796c8dcSSimon Schubert if (pre>0) { /* xxx.xxx or xx00 (engineering) form */
36995796c8dcSSimon Schubert Int n=pre;
37005796c8dcSSimon Schubert for (; pre>0; pre--, c++, cut--) {
37015796c8dcSSimon Schubert if (cut<0) { /* need new Unit */
37025796c8dcSSimon Schubert if (up==dn->lsu) break; /* out of input digits (pre>digits) */
37035796c8dcSSimon Schubert up--;
37045796c8dcSSimon Schubert cut=DECDPUN-1;
37055796c8dcSSimon Schubert u=*up;
37065796c8dcSSimon Schubert }
37075796c8dcSSimon Schubert TODIGIT(u, cut, c, pow);
37085796c8dcSSimon Schubert }
37095796c8dcSSimon Schubert if (n<dn->digits) { /* more to come, after '.' */
37105796c8dcSSimon Schubert *c='.'; c++;
37115796c8dcSSimon Schubert for (;; c++, cut--) {
37125796c8dcSSimon Schubert if (cut<0) { /* need new Unit */
37135796c8dcSSimon Schubert if (up==dn->lsu) break; /* out of input digits */
37145796c8dcSSimon Schubert up--;
37155796c8dcSSimon Schubert cut=DECDPUN-1;
37165796c8dcSSimon Schubert u=*up;
37175796c8dcSSimon Schubert }
37185796c8dcSSimon Schubert TODIGIT(u, cut, c, pow);
37195796c8dcSSimon Schubert }
37205796c8dcSSimon Schubert }
37215796c8dcSSimon Schubert else for (; pre>0; pre--, c++) *c='0'; /* 0 padding (for engineering) needed */
37225796c8dcSSimon Schubert }
37235796c8dcSSimon Schubert else { /* 0.xxx or 0.000xxx form */
37245796c8dcSSimon Schubert *c='0'; c++;
37255796c8dcSSimon Schubert *c='.'; c++;
37265796c8dcSSimon Schubert for (; pre<0; pre++, c++) *c='0'; /* add any 0's after '.' */
37275796c8dcSSimon Schubert for (; ; c++, cut--) {
37285796c8dcSSimon Schubert if (cut<0) { /* need new Unit */
37295796c8dcSSimon Schubert if (up==dn->lsu) break; /* out of input digits */
37305796c8dcSSimon Schubert up--;
37315796c8dcSSimon Schubert cut=DECDPUN-1;
37325796c8dcSSimon Schubert u=*up;
37335796c8dcSSimon Schubert }
37345796c8dcSSimon Schubert TODIGIT(u, cut, c, pow);
37355796c8dcSSimon Schubert }
37365796c8dcSSimon Schubert }
37375796c8dcSSimon Schubert
37385796c8dcSSimon Schubert /* Finally add the E-part, if needed. It will never be 0, has a
37395796c8dcSSimon Schubert base maximum and minimum of +999999999 through -999999999, but
37405796c8dcSSimon Schubert could range down to -1999999998 for anormal numbers */
37415796c8dcSSimon Schubert if (e!=0) {
37425796c8dcSSimon Schubert Flag had=0; /* 1=had non-zero */
37435796c8dcSSimon Schubert *c='E'; c++;
37445796c8dcSSimon Schubert *c='+'; c++; /* assume positive */
37455796c8dcSSimon Schubert u=e; /* .. */
37465796c8dcSSimon Schubert if (e<0) {
37475796c8dcSSimon Schubert *(c-1)='-'; /* oops, need - */
37485796c8dcSSimon Schubert u=-e; /* uInt, please */
37495796c8dcSSimon Schubert }
37505796c8dcSSimon Schubert /* lay out the exponent [_itoa or equivalent is not ANSI C] */
37515796c8dcSSimon Schubert for (cut=9; cut>=0; cut--) {
37525796c8dcSSimon Schubert TODIGIT(u, cut, c, pow);
37535796c8dcSSimon Schubert if (*c=='0' && !had) continue; /* skip leading zeros */
37545796c8dcSSimon Schubert had=1; /* had non-0 */
37555796c8dcSSimon Schubert c++; /* step for next */
37565796c8dcSSimon Schubert } /* cut */
37575796c8dcSSimon Schubert }
37585796c8dcSSimon Schubert *c='\0'; /* terminate the string (all paths) */
37595796c8dcSSimon Schubert return;
37605796c8dcSSimon Schubert } /* decToString */
37615796c8dcSSimon Schubert
37625796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
37635796c8dcSSimon Schubert /* decAddOp -- add/subtract operation */
37645796c8dcSSimon Schubert /* */
37655796c8dcSSimon Schubert /* This computes C = A + B */
37665796c8dcSSimon Schubert /* */
37675796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X+X) */
37685796c8dcSSimon Schubert /* lhs is A */
37695796c8dcSSimon Schubert /* rhs is B */
37705796c8dcSSimon Schubert /* set is the context */
37715796c8dcSSimon Schubert /* negate is DECNEG if rhs should be negated, or 0 otherwise */
37725796c8dcSSimon Schubert /* status accumulates status for the caller */
37735796c8dcSSimon Schubert /* */
37745796c8dcSSimon Schubert /* C must have space for set->digits digits. */
37755796c8dcSSimon Schubert /* Inexact in status must be 0 for correct Exact zero sign in result */
37765796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
37775796c8dcSSimon Schubert /* If possible, the coefficient is calculated directly into C. */
37785796c8dcSSimon Schubert /* However, if: */
37795796c8dcSSimon Schubert /* -- a digits+1 calculation is needed because the numbers are */
37805796c8dcSSimon Schubert /* unaligned and span more than set->digits digits */
37815796c8dcSSimon Schubert /* -- a carry to digits+1 digits looks possible */
37825796c8dcSSimon Schubert /* -- C is the same as A or B, and the result would destructively */
37835796c8dcSSimon Schubert /* overlap the A or B coefficient */
37845796c8dcSSimon Schubert /* then the result must be calculated into a temporary buffer. In */
37855796c8dcSSimon Schubert /* this case a local (stack) buffer is used if possible, and only if */
37865796c8dcSSimon Schubert /* too long for that does malloc become the final resort. */
37875796c8dcSSimon Schubert /* */
37885796c8dcSSimon Schubert /* Misalignment is handled as follows: */
37895796c8dcSSimon Schubert /* Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp. */
37905796c8dcSSimon Schubert /* BPad: Apply the padding by a combination of shifting (whole */
37915796c8dcSSimon Schubert /* units) and multiplication (part units). */
37925796c8dcSSimon Schubert /* */
37935796c8dcSSimon Schubert /* Addition, especially x=x+1, is speed-critical. */
37945796c8dcSSimon Schubert /* The static buffer is larger than might be expected to allow for */
37955796c8dcSSimon Schubert /* calls from higher-level funtions (notable exp). */
37965796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decAddOp(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set,uByte negate,uInt * status)37975796c8dcSSimon Schubert static decNumber * decAddOp(decNumber *res, const decNumber *lhs,
37985796c8dcSSimon Schubert const decNumber *rhs, decContext *set,
37995796c8dcSSimon Schubert uByte negate, uInt *status) {
38005796c8dcSSimon Schubert #if DECSUBSET
38015796c8dcSSimon Schubert decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
38025796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* .., rhs */
38035796c8dcSSimon Schubert #endif
38045796c8dcSSimon Schubert Int rhsshift; /* working shift (in Units) */
38055796c8dcSSimon Schubert Int maxdigits; /* longest logical length */
38065796c8dcSSimon Schubert Int mult; /* multiplier */
38075796c8dcSSimon Schubert Int residue; /* rounding accumulator */
38085796c8dcSSimon Schubert uByte bits; /* result bits */
38095796c8dcSSimon Schubert Flag diffsign; /* non-0 if arguments have different sign */
38105796c8dcSSimon Schubert Unit *acc; /* accumulator for result */
38115796c8dcSSimon Schubert Unit accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */
38125796c8dcSSimon Schubert /* allocations when called from */
38135796c8dcSSimon Schubert /* other operations, notable exp] */
38145796c8dcSSimon Schubert Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */
38155796c8dcSSimon Schubert Int reqdigits=set->digits; /* local copy; requested DIGITS */
38165796c8dcSSimon Schubert Int padding; /* work */
38175796c8dcSSimon Schubert
38185796c8dcSSimon Schubert #if DECCHECK
38195796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
38205796c8dcSSimon Schubert #endif
38215796c8dcSSimon Schubert
38225796c8dcSSimon Schubert do { /* protect allocated storage */
38235796c8dcSSimon Schubert #if DECSUBSET
38245796c8dcSSimon Schubert if (!set->extended) {
38255796c8dcSSimon Schubert /* reduce operands and set lostDigits status, as needed */
38265796c8dcSSimon Schubert if (lhs->digits>reqdigits) {
38275796c8dcSSimon Schubert alloclhs=decRoundOperand(lhs, set, status);
38285796c8dcSSimon Schubert if (alloclhs==NULL) break;
38295796c8dcSSimon Schubert lhs=alloclhs;
38305796c8dcSSimon Schubert }
38315796c8dcSSimon Schubert if (rhs->digits>reqdigits) {
38325796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, status);
38335796c8dcSSimon Schubert if (allocrhs==NULL) break;
38345796c8dcSSimon Schubert rhs=allocrhs;
38355796c8dcSSimon Schubert }
38365796c8dcSSimon Schubert }
38375796c8dcSSimon Schubert #endif
38385796c8dcSSimon Schubert /* [following code does not require input rounding] */
38395796c8dcSSimon Schubert
38405796c8dcSSimon Schubert /* note whether signs differ [used all paths] */
38415796c8dcSSimon Schubert diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG);
38425796c8dcSSimon Schubert
38435796c8dcSSimon Schubert /* handle infinities and NaNs */
38445796c8dcSSimon Schubert if (SPECIALARGS) { /* a special bit set */
38455796c8dcSSimon Schubert if (SPECIALARGS & (DECSNAN | DECNAN)) /* a NaN */
38465796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, status);
38475796c8dcSSimon Schubert else { /* one or two infinities */
38485796c8dcSSimon Schubert if (decNumberIsInfinite(lhs)) { /* LHS is infinity */
38495796c8dcSSimon Schubert /* two infinities with different signs is invalid */
38505796c8dcSSimon Schubert if (decNumberIsInfinite(rhs) && diffsign) {
38515796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
38525796c8dcSSimon Schubert break;
38535796c8dcSSimon Schubert }
38545796c8dcSSimon Schubert bits=lhs->bits & DECNEG; /* get sign from LHS */
38555796c8dcSSimon Schubert }
38565796c8dcSSimon Schubert else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */
38575796c8dcSSimon Schubert bits|=DECINF;
38585796c8dcSSimon Schubert decNumberZero(res);
38595796c8dcSSimon Schubert res->bits=bits; /* set +/- infinity */
38605796c8dcSSimon Schubert } /* an infinity */
38615796c8dcSSimon Schubert break;
38625796c8dcSSimon Schubert }
38635796c8dcSSimon Schubert
38645796c8dcSSimon Schubert /* Quick exit for add 0s; return the non-0, modified as need be */
38655796c8dcSSimon Schubert if (ISZERO(lhs)) {
38665796c8dcSSimon Schubert Int adjust; /* work */
38675796c8dcSSimon Schubert Int lexp=lhs->exponent; /* save in case LHS==RES */
38685796c8dcSSimon Schubert bits=lhs->bits; /* .. */
38695796c8dcSSimon Schubert residue=0; /* clear accumulator */
38705796c8dcSSimon Schubert decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */
38715796c8dcSSimon Schubert res->bits^=negate; /* flip if rhs was negated */
38725796c8dcSSimon Schubert #if DECSUBSET
38735796c8dcSSimon Schubert if (set->extended) { /* exponents on zeros count */
38745796c8dcSSimon Schubert #endif
38755796c8dcSSimon Schubert /* exponent will be the lower of the two */
38765796c8dcSSimon Schubert adjust=lexp-res->exponent; /* adjustment needed [if -ve] */
38775796c8dcSSimon Schubert if (ISZERO(res)) { /* both 0: special IEEE 754 rules */
38785796c8dcSSimon Schubert if (adjust<0) res->exponent=lexp; /* set exponent */
38795796c8dcSSimon Schubert /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */
38805796c8dcSSimon Schubert if (diffsign) {
38815796c8dcSSimon Schubert if (set->round!=DEC_ROUND_FLOOR) res->bits=0;
38825796c8dcSSimon Schubert else res->bits=DECNEG; /* preserve 0 sign */
38835796c8dcSSimon Schubert }
38845796c8dcSSimon Schubert }
38855796c8dcSSimon Schubert else { /* non-0 res */
38865796c8dcSSimon Schubert if (adjust<0) { /* 0-padding needed */
38875796c8dcSSimon Schubert if ((res->digits-adjust)>set->digits) {
38885796c8dcSSimon Schubert adjust=res->digits-set->digits; /* to fit exactly */
38895796c8dcSSimon Schubert *status|=DEC_Rounded; /* [but exact] */
38905796c8dcSSimon Schubert }
38915796c8dcSSimon Schubert res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
38925796c8dcSSimon Schubert res->exponent+=adjust; /* set the exponent. */
38935796c8dcSSimon Schubert }
38945796c8dcSSimon Schubert } /* non-0 res */
38955796c8dcSSimon Schubert #if DECSUBSET
38965796c8dcSSimon Schubert } /* extended */
38975796c8dcSSimon Schubert #endif
38985796c8dcSSimon Schubert decFinish(res, set, &residue, status); /* clean and finalize */
38995796c8dcSSimon Schubert break;}
39005796c8dcSSimon Schubert
39015796c8dcSSimon Schubert if (ISZERO(rhs)) { /* [lhs is non-zero] */
39025796c8dcSSimon Schubert Int adjust; /* work */
39035796c8dcSSimon Schubert Int rexp=rhs->exponent; /* save in case RHS==RES */
39045796c8dcSSimon Schubert bits=rhs->bits; /* be clean */
39055796c8dcSSimon Schubert residue=0; /* clear accumulator */
39065796c8dcSSimon Schubert decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */
39075796c8dcSSimon Schubert #if DECSUBSET
39085796c8dcSSimon Schubert if (set->extended) { /* exponents on zeros count */
39095796c8dcSSimon Schubert #endif
39105796c8dcSSimon Schubert /* exponent will be the lower of the two */
39115796c8dcSSimon Schubert /* [0-0 case handled above] */
39125796c8dcSSimon Schubert adjust=rexp-res->exponent; /* adjustment needed [if -ve] */
39135796c8dcSSimon Schubert if (adjust<0) { /* 0-padding needed */
39145796c8dcSSimon Schubert if ((res->digits-adjust)>set->digits) {
39155796c8dcSSimon Schubert adjust=res->digits-set->digits; /* to fit exactly */
39165796c8dcSSimon Schubert *status|=DEC_Rounded; /* [but exact] */
39175796c8dcSSimon Schubert }
39185796c8dcSSimon Schubert res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
39195796c8dcSSimon Schubert res->exponent+=adjust; /* set the exponent. */
39205796c8dcSSimon Schubert }
39215796c8dcSSimon Schubert #if DECSUBSET
39225796c8dcSSimon Schubert } /* extended */
39235796c8dcSSimon Schubert #endif
39245796c8dcSSimon Schubert decFinish(res, set, &residue, status); /* clean and finalize */
39255796c8dcSSimon Schubert break;}
39265796c8dcSSimon Schubert
39275796c8dcSSimon Schubert /* [NB: both fastpath and mainpath code below assume these cases */
39285796c8dcSSimon Schubert /* (notably 0-0) have already been handled] */
39295796c8dcSSimon Schubert
39305796c8dcSSimon Schubert /* calculate the padding needed to align the operands */
39315796c8dcSSimon Schubert padding=rhs->exponent-lhs->exponent;
39325796c8dcSSimon Schubert
39335796c8dcSSimon Schubert /* Fastpath cases where the numbers are aligned and normal, the RHS */
39345796c8dcSSimon Schubert /* is all in one unit, no operand rounding is needed, and no carry, */
39355796c8dcSSimon Schubert /* lengthening, or borrow is needed */
39365796c8dcSSimon Schubert if (padding==0
39375796c8dcSSimon Schubert && rhs->digits<=DECDPUN
39385796c8dcSSimon Schubert && rhs->exponent>=set->emin /* [some normals drop through] */
39395796c8dcSSimon Schubert && rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */
39405796c8dcSSimon Schubert && rhs->digits<=reqdigits
39415796c8dcSSimon Schubert && lhs->digits<=reqdigits) {
39425796c8dcSSimon Schubert Int partial=*lhs->lsu;
39435796c8dcSSimon Schubert if (!diffsign) { /* adding */
39445796c8dcSSimon Schubert partial+=*rhs->lsu;
39455796c8dcSSimon Schubert if ((partial<=DECDPUNMAX) /* result fits in unit */
39465796c8dcSSimon Schubert && (lhs->digits>=DECDPUN || /* .. and no digits-count change */
39475796c8dcSSimon Schubert partial<(Int)powers[lhs->digits])) { /* .. */
39485796c8dcSSimon Schubert if (res!=lhs) decNumberCopy(res, lhs); /* not in place */
39495796c8dcSSimon Schubert *res->lsu=(Unit)partial; /* [copy could have overwritten RHS] */
39505796c8dcSSimon Schubert break;
39515796c8dcSSimon Schubert }
39525796c8dcSSimon Schubert /* else drop out for careful add */
39535796c8dcSSimon Schubert }
39545796c8dcSSimon Schubert else { /* signs differ */
39555796c8dcSSimon Schubert partial-=*rhs->lsu;
39565796c8dcSSimon Schubert if (partial>0) { /* no borrow needed, and non-0 result */
39575796c8dcSSimon Schubert if (res!=lhs) decNumberCopy(res, lhs); /* not in place */
39585796c8dcSSimon Schubert *res->lsu=(Unit)partial;
39595796c8dcSSimon Schubert /* this could have reduced digits [but result>0] */
39605796c8dcSSimon Schubert res->digits=decGetDigits(res->lsu, D2U(res->digits));
39615796c8dcSSimon Schubert break;
39625796c8dcSSimon Schubert }
39635796c8dcSSimon Schubert /* else drop out for careful subtract */
39645796c8dcSSimon Schubert }
39655796c8dcSSimon Schubert }
39665796c8dcSSimon Schubert
39675796c8dcSSimon Schubert /* Now align (pad) the lhs or rhs so they can be added or */
39685796c8dcSSimon Schubert /* subtracted, as necessary. If one number is much larger than */
39695796c8dcSSimon Schubert /* the other (that is, if in plain form there is a least one */
39705796c8dcSSimon Schubert /* digit between the lowest digit of one and the highest of the */
39715796c8dcSSimon Schubert /* other) padding with up to DIGITS-1 trailing zeros may be */
39725796c8dcSSimon Schubert /* needed; then apply rounding (as exotic rounding modes may be */
39735796c8dcSSimon Schubert /* affected by the residue). */
39745796c8dcSSimon Schubert rhsshift=0; /* rhs shift to left (padding) in Units */
39755796c8dcSSimon Schubert bits=lhs->bits; /* assume sign is that of LHS */
39765796c8dcSSimon Schubert mult=1; /* likely multiplier */
39775796c8dcSSimon Schubert
39785796c8dcSSimon Schubert /* [if padding==0 the operands are aligned; no padding is needed] */
39795796c8dcSSimon Schubert if (padding!=0) {
39805796c8dcSSimon Schubert /* some padding needed; always pad the RHS, as any required */
39815796c8dcSSimon Schubert /* padding can then be effected by a simple combination of */
39825796c8dcSSimon Schubert /* shifts and a multiply */
39835796c8dcSSimon Schubert Flag swapped=0;
39845796c8dcSSimon Schubert if (padding<0) { /* LHS needs the padding */
39855796c8dcSSimon Schubert const decNumber *t;
39865796c8dcSSimon Schubert padding=-padding; /* will be +ve */
39875796c8dcSSimon Schubert bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */
39885796c8dcSSimon Schubert t=lhs; lhs=rhs; rhs=t;
39895796c8dcSSimon Schubert swapped=1;
39905796c8dcSSimon Schubert }
39915796c8dcSSimon Schubert
39925796c8dcSSimon Schubert /* If, after pad, rhs would be longer than lhs by digits+1 or */
39935796c8dcSSimon Schubert /* more then lhs cannot affect the answer, except as a residue, */
39945796c8dcSSimon Schubert /* so only need to pad up to a length of DIGITS+1. */
39955796c8dcSSimon Schubert if (rhs->digits+padding > lhs->digits+reqdigits+1) {
39965796c8dcSSimon Schubert /* The RHS is sufficient */
39975796c8dcSSimon Schubert /* for residue use the relative sign indication... */
39985796c8dcSSimon Schubert Int shift=reqdigits-rhs->digits; /* left shift needed */
39995796c8dcSSimon Schubert residue=1; /* residue for rounding */
40005796c8dcSSimon Schubert if (diffsign) residue=-residue; /* signs differ */
40015796c8dcSSimon Schubert /* copy, shortening if necessary */
40025796c8dcSSimon Schubert decCopyFit(res, rhs, set, &residue, status);
40035796c8dcSSimon Schubert /* if it was already shorter, then need to pad with zeros */
40045796c8dcSSimon Schubert if (shift>0) {
40055796c8dcSSimon Schubert res->digits=decShiftToMost(res->lsu, res->digits, shift);
40065796c8dcSSimon Schubert res->exponent-=shift; /* adjust the exponent. */
40075796c8dcSSimon Schubert }
40085796c8dcSSimon Schubert /* flip the result sign if unswapped and rhs was negated */
40095796c8dcSSimon Schubert if (!swapped) res->bits^=negate;
40105796c8dcSSimon Schubert decFinish(res, set, &residue, status); /* done */
40115796c8dcSSimon Schubert break;}
40125796c8dcSSimon Schubert
40135796c8dcSSimon Schubert /* LHS digits may affect result */
40145796c8dcSSimon Schubert rhsshift=D2U(padding+1)-1; /* this much by Unit shift .. */
40155796c8dcSSimon Schubert mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */
40165796c8dcSSimon Schubert } /* padding needed */
40175796c8dcSSimon Schubert
40185796c8dcSSimon Schubert if (diffsign) mult=-mult; /* signs differ */
40195796c8dcSSimon Schubert
40205796c8dcSSimon Schubert /* determine the longer operand */
40215796c8dcSSimon Schubert maxdigits=rhs->digits+padding; /* virtual length of RHS */
40225796c8dcSSimon Schubert if (lhs->digits>maxdigits) maxdigits=lhs->digits;
40235796c8dcSSimon Schubert
40245796c8dcSSimon Schubert /* Decide on the result buffer to use; if possible place directly */
40255796c8dcSSimon Schubert /* into result. */
40265796c8dcSSimon Schubert acc=res->lsu; /* assume add direct to result */
40275796c8dcSSimon Schubert /* If destructive overlap, or the number is too long, or a carry or */
40285796c8dcSSimon Schubert /* borrow to DIGITS+1 might be possible, a buffer must be used. */
40295796c8dcSSimon Schubert /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */
40305796c8dcSSimon Schubert if ((maxdigits>=reqdigits) /* is, or could be, too large */
40315796c8dcSSimon Schubert || (res==rhs && rhsshift>0)) { /* destructive overlap */
40325796c8dcSSimon Schubert /* buffer needed, choose it; units for maxdigits digits will be */
40335796c8dcSSimon Schubert /* needed, +1 Unit for carry or borrow */
40345796c8dcSSimon Schubert Int need=D2U(maxdigits)+1;
40355796c8dcSSimon Schubert acc=accbuff; /* assume use local buffer */
40365796c8dcSSimon Schubert if (need*sizeof(Unit)>sizeof(accbuff)) {
40375796c8dcSSimon Schubert /* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */
40385796c8dcSSimon Schubert allocacc=(Unit *)malloc(need*sizeof(Unit));
40395796c8dcSSimon Schubert if (allocacc==NULL) { /* hopeless -- abandon */
40405796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
40415796c8dcSSimon Schubert break;}
40425796c8dcSSimon Schubert acc=allocacc;
40435796c8dcSSimon Schubert }
40445796c8dcSSimon Schubert }
40455796c8dcSSimon Schubert
40465796c8dcSSimon Schubert res->bits=(uByte)(bits&DECNEG); /* it's now safe to overwrite.. */
40475796c8dcSSimon Schubert res->exponent=lhs->exponent; /* .. operands (even if aliased) */
40485796c8dcSSimon Schubert
40495796c8dcSSimon Schubert #if DECTRACE
40505796c8dcSSimon Schubert decDumpAr('A', lhs->lsu, D2U(lhs->digits));
40515796c8dcSSimon Schubert decDumpAr('B', rhs->lsu, D2U(rhs->digits));
40525796c8dcSSimon Schubert printf(" :h: %ld %ld\n", rhsshift, mult);
40535796c8dcSSimon Schubert #endif
40545796c8dcSSimon Schubert
40555796c8dcSSimon Schubert /* add [A+B*m] or subtract [A+B*(-m)] */
40565796c8dcSSimon Schubert res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits),
40575796c8dcSSimon Schubert rhs->lsu, D2U(rhs->digits),
40585796c8dcSSimon Schubert rhsshift, acc, mult)
40595796c8dcSSimon Schubert *DECDPUN; /* [units -> digits] */
40605796c8dcSSimon Schubert if (res->digits<0) { /* borrowed... */
40615796c8dcSSimon Schubert res->digits=-res->digits;
40625796c8dcSSimon Schubert res->bits^=DECNEG; /* flip the sign */
40635796c8dcSSimon Schubert }
40645796c8dcSSimon Schubert #if DECTRACE
40655796c8dcSSimon Schubert decDumpAr('+', acc, D2U(res->digits));
40665796c8dcSSimon Schubert #endif
40675796c8dcSSimon Schubert
40685796c8dcSSimon Schubert /* If a buffer was used the result must be copied back, possibly */
40695796c8dcSSimon Schubert /* shortening. (If no buffer was used then the result must have */
40705796c8dcSSimon Schubert /* fit, so can't need rounding and residue must be 0.) */
40715796c8dcSSimon Schubert residue=0; /* clear accumulator */
40725796c8dcSSimon Schubert if (acc!=res->lsu) {
40735796c8dcSSimon Schubert #if DECSUBSET
40745796c8dcSSimon Schubert if (set->extended) { /* round from first significant digit */
40755796c8dcSSimon Schubert #endif
40765796c8dcSSimon Schubert /* remove leading zeros that were added due to rounding up to */
40775796c8dcSSimon Schubert /* integral Units -- before the test for rounding. */
40785796c8dcSSimon Schubert if (res->digits>reqdigits)
40795796c8dcSSimon Schubert res->digits=decGetDigits(acc, D2U(res->digits));
40805796c8dcSSimon Schubert decSetCoeff(res, set, acc, res->digits, &residue, status);
40815796c8dcSSimon Schubert #if DECSUBSET
40825796c8dcSSimon Schubert }
40835796c8dcSSimon Schubert else { /* subset arithmetic rounds from original significant digit */
40845796c8dcSSimon Schubert /* May have an underestimate. This only occurs when both */
40855796c8dcSSimon Schubert /* numbers fit in DECDPUN digits and are padding with a */
40865796c8dcSSimon Schubert /* negative multiple (-10, -100...) and the top digit(s) become */
40875796c8dcSSimon Schubert /* 0. (This only matters when using X3.274 rules where the */
40885796c8dcSSimon Schubert /* leading zero could be included in the rounding.) */
40895796c8dcSSimon Schubert if (res->digits<maxdigits) {
40905796c8dcSSimon Schubert *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */
40915796c8dcSSimon Schubert res->digits=maxdigits;
40925796c8dcSSimon Schubert }
40935796c8dcSSimon Schubert else {
40945796c8dcSSimon Schubert /* remove leading zeros that added due to rounding up to */
40955796c8dcSSimon Schubert /* integral Units (but only those in excess of the original */
40965796c8dcSSimon Schubert /* maxdigits length, unless extended) before test for rounding. */
40975796c8dcSSimon Schubert if (res->digits>reqdigits) {
40985796c8dcSSimon Schubert res->digits=decGetDigits(acc, D2U(res->digits));
40995796c8dcSSimon Schubert if (res->digits<maxdigits) res->digits=maxdigits;
41005796c8dcSSimon Schubert }
41015796c8dcSSimon Schubert }
41025796c8dcSSimon Schubert decSetCoeff(res, set, acc, res->digits, &residue, status);
41035796c8dcSSimon Schubert /* Now apply rounding if needed before removing leading zeros. */
41045796c8dcSSimon Schubert /* This is safe because subnormals are not a possibility */
41055796c8dcSSimon Schubert if (residue!=0) {
41065796c8dcSSimon Schubert decApplyRound(res, set, residue, status);
41075796c8dcSSimon Schubert residue=0; /* did what needed to be done */
41085796c8dcSSimon Schubert }
41095796c8dcSSimon Schubert } /* subset */
41105796c8dcSSimon Schubert #endif
41115796c8dcSSimon Schubert } /* used buffer */
41125796c8dcSSimon Schubert
41135796c8dcSSimon Schubert /* strip leading zeros [these were left on in case of subset subtract] */
41145796c8dcSSimon Schubert res->digits=decGetDigits(res->lsu, D2U(res->digits));
41155796c8dcSSimon Schubert
41165796c8dcSSimon Schubert /* apply checks and rounding */
41175796c8dcSSimon Schubert decFinish(res, set, &residue, status);
41185796c8dcSSimon Schubert
41195796c8dcSSimon Schubert /* "When the sum of two operands with opposite signs is exactly */
41205796c8dcSSimon Schubert /* zero, the sign of that sum shall be '+' in all rounding modes */
41215796c8dcSSimon Schubert /* except round toward -Infinity, in which mode that sign shall be */
41225796c8dcSSimon Schubert /* '-'." [Subset zeros also never have '-', set by decFinish.] */
41235796c8dcSSimon Schubert if (ISZERO(res) && diffsign
41245796c8dcSSimon Schubert #if DECSUBSET
41255796c8dcSSimon Schubert && set->extended
41265796c8dcSSimon Schubert #endif
41275796c8dcSSimon Schubert && (*status&DEC_Inexact)==0) {
41285796c8dcSSimon Schubert if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG; /* sign - */
41295796c8dcSSimon Schubert else res->bits&=~DECNEG; /* sign + */
41305796c8dcSSimon Schubert }
41315796c8dcSSimon Schubert } while(0); /* end protected */
41325796c8dcSSimon Schubert
4133a45ae5f8SJohn Marino free(allocacc); /* drop any storage used */
41345796c8dcSSimon Schubert #if DECSUBSET
4135a45ae5f8SJohn Marino free(allocrhs); /* .. */
4136a45ae5f8SJohn Marino free(alloclhs); /* .. */
41375796c8dcSSimon Schubert #endif
41385796c8dcSSimon Schubert return res;
41395796c8dcSSimon Schubert } /* decAddOp */
41405796c8dcSSimon Schubert
41415796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
41425796c8dcSSimon Schubert /* decDivideOp -- division operation */
41435796c8dcSSimon Schubert /* */
41445796c8dcSSimon Schubert /* This routine performs the calculations for all four division */
41455796c8dcSSimon Schubert /* operators (divide, divideInteger, remainder, remainderNear). */
41465796c8dcSSimon Schubert /* */
41475796c8dcSSimon Schubert /* C=A op B */
41485796c8dcSSimon Schubert /* */
41495796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X/X) */
41505796c8dcSSimon Schubert /* lhs is A */
41515796c8dcSSimon Schubert /* rhs is B */
41525796c8dcSSimon Schubert /* set is the context */
41535796c8dcSSimon Schubert /* op is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively. */
41545796c8dcSSimon Schubert /* status is the usual accumulator */
41555796c8dcSSimon Schubert /* */
41565796c8dcSSimon Schubert /* C must have space for set->digits digits. */
41575796c8dcSSimon Schubert /* */
41585796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
41595796c8dcSSimon Schubert /* The underlying algorithm of this routine is the same as in the */
41605796c8dcSSimon Schubert /* 1981 S/370 implementation, that is, non-restoring long division */
41615796c8dcSSimon Schubert /* with bi-unit (rather than bi-digit) estimation for each unit */
41625796c8dcSSimon Schubert /* multiplier. In this pseudocode overview, complications for the */
41635796c8dcSSimon Schubert /* Remainder operators and division residues for exact rounding are */
41645796c8dcSSimon Schubert /* omitted for clarity. */
41655796c8dcSSimon Schubert /* */
41665796c8dcSSimon Schubert /* Prepare operands and handle special values */
41675796c8dcSSimon Schubert /* Test for x/0 and then 0/x */
41685796c8dcSSimon Schubert /* Exp =Exp1 - Exp2 */
41695796c8dcSSimon Schubert /* Exp =Exp +len(var1) -len(var2) */
41705796c8dcSSimon Schubert /* Sign=Sign1 * Sign2 */
41715796c8dcSSimon Schubert /* Pad accumulator (Var1) to double-length with 0's (pad1) */
41725796c8dcSSimon Schubert /* Pad Var2 to same length as Var1 */
41735796c8dcSSimon Schubert /* msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round */
41745796c8dcSSimon Schubert /* have=0 */
41755796c8dcSSimon Schubert /* Do until (have=digits+1 OR residue=0) */
41765796c8dcSSimon Schubert /* if exp<0 then if integer divide/residue then leave */
41775796c8dcSSimon Schubert /* this_unit=0 */
41785796c8dcSSimon Schubert /* Do forever */
41795796c8dcSSimon Schubert /* compare numbers */
41805796c8dcSSimon Schubert /* if <0 then leave inner_loop */
41815796c8dcSSimon Schubert /* if =0 then (* quick exit without subtract *) do */
41825796c8dcSSimon Schubert /* this_unit=this_unit+1; output this_unit */
41835796c8dcSSimon Schubert /* leave outer_loop; end */
41845796c8dcSSimon Schubert /* Compare lengths of numbers (mantissae): */
41855796c8dcSSimon Schubert /* If same then tops2=msu2pair -- {units 1&2 of var2} */
41865796c8dcSSimon Schubert /* else tops2=msu2plus -- {0, unit 1 of var2} */
41875796c8dcSSimon Schubert /* tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */
41885796c8dcSSimon Schubert /* mult=tops1/tops2 -- Good and safe guess at divisor */
41895796c8dcSSimon Schubert /* if mult=0 then mult=1 */
41905796c8dcSSimon Schubert /* this_unit=this_unit+mult */
41915796c8dcSSimon Schubert /* subtract */
41925796c8dcSSimon Schubert /* end inner_loop */
41935796c8dcSSimon Schubert /* if have\=0 | this_unit\=0 then do */
41945796c8dcSSimon Schubert /* output this_unit */
41955796c8dcSSimon Schubert /* have=have+1; end */
41965796c8dcSSimon Schubert /* var2=var2/10 */
41975796c8dcSSimon Schubert /* exp=exp-1 */
41985796c8dcSSimon Schubert /* end outer_loop */
41995796c8dcSSimon Schubert /* exp=exp+1 -- set the proper exponent */
42005796c8dcSSimon Schubert /* if have=0 then generate answer=0 */
42015796c8dcSSimon Schubert /* Return (Result is defined by Var1) */
42025796c8dcSSimon Schubert /* */
42035796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
42045796c8dcSSimon Schubert /* Two working buffers are needed during the division; one (digits+ */
42055796c8dcSSimon Schubert /* 1) to accumulate the result, and the other (up to 2*digits+1) for */
42065796c8dcSSimon Schubert /* long subtractions. These are acc and var1 respectively. */
42075796c8dcSSimon Schubert /* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/
42085796c8dcSSimon Schubert /* The static buffers may be larger than might be expected to allow */
42095796c8dcSSimon Schubert /* for calls from higher-level funtions (notable exp). */
42105796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decDivideOp(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set,Flag op,uInt * status)42115796c8dcSSimon Schubert static decNumber * decDivideOp(decNumber *res,
42125796c8dcSSimon Schubert const decNumber *lhs, const decNumber *rhs,
42135796c8dcSSimon Schubert decContext *set, Flag op, uInt *status) {
42145796c8dcSSimon Schubert #if DECSUBSET
42155796c8dcSSimon Schubert decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
42165796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* .., rhs */
42175796c8dcSSimon Schubert #endif
42185796c8dcSSimon Schubert Unit accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */
42195796c8dcSSimon Schubert Unit *acc=accbuff; /* -> accumulator array for result */
42205796c8dcSSimon Schubert Unit *allocacc=NULL; /* -> allocated buffer, iff allocated */
42215796c8dcSSimon Schubert Unit *accnext; /* -> where next digit will go */
42225796c8dcSSimon Schubert Int acclength; /* length of acc needed [Units] */
42235796c8dcSSimon Schubert Int accunits; /* count of units accumulated */
42245796c8dcSSimon Schubert Int accdigits; /* count of digits accumulated */
42255796c8dcSSimon Schubert
42265796c8dcSSimon Schubert Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)]; /* buffer for var1 */
42275796c8dcSSimon Schubert Unit *var1=varbuff; /* -> var1 array for long subtraction */
42285796c8dcSSimon Schubert Unit *varalloc=NULL; /* -> allocated buffer, iff used */
42295796c8dcSSimon Schubert Unit *msu1; /* -> msu of var1 */
42305796c8dcSSimon Schubert
42315796c8dcSSimon Schubert const Unit *var2; /* -> var2 array */
42325796c8dcSSimon Schubert const Unit *msu2; /* -> msu of var2 */
42335796c8dcSSimon Schubert Int msu2plus; /* msu2 plus one [does not vary] */
42345796c8dcSSimon Schubert eInt msu2pair; /* msu2 pair plus one [does not vary] */
42355796c8dcSSimon Schubert
42365796c8dcSSimon Schubert Int var1units, var2units; /* actual lengths */
42375796c8dcSSimon Schubert Int var2ulen; /* logical length (units) */
42385796c8dcSSimon Schubert Int var1initpad=0; /* var1 initial padding (digits) */
42395796c8dcSSimon Schubert Int maxdigits; /* longest LHS or required acc length */
42405796c8dcSSimon Schubert Int mult; /* multiplier for subtraction */
42415796c8dcSSimon Schubert Unit thisunit; /* current unit being accumulated */
42425796c8dcSSimon Schubert Int residue; /* for rounding */
42435796c8dcSSimon Schubert Int reqdigits=set->digits; /* requested DIGITS */
42445796c8dcSSimon Schubert Int exponent; /* working exponent */
42455796c8dcSSimon Schubert Int maxexponent=0; /* DIVIDE maximum exponent if unrounded */
42465796c8dcSSimon Schubert uByte bits; /* working sign */
42475796c8dcSSimon Schubert Unit *target; /* work */
42485796c8dcSSimon Schubert const Unit *source; /* .. */
42495796c8dcSSimon Schubert uInt const *pow; /* .. */
42505796c8dcSSimon Schubert Int shift, cut; /* .. */
42515796c8dcSSimon Schubert #if DECSUBSET
42525796c8dcSSimon Schubert Int dropped; /* work */
42535796c8dcSSimon Schubert #endif
42545796c8dcSSimon Schubert
42555796c8dcSSimon Schubert #if DECCHECK
42565796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
42575796c8dcSSimon Schubert #endif
42585796c8dcSSimon Schubert
42595796c8dcSSimon Schubert do { /* protect allocated storage */
42605796c8dcSSimon Schubert #if DECSUBSET
42615796c8dcSSimon Schubert if (!set->extended) {
42625796c8dcSSimon Schubert /* reduce operands and set lostDigits status, as needed */
42635796c8dcSSimon Schubert if (lhs->digits>reqdigits) {
42645796c8dcSSimon Schubert alloclhs=decRoundOperand(lhs, set, status);
42655796c8dcSSimon Schubert if (alloclhs==NULL) break;
42665796c8dcSSimon Schubert lhs=alloclhs;
42675796c8dcSSimon Schubert }
42685796c8dcSSimon Schubert if (rhs->digits>reqdigits) {
42695796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, status);
42705796c8dcSSimon Schubert if (allocrhs==NULL) break;
42715796c8dcSSimon Schubert rhs=allocrhs;
42725796c8dcSSimon Schubert }
42735796c8dcSSimon Schubert }
42745796c8dcSSimon Schubert #endif
42755796c8dcSSimon Schubert /* [following code does not require input rounding] */
42765796c8dcSSimon Schubert
42775796c8dcSSimon Schubert bits=(lhs->bits^rhs->bits)&DECNEG; /* assumed sign for divisions */
42785796c8dcSSimon Schubert
42795796c8dcSSimon Schubert /* handle infinities and NaNs */
42805796c8dcSSimon Schubert if (SPECIALARGS) { /* a special bit set */
42815796c8dcSSimon Schubert if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
42825796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, status);
42835796c8dcSSimon Schubert break;
42845796c8dcSSimon Schubert }
42855796c8dcSSimon Schubert /* one or two infinities */
42865796c8dcSSimon Schubert if (decNumberIsInfinite(lhs)) { /* LHS (dividend) is infinite */
42875796c8dcSSimon Schubert if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */
42885796c8dcSSimon Schubert op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */
42895796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
42905796c8dcSSimon Schubert break;
42915796c8dcSSimon Schubert }
42925796c8dcSSimon Schubert /* [Note that infinity/0 raises no exceptions] */
42935796c8dcSSimon Schubert decNumberZero(res);
42945796c8dcSSimon Schubert res->bits=bits|DECINF; /* set +/- infinity */
42955796c8dcSSimon Schubert break;
42965796c8dcSSimon Schubert }
42975796c8dcSSimon Schubert else { /* RHS (divisor) is infinite */
42985796c8dcSSimon Schubert residue=0;
42995796c8dcSSimon Schubert if (op&(REMAINDER|REMNEAR)) {
43005796c8dcSSimon Schubert /* result is [finished clone of] lhs */
43015796c8dcSSimon Schubert decCopyFit(res, lhs, set, &residue, status);
43025796c8dcSSimon Schubert }
43035796c8dcSSimon Schubert else { /* a division */
43045796c8dcSSimon Schubert decNumberZero(res);
43055796c8dcSSimon Schubert res->bits=bits; /* set +/- zero */
43065796c8dcSSimon Schubert /* for DIVIDEINT the exponent is always 0. For DIVIDE, result */
43075796c8dcSSimon Schubert /* is a 0 with infinitely negative exponent, clamped to minimum */
43085796c8dcSSimon Schubert if (op&DIVIDE) {
43095796c8dcSSimon Schubert res->exponent=set->emin-set->digits+1;
43105796c8dcSSimon Schubert *status|=DEC_Clamped;
43115796c8dcSSimon Schubert }
43125796c8dcSSimon Schubert }
43135796c8dcSSimon Schubert decFinish(res, set, &residue, status);
43145796c8dcSSimon Schubert break;
43155796c8dcSSimon Schubert }
43165796c8dcSSimon Schubert }
43175796c8dcSSimon Schubert
43185796c8dcSSimon Schubert /* handle 0 rhs (x/0) */
43195796c8dcSSimon Schubert if (ISZERO(rhs)) { /* x/0 is always exceptional */
43205796c8dcSSimon Schubert if (ISZERO(lhs)) {
43215796c8dcSSimon Schubert decNumberZero(res); /* [after lhs test] */
43225796c8dcSSimon Schubert *status|=DEC_Division_undefined;/* 0/0 will become NaN */
43235796c8dcSSimon Schubert }
43245796c8dcSSimon Schubert else {
43255796c8dcSSimon Schubert decNumberZero(res);
43265796c8dcSSimon Schubert if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation;
43275796c8dcSSimon Schubert else {
43285796c8dcSSimon Schubert *status|=DEC_Division_by_zero; /* x/0 */
43295796c8dcSSimon Schubert res->bits=bits|DECINF; /* .. is +/- Infinity */
43305796c8dcSSimon Schubert }
43315796c8dcSSimon Schubert }
43325796c8dcSSimon Schubert break;}
43335796c8dcSSimon Schubert
43345796c8dcSSimon Schubert /* handle 0 lhs (0/x) */
43355796c8dcSSimon Schubert if (ISZERO(lhs)) { /* 0/x [x!=0] */
43365796c8dcSSimon Schubert #if DECSUBSET
43375796c8dcSSimon Schubert if (!set->extended) decNumberZero(res);
43385796c8dcSSimon Schubert else {
43395796c8dcSSimon Schubert #endif
43405796c8dcSSimon Schubert if (op&DIVIDE) {
43415796c8dcSSimon Schubert residue=0;
43425796c8dcSSimon Schubert exponent=lhs->exponent-rhs->exponent; /* ideal exponent */
43435796c8dcSSimon Schubert decNumberCopy(res, lhs); /* [zeros always fit] */
43445796c8dcSSimon Schubert res->bits=bits; /* sign as computed */
43455796c8dcSSimon Schubert res->exponent=exponent; /* exponent, too */
43465796c8dcSSimon Schubert decFinalize(res, set, &residue, status); /* check exponent */
43475796c8dcSSimon Schubert }
43485796c8dcSSimon Schubert else if (op&DIVIDEINT) {
43495796c8dcSSimon Schubert decNumberZero(res); /* integer 0 */
43505796c8dcSSimon Schubert res->bits=bits; /* sign as computed */
43515796c8dcSSimon Schubert }
43525796c8dcSSimon Schubert else { /* a remainder */
43535796c8dcSSimon Schubert exponent=rhs->exponent; /* [save in case overwrite] */
43545796c8dcSSimon Schubert decNumberCopy(res, lhs); /* [zeros always fit] */
43555796c8dcSSimon Schubert if (exponent<res->exponent) res->exponent=exponent; /* use lower */
43565796c8dcSSimon Schubert }
43575796c8dcSSimon Schubert #if DECSUBSET
43585796c8dcSSimon Schubert }
43595796c8dcSSimon Schubert #endif
43605796c8dcSSimon Schubert break;}
43615796c8dcSSimon Schubert
43625796c8dcSSimon Schubert /* Precalculate exponent. This starts off adjusted (and hence fits */
43635796c8dcSSimon Schubert /* in 31 bits) and becomes the usual unadjusted exponent as the */
43645796c8dcSSimon Schubert /* division proceeds. The order of evaluation is important, here, */
43655796c8dcSSimon Schubert /* to avoid wrap. */
43665796c8dcSSimon Schubert exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits);
43675796c8dcSSimon Schubert
43685796c8dcSSimon Schubert /* If the working exponent is -ve, then some quick exits are */
43695796c8dcSSimon Schubert /* possible because the quotient is known to be <1 */
43705796c8dcSSimon Schubert /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */
43715796c8dcSSimon Schubert if (exponent<0 && !(op==DIVIDE)) {
43725796c8dcSSimon Schubert if (op&DIVIDEINT) {
43735796c8dcSSimon Schubert decNumberZero(res); /* integer part is 0 */
43745796c8dcSSimon Schubert #if DECSUBSET
43755796c8dcSSimon Schubert if (set->extended)
43765796c8dcSSimon Schubert #endif
43775796c8dcSSimon Schubert res->bits=bits; /* set +/- zero */
43785796c8dcSSimon Schubert break;}
43795796c8dcSSimon Schubert /* fastpath remainders so long as the lhs has the smaller */
43805796c8dcSSimon Schubert /* (or equal) exponent */
43815796c8dcSSimon Schubert if (lhs->exponent<=rhs->exponent) {
43825796c8dcSSimon Schubert if (op&REMAINDER || exponent<-1) {
43835796c8dcSSimon Schubert /* It is REMAINDER or safe REMNEAR; result is [finished */
43845796c8dcSSimon Schubert /* clone of] lhs (r = x - 0*y) */
43855796c8dcSSimon Schubert residue=0;
43865796c8dcSSimon Schubert decCopyFit(res, lhs, set, &residue, status);
43875796c8dcSSimon Schubert decFinish(res, set, &residue, status);
43885796c8dcSSimon Schubert break;
43895796c8dcSSimon Schubert }
43905796c8dcSSimon Schubert /* [unsafe REMNEAR drops through] */
43915796c8dcSSimon Schubert }
43925796c8dcSSimon Schubert } /* fastpaths */
43935796c8dcSSimon Schubert
43945796c8dcSSimon Schubert /* Long (slow) division is needed; roll up the sleeves... */
43955796c8dcSSimon Schubert
43965796c8dcSSimon Schubert /* The accumulator will hold the quotient of the division. */
43975796c8dcSSimon Schubert /* If it needs to be too long for stack storage, then allocate. */
43985796c8dcSSimon Schubert acclength=D2U(reqdigits+DECDPUN); /* in Units */
43995796c8dcSSimon Schubert if (acclength*sizeof(Unit)>sizeof(accbuff)) {
44005796c8dcSSimon Schubert /* printf("malloc dvacc %ld units\n", acclength); */
44015796c8dcSSimon Schubert allocacc=(Unit *)malloc(acclength*sizeof(Unit));
44025796c8dcSSimon Schubert if (allocacc==NULL) { /* hopeless -- abandon */
44035796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
44045796c8dcSSimon Schubert break;}
44055796c8dcSSimon Schubert acc=allocacc; /* use the allocated space */
44065796c8dcSSimon Schubert }
44075796c8dcSSimon Schubert
44085796c8dcSSimon Schubert /* var1 is the padded LHS ready for subtractions. */
44095796c8dcSSimon Schubert /* If it needs to be too long for stack storage, then allocate. */
44105796c8dcSSimon Schubert /* The maximum units needed for var1 (long subtraction) is: */
44115796c8dcSSimon Schubert /* Enough for */
44125796c8dcSSimon Schubert /* (rhs->digits+reqdigits-1) -- to allow full slide to right */
44135796c8dcSSimon Schubert /* or (lhs->digits) -- to allow for long lhs */
44145796c8dcSSimon Schubert /* whichever is larger */
44155796c8dcSSimon Schubert /* +1 -- for rounding of slide to right */
44165796c8dcSSimon Schubert /* +1 -- for leading 0s */
44175796c8dcSSimon Schubert /* +1 -- for pre-adjust if a remainder or DIVIDEINT */
44185796c8dcSSimon Schubert /* [Note: unused units do not participate in decUnitAddSub data] */
44195796c8dcSSimon Schubert maxdigits=rhs->digits+reqdigits-1;
44205796c8dcSSimon Schubert if (lhs->digits>maxdigits) maxdigits=lhs->digits;
44215796c8dcSSimon Schubert var1units=D2U(maxdigits)+2;
44225796c8dcSSimon Schubert /* allocate a guard unit above msu1 for REMAINDERNEAR */
44235796c8dcSSimon Schubert if (!(op&DIVIDE)) var1units++;
44245796c8dcSSimon Schubert if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) {
44255796c8dcSSimon Schubert /* printf("malloc dvvar %ld units\n", var1units+1); */
44265796c8dcSSimon Schubert varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit));
44275796c8dcSSimon Schubert if (varalloc==NULL) { /* hopeless -- abandon */
44285796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
44295796c8dcSSimon Schubert break;}
44305796c8dcSSimon Schubert var1=varalloc; /* use the allocated space */
44315796c8dcSSimon Schubert }
44325796c8dcSSimon Schubert
44335796c8dcSSimon Schubert /* Extend the lhs and rhs to full long subtraction length. The lhs */
44345796c8dcSSimon Schubert /* is truly extended into the var1 buffer, with 0 padding, so a */
44355796c8dcSSimon Schubert /* subtract in place is always possible. The rhs (var2) has */
44365796c8dcSSimon Schubert /* virtual padding (implemented by decUnitAddSub). */
44375796c8dcSSimon Schubert /* One guard unit was allocated above msu1 for rem=rem+rem in */
44385796c8dcSSimon Schubert /* REMAINDERNEAR. */
44395796c8dcSSimon Schubert msu1=var1+var1units-1; /* msu of var1 */
44405796c8dcSSimon Schubert source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */
44415796c8dcSSimon Schubert for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source;
44425796c8dcSSimon Schubert for (; target>=var1; target--) *target=0;
44435796c8dcSSimon Schubert
44445796c8dcSSimon Schubert /* rhs (var2) is left-aligned with var1 at the start */
44455796c8dcSSimon Schubert var2ulen=var1units; /* rhs logical length (units) */
44465796c8dcSSimon Schubert var2units=D2U(rhs->digits); /* rhs actual length (units) */
44475796c8dcSSimon Schubert var2=rhs->lsu; /* -> rhs array */
44485796c8dcSSimon Schubert msu2=var2+var2units-1; /* -> msu of var2 [never changes] */
44495796c8dcSSimon Schubert /* now set up the variables which will be used for estimating the */
44505796c8dcSSimon Schubert /* multiplication factor. If these variables are not exact, add */
44515796c8dcSSimon Schubert /* 1 to make sure that the multiplier is never overestimated. */
44525796c8dcSSimon Schubert msu2plus=*msu2; /* it's value .. */
44535796c8dcSSimon Schubert if (var2units>1) msu2plus++; /* .. +1 if any more */
44545796c8dcSSimon Schubert msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */
44555796c8dcSSimon Schubert if (var2units>1) { /* .. [else treat 2nd as 0] */
44565796c8dcSSimon Schubert msu2pair+=*(msu2-1); /* .. */
44575796c8dcSSimon Schubert if (var2units>2) msu2pair++; /* .. +1 if any more */
44585796c8dcSSimon Schubert }
44595796c8dcSSimon Schubert
44605796c8dcSSimon Schubert /* The calculation is working in units, which may have leading zeros, */
44615796c8dcSSimon Schubert /* but the exponent was calculated on the assumption that they are */
44625796c8dcSSimon Schubert /* both left-aligned. Adjust the exponent to compensate: add the */
44635796c8dcSSimon Schubert /* number of leading zeros in var1 msu and subtract those in var2 msu. */
44645796c8dcSSimon Schubert /* [This is actually done by counting the digits and negating, as */
44655796c8dcSSimon Schubert /* lead1=DECDPUN-digits1, and similarly for lead2.] */
44665796c8dcSSimon Schubert for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--;
44675796c8dcSSimon Schubert for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++;
44685796c8dcSSimon Schubert
44695796c8dcSSimon Schubert /* Now, if doing an integer divide or remainder, ensure that */
44705796c8dcSSimon Schubert /* the result will be Unit-aligned. To do this, shift the var1 */
44715796c8dcSSimon Schubert /* accumulator towards least if need be. (It's much easier to */
44725796c8dcSSimon Schubert /* do this now than to reassemble the residue afterwards, if */
44735796c8dcSSimon Schubert /* doing a remainder.) Also ensure the exponent is not negative. */
44745796c8dcSSimon Schubert if (!(op&DIVIDE)) {
44755796c8dcSSimon Schubert Unit *u; /* work */
44765796c8dcSSimon Schubert /* save the initial 'false' padding of var1, in digits */
44775796c8dcSSimon Schubert var1initpad=(var1units-D2U(lhs->digits))*DECDPUN;
44785796c8dcSSimon Schubert /* Determine the shift to do. */
44795796c8dcSSimon Schubert if (exponent<0) cut=-exponent;
44805796c8dcSSimon Schubert else cut=DECDPUN-exponent%DECDPUN;
44815796c8dcSSimon Schubert decShiftToLeast(var1, var1units, cut);
44825796c8dcSSimon Schubert exponent+=cut; /* maintain numerical value */
44835796c8dcSSimon Schubert var1initpad-=cut; /* .. and reduce padding */
44845796c8dcSSimon Schubert /* clean any most-significant units which were just emptied */
44855796c8dcSSimon Schubert for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0;
44865796c8dcSSimon Schubert } /* align */
44875796c8dcSSimon Schubert else { /* is DIVIDE */
44885796c8dcSSimon Schubert maxexponent=lhs->exponent-rhs->exponent; /* save */
44895796c8dcSSimon Schubert /* optimization: if the first iteration will just produce 0, */
44905796c8dcSSimon Schubert /* preadjust to skip it [valid for DIVIDE only] */
44915796c8dcSSimon Schubert if (*msu1<*msu2) {
44925796c8dcSSimon Schubert var2ulen--; /* shift down */
44935796c8dcSSimon Schubert exponent-=DECDPUN; /* update the exponent */
44945796c8dcSSimon Schubert }
44955796c8dcSSimon Schubert }
44965796c8dcSSimon Schubert
44975796c8dcSSimon Schubert /* ---- start the long-division loops ------------------------------ */
44985796c8dcSSimon Schubert accunits=0; /* no units accumulated yet */
44995796c8dcSSimon Schubert accdigits=0; /* .. or digits */
45005796c8dcSSimon Schubert accnext=acc+acclength-1; /* -> msu of acc [NB: allows digits+1] */
45015796c8dcSSimon Schubert for (;;) { /* outer forever loop */
45025796c8dcSSimon Schubert thisunit=0; /* current unit assumed 0 */
45035796c8dcSSimon Schubert /* find the next unit */
45045796c8dcSSimon Schubert for (;;) { /* inner forever loop */
45055796c8dcSSimon Schubert /* strip leading zero units [from either pre-adjust or from */
45065796c8dcSSimon Schubert /* subtract last time around]. Leave at least one unit. */
45075796c8dcSSimon Schubert for (; *msu1==0 && msu1>var1; msu1--) var1units--;
45085796c8dcSSimon Schubert
45095796c8dcSSimon Schubert if (var1units<var2ulen) break; /* var1 too low for subtract */
45105796c8dcSSimon Schubert if (var1units==var2ulen) { /* unit-by-unit compare needed */
45115796c8dcSSimon Schubert /* compare the two numbers, from msu */
45125796c8dcSSimon Schubert const Unit *pv1, *pv2;
45135796c8dcSSimon Schubert Unit v2; /* units to compare */
45145796c8dcSSimon Schubert pv2=msu2; /* -> msu */
45155796c8dcSSimon Schubert for (pv1=msu1; ; pv1--, pv2--) {
45165796c8dcSSimon Schubert /* v1=*pv1 -- always OK */
45175796c8dcSSimon Schubert v2=0; /* assume in padding */
45185796c8dcSSimon Schubert if (pv2>=var2) v2=*pv2; /* in range */
45195796c8dcSSimon Schubert if (*pv1!=v2) break; /* no longer the same */
45205796c8dcSSimon Schubert if (pv1==var1) break; /* done; leave pv1 as is */
45215796c8dcSSimon Schubert }
45225796c8dcSSimon Schubert /* here when all inspected or a difference seen */
45235796c8dcSSimon Schubert if (*pv1<v2) break; /* var1 too low to subtract */
45245796c8dcSSimon Schubert if (*pv1==v2) { /* var1 == var2 */
45255796c8dcSSimon Schubert /* reach here if var1 and var2 are identical; subtraction */
45265796c8dcSSimon Schubert /* would increase digit by one, and the residue will be 0 so */
45275796c8dcSSimon Schubert /* the calculation is done; leave the loop with residue=0. */
45285796c8dcSSimon Schubert thisunit++; /* as though subtracted */
45295796c8dcSSimon Schubert *var1=0; /* set var1 to 0 */
45305796c8dcSSimon Schubert var1units=1; /* .. */
45315796c8dcSSimon Schubert break; /* from inner */
45325796c8dcSSimon Schubert } /* var1 == var2 */
45335796c8dcSSimon Schubert /* *pv1>v2. Prepare for real subtraction; the lengths are equal */
45345796c8dcSSimon Schubert /* Estimate the multiplier (there's always a msu1-1)... */
45355796c8dcSSimon Schubert /* Bring in two units of var2 to provide a good estimate. */
45365796c8dcSSimon Schubert mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair);
45375796c8dcSSimon Schubert } /* lengths the same */
45385796c8dcSSimon Schubert else { /* var1units > var2ulen, so subtraction is safe */
45395796c8dcSSimon Schubert /* The var2 msu is one unit towards the lsu of the var1 msu, */
45405796c8dcSSimon Schubert /* so only one unit for var2 can be used. */
45415796c8dcSSimon Schubert mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus);
45425796c8dcSSimon Schubert }
45435796c8dcSSimon Schubert if (mult==0) mult=1; /* must always be at least 1 */
45445796c8dcSSimon Schubert /* subtraction needed; var1 is > var2 */
45455796c8dcSSimon Schubert thisunit=(Unit)(thisunit+mult); /* accumulate */
45465796c8dcSSimon Schubert /* subtract var1-var2, into var1; only the overlap needs */
45475796c8dcSSimon Schubert /* processing, as this is an in-place calculation */
45485796c8dcSSimon Schubert shift=var2ulen-var2units;
45495796c8dcSSimon Schubert #if DECTRACE
45505796c8dcSSimon Schubert decDumpAr('1', &var1[shift], var1units-shift);
45515796c8dcSSimon Schubert decDumpAr('2', var2, var2units);
45525796c8dcSSimon Schubert printf("m=%ld\n", -mult);
45535796c8dcSSimon Schubert #endif
45545796c8dcSSimon Schubert decUnitAddSub(&var1[shift], var1units-shift,
45555796c8dcSSimon Schubert var2, var2units, 0,
45565796c8dcSSimon Schubert &var1[shift], -mult);
45575796c8dcSSimon Schubert #if DECTRACE
45585796c8dcSSimon Schubert decDumpAr('#', &var1[shift], var1units-shift);
45595796c8dcSSimon Schubert #endif
45605796c8dcSSimon Schubert /* var1 now probably has leading zeros; these are removed at the */
45615796c8dcSSimon Schubert /* top of the inner loop. */
45625796c8dcSSimon Schubert } /* inner loop */
45635796c8dcSSimon Schubert
45645796c8dcSSimon Schubert /* The next unit has been calculated in full; unless it's a */
45655796c8dcSSimon Schubert /* leading zero, add to acc */
45665796c8dcSSimon Schubert if (accunits!=0 || thisunit!=0) { /* is first or non-zero */
45675796c8dcSSimon Schubert *accnext=thisunit; /* store in accumulator */
45685796c8dcSSimon Schubert /* account exactly for the new digits */
45695796c8dcSSimon Schubert if (accunits==0) {
45705796c8dcSSimon Schubert accdigits++; /* at least one */
45715796c8dcSSimon Schubert for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++;
45725796c8dcSSimon Schubert }
45735796c8dcSSimon Schubert else accdigits+=DECDPUN;
45745796c8dcSSimon Schubert accunits++; /* update count */
45755796c8dcSSimon Schubert accnext--; /* ready for next */
45765796c8dcSSimon Schubert if (accdigits>reqdigits) break; /* have enough digits */
45775796c8dcSSimon Schubert }
45785796c8dcSSimon Schubert
45795796c8dcSSimon Schubert /* if the residue is zero, the operation is done (unless divide */
45805796c8dcSSimon Schubert /* or divideInteger and still not enough digits yet) */
45815796c8dcSSimon Schubert if (*var1==0 && var1units==1) { /* residue is 0 */
45825796c8dcSSimon Schubert if (op&(REMAINDER|REMNEAR)) break;
45835796c8dcSSimon Schubert if ((op&DIVIDE) && (exponent<=maxexponent)) break;
45845796c8dcSSimon Schubert /* [drop through if divideInteger] */
45855796c8dcSSimon Schubert }
45865796c8dcSSimon Schubert /* also done enough if calculating remainder or integer */
45875796c8dcSSimon Schubert /* divide and just did the last ('units') unit */
45885796c8dcSSimon Schubert if (exponent==0 && !(op&DIVIDE)) break;
45895796c8dcSSimon Schubert
45905796c8dcSSimon Schubert /* to get here, var1 is less than var2, so divide var2 by the per- */
45915796c8dcSSimon Schubert /* Unit power of ten and go for the next digit */
45925796c8dcSSimon Schubert var2ulen--; /* shift down */
45935796c8dcSSimon Schubert exponent-=DECDPUN; /* update the exponent */
45945796c8dcSSimon Schubert } /* outer loop */
45955796c8dcSSimon Schubert
45965796c8dcSSimon Schubert /* ---- division is complete --------------------------------------- */
45975796c8dcSSimon Schubert /* here: acc has at least reqdigits+1 of good results (or fewer */
45985796c8dcSSimon Schubert /* if early stop), starting at accnext+1 (its lsu) */
45995796c8dcSSimon Schubert /* var1 has any residue at the stopping point */
46005796c8dcSSimon Schubert /* accunits is the number of digits collected in acc */
46015796c8dcSSimon Schubert if (accunits==0) { /* acc is 0 */
46025796c8dcSSimon Schubert accunits=1; /* show have a unit .. */
46035796c8dcSSimon Schubert accdigits=1; /* .. */
46045796c8dcSSimon Schubert *accnext=0; /* .. whose value is 0 */
46055796c8dcSSimon Schubert }
46065796c8dcSSimon Schubert else accnext++; /* back to last placed */
46075796c8dcSSimon Schubert /* accnext now -> lowest unit of result */
46085796c8dcSSimon Schubert
46095796c8dcSSimon Schubert residue=0; /* assume no residue */
46105796c8dcSSimon Schubert if (op&DIVIDE) {
46115796c8dcSSimon Schubert /* record the presence of any residue, for rounding */
46125796c8dcSSimon Schubert if (*var1!=0 || var1units>1) residue=1;
46135796c8dcSSimon Schubert else { /* no residue */
46145796c8dcSSimon Schubert /* Had an exact division; clean up spurious trailing 0s. */
46155796c8dcSSimon Schubert /* There will be at most DECDPUN-1, from the final multiply, */
46165796c8dcSSimon Schubert /* and then only if the result is non-0 (and even) and the */
46175796c8dcSSimon Schubert /* exponent is 'loose'. */
46185796c8dcSSimon Schubert #if DECDPUN>1
46195796c8dcSSimon Schubert Unit lsu=*accnext;
46205796c8dcSSimon Schubert if (!(lsu&0x01) && (lsu!=0)) {
46215796c8dcSSimon Schubert /* count the trailing zeros */
46225796c8dcSSimon Schubert Int drop=0;
46235796c8dcSSimon Schubert for (;; drop++) { /* [will terminate because lsu!=0] */
46245796c8dcSSimon Schubert if (exponent>=maxexponent) break; /* don't chop real 0s */
46255796c8dcSSimon Schubert #if DECDPUN<=4
46265796c8dcSSimon Schubert if ((lsu-QUOT10(lsu, drop+1)
46275796c8dcSSimon Schubert *powers[drop+1])!=0) break; /* found non-0 digit */
46285796c8dcSSimon Schubert #else
46295796c8dcSSimon Schubert if (lsu%powers[drop+1]!=0) break; /* found non-0 digit */
46305796c8dcSSimon Schubert #endif
46315796c8dcSSimon Schubert exponent++;
46325796c8dcSSimon Schubert }
46335796c8dcSSimon Schubert if (drop>0) {
46345796c8dcSSimon Schubert accunits=decShiftToLeast(accnext, accunits, drop);
46355796c8dcSSimon Schubert accdigits=decGetDigits(accnext, accunits);
46365796c8dcSSimon Schubert accunits=D2U(accdigits);
46375796c8dcSSimon Schubert /* [exponent was adjusted in the loop] */
46385796c8dcSSimon Schubert }
46395796c8dcSSimon Schubert } /* neither odd nor 0 */
46405796c8dcSSimon Schubert #endif
46415796c8dcSSimon Schubert } /* exact divide */
46425796c8dcSSimon Schubert } /* divide */
46435796c8dcSSimon Schubert else /* op!=DIVIDE */ {
46445796c8dcSSimon Schubert /* check for coefficient overflow */
46455796c8dcSSimon Schubert if (accdigits+exponent>reqdigits) {
46465796c8dcSSimon Schubert *status|=DEC_Division_impossible;
46475796c8dcSSimon Schubert break;
46485796c8dcSSimon Schubert }
46495796c8dcSSimon Schubert if (op & (REMAINDER|REMNEAR)) {
46505796c8dcSSimon Schubert /* [Here, the exponent will be 0, because var1 was adjusted */
46515796c8dcSSimon Schubert /* appropriately.] */
46525796c8dcSSimon Schubert Int postshift; /* work */
46535796c8dcSSimon Schubert Flag wasodd=0; /* integer was odd */
46545796c8dcSSimon Schubert Unit *quotlsu; /* for save */
46555796c8dcSSimon Schubert Int quotdigits; /* .. */
46565796c8dcSSimon Schubert
46575796c8dcSSimon Schubert bits=lhs->bits; /* remainder sign is always as lhs */
46585796c8dcSSimon Schubert
46595796c8dcSSimon Schubert /* Fastpath when residue is truly 0 is worthwhile [and */
46605796c8dcSSimon Schubert /* simplifies the code below] */
46615796c8dcSSimon Schubert if (*var1==0 && var1units==1) { /* residue is 0 */
46625796c8dcSSimon Schubert Int exp=lhs->exponent; /* save min(exponents) */
46635796c8dcSSimon Schubert if (rhs->exponent<exp) exp=rhs->exponent;
46645796c8dcSSimon Schubert decNumberZero(res); /* 0 coefficient */
46655796c8dcSSimon Schubert #if DECSUBSET
46665796c8dcSSimon Schubert if (set->extended)
46675796c8dcSSimon Schubert #endif
46685796c8dcSSimon Schubert res->exponent=exp; /* .. with proper exponent */
46695796c8dcSSimon Schubert res->bits=(uByte)(bits&DECNEG); /* [cleaned] */
46705796c8dcSSimon Schubert decFinish(res, set, &residue, status); /* might clamp */
46715796c8dcSSimon Schubert break;
46725796c8dcSSimon Schubert }
46735796c8dcSSimon Schubert /* note if the quotient was odd */
46745796c8dcSSimon Schubert if (*accnext & 0x01) wasodd=1; /* acc is odd */
46755796c8dcSSimon Schubert quotlsu=accnext; /* save in case need to reinspect */
46765796c8dcSSimon Schubert quotdigits=accdigits; /* .. */
46775796c8dcSSimon Schubert
46785796c8dcSSimon Schubert /* treat the residue, in var1, as the value to return, via acc */
46795796c8dcSSimon Schubert /* calculate the unused zero digits. This is the smaller of: */
46805796c8dcSSimon Schubert /* var1 initial padding (saved above) */
46815796c8dcSSimon Schubert /* var2 residual padding, which happens to be given by: */
46825796c8dcSSimon Schubert postshift=var1initpad+exponent-lhs->exponent+rhs->exponent;
46835796c8dcSSimon Schubert /* [the 'exponent' term accounts for the shifts during divide] */
46845796c8dcSSimon Schubert if (var1initpad<postshift) postshift=var1initpad;
46855796c8dcSSimon Schubert
46865796c8dcSSimon Schubert /* shift var1 the requested amount, and adjust its digits */
46875796c8dcSSimon Schubert var1units=decShiftToLeast(var1, var1units, postshift);
46885796c8dcSSimon Schubert accnext=var1;
46895796c8dcSSimon Schubert accdigits=decGetDigits(var1, var1units);
46905796c8dcSSimon Schubert accunits=D2U(accdigits);
46915796c8dcSSimon Schubert
46925796c8dcSSimon Schubert exponent=lhs->exponent; /* exponent is smaller of lhs & rhs */
46935796c8dcSSimon Schubert if (rhs->exponent<exponent) exponent=rhs->exponent;
46945796c8dcSSimon Schubert
46955796c8dcSSimon Schubert /* Now correct the result if doing remainderNear; if it */
46965796c8dcSSimon Schubert /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */
46975796c8dcSSimon Schubert /* the integer was odd then the result should be rem-rhs. */
46985796c8dcSSimon Schubert if (op&REMNEAR) {
46995796c8dcSSimon Schubert Int compare, tarunits; /* work */
47005796c8dcSSimon Schubert Unit *up; /* .. */
47015796c8dcSSimon Schubert /* calculate remainder*2 into the var1 buffer (which has */
47025796c8dcSSimon Schubert /* 'headroom' of an extra unit and hence enough space) */
47035796c8dcSSimon Schubert /* [a dedicated 'double' loop would be faster, here] */
47045796c8dcSSimon Schubert tarunits=decUnitAddSub(accnext, accunits, accnext, accunits,
47055796c8dcSSimon Schubert 0, accnext, 1);
47065796c8dcSSimon Schubert /* decDumpAr('r', accnext, tarunits); */
47075796c8dcSSimon Schubert
47085796c8dcSSimon Schubert /* Here, accnext (var1) holds tarunits Units with twice the */
47095796c8dcSSimon Schubert /* remainder's coefficient, which must now be compared to the */
47105796c8dcSSimon Schubert /* RHS. The remainder's exponent may be smaller than the RHS's. */
47115796c8dcSSimon Schubert compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits),
47125796c8dcSSimon Schubert rhs->exponent-exponent);
47135796c8dcSSimon Schubert if (compare==BADINT) { /* deep trouble */
47145796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
47155796c8dcSSimon Schubert break;}
47165796c8dcSSimon Schubert
47175796c8dcSSimon Schubert /* now restore the remainder by dividing by two; the lsu */
47185796c8dcSSimon Schubert /* is known to be even. */
47195796c8dcSSimon Schubert for (up=accnext; up<accnext+tarunits; up++) {
47205796c8dcSSimon Schubert Int half; /* half to add to lower unit */
47215796c8dcSSimon Schubert half=*up & 0x01;
47225796c8dcSSimon Schubert *up/=2; /* [shift] */
47235796c8dcSSimon Schubert if (!half) continue;
47245796c8dcSSimon Schubert *(up-1)+=(DECDPUNMAX+1)/2;
47255796c8dcSSimon Schubert }
47265796c8dcSSimon Schubert /* [accunits still describes the original remainder length] */
47275796c8dcSSimon Schubert
47285796c8dcSSimon Schubert if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */
47295796c8dcSSimon Schubert Int exp, expunits, exprem; /* work */
47305796c8dcSSimon Schubert /* This is effectively causing round-up of the quotient, */
47315796c8dcSSimon Schubert /* so if it was the rare case where it was full and all */
47325796c8dcSSimon Schubert /* nines, it would overflow and hence division-impossible */
47335796c8dcSSimon Schubert /* should be raised */
47345796c8dcSSimon Schubert Flag allnines=0; /* 1 if quotient all nines */
47355796c8dcSSimon Schubert if (quotdigits==reqdigits) { /* could be borderline */
47365796c8dcSSimon Schubert for (up=quotlsu; ; up++) {
47375796c8dcSSimon Schubert if (quotdigits>DECDPUN) {
47385796c8dcSSimon Schubert if (*up!=DECDPUNMAX) break;/* non-nines */
47395796c8dcSSimon Schubert }
47405796c8dcSSimon Schubert else { /* this is the last Unit */
47415796c8dcSSimon Schubert if (*up==powers[quotdigits]-1) allnines=1;
47425796c8dcSSimon Schubert break;
47435796c8dcSSimon Schubert }
47445796c8dcSSimon Schubert quotdigits-=DECDPUN; /* checked those digits */
47455796c8dcSSimon Schubert } /* up */
47465796c8dcSSimon Schubert } /* borderline check */
47475796c8dcSSimon Schubert if (allnines) {
47485796c8dcSSimon Schubert *status|=DEC_Division_impossible;
47495796c8dcSSimon Schubert break;}
47505796c8dcSSimon Schubert
47515796c8dcSSimon Schubert /* rem-rhs is needed; the sign will invert. Again, var1 */
47525796c8dcSSimon Schubert /* can safely be used for the working Units array. */
47535796c8dcSSimon Schubert exp=rhs->exponent-exponent; /* RHS padding needed */
47545796c8dcSSimon Schubert /* Calculate units and remainder from exponent. */
47555796c8dcSSimon Schubert expunits=exp/DECDPUN;
47565796c8dcSSimon Schubert exprem=exp%DECDPUN;
47575796c8dcSSimon Schubert /* subtract [A+B*(-m)]; the result will always be negative */
47585796c8dcSSimon Schubert accunits=-decUnitAddSub(accnext, accunits,
47595796c8dcSSimon Schubert rhs->lsu, D2U(rhs->digits),
47605796c8dcSSimon Schubert expunits, accnext, -(Int)powers[exprem]);
47615796c8dcSSimon Schubert accdigits=decGetDigits(accnext, accunits); /* count digits exactly */
47625796c8dcSSimon Schubert accunits=D2U(accdigits); /* and recalculate the units for copy */
47635796c8dcSSimon Schubert /* [exponent is as for original remainder] */
47645796c8dcSSimon Schubert bits^=DECNEG; /* flip the sign */
47655796c8dcSSimon Schubert }
47665796c8dcSSimon Schubert } /* REMNEAR */
47675796c8dcSSimon Schubert } /* REMAINDER or REMNEAR */
47685796c8dcSSimon Schubert } /* not DIVIDE */
47695796c8dcSSimon Schubert
47705796c8dcSSimon Schubert /* Set exponent and bits */
47715796c8dcSSimon Schubert res->exponent=exponent;
47725796c8dcSSimon Schubert res->bits=(uByte)(bits&DECNEG); /* [cleaned] */
47735796c8dcSSimon Schubert
47745796c8dcSSimon Schubert /* Now the coefficient. */
47755796c8dcSSimon Schubert decSetCoeff(res, set, accnext, accdigits, &residue, status);
47765796c8dcSSimon Schubert
47775796c8dcSSimon Schubert decFinish(res, set, &residue, status); /* final cleanup */
47785796c8dcSSimon Schubert
47795796c8dcSSimon Schubert #if DECSUBSET
47805796c8dcSSimon Schubert /* If a divide then strip trailing zeros if subset [after round] */
47815796c8dcSSimon Schubert if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, 1, &dropped);
47825796c8dcSSimon Schubert #endif
47835796c8dcSSimon Schubert } while(0); /* end protected */
47845796c8dcSSimon Schubert
4785a45ae5f8SJohn Marino free(varalloc); /* drop any storage used */
4786a45ae5f8SJohn Marino free(allocacc); /* .. */
47875796c8dcSSimon Schubert #if DECSUBSET
4788a45ae5f8SJohn Marino free(allocrhs); /* .. */
4789a45ae5f8SJohn Marino free(alloclhs); /* .. */
47905796c8dcSSimon Schubert #endif
47915796c8dcSSimon Schubert return res;
47925796c8dcSSimon Schubert } /* decDivideOp */
47935796c8dcSSimon Schubert
47945796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
47955796c8dcSSimon Schubert /* decMultiplyOp -- multiplication operation */
47965796c8dcSSimon Schubert /* */
47975796c8dcSSimon Schubert /* This routine performs the multiplication C=A x B. */
47985796c8dcSSimon Schubert /* */
47995796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X*X) */
48005796c8dcSSimon Schubert /* lhs is A */
48015796c8dcSSimon Schubert /* rhs is B */
48025796c8dcSSimon Schubert /* set is the context */
48035796c8dcSSimon Schubert /* status is the usual accumulator */
48045796c8dcSSimon Schubert /* */
48055796c8dcSSimon Schubert /* C must have space for set->digits digits. */
48065796c8dcSSimon Schubert /* */
48075796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
48085796c8dcSSimon Schubert /* 'Classic' multiplication is used rather than Karatsuba, as the */
48095796c8dcSSimon Schubert /* latter would give only a minor improvement for the short numbers */
48105796c8dcSSimon Schubert /* expected to be handled most (and uses much more memory). */
48115796c8dcSSimon Schubert /* */
48125796c8dcSSimon Schubert /* There are two major paths here: the general-purpose ('old code') */
48135796c8dcSSimon Schubert /* path which handles all DECDPUN values, and a fastpath version */
48145796c8dcSSimon Schubert /* which is used if 64-bit ints are available, DECDPUN<=4, and more */
48155796c8dcSSimon Schubert /* than two calls to decUnitAddSub would be made. */
48165796c8dcSSimon Schubert /* */
48175796c8dcSSimon Schubert /* The fastpath version lumps units together into 8-digit or 9-digit */
48185796c8dcSSimon Schubert /* chunks, and also uses a lazy carry strategy to minimise expensive */
48195796c8dcSSimon Schubert /* 64-bit divisions. The chunks are then broken apart again into */
48205796c8dcSSimon Schubert /* units for continuing processing. Despite this overhead, the */
48215796c8dcSSimon Schubert /* fastpath can speed up some 16-digit operations by 10x (and much */
48225796c8dcSSimon Schubert /* more for higher-precision calculations). */
48235796c8dcSSimon Schubert /* */
48245796c8dcSSimon Schubert /* A buffer always has to be used for the accumulator; in the */
48255796c8dcSSimon Schubert /* fastpath, buffers are also always needed for the chunked copies of */
48265796c8dcSSimon Schubert /* of the operand coefficients. */
48275796c8dcSSimon Schubert /* Static buffers are larger than needed just for multiply, to allow */
48285796c8dcSSimon Schubert /* for calls from other operations (notably exp). */
48295796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
48305796c8dcSSimon Schubert #define FASTMUL (DECUSE64 && DECDPUN<5)
decMultiplyOp(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set,uInt * status)48315796c8dcSSimon Schubert static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs,
48325796c8dcSSimon Schubert const decNumber *rhs, decContext *set,
48335796c8dcSSimon Schubert uInt *status) {
48345796c8dcSSimon Schubert Int accunits; /* Units of accumulator in use */
48355796c8dcSSimon Schubert Int exponent; /* work */
48365796c8dcSSimon Schubert Int residue=0; /* rounding residue */
48375796c8dcSSimon Schubert uByte bits; /* result sign */
48385796c8dcSSimon Schubert Unit *acc; /* -> accumulator Unit array */
48395796c8dcSSimon Schubert Int needbytes; /* size calculator */
48405796c8dcSSimon Schubert void *allocacc=NULL; /* -> allocated accumulator, iff allocated */
48415796c8dcSSimon Schubert Unit accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */
48425796c8dcSSimon Schubert /* *4 for calls from other operations) */
48435796c8dcSSimon Schubert const Unit *mer, *mermsup; /* work */
48445796c8dcSSimon Schubert Int madlength; /* Units in multiplicand */
48455796c8dcSSimon Schubert Int shift; /* Units to shift multiplicand by */
48465796c8dcSSimon Schubert
48475796c8dcSSimon Schubert #if FASTMUL
48485796c8dcSSimon Schubert /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */
48495796c8dcSSimon Schubert /* (DECDPUN is 2 or 4) then work in base 10**8 */
48505796c8dcSSimon Schubert #if DECDPUN & 1 /* odd */
48515796c8dcSSimon Schubert #define FASTBASE 1000000000 /* base */
48525796c8dcSSimon Schubert #define FASTDIGS 9 /* digits in base */
48535796c8dcSSimon Schubert #define FASTLAZY 18 /* carry resolution point [1->18] */
48545796c8dcSSimon Schubert #else
48555796c8dcSSimon Schubert #define FASTBASE 100000000
48565796c8dcSSimon Schubert #define FASTDIGS 8
48575796c8dcSSimon Schubert #define FASTLAZY 1844 /* carry resolution point [1->1844] */
48585796c8dcSSimon Schubert #endif
48595796c8dcSSimon Schubert /* three buffers are used, two for chunked copies of the operands */
48605796c8dcSSimon Schubert /* (base 10**8 or base 10**9) and one base 2**64 accumulator with */
48615796c8dcSSimon Schubert /* lazy carry evaluation */
48625796c8dcSSimon Schubert uInt zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
48635796c8dcSSimon Schubert uInt *zlhi=zlhibuff; /* -> lhs array */
48645796c8dcSSimon Schubert uInt *alloclhi=NULL; /* -> allocated buffer, iff allocated */
48655796c8dcSSimon Schubert uInt zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
48665796c8dcSSimon Schubert uInt *zrhi=zrhibuff; /* -> rhs array */
48675796c8dcSSimon Schubert uInt *allocrhi=NULL; /* -> allocated buffer, iff allocated */
48685796c8dcSSimon Schubert uLong zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */
48695796c8dcSSimon Schubert /* [allocacc is shared for both paths, as only one will run] */
48705796c8dcSSimon Schubert uLong *zacc=zaccbuff; /* -> accumulator array for exact result */
48715796c8dcSSimon Schubert #if DECDPUN==1
48725796c8dcSSimon Schubert Int zoff; /* accumulator offset */
48735796c8dcSSimon Schubert #endif
48745796c8dcSSimon Schubert uInt *lip, *rip; /* item pointers */
48755796c8dcSSimon Schubert uInt *lmsi, *rmsi; /* most significant items */
48765796c8dcSSimon Schubert Int ilhs, irhs, iacc; /* item counts in the arrays */
48775796c8dcSSimon Schubert Int lazy; /* lazy carry counter */
48785796c8dcSSimon Schubert uLong lcarry; /* uLong carry */
48795796c8dcSSimon Schubert uInt carry; /* carry (NB not uLong) */
48805796c8dcSSimon Schubert Int count; /* work */
48815796c8dcSSimon Schubert const Unit *cup; /* .. */
48825796c8dcSSimon Schubert Unit *up; /* .. */
48835796c8dcSSimon Schubert uLong *lp; /* .. */
48845796c8dcSSimon Schubert Int p; /* .. */
48855796c8dcSSimon Schubert #endif
48865796c8dcSSimon Schubert
48875796c8dcSSimon Schubert #if DECSUBSET
48885796c8dcSSimon Schubert decNumber *alloclhs=NULL; /* -> allocated buffer, iff allocated */
48895796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* -> allocated buffer, iff allocated */
48905796c8dcSSimon Schubert #endif
48915796c8dcSSimon Schubert
48925796c8dcSSimon Schubert #if DECCHECK
48935796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
48945796c8dcSSimon Schubert #endif
48955796c8dcSSimon Schubert
48965796c8dcSSimon Schubert /* precalculate result sign */
48975796c8dcSSimon Schubert bits=(uByte)((lhs->bits^rhs->bits)&DECNEG);
48985796c8dcSSimon Schubert
48995796c8dcSSimon Schubert /* handle infinities and NaNs */
49005796c8dcSSimon Schubert if (SPECIALARGS) { /* a special bit set */
49015796c8dcSSimon Schubert if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
49025796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, status);
49035796c8dcSSimon Schubert return res;}
49045796c8dcSSimon Schubert /* one or two infinities; Infinity * 0 is invalid */
49055796c8dcSSimon Schubert if (((lhs->bits & DECINF)==0 && ISZERO(lhs))
49065796c8dcSSimon Schubert ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) {
49075796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
49085796c8dcSSimon Schubert return res;}
49095796c8dcSSimon Schubert decNumberZero(res);
49105796c8dcSSimon Schubert res->bits=bits|DECINF; /* infinity */
49115796c8dcSSimon Schubert return res;}
49125796c8dcSSimon Schubert
49135796c8dcSSimon Schubert /* For best speed, as in DMSRCN [the original Rexx numerics */
49145796c8dcSSimon Schubert /* module], use the shorter number as the multiplier (rhs) and */
49155796c8dcSSimon Schubert /* the longer as the multiplicand (lhs) to minimise the number of */
49165796c8dcSSimon Schubert /* adds (partial products) */
49175796c8dcSSimon Schubert if (lhs->digits<rhs->digits) { /* swap... */
49185796c8dcSSimon Schubert const decNumber *hold=lhs;
49195796c8dcSSimon Schubert lhs=rhs;
49205796c8dcSSimon Schubert rhs=hold;
49215796c8dcSSimon Schubert }
49225796c8dcSSimon Schubert
49235796c8dcSSimon Schubert do { /* protect allocated storage */
49245796c8dcSSimon Schubert #if DECSUBSET
49255796c8dcSSimon Schubert if (!set->extended) {
49265796c8dcSSimon Schubert /* reduce operands and set lostDigits status, as needed */
49275796c8dcSSimon Schubert if (lhs->digits>set->digits) {
49285796c8dcSSimon Schubert alloclhs=decRoundOperand(lhs, set, status);
49295796c8dcSSimon Schubert if (alloclhs==NULL) break;
49305796c8dcSSimon Schubert lhs=alloclhs;
49315796c8dcSSimon Schubert }
49325796c8dcSSimon Schubert if (rhs->digits>set->digits) {
49335796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, status);
49345796c8dcSSimon Schubert if (allocrhs==NULL) break;
49355796c8dcSSimon Schubert rhs=allocrhs;
49365796c8dcSSimon Schubert }
49375796c8dcSSimon Schubert }
49385796c8dcSSimon Schubert #endif
49395796c8dcSSimon Schubert /* [following code does not require input rounding] */
49405796c8dcSSimon Schubert
49415796c8dcSSimon Schubert #if FASTMUL /* fastpath can be used */
49425796c8dcSSimon Schubert /* use the fast path if there are enough digits in the shorter */
49435796c8dcSSimon Schubert /* operand to make the setup and takedown worthwhile */
49445796c8dcSSimon Schubert #define NEEDTWO (DECDPUN*2) /* within two decUnitAddSub calls */
49455796c8dcSSimon Schubert if (rhs->digits>NEEDTWO) { /* use fastpath... */
49465796c8dcSSimon Schubert /* calculate the number of elements in each array */
49475796c8dcSSimon Schubert ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */
49485796c8dcSSimon Schubert irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */
49495796c8dcSSimon Schubert iacc=ilhs+irhs;
49505796c8dcSSimon Schubert
49515796c8dcSSimon Schubert /* allocate buffers if required, as usual */
49525796c8dcSSimon Schubert needbytes=ilhs*sizeof(uInt);
49535796c8dcSSimon Schubert if (needbytes>(Int)sizeof(zlhibuff)) {
49545796c8dcSSimon Schubert alloclhi=(uInt *)malloc(needbytes);
49555796c8dcSSimon Schubert zlhi=alloclhi;}
49565796c8dcSSimon Schubert needbytes=irhs*sizeof(uInt);
49575796c8dcSSimon Schubert if (needbytes>(Int)sizeof(zrhibuff)) {
49585796c8dcSSimon Schubert allocrhi=(uInt *)malloc(needbytes);
49595796c8dcSSimon Schubert zrhi=allocrhi;}
49605796c8dcSSimon Schubert
49615796c8dcSSimon Schubert /* Allocating the accumulator space needs a special case when */
49625796c8dcSSimon Schubert /* DECDPUN=1 because when converting the accumulator to Units */
49635796c8dcSSimon Schubert /* after the multiplication each 8-byte item becomes 9 1-byte */
49645796c8dcSSimon Schubert /* units. Therefore iacc extra bytes are needed at the front */
49655796c8dcSSimon Schubert /* (rounded up to a multiple of 8 bytes), and the uLong */
49665796c8dcSSimon Schubert /* accumulator starts offset the appropriate number of units */
49675796c8dcSSimon Schubert /* to the right to avoid overwrite during the unchunking. */
49685796c8dcSSimon Schubert needbytes=iacc*sizeof(uLong);
49695796c8dcSSimon Schubert #if DECDPUN==1
49705796c8dcSSimon Schubert zoff=(iacc+7)/8; /* items to offset by */
49715796c8dcSSimon Schubert needbytes+=zoff*8;
49725796c8dcSSimon Schubert #endif
49735796c8dcSSimon Schubert if (needbytes>(Int)sizeof(zaccbuff)) {
49745796c8dcSSimon Schubert allocacc=(uLong *)malloc(needbytes);
49755796c8dcSSimon Schubert zacc=(uLong *)allocacc;}
49765796c8dcSSimon Schubert if (zlhi==NULL||zrhi==NULL||zacc==NULL) {
49775796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
49785796c8dcSSimon Schubert break;}
49795796c8dcSSimon Schubert
49805796c8dcSSimon Schubert acc=(Unit *)zacc; /* -> target Unit array */
49815796c8dcSSimon Schubert #if DECDPUN==1
49825796c8dcSSimon Schubert zacc+=zoff; /* start uLong accumulator to right */
49835796c8dcSSimon Schubert #endif
49845796c8dcSSimon Schubert
49855796c8dcSSimon Schubert /* assemble the chunked copies of the left and right sides */
49865796c8dcSSimon Schubert for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++)
49875796c8dcSSimon Schubert for (p=0, *lip=0; p<FASTDIGS && count>0;
49885796c8dcSSimon Schubert p+=DECDPUN, cup++, count-=DECDPUN)
49895796c8dcSSimon Schubert *lip+=*cup*powers[p];
49905796c8dcSSimon Schubert lmsi=lip-1; /* save -> msi */
49915796c8dcSSimon Schubert for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++)
49925796c8dcSSimon Schubert for (p=0, *rip=0; p<FASTDIGS && count>0;
49935796c8dcSSimon Schubert p+=DECDPUN, cup++, count-=DECDPUN)
49945796c8dcSSimon Schubert *rip+=*cup*powers[p];
49955796c8dcSSimon Schubert rmsi=rip-1; /* save -> msi */
49965796c8dcSSimon Schubert
49975796c8dcSSimon Schubert /* zero the accumulator */
49985796c8dcSSimon Schubert for (lp=zacc; lp<zacc+iacc; lp++) *lp=0;
49995796c8dcSSimon Schubert
50005796c8dcSSimon Schubert /* Start the multiplication */
50015796c8dcSSimon Schubert /* Resolving carries can dominate the cost of accumulating the */
50025796c8dcSSimon Schubert /* partial products, so this is only done when necessary. */
50035796c8dcSSimon Schubert /* Each uLong item in the accumulator can hold values up to */
50045796c8dcSSimon Schubert /* 2**64-1, and each partial product can be as large as */
50055796c8dcSSimon Schubert /* (10**FASTDIGS-1)**2. When FASTDIGS=9, this can be added to */
50065796c8dcSSimon Schubert /* itself 18.4 times in a uLong without overflowing, so during */
50075796c8dcSSimon Schubert /* the main calculation resolution is carried out every 18th */
50085796c8dcSSimon Schubert /* add -- every 162 digits. Similarly, when FASTDIGS=8, the */
50095796c8dcSSimon Schubert /* partial products can be added to themselves 1844.6 times in */
50105796c8dcSSimon Schubert /* a uLong without overflowing, so intermediate carry */
50115796c8dcSSimon Schubert /* resolution occurs only every 14752 digits. Hence for common */
50125796c8dcSSimon Schubert /* short numbers usually only the one final carry resolution */
50135796c8dcSSimon Schubert /* occurs. */
50145796c8dcSSimon Schubert /* (The count is set via FASTLAZY to simplify experiments to */
50155796c8dcSSimon Schubert /* measure the value of this approach: a 35% improvement on a */
50165796c8dcSSimon Schubert /* [34x34] multiply.) */
50175796c8dcSSimon Schubert lazy=FASTLAZY; /* carry delay count */
50185796c8dcSSimon Schubert for (rip=zrhi; rip<=rmsi; rip++) { /* over each item in rhs */
50195796c8dcSSimon Schubert lp=zacc+(rip-zrhi); /* where to add the lhs */
50205796c8dcSSimon Schubert for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */
50215796c8dcSSimon Schubert *lp+=(uLong)(*lip)*(*rip); /* [this should in-line] */
50225796c8dcSSimon Schubert } /* lip loop */
50235796c8dcSSimon Schubert lazy--;
50245796c8dcSSimon Schubert if (lazy>0 && rip!=rmsi) continue;
50255796c8dcSSimon Schubert lazy=FASTLAZY; /* reset delay count */
50265796c8dcSSimon Schubert /* spin up the accumulator resolving overflows */
50275796c8dcSSimon Schubert for (lp=zacc; lp<zacc+iacc; lp++) {
50285796c8dcSSimon Schubert if (*lp<FASTBASE) continue; /* it fits */
50295796c8dcSSimon Schubert lcarry=*lp/FASTBASE; /* top part [slow divide] */
50305796c8dcSSimon Schubert /* lcarry can exceed 2**32-1, so check again; this check */
50315796c8dcSSimon Schubert /* and occasional extra divide (slow) is well worth it, as */
50325796c8dcSSimon Schubert /* it allows FASTLAZY to be increased to 18 rather than 4 */
50335796c8dcSSimon Schubert /* in the FASTDIGS=9 case */
50345796c8dcSSimon Schubert if (lcarry<FASTBASE) carry=(uInt)lcarry; /* [usual] */
50355796c8dcSSimon Schubert else { /* two-place carry [fairly rare] */
50365796c8dcSSimon Schubert uInt carry2=(uInt)(lcarry/FASTBASE); /* top top part */
50375796c8dcSSimon Schubert *(lp+2)+=carry2; /* add to item+2 */
50385796c8dcSSimon Schubert *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */
50395796c8dcSSimon Schubert carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */
50405796c8dcSSimon Schubert }
50415796c8dcSSimon Schubert *(lp+1)+=carry; /* add to item above [inline] */
50425796c8dcSSimon Schubert *lp-=((uLong)FASTBASE*carry); /* [inline] */
50435796c8dcSSimon Schubert } /* carry resolution */
50445796c8dcSSimon Schubert } /* rip loop */
50455796c8dcSSimon Schubert
50465796c8dcSSimon Schubert /* The multiplication is complete; time to convert back into */
50475796c8dcSSimon Schubert /* units. This can be done in-place in the accumulator and in */
50485796c8dcSSimon Schubert /* 32-bit operations, because carries were resolved after the */
50495796c8dcSSimon Schubert /* final add. This needs N-1 divides and multiplies for */
50505796c8dcSSimon Schubert /* each item in the accumulator (which will become up to N */
50515796c8dcSSimon Schubert /* units, where 2<=N<=9). */
50525796c8dcSSimon Schubert for (lp=zacc, up=acc; lp<zacc+iacc; lp++) {
50535796c8dcSSimon Schubert uInt item=(uInt)*lp; /* decapitate to uInt */
50545796c8dcSSimon Schubert for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) {
50555796c8dcSSimon Schubert uInt part=item/(DECDPUNMAX+1);
50565796c8dcSSimon Schubert *up=(Unit)(item-(part*(DECDPUNMAX+1)));
50575796c8dcSSimon Schubert item=part;
50585796c8dcSSimon Schubert } /* p */
50595796c8dcSSimon Schubert *up=(Unit)item; up++; /* [final needs no division] */
50605796c8dcSSimon Schubert } /* lp */
50615796c8dcSSimon Schubert accunits=up-acc; /* count of units */
50625796c8dcSSimon Schubert }
50635796c8dcSSimon Schubert else { /* here to use units directly, without chunking ['old code'] */
50645796c8dcSSimon Schubert #endif
50655796c8dcSSimon Schubert
50665796c8dcSSimon Schubert /* if accumulator will be too long for local storage, then allocate */
50675796c8dcSSimon Schubert acc=accbuff; /* -> assume buffer for accumulator */
50685796c8dcSSimon Schubert needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit);
50695796c8dcSSimon Schubert if (needbytes>(Int)sizeof(accbuff)) {
50705796c8dcSSimon Schubert allocacc=(Unit *)malloc(needbytes);
50715796c8dcSSimon Schubert if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;}
50725796c8dcSSimon Schubert acc=(Unit *)allocacc; /* use the allocated space */
50735796c8dcSSimon Schubert }
50745796c8dcSSimon Schubert
50755796c8dcSSimon Schubert /* Now the main long multiplication loop */
50765796c8dcSSimon Schubert /* Unlike the equivalent in the IBM Java implementation, there */
50775796c8dcSSimon Schubert /* is no advantage in calculating from msu to lsu. So, do it */
50785796c8dcSSimon Schubert /* by the book, as it were. */
50795796c8dcSSimon Schubert /* Each iteration calculates ACC=ACC+MULTAND*MULT */
50805796c8dcSSimon Schubert accunits=1; /* accumulator starts at '0' */
50815796c8dcSSimon Schubert *acc=0; /* .. (lsu=0) */
50825796c8dcSSimon Schubert shift=0; /* no multiplicand shift at first */
50835796c8dcSSimon Schubert madlength=D2U(lhs->digits); /* this won't change */
50845796c8dcSSimon Schubert mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */
50855796c8dcSSimon Schubert
50865796c8dcSSimon Schubert for (mer=rhs->lsu; mer<mermsup; mer++) {
50875796c8dcSSimon Schubert /* Here, *mer is the next Unit in the multiplier to use */
50885796c8dcSSimon Schubert /* If non-zero [optimization] add it... */
50895796c8dcSSimon Schubert if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift,
50905796c8dcSSimon Schubert lhs->lsu, madlength, 0,
50915796c8dcSSimon Schubert &acc[shift], *mer)
50925796c8dcSSimon Schubert + shift;
50935796c8dcSSimon Schubert else { /* extend acc with a 0; it will be used shortly */
50945796c8dcSSimon Schubert *(acc+accunits)=0; /* [this avoids length of <=0 later] */
50955796c8dcSSimon Schubert accunits++;
50965796c8dcSSimon Schubert }
50975796c8dcSSimon Schubert /* multiply multiplicand by 10**DECDPUN for next Unit to left */
50985796c8dcSSimon Schubert shift++; /* add this for 'logical length' */
50995796c8dcSSimon Schubert } /* n */
51005796c8dcSSimon Schubert #if FASTMUL
51015796c8dcSSimon Schubert } /* unchunked units */
51025796c8dcSSimon Schubert #endif
51035796c8dcSSimon Schubert /* common end-path */
51045796c8dcSSimon Schubert #if DECTRACE
51055796c8dcSSimon Schubert decDumpAr('*', acc, accunits); /* Show exact result */
51065796c8dcSSimon Schubert #endif
51075796c8dcSSimon Schubert
51085796c8dcSSimon Schubert /* acc now contains the exact result of the multiplication, */
51095796c8dcSSimon Schubert /* possibly with a leading zero unit; build the decNumber from */
51105796c8dcSSimon Schubert /* it, noting if any residue */
51115796c8dcSSimon Schubert res->bits=bits; /* set sign */
51125796c8dcSSimon Schubert res->digits=decGetDigits(acc, accunits); /* count digits exactly */
51135796c8dcSSimon Schubert
51145796c8dcSSimon Schubert /* There can be a 31-bit wrap in calculating the exponent. */
51155796c8dcSSimon Schubert /* This can only happen if both input exponents are negative and */
51165796c8dcSSimon Schubert /* both their magnitudes are large. If there was a wrap, set a */
51175796c8dcSSimon Schubert /* safe very negative exponent, from which decFinalize() will */
51185796c8dcSSimon Schubert /* raise a hard underflow shortly. */
51195796c8dcSSimon Schubert exponent=lhs->exponent+rhs->exponent; /* calculate exponent */
51205796c8dcSSimon Schubert if (lhs->exponent<0 && rhs->exponent<0 && exponent>0)
51215796c8dcSSimon Schubert exponent=-2*DECNUMMAXE; /* force underflow */
51225796c8dcSSimon Schubert res->exponent=exponent; /* OK to overwrite now */
51235796c8dcSSimon Schubert
51245796c8dcSSimon Schubert
51255796c8dcSSimon Schubert /* Set the coefficient. If any rounding, residue records */
51265796c8dcSSimon Schubert decSetCoeff(res, set, acc, res->digits, &residue, status);
51275796c8dcSSimon Schubert decFinish(res, set, &residue, status); /* final cleanup */
51285796c8dcSSimon Schubert } while(0); /* end protected */
51295796c8dcSSimon Schubert
5130a45ae5f8SJohn Marino free(allocacc); /* drop any storage used */
51315796c8dcSSimon Schubert #if DECSUBSET
5132a45ae5f8SJohn Marino free(allocrhs); /* .. */
5133a45ae5f8SJohn Marino free(alloclhs); /* .. */
51345796c8dcSSimon Schubert #endif
51355796c8dcSSimon Schubert #if FASTMUL
5136a45ae5f8SJohn Marino free(allocrhi); /* .. */
5137a45ae5f8SJohn Marino free(alloclhi); /* .. */
51385796c8dcSSimon Schubert #endif
51395796c8dcSSimon Schubert return res;
51405796c8dcSSimon Schubert } /* decMultiplyOp */
51415796c8dcSSimon Schubert
51425796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
51435796c8dcSSimon Schubert /* decExpOp -- effect exponentiation */
51445796c8dcSSimon Schubert /* */
51455796c8dcSSimon Schubert /* This computes C = exp(A) */
51465796c8dcSSimon Schubert /* */
51475796c8dcSSimon Schubert /* res is C, the result. C may be A */
51485796c8dcSSimon Schubert /* rhs is A */
51495796c8dcSSimon Schubert /* set is the context; note that rounding mode has no effect */
51505796c8dcSSimon Schubert /* */
51515796c8dcSSimon Schubert /* C must have space for set->digits digits. status is updated but */
51525796c8dcSSimon Schubert /* not set. */
51535796c8dcSSimon Schubert /* */
51545796c8dcSSimon Schubert /* Restrictions: */
51555796c8dcSSimon Schubert /* */
51565796c8dcSSimon Schubert /* digits, emax, and -emin in the context must be less than */
51575796c8dcSSimon Schubert /* 2*DEC_MAX_MATH (1999998), and the rhs must be within these */
51585796c8dcSSimon Schubert /* bounds or a zero. This is an internal routine, so these */
51595796c8dcSSimon Schubert /* restrictions are contractual and not enforced. */
51605796c8dcSSimon Schubert /* */
51615796c8dcSSimon Schubert /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */
51625796c8dcSSimon Schubert /* almost always be correctly rounded, but may be up to 1 ulp in */
51635796c8dcSSimon Schubert /* error in rare cases. */
51645796c8dcSSimon Schubert /* */
51655796c8dcSSimon Schubert /* Finite results will always be full precision and Inexact, except */
51665796c8dcSSimon Schubert /* when A is a zero or -Infinity (giving 1 or 0 respectively). */
51675796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
51685796c8dcSSimon Schubert /* This approach used here is similar to the algorithm described in */
51695796c8dcSSimon Schubert /* */
51705796c8dcSSimon Schubert /* Variable Precision Exponential Function, T. E. Hull and */
51715796c8dcSSimon Schubert /* A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */
51725796c8dcSSimon Schubert /* pp79-91, ACM, June 1986. */
51735796c8dcSSimon Schubert /* */
51745796c8dcSSimon Schubert /* with the main difference being that the iterations in the series */
51755796c8dcSSimon Schubert /* evaluation are terminated dynamically (which does not require the */
51765796c8dcSSimon Schubert /* extra variable-precision variables which are expensive in this */
51775796c8dcSSimon Schubert /* context). */
51785796c8dcSSimon Schubert /* */
51795796c8dcSSimon Schubert /* The error analysis in Hull & Abrham's paper applies except for the */
51805796c8dcSSimon Schubert /* round-off error accumulation during the series evaluation. This */
51815796c8dcSSimon Schubert /* code does not precalculate the number of iterations and so cannot */
51825796c8dcSSimon Schubert /* use Horner's scheme. Instead, the accumulation is done at double- */
51835796c8dcSSimon Schubert /* precision, which ensures that the additions of the terms are exact */
51845796c8dcSSimon Schubert /* and do not accumulate round-off (and any round-off errors in the */
51855796c8dcSSimon Schubert /* terms themselves move 'to the right' faster than they can */
51865796c8dcSSimon Schubert /* accumulate). This code also extends the calculation by allowing, */
51875796c8dcSSimon Schubert /* in the spirit of other decNumber operators, the input to be more */
51885796c8dcSSimon Schubert /* precise than the result (the precision used is based on the more */
51895796c8dcSSimon Schubert /* precise of the input or requested result). */
51905796c8dcSSimon Schubert /* */
51915796c8dcSSimon Schubert /* Implementation notes: */
51925796c8dcSSimon Schubert /* */
51935796c8dcSSimon Schubert /* 1. This is separated out as decExpOp so it can be called from */
51945796c8dcSSimon Schubert /* other Mathematical functions (notably Ln) with a wider range */
51955796c8dcSSimon Schubert /* than normal. In particular, it can handle the slightly wider */
51965796c8dcSSimon Schubert /* (double) range needed by Ln (which has to be able to calculate */
51975796c8dcSSimon Schubert /* exp(-x) where x can be the tiniest number (Ntiny). */
51985796c8dcSSimon Schubert /* */
51995796c8dcSSimon Schubert /* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop */
52005796c8dcSSimon Schubert /* iterations by appoximately a third with additional (although */
52015796c8dcSSimon Schubert /* diminishing) returns as the range is reduced to even smaller */
52025796c8dcSSimon Schubert /* fractions. However, h (the power of 10 used to correct the */
52035796c8dcSSimon Schubert /* result at the end, see below) must be kept <=8 as otherwise */
52045796c8dcSSimon Schubert /* the final result cannot be computed. Hence the leverage is a */
52055796c8dcSSimon Schubert /* sliding value (8-h), where potentially the range is reduced */
52065796c8dcSSimon Schubert /* more for smaller values. */
52075796c8dcSSimon Schubert /* */
52085796c8dcSSimon Schubert /* The leverage that can be applied in this way is severely */
52095796c8dcSSimon Schubert /* limited by the cost of the raise-to-the power at the end, */
52105796c8dcSSimon Schubert /* which dominates when the number of iterations is small (less */
52115796c8dcSSimon Schubert /* than ten) or when rhs is short. As an example, the adjustment */
52125796c8dcSSimon Schubert /* x**10,000,000 needs 31 multiplications, all but one full-width. */
52135796c8dcSSimon Schubert /* */
52145796c8dcSSimon Schubert /* 3. The restrictions (especially precision) could be raised with */
52155796c8dcSSimon Schubert /* care, but the full decNumber range seems very hard within the */
52165796c8dcSSimon Schubert /* 32-bit limits. */
52175796c8dcSSimon Schubert /* */
52185796c8dcSSimon Schubert /* 4. The working precisions for the static buffers are twice the */
52195796c8dcSSimon Schubert /* obvious size to allow for calls from decNumberPower. */
52205796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decExpOp(decNumber * res,const decNumber * rhs,decContext * set,uInt * status)52215796c8dcSSimon Schubert decNumber * decExpOp(decNumber *res, const decNumber *rhs,
52225796c8dcSSimon Schubert decContext *set, uInt *status) {
52235796c8dcSSimon Schubert uInt ignore=0; /* working status */
52245796c8dcSSimon Schubert Int h; /* adjusted exponent for 0.xxxx */
52255796c8dcSSimon Schubert Int p; /* working precision */
52265796c8dcSSimon Schubert Int residue; /* rounding residue */
52275796c8dcSSimon Schubert uInt needbytes; /* for space calculations */
52285796c8dcSSimon Schubert const decNumber *x=rhs; /* (may point to safe copy later) */
52295796c8dcSSimon Schubert decContext aset, tset, dset; /* working contexts */
52305796c8dcSSimon Schubert Int comp; /* work */
52315796c8dcSSimon Schubert
52325796c8dcSSimon Schubert /* the argument is often copied to normalize it, so (unusually) it */
52335796c8dcSSimon Schubert /* is treated like other buffers, using DECBUFFER, +1 in case */
52345796c8dcSSimon Schubert /* DECBUFFER is 0 */
52355796c8dcSSimon Schubert decNumber bufr[D2N(DECBUFFER*2+1)];
52365796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* non-NULL if rhs buffer allocated */
52375796c8dcSSimon Schubert
52385796c8dcSSimon Schubert /* the working precision will be no more than set->digits+8+1 */
52395796c8dcSSimon Schubert /* so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER */
52405796c8dcSSimon Schubert /* is 0 (and twice that for the accumulator) */
52415796c8dcSSimon Schubert
52425796c8dcSSimon Schubert /* buffer for t, term (working precision plus) */
52435796c8dcSSimon Schubert decNumber buft[D2N(DECBUFFER*2+9+1)];
52445796c8dcSSimon Schubert decNumber *allocbuft=NULL; /* -> allocated buft, iff allocated */
52455796c8dcSSimon Schubert decNumber *t=buft; /* term */
52465796c8dcSSimon Schubert /* buffer for a, accumulator (working precision * 2), at least 9 */
52475796c8dcSSimon Schubert decNumber bufa[D2N(DECBUFFER*4+18+1)];
52485796c8dcSSimon Schubert decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
52495796c8dcSSimon Schubert decNumber *a=bufa; /* accumulator */
52505796c8dcSSimon Schubert /* decNumber for the divisor term; this needs at most 9 digits */
52515796c8dcSSimon Schubert /* and so can be fixed size [16 so can use standard context] */
52525796c8dcSSimon Schubert decNumber bufd[D2N(16)];
52535796c8dcSSimon Schubert decNumber *d=bufd; /* divisor */
52545796c8dcSSimon Schubert decNumber numone; /* constant 1 */
52555796c8dcSSimon Schubert
52565796c8dcSSimon Schubert #if DECCHECK
52575796c8dcSSimon Schubert Int iterations=0; /* for later sanity check */
52585796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
52595796c8dcSSimon Schubert #endif
52605796c8dcSSimon Schubert
52615796c8dcSSimon Schubert do { /* protect allocated storage */
52625796c8dcSSimon Schubert if (SPECIALARG) { /* handle infinities and NaNs */
52635796c8dcSSimon Schubert if (decNumberIsInfinite(rhs)) { /* an infinity */
52645796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) /* -Infinity -> +0 */
52655796c8dcSSimon Schubert decNumberZero(res);
52665796c8dcSSimon Schubert else decNumberCopy(res, rhs); /* +Infinity -> self */
52675796c8dcSSimon Schubert }
52685796c8dcSSimon Schubert else decNaNs(res, rhs, NULL, set, status); /* a NaN */
52695796c8dcSSimon Schubert break;}
52705796c8dcSSimon Schubert
52715796c8dcSSimon Schubert if (ISZERO(rhs)) { /* zeros -> exact 1 */
52725796c8dcSSimon Schubert decNumberZero(res); /* make clean 1 */
52735796c8dcSSimon Schubert *res->lsu=1; /* .. */
52745796c8dcSSimon Schubert break;} /* [no status to set] */
52755796c8dcSSimon Schubert
52765796c8dcSSimon Schubert /* e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path */
52775796c8dcSSimon Schubert /* positive and negative tiny cases which will result in inexact */
52785796c8dcSSimon Schubert /* 1. This also allows the later add-accumulate to always be */
52795796c8dcSSimon Schubert /* exact (because its length will never be more than twice the */
52805796c8dcSSimon Schubert /* working precision). */
52815796c8dcSSimon Schubert /* The comparator (tiny) needs just one digit, so use the */
52825796c8dcSSimon Schubert /* decNumber d for it (reused as the divisor, etc., below); its */
52835796c8dcSSimon Schubert /* exponent is such that if x is positive it will have */
52845796c8dcSSimon Schubert /* set->digits-1 zeros between the decimal point and the digit, */
52855796c8dcSSimon Schubert /* which is 4, and if x is negative one more zero there as the */
52865796c8dcSSimon Schubert /* more precise result will be of the form 0.9999999 rather than */
52875796c8dcSSimon Schubert /* 1.0000001. Hence, tiny will be 0.0000004 if digits=7 and x>0 */
52885796c8dcSSimon Schubert /* or 0.00000004 if digits=7 and x<0. If RHS not larger than */
52895796c8dcSSimon Schubert /* this then the result will be 1.000000 */
52905796c8dcSSimon Schubert decNumberZero(d); /* clean */
52915796c8dcSSimon Schubert *d->lsu=4; /* set 4 .. */
52925796c8dcSSimon Schubert d->exponent=-set->digits; /* * 10**(-d) */
52935796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) d->exponent--; /* negative case */
52945796c8dcSSimon Schubert comp=decCompare(d, rhs, 1); /* signless compare */
52955796c8dcSSimon Schubert if (comp==BADINT) {
52965796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
52975796c8dcSSimon Schubert break;}
52985796c8dcSSimon Schubert if (comp>=0) { /* rhs < d */
52995796c8dcSSimon Schubert Int shift=set->digits-1;
53005796c8dcSSimon Schubert decNumberZero(res); /* set 1 */
53015796c8dcSSimon Schubert *res->lsu=1; /* .. */
53025796c8dcSSimon Schubert res->digits=decShiftToMost(res->lsu, 1, shift);
53035796c8dcSSimon Schubert res->exponent=-shift; /* make 1.0000... */
53045796c8dcSSimon Schubert *status|=DEC_Inexact | DEC_Rounded; /* .. inexactly */
53055796c8dcSSimon Schubert break;} /* tiny */
53065796c8dcSSimon Schubert
53075796c8dcSSimon Schubert /* set up the context to be used for calculating a, as this is */
53085796c8dcSSimon Schubert /* used on both paths below */
53095796c8dcSSimon Schubert decContextDefault(&aset, DEC_INIT_DECIMAL64);
53105796c8dcSSimon Schubert /* accumulator bounds are as requested (could underflow) */
53115796c8dcSSimon Schubert aset.emax=set->emax; /* usual bounds */
53125796c8dcSSimon Schubert aset.emin=set->emin; /* .. */
53135796c8dcSSimon Schubert aset.clamp=0; /* and no concrete format */
53145796c8dcSSimon Schubert
53155796c8dcSSimon Schubert /* calculate the adjusted (Hull & Abrham) exponent (where the */
53165796c8dcSSimon Schubert /* decimal point is just to the left of the coefficient msd) */
53175796c8dcSSimon Schubert h=rhs->exponent+rhs->digits;
53185796c8dcSSimon Schubert /* if h>8 then 10**h cannot be calculated safely; however, when */
53195796c8dcSSimon Schubert /* h=8 then exp(|rhs|) will be at least exp(1E+7) which is at */
53205796c8dcSSimon Schubert /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */
53215796c8dcSSimon Schubert /* overflow (or underflow to 0) is guaranteed -- so this case can */
53225796c8dcSSimon Schubert /* be handled by simply forcing the appropriate excess */
53235796c8dcSSimon Schubert if (h>8) { /* overflow/underflow */
53245796c8dcSSimon Schubert /* set up here so Power call below will over or underflow to */
53255796c8dcSSimon Schubert /* zero; set accumulator to either 2 or 0.02 */
53265796c8dcSSimon Schubert /* [stack buffer for a is always big enough for this] */
53275796c8dcSSimon Schubert decNumberZero(a);
53285796c8dcSSimon Schubert *a->lsu=2; /* not 1 but < exp(1) */
53295796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */
53305796c8dcSSimon Schubert h=8; /* clamp so 10**h computable */
53315796c8dcSSimon Schubert p=9; /* set a working precision */
53325796c8dcSSimon Schubert }
53335796c8dcSSimon Schubert else { /* h<=8 */
53345796c8dcSSimon Schubert Int maxlever=(rhs->digits>8?1:0);
53355796c8dcSSimon Schubert /* [could/should increase this for precisions >40 or so, too] */
53365796c8dcSSimon Schubert
53375796c8dcSSimon Schubert /* if h is 8, cannot normalize to a lower upper limit because */
53385796c8dcSSimon Schubert /* the final result will not be computable (see notes above), */
53395796c8dcSSimon Schubert /* but leverage can be applied whenever h is less than 8. */
53405796c8dcSSimon Schubert /* Apply as much as possible, up to a MAXLEVER digits, which */
53415796c8dcSSimon Schubert /* sets the tradeoff against the cost of the later a**(10**h). */
53425796c8dcSSimon Schubert /* As h is increased, the working precision below also */
53435796c8dcSSimon Schubert /* increases to compensate for the "constant digits at the */
53445796c8dcSSimon Schubert /* front" effect. */
53455796c8dcSSimon Schubert Int lever=MINI(8-h, maxlever); /* leverage attainable */
53465796c8dcSSimon Schubert Int use=-rhs->digits-lever; /* exponent to use for RHS */
53475796c8dcSSimon Schubert h+=lever; /* apply leverage selected */
53485796c8dcSSimon Schubert if (h<0) { /* clamp */
53495796c8dcSSimon Schubert use+=h; /* [may end up subnormal] */
53505796c8dcSSimon Schubert h=0;
53515796c8dcSSimon Schubert }
53525796c8dcSSimon Schubert /* Take a copy of RHS if it needs normalization (true whenever x>=1) */
53535796c8dcSSimon Schubert if (rhs->exponent!=use) {
53545796c8dcSSimon Schubert decNumber *newrhs=bufr; /* assume will fit on stack */
53555796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
53565796c8dcSSimon Schubert if (needbytes>sizeof(bufr)) { /* need malloc space */
53575796c8dcSSimon Schubert allocrhs=(decNumber *)malloc(needbytes);
53585796c8dcSSimon Schubert if (allocrhs==NULL) { /* hopeless -- abandon */
53595796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
53605796c8dcSSimon Schubert break;}
53615796c8dcSSimon Schubert newrhs=allocrhs; /* use the allocated space */
53625796c8dcSSimon Schubert }
53635796c8dcSSimon Schubert decNumberCopy(newrhs, rhs); /* copy to safe space */
53645796c8dcSSimon Schubert newrhs->exponent=use; /* normalize; now <1 */
53655796c8dcSSimon Schubert x=newrhs; /* ready for use */
53665796c8dcSSimon Schubert /* decNumberShow(x); */
53675796c8dcSSimon Schubert }
53685796c8dcSSimon Schubert
53695796c8dcSSimon Schubert /* Now use the usual power series to evaluate exp(x). The */
53705796c8dcSSimon Schubert /* series starts as 1 + x + x^2/2 ... so prime ready for the */
53715796c8dcSSimon Schubert /* third term by setting the term variable t=x, the accumulator */
53725796c8dcSSimon Schubert /* a=1, and the divisor d=2. */
53735796c8dcSSimon Schubert
53745796c8dcSSimon Schubert /* First determine the working precision. From Hull & Abrham */
53755796c8dcSSimon Schubert /* this is set->digits+h+2. However, if x is 'over-precise' we */
53765796c8dcSSimon Schubert /* need to allow for all its digits to potentially participate */
53775796c8dcSSimon Schubert /* (consider an x where all the excess digits are 9s) so in */
53785796c8dcSSimon Schubert /* this case use x->digits+h+2 */
53795796c8dcSSimon Schubert p=MAXI(x->digits, set->digits)+h+2; /* [h<=8] */
53805796c8dcSSimon Schubert
53815796c8dcSSimon Schubert /* a and t are variable precision, and depend on p, so space */
53825796c8dcSSimon Schubert /* must be allocated for them if necessary */
53835796c8dcSSimon Schubert
53845796c8dcSSimon Schubert /* the accumulator needs to be able to hold 2p digits so that */
53855796c8dcSSimon Schubert /* the additions on the second and subsequent iterations are */
53865796c8dcSSimon Schubert /* sufficiently exact. */
53875796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit);
53885796c8dcSSimon Schubert if (needbytes>sizeof(bufa)) { /* need malloc space */
53895796c8dcSSimon Schubert allocbufa=(decNumber *)malloc(needbytes);
53905796c8dcSSimon Schubert if (allocbufa==NULL) { /* hopeless -- abandon */
53915796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
53925796c8dcSSimon Schubert break;}
53935796c8dcSSimon Schubert a=allocbufa; /* use the allocated space */
53945796c8dcSSimon Schubert }
53955796c8dcSSimon Schubert /* the term needs to be able to hold p digits (which is */
53965796c8dcSSimon Schubert /* guaranteed to be larger than x->digits, so the initial copy */
53975796c8dcSSimon Schubert /* is safe); it may also be used for the raise-to-power */
53985796c8dcSSimon Schubert /* calculation below, which needs an extra two digits */
53995796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit);
54005796c8dcSSimon Schubert if (needbytes>sizeof(buft)) { /* need malloc space */
54015796c8dcSSimon Schubert allocbuft=(decNumber *)malloc(needbytes);
54025796c8dcSSimon Schubert if (allocbuft==NULL) { /* hopeless -- abandon */
54035796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
54045796c8dcSSimon Schubert break;}
54055796c8dcSSimon Schubert t=allocbuft; /* use the allocated space */
54065796c8dcSSimon Schubert }
54075796c8dcSSimon Schubert
54085796c8dcSSimon Schubert decNumberCopy(t, x); /* term=x */
54095796c8dcSSimon Schubert decNumberZero(a); *a->lsu=1; /* accumulator=1 */
54105796c8dcSSimon Schubert decNumberZero(d); *d->lsu=2; /* divisor=2 */
54115796c8dcSSimon Schubert decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */
54125796c8dcSSimon Schubert
54135796c8dcSSimon Schubert /* set up the contexts for calculating a, t, and d */
54145796c8dcSSimon Schubert decContextDefault(&tset, DEC_INIT_DECIMAL64);
54155796c8dcSSimon Schubert dset=tset;
54165796c8dcSSimon Schubert /* accumulator bounds are set above, set precision now */
54175796c8dcSSimon Schubert aset.digits=p*2; /* double */
54185796c8dcSSimon Schubert /* term bounds avoid any underflow or overflow */
54195796c8dcSSimon Schubert tset.digits=p;
54205796c8dcSSimon Schubert tset.emin=DEC_MIN_EMIN; /* [emax is plenty] */
54215796c8dcSSimon Schubert /* [dset.digits=16, etc., are sufficient] */
54225796c8dcSSimon Schubert
54235796c8dcSSimon Schubert /* finally ready to roll */
54245796c8dcSSimon Schubert for (;;) {
54255796c8dcSSimon Schubert #if DECCHECK
54265796c8dcSSimon Schubert iterations++;
54275796c8dcSSimon Schubert #endif
54285796c8dcSSimon Schubert /* only the status from the accumulation is interesting */
54295796c8dcSSimon Schubert /* [but it should remain unchanged after first add] */
54305796c8dcSSimon Schubert decAddOp(a, a, t, &aset, 0, status); /* a=a+t */
54315796c8dcSSimon Schubert decMultiplyOp(t, t, x, &tset, &ignore); /* t=t*x */
54325796c8dcSSimon Schubert decDivideOp(t, t, d, &tset, DIVIDE, &ignore); /* t=t/d */
54335796c8dcSSimon Schubert /* the iteration ends when the term cannot affect the result, */
54345796c8dcSSimon Schubert /* if rounded to p digits, which is when its value is smaller */
54355796c8dcSSimon Schubert /* than the accumulator by p+1 digits. There must also be */
54365796c8dcSSimon Schubert /* full precision in a. */
54375796c8dcSSimon Schubert if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1))
54385796c8dcSSimon Schubert && (a->digits>=p)) break;
54395796c8dcSSimon Schubert decAddOp(d, d, &numone, &dset, 0, &ignore); /* d=d+1 */
54405796c8dcSSimon Schubert } /* iterate */
54415796c8dcSSimon Schubert
54425796c8dcSSimon Schubert #if DECCHECK
54435796c8dcSSimon Schubert /* just a sanity check; comment out test to show always */
54445796c8dcSSimon Schubert if (iterations>p+3)
54455796c8dcSSimon Schubert printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
54465796c8dcSSimon Schubert (LI)iterations, (LI)*status, (LI)p, (LI)x->digits);
54475796c8dcSSimon Schubert #endif
54485796c8dcSSimon Schubert } /* h<=8 */
54495796c8dcSSimon Schubert
54505796c8dcSSimon Schubert /* apply postconditioning: a=a**(10**h) -- this is calculated */
54515796c8dcSSimon Schubert /* at a slightly higher precision than Hull & Abrham suggest */
54525796c8dcSSimon Schubert if (h>0) {
54535796c8dcSSimon Schubert Int seenbit=0; /* set once a 1-bit is seen */
54545796c8dcSSimon Schubert Int i; /* counter */
54555796c8dcSSimon Schubert Int n=powers[h]; /* always positive */
54565796c8dcSSimon Schubert aset.digits=p+2; /* sufficient precision */
54575796c8dcSSimon Schubert /* avoid the overhead and many extra digits of decNumberPower */
54585796c8dcSSimon Schubert /* as all that is needed is the short 'multipliers' loop; here */
54595796c8dcSSimon Schubert /* accumulate the answer into t */
54605796c8dcSSimon Schubert decNumberZero(t); *t->lsu=1; /* acc=1 */
54615796c8dcSSimon Schubert for (i=1;;i++){ /* for each bit [top bit ignored] */
54625796c8dcSSimon Schubert /* abandon if have had overflow or terminal underflow */
54635796c8dcSSimon Schubert if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
54645796c8dcSSimon Schubert if (*status&DEC_Overflow || ISZERO(t)) break;}
54655796c8dcSSimon Schubert n=n<<1; /* move next bit to testable position */
54665796c8dcSSimon Schubert if (n<0) { /* top bit is set */
54675796c8dcSSimon Schubert seenbit=1; /* OK, have a significant bit */
54685796c8dcSSimon Schubert decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */
54695796c8dcSSimon Schubert }
54705796c8dcSSimon Schubert if (i==31) break; /* that was the last bit */
54715796c8dcSSimon Schubert if (!seenbit) continue; /* no need to square 1 */
54725796c8dcSSimon Schubert decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */
54735796c8dcSSimon Schubert } /*i*/ /* 32 bits */
54745796c8dcSSimon Schubert /* decNumberShow(t); */
54755796c8dcSSimon Schubert a=t; /* and carry on using t instead of a */
54765796c8dcSSimon Schubert }
54775796c8dcSSimon Schubert
54785796c8dcSSimon Schubert /* Copy and round the result to res */
54795796c8dcSSimon Schubert residue=1; /* indicate dirt to right .. */
54805796c8dcSSimon Schubert if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */
54815796c8dcSSimon Schubert aset.digits=set->digits; /* [use default rounding] */
54825796c8dcSSimon Schubert decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
54835796c8dcSSimon Schubert decFinish(res, set, &residue, status); /* cleanup/set flags */
54845796c8dcSSimon Schubert } while(0); /* end protected */
54855796c8dcSSimon Schubert
5486a45ae5f8SJohn Marino free(allocrhs); /* drop any storage used */
5487a45ae5f8SJohn Marino free(allocbufa); /* .. */
5488a45ae5f8SJohn Marino free(allocbuft); /* .. */
54895796c8dcSSimon Schubert /* [status is handled by caller] */
54905796c8dcSSimon Schubert return res;
54915796c8dcSSimon Schubert } /* decExpOp */
54925796c8dcSSimon Schubert
54935796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
54945796c8dcSSimon Schubert /* Initial-estimate natural logarithm table */
54955796c8dcSSimon Schubert /* */
54965796c8dcSSimon Schubert /* LNnn -- 90-entry 16-bit table for values from .10 through .99. */
54975796c8dcSSimon Schubert /* The result is a 4-digit encode of the coefficient (c=the */
54985796c8dcSSimon Schubert /* top 14 bits encoding 0-9999) and a 2-digit encode of the */
54995796c8dcSSimon Schubert /* exponent (e=the bottom 2 bits encoding 0-3) */
55005796c8dcSSimon Schubert /* */
55015796c8dcSSimon Schubert /* The resulting value is given by: */
55025796c8dcSSimon Schubert /* */
55035796c8dcSSimon Schubert /* v = -c * 10**(-e-3) */
55045796c8dcSSimon Schubert /* */
55055796c8dcSSimon Schubert /* where e and c are extracted from entry k = LNnn[x-10] */
55065796c8dcSSimon Schubert /* where x is truncated (NB) into the range 10 through 99, */
55075796c8dcSSimon Schubert /* and then c = k>>2 and e = k&3. */
55085796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
55095796c8dcSSimon Schubert const uShort LNnn[90]={9016, 8652, 8316, 8008, 7724, 7456, 7208,
55105796c8dcSSimon Schubert 6972, 6748, 6540, 6340, 6148, 5968, 5792, 5628, 5464, 5312,
55115796c8dcSSimon Schubert 5164, 5020, 4884, 4748, 4620, 4496, 4376, 4256, 4144, 4032,
55125796c8dcSSimon Schubert 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629,
55135796c8dcSSimon Schubert 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837,
55145796c8dcSSimon Schubert 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321,
55155796c8dcSSimon Schubert 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717,
55165796c8dcSSimon Schubert 10197, 9685, 9177, 8677, 8185, 7697, 7213, 6737, 6269, 5801,
55175796c8dcSSimon Schubert 5341, 4889, 4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254,
55185796c8dcSSimon Schubert 10130, 6046, 20055};
55195796c8dcSSimon Schubert
55205796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
55215796c8dcSSimon Schubert /* decLnOp -- effect natural logarithm */
55225796c8dcSSimon Schubert /* */
55235796c8dcSSimon Schubert /* This computes C = ln(A) */
55245796c8dcSSimon Schubert /* */
55255796c8dcSSimon Schubert /* res is C, the result. C may be A */
55265796c8dcSSimon Schubert /* rhs is A */
55275796c8dcSSimon Schubert /* set is the context; note that rounding mode has no effect */
55285796c8dcSSimon Schubert /* */
55295796c8dcSSimon Schubert /* C must have space for set->digits digits. */
55305796c8dcSSimon Schubert /* */
55315796c8dcSSimon Schubert /* Notable cases: */
55325796c8dcSSimon Schubert /* A<0 -> Invalid */
55335796c8dcSSimon Schubert /* A=0 -> -Infinity (Exact) */
55345796c8dcSSimon Schubert /* A=+Infinity -> +Infinity (Exact) */
55355796c8dcSSimon Schubert /* A=1 exactly -> 0 (Exact) */
55365796c8dcSSimon Schubert /* */
55375796c8dcSSimon Schubert /* Restrictions (as for Exp): */
55385796c8dcSSimon Schubert /* */
55395796c8dcSSimon Schubert /* digits, emax, and -emin in the context must be less than */
55405796c8dcSSimon Schubert /* DEC_MAX_MATH+11 (1000010), and the rhs must be within these */
55415796c8dcSSimon Schubert /* bounds or a zero. This is an internal routine, so these */
55425796c8dcSSimon Schubert /* restrictions are contractual and not enforced. */
55435796c8dcSSimon Schubert /* */
55445796c8dcSSimon Schubert /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will */
55455796c8dcSSimon Schubert /* almost always be correctly rounded, but may be up to 1 ulp in */
55465796c8dcSSimon Schubert /* error in rare cases. */
55475796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
55485796c8dcSSimon Schubert /* The result is calculated using Newton's method, with each */
55495796c8dcSSimon Schubert /* iteration calculating a' = a + x * exp(-a) - 1. See, for example, */
55505796c8dcSSimon Schubert /* Epperson 1989. */
55515796c8dcSSimon Schubert /* */
55525796c8dcSSimon Schubert /* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */
55535796c8dcSSimon Schubert /* This has to be calculated at the sum of the precision of x and the */
55545796c8dcSSimon Schubert /* working precision. */
55555796c8dcSSimon Schubert /* */
55565796c8dcSSimon Schubert /* Implementation notes: */
55575796c8dcSSimon Schubert /* */
55585796c8dcSSimon Schubert /* 1. This is separated out as decLnOp so it can be called from */
55595796c8dcSSimon Schubert /* other Mathematical functions (e.g., Log 10) with a wider range */
55605796c8dcSSimon Schubert /* than normal. In particular, it can handle the slightly wider */
55615796c8dcSSimon Schubert /* (+9+2) range needed by a power function. */
55625796c8dcSSimon Schubert /* */
55635796c8dcSSimon Schubert /* 2. The speed of this function is about 10x slower than exp, as */
55645796c8dcSSimon Schubert /* it typically needs 4-6 iterations for short numbers, and the */
55655796c8dcSSimon Schubert /* extra precision needed adds a squaring effect, twice. */
55665796c8dcSSimon Schubert /* */
55675796c8dcSSimon Schubert /* 3. Fastpaths are included for ln(10) and ln(2), up to length 40, */
55685796c8dcSSimon Schubert /* as these are common requests. ln(10) is used by log10(x). */
55695796c8dcSSimon Schubert /* */
55705796c8dcSSimon Schubert /* 4. An iteration might be saved by widening the LNnn table, and */
55715796c8dcSSimon Schubert /* would certainly save at least one if it were made ten times */
55725796c8dcSSimon Schubert /* bigger, too (for truncated fractions 0.100 through 0.999). */
55735796c8dcSSimon Schubert /* However, for most practical evaluations, at least four or five */
55745796c8dcSSimon Schubert /* iterations will be neede -- so this would only speed up by */
55755796c8dcSSimon Schubert /* 20-25% and that probably does not justify increasing the table */
55765796c8dcSSimon Schubert /* size. */
55775796c8dcSSimon Schubert /* */
55785796c8dcSSimon Schubert /* 5. The static buffers are larger than might be expected to allow */
55795796c8dcSSimon Schubert /* for calls from decNumberPower. */
55805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decLnOp(decNumber * res,const decNumber * rhs,decContext * set,uInt * status)55815796c8dcSSimon Schubert decNumber * decLnOp(decNumber *res, const decNumber *rhs,
55825796c8dcSSimon Schubert decContext *set, uInt *status) {
55835796c8dcSSimon Schubert uInt ignore=0; /* working status accumulator */
55845796c8dcSSimon Schubert uInt needbytes; /* for space calculations */
55855796c8dcSSimon Schubert Int residue; /* rounding residue */
55865796c8dcSSimon Schubert Int r; /* rhs=f*10**r [see below] */
55875796c8dcSSimon Schubert Int p; /* working precision */
55885796c8dcSSimon Schubert Int pp; /* precision for iteration */
55895796c8dcSSimon Schubert Int t; /* work */
55905796c8dcSSimon Schubert
55915796c8dcSSimon Schubert /* buffers for a (accumulator, typically precision+2) and b */
55925796c8dcSSimon Schubert /* (adjustment calculator, same size) */
55935796c8dcSSimon Schubert decNumber bufa[D2N(DECBUFFER+12)];
55945796c8dcSSimon Schubert decNumber *allocbufa=NULL; /* -> allocated bufa, iff allocated */
55955796c8dcSSimon Schubert decNumber *a=bufa; /* accumulator/work */
55965796c8dcSSimon Schubert decNumber bufb[D2N(DECBUFFER*2+2)];
55975796c8dcSSimon Schubert decNumber *allocbufb=NULL; /* -> allocated bufa, iff allocated */
55985796c8dcSSimon Schubert decNumber *b=bufb; /* adjustment/work */
55995796c8dcSSimon Schubert
56005796c8dcSSimon Schubert decNumber numone; /* constant 1 */
56015796c8dcSSimon Schubert decNumber cmp; /* work */
56025796c8dcSSimon Schubert decContext aset, bset; /* working contexts */
56035796c8dcSSimon Schubert
56045796c8dcSSimon Schubert #if DECCHECK
56055796c8dcSSimon Schubert Int iterations=0; /* for later sanity check */
56065796c8dcSSimon Schubert if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
56075796c8dcSSimon Schubert #endif
56085796c8dcSSimon Schubert
56095796c8dcSSimon Schubert do { /* protect allocated storage */
56105796c8dcSSimon Schubert if (SPECIALARG) { /* handle infinities and NaNs */
56115796c8dcSSimon Schubert if (decNumberIsInfinite(rhs)) { /* an infinity */
56125796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) /* -Infinity -> error */
56135796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
56145796c8dcSSimon Schubert else decNumberCopy(res, rhs); /* +Infinity -> self */
56155796c8dcSSimon Schubert }
56165796c8dcSSimon Schubert else decNaNs(res, rhs, NULL, set, status); /* a NaN */
56175796c8dcSSimon Schubert break;}
56185796c8dcSSimon Schubert
56195796c8dcSSimon Schubert if (ISZERO(rhs)) { /* +/- zeros -> -Infinity */
56205796c8dcSSimon Schubert decNumberZero(res); /* make clean */
56215796c8dcSSimon Schubert res->bits=DECINF|DECNEG; /* set - infinity */
56225796c8dcSSimon Schubert break;} /* [no status to set] */
56235796c8dcSSimon Schubert
56245796c8dcSSimon Schubert /* Non-zero negatives are bad... */
56255796c8dcSSimon Schubert if (decNumberIsNegative(rhs)) { /* -x -> error */
56265796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
56275796c8dcSSimon Schubert break;}
56285796c8dcSSimon Schubert
56295796c8dcSSimon Schubert /* Here, rhs is positive, finite, and in range */
56305796c8dcSSimon Schubert
56315796c8dcSSimon Schubert /* lookaside fastpath code for ln(2) and ln(10) at common lengths */
56325796c8dcSSimon Schubert if (rhs->exponent==0 && set->digits<=40) {
56335796c8dcSSimon Schubert #if DECDPUN==1
56345796c8dcSSimon Schubert if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */
56355796c8dcSSimon Schubert #else
56365796c8dcSSimon Schubert if (rhs->lsu[0]==10 && rhs->digits==2) { /* ln(10) */
56375796c8dcSSimon Schubert #endif
56385796c8dcSSimon Schubert aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
56395796c8dcSSimon Schubert #define LN10 "2.302585092994045684017991454684364207601"
56405796c8dcSSimon Schubert decNumberFromString(res, LN10, &aset);
56415796c8dcSSimon Schubert *status|=(DEC_Inexact | DEC_Rounded); /* is inexact */
56425796c8dcSSimon Schubert break;}
56435796c8dcSSimon Schubert if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */
56445796c8dcSSimon Schubert aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
56455796c8dcSSimon Schubert #define LN2 "0.6931471805599453094172321214581765680755"
56465796c8dcSSimon Schubert decNumberFromString(res, LN2, &aset);
56475796c8dcSSimon Schubert *status|=(DEC_Inexact | DEC_Rounded);
56485796c8dcSSimon Schubert break;}
56495796c8dcSSimon Schubert } /* integer and short */
56505796c8dcSSimon Schubert
56515796c8dcSSimon Schubert /* Determine the working precision. This is normally the */
56525796c8dcSSimon Schubert /* requested precision + 2, with a minimum of 9. However, if */
56535796c8dcSSimon Schubert /* the rhs is 'over-precise' then allow for all its digits to */
56545796c8dcSSimon Schubert /* potentially participate (consider an rhs where all the excess */
56555796c8dcSSimon Schubert /* digits are 9s) so in this case use rhs->digits+2. */
56565796c8dcSSimon Schubert p=MAXI(rhs->digits, MAXI(set->digits, 7))+2;
56575796c8dcSSimon Schubert
56585796c8dcSSimon Schubert /* Allocate space for the accumulator and the high-precision */
56595796c8dcSSimon Schubert /* adjustment calculator, if necessary. The accumulator must */
56605796c8dcSSimon Schubert /* be able to hold p digits, and the adjustment up to */
56615796c8dcSSimon Schubert /* rhs->digits+p digits. They are also made big enough for 16 */
56625796c8dcSSimon Schubert /* digits so that they can be used for calculating the initial */
56635796c8dcSSimon Schubert /* estimate. */
56645796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit);
56655796c8dcSSimon Schubert if (needbytes>sizeof(bufa)) { /* need malloc space */
56665796c8dcSSimon Schubert allocbufa=(decNumber *)malloc(needbytes);
56675796c8dcSSimon Schubert if (allocbufa==NULL) { /* hopeless -- abandon */
56685796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
56695796c8dcSSimon Schubert break;}
56705796c8dcSSimon Schubert a=allocbufa; /* use the allocated space */
56715796c8dcSSimon Schubert }
56725796c8dcSSimon Schubert pp=p+rhs->digits;
56735796c8dcSSimon Schubert needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit);
56745796c8dcSSimon Schubert if (needbytes>sizeof(bufb)) { /* need malloc space */
56755796c8dcSSimon Schubert allocbufb=(decNumber *)malloc(needbytes);
56765796c8dcSSimon Schubert if (allocbufb==NULL) { /* hopeless -- abandon */
56775796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
56785796c8dcSSimon Schubert break;}
56795796c8dcSSimon Schubert b=allocbufb; /* use the allocated space */
56805796c8dcSSimon Schubert }
56815796c8dcSSimon Schubert
56825796c8dcSSimon Schubert /* Prepare an initial estimate in acc. Calculate this by */
56835796c8dcSSimon Schubert /* considering the coefficient of x to be a normalized fraction, */
56845796c8dcSSimon Schubert /* f, with the decimal point at far left and multiplied by */
56855796c8dcSSimon Schubert /* 10**r. Then, rhs=f*10**r and 0.1<=f<1, and */
56865796c8dcSSimon Schubert /* ln(x) = ln(f) + ln(10)*r */
56875796c8dcSSimon Schubert /* Get the initial estimate for ln(f) from a small lookup */
56885796c8dcSSimon Schubert /* table (see above) indexed by the first two digits of f, */
56895796c8dcSSimon Schubert /* truncated. */
56905796c8dcSSimon Schubert
56915796c8dcSSimon Schubert decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */
56925796c8dcSSimon Schubert r=rhs->exponent+rhs->digits; /* 'normalised' exponent */
56935796c8dcSSimon Schubert decNumberFromInt32(a, r); /* a=r */
56945796c8dcSSimon Schubert decNumberFromInt32(b, 2302585); /* b=ln(10) (2.302585) */
56955796c8dcSSimon Schubert b->exponent=-6; /* .. */
56965796c8dcSSimon Schubert decMultiplyOp(a, a, b, &aset, &ignore); /* a=a*b */
56975796c8dcSSimon Schubert /* now get top two digits of rhs into b by simple truncate and */
56985796c8dcSSimon Schubert /* force to integer */
56995796c8dcSSimon Schubert residue=0; /* (no residue) */
57005796c8dcSSimon Schubert aset.digits=2; aset.round=DEC_ROUND_DOWN;
57015796c8dcSSimon Schubert decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */
57025796c8dcSSimon Schubert b->exponent=0; /* make integer */
57035796c8dcSSimon Schubert t=decGetInt(b); /* [cannot fail] */
57045796c8dcSSimon Schubert if (t<10) t=X10(t); /* adjust single-digit b */
57055796c8dcSSimon Schubert t=LNnn[t-10]; /* look up ln(b) */
57065796c8dcSSimon Schubert decNumberFromInt32(b, t>>2); /* b=ln(b) coefficient */
57075796c8dcSSimon Schubert b->exponent=-(t&3)-3; /* set exponent */
57085796c8dcSSimon Schubert b->bits=DECNEG; /* ln(0.10)->ln(0.99) always -ve */
57095796c8dcSSimon Schubert aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */
57105796c8dcSSimon Schubert decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */
57115796c8dcSSimon Schubert /* the initial estimate is now in a, with up to 4 digits correct. */
57125796c8dcSSimon Schubert /* When rhs is at or near Nmax the estimate will be low, so we */
57135796c8dcSSimon Schubert /* will approach it from below, avoiding overflow when calling exp. */
57145796c8dcSSimon Schubert
57155796c8dcSSimon Schubert decNumberZero(&numone); *numone.lsu=1; /* constant 1 for adjustment */
57165796c8dcSSimon Schubert
57175796c8dcSSimon Schubert /* accumulator bounds are as requested (could underflow, but */
57185796c8dcSSimon Schubert /* cannot overflow) */
57195796c8dcSSimon Schubert aset.emax=set->emax;
57205796c8dcSSimon Schubert aset.emin=set->emin;
57215796c8dcSSimon Schubert aset.clamp=0; /* no concrete format */
57225796c8dcSSimon Schubert /* set up a context to be used for the multiply and subtract */
57235796c8dcSSimon Schubert bset=aset;
57245796c8dcSSimon Schubert bset.emax=DEC_MAX_MATH*2; /* use double bounds for the */
57255796c8dcSSimon Schubert bset.emin=-DEC_MAX_MATH*2; /* adjustment calculation */
57265796c8dcSSimon Schubert /* [see decExpOp call below] */
57275796c8dcSSimon Schubert /* for each iteration double the number of digits to calculate, */
57285796c8dcSSimon Schubert /* up to a maximum of p */
57295796c8dcSSimon Schubert pp=9; /* initial precision */
57305796c8dcSSimon Schubert /* [initially 9 as then the sequence starts 7+2, 16+2, and */
57315796c8dcSSimon Schubert /* 34+2, which is ideal for standard-sized numbers] */
57325796c8dcSSimon Schubert aset.digits=pp; /* working context */
57335796c8dcSSimon Schubert bset.digits=pp+rhs->digits; /* wider context */
57345796c8dcSSimon Schubert for (;;) { /* iterate */
57355796c8dcSSimon Schubert #if DECCHECK
57365796c8dcSSimon Schubert iterations++;
57375796c8dcSSimon Schubert if (iterations>24) break; /* consider 9 * 2**24 */
57385796c8dcSSimon Schubert #endif
57395796c8dcSSimon Schubert /* calculate the adjustment (exp(-a)*x-1) into b. This is a */
57405796c8dcSSimon Schubert /* catastrophic subtraction but it really is the difference */
57415796c8dcSSimon Schubert /* from 1 that is of interest. */
57425796c8dcSSimon Schubert /* Use the internal entry point to Exp as it allows the double */
57435796c8dcSSimon Schubert /* range for calculating exp(-a) when a is the tiniest subnormal. */
57445796c8dcSSimon Schubert a->bits^=DECNEG; /* make -a */
57455796c8dcSSimon Schubert decExpOp(b, a, &bset, &ignore); /* b=exp(-a) */
57465796c8dcSSimon Schubert a->bits^=DECNEG; /* restore sign of a */
57475796c8dcSSimon Schubert /* now multiply by rhs and subtract 1, at the wider precision */
57485796c8dcSSimon Schubert decMultiplyOp(b, b, rhs, &bset, &ignore); /* b=b*rhs */
57495796c8dcSSimon Schubert decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */
57505796c8dcSSimon Schubert
57515796c8dcSSimon Schubert /* the iteration ends when the adjustment cannot affect the */
57525796c8dcSSimon Schubert /* result by >=0.5 ulp (at the requested digits), which */
57535796c8dcSSimon Schubert /* is when its value is smaller than the accumulator by */
57545796c8dcSSimon Schubert /* set->digits+1 digits (or it is zero) -- this is a looser */
57555796c8dcSSimon Schubert /* requirement than for Exp because all that happens to the */
57565796c8dcSSimon Schubert /* accumulator after this is the final rounding (but note that */
57575796c8dcSSimon Schubert /* there must also be full precision in a, or a=0). */
57585796c8dcSSimon Schubert
57595796c8dcSSimon Schubert if (decNumberIsZero(b) ||
57605796c8dcSSimon Schubert (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) {
57615796c8dcSSimon Schubert if (a->digits==p) break;
57625796c8dcSSimon Schubert if (decNumberIsZero(a)) {
57635796c8dcSSimon Schubert decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */
57645796c8dcSSimon Schubert if (cmp.lsu[0]==0) a->exponent=0; /* yes, exact 0 */
57655796c8dcSSimon Schubert else *status|=(DEC_Inexact | DEC_Rounded); /* no, inexact */
57665796c8dcSSimon Schubert break;
57675796c8dcSSimon Schubert }
57685796c8dcSSimon Schubert /* force padding if adjustment has gone to 0 before full length */
57695796c8dcSSimon Schubert if (decNumberIsZero(b)) b->exponent=a->exponent-p;
57705796c8dcSSimon Schubert }
57715796c8dcSSimon Schubert
57725796c8dcSSimon Schubert /* not done yet ... */
57735796c8dcSSimon Schubert decAddOp(a, a, b, &aset, 0, &ignore); /* a=a+b for next estimate */
57745796c8dcSSimon Schubert if (pp==p) continue; /* precision is at maximum */
57755796c8dcSSimon Schubert /* lengthen the next calculation */
57765796c8dcSSimon Schubert pp=pp*2; /* double precision */
57775796c8dcSSimon Schubert if (pp>p) pp=p; /* clamp to maximum */
57785796c8dcSSimon Schubert aset.digits=pp; /* working context */
57795796c8dcSSimon Schubert bset.digits=pp+rhs->digits; /* wider context */
57805796c8dcSSimon Schubert } /* Newton's iteration */
57815796c8dcSSimon Schubert
57825796c8dcSSimon Schubert #if DECCHECK
57835796c8dcSSimon Schubert /* just a sanity check; remove the test to show always */
57845796c8dcSSimon Schubert if (iterations>24)
57855796c8dcSSimon Schubert printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
57865796c8dcSSimon Schubert (LI)iterations, (LI)*status, (LI)p, (LI)rhs->digits);
57875796c8dcSSimon Schubert #endif
57885796c8dcSSimon Schubert
57895796c8dcSSimon Schubert /* Copy and round the result to res */
57905796c8dcSSimon Schubert residue=1; /* indicate dirt to right */
57915796c8dcSSimon Schubert if (ISZERO(a)) residue=0; /* .. unless underflowed to 0 */
57925796c8dcSSimon Schubert aset.digits=set->digits; /* [use default rounding] */
57935796c8dcSSimon Schubert decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
57945796c8dcSSimon Schubert decFinish(res, set, &residue, status); /* cleanup/set flags */
57955796c8dcSSimon Schubert } while(0); /* end protected */
57965796c8dcSSimon Schubert
5797a45ae5f8SJohn Marino free(allocbufa); /* drop any storage used */
5798a45ae5f8SJohn Marino free(allocbufb); /* .. */
57995796c8dcSSimon Schubert /* [status is handled by caller] */
58005796c8dcSSimon Schubert return res;
58015796c8dcSSimon Schubert } /* decLnOp */
58025796c8dcSSimon Schubert
58035796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
58045796c8dcSSimon Schubert /* decQuantizeOp -- force exponent to requested value */
58055796c8dcSSimon Schubert /* */
58065796c8dcSSimon Schubert /* This computes C = op(A, B), where op adjusts the coefficient */
58075796c8dcSSimon Schubert /* of C (by rounding or shifting) such that the exponent (-scale) */
58085796c8dcSSimon Schubert /* of C has the value B or matches the exponent of B. */
58095796c8dcSSimon Schubert /* The numerical value of C will equal A, except for the effects of */
58105796c8dcSSimon Schubert /* any rounding that occurred. */
58115796c8dcSSimon Schubert /* */
58125796c8dcSSimon Schubert /* res is C, the result. C may be A or B */
58135796c8dcSSimon Schubert /* lhs is A, the number to adjust */
58145796c8dcSSimon Schubert /* rhs is B, the requested exponent */
58155796c8dcSSimon Schubert /* set is the context */
58165796c8dcSSimon Schubert /* quant is 1 for quantize or 0 for rescale */
58175796c8dcSSimon Schubert /* status is the status accumulator (this can be called without */
58185796c8dcSSimon Schubert /* risk of control loss) */
58195796c8dcSSimon Schubert /* */
58205796c8dcSSimon Schubert /* C must have space for set->digits digits. */
58215796c8dcSSimon Schubert /* */
58225796c8dcSSimon Schubert /* Unless there is an error or the result is infinite, the exponent */
58235796c8dcSSimon Schubert /* after the operation is guaranteed to be that requested. */
58245796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
58255796c8dcSSimon Schubert static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs,
58265796c8dcSSimon Schubert const decNumber *rhs, decContext *set,
58275796c8dcSSimon Schubert Flag quant, uInt *status) {
58285796c8dcSSimon Schubert #if DECSUBSET
58295796c8dcSSimon Schubert decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
58305796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* .., rhs */
58315796c8dcSSimon Schubert #endif
58325796c8dcSSimon Schubert const decNumber *inrhs=rhs; /* save original rhs */
58335796c8dcSSimon Schubert Int reqdigits=set->digits; /* requested DIGITS */
58345796c8dcSSimon Schubert Int reqexp; /* requested exponent [-scale] */
58355796c8dcSSimon Schubert Int residue=0; /* rounding residue */
58365796c8dcSSimon Schubert Int etiny=set->emin-(reqdigits-1);
58375796c8dcSSimon Schubert
58385796c8dcSSimon Schubert #if DECCHECK
58395796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
58405796c8dcSSimon Schubert #endif
58415796c8dcSSimon Schubert
58425796c8dcSSimon Schubert do { /* protect allocated storage */
58435796c8dcSSimon Schubert #if DECSUBSET
58445796c8dcSSimon Schubert if (!set->extended) {
58455796c8dcSSimon Schubert /* reduce operands and set lostDigits status, as needed */
58465796c8dcSSimon Schubert if (lhs->digits>reqdigits) {
58475796c8dcSSimon Schubert alloclhs=decRoundOperand(lhs, set, status);
58485796c8dcSSimon Schubert if (alloclhs==NULL) break;
58495796c8dcSSimon Schubert lhs=alloclhs;
58505796c8dcSSimon Schubert }
58515796c8dcSSimon Schubert if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */
58525796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, status);
58535796c8dcSSimon Schubert if (allocrhs==NULL) break;
58545796c8dcSSimon Schubert rhs=allocrhs;
58555796c8dcSSimon Schubert }
58565796c8dcSSimon Schubert }
58575796c8dcSSimon Schubert #endif
58585796c8dcSSimon Schubert /* [following code does not require input rounding] */
58595796c8dcSSimon Schubert
58605796c8dcSSimon Schubert /* Handle special values */
58615796c8dcSSimon Schubert if (SPECIALARGS) {
58625796c8dcSSimon Schubert /* NaNs get usual processing */
58635796c8dcSSimon Schubert if (SPECIALARGS & (DECSNAN | DECNAN))
58645796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, status);
58655796c8dcSSimon Schubert /* one infinity but not both is bad */
58665796c8dcSSimon Schubert else if ((lhs->bits ^ rhs->bits) & DECINF)
58675796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
58685796c8dcSSimon Schubert /* both infinity: return lhs */
58695796c8dcSSimon Schubert else decNumberCopy(res, lhs); /* [nop if in place] */
58705796c8dcSSimon Schubert break;
58715796c8dcSSimon Schubert }
58725796c8dcSSimon Schubert
58735796c8dcSSimon Schubert /* set requested exponent */
58745796c8dcSSimon Schubert if (quant) reqexp=inrhs->exponent; /* quantize -- match exponents */
58755796c8dcSSimon Schubert else { /* rescale -- use value of rhs */
58765796c8dcSSimon Schubert /* Original rhs must be an integer that fits and is in range, */
58775796c8dcSSimon Schubert /* which could be from -1999999997 to +999999999, thanks to */
58785796c8dcSSimon Schubert /* subnormals */
58795796c8dcSSimon Schubert reqexp=decGetInt(inrhs); /* [cannot fail] */
58805796c8dcSSimon Schubert }
58815796c8dcSSimon Schubert
58825796c8dcSSimon Schubert #if DECSUBSET
58835796c8dcSSimon Schubert if (!set->extended) etiny=set->emin; /* no subnormals */
58845796c8dcSSimon Schubert #endif
58855796c8dcSSimon Schubert
58865796c8dcSSimon Schubert if (reqexp==BADINT /* bad (rescale only) or .. */
58875796c8dcSSimon Schubert || reqexp==BIGODD || reqexp==BIGEVEN /* very big (ditto) or .. */
58885796c8dcSSimon Schubert || (reqexp<etiny) /* < lowest */
58895796c8dcSSimon Schubert || (reqexp>set->emax)) { /* > emax */
58905796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
58915796c8dcSSimon Schubert break;}
58925796c8dcSSimon Schubert
58935796c8dcSSimon Schubert /* the RHS has been processed, so it can be overwritten now if necessary */
58945796c8dcSSimon Schubert if (ISZERO(lhs)) { /* zero coefficient unchanged */
58955796c8dcSSimon Schubert decNumberCopy(res, lhs); /* [nop if in place] */
58965796c8dcSSimon Schubert res->exponent=reqexp; /* .. just set exponent */
58975796c8dcSSimon Schubert #if DECSUBSET
58985796c8dcSSimon Schubert if (!set->extended) res->bits=0; /* subset specification; no -0 */
58995796c8dcSSimon Schubert #endif
59005796c8dcSSimon Schubert }
59015796c8dcSSimon Schubert else { /* non-zero lhs */
59025796c8dcSSimon Schubert Int adjust=reqexp-lhs->exponent; /* digit adjustment needed */
59035796c8dcSSimon Schubert /* if adjusted coefficient will definitely not fit, give up now */
59045796c8dcSSimon Schubert if ((lhs->digits-adjust)>reqdigits) {
59055796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
59065796c8dcSSimon Schubert break;
59075796c8dcSSimon Schubert }
59085796c8dcSSimon Schubert
59095796c8dcSSimon Schubert if (adjust>0) { /* increasing exponent */
59105796c8dcSSimon Schubert /* this will decrease the length of the coefficient by adjust */
59115796c8dcSSimon Schubert /* digits, and must round as it does so */
59125796c8dcSSimon Schubert decContext workset; /* work */
59135796c8dcSSimon Schubert workset=*set; /* clone rounding, etc. */
59145796c8dcSSimon Schubert workset.digits=lhs->digits-adjust; /* set requested length */
59155796c8dcSSimon Schubert /* [note that the latter can be <1, here] */
59165796c8dcSSimon Schubert decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */
59175796c8dcSSimon Schubert decApplyRound(res, &workset, residue, status); /* .. and round */
59185796c8dcSSimon Schubert residue=0; /* [used] */
59195796c8dcSSimon Schubert /* If just rounded a 999s case, exponent will be off by one; */
59205796c8dcSSimon Schubert /* adjust back (after checking space), if so. */
59215796c8dcSSimon Schubert if (res->exponent>reqexp) {
59225796c8dcSSimon Schubert /* re-check needed, e.g., for quantize(0.9999, 0.001) under */
59235796c8dcSSimon Schubert /* set->digits==3 */
59245796c8dcSSimon Schubert if (res->digits==reqdigits) { /* cannot shift by 1 */
59255796c8dcSSimon Schubert *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */
59265796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
59275796c8dcSSimon Schubert break;
59285796c8dcSSimon Schubert }
59295796c8dcSSimon Schubert res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */
59305796c8dcSSimon Schubert res->exponent--; /* (re)adjust the exponent. */
59315796c8dcSSimon Schubert }
59325796c8dcSSimon Schubert #if DECSUBSET
59335796c8dcSSimon Schubert if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */
59345796c8dcSSimon Schubert #endif
59355796c8dcSSimon Schubert } /* increase */
59365796c8dcSSimon Schubert else /* adjust<=0 */ { /* decreasing or = exponent */
59375796c8dcSSimon Schubert /* this will increase the length of the coefficient by -adjust */
59385796c8dcSSimon Schubert /* digits, by adding zero or more trailing zeros; this is */
59395796c8dcSSimon Schubert /* already checked for fit, above */
59405796c8dcSSimon Schubert decNumberCopy(res, lhs); /* [it will fit] */
59415796c8dcSSimon Schubert /* if padding needed (adjust<0), add it now... */
59425796c8dcSSimon Schubert if (adjust<0) {
59435796c8dcSSimon Schubert res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
59445796c8dcSSimon Schubert res->exponent+=adjust; /* adjust the exponent */
59455796c8dcSSimon Schubert }
59465796c8dcSSimon Schubert } /* decrease */
59475796c8dcSSimon Schubert } /* non-zero */
59485796c8dcSSimon Schubert
59495796c8dcSSimon Schubert /* Check for overflow [do not use Finalize in this case, as an */
59505796c8dcSSimon Schubert /* overflow here is a "don't fit" situation] */
59515796c8dcSSimon Schubert if (res->exponent>set->emax-res->digits+1) { /* too big */
59525796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
59535796c8dcSSimon Schubert break;
59545796c8dcSSimon Schubert }
59555796c8dcSSimon Schubert else {
59565796c8dcSSimon Schubert decFinalize(res, set, &residue, status); /* set subnormal flags */
59575796c8dcSSimon Schubert *status&=~DEC_Underflow; /* suppress Underflow [as per 754] */
59585796c8dcSSimon Schubert }
59595796c8dcSSimon Schubert } while(0); /* end protected */
59605796c8dcSSimon Schubert
59615796c8dcSSimon Schubert #if DECSUBSET
5962a45ae5f8SJohn Marino free(allocrhs); /* drop any storage used */
5963a45ae5f8SJohn Marino free(alloclhs); /* .. */
59645796c8dcSSimon Schubert #endif
59655796c8dcSSimon Schubert return res;
59665796c8dcSSimon Schubert } /* decQuantizeOp */
59675796c8dcSSimon Schubert
59685796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
59695796c8dcSSimon Schubert /* decCompareOp -- compare, min, or max two Numbers */
59705796c8dcSSimon Schubert /* */
59715796c8dcSSimon Schubert /* This computes C = A ? B and carries out one of four operations: */
59725796c8dcSSimon Schubert /* COMPARE -- returns the signum (as a number) giving the */
59735796c8dcSSimon Schubert /* result of a comparison unless one or both */
59745796c8dcSSimon Schubert /* operands is a NaN (in which case a NaN results) */
59755796c8dcSSimon Schubert /* COMPSIG -- as COMPARE except that a quiet NaN raises */
59765796c8dcSSimon Schubert /* Invalid operation. */
59775796c8dcSSimon Schubert /* COMPMAX -- returns the larger of the operands, using the */
59785796c8dcSSimon Schubert /* 754 maxnum operation */
59795796c8dcSSimon Schubert /* COMPMAXMAG -- ditto, comparing absolute values */
59805796c8dcSSimon Schubert /* COMPMIN -- the 754 minnum operation */
59815796c8dcSSimon Schubert /* COMPMINMAG -- ditto, comparing absolute values */
59825796c8dcSSimon Schubert /* COMTOTAL -- returns the signum (as a number) giving the */
59835796c8dcSSimon Schubert /* result of a comparison using 754 total ordering */
59845796c8dcSSimon Schubert /* */
59855796c8dcSSimon Schubert /* res is C, the result. C may be A and/or B (e.g., X=X?X) */
59865796c8dcSSimon Schubert /* lhs is A */
59875796c8dcSSimon Schubert /* rhs is B */
59885796c8dcSSimon Schubert /* set is the context */
59895796c8dcSSimon Schubert /* op is the operation flag */
59905796c8dcSSimon Schubert /* status is the usual accumulator */
59915796c8dcSSimon Schubert /* */
59925796c8dcSSimon Schubert /* C must have space for one digit for COMPARE or set->digits for */
59935796c8dcSSimon Schubert /* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG. */
59945796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
59955796c8dcSSimon Schubert /* The emphasis here is on speed for common cases, and avoiding */
59965796c8dcSSimon Schubert /* coefficient comparison if possible. */
59975796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
59985796c8dcSSimon Schubert decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
59995796c8dcSSimon Schubert const decNumber *rhs, decContext *set,
60005796c8dcSSimon Schubert Flag op, uInt *status) {
60015796c8dcSSimon Schubert #if DECSUBSET
60025796c8dcSSimon Schubert decNumber *alloclhs=NULL; /* non-NULL if rounded lhs allocated */
60035796c8dcSSimon Schubert decNumber *allocrhs=NULL; /* .., rhs */
60045796c8dcSSimon Schubert #endif
60055796c8dcSSimon Schubert Int result=0; /* default result value */
60065796c8dcSSimon Schubert uByte merged; /* work */
60075796c8dcSSimon Schubert
60085796c8dcSSimon Schubert #if DECCHECK
60095796c8dcSSimon Schubert if (decCheckOperands(res, lhs, rhs, set)) return res;
60105796c8dcSSimon Schubert #endif
60115796c8dcSSimon Schubert
60125796c8dcSSimon Schubert do { /* protect allocated storage */
60135796c8dcSSimon Schubert #if DECSUBSET
60145796c8dcSSimon Schubert if (!set->extended) {
60155796c8dcSSimon Schubert /* reduce operands and set lostDigits status, as needed */
60165796c8dcSSimon Schubert if (lhs->digits>set->digits) {
60175796c8dcSSimon Schubert alloclhs=decRoundOperand(lhs, set, status);
60185796c8dcSSimon Schubert if (alloclhs==NULL) {result=BADINT; break;}
60195796c8dcSSimon Schubert lhs=alloclhs;
60205796c8dcSSimon Schubert }
60215796c8dcSSimon Schubert if (rhs->digits>set->digits) {
60225796c8dcSSimon Schubert allocrhs=decRoundOperand(rhs, set, status);
60235796c8dcSSimon Schubert if (allocrhs==NULL) {result=BADINT; break;}
60245796c8dcSSimon Schubert rhs=allocrhs;
60255796c8dcSSimon Schubert }
60265796c8dcSSimon Schubert }
60275796c8dcSSimon Schubert #endif
60285796c8dcSSimon Schubert /* [following code does not require input rounding] */
60295796c8dcSSimon Schubert
60305796c8dcSSimon Schubert /* If total ordering then handle differing signs 'up front' */
60315796c8dcSSimon Schubert if (op==COMPTOTAL) { /* total ordering */
60325796c8dcSSimon Schubert if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) {
60335796c8dcSSimon Schubert result=-1;
60345796c8dcSSimon Schubert break;
60355796c8dcSSimon Schubert }
60365796c8dcSSimon Schubert if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) {
60375796c8dcSSimon Schubert result=+1;
60385796c8dcSSimon Schubert break;
60395796c8dcSSimon Schubert }
60405796c8dcSSimon Schubert }
60415796c8dcSSimon Schubert
60425796c8dcSSimon Schubert /* handle NaNs specially; let infinities drop through */
60435796c8dcSSimon Schubert /* This assumes sNaN (even just one) leads to NaN. */
60445796c8dcSSimon Schubert merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN);
60455796c8dcSSimon Schubert if (merged) { /* a NaN bit set */
60465796c8dcSSimon Schubert if (op==COMPARE); /* result will be NaN */
60475796c8dcSSimon Schubert else if (op==COMPSIG) /* treat qNaN as sNaN */
60485796c8dcSSimon Schubert *status|=DEC_Invalid_operation | DEC_sNaN;
60495796c8dcSSimon Schubert else if (op==COMPTOTAL) { /* total ordering, always finite */
60505796c8dcSSimon Schubert /* signs are known to be the same; compute the ordering here */
60515796c8dcSSimon Schubert /* as if the signs are both positive, then invert for negatives */
60525796c8dcSSimon Schubert if (!decNumberIsNaN(lhs)) result=-1;
60535796c8dcSSimon Schubert else if (!decNumberIsNaN(rhs)) result=+1;
60545796c8dcSSimon Schubert /* here if both NaNs */
60555796c8dcSSimon Schubert else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1;
60565796c8dcSSimon Schubert else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1;
60575796c8dcSSimon Schubert else { /* both NaN or both sNaN */
60585796c8dcSSimon Schubert /* now it just depends on the payload */
60595796c8dcSSimon Schubert result=decUnitCompare(lhs->lsu, D2U(lhs->digits),
60605796c8dcSSimon Schubert rhs->lsu, D2U(rhs->digits), 0);
60615796c8dcSSimon Schubert /* [Error not possible, as these are 'aligned'] */
60625796c8dcSSimon Schubert } /* both same NaNs */
60635796c8dcSSimon Schubert if (decNumberIsNegative(lhs)) result=-result;
60645796c8dcSSimon Schubert break;
60655796c8dcSSimon Schubert } /* total order */
60665796c8dcSSimon Schubert
60675796c8dcSSimon Schubert else if (merged & DECSNAN); /* sNaN -> qNaN */
60685796c8dcSSimon Schubert else { /* here if MIN or MAX and one or two quiet NaNs */
60695796c8dcSSimon Schubert /* min or max -- 754 rules ignore single NaN */
60705796c8dcSSimon Schubert if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) {
60715796c8dcSSimon Schubert /* just one NaN; force choice to be the non-NaN operand */
60725796c8dcSSimon Schubert op=COMPMAX;
60735796c8dcSSimon Schubert if (lhs->bits & DECNAN) result=-1; /* pick rhs */
60745796c8dcSSimon Schubert else result=+1; /* pick lhs */
60755796c8dcSSimon Schubert break;
60765796c8dcSSimon Schubert }
60775796c8dcSSimon Schubert } /* max or min */
60785796c8dcSSimon Schubert op=COMPNAN; /* use special path */
60795796c8dcSSimon Schubert decNaNs(res, lhs, rhs, set, status); /* propagate NaN */
60805796c8dcSSimon Schubert break;
60815796c8dcSSimon Schubert }
60825796c8dcSSimon Schubert /* have numbers */
60835796c8dcSSimon Schubert if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1);
60845796c8dcSSimon Schubert else result=decCompare(lhs, rhs, 0); /* sign matters */
60855796c8dcSSimon Schubert } while(0); /* end protected */
60865796c8dcSSimon Schubert
60875796c8dcSSimon Schubert if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */
60885796c8dcSSimon Schubert else {
60895796c8dcSSimon Schubert if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */
60905796c8dcSSimon Schubert if (op==COMPTOTAL && result==0) {
60915796c8dcSSimon Schubert /* operands are numerically equal or same NaN (and same sign, */
60925796c8dcSSimon Schubert /* tested first); if identical, leave result 0 */
60935796c8dcSSimon Schubert if (lhs->exponent!=rhs->exponent) {
60945796c8dcSSimon Schubert if (lhs->exponent<rhs->exponent) result=-1;
60955796c8dcSSimon Schubert else result=+1;
60965796c8dcSSimon Schubert if (decNumberIsNegative(lhs)) result=-result;
60975796c8dcSSimon Schubert } /* lexp!=rexp */
60985796c8dcSSimon Schubert } /* total-order by exponent */
60995796c8dcSSimon Schubert decNumberZero(res); /* [always a valid result] */
61005796c8dcSSimon Schubert if (result!=0) { /* must be -1 or +1 */
61015796c8dcSSimon Schubert *res->lsu=1;
61025796c8dcSSimon Schubert if (result<0) res->bits=DECNEG;
61035796c8dcSSimon Schubert }
61045796c8dcSSimon Schubert }
61055796c8dcSSimon Schubert else if (op==COMPNAN); /* special, drop through */
61065796c8dcSSimon Schubert else { /* MAX or MIN, non-NaN result */
61075796c8dcSSimon Schubert Int residue=0; /* rounding accumulator */
61085796c8dcSSimon Schubert /* choose the operand for the result */
61095796c8dcSSimon Schubert const decNumber *choice;
61105796c8dcSSimon Schubert if (result==0) { /* operands are numerically equal */
61115796c8dcSSimon Schubert /* choose according to sign then exponent (see 754) */
61125796c8dcSSimon Schubert uByte slhs=(lhs->bits & DECNEG);
61135796c8dcSSimon Schubert uByte srhs=(rhs->bits & DECNEG);
61145796c8dcSSimon Schubert #if DECSUBSET
61155796c8dcSSimon Schubert if (!set->extended) { /* subset: force left-hand */
61165796c8dcSSimon Schubert op=COMPMAX;
61175796c8dcSSimon Schubert result=+1;
61185796c8dcSSimon Schubert }
61195796c8dcSSimon Schubert else
61205796c8dcSSimon Schubert #endif
61215796c8dcSSimon Schubert if (slhs!=srhs) { /* signs differ */
61225796c8dcSSimon Schubert if (slhs) result=-1; /* rhs is max */
61235796c8dcSSimon Schubert else result=+1; /* lhs is max */
61245796c8dcSSimon Schubert }
61255796c8dcSSimon Schubert else if (slhs && srhs) { /* both negative */
61265796c8dcSSimon Schubert if (lhs->exponent<rhs->exponent) result=+1;
61275796c8dcSSimon Schubert else result=-1;
61285796c8dcSSimon Schubert /* [if equal, use lhs, technically identical] */
61295796c8dcSSimon Schubert }
61305796c8dcSSimon Schubert else { /* both positive */
61315796c8dcSSimon Schubert if (lhs->exponent>rhs->exponent) result=+1;
61325796c8dcSSimon Schubert else result=-1;
61335796c8dcSSimon Schubert /* [ditto] */
61345796c8dcSSimon Schubert }
61355796c8dcSSimon Schubert } /* numerically equal */
61365796c8dcSSimon Schubert /* here result will be non-0; reverse if looking for MIN */
61375796c8dcSSimon Schubert if (op==COMPMIN || op==COMPMINMAG) result=-result;
61385796c8dcSSimon Schubert choice=(result>0 ? lhs : rhs); /* choose */
61395796c8dcSSimon Schubert /* copy chosen to result, rounding if need be */
61405796c8dcSSimon Schubert decCopyFit(res, choice, set, &residue, status);
61415796c8dcSSimon Schubert decFinish(res, set, &residue, status);
61425796c8dcSSimon Schubert }
61435796c8dcSSimon Schubert }
61445796c8dcSSimon Schubert #if DECSUBSET
6145a45ae5f8SJohn Marino free(allocrhs); /* free any storage used */
6146a45ae5f8SJohn Marino free(alloclhs); /* .. */
61475796c8dcSSimon Schubert #endif
61485796c8dcSSimon Schubert return res;
61495796c8dcSSimon Schubert } /* decCompareOp */
61505796c8dcSSimon Schubert
61515796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
61525796c8dcSSimon Schubert /* decCompare -- compare two decNumbers by numerical value */
61535796c8dcSSimon Schubert /* */
61545796c8dcSSimon Schubert /* This routine compares A ? B without altering them. */
61555796c8dcSSimon Schubert /* */
61565796c8dcSSimon Schubert /* Arg1 is A, a decNumber which is not a NaN */
61575796c8dcSSimon Schubert /* Arg2 is B, a decNumber which is not a NaN */
61585796c8dcSSimon Schubert /* Arg3 is 1 for a sign-independent compare, 0 otherwise */
61595796c8dcSSimon Schubert /* */
61605796c8dcSSimon Schubert /* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */
61615796c8dcSSimon Schubert /* (the only possible failure is an allocation error) */
61625796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
61635796c8dcSSimon Schubert static Int decCompare(const decNumber *lhs, const decNumber *rhs,
61645796c8dcSSimon Schubert Flag abs) {
61655796c8dcSSimon Schubert Int result; /* result value */
61665796c8dcSSimon Schubert Int sigr; /* rhs signum */
61675796c8dcSSimon Schubert Int compare; /* work */
61685796c8dcSSimon Schubert
61695796c8dcSSimon Schubert result=1; /* assume signum(lhs) */
61705796c8dcSSimon Schubert if (ISZERO(lhs)) result=0;
61715796c8dcSSimon Schubert if (abs) {
61725796c8dcSSimon Schubert if (ISZERO(rhs)) return result; /* LHS wins or both 0 */
61735796c8dcSSimon Schubert /* RHS is non-zero */
61745796c8dcSSimon Schubert if (result==0) return -1; /* LHS is 0; RHS wins */
61755796c8dcSSimon Schubert /* [here, both non-zero, result=1] */
61765796c8dcSSimon Schubert }
61775796c8dcSSimon Schubert else { /* signs matter */
61785796c8dcSSimon Schubert if (result && decNumberIsNegative(lhs)) result=-1;
61795796c8dcSSimon Schubert sigr=1; /* compute signum(rhs) */
61805796c8dcSSimon Schubert if (ISZERO(rhs)) sigr=0;
61815796c8dcSSimon Schubert else if (decNumberIsNegative(rhs)) sigr=-1;
61825796c8dcSSimon Schubert if (result > sigr) return +1; /* L > R, return 1 */
61835796c8dcSSimon Schubert if (result < sigr) return -1; /* L < R, return -1 */
61845796c8dcSSimon Schubert if (result==0) return 0; /* both 0 */
61855796c8dcSSimon Schubert }
61865796c8dcSSimon Schubert
61875796c8dcSSimon Schubert /* signums are the same; both are non-zero */
61885796c8dcSSimon Schubert if ((lhs->bits | rhs->bits) & DECINF) { /* one or more infinities */
61895796c8dcSSimon Schubert if (decNumberIsInfinite(rhs)) {
61905796c8dcSSimon Schubert if (decNumberIsInfinite(lhs)) result=0;/* both infinite */
61915796c8dcSSimon Schubert else result=-result; /* only rhs infinite */
61925796c8dcSSimon Schubert }
61935796c8dcSSimon Schubert return result;
61945796c8dcSSimon Schubert }
61955796c8dcSSimon Schubert /* must compare the coefficients, allowing for exponents */
61965796c8dcSSimon Schubert if (lhs->exponent>rhs->exponent) { /* LHS exponent larger */
61975796c8dcSSimon Schubert /* swap sides, and sign */
61985796c8dcSSimon Schubert const decNumber *temp=lhs;
61995796c8dcSSimon Schubert lhs=rhs;
62005796c8dcSSimon Schubert rhs=temp;
62015796c8dcSSimon Schubert result=-result;
62025796c8dcSSimon Schubert }
62035796c8dcSSimon Schubert compare=decUnitCompare(lhs->lsu, D2U(lhs->digits),
62045796c8dcSSimon Schubert rhs->lsu, D2U(rhs->digits),
62055796c8dcSSimon Schubert rhs->exponent-lhs->exponent);
62065796c8dcSSimon Schubert if (compare!=BADINT) compare*=result; /* comparison succeeded */
62075796c8dcSSimon Schubert return compare;
62085796c8dcSSimon Schubert } /* decCompare */
62095796c8dcSSimon Schubert
62105796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
62115796c8dcSSimon Schubert /* decUnitCompare -- compare two >=0 integers in Unit arrays */
62125796c8dcSSimon Schubert /* */
62135796c8dcSSimon Schubert /* This routine compares A ? B*10**E where A and B are unit arrays */
62145796c8dcSSimon Schubert /* A is a plain integer */
62155796c8dcSSimon Schubert /* B has an exponent of E (which must be non-negative) */
62165796c8dcSSimon Schubert /* */
62175796c8dcSSimon Schubert /* Arg1 is A first Unit (lsu) */
62185796c8dcSSimon Schubert /* Arg2 is A length in Units */
62195796c8dcSSimon Schubert /* Arg3 is B first Unit (lsu) */
62205796c8dcSSimon Schubert /* Arg4 is B length in Units */
62215796c8dcSSimon Schubert /* Arg5 is E (0 if the units are aligned) */
62225796c8dcSSimon Schubert /* */
62235796c8dcSSimon Schubert /* returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure */
62245796c8dcSSimon Schubert /* (the only possible failure is an allocation error, which can */
62255796c8dcSSimon Schubert /* only occur if E!=0) */
62265796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
62275796c8dcSSimon Schubert static Int decUnitCompare(const Unit *a, Int alength,
62285796c8dcSSimon Schubert const Unit *b, Int blength, Int exp) {
62295796c8dcSSimon Schubert Unit *acc; /* accumulator for result */
62305796c8dcSSimon Schubert Unit accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */
62315796c8dcSSimon Schubert Unit *allocacc=NULL; /* -> allocated acc buffer, iff allocated */
62325796c8dcSSimon Schubert Int accunits, need; /* units in use or needed for acc */
62335796c8dcSSimon Schubert const Unit *l, *r, *u; /* work */
62345796c8dcSSimon Schubert Int expunits, exprem, result; /* .. */
62355796c8dcSSimon Schubert
62365796c8dcSSimon Schubert if (exp==0) { /* aligned; fastpath */
62375796c8dcSSimon Schubert if (alength>blength) return 1;
62385796c8dcSSimon Schubert if (alength<blength) return -1;
62395796c8dcSSimon Schubert /* same number of units in both -- need unit-by-unit compare */
62405796c8dcSSimon Schubert l=a+alength-1;
62415796c8dcSSimon Schubert r=b+alength-1;
62425796c8dcSSimon Schubert for (;l>=a; l--, r--) {
62435796c8dcSSimon Schubert if (*l>*r) return 1;
62445796c8dcSSimon Schubert if (*l<*r) return -1;
62455796c8dcSSimon Schubert }
62465796c8dcSSimon Schubert return 0; /* all units match */
62475796c8dcSSimon Schubert } /* aligned */
62485796c8dcSSimon Schubert
62495796c8dcSSimon Schubert /* Unaligned. If one is >1 unit longer than the other, padded */
62505796c8dcSSimon Schubert /* approximately, then can return easily */
62515796c8dcSSimon Schubert if (alength>blength+(Int)D2U(exp)) return 1;
62525796c8dcSSimon Schubert if (alength+1<blength+(Int)D2U(exp)) return -1;
62535796c8dcSSimon Schubert
62545796c8dcSSimon Schubert /* Need to do a real subtract. For this, a result buffer is needed */
62555796c8dcSSimon Schubert /* even though only the sign is of interest. Its length needs */
62565796c8dcSSimon Schubert /* to be the larger of alength and padded blength, +2 */
62575796c8dcSSimon Schubert need=blength+D2U(exp); /* maximum real length of B */
62585796c8dcSSimon Schubert if (need<alength) need=alength;
62595796c8dcSSimon Schubert need+=2;
62605796c8dcSSimon Schubert acc=accbuff; /* assume use local buffer */
62615796c8dcSSimon Schubert if (need*sizeof(Unit)>sizeof(accbuff)) {
62625796c8dcSSimon Schubert allocacc=(Unit *)malloc(need*sizeof(Unit));
62635796c8dcSSimon Schubert if (allocacc==NULL) return BADINT; /* hopeless -- abandon */
62645796c8dcSSimon Schubert acc=allocacc;
62655796c8dcSSimon Schubert }
62665796c8dcSSimon Schubert /* Calculate units and remainder from exponent. */
62675796c8dcSSimon Schubert expunits=exp/DECDPUN;
62685796c8dcSSimon Schubert exprem=exp%DECDPUN;
62695796c8dcSSimon Schubert /* subtract [A+B*(-m)] */
62705796c8dcSSimon Schubert accunits=decUnitAddSub(a, alength, b, blength, expunits, acc,
62715796c8dcSSimon Schubert -(Int)powers[exprem]);
62725796c8dcSSimon Schubert /* [UnitAddSub result may have leading zeros, even on zero] */
62735796c8dcSSimon Schubert if (accunits<0) result=-1; /* negative result */
62745796c8dcSSimon Schubert else { /* non-negative result */
62755796c8dcSSimon Schubert /* check units of the result before freeing any storage */
62765796c8dcSSimon Schubert for (u=acc; u<acc+accunits-1 && *u==0;) u++;
62775796c8dcSSimon Schubert result=(*u==0 ? 0 : +1);
62785796c8dcSSimon Schubert }
62795796c8dcSSimon Schubert /* clean up and return the result */
6280a45ae5f8SJohn Marino free(allocacc); /* drop any storage used */
62815796c8dcSSimon Schubert return result;
62825796c8dcSSimon Schubert } /* decUnitCompare */
62835796c8dcSSimon Schubert
62845796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
62855796c8dcSSimon Schubert /* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays */
62865796c8dcSSimon Schubert /* */
62875796c8dcSSimon Schubert /* This routine performs the calculation: */
62885796c8dcSSimon Schubert /* */
62895796c8dcSSimon Schubert /* C=A+(B*M) */
62905796c8dcSSimon Schubert /* */
62915796c8dcSSimon Schubert /* Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */
62925796c8dcSSimon Schubert /* */
62935796c8dcSSimon Schubert /* A may be shorter or longer than B. */
62945796c8dcSSimon Schubert /* */
62955796c8dcSSimon Schubert /* Leading zeros are not removed after a calculation. The result is */
62965796c8dcSSimon Schubert /* either the same length as the longer of A and B (adding any */
62975796c8dcSSimon Schubert /* shift), or one Unit longer than that (if a Unit carry occurred). */
62985796c8dcSSimon Schubert /* */
62995796c8dcSSimon Schubert /* A and B content are not altered unless C is also A or B. */
63005796c8dcSSimon Schubert /* C may be the same array as A or B, but only if no zero padding is */
63015796c8dcSSimon Schubert /* requested (that is, C may be B only if bshift==0). */
63025796c8dcSSimon Schubert /* C is filled from the lsu; only those units necessary to complete */
63035796c8dcSSimon Schubert /* the calculation are referenced. */
63045796c8dcSSimon Schubert /* */
63055796c8dcSSimon Schubert /* Arg1 is A first Unit (lsu) */
63065796c8dcSSimon Schubert /* Arg2 is A length in Units */
63075796c8dcSSimon Schubert /* Arg3 is B first Unit (lsu) */
63085796c8dcSSimon Schubert /* Arg4 is B length in Units */
63095796c8dcSSimon Schubert /* Arg5 is B shift in Units (>=0; pads with 0 units if positive) */
63105796c8dcSSimon Schubert /* Arg6 is C first Unit (lsu) */
63115796c8dcSSimon Schubert /* Arg7 is M, the multiplier */
63125796c8dcSSimon Schubert /* */
63135796c8dcSSimon Schubert /* returns the count of Units written to C, which will be non-zero */
63145796c8dcSSimon Schubert /* and negated if the result is negative. That is, the sign of the */
63155796c8dcSSimon Schubert /* returned Int is the sign of the result (positive for zero) and */
63165796c8dcSSimon Schubert /* the absolute value of the Int is the count of Units. */
63175796c8dcSSimon Schubert /* */
63185796c8dcSSimon Schubert /* It is the caller's responsibility to make sure that C size is */
63195796c8dcSSimon Schubert /* safe, allowing space if necessary for a one-Unit carry. */
63205796c8dcSSimon Schubert /* */
63215796c8dcSSimon Schubert /* This routine is severely performance-critical; *any* change here */
63225796c8dcSSimon Schubert /* must be measured (timed) to assure no performance degradation. */
63235796c8dcSSimon Schubert /* In particular, trickery here tends to be counter-productive, as */
63245796c8dcSSimon Schubert /* increased complexity of code hurts register optimizations on */
63255796c8dcSSimon Schubert /* register-poor architectures. Avoiding divisions is nearly */
63265796c8dcSSimon Schubert /* always a Good Idea, however. */
63275796c8dcSSimon Schubert /* */
63285796c8dcSSimon Schubert /* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark */
63295796c8dcSSimon Schubert /* (IBM Warwick, UK) for some of the ideas used in this routine. */
63305796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
63315796c8dcSSimon Schubert static Int decUnitAddSub(const Unit *a, Int alength,
63325796c8dcSSimon Schubert const Unit *b, Int blength, Int bshift,
63335796c8dcSSimon Schubert Unit *c, Int m) {
63345796c8dcSSimon Schubert const Unit *alsu=a; /* A lsu [need to remember it] */
63355796c8dcSSimon Schubert Unit *clsu=c; /* C ditto */
63365796c8dcSSimon Schubert Unit *minC; /* low water mark for C */
63375796c8dcSSimon Schubert Unit *maxC; /* high water mark for C */
63385796c8dcSSimon Schubert eInt carry=0; /* carry integer (could be Long) */
63395796c8dcSSimon Schubert Int add; /* work */
63405796c8dcSSimon Schubert #if DECDPUN<=4 /* myriadal, millenary, etc. */
63415796c8dcSSimon Schubert Int est; /* estimated quotient */
63425796c8dcSSimon Schubert #endif
63435796c8dcSSimon Schubert
63445796c8dcSSimon Schubert #if DECTRACE
63455796c8dcSSimon Schubert if (alength<1 || blength<1)
63465796c8dcSSimon Schubert printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m);
63475796c8dcSSimon Schubert #endif
63485796c8dcSSimon Schubert
63495796c8dcSSimon Schubert maxC=c+alength; /* A is usually the longer */
63505796c8dcSSimon Schubert minC=c+blength; /* .. and B the shorter */
63515796c8dcSSimon Schubert if (bshift!=0) { /* B is shifted; low As copy across */
63525796c8dcSSimon Schubert minC+=bshift;
63535796c8dcSSimon Schubert /* if in place [common], skip copy unless there's a gap [rare] */
63545796c8dcSSimon Schubert if (a==c && bshift<=alength) {
63555796c8dcSSimon Schubert c+=bshift;
63565796c8dcSSimon Schubert a+=bshift;
63575796c8dcSSimon Schubert }
63585796c8dcSSimon Schubert else for (; c<clsu+bshift; a++, c++) { /* copy needed */
63595796c8dcSSimon Schubert if (a<alsu+alength) *c=*a;
63605796c8dcSSimon Schubert else *c=0;
63615796c8dcSSimon Schubert }
63625796c8dcSSimon Schubert }
63635796c8dcSSimon Schubert if (minC>maxC) { /* swap */
63645796c8dcSSimon Schubert Unit *hold=minC;
63655796c8dcSSimon Schubert minC=maxC;
63665796c8dcSSimon Schubert maxC=hold;
63675796c8dcSSimon Schubert }
63685796c8dcSSimon Schubert
63695796c8dcSSimon Schubert /* For speed, do the addition as two loops; the first where both A */
63705796c8dcSSimon Schubert /* and B contribute, and the second (if necessary) where only one or */
63715796c8dcSSimon Schubert /* other of the numbers contribute. */
63725796c8dcSSimon Schubert /* Carry handling is the same (i.e., duplicated) in each case. */
63735796c8dcSSimon Schubert for (; c<minC; c++) {
63745796c8dcSSimon Schubert carry+=*a;
63755796c8dcSSimon Schubert a++;
63765796c8dcSSimon Schubert carry+=((eInt)*b)*m; /* [special-casing m=1/-1 */
63775796c8dcSSimon Schubert b++; /* here is not a win] */
63785796c8dcSSimon Schubert /* here carry is new Unit of digits; it could be +ve or -ve */
63795796c8dcSSimon Schubert if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */
63805796c8dcSSimon Schubert *c=(Unit)carry;
63815796c8dcSSimon Schubert carry=0;
63825796c8dcSSimon Schubert continue;
63835796c8dcSSimon Schubert }
63845796c8dcSSimon Schubert #if DECDPUN==4 /* use divide-by-multiply */
63855796c8dcSSimon Schubert if (carry>=0) {
63865796c8dcSSimon Schubert est=(((ueInt)carry>>11)*53687)>>18;
63875796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
63885796c8dcSSimon Schubert carry=est; /* likely quotient [89%] */
63895796c8dcSSimon Schubert if (*c<DECDPUNMAX+1) continue; /* estimate was correct */
63905796c8dcSSimon Schubert carry++;
63915796c8dcSSimon Schubert *c-=DECDPUNMAX+1;
63925796c8dcSSimon Schubert continue;
63935796c8dcSSimon Schubert }
63945796c8dcSSimon Schubert /* negative case */
63955796c8dcSSimon Schubert carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
63965796c8dcSSimon Schubert est=(((ueInt)carry>>11)*53687)>>18;
63975796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1));
63985796c8dcSSimon Schubert carry=est-(DECDPUNMAX+1); /* correctly negative */
63995796c8dcSSimon Schubert if (*c<DECDPUNMAX+1) continue; /* was OK */
64005796c8dcSSimon Schubert carry++;
64015796c8dcSSimon Schubert *c-=DECDPUNMAX+1;
64025796c8dcSSimon Schubert #elif DECDPUN==3
64035796c8dcSSimon Schubert if (carry>=0) {
64045796c8dcSSimon Schubert est=(((ueInt)carry>>3)*16777)>>21;
64055796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
64065796c8dcSSimon Schubert carry=est; /* likely quotient [99%] */
64075796c8dcSSimon Schubert if (*c<DECDPUNMAX+1) continue; /* estimate was correct */
64085796c8dcSSimon Schubert carry++;
64095796c8dcSSimon Schubert *c-=DECDPUNMAX+1;
64105796c8dcSSimon Schubert continue;
64115796c8dcSSimon Schubert }
64125796c8dcSSimon Schubert /* negative case */
64135796c8dcSSimon Schubert carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
64145796c8dcSSimon Schubert est=(((ueInt)carry>>3)*16777)>>21;
64155796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1));
64165796c8dcSSimon Schubert carry=est-(DECDPUNMAX+1); /* correctly negative */
64175796c8dcSSimon Schubert if (*c<DECDPUNMAX+1) continue; /* was OK */
64185796c8dcSSimon Schubert carry++;
64195796c8dcSSimon Schubert *c-=DECDPUNMAX+1;
64205796c8dcSSimon Schubert #elif DECDPUN<=2
64215796c8dcSSimon Schubert /* Can use QUOT10 as carry <= 4 digits */
64225796c8dcSSimon Schubert if (carry>=0) {
64235796c8dcSSimon Schubert est=QUOT10(carry, DECDPUN);
64245796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
64255796c8dcSSimon Schubert carry=est; /* quotient */
64265796c8dcSSimon Schubert continue;
64275796c8dcSSimon Schubert }
64285796c8dcSSimon Schubert /* negative case */
64295796c8dcSSimon Schubert carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
64305796c8dcSSimon Schubert est=QUOT10(carry, DECDPUN);
64315796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1));
64325796c8dcSSimon Schubert carry=est-(DECDPUNMAX+1); /* correctly negative */
64335796c8dcSSimon Schubert #else
64345796c8dcSSimon Schubert /* remainder operator is undefined if negative, so must test */
64355796c8dcSSimon Schubert if ((ueInt)carry<(DECDPUNMAX+1)*2) { /* fastpath carry +1 */
64365796c8dcSSimon Schubert *c=(Unit)(carry-(DECDPUNMAX+1)); /* [helps additions] */
64375796c8dcSSimon Schubert carry=1;
64385796c8dcSSimon Schubert continue;
64395796c8dcSSimon Schubert }
64405796c8dcSSimon Schubert if (carry>=0) {
64415796c8dcSSimon Schubert *c=(Unit)(carry%(DECDPUNMAX+1));
64425796c8dcSSimon Schubert carry=carry/(DECDPUNMAX+1);
64435796c8dcSSimon Schubert continue;
64445796c8dcSSimon Schubert }
64455796c8dcSSimon Schubert /* negative case */
64465796c8dcSSimon Schubert carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
64475796c8dcSSimon Schubert *c=(Unit)(carry%(DECDPUNMAX+1));
64485796c8dcSSimon Schubert carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
64495796c8dcSSimon Schubert #endif
64505796c8dcSSimon Schubert } /* c */
64515796c8dcSSimon Schubert
64525796c8dcSSimon Schubert /* now may have one or other to complete */
64535796c8dcSSimon Schubert /* [pretest to avoid loop setup/shutdown] */
64545796c8dcSSimon Schubert if (c<maxC) for (; c<maxC; c++) {
64555796c8dcSSimon Schubert if (a<alsu+alength) { /* still in A */
64565796c8dcSSimon Schubert carry+=*a;
64575796c8dcSSimon Schubert a++;
64585796c8dcSSimon Schubert }
64595796c8dcSSimon Schubert else { /* inside B */
64605796c8dcSSimon Schubert carry+=((eInt)*b)*m;
64615796c8dcSSimon Schubert b++;
64625796c8dcSSimon Schubert }
64635796c8dcSSimon Schubert /* here carry is new Unit of digits; it could be +ve or -ve and */
64645796c8dcSSimon Schubert /* magnitude up to DECDPUNMAX squared */
64655796c8dcSSimon Schubert if ((ueInt)carry<=DECDPUNMAX) { /* fastpath 0-DECDPUNMAX */
64665796c8dcSSimon Schubert *c=(Unit)carry;
64675796c8dcSSimon Schubert carry=0;
64685796c8dcSSimon Schubert continue;
64695796c8dcSSimon Schubert }
64705796c8dcSSimon Schubert /* result for this unit is negative or >DECDPUNMAX */
64715796c8dcSSimon Schubert #if DECDPUN==4 /* use divide-by-multiply */
64725796c8dcSSimon Schubert if (carry>=0) {
64735796c8dcSSimon Schubert est=(((ueInt)carry>>11)*53687)>>18;
64745796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
64755796c8dcSSimon Schubert carry=est; /* likely quotient [79.7%] */
64765796c8dcSSimon Schubert if (*c<DECDPUNMAX+1) continue; /* estimate was correct */
64775796c8dcSSimon Schubert carry++;
64785796c8dcSSimon Schubert *c-=DECDPUNMAX+1;
64795796c8dcSSimon Schubert continue;
64805796c8dcSSimon Schubert }
64815796c8dcSSimon Schubert /* negative case */
64825796c8dcSSimon Schubert carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
64835796c8dcSSimon Schubert est=(((ueInt)carry>>11)*53687)>>18;
64845796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1));
64855796c8dcSSimon Schubert carry=est-(DECDPUNMAX+1); /* correctly negative */
64865796c8dcSSimon Schubert if (*c<DECDPUNMAX+1) continue; /* was OK */
64875796c8dcSSimon Schubert carry++;
64885796c8dcSSimon Schubert *c-=DECDPUNMAX+1;
64895796c8dcSSimon Schubert #elif DECDPUN==3
64905796c8dcSSimon Schubert if (carry>=0) {
64915796c8dcSSimon Schubert est=(((ueInt)carry>>3)*16777)>>21;
64925796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
64935796c8dcSSimon Schubert carry=est; /* likely quotient [99%] */
64945796c8dcSSimon Schubert if (*c<DECDPUNMAX+1) continue; /* estimate was correct */
64955796c8dcSSimon Schubert carry++;
64965796c8dcSSimon Schubert *c-=DECDPUNMAX+1;
64975796c8dcSSimon Schubert continue;
64985796c8dcSSimon Schubert }
64995796c8dcSSimon Schubert /* negative case */
65005796c8dcSSimon Schubert carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
65015796c8dcSSimon Schubert est=(((ueInt)carry>>3)*16777)>>21;
65025796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1));
65035796c8dcSSimon Schubert carry=est-(DECDPUNMAX+1); /* correctly negative */
65045796c8dcSSimon Schubert if (*c<DECDPUNMAX+1) continue; /* was OK */
65055796c8dcSSimon Schubert carry++;
65065796c8dcSSimon Schubert *c-=DECDPUNMAX+1;
65075796c8dcSSimon Schubert #elif DECDPUN<=2
65085796c8dcSSimon Schubert if (carry>=0) {
65095796c8dcSSimon Schubert est=QUOT10(carry, DECDPUN);
65105796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
65115796c8dcSSimon Schubert carry=est; /* quotient */
65125796c8dcSSimon Schubert continue;
65135796c8dcSSimon Schubert }
65145796c8dcSSimon Schubert /* negative case */
65155796c8dcSSimon Schubert carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
65165796c8dcSSimon Schubert est=QUOT10(carry, DECDPUN);
65175796c8dcSSimon Schubert *c=(Unit)(carry-est*(DECDPUNMAX+1));
65185796c8dcSSimon Schubert carry=est-(DECDPUNMAX+1); /* correctly negative */
65195796c8dcSSimon Schubert #else
65205796c8dcSSimon Schubert if ((ueInt)carry<(DECDPUNMAX+1)*2){ /* fastpath carry 1 */
65215796c8dcSSimon Schubert *c=(Unit)(carry-(DECDPUNMAX+1));
65225796c8dcSSimon Schubert carry=1;
65235796c8dcSSimon Schubert continue;
65245796c8dcSSimon Schubert }
65255796c8dcSSimon Schubert /* remainder operator is undefined if negative, so must test */
65265796c8dcSSimon Schubert if (carry>=0) {
65275796c8dcSSimon Schubert *c=(Unit)(carry%(DECDPUNMAX+1));
65285796c8dcSSimon Schubert carry=carry/(DECDPUNMAX+1);
65295796c8dcSSimon Schubert continue;
65305796c8dcSSimon Schubert }
65315796c8dcSSimon Schubert /* negative case */
65325796c8dcSSimon Schubert carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
65335796c8dcSSimon Schubert *c=(Unit)(carry%(DECDPUNMAX+1));
65345796c8dcSSimon Schubert carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
65355796c8dcSSimon Schubert #endif
65365796c8dcSSimon Schubert } /* c */
65375796c8dcSSimon Schubert
65385796c8dcSSimon Schubert /* OK, all A and B processed; might still have carry or borrow */
65395796c8dcSSimon Schubert /* return number of Units in the result, negated if a borrow */
65405796c8dcSSimon Schubert if (carry==0) return c-clsu; /* no carry, so no more to do */
65415796c8dcSSimon Schubert if (carry>0) { /* positive carry */
65425796c8dcSSimon Schubert *c=(Unit)carry; /* place as new unit */
65435796c8dcSSimon Schubert c++; /* .. */
65445796c8dcSSimon Schubert return c-clsu;
65455796c8dcSSimon Schubert }
65465796c8dcSSimon Schubert /* -ve carry: it's a borrow; complement needed */
65475796c8dcSSimon Schubert add=1; /* temporary carry... */
65485796c8dcSSimon Schubert for (c=clsu; c<maxC; c++) {
65495796c8dcSSimon Schubert add=DECDPUNMAX+add-*c;
65505796c8dcSSimon Schubert if (add<=DECDPUNMAX) {
65515796c8dcSSimon Schubert *c=(Unit)add;
65525796c8dcSSimon Schubert add=0;
65535796c8dcSSimon Schubert }
65545796c8dcSSimon Schubert else {
65555796c8dcSSimon Schubert *c=0;
65565796c8dcSSimon Schubert add=1;
65575796c8dcSSimon Schubert }
65585796c8dcSSimon Schubert }
65595796c8dcSSimon Schubert /* add an extra unit iff it would be non-zero */
65605796c8dcSSimon Schubert #if DECTRACE
65615796c8dcSSimon Schubert printf("UAS borrow: add %ld, carry %ld\n", add, carry);
65625796c8dcSSimon Schubert #endif
65635796c8dcSSimon Schubert if ((add-carry-1)!=0) {
65645796c8dcSSimon Schubert *c=(Unit)(add-carry-1);
65655796c8dcSSimon Schubert c++; /* interesting, include it */
65665796c8dcSSimon Schubert }
65675796c8dcSSimon Schubert return clsu-c; /* -ve result indicates borrowed */
65685796c8dcSSimon Schubert } /* decUnitAddSub */
65695796c8dcSSimon Schubert
65705796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
65715796c8dcSSimon Schubert /* decTrim -- trim trailing zeros or normalize */
65725796c8dcSSimon Schubert /* */
65735796c8dcSSimon Schubert /* dn is the number to trim or normalize */
65745796c8dcSSimon Schubert /* set is the context to use to check for clamp */
65755796c8dcSSimon Schubert /* all is 1 to remove all trailing zeros, 0 for just fraction ones */
65765796c8dcSSimon Schubert /* noclamp is 1 to unconditional (unclamped) trim */
65775796c8dcSSimon Schubert /* dropped returns the number of discarded trailing zeros */
65785796c8dcSSimon Schubert /* returns dn */
65795796c8dcSSimon Schubert /* */
65805796c8dcSSimon Schubert /* If clamp is set in the context then the number of zeros trimmed */
65815796c8dcSSimon Schubert /* may be limited if the exponent is high. */
65825796c8dcSSimon Schubert /* All fields are updated as required. This is a utility operation, */
65835796c8dcSSimon Schubert /* so special values are unchanged and no error is possible. */
65845796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
65855796c8dcSSimon Schubert static decNumber * decTrim(decNumber *dn, decContext *set, Flag all,
65865796c8dcSSimon Schubert Flag noclamp, Int *dropped) {
65875796c8dcSSimon Schubert Int d, exp; /* work */
65885796c8dcSSimon Schubert uInt cut; /* .. */
65895796c8dcSSimon Schubert Unit *up; /* -> current Unit */
65905796c8dcSSimon Schubert
65915796c8dcSSimon Schubert #if DECCHECK
65925796c8dcSSimon Schubert if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
65935796c8dcSSimon Schubert #endif
65945796c8dcSSimon Schubert
65955796c8dcSSimon Schubert *dropped=0; /* assume no zeros dropped */
65965796c8dcSSimon Schubert if ((dn->bits & DECSPECIAL) /* fast exit if special .. */
65975796c8dcSSimon Schubert || (*dn->lsu & 0x01)) return dn; /* .. or odd */
65985796c8dcSSimon Schubert if (ISZERO(dn)) { /* .. or 0 */
65995796c8dcSSimon Schubert dn->exponent=0; /* (sign is preserved) */
66005796c8dcSSimon Schubert return dn;
66015796c8dcSSimon Schubert }
66025796c8dcSSimon Schubert
66035796c8dcSSimon Schubert /* have a finite number which is even */
66045796c8dcSSimon Schubert exp=dn->exponent;
66055796c8dcSSimon Schubert cut=1; /* digit (1-DECDPUN) in Unit */
66065796c8dcSSimon Schubert up=dn->lsu; /* -> current Unit */
66075796c8dcSSimon Schubert for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */
66085796c8dcSSimon Schubert /* slice by powers */
66095796c8dcSSimon Schubert #if DECDPUN<=4
66105796c8dcSSimon Schubert uInt quot=QUOT10(*up, cut);
66115796c8dcSSimon Schubert if ((*up-quot*powers[cut])!=0) break; /* found non-0 digit */
66125796c8dcSSimon Schubert #else
66135796c8dcSSimon Schubert if (*up%powers[cut]!=0) break; /* found non-0 digit */
66145796c8dcSSimon Schubert #endif
66155796c8dcSSimon Schubert /* have a trailing 0 */
66165796c8dcSSimon Schubert if (!all) { /* trimming */
66175796c8dcSSimon Schubert /* [if exp>0 then all trailing 0s are significant for trim] */
66185796c8dcSSimon Schubert if (exp<=0) { /* if digit might be significant */
66195796c8dcSSimon Schubert if (exp==0) break; /* then quit */
66205796c8dcSSimon Schubert exp++; /* next digit might be significant */
66215796c8dcSSimon Schubert }
66225796c8dcSSimon Schubert }
66235796c8dcSSimon Schubert cut++; /* next power */
66245796c8dcSSimon Schubert if (cut>DECDPUN) { /* need new Unit */
66255796c8dcSSimon Schubert up++;
66265796c8dcSSimon Schubert cut=1;
66275796c8dcSSimon Schubert }
66285796c8dcSSimon Schubert } /* d */
66295796c8dcSSimon Schubert if (d==0) return dn; /* none to drop */
66305796c8dcSSimon Schubert
66315796c8dcSSimon Schubert /* may need to limit drop if clamping */
66325796c8dcSSimon Schubert if (set->clamp && !noclamp) {
66335796c8dcSSimon Schubert Int maxd=set->emax-set->digits+1-dn->exponent;
66345796c8dcSSimon Schubert if (maxd<=0) return dn; /* nothing possible */
66355796c8dcSSimon Schubert if (d>maxd) d=maxd;
66365796c8dcSSimon Schubert }
66375796c8dcSSimon Schubert
66385796c8dcSSimon Schubert /* effect the drop */
66395796c8dcSSimon Schubert decShiftToLeast(dn->lsu, D2U(dn->digits), d);
66405796c8dcSSimon Schubert dn->exponent+=d; /* maintain numerical value */
66415796c8dcSSimon Schubert dn->digits-=d; /* new length */
66425796c8dcSSimon Schubert *dropped=d; /* report the count */
66435796c8dcSSimon Schubert return dn;
66445796c8dcSSimon Schubert } /* decTrim */
66455796c8dcSSimon Schubert
66465796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
66475796c8dcSSimon Schubert /* decReverse -- reverse a Unit array in place */
66485796c8dcSSimon Schubert /* */
66495796c8dcSSimon Schubert /* ulo is the start of the array */
66505796c8dcSSimon Schubert /* uhi is the end of the array (highest Unit to include) */
66515796c8dcSSimon Schubert /* */
66525796c8dcSSimon Schubert /* The units ulo through uhi are reversed in place (if the number */
66535796c8dcSSimon Schubert /* of units is odd, the middle one is untouched). Note that the */
66545796c8dcSSimon Schubert /* digit(s) in each unit are unaffected. */
66555796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
66565796c8dcSSimon Schubert static void decReverse(Unit *ulo, Unit *uhi) {
66575796c8dcSSimon Schubert Unit temp;
66585796c8dcSSimon Schubert for (; ulo<uhi; ulo++, uhi--) {
66595796c8dcSSimon Schubert temp=*ulo;
66605796c8dcSSimon Schubert *ulo=*uhi;
66615796c8dcSSimon Schubert *uhi=temp;
66625796c8dcSSimon Schubert }
66635796c8dcSSimon Schubert return;
66645796c8dcSSimon Schubert } /* decReverse */
66655796c8dcSSimon Schubert
66665796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
66675796c8dcSSimon Schubert /* decShiftToMost -- shift digits in array towards most significant */
66685796c8dcSSimon Schubert /* */
66695796c8dcSSimon Schubert /* uar is the array */
66705796c8dcSSimon Schubert /* digits is the count of digits in use in the array */
66715796c8dcSSimon Schubert /* shift is the number of zeros to pad with (least significant); */
66725796c8dcSSimon Schubert /* it must be zero or positive */
66735796c8dcSSimon Schubert /* */
66745796c8dcSSimon Schubert /* returns the new length of the integer in the array, in digits */
66755796c8dcSSimon Schubert /* */
66765796c8dcSSimon Schubert /* No overflow is permitted (that is, the uar array must be known to */
66775796c8dcSSimon Schubert /* be large enough to hold the result, after shifting). */
66785796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
66795796c8dcSSimon Schubert static Int decShiftToMost(Unit *uar, Int digits, Int shift) {
66805796c8dcSSimon Schubert Unit *target, *source, *first; /* work */
66815796c8dcSSimon Schubert Int cut; /* odd 0's to add */
66825796c8dcSSimon Schubert uInt next; /* work */
66835796c8dcSSimon Schubert
66845796c8dcSSimon Schubert if (shift==0) return digits; /* [fastpath] nothing to do */
66855796c8dcSSimon Schubert if ((digits+shift)<=DECDPUN) { /* [fastpath] single-unit case */
66865796c8dcSSimon Schubert *uar=(Unit)(*uar*powers[shift]);
66875796c8dcSSimon Schubert return digits+shift;
66885796c8dcSSimon Schubert }
66895796c8dcSSimon Schubert
66905796c8dcSSimon Schubert next=0; /* all paths */
66915796c8dcSSimon Schubert source=uar+D2U(digits)-1; /* where msu comes from */
66925796c8dcSSimon Schubert target=source+D2U(shift); /* where upper part of first cut goes */
66935796c8dcSSimon Schubert cut=DECDPUN-MSUDIGITS(shift); /* where to slice */
66945796c8dcSSimon Schubert if (cut==0) { /* unit-boundary case */
66955796c8dcSSimon Schubert for (; source>=uar; source--, target--) *target=*source;
66965796c8dcSSimon Schubert }
66975796c8dcSSimon Schubert else {
66985796c8dcSSimon Schubert first=uar+D2U(digits+shift)-1; /* where msu of source will end up */
66995796c8dcSSimon Schubert for (; source>=uar; source--, target--) {
67005796c8dcSSimon Schubert /* split the source Unit and accumulate remainder for next */
67015796c8dcSSimon Schubert #if DECDPUN<=4
67025796c8dcSSimon Schubert uInt quot=QUOT10(*source, cut);
67035796c8dcSSimon Schubert uInt rem=*source-quot*powers[cut];
67045796c8dcSSimon Schubert next+=quot;
67055796c8dcSSimon Schubert #else
67065796c8dcSSimon Schubert uInt rem=*source%powers[cut];
67075796c8dcSSimon Schubert next+=*source/powers[cut];
67085796c8dcSSimon Schubert #endif
67095796c8dcSSimon Schubert if (target<=first) *target=(Unit)next; /* write to target iff valid */
67105796c8dcSSimon Schubert next=rem*powers[DECDPUN-cut]; /* save remainder for next Unit */
67115796c8dcSSimon Schubert }
67125796c8dcSSimon Schubert } /* shift-move */
67135796c8dcSSimon Schubert
67145796c8dcSSimon Schubert /* propagate any partial unit to one below and clear the rest */
67155796c8dcSSimon Schubert for (; target>=uar; target--) {
67165796c8dcSSimon Schubert *target=(Unit)next;
67175796c8dcSSimon Schubert next=0;
67185796c8dcSSimon Schubert }
67195796c8dcSSimon Schubert return digits+shift;
67205796c8dcSSimon Schubert } /* decShiftToMost */
67215796c8dcSSimon Schubert
67225796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
67235796c8dcSSimon Schubert /* decShiftToLeast -- shift digits in array towards least significant */
67245796c8dcSSimon Schubert /* */
67255796c8dcSSimon Schubert /* uar is the array */
67265796c8dcSSimon Schubert /* units is length of the array, in units */
67275796c8dcSSimon Schubert /* shift is the number of digits to remove from the lsu end; it */
67285796c8dcSSimon Schubert /* must be zero or positive and <= than units*DECDPUN. */
67295796c8dcSSimon Schubert /* */
67305796c8dcSSimon Schubert /* returns the new length of the integer in the array, in units */
67315796c8dcSSimon Schubert /* */
67325796c8dcSSimon Schubert /* Removed digits are discarded (lost). Units not required to hold */
67335796c8dcSSimon Schubert /* the final result are unchanged. */
67345796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
67355796c8dcSSimon Schubert static Int decShiftToLeast(Unit *uar, Int units, Int shift) {
67365796c8dcSSimon Schubert Unit *target, *up; /* work */
67375796c8dcSSimon Schubert Int cut, count; /* work */
67385796c8dcSSimon Schubert Int quot, rem; /* for division */
67395796c8dcSSimon Schubert
67405796c8dcSSimon Schubert if (shift==0) return units; /* [fastpath] nothing to do */
67415796c8dcSSimon Schubert if (shift==units*DECDPUN) { /* [fastpath] little to do */
67425796c8dcSSimon Schubert *uar=0; /* all digits cleared gives zero */
67435796c8dcSSimon Schubert return 1; /* leaves just the one */
67445796c8dcSSimon Schubert }
67455796c8dcSSimon Schubert
67465796c8dcSSimon Schubert target=uar; /* both paths */
67475796c8dcSSimon Schubert cut=MSUDIGITS(shift);
67485796c8dcSSimon Schubert if (cut==DECDPUN) { /* unit-boundary case; easy */
67495796c8dcSSimon Schubert up=uar+D2U(shift);
67505796c8dcSSimon Schubert for (; up<uar+units; target++, up++) *target=*up;
67515796c8dcSSimon Schubert return target-uar;
67525796c8dcSSimon Schubert }
67535796c8dcSSimon Schubert
67545796c8dcSSimon Schubert /* messier */
67555796c8dcSSimon Schubert up=uar+D2U(shift-cut); /* source; correct to whole Units */
67565796c8dcSSimon Schubert count=units*DECDPUN-shift; /* the maximum new length */
67575796c8dcSSimon Schubert #if DECDPUN<=4
67585796c8dcSSimon Schubert quot=QUOT10(*up, cut);
67595796c8dcSSimon Schubert #else
67605796c8dcSSimon Schubert quot=*up/powers[cut];
67615796c8dcSSimon Schubert #endif
67625796c8dcSSimon Schubert for (; ; target++) {
67635796c8dcSSimon Schubert *target=(Unit)quot;
67645796c8dcSSimon Schubert count-=(DECDPUN-cut);
67655796c8dcSSimon Schubert if (count<=0) break;
67665796c8dcSSimon Schubert up++;
67675796c8dcSSimon Schubert quot=*up;
67685796c8dcSSimon Schubert #if DECDPUN<=4
67695796c8dcSSimon Schubert quot=QUOT10(quot, cut);
67705796c8dcSSimon Schubert rem=*up-quot*powers[cut];
67715796c8dcSSimon Schubert #else
67725796c8dcSSimon Schubert rem=quot%powers[cut];
67735796c8dcSSimon Schubert quot=quot/powers[cut];
67745796c8dcSSimon Schubert #endif
67755796c8dcSSimon Schubert *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
67765796c8dcSSimon Schubert count-=cut;
67775796c8dcSSimon Schubert if (count<=0) break;
67785796c8dcSSimon Schubert }
67795796c8dcSSimon Schubert return target-uar+1;
67805796c8dcSSimon Schubert } /* decShiftToLeast */
67815796c8dcSSimon Schubert
67825796c8dcSSimon Schubert #if DECSUBSET
67835796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
67845796c8dcSSimon Schubert /* decRoundOperand -- round an operand [used for subset only] */
67855796c8dcSSimon Schubert /* */
67865796c8dcSSimon Schubert /* dn is the number to round (dn->digits is > set->digits) */
67875796c8dcSSimon Schubert /* set is the relevant context */
67885796c8dcSSimon Schubert /* status is the status accumulator */
67895796c8dcSSimon Schubert /* */
67905796c8dcSSimon Schubert /* returns an allocated decNumber with the rounded result. */
67915796c8dcSSimon Schubert /* */
67925796c8dcSSimon Schubert /* lostDigits and other status may be set by this. */
67935796c8dcSSimon Schubert /* */
67945796c8dcSSimon Schubert /* Since the input is an operand, it must not be modified. */
67955796c8dcSSimon Schubert /* Instead, return an allocated decNumber, rounded as required. */
67965796c8dcSSimon Schubert /* It is the caller's responsibility to free the allocated storage. */
67975796c8dcSSimon Schubert /* */
67985796c8dcSSimon Schubert /* If no storage is available then the result cannot be used, so NULL */
67995796c8dcSSimon Schubert /* is returned. */
68005796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
68015796c8dcSSimon Schubert static decNumber *decRoundOperand(const decNumber *dn, decContext *set,
68025796c8dcSSimon Schubert uInt *status) {
68035796c8dcSSimon Schubert decNumber *res; /* result structure */
68045796c8dcSSimon Schubert uInt newstatus=0; /* status from round */
68055796c8dcSSimon Schubert Int residue=0; /* rounding accumulator */
68065796c8dcSSimon Schubert
68075796c8dcSSimon Schubert /* Allocate storage for the returned decNumber, big enough for the */
68085796c8dcSSimon Schubert /* length specified by the context */
68095796c8dcSSimon Schubert res=(decNumber *)malloc(sizeof(decNumber)
68105796c8dcSSimon Schubert +(D2U(set->digits)-1)*sizeof(Unit));
68115796c8dcSSimon Schubert if (res==NULL) {
68125796c8dcSSimon Schubert *status|=DEC_Insufficient_storage;
68135796c8dcSSimon Schubert return NULL;
68145796c8dcSSimon Schubert }
68155796c8dcSSimon Schubert decCopyFit(res, dn, set, &residue, &newstatus);
68165796c8dcSSimon Schubert decApplyRound(res, set, residue, &newstatus);
68175796c8dcSSimon Schubert
68185796c8dcSSimon Schubert /* If that set Inexact then "lost digits" is raised... */
68195796c8dcSSimon Schubert if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits;
68205796c8dcSSimon Schubert *status|=newstatus;
68215796c8dcSSimon Schubert return res;
68225796c8dcSSimon Schubert } /* decRoundOperand */
68235796c8dcSSimon Schubert #endif
68245796c8dcSSimon Schubert
68255796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
68265796c8dcSSimon Schubert /* decCopyFit -- copy a number, truncating the coefficient if needed */
68275796c8dcSSimon Schubert /* */
68285796c8dcSSimon Schubert /* dest is the target decNumber */
68295796c8dcSSimon Schubert /* src is the source decNumber */
68305796c8dcSSimon Schubert /* set is the context [used for length (digits) and rounding mode] */
68315796c8dcSSimon Schubert /* residue is the residue accumulator */
68325796c8dcSSimon Schubert /* status contains the current status to be updated */
68335796c8dcSSimon Schubert /* */
68345796c8dcSSimon Schubert /* (dest==src is allowed and will be a no-op if fits) */
68355796c8dcSSimon Schubert /* All fields are updated as required. */
68365796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
68375796c8dcSSimon Schubert static void decCopyFit(decNumber *dest, const decNumber *src,
68385796c8dcSSimon Schubert decContext *set, Int *residue, uInt *status) {
68395796c8dcSSimon Schubert dest->bits=src->bits;
68405796c8dcSSimon Schubert dest->exponent=src->exponent;
68415796c8dcSSimon Schubert decSetCoeff(dest, set, src->lsu, src->digits, residue, status);
68425796c8dcSSimon Schubert } /* decCopyFit */
68435796c8dcSSimon Schubert
68445796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
68455796c8dcSSimon Schubert /* decSetCoeff -- set the coefficient of a number */
68465796c8dcSSimon Schubert /* */
68475796c8dcSSimon Schubert /* dn is the number whose coefficient array is to be set. */
68485796c8dcSSimon Schubert /* It must have space for set->digits digits */
68495796c8dcSSimon Schubert /* set is the context [for size] */
68505796c8dcSSimon Schubert /* lsu -> lsu of the source coefficient [may be dn->lsu] */
68515796c8dcSSimon Schubert /* len is digits in the source coefficient [may be dn->digits] */
68525796c8dcSSimon Schubert /* residue is the residue accumulator. This has values as in */
68535796c8dcSSimon Schubert /* decApplyRound, and will be unchanged unless the */
68545796c8dcSSimon Schubert /* target size is less than len. In this case, the */
68555796c8dcSSimon Schubert /* coefficient is truncated and the residue is updated to */
68565796c8dcSSimon Schubert /* reflect the previous residue and the dropped digits. */
68575796c8dcSSimon Schubert /* status is the status accumulator, as usual */
68585796c8dcSSimon Schubert /* */
68595796c8dcSSimon Schubert /* The coefficient may already be in the number, or it can be an */
68605796c8dcSSimon Schubert /* external intermediate array. If it is in the number, lsu must == */
68615796c8dcSSimon Schubert /* dn->lsu and len must == dn->digits. */
68625796c8dcSSimon Schubert /* */
68635796c8dcSSimon Schubert /* Note that the coefficient length (len) may be < set->digits, and */
68645796c8dcSSimon Schubert /* in this case this merely copies the coefficient (or is a no-op */
68655796c8dcSSimon Schubert /* if dn->lsu==lsu). */
68665796c8dcSSimon Schubert /* */
68675796c8dcSSimon Schubert /* Note also that (only internally, from decQuantizeOp and */
68685796c8dcSSimon Schubert /* decSetSubnormal) the value of set->digits may be less than one, */
68695796c8dcSSimon Schubert /* indicating a round to left. This routine handles that case */
68705796c8dcSSimon Schubert /* correctly; caller ensures space. */
68715796c8dcSSimon Schubert /* */
68725796c8dcSSimon Schubert /* dn->digits, dn->lsu (and as required), and dn->exponent are */
68735796c8dcSSimon Schubert /* updated as necessary. dn->bits (sign) is unchanged. */
68745796c8dcSSimon Schubert /* */
68755796c8dcSSimon Schubert /* DEC_Rounded status is set if any digits are discarded. */
68765796c8dcSSimon Schubert /* DEC_Inexact status is set if any non-zero digits are discarded, or */
68775796c8dcSSimon Schubert /* incoming residue was non-0 (implies rounded) */
68785796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
68795796c8dcSSimon Schubert /* mapping array: maps 0-9 to canonical residues, so that a residue */
68805796c8dcSSimon Schubert /* can be adjusted in the range [-1, +1] and achieve correct rounding */
68815796c8dcSSimon Schubert /* 0 1 2 3 4 5 6 7 8 9 */
68825796c8dcSSimon Schubert static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7};
68835796c8dcSSimon Schubert static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu,
68845796c8dcSSimon Schubert Int len, Int *residue, uInt *status) {
68855796c8dcSSimon Schubert Int discard; /* number of digits to discard */
68865796c8dcSSimon Schubert uInt cut; /* cut point in Unit */
68875796c8dcSSimon Schubert const Unit *up; /* work */
68885796c8dcSSimon Schubert Unit *target; /* .. */
68895796c8dcSSimon Schubert Int count; /* .. */
68905796c8dcSSimon Schubert #if DECDPUN<=4
68915796c8dcSSimon Schubert uInt temp; /* .. */
68925796c8dcSSimon Schubert #endif
68935796c8dcSSimon Schubert
68945796c8dcSSimon Schubert discard=len-set->digits; /* digits to discard */
68955796c8dcSSimon Schubert if (discard<=0) { /* no digits are being discarded */
68965796c8dcSSimon Schubert if (dn->lsu!=lsu) { /* copy needed */
68975796c8dcSSimon Schubert /* copy the coefficient array to the result number; no shift needed */
68985796c8dcSSimon Schubert count=len; /* avoids D2U */
68995796c8dcSSimon Schubert up=lsu;
69005796c8dcSSimon Schubert for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
69015796c8dcSSimon Schubert *target=*up;
69025796c8dcSSimon Schubert dn->digits=len; /* set the new length */
69035796c8dcSSimon Schubert }
69045796c8dcSSimon Schubert /* dn->exponent and residue are unchanged, record any inexactitude */
69055796c8dcSSimon Schubert if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded);
69065796c8dcSSimon Schubert return;
69075796c8dcSSimon Schubert }
69085796c8dcSSimon Schubert
69095796c8dcSSimon Schubert /* some digits must be discarded ... */
69105796c8dcSSimon Schubert dn->exponent+=discard; /* maintain numerical value */
69115796c8dcSSimon Schubert *status|=DEC_Rounded; /* accumulate Rounded status */
69125796c8dcSSimon Schubert if (*residue>1) *residue=1; /* previous residue now to right, so reduce */
69135796c8dcSSimon Schubert
69145796c8dcSSimon Schubert if (discard>len) { /* everything, +1, is being discarded */
69155796c8dcSSimon Schubert /* guard digit is 0 */
69165796c8dcSSimon Schubert /* residue is all the number [NB could be all 0s] */
69175796c8dcSSimon Schubert if (*residue<=0) { /* not already positive */
69185796c8dcSSimon Schubert count=len; /* avoids D2U */
69195796c8dcSSimon Schubert for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */
69205796c8dcSSimon Schubert *residue=1;
69215796c8dcSSimon Schubert break; /* no need to check any others */
69225796c8dcSSimon Schubert }
69235796c8dcSSimon Schubert }
69245796c8dcSSimon Schubert if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
69255796c8dcSSimon Schubert *dn->lsu=0; /* coefficient will now be 0 */
69265796c8dcSSimon Schubert dn->digits=1; /* .. */
69275796c8dcSSimon Schubert return;
69285796c8dcSSimon Schubert } /* total discard */
69295796c8dcSSimon Schubert
69305796c8dcSSimon Schubert /* partial discard [most common case] */
69315796c8dcSSimon Schubert /* here, at least the first (most significant) discarded digit exists */
69325796c8dcSSimon Schubert
69335796c8dcSSimon Schubert /* spin up the number, noting residue during the spin, until get to */
69345796c8dcSSimon Schubert /* the Unit with the first discarded digit. When reach it, extract */
69355796c8dcSSimon Schubert /* it and remember its position */
69365796c8dcSSimon Schubert count=0;
69375796c8dcSSimon Schubert for (up=lsu;; up++) {
69385796c8dcSSimon Schubert count+=DECDPUN;
69395796c8dcSSimon Schubert if (count>=discard) break; /* full ones all checked */
69405796c8dcSSimon Schubert if (*up!=0) *residue=1;
69415796c8dcSSimon Schubert } /* up */
69425796c8dcSSimon Schubert
69435796c8dcSSimon Schubert /* here up -> Unit with first discarded digit */
69445796c8dcSSimon Schubert cut=discard-(count-DECDPUN)-1;
69455796c8dcSSimon Schubert if (cut==DECDPUN-1) { /* unit-boundary case (fast) */
69465796c8dcSSimon Schubert Unit half=(Unit)powers[DECDPUN]>>1;
69475796c8dcSSimon Schubert /* set residue directly */
69485796c8dcSSimon Schubert if (*up>=half) {
69495796c8dcSSimon Schubert if (*up>half) *residue=7;
69505796c8dcSSimon Schubert else *residue+=5; /* add sticky bit */
69515796c8dcSSimon Schubert }
69525796c8dcSSimon Schubert else { /* <half */
69535796c8dcSSimon Schubert if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */
69545796c8dcSSimon Schubert }
69555796c8dcSSimon Schubert if (set->digits<=0) { /* special for Quantize/Subnormal :-( */
69565796c8dcSSimon Schubert *dn->lsu=0; /* .. result is 0 */
69575796c8dcSSimon Schubert dn->digits=1; /* .. */
69585796c8dcSSimon Schubert }
69595796c8dcSSimon Schubert else { /* shift to least */
69605796c8dcSSimon Schubert count=set->digits; /* now digits to end up with */
69615796c8dcSSimon Schubert dn->digits=count; /* set the new length */
69625796c8dcSSimon Schubert up++; /* move to next */
69635796c8dcSSimon Schubert /* on unit boundary, so shift-down copy loop is simple */
69645796c8dcSSimon Schubert for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
69655796c8dcSSimon Schubert *target=*up;
69665796c8dcSSimon Schubert }
69675796c8dcSSimon Schubert } /* unit-boundary case */
69685796c8dcSSimon Schubert
69695796c8dcSSimon Schubert else { /* discard digit is in low digit(s), and not top digit */
69705796c8dcSSimon Schubert uInt discard1; /* first discarded digit */
69715796c8dcSSimon Schubert uInt quot, rem; /* for divisions */
69725796c8dcSSimon Schubert if (cut==0) quot=*up; /* is at bottom of unit */
69735796c8dcSSimon Schubert else /* cut>0 */ { /* it's not at bottom of unit */
69745796c8dcSSimon Schubert #if DECDPUN<=4
69755796c8dcSSimon Schubert quot=QUOT10(*up, cut);
69765796c8dcSSimon Schubert rem=*up-quot*powers[cut];
69775796c8dcSSimon Schubert #else
69785796c8dcSSimon Schubert rem=*up%powers[cut];
69795796c8dcSSimon Schubert quot=*up/powers[cut];
69805796c8dcSSimon Schubert #endif
69815796c8dcSSimon Schubert if (rem!=0) *residue=1;
69825796c8dcSSimon Schubert }
69835796c8dcSSimon Schubert /* discard digit is now at bottom of quot */
69845796c8dcSSimon Schubert #if DECDPUN<=4
69855796c8dcSSimon Schubert temp=(quot*6554)>>16; /* fast /10 */
69865796c8dcSSimon Schubert /* Vowels algorithm here not a win (9 instructions) */
69875796c8dcSSimon Schubert discard1=quot-X10(temp);
69885796c8dcSSimon Schubert quot=temp;
69895796c8dcSSimon Schubert #else
69905796c8dcSSimon Schubert discard1=quot%10;
69915796c8dcSSimon Schubert quot=quot/10;
69925796c8dcSSimon Schubert #endif
69935796c8dcSSimon Schubert /* here, discard1 is the guard digit, and residue is everything */
69945796c8dcSSimon Schubert /* else [use mapping array to accumulate residue safely] */
69955796c8dcSSimon Schubert *residue+=resmap[discard1];
69965796c8dcSSimon Schubert cut++; /* update cut */
69975796c8dcSSimon Schubert /* here: up -> Unit of the array with bottom digit */
69985796c8dcSSimon Schubert /* cut is the division point for each Unit */
69995796c8dcSSimon Schubert /* quot holds the uncut high-order digits for the current unit */
70005796c8dcSSimon Schubert if (set->digits<=0) { /* special for Quantize/Subnormal :-( */
70015796c8dcSSimon Schubert *dn->lsu=0; /* .. result is 0 */
70025796c8dcSSimon Schubert dn->digits=1; /* .. */
70035796c8dcSSimon Schubert }
70045796c8dcSSimon Schubert else { /* shift to least needed */
70055796c8dcSSimon Schubert count=set->digits; /* now digits to end up with */
70065796c8dcSSimon Schubert dn->digits=count; /* set the new length */
70075796c8dcSSimon Schubert /* shift-copy the coefficient array to the result number */
70085796c8dcSSimon Schubert for (target=dn->lsu; ; target++) {
70095796c8dcSSimon Schubert *target=(Unit)quot;
70105796c8dcSSimon Schubert count-=(DECDPUN-cut);
70115796c8dcSSimon Schubert if (count<=0) break;
70125796c8dcSSimon Schubert up++;
70135796c8dcSSimon Schubert quot=*up;
70145796c8dcSSimon Schubert #if DECDPUN<=4
70155796c8dcSSimon Schubert quot=QUOT10(quot, cut);
70165796c8dcSSimon Schubert rem=*up-quot*powers[cut];
70175796c8dcSSimon Schubert #else
70185796c8dcSSimon Schubert rem=quot%powers[cut];
70195796c8dcSSimon Schubert quot=quot/powers[cut];
70205796c8dcSSimon Schubert #endif
70215796c8dcSSimon Schubert *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
70225796c8dcSSimon Schubert count-=cut;
70235796c8dcSSimon Schubert if (count<=0) break;
70245796c8dcSSimon Schubert } /* shift-copy loop */
70255796c8dcSSimon Schubert } /* shift to least */
70265796c8dcSSimon Schubert } /* not unit boundary */
70275796c8dcSSimon Schubert
70285796c8dcSSimon Schubert if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
70295796c8dcSSimon Schubert return;
70305796c8dcSSimon Schubert } /* decSetCoeff */
70315796c8dcSSimon Schubert
70325796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
70335796c8dcSSimon Schubert /* decApplyRound -- apply pending rounding to a number */
70345796c8dcSSimon Schubert /* */
70355796c8dcSSimon Schubert /* dn is the number, with space for set->digits digits */
70365796c8dcSSimon Schubert /* set is the context [for size and rounding mode] */
70375796c8dcSSimon Schubert /* residue indicates pending rounding, being any accumulated */
70385796c8dcSSimon Schubert /* guard and sticky information. It may be: */
70395796c8dcSSimon Schubert /* 6-9: rounding digit is >5 */
70405796c8dcSSimon Schubert /* 5: rounding digit is exactly half-way */
70415796c8dcSSimon Schubert /* 1-4: rounding digit is <5 and >0 */
70425796c8dcSSimon Schubert /* 0: the coefficient is exact */
70435796c8dcSSimon Schubert /* -1: as 1, but the hidden digits are subtractive, that */
70445796c8dcSSimon Schubert /* is, of the opposite sign to dn. In this case the */
70455796c8dcSSimon Schubert /* coefficient must be non-0. This case occurs when */
70465796c8dcSSimon Schubert /* subtracting a small number (which can be reduced to */
70475796c8dcSSimon Schubert /* a sticky bit); see decAddOp. */
70485796c8dcSSimon Schubert /* status is the status accumulator, as usual */
70495796c8dcSSimon Schubert /* */
70505796c8dcSSimon Schubert /* This routine applies rounding while keeping the length of the */
70515796c8dcSSimon Schubert /* coefficient constant. The exponent and status are unchanged */
70525796c8dcSSimon Schubert /* except if: */
70535796c8dcSSimon Schubert /* */
70545796c8dcSSimon Schubert /* -- the coefficient was increased and is all nines (in which */
70555796c8dcSSimon Schubert /* case Overflow could occur, and is handled directly here so */
70565796c8dcSSimon Schubert /* the caller does not need to re-test for overflow) */
70575796c8dcSSimon Schubert /* */
70585796c8dcSSimon Schubert /* -- the coefficient was decreased and becomes all nines (in which */
70595796c8dcSSimon Schubert /* case Underflow could occur, and is also handled directly). */
70605796c8dcSSimon Schubert /* */
70615796c8dcSSimon Schubert /* All fields in dn are updated as required. */
70625796c8dcSSimon Schubert /* */
70635796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
70645796c8dcSSimon Schubert static void decApplyRound(decNumber *dn, decContext *set, Int residue,
70655796c8dcSSimon Schubert uInt *status) {
70665796c8dcSSimon Schubert Int bump; /* 1 if coefficient needs to be incremented */
70675796c8dcSSimon Schubert /* -1 if coefficient needs to be decremented */
70685796c8dcSSimon Schubert
70695796c8dcSSimon Schubert if (residue==0) return; /* nothing to apply */
70705796c8dcSSimon Schubert
70715796c8dcSSimon Schubert bump=0; /* assume a smooth ride */
70725796c8dcSSimon Schubert
70735796c8dcSSimon Schubert /* now decide whether, and how, to round, depending on mode */
70745796c8dcSSimon Schubert switch (set->round) {
70755796c8dcSSimon Schubert case DEC_ROUND_05UP: { /* round zero or five up (for reround) */
70765796c8dcSSimon Schubert /* This is the same as DEC_ROUND_DOWN unless there is a */
70775796c8dcSSimon Schubert /* positive residue and the lsd of dn is 0 or 5, in which case */
70785796c8dcSSimon Schubert /* it is bumped; when residue is <0, the number is therefore */
70795796c8dcSSimon Schubert /* bumped down unless the final digit was 1 or 6 (in which */
70805796c8dcSSimon Schubert /* case it is bumped down and then up -- a no-op) */
70815796c8dcSSimon Schubert Int lsd5=*dn->lsu%5; /* get lsd and quintate */
70825796c8dcSSimon Schubert if (residue<0 && lsd5!=1) bump=-1;
70835796c8dcSSimon Schubert else if (residue>0 && lsd5==0) bump=1;
70845796c8dcSSimon Schubert /* [bump==1 could be applied directly; use common path for clarity] */
70855796c8dcSSimon Schubert break;} /* r-05 */
70865796c8dcSSimon Schubert
70875796c8dcSSimon Schubert case DEC_ROUND_DOWN: {
70885796c8dcSSimon Schubert /* no change, except if negative residue */
70895796c8dcSSimon Schubert if (residue<0) bump=-1;
70905796c8dcSSimon Schubert break;} /* r-d */
70915796c8dcSSimon Schubert
70925796c8dcSSimon Schubert case DEC_ROUND_HALF_DOWN: {
70935796c8dcSSimon Schubert if (residue>5) bump=1;
70945796c8dcSSimon Schubert break;} /* r-h-d */
70955796c8dcSSimon Schubert
70965796c8dcSSimon Schubert case DEC_ROUND_HALF_EVEN: {
70975796c8dcSSimon Schubert if (residue>5) bump=1; /* >0.5 goes up */
70985796c8dcSSimon Schubert else if (residue==5) { /* exactly 0.5000... */
70995796c8dcSSimon Schubert /* 0.5 goes up iff [new] lsd is odd */
71005796c8dcSSimon Schubert if (*dn->lsu & 0x01) bump=1;
71015796c8dcSSimon Schubert }
71025796c8dcSSimon Schubert break;} /* r-h-e */
71035796c8dcSSimon Schubert
71045796c8dcSSimon Schubert case DEC_ROUND_HALF_UP: {
71055796c8dcSSimon Schubert if (residue>=5) bump=1;
71065796c8dcSSimon Schubert break;} /* r-h-u */
71075796c8dcSSimon Schubert
71085796c8dcSSimon Schubert case DEC_ROUND_UP: {
71095796c8dcSSimon Schubert if (residue>0) bump=1;
71105796c8dcSSimon Schubert break;} /* r-u */
71115796c8dcSSimon Schubert
71125796c8dcSSimon Schubert case DEC_ROUND_CEILING: {
71135796c8dcSSimon Schubert /* same as _UP for positive numbers, and as _DOWN for negatives */
71145796c8dcSSimon Schubert /* [negative residue cannot occur on 0] */
71155796c8dcSSimon Schubert if (decNumberIsNegative(dn)) {
71165796c8dcSSimon Schubert if (residue<0) bump=-1;
71175796c8dcSSimon Schubert }
71185796c8dcSSimon Schubert else {
71195796c8dcSSimon Schubert if (residue>0) bump=1;
71205796c8dcSSimon Schubert }
71215796c8dcSSimon Schubert break;} /* r-c */
71225796c8dcSSimon Schubert
71235796c8dcSSimon Schubert case DEC_ROUND_FLOOR: {
71245796c8dcSSimon Schubert /* same as _UP for negative numbers, and as _DOWN for positive */
71255796c8dcSSimon Schubert /* [negative residue cannot occur on 0] */
71265796c8dcSSimon Schubert if (!decNumberIsNegative(dn)) {
71275796c8dcSSimon Schubert if (residue<0) bump=-1;
71285796c8dcSSimon Schubert }
71295796c8dcSSimon Schubert else {
71305796c8dcSSimon Schubert if (residue>0) bump=1;
71315796c8dcSSimon Schubert }
71325796c8dcSSimon Schubert break;} /* r-f */
71335796c8dcSSimon Schubert
71345796c8dcSSimon Schubert default: { /* e.g., DEC_ROUND_MAX */
71355796c8dcSSimon Schubert *status|=DEC_Invalid_context;
71365796c8dcSSimon Schubert #if DECTRACE || (DECCHECK && DECVERB)
71375796c8dcSSimon Schubert printf("Unknown rounding mode: %d\n", set->round);
71385796c8dcSSimon Schubert #endif
71395796c8dcSSimon Schubert break;}
71405796c8dcSSimon Schubert } /* switch */
71415796c8dcSSimon Schubert
71425796c8dcSSimon Schubert /* now bump the number, up or down, if need be */
71435796c8dcSSimon Schubert if (bump==0) return; /* no action required */
71445796c8dcSSimon Schubert
71455796c8dcSSimon Schubert /* Simply use decUnitAddSub unless bumping up and the number is */
71465796c8dcSSimon Schubert /* all nines. In this special case set to 100... explicitly */
71475796c8dcSSimon Schubert /* and adjust the exponent by one (as otherwise could overflow */
71485796c8dcSSimon Schubert /* the array) */
71495796c8dcSSimon Schubert /* Similarly handle all-nines result if bumping down. */
71505796c8dcSSimon Schubert if (bump>0) {
71515796c8dcSSimon Schubert Unit *up; /* work */
71525796c8dcSSimon Schubert uInt count=dn->digits; /* digits to be checked */
71535796c8dcSSimon Schubert for (up=dn->lsu; ; up++) {
71545796c8dcSSimon Schubert if (count<=DECDPUN) {
71555796c8dcSSimon Schubert /* this is the last Unit (the msu) */
71565796c8dcSSimon Schubert if (*up!=powers[count]-1) break; /* not still 9s */
71575796c8dcSSimon Schubert /* here if it, too, is all nines */
71585796c8dcSSimon Schubert *up=(Unit)powers[count-1]; /* here 999 -> 100 etc. */
71595796c8dcSSimon Schubert for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */
71605796c8dcSSimon Schubert dn->exponent++; /* and bump exponent */
71615796c8dcSSimon Schubert /* [which, very rarely, could cause Overflow...] */
71625796c8dcSSimon Schubert if ((dn->exponent+dn->digits)>set->emax+1) {
71635796c8dcSSimon Schubert decSetOverflow(dn, set, status);
71645796c8dcSSimon Schubert }
71655796c8dcSSimon Schubert return; /* done */
71665796c8dcSSimon Schubert }
71675796c8dcSSimon Schubert /* a full unit to check, with more to come */
71685796c8dcSSimon Schubert if (*up!=DECDPUNMAX) break; /* not still 9s */
71695796c8dcSSimon Schubert count-=DECDPUN;
71705796c8dcSSimon Schubert } /* up */
71715796c8dcSSimon Schubert } /* bump>0 */
71725796c8dcSSimon Schubert else { /* -1 */
71735796c8dcSSimon Schubert /* here checking for a pre-bump of 1000... (leading 1, all */
71745796c8dcSSimon Schubert /* other digits zero) */
71755796c8dcSSimon Schubert Unit *up, *sup; /* work */
71765796c8dcSSimon Schubert uInt count=dn->digits; /* digits to be checked */
71775796c8dcSSimon Schubert for (up=dn->lsu; ; up++) {
71785796c8dcSSimon Schubert if (count<=DECDPUN) {
71795796c8dcSSimon Schubert /* this is the last Unit (the msu) */
71805796c8dcSSimon Schubert if (*up!=powers[count-1]) break; /* not 100.. */
71815796c8dcSSimon Schubert /* here if have the 1000... case */
71825796c8dcSSimon Schubert sup=up; /* save msu pointer */
71835796c8dcSSimon Schubert *up=(Unit)powers[count]-1; /* here 100 in msu -> 999 */
71845796c8dcSSimon Schubert /* others all to all-nines, too */
71855796c8dcSSimon Schubert for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1;
71865796c8dcSSimon Schubert dn->exponent--; /* and bump exponent */
71875796c8dcSSimon Schubert
71885796c8dcSSimon Schubert /* iff the number was at the subnormal boundary (exponent=etiny) */
71895796c8dcSSimon Schubert /* then the exponent is now out of range, so it will in fact get */
71905796c8dcSSimon Schubert /* clamped to etiny and the final 9 dropped. */
71915796c8dcSSimon Schubert /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */
71925796c8dcSSimon Schubert /* dn->exponent, set->digits); */
71935796c8dcSSimon Schubert if (dn->exponent+1==set->emin-set->digits+1) {
71945796c8dcSSimon Schubert if (count==1 && dn->digits==1) *sup=0; /* here 9 -> 0[.9] */
71955796c8dcSSimon Schubert else {
71965796c8dcSSimon Schubert *sup=(Unit)powers[count-1]-1; /* here 999.. in msu -> 99.. */
71975796c8dcSSimon Schubert dn->digits--;
71985796c8dcSSimon Schubert }
71995796c8dcSSimon Schubert dn->exponent++;
72005796c8dcSSimon Schubert *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
72015796c8dcSSimon Schubert }
72025796c8dcSSimon Schubert return; /* done */
72035796c8dcSSimon Schubert }
72045796c8dcSSimon Schubert
72055796c8dcSSimon Schubert /* a full unit to check, with more to come */
72065796c8dcSSimon Schubert if (*up!=0) break; /* not still 0s */
72075796c8dcSSimon Schubert count-=DECDPUN;
72085796c8dcSSimon Schubert } /* up */
72095796c8dcSSimon Schubert
72105796c8dcSSimon Schubert } /* bump<0 */
72115796c8dcSSimon Schubert
72125796c8dcSSimon Schubert /* Actual bump needed. Do it. */
72135796c8dcSSimon Schubert decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump);
72145796c8dcSSimon Schubert } /* decApplyRound */
72155796c8dcSSimon Schubert
72165796c8dcSSimon Schubert #if DECSUBSET
72175796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
72185796c8dcSSimon Schubert /* decFinish -- finish processing a number */
72195796c8dcSSimon Schubert /* */
72205796c8dcSSimon Schubert /* dn is the number */
72215796c8dcSSimon Schubert /* set is the context */
72225796c8dcSSimon Schubert /* residue is the rounding accumulator (as in decApplyRound) */
72235796c8dcSSimon Schubert /* status is the accumulator */
72245796c8dcSSimon Schubert /* */
72255796c8dcSSimon Schubert /* This finishes off the current number by: */
72265796c8dcSSimon Schubert /* 1. If not extended: */
72275796c8dcSSimon Schubert /* a. Converting a zero result to clean '0' */
72285796c8dcSSimon Schubert /* b. Reducing positive exponents to 0, if would fit in digits */
72295796c8dcSSimon Schubert /* 2. Checking for overflow and subnormals (always) */
72305796c8dcSSimon Schubert /* Note this is just Finalize when no subset arithmetic. */
72315796c8dcSSimon Schubert /* All fields are updated as required. */
72325796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
72335796c8dcSSimon Schubert static void decFinish(decNumber *dn, decContext *set, Int *residue,
72345796c8dcSSimon Schubert uInt *status) {
72355796c8dcSSimon Schubert if (!set->extended) {
72365796c8dcSSimon Schubert if ISZERO(dn) { /* value is zero */
72375796c8dcSSimon Schubert dn->exponent=0; /* clean exponent .. */
72385796c8dcSSimon Schubert dn->bits=0; /* .. and sign */
72395796c8dcSSimon Schubert return; /* no error possible */
72405796c8dcSSimon Schubert }
72415796c8dcSSimon Schubert if (dn->exponent>=0) { /* non-negative exponent */
72425796c8dcSSimon Schubert /* >0; reduce to integer if possible */
72435796c8dcSSimon Schubert if (set->digits >= (dn->exponent+dn->digits)) {
72445796c8dcSSimon Schubert dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent);
72455796c8dcSSimon Schubert dn->exponent=0;
72465796c8dcSSimon Schubert }
72475796c8dcSSimon Schubert }
72485796c8dcSSimon Schubert } /* !extended */
72495796c8dcSSimon Schubert
72505796c8dcSSimon Schubert decFinalize(dn, set, residue, status);
72515796c8dcSSimon Schubert } /* decFinish */
72525796c8dcSSimon Schubert #endif
72535796c8dcSSimon Schubert
72545796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
72555796c8dcSSimon Schubert /* decFinalize -- final check, clamp, and round of a number */
72565796c8dcSSimon Schubert /* */
72575796c8dcSSimon Schubert /* dn is the number */
72585796c8dcSSimon Schubert /* set is the context */
72595796c8dcSSimon Schubert /* residue is the rounding accumulator (as in decApplyRound) */
72605796c8dcSSimon Schubert /* status is the status accumulator */
72615796c8dcSSimon Schubert /* */
72625796c8dcSSimon Schubert /* This finishes off the current number by checking for subnormal */
72635796c8dcSSimon Schubert /* results, applying any pending rounding, checking for overflow, */
72645796c8dcSSimon Schubert /* and applying any clamping. */
72655796c8dcSSimon Schubert /* Underflow and overflow conditions are raised as appropriate. */
72665796c8dcSSimon Schubert /* All fields are updated as required. */
72675796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
72685796c8dcSSimon Schubert static void decFinalize(decNumber *dn, decContext *set, Int *residue,
72695796c8dcSSimon Schubert uInt *status) {
72705796c8dcSSimon Schubert Int shift; /* shift needed if clamping */
72715796c8dcSSimon Schubert Int tinyexp=set->emin-dn->digits+1; /* precalculate subnormal boundary */
72725796c8dcSSimon Schubert
72735796c8dcSSimon Schubert /* Must be careful, here, when checking the exponent as the */
72745796c8dcSSimon Schubert /* adjusted exponent could overflow 31 bits [because it may already */
72755796c8dcSSimon Schubert /* be up to twice the expected]. */
72765796c8dcSSimon Schubert
72775796c8dcSSimon Schubert /* First test for subnormal. This must be done before any final */
72785796c8dcSSimon Schubert /* round as the result could be rounded to Nmin or 0. */
72795796c8dcSSimon Schubert if (dn->exponent<=tinyexp) { /* prefilter */
72805796c8dcSSimon Schubert Int comp;
72815796c8dcSSimon Schubert decNumber nmin;
72825796c8dcSSimon Schubert /* A very nasty case here is dn == Nmin and residue<0 */
72835796c8dcSSimon Schubert if (dn->exponent<tinyexp) {
72845796c8dcSSimon Schubert /* Go handle subnormals; this will apply round if needed. */
72855796c8dcSSimon Schubert decSetSubnormal(dn, set, residue, status);
72865796c8dcSSimon Schubert return;
72875796c8dcSSimon Schubert }
72885796c8dcSSimon Schubert /* Equals case: only subnormal if dn=Nmin and negative residue */
72895796c8dcSSimon Schubert decNumberZero(&nmin);
72905796c8dcSSimon Schubert nmin.lsu[0]=1;
72915796c8dcSSimon Schubert nmin.exponent=set->emin;
72925796c8dcSSimon Schubert comp=decCompare(dn, &nmin, 1); /* (signless compare) */
72935796c8dcSSimon Schubert if (comp==BADINT) { /* oops */
72945796c8dcSSimon Schubert *status|=DEC_Insufficient_storage; /* abandon... */
72955796c8dcSSimon Schubert return;
72965796c8dcSSimon Schubert }
72975796c8dcSSimon Schubert if (*residue<0 && comp==0) { /* neg residue and dn==Nmin */
72985796c8dcSSimon Schubert decApplyRound(dn, set, *residue, status); /* might force down */
72995796c8dcSSimon Schubert decSetSubnormal(dn, set, residue, status);
73005796c8dcSSimon Schubert return;
73015796c8dcSSimon Schubert }
73025796c8dcSSimon Schubert }
73035796c8dcSSimon Schubert
73045796c8dcSSimon Schubert /* now apply any pending round (this could raise overflow). */
73055796c8dcSSimon Schubert if (*residue!=0) decApplyRound(dn, set, *residue, status);
73065796c8dcSSimon Schubert
73075796c8dcSSimon Schubert /* Check for overflow [redundant in the 'rare' case] or clamp */
73085796c8dcSSimon Schubert if (dn->exponent<=set->emax-set->digits+1) return; /* neither needed */
73095796c8dcSSimon Schubert
73105796c8dcSSimon Schubert
73115796c8dcSSimon Schubert /* here when might have an overflow or clamp to do */
73125796c8dcSSimon Schubert if (dn->exponent>set->emax-dn->digits+1) { /* too big */
73135796c8dcSSimon Schubert decSetOverflow(dn, set, status);
73145796c8dcSSimon Schubert return;
73155796c8dcSSimon Schubert }
73165796c8dcSSimon Schubert /* here when the result is normal but in clamp range */
73175796c8dcSSimon Schubert if (!set->clamp) return;
73185796c8dcSSimon Schubert
73195796c8dcSSimon Schubert /* here when need to apply the IEEE exponent clamp (fold-down) */
73205796c8dcSSimon Schubert shift=dn->exponent-(set->emax-set->digits+1);
73215796c8dcSSimon Schubert
73225796c8dcSSimon Schubert /* shift coefficient (if non-zero) */
73235796c8dcSSimon Schubert if (!ISZERO(dn)) {
73245796c8dcSSimon Schubert dn->digits=decShiftToMost(dn->lsu, dn->digits, shift);
73255796c8dcSSimon Schubert }
73265796c8dcSSimon Schubert dn->exponent-=shift; /* adjust the exponent to match */
73275796c8dcSSimon Schubert *status|=DEC_Clamped; /* and record the dirty deed */
73285796c8dcSSimon Schubert return;
73295796c8dcSSimon Schubert } /* decFinalize */
73305796c8dcSSimon Schubert
73315796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
73325796c8dcSSimon Schubert /* decSetOverflow -- set number to proper overflow value */
73335796c8dcSSimon Schubert /* */
73345796c8dcSSimon Schubert /* dn is the number (used for sign [only] and result) */
73355796c8dcSSimon Schubert /* set is the context [used for the rounding mode, etc.] */
73365796c8dcSSimon Schubert /* status contains the current status to be updated */
73375796c8dcSSimon Schubert /* */
73385796c8dcSSimon Schubert /* This sets the sign of a number and sets its value to either */
73395796c8dcSSimon Schubert /* Infinity or the maximum finite value, depending on the sign of */
73405796c8dcSSimon Schubert /* dn and the rounding mode, following IEEE 754 rules. */
73415796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
73425796c8dcSSimon Schubert static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) {
73435796c8dcSSimon Schubert Flag needmax=0; /* result is maximum finite value */
73445796c8dcSSimon Schubert uByte sign=dn->bits&DECNEG; /* clean and save sign bit */
73455796c8dcSSimon Schubert
73465796c8dcSSimon Schubert if (ISZERO(dn)) { /* zero does not overflow magnitude */
73475796c8dcSSimon Schubert Int emax=set->emax; /* limit value */
73485796c8dcSSimon Schubert if (set->clamp) emax-=set->digits-1; /* lower if clamping */
73495796c8dcSSimon Schubert if (dn->exponent>emax) { /* clamp required */
73505796c8dcSSimon Schubert dn->exponent=emax;
73515796c8dcSSimon Schubert *status|=DEC_Clamped;
73525796c8dcSSimon Schubert }
73535796c8dcSSimon Schubert return;
73545796c8dcSSimon Schubert }
73555796c8dcSSimon Schubert
73565796c8dcSSimon Schubert decNumberZero(dn);
73575796c8dcSSimon Schubert switch (set->round) {
73585796c8dcSSimon Schubert case DEC_ROUND_DOWN: {
73595796c8dcSSimon Schubert needmax=1; /* never Infinity */
73605796c8dcSSimon Schubert break;} /* r-d */
73615796c8dcSSimon Schubert case DEC_ROUND_05UP: {
73625796c8dcSSimon Schubert needmax=1; /* never Infinity */
73635796c8dcSSimon Schubert break;} /* r-05 */
73645796c8dcSSimon Schubert case DEC_ROUND_CEILING: {
73655796c8dcSSimon Schubert if (sign) needmax=1; /* Infinity if non-negative */
73665796c8dcSSimon Schubert break;} /* r-c */
73675796c8dcSSimon Schubert case DEC_ROUND_FLOOR: {
73685796c8dcSSimon Schubert if (!sign) needmax=1; /* Infinity if negative */
73695796c8dcSSimon Schubert break;} /* r-f */
73705796c8dcSSimon Schubert default: break; /* Infinity in all other cases */
73715796c8dcSSimon Schubert }
73725796c8dcSSimon Schubert if (needmax) {
73735796c8dcSSimon Schubert decSetMaxValue(dn, set);
73745796c8dcSSimon Schubert dn->bits=sign; /* set sign */
73755796c8dcSSimon Schubert }
73765796c8dcSSimon Schubert else dn->bits=sign|DECINF; /* Value is +/-Infinity */
73775796c8dcSSimon Schubert *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded;
73785796c8dcSSimon Schubert } /* decSetOverflow */
73795796c8dcSSimon Schubert
73805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
73815796c8dcSSimon Schubert /* decSetMaxValue -- set number to +Nmax (maximum normal value) */
73825796c8dcSSimon Schubert /* */
73835796c8dcSSimon Schubert /* dn is the number to set */
73845796c8dcSSimon Schubert /* set is the context [used for digits and emax] */
73855796c8dcSSimon Schubert /* */
73865796c8dcSSimon Schubert /* This sets the number to the maximum positive value. */
73875796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
73885796c8dcSSimon Schubert static void decSetMaxValue(decNumber *dn, decContext *set) {
73895796c8dcSSimon Schubert Unit *up; /* work */
73905796c8dcSSimon Schubert Int count=set->digits; /* nines to add */
73915796c8dcSSimon Schubert dn->digits=count;
73925796c8dcSSimon Schubert /* fill in all nines to set maximum value */
73935796c8dcSSimon Schubert for (up=dn->lsu; ; up++) {
73945796c8dcSSimon Schubert if (count>DECDPUN) *up=DECDPUNMAX; /* unit full o'nines */
73955796c8dcSSimon Schubert else { /* this is the msu */
73965796c8dcSSimon Schubert *up=(Unit)(powers[count]-1);
73975796c8dcSSimon Schubert break;
73985796c8dcSSimon Schubert }
73995796c8dcSSimon Schubert count-=DECDPUN; /* filled those digits */
74005796c8dcSSimon Schubert } /* up */
74015796c8dcSSimon Schubert dn->bits=0; /* + sign */
74025796c8dcSSimon Schubert dn->exponent=set->emax-set->digits+1;
74035796c8dcSSimon Schubert } /* decSetMaxValue */
74045796c8dcSSimon Schubert
74055796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
74065796c8dcSSimon Schubert /* decSetSubnormal -- process value whose exponent is <Emin */
74075796c8dcSSimon Schubert /* */
74085796c8dcSSimon Schubert /* dn is the number (used as input as well as output; it may have */
74095796c8dcSSimon Schubert /* an allowed subnormal value, which may need to be rounded) */
74105796c8dcSSimon Schubert /* set is the context [used for the rounding mode] */
74115796c8dcSSimon Schubert /* residue is any pending residue */
74125796c8dcSSimon Schubert /* status contains the current status to be updated */
74135796c8dcSSimon Schubert /* */
74145796c8dcSSimon Schubert /* If subset mode, set result to zero and set Underflow flags. */
74155796c8dcSSimon Schubert /* */
74165796c8dcSSimon Schubert /* Value may be zero with a low exponent; this does not set Subnormal */
74175796c8dcSSimon Schubert /* but the exponent will be clamped to Etiny. */
74185796c8dcSSimon Schubert /* */
74195796c8dcSSimon Schubert /* Otherwise ensure exponent is not out of range, and round as */
74205796c8dcSSimon Schubert /* necessary. Underflow is set if the result is Inexact. */
74215796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
74225796c8dcSSimon Schubert static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
74235796c8dcSSimon Schubert uInt *status) {
74245796c8dcSSimon Schubert decContext workset; /* work */
74255796c8dcSSimon Schubert Int etiny, adjust; /* .. */
74265796c8dcSSimon Schubert
74275796c8dcSSimon Schubert #if DECSUBSET
74285796c8dcSSimon Schubert /* simple set to zero and 'hard underflow' for subset */
74295796c8dcSSimon Schubert if (!set->extended) {
74305796c8dcSSimon Schubert decNumberZero(dn);
74315796c8dcSSimon Schubert /* always full overflow */
74325796c8dcSSimon Schubert *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
74335796c8dcSSimon Schubert return;
74345796c8dcSSimon Schubert }
74355796c8dcSSimon Schubert #endif
74365796c8dcSSimon Schubert
74375796c8dcSSimon Schubert /* Full arithmetic -- allow subnormals, rounded to minimum exponent */
74385796c8dcSSimon Schubert /* (Etiny) if needed */
74395796c8dcSSimon Schubert etiny=set->emin-(set->digits-1); /* smallest allowed exponent */
74405796c8dcSSimon Schubert
74415796c8dcSSimon Schubert if ISZERO(dn) { /* value is zero */
74425796c8dcSSimon Schubert /* residue can never be non-zero here */
74435796c8dcSSimon Schubert #if DECCHECK
74445796c8dcSSimon Schubert if (*residue!=0) {
74455796c8dcSSimon Schubert printf("++ Subnormal 0 residue %ld\n", (LI)*residue);
74465796c8dcSSimon Schubert *status|=DEC_Invalid_operation;
74475796c8dcSSimon Schubert }
74485796c8dcSSimon Schubert #endif
74495796c8dcSSimon Schubert if (dn->exponent<etiny) { /* clamp required */
74505796c8dcSSimon Schubert dn->exponent=etiny;
74515796c8dcSSimon Schubert *status|=DEC_Clamped;
74525796c8dcSSimon Schubert }
74535796c8dcSSimon Schubert return;
74545796c8dcSSimon Schubert }
74555796c8dcSSimon Schubert
74565796c8dcSSimon Schubert *status|=DEC_Subnormal; /* have a non-zero subnormal */
74575796c8dcSSimon Schubert adjust=etiny-dn->exponent; /* calculate digits to remove */
74585796c8dcSSimon Schubert if (adjust<=0) { /* not out of range; unrounded */
74595796c8dcSSimon Schubert /* residue can never be non-zero here, except in the Nmin-residue */
74605796c8dcSSimon Schubert /* case (which is a subnormal result), so can take fast-path here */
74615796c8dcSSimon Schubert /* it may already be inexact (from setting the coefficient) */
74625796c8dcSSimon Schubert if (*status&DEC_Inexact) *status|=DEC_Underflow;
74635796c8dcSSimon Schubert return;
74645796c8dcSSimon Schubert }
74655796c8dcSSimon Schubert
74665796c8dcSSimon Schubert /* adjust>0, so need to rescale the result so exponent becomes Etiny */
74675796c8dcSSimon Schubert /* [this code is similar to that in rescale] */
74685796c8dcSSimon Schubert workset=*set; /* clone rounding, etc. */
74695796c8dcSSimon Schubert workset.digits=dn->digits-adjust; /* set requested length */
74705796c8dcSSimon Schubert workset.emin-=adjust; /* and adjust emin to match */
74715796c8dcSSimon Schubert /* [note that the latter can be <1, here, similar to Rescale case] */
74725796c8dcSSimon Schubert decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status);
74735796c8dcSSimon Schubert decApplyRound(dn, &workset, *residue, status);
74745796c8dcSSimon Schubert
74755796c8dcSSimon Schubert /* Use 754 default rule: Underflow is set iff Inexact */
74765796c8dcSSimon Schubert /* [independent of whether trapped] */
74775796c8dcSSimon Schubert if (*status&DEC_Inexact) *status|=DEC_Underflow;
74785796c8dcSSimon Schubert
74795796c8dcSSimon Schubert /* if rounded up a 999s case, exponent will be off by one; adjust */
74805796c8dcSSimon Schubert /* back if so [it will fit, because it was shortened earlier] */
74815796c8dcSSimon Schubert if (dn->exponent>etiny) {
74825796c8dcSSimon Schubert dn->digits=decShiftToMost(dn->lsu, dn->digits, 1);
74835796c8dcSSimon Schubert dn->exponent--; /* (re)adjust the exponent. */
74845796c8dcSSimon Schubert }
74855796c8dcSSimon Schubert
74865796c8dcSSimon Schubert /* if rounded to zero, it is by definition clamped... */
74875796c8dcSSimon Schubert if (ISZERO(dn)) *status|=DEC_Clamped;
74885796c8dcSSimon Schubert } /* decSetSubnormal */
74895796c8dcSSimon Schubert
74905796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
74915796c8dcSSimon Schubert /* decCheckMath - check entry conditions for a math function */
74925796c8dcSSimon Schubert /* */
74935796c8dcSSimon Schubert /* This checks the context and the operand */
74945796c8dcSSimon Schubert /* */
74955796c8dcSSimon Schubert /* rhs is the operand to check */
74965796c8dcSSimon Schubert /* set is the context to check */
74975796c8dcSSimon Schubert /* status is unchanged if both are good */
74985796c8dcSSimon Schubert /* */
74995796c8dcSSimon Schubert /* returns non-zero if status is changed, 0 otherwise */
75005796c8dcSSimon Schubert /* */
75015796c8dcSSimon Schubert /* Restrictions enforced: */
75025796c8dcSSimon Schubert /* */
75035796c8dcSSimon Schubert /* digits, emax, and -emin in the context must be less than */
75045796c8dcSSimon Schubert /* DEC_MAX_MATH (999999), and A must be within these bounds if */
75055796c8dcSSimon Schubert /* non-zero. Invalid_operation is set in the status if a */
75065796c8dcSSimon Schubert /* restriction is violated. */
75075796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
75085796c8dcSSimon Schubert static uInt decCheckMath(const decNumber *rhs, decContext *set,
75095796c8dcSSimon Schubert uInt *status) {
75105796c8dcSSimon Schubert uInt save=*status; /* record */
75115796c8dcSSimon Schubert if (set->digits>DEC_MAX_MATH
75125796c8dcSSimon Schubert || set->emax>DEC_MAX_MATH
75135796c8dcSSimon Schubert || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context;
75145796c8dcSSimon Schubert else if ((rhs->digits>DEC_MAX_MATH
75155796c8dcSSimon Schubert || rhs->exponent+rhs->digits>DEC_MAX_MATH+1
75165796c8dcSSimon Schubert || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH))
75175796c8dcSSimon Schubert && !ISZERO(rhs)) *status|=DEC_Invalid_operation;
75185796c8dcSSimon Schubert return (*status!=save);
75195796c8dcSSimon Schubert } /* decCheckMath */
75205796c8dcSSimon Schubert
75215796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
75225796c8dcSSimon Schubert /* decGetInt -- get integer from a number */
75235796c8dcSSimon Schubert /* */
75245796c8dcSSimon Schubert /* dn is the number [which will not be altered] */
75255796c8dcSSimon Schubert /* */
75265796c8dcSSimon Schubert /* returns one of: */
75275796c8dcSSimon Schubert /* BADINT if there is a non-zero fraction */
75285796c8dcSSimon Schubert /* the converted integer */
75295796c8dcSSimon Schubert /* BIGEVEN if the integer is even and magnitude > 2*10**9 */
75305796c8dcSSimon Schubert /* BIGODD if the integer is odd and magnitude > 2*10**9 */
75315796c8dcSSimon Schubert /* */
75325796c8dcSSimon Schubert /* This checks and gets a whole number from the input decNumber. */
75335796c8dcSSimon Schubert /* The sign can be determined from dn by the caller when BIGEVEN or */
75345796c8dcSSimon Schubert /* BIGODD is returned. */
75355796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
75365796c8dcSSimon Schubert static Int decGetInt(const decNumber *dn) {
75375796c8dcSSimon Schubert Int theInt; /* result accumulator */
75385796c8dcSSimon Schubert const Unit *up; /* work */
75395796c8dcSSimon Schubert Int got; /* digits (real or not) processed */
75405796c8dcSSimon Schubert Int ilength=dn->digits+dn->exponent; /* integral length */
75415796c8dcSSimon Schubert Flag neg=decNumberIsNegative(dn); /* 1 if -ve */
75425796c8dcSSimon Schubert
75435796c8dcSSimon Schubert /* The number must be an integer that fits in 10 digits */
75445796c8dcSSimon Schubert /* Assert, here, that 10 is enough for any rescale Etiny */
75455796c8dcSSimon Schubert #if DEC_MAX_EMAX > 999999999
75465796c8dcSSimon Schubert #error GetInt may need updating [for Emax]
75475796c8dcSSimon Schubert #endif
75485796c8dcSSimon Schubert #if DEC_MIN_EMIN < -999999999
75495796c8dcSSimon Schubert #error GetInt may need updating [for Emin]
75505796c8dcSSimon Schubert #endif
75515796c8dcSSimon Schubert if (ISZERO(dn)) return 0; /* zeros are OK, with any exponent */
75525796c8dcSSimon Schubert
75535796c8dcSSimon Schubert up=dn->lsu; /* ready for lsu */
75545796c8dcSSimon Schubert theInt=0; /* ready to accumulate */
75555796c8dcSSimon Schubert if (dn->exponent>=0) { /* relatively easy */
75565796c8dcSSimon Schubert /* no fractional part [usual]; allow for positive exponent */
75575796c8dcSSimon Schubert got=dn->exponent;
75585796c8dcSSimon Schubert }
75595796c8dcSSimon Schubert else { /* -ve exponent; some fractional part to check and discard */
75605796c8dcSSimon Schubert Int count=-dn->exponent; /* digits to discard */
75615796c8dcSSimon Schubert /* spin up whole units until reach the Unit with the unit digit */
75625796c8dcSSimon Schubert for (; count>=DECDPUN; up++) {
75635796c8dcSSimon Schubert if (*up!=0) return BADINT; /* non-zero Unit to discard */
75645796c8dcSSimon Schubert count-=DECDPUN;
75655796c8dcSSimon Schubert }
75665796c8dcSSimon Schubert if (count==0) got=0; /* [a multiple of DECDPUN] */
75675796c8dcSSimon Schubert else { /* [not multiple of DECDPUN] */
75685796c8dcSSimon Schubert Int rem; /* work */
75695796c8dcSSimon Schubert /* slice off fraction digits and check for non-zero */
75705796c8dcSSimon Schubert #if DECDPUN<=4
75715796c8dcSSimon Schubert theInt=QUOT10(*up, count);
75725796c8dcSSimon Schubert rem=*up-theInt*powers[count];
75735796c8dcSSimon Schubert #else
75745796c8dcSSimon Schubert rem=*up%powers[count]; /* slice off discards */
75755796c8dcSSimon Schubert theInt=*up/powers[count];
75765796c8dcSSimon Schubert #endif
75775796c8dcSSimon Schubert if (rem!=0) return BADINT; /* non-zero fraction */
75785796c8dcSSimon Schubert /* it looks good */
75795796c8dcSSimon Schubert got=DECDPUN-count; /* number of digits so far */
75805796c8dcSSimon Schubert up++; /* ready for next */
75815796c8dcSSimon Schubert }
75825796c8dcSSimon Schubert }
75835796c8dcSSimon Schubert /* now it's known there's no fractional part */
75845796c8dcSSimon Schubert
75855796c8dcSSimon Schubert /* tricky code now, to accumulate up to 9.3 digits */
75865796c8dcSSimon Schubert if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */
75875796c8dcSSimon Schubert
75885796c8dcSSimon Schubert if (ilength<11) {
75895796c8dcSSimon Schubert Int save=theInt;
75905796c8dcSSimon Schubert /* collect any remaining unit(s) */
75915796c8dcSSimon Schubert for (; got<ilength; up++) {
75925796c8dcSSimon Schubert theInt+=*up*powers[got];
75935796c8dcSSimon Schubert got+=DECDPUN;
75945796c8dcSSimon Schubert }
75955796c8dcSSimon Schubert if (ilength==10) { /* need to check for wrap */
75965796c8dcSSimon Schubert if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11;
75975796c8dcSSimon Schubert /* [that test also disallows the BADINT result case] */
75985796c8dcSSimon Schubert else if (neg && theInt>1999999997) ilength=11;
75995796c8dcSSimon Schubert else if (!neg && theInt>999999999) ilength=11;
76005796c8dcSSimon Schubert if (ilength==11) theInt=save; /* restore correct low bit */
76015796c8dcSSimon Schubert }
76025796c8dcSSimon Schubert }
76035796c8dcSSimon Schubert
76045796c8dcSSimon Schubert if (ilength>10) { /* too big */
76055796c8dcSSimon Schubert if (theInt&1) return BIGODD; /* bottom bit 1 */
76065796c8dcSSimon Schubert return BIGEVEN; /* bottom bit 0 */
76075796c8dcSSimon Schubert }
76085796c8dcSSimon Schubert
76095796c8dcSSimon Schubert if (neg) theInt=-theInt; /* apply sign */
76105796c8dcSSimon Schubert return theInt;
76115796c8dcSSimon Schubert } /* decGetInt */
76125796c8dcSSimon Schubert
76135796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
76145796c8dcSSimon Schubert /* decDecap -- decapitate the coefficient of a number */
76155796c8dcSSimon Schubert /* */
76165796c8dcSSimon Schubert /* dn is the number to be decapitated */
76175796c8dcSSimon Schubert /* drop is the number of digits to be removed from the left of dn; */
76185796c8dcSSimon Schubert /* this must be <= dn->digits (if equal, the coefficient is */
76195796c8dcSSimon Schubert /* set to 0) */
76205796c8dcSSimon Schubert /* */
76215796c8dcSSimon Schubert /* Returns dn; dn->digits will be <= the initial digits less drop */
76225796c8dcSSimon Schubert /* (after removing drop digits there may be leading zero digits */
76235796c8dcSSimon Schubert /* which will also be removed). Only dn->lsu and dn->digits change. */
76245796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
76255796c8dcSSimon Schubert static decNumber *decDecap(decNumber *dn, Int drop) {
76265796c8dcSSimon Schubert Unit *msu; /* -> target cut point */
76275796c8dcSSimon Schubert Int cut; /* work */
76285796c8dcSSimon Schubert if (drop>=dn->digits) { /* losing the whole thing */
76295796c8dcSSimon Schubert #if DECCHECK
76305796c8dcSSimon Schubert if (drop>dn->digits)
76315796c8dcSSimon Schubert printf("decDecap called with drop>digits [%ld>%ld]\n",
76325796c8dcSSimon Schubert (LI)drop, (LI)dn->digits);
76335796c8dcSSimon Schubert #endif
76345796c8dcSSimon Schubert dn->lsu[0]=0;
76355796c8dcSSimon Schubert dn->digits=1;
76365796c8dcSSimon Schubert return dn;
76375796c8dcSSimon Schubert }
76385796c8dcSSimon Schubert msu=dn->lsu+D2U(dn->digits-drop)-1; /* -> likely msu */
76395796c8dcSSimon Schubert cut=MSUDIGITS(dn->digits-drop); /* digits to be in use in msu */
76405796c8dcSSimon Schubert if (cut!=DECDPUN) *msu%=powers[cut]; /* clear left digits */
76415796c8dcSSimon Schubert /* that may have left leading zero digits, so do a proper count... */
76425796c8dcSSimon Schubert dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1);
76435796c8dcSSimon Schubert return dn;
76445796c8dcSSimon Schubert } /* decDecap */
76455796c8dcSSimon Schubert
76465796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
76475796c8dcSSimon Schubert /* decBiStr -- compare string with pairwise options */
76485796c8dcSSimon Schubert /* */
76495796c8dcSSimon Schubert /* targ is the string to compare */
76505796c8dcSSimon Schubert /* str1 is one of the strings to compare against (length may be 0) */
76515796c8dcSSimon Schubert /* str2 is the other; it must be the same length as str1 */
76525796c8dcSSimon Schubert /* */
76535796c8dcSSimon Schubert /* returns 1 if strings compare equal, (that is, it is the same */
76545796c8dcSSimon Schubert /* length as str1 and str2, and each character of targ is in either */
76555796c8dcSSimon Schubert /* str1 or str2 in the corresponding position), or 0 otherwise */
76565796c8dcSSimon Schubert /* */
76575796c8dcSSimon Schubert /* This is used for generic caseless compare, including the awkward */
76585796c8dcSSimon Schubert /* case of the Turkish dotted and dotless Is. Use as (for example): */
76595796c8dcSSimon Schubert /* if (decBiStr(test, "mike", "MIKE")) ... */
76605796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
76615796c8dcSSimon Schubert static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
76625796c8dcSSimon Schubert for (;;targ++, str1++, str2++) {
76635796c8dcSSimon Schubert if (*targ!=*str1 && *targ!=*str2) return 0;
76645796c8dcSSimon Schubert /* *targ has a match in one (or both, if terminator) */
76655796c8dcSSimon Schubert if (*targ=='\0') break;
76665796c8dcSSimon Schubert } /* forever */
76675796c8dcSSimon Schubert return 1;
76685796c8dcSSimon Schubert } /* decBiStr */
76695796c8dcSSimon Schubert
76705796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
76715796c8dcSSimon Schubert /* decNaNs -- handle NaN operand or operands */
76725796c8dcSSimon Schubert /* */
76735796c8dcSSimon Schubert /* res is the result number */
76745796c8dcSSimon Schubert /* lhs is the first operand */
76755796c8dcSSimon Schubert /* rhs is the second operand, or NULL if none */
76765796c8dcSSimon Schubert /* context is used to limit payload length */
76775796c8dcSSimon Schubert /* status contains the current status */
76785796c8dcSSimon Schubert /* returns res in case convenient */
76795796c8dcSSimon Schubert /* */
76805796c8dcSSimon Schubert /* Called when one or both operands is a NaN, and propagates the */
76815796c8dcSSimon Schubert /* appropriate result to res. When an sNaN is found, it is changed */
76825796c8dcSSimon Schubert /* to a qNaN and Invalid operation is set. */
76835796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
76845796c8dcSSimon Schubert static decNumber * decNaNs(decNumber *res, const decNumber *lhs,
76855796c8dcSSimon Schubert const decNumber *rhs, decContext *set,
76865796c8dcSSimon Schubert uInt *status) {
76875796c8dcSSimon Schubert /* This decision tree ends up with LHS being the source pointer, */
76885796c8dcSSimon Schubert /* and status updated if need be */
76895796c8dcSSimon Schubert if (lhs->bits & DECSNAN)
76905796c8dcSSimon Schubert *status|=DEC_Invalid_operation | DEC_sNaN;
76915796c8dcSSimon Schubert else if (rhs==NULL);
76925796c8dcSSimon Schubert else if (rhs->bits & DECSNAN) {
76935796c8dcSSimon Schubert lhs=rhs;
76945796c8dcSSimon Schubert *status|=DEC_Invalid_operation | DEC_sNaN;
76955796c8dcSSimon Schubert }
76965796c8dcSSimon Schubert else if (lhs->bits & DECNAN);
76975796c8dcSSimon Schubert else lhs=rhs;
76985796c8dcSSimon Schubert
76995796c8dcSSimon Schubert /* propagate the payload */
77005796c8dcSSimon Schubert if (lhs->digits<=set->digits) decNumberCopy(res, lhs); /* easy */
77015796c8dcSSimon Schubert else { /* too long */
77025796c8dcSSimon Schubert const Unit *ul;
77035796c8dcSSimon Schubert Unit *ur, *uresp1;
77045796c8dcSSimon Schubert /* copy safe number of units, then decapitate */
77055796c8dcSSimon Schubert res->bits=lhs->bits; /* need sign etc. */
77065796c8dcSSimon Schubert uresp1=res->lsu+D2U(set->digits);
77075796c8dcSSimon Schubert for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul;
77085796c8dcSSimon Schubert res->digits=D2U(set->digits)*DECDPUN;
77095796c8dcSSimon Schubert /* maybe still too long */
77105796c8dcSSimon Schubert if (res->digits>set->digits) decDecap(res, res->digits-set->digits);
77115796c8dcSSimon Schubert }
77125796c8dcSSimon Schubert
77135796c8dcSSimon Schubert res->bits&=~DECSNAN; /* convert any sNaN to NaN, while */
77145796c8dcSSimon Schubert res->bits|=DECNAN; /* .. preserving sign */
77155796c8dcSSimon Schubert res->exponent=0; /* clean exponent */
77165796c8dcSSimon Schubert /* [coefficient was copied/decapitated] */
77175796c8dcSSimon Schubert return res;
77185796c8dcSSimon Schubert } /* decNaNs */
77195796c8dcSSimon Schubert
77205796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
77215796c8dcSSimon Schubert /* decStatus -- apply non-zero status */
77225796c8dcSSimon Schubert /* */
77235796c8dcSSimon Schubert /* dn is the number to set if error */
77245796c8dcSSimon Schubert /* status contains the current status (not yet in context) */
77255796c8dcSSimon Schubert /* set is the context */
77265796c8dcSSimon Schubert /* */
77275796c8dcSSimon Schubert /* If the status is an error status, the number is set to a NaN, */
77285796c8dcSSimon Schubert /* unless the error was an overflow, divide-by-zero, or underflow, */
77295796c8dcSSimon Schubert /* in which case the number will have already been set. */
77305796c8dcSSimon Schubert /* */
77315796c8dcSSimon Schubert /* The context status is then updated with the new status. Note that */
77325796c8dcSSimon Schubert /* this may raise a signal, so control may never return from this */
77335796c8dcSSimon Schubert /* routine (hence resources must be recovered before it is called). */
77345796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
77355796c8dcSSimon Schubert static void decStatus(decNumber *dn, uInt status, decContext *set) {
77365796c8dcSSimon Schubert if (status & DEC_NaNs) { /* error status -> NaN */
77375796c8dcSSimon Schubert /* if cause was an sNaN, clear and propagate [NaN is already set up] */
77385796c8dcSSimon Schubert if (status & DEC_sNaN) status&=~DEC_sNaN;
77395796c8dcSSimon Schubert else {
77405796c8dcSSimon Schubert decNumberZero(dn); /* other error: clean throughout */
77415796c8dcSSimon Schubert dn->bits=DECNAN; /* and make a quiet NaN */
77425796c8dcSSimon Schubert }
77435796c8dcSSimon Schubert }
77445796c8dcSSimon Schubert decContextSetStatus(set, status); /* [may not return] */
77455796c8dcSSimon Schubert return;
77465796c8dcSSimon Schubert } /* decStatus */
77475796c8dcSSimon Schubert
77485796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
77495796c8dcSSimon Schubert /* decGetDigits -- count digits in a Units array */
77505796c8dcSSimon Schubert /* */
77515796c8dcSSimon Schubert /* uar is the Unit array holding the number (this is often an */
77525796c8dcSSimon Schubert /* accumulator of some sort) */
77535796c8dcSSimon Schubert /* len is the length of the array in units [>=1] */
77545796c8dcSSimon Schubert /* */
77555796c8dcSSimon Schubert /* returns the number of (significant) digits in the array */
77565796c8dcSSimon Schubert /* */
77575796c8dcSSimon Schubert /* All leading zeros are excluded, except the last if the array has */
77585796c8dcSSimon Schubert /* only zero Units. */
77595796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
77605796c8dcSSimon Schubert /* This may be called twice during some operations. */
77615796c8dcSSimon Schubert static Int decGetDigits(Unit *uar, Int len) {
77625796c8dcSSimon Schubert Unit *up=uar+(len-1); /* -> msu */
77635796c8dcSSimon Schubert Int digits=(len-1)*DECDPUN+1; /* possible digits excluding msu */
77645796c8dcSSimon Schubert #if DECDPUN>4
77655796c8dcSSimon Schubert uInt const *pow; /* work */
77665796c8dcSSimon Schubert #endif
77675796c8dcSSimon Schubert /* (at least 1 in final msu) */
77685796c8dcSSimon Schubert #if DECCHECK
77695796c8dcSSimon Schubert if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len);
77705796c8dcSSimon Schubert #endif
77715796c8dcSSimon Schubert
77725796c8dcSSimon Schubert for (; up>=uar; up--) {
77735796c8dcSSimon Schubert if (*up==0) { /* unit is all 0s */
77745796c8dcSSimon Schubert if (digits==1) break; /* a zero has one digit */
77755796c8dcSSimon Schubert digits-=DECDPUN; /* adjust for 0 unit */
77765796c8dcSSimon Schubert continue;}
77775796c8dcSSimon Schubert /* found the first (most significant) non-zero Unit */
77785796c8dcSSimon Schubert #if DECDPUN>1 /* not done yet */
77795796c8dcSSimon Schubert if (*up<10) break; /* is 1-9 */
77805796c8dcSSimon Schubert digits++;
77815796c8dcSSimon Schubert #if DECDPUN>2 /* not done yet */
77825796c8dcSSimon Schubert if (*up<100) break; /* is 10-99 */
77835796c8dcSSimon Schubert digits++;
77845796c8dcSSimon Schubert #if DECDPUN>3 /* not done yet */
77855796c8dcSSimon Schubert if (*up<1000) break; /* is 100-999 */
77865796c8dcSSimon Schubert digits++;
77875796c8dcSSimon Schubert #if DECDPUN>4 /* count the rest ... */
77885796c8dcSSimon Schubert for (pow=&powers[4]; *up>=*pow; pow++) digits++;
77895796c8dcSSimon Schubert #endif
77905796c8dcSSimon Schubert #endif
77915796c8dcSSimon Schubert #endif
77925796c8dcSSimon Schubert #endif
77935796c8dcSSimon Schubert break;
77945796c8dcSSimon Schubert } /* up */
77955796c8dcSSimon Schubert return digits;
77965796c8dcSSimon Schubert } /* decGetDigits */
77975796c8dcSSimon Schubert
77985796c8dcSSimon Schubert #if DECTRACE | DECCHECK
77995796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
78005796c8dcSSimon Schubert /* decNumberShow -- display a number [debug aid] */
78015796c8dcSSimon Schubert /* dn is the number to show */
78025796c8dcSSimon Schubert /* */
78035796c8dcSSimon Schubert /* Shows: sign, exponent, coefficient (msu first), digits */
78045796c8dcSSimon Schubert /* or: sign, special-value */
78055796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
78065796c8dcSSimon Schubert /* this is public so other modules can use it */
78075796c8dcSSimon Schubert void decNumberShow(const decNumber *dn) {
78085796c8dcSSimon Schubert const Unit *up; /* work */
78095796c8dcSSimon Schubert uInt u, d; /* .. */
78105796c8dcSSimon Schubert Int cut; /* .. */
78115796c8dcSSimon Schubert char isign='+'; /* main sign */
78125796c8dcSSimon Schubert if (dn==NULL) {
78135796c8dcSSimon Schubert printf("NULL\n");
78145796c8dcSSimon Schubert return;}
78155796c8dcSSimon Schubert if (decNumberIsNegative(dn)) isign='-';
78165796c8dcSSimon Schubert printf(" >> %c ", isign);
78175796c8dcSSimon Schubert if (dn->bits&DECSPECIAL) { /* Is a special value */
78185796c8dcSSimon Schubert if (decNumberIsInfinite(dn)) printf("Infinity");
78195796c8dcSSimon Schubert else { /* a NaN */
78205796c8dcSSimon Schubert if (dn->bits&DECSNAN) printf("sNaN"); /* signalling NaN */
78215796c8dcSSimon Schubert else printf("NaN");
78225796c8dcSSimon Schubert }
78235796c8dcSSimon Schubert /* if coefficient and exponent are 0, no more to do */
78245796c8dcSSimon Schubert if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) {
78255796c8dcSSimon Schubert printf("\n");
78265796c8dcSSimon Schubert return;}
78275796c8dcSSimon Schubert /* drop through to report other information */
78285796c8dcSSimon Schubert printf(" ");
78295796c8dcSSimon Schubert }
78305796c8dcSSimon Schubert
78315796c8dcSSimon Schubert /* now carefully display the coefficient */
78325796c8dcSSimon Schubert up=dn->lsu+D2U(dn->digits)-1; /* msu */
78335796c8dcSSimon Schubert printf("%ld", (LI)*up);
78345796c8dcSSimon Schubert for (up=up-1; up>=dn->lsu; up--) {
78355796c8dcSSimon Schubert u=*up;
78365796c8dcSSimon Schubert printf(":");
78375796c8dcSSimon Schubert for (cut=DECDPUN-1; cut>=0; cut--) {
78385796c8dcSSimon Schubert d=u/powers[cut];
78395796c8dcSSimon Schubert u-=d*powers[cut];
78405796c8dcSSimon Schubert printf("%ld", (LI)d);
78415796c8dcSSimon Schubert } /* cut */
78425796c8dcSSimon Schubert } /* up */
78435796c8dcSSimon Schubert if (dn->exponent!=0) {
78445796c8dcSSimon Schubert char esign='+';
78455796c8dcSSimon Schubert if (dn->exponent<0) esign='-';
78465796c8dcSSimon Schubert printf(" E%c%ld", esign, (LI)abs(dn->exponent));
78475796c8dcSSimon Schubert }
78485796c8dcSSimon Schubert printf(" [%ld]\n", (LI)dn->digits);
78495796c8dcSSimon Schubert } /* decNumberShow */
78505796c8dcSSimon Schubert #endif
78515796c8dcSSimon Schubert
78525796c8dcSSimon Schubert #if DECTRACE || DECCHECK
78535796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
78545796c8dcSSimon Schubert /* decDumpAr -- display a unit array [debug/check aid] */
78555796c8dcSSimon Schubert /* name is a single-character tag name */
78565796c8dcSSimon Schubert /* ar is the array to display */
78575796c8dcSSimon Schubert /* len is the length of the array in Units */
78585796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
78595796c8dcSSimon Schubert static void decDumpAr(char name, const Unit *ar, Int len) {
78605796c8dcSSimon Schubert Int i;
78615796c8dcSSimon Schubert const char *spec;
78625796c8dcSSimon Schubert #if DECDPUN==9
78635796c8dcSSimon Schubert spec="%09d ";
78645796c8dcSSimon Schubert #elif DECDPUN==8
78655796c8dcSSimon Schubert spec="%08d ";
78665796c8dcSSimon Schubert #elif DECDPUN==7
78675796c8dcSSimon Schubert spec="%07d ";
78685796c8dcSSimon Schubert #elif DECDPUN==6
78695796c8dcSSimon Schubert spec="%06d ";
78705796c8dcSSimon Schubert #elif DECDPUN==5
78715796c8dcSSimon Schubert spec="%05d ";
78725796c8dcSSimon Schubert #elif DECDPUN==4
78735796c8dcSSimon Schubert spec="%04d ";
78745796c8dcSSimon Schubert #elif DECDPUN==3
78755796c8dcSSimon Schubert spec="%03d ";
78765796c8dcSSimon Schubert #elif DECDPUN==2
78775796c8dcSSimon Schubert spec="%02d ";
78785796c8dcSSimon Schubert #else
78795796c8dcSSimon Schubert spec="%d ";
78805796c8dcSSimon Schubert #endif
78815796c8dcSSimon Schubert printf(" :%c: ", name);
78825796c8dcSSimon Schubert for (i=len-1; i>=0; i--) {
78835796c8dcSSimon Schubert if (i==len-1) printf("%ld ", (LI)ar[i]);
78845796c8dcSSimon Schubert else printf(spec, ar[i]);
78855796c8dcSSimon Schubert }
78865796c8dcSSimon Schubert printf("\n");
78875796c8dcSSimon Schubert return;}
78885796c8dcSSimon Schubert #endif
78895796c8dcSSimon Schubert
78905796c8dcSSimon Schubert #if DECCHECK
78915796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
78925796c8dcSSimon Schubert /* decCheckOperands -- check operand(s) to a routine */
78935796c8dcSSimon Schubert /* res is the result structure (not checked; it will be set to */
78945796c8dcSSimon Schubert /* quiet NaN if error found (and it is not NULL)) */
78955796c8dcSSimon Schubert /* lhs is the first operand (may be DECUNRESU) */
78965796c8dcSSimon Schubert /* rhs is the second (may be DECUNUSED) */
78975796c8dcSSimon Schubert /* set is the context (may be DECUNCONT) */
78985796c8dcSSimon Schubert /* returns 0 if both operands, and the context are clean, or 1 */
78995796c8dcSSimon Schubert /* otherwise (in which case the context will show an error, */
79005796c8dcSSimon Schubert /* unless NULL). Note that res is not cleaned; caller should */
79015796c8dcSSimon Schubert /* handle this so res=NULL case is safe. */
79025796c8dcSSimon Schubert /* The caller is expected to abandon immediately if 1 is returned. */
79035796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
79045796c8dcSSimon Schubert static Flag decCheckOperands(decNumber *res, const decNumber *lhs,
79055796c8dcSSimon Schubert const decNumber *rhs, decContext *set) {
79065796c8dcSSimon Schubert Flag bad=0;
79075796c8dcSSimon Schubert if (set==NULL) { /* oops; hopeless */
79085796c8dcSSimon Schubert #if DECTRACE || DECVERB
79095796c8dcSSimon Schubert printf("Reference to context is NULL.\n");
79105796c8dcSSimon Schubert #endif
79115796c8dcSSimon Schubert bad=1;
79125796c8dcSSimon Schubert return 1;}
79135796c8dcSSimon Schubert else if (set!=DECUNCONT
79145796c8dcSSimon Schubert && (set->digits<1 || set->round>=DEC_ROUND_MAX)) {
79155796c8dcSSimon Schubert bad=1;
79165796c8dcSSimon Schubert #if DECTRACE || DECVERB
79175796c8dcSSimon Schubert printf("Bad context [digits=%ld round=%ld].\n",
79185796c8dcSSimon Schubert (LI)set->digits, (LI)set->round);
79195796c8dcSSimon Schubert #endif
79205796c8dcSSimon Schubert }
79215796c8dcSSimon Schubert else {
79225796c8dcSSimon Schubert if (res==NULL) {
79235796c8dcSSimon Schubert bad=1;
79245796c8dcSSimon Schubert #if DECTRACE
79255796c8dcSSimon Schubert /* this one not DECVERB as standard tests include NULL */
79265796c8dcSSimon Schubert printf("Reference to result is NULL.\n");
79275796c8dcSSimon Schubert #endif
79285796c8dcSSimon Schubert }
79295796c8dcSSimon Schubert if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs));
79305796c8dcSSimon Schubert if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs));
79315796c8dcSSimon Schubert }
79325796c8dcSSimon Schubert if (bad) {
79335796c8dcSSimon Schubert if (set!=DECUNCONT) decContextSetStatus(set, DEC_Invalid_operation);
79345796c8dcSSimon Schubert if (res!=DECUNRESU && res!=NULL) {
79355796c8dcSSimon Schubert decNumberZero(res);
79365796c8dcSSimon Schubert res->bits=DECNAN; /* qNaN */
79375796c8dcSSimon Schubert }
79385796c8dcSSimon Schubert }
79395796c8dcSSimon Schubert return bad;
79405796c8dcSSimon Schubert } /* decCheckOperands */
79415796c8dcSSimon Schubert
79425796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
79435796c8dcSSimon Schubert /* decCheckNumber -- check a number */
79445796c8dcSSimon Schubert /* dn is the number to check */
79455796c8dcSSimon Schubert /* returns 0 if the number is clean, or 1 otherwise */
79465796c8dcSSimon Schubert /* */
79475796c8dcSSimon Schubert /* The number is considered valid if it could be a result from some */
79485796c8dcSSimon Schubert /* operation in some valid context. */
79495796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
79505796c8dcSSimon Schubert static Flag decCheckNumber(const decNumber *dn) {
79515796c8dcSSimon Schubert const Unit *up; /* work */
79525796c8dcSSimon Schubert uInt maxuint; /* .. */
79535796c8dcSSimon Schubert Int ae, d, digits; /* .. */
79545796c8dcSSimon Schubert Int emin, emax; /* .. */
79555796c8dcSSimon Schubert
79565796c8dcSSimon Schubert if (dn==NULL) { /* hopeless */
79575796c8dcSSimon Schubert #if DECTRACE
79585796c8dcSSimon Schubert /* this one not DECVERB as standard tests include NULL */
79595796c8dcSSimon Schubert printf("Reference to decNumber is NULL.\n");
79605796c8dcSSimon Schubert #endif
79615796c8dcSSimon Schubert return 1;}
79625796c8dcSSimon Schubert
79635796c8dcSSimon Schubert /* check special values */
79645796c8dcSSimon Schubert if (dn->bits & DECSPECIAL) {
79655796c8dcSSimon Schubert if (dn->exponent!=0) {
79665796c8dcSSimon Schubert #if DECTRACE || DECVERB
79675796c8dcSSimon Schubert printf("Exponent %ld (not 0) for a special value [%02x].\n",
79685796c8dcSSimon Schubert (LI)dn->exponent, dn->bits);
79695796c8dcSSimon Schubert #endif
79705796c8dcSSimon Schubert return 1;}
79715796c8dcSSimon Schubert
79725796c8dcSSimon Schubert /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */
79735796c8dcSSimon Schubert if (decNumberIsInfinite(dn)) {
79745796c8dcSSimon Schubert if (dn->digits!=1) {
79755796c8dcSSimon Schubert #if DECTRACE || DECVERB
79765796c8dcSSimon Schubert printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits);
79775796c8dcSSimon Schubert #endif
79785796c8dcSSimon Schubert return 1;}
79795796c8dcSSimon Schubert if (*dn->lsu!=0) {
79805796c8dcSSimon Schubert #if DECTRACE || DECVERB
79815796c8dcSSimon Schubert printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu);
79825796c8dcSSimon Schubert #endif
79835796c8dcSSimon Schubert decDumpAr('I', dn->lsu, D2U(dn->digits));
79845796c8dcSSimon Schubert return 1;}
79855796c8dcSSimon Schubert } /* Inf */
79865796c8dcSSimon Schubert /* 2002.12.26: negative NaNs can now appear through proposed IEEE */
79875796c8dcSSimon Schubert /* concrete formats (decimal64, etc.). */
79885796c8dcSSimon Schubert return 0;
79895796c8dcSSimon Schubert }
79905796c8dcSSimon Schubert
79915796c8dcSSimon Schubert /* check the coefficient */
79925796c8dcSSimon Schubert if (dn->digits<1 || dn->digits>DECNUMMAXP) {
79935796c8dcSSimon Schubert #if DECTRACE || DECVERB
79945796c8dcSSimon Schubert printf("Digits %ld in number.\n", (LI)dn->digits);
79955796c8dcSSimon Schubert #endif
79965796c8dcSSimon Schubert return 1;}
79975796c8dcSSimon Schubert
79985796c8dcSSimon Schubert d=dn->digits;
79995796c8dcSSimon Schubert
80005796c8dcSSimon Schubert for (up=dn->lsu; d>0; up++) {
80015796c8dcSSimon Schubert if (d>DECDPUN) maxuint=DECDPUNMAX;
80025796c8dcSSimon Schubert else { /* reached the msu */
80035796c8dcSSimon Schubert maxuint=powers[d]-1;
80045796c8dcSSimon Schubert if (dn->digits>1 && *up<powers[d-1]) {
80055796c8dcSSimon Schubert #if DECTRACE || DECVERB
80065796c8dcSSimon Schubert printf("Leading 0 in number.\n");
80075796c8dcSSimon Schubert decNumberShow(dn);
80085796c8dcSSimon Schubert #endif
80095796c8dcSSimon Schubert return 1;}
80105796c8dcSSimon Schubert }
80115796c8dcSSimon Schubert if (*up>maxuint) {
80125796c8dcSSimon Schubert #if DECTRACE || DECVERB
80135796c8dcSSimon Schubert printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n",
80145796c8dcSSimon Schubert (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint);
80155796c8dcSSimon Schubert #endif
80165796c8dcSSimon Schubert return 1;}
80175796c8dcSSimon Schubert d-=DECDPUN;
80185796c8dcSSimon Schubert }
80195796c8dcSSimon Schubert
80205796c8dcSSimon Schubert /* check the exponent. Note that input operands can have exponents */
80215796c8dcSSimon Schubert /* which are out of the set->emin/set->emax and set->digits range */
80225796c8dcSSimon Schubert /* (just as they can have more digits than set->digits). */
80235796c8dcSSimon Schubert ae=dn->exponent+dn->digits-1; /* adjusted exponent */
80245796c8dcSSimon Schubert emax=DECNUMMAXE;
80255796c8dcSSimon Schubert emin=DECNUMMINE;
80265796c8dcSSimon Schubert digits=DECNUMMAXP;
80275796c8dcSSimon Schubert if (ae<emin-(digits-1)) {
80285796c8dcSSimon Schubert #if DECTRACE || DECVERB
80295796c8dcSSimon Schubert printf("Adjusted exponent underflow [%ld].\n", (LI)ae);
80305796c8dcSSimon Schubert decNumberShow(dn);
80315796c8dcSSimon Schubert #endif
80325796c8dcSSimon Schubert return 1;}
80335796c8dcSSimon Schubert if (ae>+emax) {
80345796c8dcSSimon Schubert #if DECTRACE || DECVERB
80355796c8dcSSimon Schubert printf("Adjusted exponent overflow [%ld].\n", (LI)ae);
80365796c8dcSSimon Schubert decNumberShow(dn);
80375796c8dcSSimon Schubert #endif
80385796c8dcSSimon Schubert return 1;}
80395796c8dcSSimon Schubert
80405796c8dcSSimon Schubert return 0; /* it's OK */
80415796c8dcSSimon Schubert } /* decCheckNumber */
80425796c8dcSSimon Schubert
80435796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
80445796c8dcSSimon Schubert /* decCheckInexact -- check a normal finite inexact result has digits */
80455796c8dcSSimon Schubert /* dn is the number to check */
80465796c8dcSSimon Schubert /* set is the context (for status and precision) */
80475796c8dcSSimon Schubert /* sets Invalid operation, etc., if some digits are missing */
80485796c8dcSSimon Schubert /* [this check is not made for DECSUBSET compilation or when */
80495796c8dcSSimon Schubert /* subnormal is not set] */
80505796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
80515796c8dcSSimon Schubert static void decCheckInexact(const decNumber *dn, decContext *set) {
80525796c8dcSSimon Schubert #if !DECSUBSET && DECEXTFLAG
80535796c8dcSSimon Schubert if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact
80545796c8dcSSimon Schubert && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) {
80555796c8dcSSimon Schubert #if DECTRACE || DECVERB
80565796c8dcSSimon Schubert printf("Insufficient digits [%ld] on normal Inexact result.\n",
80575796c8dcSSimon Schubert (LI)dn->digits);
80585796c8dcSSimon Schubert decNumberShow(dn);
80595796c8dcSSimon Schubert #endif
80605796c8dcSSimon Schubert decContextSetStatus(set, DEC_Invalid_operation);
80615796c8dcSSimon Schubert }
80625796c8dcSSimon Schubert #else
80635796c8dcSSimon Schubert /* next is a noop for quiet compiler */
80645796c8dcSSimon Schubert if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation;
80655796c8dcSSimon Schubert #endif
80665796c8dcSSimon Schubert return;
80675796c8dcSSimon Schubert } /* decCheckInexact */
80685796c8dcSSimon Schubert #endif
80695796c8dcSSimon Schubert
80705796c8dcSSimon Schubert #if DECALLOC
80715796c8dcSSimon Schubert #undef malloc
80725796c8dcSSimon Schubert #undef free
80735796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
80745796c8dcSSimon Schubert /* decMalloc -- accountable allocation routine */
80755796c8dcSSimon Schubert /* n is the number of bytes to allocate */
80765796c8dcSSimon Schubert /* */
80775796c8dcSSimon Schubert /* Semantics is the same as the stdlib malloc routine, but bytes */
80785796c8dcSSimon Schubert /* allocated are accounted for globally, and corruption fences are */
80795796c8dcSSimon Schubert /* added before and after the 'actual' storage. */
80805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
80815796c8dcSSimon Schubert /* This routine allocates storage with an extra twelve bytes; 8 are */
80825796c8dcSSimon Schubert /* at the start and hold: */
80835796c8dcSSimon Schubert /* 0-3 the original length requested */
80845796c8dcSSimon Schubert /* 4-7 buffer corruption detection fence (DECFENCE, x4) */
80855796c8dcSSimon Schubert /* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */
80865796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
80875796c8dcSSimon Schubert static void *decMalloc(size_t n) {
80885796c8dcSSimon Schubert uInt size=n+12; /* true size */
80895796c8dcSSimon Schubert void *alloc; /* -> allocated storage */
80905796c8dcSSimon Schubert uByte *b, *b0; /* work */
80915796c8dcSSimon Schubert uInt uiwork; /* for macros */
80925796c8dcSSimon Schubert
80935796c8dcSSimon Schubert alloc=malloc(size); /* -> allocated storage */
80945796c8dcSSimon Schubert if (alloc==NULL) return NULL; /* out of strorage */
80955796c8dcSSimon Schubert b0=(uByte *)alloc; /* as bytes */
80965796c8dcSSimon Schubert decAllocBytes+=n; /* account for storage */
80975796c8dcSSimon Schubert UBFROMUI(alloc, n); /* save n */
80985796c8dcSSimon Schubert /* printf(" alloc ++ dAB: %ld (%ld)\n", (LI)decAllocBytes, (LI)n); */
80995796c8dcSSimon Schubert for (b=b0+4; b<b0+8; b++) *b=DECFENCE;
81005796c8dcSSimon Schubert for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE;
81015796c8dcSSimon Schubert return b0+8; /* -> play area */
81025796c8dcSSimon Schubert } /* decMalloc */
81035796c8dcSSimon Schubert
81045796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
81055796c8dcSSimon Schubert /* decFree -- accountable free routine */
81065796c8dcSSimon Schubert /* alloc is the storage to free */
81075796c8dcSSimon Schubert /* */
81085796c8dcSSimon Schubert /* Semantics is the same as the stdlib malloc routine, except that */
81095796c8dcSSimon Schubert /* the global storage accounting is updated and the fences are */
81105796c8dcSSimon Schubert /* checked to ensure that no routine has written 'out of bounds'. */
81115796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
81125796c8dcSSimon Schubert /* This routine first checks that the fences have not been corrupted. */
81135796c8dcSSimon Schubert /* It then frees the storage using the 'truw' storage address (that */
81145796c8dcSSimon Schubert /* is, offset by 8). */
81155796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
81165796c8dcSSimon Schubert static void decFree(void *alloc) {
81175796c8dcSSimon Schubert uInt n; /* original length */
81185796c8dcSSimon Schubert uByte *b, *b0; /* work */
81195796c8dcSSimon Schubert uInt uiwork; /* for macros */
81205796c8dcSSimon Schubert
81215796c8dcSSimon Schubert if (alloc==NULL) return; /* allowed; it's a nop */
81225796c8dcSSimon Schubert b0=(uByte *)alloc; /* as bytes */
81235796c8dcSSimon Schubert b0-=8; /* -> true start of storage */
81245796c8dcSSimon Schubert n=UBTOUI(b0); /* lift length */
81255796c8dcSSimon Schubert for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE)
81265796c8dcSSimon Schubert printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b,
81275796c8dcSSimon Schubert b-b0-8, (LI)b0);
81285796c8dcSSimon Schubert for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE)
81295796c8dcSSimon Schubert printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b,
81305796c8dcSSimon Schubert b-b0-8, (LI)b0, (LI)n);
81315796c8dcSSimon Schubert free(b0); /* drop the storage */
81325796c8dcSSimon Schubert decAllocBytes-=n; /* account for storage */
81335796c8dcSSimon Schubert /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */
81345796c8dcSSimon Schubert } /* decFree */
81355796c8dcSSimon Schubert #define malloc(a) decMalloc(a)
81365796c8dcSSimon Schubert #define free(a) decFree(a)
81375796c8dcSSimon Schubert #endif
8138