xref: /openbmc/qemu/libdecnumber/decNumber.c (revision 21d7826f)
172ac97cdSTom Musta /* Decimal number arithmetic module for the decNumber C Library.
272ac97cdSTom Musta    Copyright (C) 2005, 2007 Free Software Foundation, Inc.
372ac97cdSTom Musta    Contributed by IBM Corporation.  Author Mike Cowlishaw.
472ac97cdSTom Musta 
572ac97cdSTom Musta    This file is part of GCC.
672ac97cdSTom Musta 
772ac97cdSTom Musta    GCC is free software; you can redistribute it and/or modify it under
872ac97cdSTom Musta    the terms of the GNU General Public License as published by the Free
972ac97cdSTom Musta    Software Foundation; either version 2, or (at your option) any later
1072ac97cdSTom Musta    version.
1172ac97cdSTom Musta 
1272ac97cdSTom Musta    In addition to the permissions in the GNU General Public License,
1372ac97cdSTom Musta    the Free Software Foundation gives you unlimited permission to link
1472ac97cdSTom Musta    the compiled version of this file into combinations with other
1572ac97cdSTom Musta    programs, and to distribute those combinations without any
1672ac97cdSTom Musta    restriction coming from the use of this file.  (The General Public
1772ac97cdSTom Musta    License restrictions do apply in other respects; for example, they
1872ac97cdSTom Musta    cover modification of the file, and distribution when not linked
1972ac97cdSTom Musta    into a combine executable.)
2072ac97cdSTom Musta 
2172ac97cdSTom Musta    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
2272ac97cdSTom Musta    WARRANTY; without even the implied warranty of MERCHANTABILITY or
2372ac97cdSTom Musta    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
2472ac97cdSTom Musta    for more details.
2572ac97cdSTom Musta 
2672ac97cdSTom Musta    You should have received a copy of the GNU General Public License
2772ac97cdSTom Musta    along with GCC; see the file COPYING.  If not, write to the Free
2872ac97cdSTom Musta    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2972ac97cdSTom Musta    02110-1301, USA.  */
3072ac97cdSTom Musta 
3172ac97cdSTom Musta /* ------------------------------------------------------------------ */
3272ac97cdSTom Musta /* Decimal Number arithmetic module				      */
3372ac97cdSTom Musta /* ------------------------------------------------------------------ */
3472ac97cdSTom Musta /* This module comprises the routines for General Decimal Arithmetic  */
3572ac97cdSTom Musta /* as defined in the specification which may be found on the	      */
3672ac97cdSTom Musta /* http://www2.hursley.ibm.com/decimal web pages.  It implements both */
3772ac97cdSTom Musta /* the full ('extended') arithmetic and the simpler ('subset')	      */
3872ac97cdSTom Musta /* arithmetic.							      */
3972ac97cdSTom Musta /*								      */
4072ac97cdSTom Musta /* Usage notes:							      */
4172ac97cdSTom Musta /*								      */
4272ac97cdSTom Musta /* 1. This code is ANSI C89 except:				      */
4372ac97cdSTom Musta /*								      */
4472ac97cdSTom Musta /*       If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and	      */
4572ac97cdSTom Musta /*	 uint64_t types may be used.  To avoid these, set DECUSE64=0  */
4672ac97cdSTom Musta /*	 and DECDPUN<=4 (see documentation).			      */
4772ac97cdSTom Musta /*								      */
4872ac97cdSTom Musta /* 2. The decNumber format which this library uses is optimized for   */
4972ac97cdSTom Musta /*    efficient processing of relatively short numbers; in particular */
5072ac97cdSTom Musta /*    it allows the use of fixed sized structures and minimizes copy  */
5172ac97cdSTom Musta /*    and move operations.  It does, however, support arbitrary	      */
5272ac97cdSTom Musta /*    precision (up to 999,999,999 digits) and arbitrary exponent     */
5372ac97cdSTom Musta /*    range (Emax in the range 0 through 999,999,999 and Emin in the  */
5472ac97cdSTom Musta /*    range -999,999,999 through 0).  Mathematical functions (for     */
5572ac97cdSTom Musta /*    example decNumberExp) as identified below are restricted more   */
5672ac97cdSTom Musta /*    tightly: digits, emax, and -emin in the context must be <=      */
5772ac97cdSTom Musta /*    DEC_MAX_MATH (999999), and their operand(s) must be within      */
5872ac97cdSTom Musta /*    these bounds.						      */
5972ac97cdSTom Musta /*								      */
6072ac97cdSTom Musta /* 3. Logical functions are further restricted; their operands must   */
6172ac97cdSTom Musta /*    be finite, positive, have an exponent of zero, and all digits   */
6272ac97cdSTom Musta /*    must be either 0 or 1.  The result will only contain digits     */
6372ac97cdSTom Musta /*    which are 0 or 1 (and will have exponent=0 and a sign of 0).    */
6472ac97cdSTom Musta /*								      */
6572ac97cdSTom Musta /* 4. Operands to operator functions are never modified unless they   */
6672ac97cdSTom Musta /*    are also specified to be the result number (which is always     */
6772ac97cdSTom Musta /*    permitted).  Other than that case, operands must not overlap.   */
6872ac97cdSTom Musta /*								      */
6972ac97cdSTom Musta /* 5. Error handling: the type of the error is ORed into the status   */
7072ac97cdSTom Musta /*    flags in the current context (decContext structure).  The	      */
7172ac97cdSTom Musta /*    SIGFPE signal is then raised if the corresponding trap-enabler  */
7272ac97cdSTom Musta /*    flag in the decContext is set (is 1).			      */
7372ac97cdSTom Musta /*								      */
7472ac97cdSTom Musta /*    It is the responsibility of the caller to clear the status      */
7572ac97cdSTom Musta /*    flags as required.					      */
7672ac97cdSTom Musta /*								      */
7772ac97cdSTom Musta /*    The result of any routine which returns a number will always    */
7872ac97cdSTom Musta /*    be a valid number (which may be a special value, such as an     */
7972ac97cdSTom Musta /*    Infinity or NaN).						      */
8072ac97cdSTom Musta /*								      */
8172ac97cdSTom Musta /* 6. The decNumber format is not an exchangeable concrete	      */
8272ac97cdSTom Musta /*    representation as it comprises fields which may be machine-     */
8372ac97cdSTom Musta /*    dependent (packed or unpacked, or special length, for example). */
8472ac97cdSTom Musta /*    Canonical conversions to and from strings are provided; other   */
8572ac97cdSTom Musta /*    conversions are available in separate modules.		      */
8672ac97cdSTom Musta /*								      */
8772ac97cdSTom Musta /* 7. Normally, input operands are assumed to be valid.	 Set DECCHECK */
8872ac97cdSTom Musta /*    to 1 for extended operand checking (including NULL operands).   */
8972ac97cdSTom Musta /*    Results are undefined if a badly-formed structure (or a NULL    */
9072ac97cdSTom Musta /*    pointer to a structure) is provided, though with DECCHECK	      */
9172ac97cdSTom Musta /*    enabled the operator routines are protected against exceptions. */
9272ac97cdSTom Musta /*    (Except if the result pointer is NULL, which is unrecoverable.) */
9372ac97cdSTom Musta /*								      */
9472ac97cdSTom Musta /*    However, the routines will never cause exceptions if they are   */
9572ac97cdSTom Musta /*    given well-formed operands, even if the value of the operands   */
9672ac97cdSTom Musta /*    is inappropriate for the operation and DECCHECK is not set.     */
9772ac97cdSTom Musta /*    (Except for SIGFPE, as and where documented.)		      */
9872ac97cdSTom Musta /*								      */
9972ac97cdSTom Musta /* 8. Subset arithmetic is available only if DECSUBSET is set to 1.   */
10072ac97cdSTom Musta /* ------------------------------------------------------------------ */
10172ac97cdSTom Musta /* Implementation notes for maintenance of this module:		      */
10272ac97cdSTom Musta /*								      */
10372ac97cdSTom Musta /* 1. Storage leak protection:	Routines which use malloc are not     */
10472ac97cdSTom Musta /*    permitted to use return for fastpath or error exits (i.e.,      */
10572ac97cdSTom Musta /*    they follow strict structured programming conventions).	      */
10672ac97cdSTom Musta /*    Instead they have a do{}while(0); construct surrounding the     */
10772ac97cdSTom Musta /*    code which is protected -- break may be used to exit this.      */
10872ac97cdSTom Musta /*    Other routines can safely use the return statement inline.      */
10972ac97cdSTom Musta /*								      */
11072ac97cdSTom Musta /*    Storage leak accounting can be enabled using DECALLOC.	      */
11172ac97cdSTom Musta /*								      */
11272ac97cdSTom Musta /* 2. All loops use the for(;;) construct.  Any do construct does     */
11372ac97cdSTom Musta /*    not loop; it is for allocation protection as just described.    */
11472ac97cdSTom Musta /*								      */
11572ac97cdSTom Musta /* 3. Setting status in the context must always be the very last      */
11672ac97cdSTom Musta /*    action in a routine, as non-0 status may raise a trap and hence */
11772ac97cdSTom Musta /*    the call to set status may not return (if the handler uses long */
11872ac97cdSTom Musta /*    jump).  Therefore all cleanup must be done first.	 In general,  */
11972ac97cdSTom Musta /*    to achieve this status is accumulated and is only applied just  */
12072ac97cdSTom Musta /*    before return by calling decContextSetStatus (via decStatus).   */
12172ac97cdSTom Musta /*								      */
12272ac97cdSTom Musta /*    Routines which allocate storage cannot, in general, use the     */
12372ac97cdSTom Musta /*    'top level' routines which could cause a non-returning	      */
12472ac97cdSTom Musta /*    transfer of control.  The decXxxxOp routines are safe (do not   */
12572ac97cdSTom Musta /*    call decStatus even if traps are set in the context) and should */
12672ac97cdSTom Musta /*    be used instead (they are also a little faster).		      */
12772ac97cdSTom Musta /*								      */
12872ac97cdSTom Musta /* 4. Exponent checking is minimized by allowing the exponent to      */
12972ac97cdSTom Musta /*    grow outside its limits during calculations, provided that      */
13072ac97cdSTom Musta /*    the decFinalize function is called later.	 Multiplication and   */
13172ac97cdSTom Musta /*    division, and intermediate calculations in exponentiation,      */
13272ac97cdSTom Musta /*    require more careful checks because of the risk of 31-bit	      */
13372ac97cdSTom Musta /*    overflow (the most negative valid exponent is -1999999997, for  */
13472ac97cdSTom Musta /*    a 999999999-digit number with adjusted exponent of -999999999). */
13572ac97cdSTom Musta /*								      */
13672ac97cdSTom Musta /* 5. Rounding is deferred until finalization of results, with any    */
13772ac97cdSTom Musta /*    'off to the right' data being represented as a single digit     */
13872ac97cdSTom Musta /*    residue (in the range -1 through 9).  This avoids any double-   */
13972ac97cdSTom Musta /*    rounding when more than one shortening takes place (for	      */
14072ac97cdSTom Musta /*    example, when a result is subnormal).			      */
14172ac97cdSTom Musta /*								      */
14272ac97cdSTom Musta /* 6. The digits count is allowed to rise to a multiple of DECDPUN    */
14372ac97cdSTom Musta /*    during many operations, so whole Units are handled and exact    */
14472ac97cdSTom Musta /*    accounting of digits is not needed.  The correct digits value   */
14572ac97cdSTom Musta /*    is found by decGetDigits, which accounts for leading zeros.     */
14672ac97cdSTom Musta /*    This must be called before any rounding if the number of digits */
14772ac97cdSTom Musta /*    is not known exactly.					      */
14872ac97cdSTom Musta /*								      */
14972ac97cdSTom Musta /* 7. The multiply-by-reciprocal 'trick' is used for partitioning     */
15072ac97cdSTom Musta /*    numbers up to four digits, using appropriate constants.  This   */
15172ac97cdSTom Musta /*    is not useful for longer numbers because overflow of 32 bits    */
15272ac97cdSTom Musta /*    would lead to 4 multiplies, which is almost as expensive as     */
15372ac97cdSTom Musta /*    a divide (unless a floating-point or 64-bit multiply is	      */
15472ac97cdSTom Musta /*    assumed to be available).					      */
15572ac97cdSTom Musta /*								      */
15672ac97cdSTom Musta /* 8. Unusual abbreviations that may be used in the commentary:	      */
15772ac97cdSTom Musta /*	lhs -- left hand side (operand, of an operation)	      */
15872ac97cdSTom Musta /*	lsd -- least significant digit (of coefficient)		      */
15972ac97cdSTom Musta /*	lsu -- least significant Unit (of coefficient)		      */
16072ac97cdSTom Musta /*	msd -- most significant digit (of coefficient)		      */
16172ac97cdSTom Musta /*	msi -- most significant item (in an array)		      */
16272ac97cdSTom Musta /*	msu -- most significant Unit (of coefficient)		      */
16372ac97cdSTom Musta /*	rhs -- right hand side (operand, of an operation)	      */
16472ac97cdSTom Musta /*	+ve -- positive						      */
16572ac97cdSTom Musta /*	-ve -- negative						      */
16672ac97cdSTom Musta /*	**  -- raise to the power				      */
16772ac97cdSTom Musta /* ------------------------------------------------------------------ */
16872ac97cdSTom Musta 
1697a4e543dSPeter Maydell #include "qemu/osdep.h"
170727385c4SLuis Pires #include "qemu/host-utils.h"
1710f2d3732STom Musta #include "libdecnumber/dconfig.h"
1720f2d3732STom Musta #include "libdecnumber/decNumber.h"
1730f2d3732STom Musta #include "libdecnumber/decNumberLocal.h"
17472ac97cdSTom Musta 
17572ac97cdSTom Musta /* Constants */
17672ac97cdSTom Musta /* Public lookup table used by the D2U macro */
17772ac97cdSTom Musta const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
17872ac97cdSTom Musta 
17972ac97cdSTom Musta #define DECVERB	    1		   /* set to 1 for verbose DECCHECK */
18072ac97cdSTom Musta #define powers	    DECPOWERS	   /* old internal name */
18172ac97cdSTom Musta 
18272ac97cdSTom Musta /* Local constants */
18372ac97cdSTom Musta #define DIVIDE	    0x80	   /* Divide operators */
18472ac97cdSTom Musta #define REMAINDER   0x40	   /* .. */
18572ac97cdSTom Musta #define DIVIDEINT   0x20	   /* .. */
18672ac97cdSTom Musta #define REMNEAR	    0x10	   /* .. */
18772ac97cdSTom Musta #define COMPARE	    0x01	   /* Compare operators */
18872ac97cdSTom Musta #define COMPMAX	    0x02	   /* .. */
18972ac97cdSTom Musta #define COMPMIN	    0x03	   /* .. */
19072ac97cdSTom Musta #define COMPTOTAL   0x04	   /* .. */
19172ac97cdSTom Musta #define COMPNAN	    0x05	   /* .. [NaN processing] */
19272ac97cdSTom Musta #define COMPSIG	    0x06	   /* .. [signaling COMPARE] */
19372ac97cdSTom Musta #define COMPMAXMAG  0x07	   /* .. */
19472ac97cdSTom Musta #define COMPMINMAG  0x08	   /* .. */
19572ac97cdSTom Musta 
19672ac97cdSTom Musta #define DEC_sNaN     0x40000000	   /* local status: sNaN signal */
19772ac97cdSTom Musta #define BADINT	(Int)0x80000000	   /* most-negative Int; error indicator */
19872ac97cdSTom Musta /* Next two indicate an integer >= 10**6, and its parity (bottom bit) */
19972ac97cdSTom Musta #define BIGEVEN (Int)0x80000002
20072ac97cdSTom Musta #define BIGODD	(Int)0x80000003
20172ac97cdSTom Musta 
20272ac97cdSTom Musta static Unit uarrone[1]={1};   /* Unit array of 1, used for incrementing */
20372ac97cdSTom Musta 
20472ac97cdSTom Musta /* Granularity-dependent code */
20572ac97cdSTom Musta #if DECDPUN<=4
20672ac97cdSTom Musta   #define eInt	Int	      /* extended integer */
20772ac97cdSTom Musta   #define ueInt uInt	      /* unsigned extended integer */
20872ac97cdSTom Musta   /* Constant multipliers for divide-by-power-of five using reciprocal */
20972ac97cdSTom Musta   /* multiply, after removing powers of 2 by shifting, and final shift */
21072ac97cdSTom Musta   /* of 17 [we only need up to **4] */
21172ac97cdSTom Musta   static const uInt multies[]={131073, 26215, 5243, 1049, 210};
21272ac97cdSTom Musta   /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */
21372ac97cdSTom Musta   #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
21472ac97cdSTom Musta #else
21572ac97cdSTom Musta   /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */
21672ac97cdSTom Musta   #if !DECUSE64
21772ac97cdSTom Musta     #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4
21872ac97cdSTom Musta   #endif
21972ac97cdSTom Musta   #define eInt	Long	      /* extended integer */
22072ac97cdSTom Musta   #define ueInt uLong	      /* unsigned extended integer */
22172ac97cdSTom Musta #endif
22272ac97cdSTom Musta 
22372ac97cdSTom Musta /* Local routines */
22472ac97cdSTom Musta static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *,
22572ac97cdSTom Musta 			      decContext *, uByte, uInt *);
22672ac97cdSTom Musta static Flag	   decBiStr(const char *, const char *, const char *);
22772ac97cdSTom Musta static uInt	   decCheckMath(const decNumber *, decContext *, uInt *);
22872ac97cdSTom Musta static void	   decApplyRound(decNumber *, decContext *, Int, uInt *);
22972ac97cdSTom Musta static Int	   decCompare(const decNumber *lhs, const decNumber *rhs, Flag);
23072ac97cdSTom Musta static decNumber * decCompareOp(decNumber *, const decNumber *,
23172ac97cdSTom Musta 			      const decNumber *, decContext *,
23272ac97cdSTom Musta 			      Flag, uInt *);
23372ac97cdSTom Musta static void	   decCopyFit(decNumber *, const decNumber *, decContext *,
23472ac97cdSTom Musta 			      Int *, uInt *);
23572ac97cdSTom Musta static decNumber * decDecap(decNumber *, Int);
23672ac97cdSTom Musta static decNumber * decDivideOp(decNumber *, const decNumber *,
23772ac97cdSTom Musta 			      const decNumber *, decContext *, Flag, uInt *);
23872ac97cdSTom Musta static decNumber * decExpOp(decNumber *, const decNumber *,
23972ac97cdSTom Musta 			      decContext *, uInt *);
24072ac97cdSTom Musta static void	   decFinalize(decNumber *, decContext *, Int *, uInt *);
24172ac97cdSTom Musta static Int	   decGetDigits(Unit *, Int);
24272ac97cdSTom Musta static Int	   decGetInt(const decNumber *);
24372ac97cdSTom Musta static decNumber * decLnOp(decNumber *, const decNumber *,
24472ac97cdSTom Musta 			      decContext *, uInt *);
24572ac97cdSTom Musta static decNumber * decMultiplyOp(decNumber *, const decNumber *,
24672ac97cdSTom Musta 			      const decNumber *, decContext *,
24772ac97cdSTom Musta 			      uInt *);
24872ac97cdSTom Musta static decNumber * decNaNs(decNumber *, const decNumber *,
24972ac97cdSTom Musta 			      const decNumber *, decContext *, uInt *);
25072ac97cdSTom Musta static decNumber * decQuantizeOp(decNumber *, const decNumber *,
25172ac97cdSTom Musta 			      const decNumber *, decContext *, Flag,
25272ac97cdSTom Musta 			      uInt *);
25372ac97cdSTom Musta static void	   decReverse(Unit *, Unit *);
25472ac97cdSTom Musta static void	   decSetCoeff(decNumber *, decContext *, const Unit *,
25572ac97cdSTom Musta 			      Int, Int *, uInt *);
25672ac97cdSTom Musta static void	   decSetMaxValue(decNumber *, decContext *);
25772ac97cdSTom Musta static void	   decSetOverflow(decNumber *, decContext *, uInt *);
25872ac97cdSTom Musta static void	   decSetSubnormal(decNumber *, decContext *, Int *, uInt *);
25972ac97cdSTom Musta static Int	   decShiftToLeast(Unit *, Int, Int);
26072ac97cdSTom Musta static Int	   decShiftToMost(Unit *, Int, Int);
26172ac97cdSTom Musta static void	   decStatus(decNumber *, uInt, decContext *);
26272ac97cdSTom Musta static void	   decToString(const decNumber *, char[], Flag);
26372ac97cdSTom Musta static decNumber * decTrim(decNumber *, decContext *, Flag, Int *);
26472ac97cdSTom Musta static Int	   decUnitAddSub(const Unit *, Int, const Unit *, Int, Int,
26572ac97cdSTom Musta 			      Unit *, Int);
26672ac97cdSTom Musta static Int	   decUnitCompare(const Unit *, Int, const Unit *, Int, Int);
267*21d7826fSLuis Pires static bool        mulUInt128ByPowOf10(uLong *, uLong *, uInt);
26872ac97cdSTom Musta 
26972ac97cdSTom Musta #if !DECSUBSET
27072ac97cdSTom Musta /* decFinish == decFinalize when no subset arithmetic needed */
27172ac97cdSTom Musta #define decFinish(a,b,c,d) decFinalize(a,b,c,d)
27272ac97cdSTom Musta #else
27372ac97cdSTom Musta static void	   decFinish(decNumber *, decContext *, Int *, uInt *);
27472ac97cdSTom Musta static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *);
27572ac97cdSTom Musta #endif
27672ac97cdSTom Musta 
27772ac97cdSTom Musta /* Local macros */
27872ac97cdSTom Musta /* masked special-values bits */
27972ac97cdSTom Musta #define SPECIALARG  (rhs->bits & DECSPECIAL)
28072ac97cdSTom Musta #define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL)
28172ac97cdSTom Musta 
28272ac97cdSTom Musta /* Diagnostic macros, etc. */
28372ac97cdSTom Musta #if DECALLOC
28472ac97cdSTom Musta /* Handle malloc/free accounting.  If enabled, our accountable routines */
28572ac97cdSTom Musta /* are used; otherwise the code just goes straight to the system malloc */
28672ac97cdSTom Musta /* and free routines. */
28772ac97cdSTom Musta #define malloc(a) decMalloc(a)
28872ac97cdSTom Musta #define free(a) decFree(a)
28972ac97cdSTom Musta #define DECFENCE 0x5a		   /* corruption detector */
29072ac97cdSTom Musta /* 'Our' malloc and free: */
29172ac97cdSTom Musta static void *decMalloc(size_t);
29272ac97cdSTom Musta static void  decFree(void *);
29372ac97cdSTom Musta uInt decAllocBytes=0;		   /* count of bytes allocated */
29472ac97cdSTom Musta /* Note that DECALLOC code only checks for storage buffer overflow. */
29572ac97cdSTom Musta /* To check for memory leaks, the decAllocBytes variable must be */
29672ac97cdSTom Musta /* checked to be 0 at appropriate times (e.g., after the test */
29772ac97cdSTom Musta /* harness completes a set of tests).  This checking may be unreliable */
29872ac97cdSTom Musta /* if the testing is done in a multi-thread environment. */
29972ac97cdSTom Musta #endif
30072ac97cdSTom Musta 
30172ac97cdSTom Musta #if DECCHECK
30272ac97cdSTom Musta /* Optional checking routines.	Enabling these means that decNumber */
30372ac97cdSTom Musta /* and decContext operands to operator routines are checked for */
30472ac97cdSTom Musta /* correctness.	 This roughly doubles the execution time of the */
30572ac97cdSTom Musta /* fastest routines (and adds 600+ bytes), so should not normally be */
30672ac97cdSTom Musta /* used in 'production'. */
30772ac97cdSTom Musta /* decCheckInexact is used to check that inexact results have a full */
30872ac97cdSTom Musta /* complement of digits (where appropriate -- this is not the case */
30972ac97cdSTom Musta /* for Quantize, for example) */
31072ac97cdSTom Musta #define DECUNRESU ((decNumber *)(void *)0xffffffff)
31172ac97cdSTom Musta #define DECUNUSED ((const decNumber *)(void *)0xffffffff)
31272ac97cdSTom Musta #define DECUNCONT ((decContext *)(void *)(0xffffffff))
31372ac97cdSTom Musta static Flag decCheckOperands(decNumber *, const decNumber *,
31472ac97cdSTom Musta 			     const decNumber *, decContext *);
31572ac97cdSTom Musta static Flag decCheckNumber(const decNumber *);
31672ac97cdSTom Musta static void decCheckInexact(const decNumber *, decContext *);
31772ac97cdSTom Musta #endif
31872ac97cdSTom Musta 
31972ac97cdSTom Musta #if DECTRACE || DECCHECK
32072ac97cdSTom Musta /* Optional trace/debugging routines (may or may not be used) */
32172ac97cdSTom Musta void decNumberShow(const decNumber *);	/* displays the components of a number */
32272ac97cdSTom Musta static void decDumpAr(char, const Unit *, Int);
32372ac97cdSTom Musta #endif
32472ac97cdSTom Musta 
32572ac97cdSTom Musta /* ================================================================== */
32672ac97cdSTom Musta /* Conversions							      */
32772ac97cdSTom Musta /* ================================================================== */
32872ac97cdSTom Musta 
32972ac97cdSTom Musta /* ------------------------------------------------------------------ */
33072ac97cdSTom Musta /* from-int32 -- conversion from Int or uInt			      */
33172ac97cdSTom Musta /*								      */
33272ac97cdSTom Musta /*  dn is the decNumber to receive the integer			      */
33372ac97cdSTom Musta /*  in or uin is the integer to be converted			      */
33472ac97cdSTom Musta /*  returns dn							      */
33572ac97cdSTom Musta /*								      */
33672ac97cdSTom Musta /* No error is possible.					      */
33772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberFromInt32(decNumber * dn,Int in)33872ac97cdSTom Musta decNumber * decNumberFromInt32(decNumber *dn, Int in) {
33972ac97cdSTom Musta   uInt unsig;
34072ac97cdSTom Musta   if (in>=0) unsig=in;
34172ac97cdSTom Musta    else {				/* negative (possibly BADINT) */
34272ac97cdSTom Musta     if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */
34372ac97cdSTom Musta      else unsig=-in;			/* invert */
34472ac97cdSTom Musta     }
34572ac97cdSTom Musta   /* in is now positive */
34672ac97cdSTom Musta   decNumberFromUInt32(dn, unsig);
34772ac97cdSTom Musta   if (in<0) dn->bits=DECNEG;		/* sign needed */
34872ac97cdSTom Musta   return dn;
34972ac97cdSTom Musta   } /* decNumberFromInt32 */
35072ac97cdSTom Musta 
decNumberFromUInt32(decNumber * dn,uInt uin)35172ac97cdSTom Musta decNumber * decNumberFromUInt32(decNumber *dn, uInt uin) {
35272ac97cdSTom Musta   Unit *up;				/* work pointer */
35372ac97cdSTom Musta   decNumberZero(dn);			/* clean */
35472ac97cdSTom Musta   if (uin==0) return dn;		/* [or decGetDigits bad call] */
35572ac97cdSTom Musta   for (up=dn->lsu; uin>0; up++) {
35672ac97cdSTom Musta     *up=(Unit)(uin%(DECDPUNMAX+1));
35772ac97cdSTom Musta     uin=uin/(DECDPUNMAX+1);
35872ac97cdSTom Musta     }
35972ac97cdSTom Musta   dn->digits=decGetDigits(dn->lsu, up-dn->lsu);
36072ac97cdSTom Musta   return dn;
36172ac97cdSTom Musta   } /* decNumberFromUInt32 */
36272ac97cdSTom Musta 
36372ac97cdSTom Musta /* ------------------------------------------------------------------ */
36472ac97cdSTom Musta /* to-int32 -- conversion to Int or uInt			      */
36572ac97cdSTom Musta /*								      */
36672ac97cdSTom Musta /*  dn is the decNumber to convert				      */
36772ac97cdSTom Musta /*  set is the context for reporting errors			      */
36872ac97cdSTom Musta /*  returns the converted decNumber, or 0 if Invalid is set	      */
36972ac97cdSTom Musta /*								      */
37072ac97cdSTom Musta /* Invalid is set if the decNumber does not have exponent==0 or if    */
37172ac97cdSTom Musta /* it is a NaN, Infinite, or out-of-range.			      */
37272ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberToInt32(const decNumber * dn,decContext * set)37372ac97cdSTom Musta Int decNumberToInt32(const decNumber *dn, decContext *set) {
37472ac97cdSTom Musta   #if DECCHECK
37572ac97cdSTom Musta   if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
37672ac97cdSTom Musta   #endif
37772ac97cdSTom Musta 
37872ac97cdSTom Musta   /* special or too many digits, or bad exponent */
37972ac97cdSTom Musta   if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */
38072ac97cdSTom Musta    else { /* is a finite integer with 10 or fewer digits */
38172ac97cdSTom Musta     Int d;			   /* work */
38272ac97cdSTom Musta     const Unit *up;		   /* .. */
38372ac97cdSTom Musta     uInt hi=0, lo;		   /* .. */
38472ac97cdSTom Musta     up=dn->lsu;			   /* -> lsu */
38572ac97cdSTom Musta     lo=*up;			   /* get 1 to 9 digits */
38672ac97cdSTom Musta     #if DECDPUN>1		   /* split to higher */
38772ac97cdSTom Musta       hi=lo/10;
38872ac97cdSTom Musta       lo=lo%10;
38972ac97cdSTom Musta     #endif
39072ac97cdSTom Musta     up++;
39172ac97cdSTom Musta     /* collect remaining Units, if any, into hi */
39272ac97cdSTom Musta     for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
39372ac97cdSTom Musta     /* now low has the lsd, hi the remainder */
39472ac97cdSTom Musta     if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */
39572ac97cdSTom Musta       /* most-negative is a reprieve */
39672ac97cdSTom Musta       if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000;
39772ac97cdSTom Musta       /* bad -- drop through */
39872ac97cdSTom Musta       }
39972ac97cdSTom Musta      else { /* in-range always */
40072ac97cdSTom Musta       Int i=X10(hi)+lo;
40172ac97cdSTom Musta       if (dn->bits&DECNEG) return -i;
40272ac97cdSTom Musta       return i;
40372ac97cdSTom Musta       }
40472ac97cdSTom Musta     } /* integer */
40572ac97cdSTom Musta   decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
40672ac97cdSTom Musta   return 0;
40772ac97cdSTom Musta   } /* decNumberToInt32 */
40872ac97cdSTom Musta 
decNumberToUInt32(const decNumber * dn,decContext * set)40972ac97cdSTom Musta uInt decNumberToUInt32(const decNumber *dn, decContext *set) {
41072ac97cdSTom Musta   #if DECCHECK
41172ac97cdSTom Musta   if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
41272ac97cdSTom Musta   #endif
41372ac97cdSTom Musta   /* special or too many digits, or bad exponent, or negative (<0) */
41472ac97cdSTom Musta   if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0
41572ac97cdSTom Musta     || (dn->bits&DECNEG && !ISZERO(dn)));		    /* bad */
41672ac97cdSTom Musta    else { /* is a finite integer with 10 or fewer digits */
41772ac97cdSTom Musta     Int d;			   /* work */
41872ac97cdSTom Musta     const Unit *up;		   /* .. */
41972ac97cdSTom Musta     uInt hi=0, lo;		   /* .. */
42072ac97cdSTom Musta     up=dn->lsu;			   /* -> lsu */
42172ac97cdSTom Musta     lo=*up;			   /* get 1 to 9 digits */
42272ac97cdSTom Musta     #if DECDPUN>1		   /* split to higher */
42372ac97cdSTom Musta       hi=lo/10;
42472ac97cdSTom Musta       lo=lo%10;
42572ac97cdSTom Musta     #endif
42672ac97cdSTom Musta     up++;
42772ac97cdSTom Musta     /* collect remaining Units, if any, into hi */
42872ac97cdSTom Musta     for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
42972ac97cdSTom Musta 
43072ac97cdSTom Musta     /* now low has the lsd, hi the remainder */
43172ac97cdSTom Musta     if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */
43272ac97cdSTom Musta      else return X10(hi)+lo;
43372ac97cdSTom Musta     } /* integer */
43472ac97cdSTom Musta   decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
43572ac97cdSTom Musta   return 0;
43672ac97cdSTom Musta   } /* decNumberToUInt32 */
43772ac97cdSTom Musta 
decNumberFromInt64(decNumber * dn,int64_t in)4388e706db2STom Musta decNumber *decNumberFromInt64(decNumber *dn, int64_t in)
4398e706db2STom Musta {
4408e706db2STom Musta     uint64_t unsig = in;
4418e706db2STom Musta     if (in < 0) {
4428e706db2STom Musta         unsig = -unsig;
4438e706db2STom Musta     }
4448e706db2STom Musta 
4458e706db2STom Musta     decNumberFromUInt64(dn, unsig);
4468e706db2STom Musta     if (in < 0) {
4478e706db2STom Musta         dn->bits = DECNEG;        /* sign needed */
4488e706db2STom Musta     }
4498e706db2STom Musta     return dn;
4508e706db2STom Musta } /* decNumberFromInt64 */
4518e706db2STom Musta 
decNumberFromUInt64(decNumber * dn,uint64_t uin)4528e706db2STom Musta decNumber *decNumberFromUInt64(decNumber *dn, uint64_t uin)
4538e706db2STom Musta {
4548e706db2STom Musta     Unit *up;                             /* work pointer */
4558e706db2STom Musta     decNumberZero(dn);                    /* clean */
4568e706db2STom Musta     if (uin == 0) {
4578e706db2STom Musta         return dn;                /* [or decGetDigits bad call] */
4588e706db2STom Musta     }
4598e706db2STom Musta     for (up = dn->lsu; uin > 0; up++) {
4608e706db2STom Musta         *up = (Unit)(uin % (DECDPUNMAX + 1));
4618e706db2STom Musta         uin = uin / (DECDPUNMAX + 1);
4628e706db2STom Musta     }
4638e706db2STom Musta     dn->digits = decGetDigits(dn->lsu, up-dn->lsu);
4648e706db2STom Musta     return dn;
4658e706db2STom Musta } /* decNumberFromUInt64 */
4668e706db2STom Musta 
decNumberFromInt128(decNumber * dn,uint64_t lo,int64_t hi)467727385c4SLuis Pires decNumber *decNumberFromInt128(decNumber *dn, uint64_t lo, int64_t hi)
468727385c4SLuis Pires {
469727385c4SLuis Pires     uint64_t unsig_hi = hi;
470727385c4SLuis Pires     if (hi < 0) {
471727385c4SLuis Pires         if (lo == 0) {
472727385c4SLuis Pires             unsig_hi = -unsig_hi;
473727385c4SLuis Pires         } else {
474727385c4SLuis Pires             unsig_hi = ~unsig_hi;
475727385c4SLuis Pires             lo = -lo;
476727385c4SLuis Pires         }
477727385c4SLuis Pires     }
478727385c4SLuis Pires 
479727385c4SLuis Pires     decNumberFromUInt128(dn, lo, unsig_hi);
480727385c4SLuis Pires     if (hi < 0) {
481727385c4SLuis Pires         dn->bits = DECNEG;        /* sign needed */
482727385c4SLuis Pires     }
483727385c4SLuis Pires     return dn;
484727385c4SLuis Pires } /* decNumberFromInt128 */
485727385c4SLuis Pires 
decNumberFromUInt128(decNumber * dn,uint64_t lo,uint64_t hi)486727385c4SLuis Pires decNumber *decNumberFromUInt128(decNumber *dn, uint64_t lo, uint64_t hi)
487727385c4SLuis Pires {
488727385c4SLuis Pires     uint64_t rem;
489727385c4SLuis Pires     Unit *up;                             /* work pointer */
490727385c4SLuis Pires     decNumberZero(dn);                    /* clean */
491727385c4SLuis Pires     if (lo == 0 && hi == 0) {
492727385c4SLuis Pires         return dn;                /* [or decGetDigits bad call] */
493727385c4SLuis Pires     }
494727385c4SLuis Pires     for (up = dn->lsu; hi > 0 || lo > 0; up++) {
495727385c4SLuis Pires         rem = divu128(&lo, &hi, DECDPUNMAX + 1);
496727385c4SLuis Pires         *up = (Unit)rem;
497727385c4SLuis Pires     }
498727385c4SLuis Pires     dn->digits = decGetDigits(dn->lsu, up - dn->lsu);
499727385c4SLuis Pires     return dn;
500727385c4SLuis Pires } /* decNumberFromUInt128 */
501727385c4SLuis Pires 
50279af3572STom Musta /* ------------------------------------------------------------------ */
50379af3572STom Musta /* to-int64 -- conversion to int64                                    */
50479af3572STom Musta /*                                                                    */
50579af3572STom Musta /*  dn is the decNumber to convert.  dn is assumed to have been       */
50679af3572STom Musta /*    rounded to a floating point integer value.                      */
50779af3572STom Musta /*  set is the context for reporting errors                           */
50879af3572STom Musta /*  returns the converted decNumber, or 0 if Invalid is set           */
50979af3572STom Musta /*                                                                    */
51079af3572STom Musta /* Invalid is set if the decNumber is a NaN, Infinite or is out of    */
51179af3572STom Musta /* range for a signed 64 bit integer.                                 */
51279af3572STom Musta /* ------------------------------------------------------------------ */
51379af3572STom Musta 
decNumberIntegralToInt64(const decNumber * dn,decContext * set)51479af3572STom Musta int64_t decNumberIntegralToInt64(const decNumber *dn, decContext *set)
51579af3572STom Musta {
51679af3572STom Musta     if (decNumberIsSpecial(dn) || (dn->exponent < 0) ||
51779af3572STom Musta        (dn->digits + dn->exponent > 19)) {
51879af3572STom Musta         goto Invalid;
51979af3572STom Musta     } else {
52079af3572STom Musta         int64_t d;        /* work */
52179af3572STom Musta         const Unit *up;   /* .. */
52279af3572STom Musta         uint64_t hi = 0;
52379af3572STom Musta         up = dn->lsu;     /* -> lsu */
52479af3572STom Musta 
52579af3572STom Musta         for (d = 1; d <= dn->digits; up++, d += DECDPUN) {
52679af3572STom Musta             uint64_t prev = hi;
52779af3572STom Musta             hi += *up * powers[d-1];
52879af3572STom Musta             if ((hi < prev) || (hi > INT64_MAX)) {
52979af3572STom Musta                 goto Invalid;
53079af3572STom Musta             }
53179af3572STom Musta         }
53279af3572STom Musta 
53379af3572STom Musta         uint64_t prev = hi;
53479af3572STom Musta         hi *= (uint64_t)powers[dn->exponent];
53579af3572STom Musta         if ((hi < prev) || (hi > INT64_MAX)) {
53679af3572STom Musta             goto Invalid;
53779af3572STom Musta         }
53879af3572STom Musta         return (decNumberIsNegative(dn)) ? -((int64_t)hi) : (int64_t)hi;
53979af3572STom Musta     }
54079af3572STom Musta 
54179af3572STom Musta Invalid:
54279af3572STom Musta     decContextSetStatus(set, DEC_Invalid_operation);
54379af3572STom Musta     return 0;
54479af3572STom Musta } /* decNumberIntegralToInt64 */
54579af3572STom Musta 
546*21d7826fSLuis Pires /* ------------------------------------------------------------------ */
547*21d7826fSLuis Pires /* decNumberIntegralToInt128 -- conversion to int128                  */
548*21d7826fSLuis Pires /*                                                                    */
549*21d7826fSLuis Pires /*  dn is the decNumber to convert.  dn is assumed to have been       */
550*21d7826fSLuis Pires /*    rounded to a floating point integer value.                      */
551*21d7826fSLuis Pires /*  set is the context for reporting errors                           */
552*21d7826fSLuis Pires /*  returns the converted decNumber via plow and phigh                */
553*21d7826fSLuis Pires /*                                                                    */
554*21d7826fSLuis Pires /* Invalid is set if the decNumber is a NaN, Infinite or is out of    */
555*21d7826fSLuis Pires /* range for a signed 128 bit integer.                                */
556*21d7826fSLuis Pires /* ------------------------------------------------------------------ */
557*21d7826fSLuis Pires 
decNumberIntegralToInt128(const decNumber * dn,decContext * set,uint64_t * plow,uint64_t * phigh)558*21d7826fSLuis Pires void decNumberIntegralToInt128(const decNumber *dn, decContext *set,
559*21d7826fSLuis Pires         uint64_t *plow, uint64_t *phigh)
560*21d7826fSLuis Pires {
561*21d7826fSLuis Pires     int d;        /* work */
562*21d7826fSLuis Pires     const Unit *up;   /* .. */
563*21d7826fSLuis Pires     uint64_t lo = 0, hi = 0;
564*21d7826fSLuis Pires 
565*21d7826fSLuis Pires     if (decNumberIsSpecial(dn) || (dn->exponent < 0) ||
566*21d7826fSLuis Pires        (dn->digits + dn->exponent > 39)) {
567*21d7826fSLuis Pires         goto Invalid;
568*21d7826fSLuis Pires     }
569*21d7826fSLuis Pires 
570*21d7826fSLuis Pires     up = dn->lsu;     /* -> lsu */
571*21d7826fSLuis Pires 
572*21d7826fSLuis Pires     for (d = (dn->digits - 1) / DECDPUN; d >= 0; d--) {
573*21d7826fSLuis Pires         if (mulu128(&lo, &hi, DECDPUNMAX + 1)) {
574*21d7826fSLuis Pires             /* overflow */
575*21d7826fSLuis Pires             goto Invalid;
576*21d7826fSLuis Pires         }
577*21d7826fSLuis Pires         if (uadd64_overflow(lo, up[d], &lo)) {
578*21d7826fSLuis Pires             if (uadd64_overflow(hi, 1, &hi)) {
579*21d7826fSLuis Pires                 /* overflow */
580*21d7826fSLuis Pires                 goto Invalid;
581*21d7826fSLuis Pires             }
582*21d7826fSLuis Pires         }
583*21d7826fSLuis Pires     }
584*21d7826fSLuis Pires 
585*21d7826fSLuis Pires     if (mulUInt128ByPowOf10(&lo, &hi, dn->exponent)) {
586*21d7826fSLuis Pires         /* overflow */
587*21d7826fSLuis Pires         goto Invalid;
588*21d7826fSLuis Pires     }
589*21d7826fSLuis Pires 
590*21d7826fSLuis Pires     if (decNumberIsNegative(dn)) {
591*21d7826fSLuis Pires         if (lo == 0) {
592*21d7826fSLuis Pires             *phigh = -hi;
593*21d7826fSLuis Pires             *plow = 0;
594*21d7826fSLuis Pires         } else {
595*21d7826fSLuis Pires             *phigh = ~hi;
596*21d7826fSLuis Pires             *plow = -lo;
597*21d7826fSLuis Pires         }
598*21d7826fSLuis Pires     } else {
599*21d7826fSLuis Pires         *plow = lo;
600*21d7826fSLuis Pires         *phigh = hi;
601*21d7826fSLuis Pires     }
602*21d7826fSLuis Pires 
603*21d7826fSLuis Pires     return;
604*21d7826fSLuis Pires 
605*21d7826fSLuis Pires Invalid:
606*21d7826fSLuis Pires     decContextSetStatus(set, DEC_Invalid_operation);
607*21d7826fSLuis Pires } /* decNumberIntegralToInt128 */
6088e706db2STom Musta 
60972ac97cdSTom Musta /* ------------------------------------------------------------------ */
61072ac97cdSTom Musta /* to-scientific-string -- conversion to numeric string		      */
61172ac97cdSTom Musta /* to-engineering-string -- conversion to numeric string	      */
61272ac97cdSTom Musta /*								      */
61372ac97cdSTom Musta /*   decNumberToString(dn, string);				      */
61472ac97cdSTom Musta /*   decNumberToEngString(dn, string);				      */
61572ac97cdSTom Musta /*								      */
61672ac97cdSTom Musta /*  dn is the decNumber to convert				      */
61772ac97cdSTom Musta /*  string is the string where the result will be laid out	      */
61872ac97cdSTom Musta /*								      */
61972ac97cdSTom Musta /*  string must be at least dn->digits+14 characters long	      */
62072ac97cdSTom Musta /*								      */
62172ac97cdSTom Musta /*  No error is possible, and no status can be set.		      */
62272ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberToString(const decNumber * dn,char * string)62372ac97cdSTom Musta char * decNumberToString(const decNumber *dn, char *string){
62472ac97cdSTom Musta   decToString(dn, string, 0);
62572ac97cdSTom Musta   return string;
62672ac97cdSTom Musta   } /* DecNumberToString */
62772ac97cdSTom Musta 
decNumberToEngString(const decNumber * dn,char * string)62872ac97cdSTom Musta char * decNumberToEngString(const decNumber *dn, char *string){
62972ac97cdSTom Musta   decToString(dn, string, 1);
63072ac97cdSTom Musta   return string;
63172ac97cdSTom Musta   } /* DecNumberToEngString */
63272ac97cdSTom Musta 
63372ac97cdSTom Musta /* ------------------------------------------------------------------ */
63472ac97cdSTom Musta /* to-number -- conversion from numeric string			      */
63572ac97cdSTom Musta /*								      */
63672ac97cdSTom Musta /* decNumberFromString -- convert string to decNumber		      */
63772ac97cdSTom Musta /*   dn	       -- the number structure to fill			      */
63872ac97cdSTom Musta /*   chars[]   -- the string to convert ('\0' terminated)	      */
63972ac97cdSTom Musta /*   set       -- the context used for processing any error,	      */
64072ac97cdSTom Musta /*		  determining the maximum precision available	      */
64172ac97cdSTom Musta /*		  (set.digits), determining the maximum and minimum   */
64272ac97cdSTom Musta /*		  exponent (set.emax and set.emin), determining if    */
64372ac97cdSTom Musta /*		  extended values are allowed, and checking the	      */
64472ac97cdSTom Musta /*		  rounding mode if overflow occurs or rounding is     */
64572ac97cdSTom Musta /*		  needed.					      */
64672ac97cdSTom Musta /*								      */
64772ac97cdSTom Musta /* The length of the coefficient and the size of the exponent are     */
64872ac97cdSTom Musta /* checked by this routine, so the correct error (Underflow or	      */
64972ac97cdSTom Musta /* Overflow) can be reported or rounding applied, as necessary.	      */
65072ac97cdSTom Musta /*								      */
65172ac97cdSTom Musta /* If bad syntax is detected, the result will be a quiet NaN.	      */
65272ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberFromString(decNumber * dn,const char chars[],decContext * set)65372ac97cdSTom Musta decNumber * decNumberFromString(decNumber *dn, const char chars[],
65472ac97cdSTom Musta 				decContext *set) {
65572ac97cdSTom Musta   Int	exponent=0;		   /* working exponent [assume 0] */
65672ac97cdSTom Musta   uByte bits=0;			   /* working flags [assume +ve] */
65772ac97cdSTom Musta   Unit	*res;			   /* where result will be built */
65872ac97cdSTom Musta   Unit	resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */
65972ac97cdSTom Musta 				   /* [+9 allows for ln() constants] */
66072ac97cdSTom Musta   Unit	*allocres=NULL;		   /* -> allocated result, iff allocated */
66172ac97cdSTom Musta   Int	d=0;			   /* count of digits found in decimal part */
66272ac97cdSTom Musta   const char *dotchar=NULL;	   /* where dot was found */
66372ac97cdSTom Musta   const char *cfirst=chars;	   /* -> first character of decimal part */
66472ac97cdSTom Musta   const char *last=NULL;	   /* -> last digit of decimal part */
66572ac97cdSTom Musta   const char *c;		   /* work */
66672ac97cdSTom Musta   Unit	*up;			   /* .. */
66772ac97cdSTom Musta   #if DECDPUN>1
66872ac97cdSTom Musta   Int	cut, out;		   /* .. */
66972ac97cdSTom Musta   #endif
67072ac97cdSTom Musta   Int	residue;		   /* rounding residue */
67172ac97cdSTom Musta   uInt	status=0;		   /* error code */
67272ac97cdSTom Musta 
67372ac97cdSTom Musta   #if DECCHECK
67472ac97cdSTom Musta   if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set))
67572ac97cdSTom Musta     return decNumberZero(dn);
67672ac97cdSTom Musta   #endif
67772ac97cdSTom Musta 
67872ac97cdSTom Musta   do {				   /* status & malloc protection */
67972ac97cdSTom Musta     for (c=chars;; c++) {	   /* -> input character */
68072ac97cdSTom Musta       if (*c>='0' && *c<='9') {	   /* test for Arabic digit */
68172ac97cdSTom Musta 	last=c;
68272ac97cdSTom Musta 	d++;			   /* count of real digits */
68372ac97cdSTom Musta 	continue;		   /* still in decimal part */
68472ac97cdSTom Musta 	}
68572ac97cdSTom Musta       if (*c=='.' && dotchar==NULL) { /* first '.' */
68672ac97cdSTom Musta 	dotchar=c;		   /* record offset into decimal part */
68772ac97cdSTom Musta 	if (c==cfirst) cfirst++;   /* first digit must follow */
68872ac97cdSTom Musta 	continue;}
68972ac97cdSTom Musta       if (c==chars) {		   /* first in string... */
69072ac97cdSTom Musta 	if (*c=='-') {		   /* valid - sign */
69172ac97cdSTom Musta 	  cfirst++;
69272ac97cdSTom Musta 	  bits=DECNEG;
69372ac97cdSTom Musta 	  continue;}
69472ac97cdSTom Musta 	if (*c=='+') {		   /* valid + sign */
69572ac97cdSTom Musta 	  cfirst++;
69672ac97cdSTom Musta 	  continue;}
69772ac97cdSTom Musta 	}
69872ac97cdSTom Musta       /* *c is not a digit, or a valid +, -, or '.' */
69972ac97cdSTom Musta       break;
70072ac97cdSTom Musta       } /* c */
70172ac97cdSTom Musta 
70272ac97cdSTom Musta     if (last==NULL) {		   /* no digits yet */
70372ac97cdSTom Musta       status=DEC_Conversion_syntax;/* assume the worst */
70472ac97cdSTom Musta       if (*c=='\0') break;	   /* and no more to come... */
70572ac97cdSTom Musta       #if DECSUBSET
70672ac97cdSTom Musta       /* if subset then infinities and NaNs are not allowed */
70772ac97cdSTom Musta       if (!set->extended) break;   /* hopeless */
70872ac97cdSTom Musta       #endif
70972ac97cdSTom Musta       /* Infinities and NaNs are possible, here */
71072ac97cdSTom Musta       if (dotchar!=NULL) break;	   /* .. unless had a dot */
71172ac97cdSTom Musta       decNumberZero(dn);	   /* be optimistic */
71272ac97cdSTom Musta       if (decBiStr(c, "infinity", "INFINITY")
71372ac97cdSTom Musta        || decBiStr(c, "inf", "INF")) {
71472ac97cdSTom Musta 	dn->bits=bits | DECINF;
71572ac97cdSTom Musta 	status=0;		   /* is OK */
71672ac97cdSTom Musta 	break; /* all done */
71772ac97cdSTom Musta 	}
71872ac97cdSTom Musta       /* a NaN expected */
71972ac97cdSTom Musta       /* 2003.09.10 NaNs are now permitted to have a sign */
72072ac97cdSTom Musta       dn->bits=bits | DECNAN;	   /* assume simple NaN */
72172ac97cdSTom Musta       if (*c=='s' || *c=='S') {	   /* looks like an sNaN */
72272ac97cdSTom Musta 	c++;
72372ac97cdSTom Musta 	dn->bits=bits | DECSNAN;
72472ac97cdSTom Musta 	}
72572ac97cdSTom Musta       if (*c!='n' && *c!='N') break;	/* check caseless "NaN" */
72672ac97cdSTom Musta       c++;
72772ac97cdSTom Musta       if (*c!='a' && *c!='A') break;	/* .. */
72872ac97cdSTom Musta       c++;
72972ac97cdSTom Musta       if (*c!='n' && *c!='N') break;	/* .. */
73072ac97cdSTom Musta       c++;
73172ac97cdSTom Musta       /* now either nothing, or nnnn payload, expected */
73272ac97cdSTom Musta       /* -> start of integer and skip leading 0s [including plain 0] */
73372ac97cdSTom Musta       for (cfirst=c; *cfirst=='0';) cfirst++;
73472ac97cdSTom Musta       if (*cfirst=='\0') {	   /* "NaN" or "sNaN", maybe with all 0s */
73572ac97cdSTom Musta 	status=0;		   /* it's good */
73672ac97cdSTom Musta 	break;			   /* .. */
73772ac97cdSTom Musta 	}
73872ac97cdSTom Musta       /* something other than 0s; setup last and d as usual [no dots] */
73972ac97cdSTom Musta       for (c=cfirst;; c++, d++) {
74072ac97cdSTom Musta 	if (*c<'0' || *c>'9') break; /* test for Arabic digit */
74172ac97cdSTom Musta 	last=c;
74272ac97cdSTom Musta 	}
74372ac97cdSTom Musta       if (*c!='\0') break;	   /* not all digits */
74472ac97cdSTom Musta       if (d>set->digits-1) {
74572ac97cdSTom Musta 	/* [NB: payload in a decNumber can be full length unless */
74672ac97cdSTom Musta 	/* clamped, in which case can only be digits-1] */
74772ac97cdSTom Musta 	if (set->clamp) break;
74872ac97cdSTom Musta 	if (d>set->digits) break;
74972ac97cdSTom Musta 	} /* too many digits? */
75072ac97cdSTom Musta       /* good; drop through to convert the integer to coefficient */
75172ac97cdSTom Musta       status=0;			   /* syntax is OK */
75272ac97cdSTom Musta       bits=dn->bits;		   /* for copy-back */
75372ac97cdSTom Musta       } /* last==NULL */
75472ac97cdSTom Musta 
75572ac97cdSTom Musta      else if (*c!='\0') {	   /* more to process... */
75672ac97cdSTom Musta       /* had some digits; exponent is only valid sequence now */
75772ac97cdSTom Musta       Flag nege;		   /* 1=negative exponent */
75872ac97cdSTom Musta       const char *firstexp;	   /* -> first significant exponent digit */
75972ac97cdSTom Musta       status=DEC_Conversion_syntax;/* assume the worst */
76072ac97cdSTom Musta       if (*c!='e' && *c!='E') break;
76172ac97cdSTom Musta       /* Found 'e' or 'E' -- now process explicit exponent */
76272ac97cdSTom Musta       /* 1998.07.11: sign no longer required */
76372ac97cdSTom Musta       nege=0;
76472ac97cdSTom Musta       c++;			   /* to (possible) sign */
76572ac97cdSTom Musta       if (*c=='-') {nege=1; c++;}
76672ac97cdSTom Musta        else if (*c=='+') c++;
76772ac97cdSTom Musta       if (*c=='\0') break;
76872ac97cdSTom Musta 
76972ac97cdSTom Musta       for (; *c=='0' && *(c+1)!='\0';) c++;  /* strip insignificant zeros */
77072ac97cdSTom Musta       firstexp=c;			     /* save exponent digit place */
77172ac97cdSTom Musta       for (; ;c++) {
77272ac97cdSTom Musta 	if (*c<'0' || *c>'9') break;	     /* not a digit */
77372ac97cdSTom Musta 	exponent=X10(exponent)+(Int)*c-(Int)'0';
77472ac97cdSTom Musta 	} /* c */
77572ac97cdSTom Musta       /* if not now on a '\0', *c must not be a digit */
77672ac97cdSTom Musta       if (*c!='\0') break;
77772ac97cdSTom Musta 
77872ac97cdSTom Musta       /* (this next test must be after the syntax checks) */
77972ac97cdSTom Musta       /* if it was too long the exponent may have wrapped, so check */
78072ac97cdSTom Musta       /* carefully and set it to a certain overflow if wrap possible */
78172ac97cdSTom Musta       if (c>=firstexp+9+1) {
78272ac97cdSTom Musta 	if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2;
78372ac97cdSTom Musta 	/* [up to 1999999999 is OK, for example 1E-1000000998] */
78472ac97cdSTom Musta 	}
78572ac97cdSTom Musta       if (nege) exponent=-exponent;	/* was negative */
78672ac97cdSTom Musta       status=0;				/* is OK */
78772ac97cdSTom Musta       } /* stuff after digits */
78872ac97cdSTom Musta 
78972ac97cdSTom Musta     /* Here when whole string has been inspected; syntax is good */
79072ac97cdSTom Musta     /* cfirst->first digit (never dot), last->last digit (ditto) */
79172ac97cdSTom Musta 
79272ac97cdSTom Musta     /* strip leading zeros/dot [leave final 0 if all 0's] */
79372ac97cdSTom Musta     if (*cfirst=='0') {			/* [cfirst has stepped over .] */
79472ac97cdSTom Musta       for (c=cfirst; c<last; c++, cfirst++) {
79572ac97cdSTom Musta 	if (*c=='.') continue;		/* ignore dots */
79672ac97cdSTom Musta 	if (*c!='0') break;		/* non-zero found */
79772ac97cdSTom Musta 	d--;				/* 0 stripped */
79872ac97cdSTom Musta 	} /* c */
79972ac97cdSTom Musta       #if DECSUBSET
80072ac97cdSTom Musta       /* make a rapid exit for easy zeros if !extended */
80172ac97cdSTom Musta       if (*cfirst=='0' && !set->extended) {
80272ac97cdSTom Musta 	decNumberZero(dn);		/* clean result */
80372ac97cdSTom Musta 	break;				/* [could be return] */
80472ac97cdSTom Musta 	}
80572ac97cdSTom Musta       #endif
80672ac97cdSTom Musta       } /* at least one leading 0 */
80772ac97cdSTom Musta 
80872ac97cdSTom Musta     /* Handle decimal point... */
80972ac97cdSTom Musta     if (dotchar!=NULL && dotchar<last)	/* non-trailing '.' found? */
81072ac97cdSTom Musta       exponent-=(last-dotchar);		/* adjust exponent */
81172ac97cdSTom Musta     /* [we can now ignore the .] */
81272ac97cdSTom Musta 
81372ac97cdSTom Musta     /* OK, the digits string is good.  Assemble in the decNumber, or in */
81472ac97cdSTom Musta     /* a temporary units array if rounding is needed */
81572ac97cdSTom Musta     if (d<=set->digits) res=dn->lsu;	/* fits into supplied decNumber */
81672ac97cdSTom Musta      else {				/* rounding needed */
81772ac97cdSTom Musta       Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */
81872ac97cdSTom Musta       res=resbuff;			/* assume use local buffer */
81972ac97cdSTom Musta       if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */
82072ac97cdSTom Musta 	allocres=(Unit *)malloc(needbytes);
82172ac97cdSTom Musta 	if (allocres==NULL) {status|=DEC_Insufficient_storage; break;}
82272ac97cdSTom Musta 	res=allocres;
82372ac97cdSTom Musta 	}
82472ac97cdSTom Musta       }
82572ac97cdSTom Musta     /* res now -> number lsu, buffer, or allocated storage for Unit array */
82672ac97cdSTom Musta 
82772ac97cdSTom Musta     /* Place the coefficient into the selected Unit array */
82872ac97cdSTom Musta     /* [this is often 70% of the cost of this function when DECDPUN>1] */
82972ac97cdSTom Musta     #if DECDPUN>1
83072ac97cdSTom Musta     out=0;			   /* accumulator */
83172ac97cdSTom Musta     up=res+D2U(d)-1;		   /* -> msu */
83272ac97cdSTom Musta     cut=d-(up-res)*DECDPUN;	   /* digits in top unit */
83372ac97cdSTom Musta     for (c=cfirst;; c++) {	   /* along the digits */
83472ac97cdSTom Musta       if (*c=='.') continue;	   /* ignore '.' [don't decrement cut] */
83572ac97cdSTom Musta       out=X10(out)+(Int)*c-(Int)'0';
83672ac97cdSTom Musta       if (c==last) break;	   /* done [never get to trailing '.'] */
83772ac97cdSTom Musta       cut--;
83872ac97cdSTom Musta       if (cut>0) continue;	   /* more for this unit */
83972ac97cdSTom Musta       *up=(Unit)out;		   /* write unit */
84072ac97cdSTom Musta       up--;			   /* prepare for unit below.. */
84172ac97cdSTom Musta       cut=DECDPUN;		   /* .. */
84272ac97cdSTom Musta       out=0;			   /* .. */
84372ac97cdSTom Musta       } /* c */
84472ac97cdSTom Musta     *up=(Unit)out;		   /* write lsu */
84572ac97cdSTom Musta 
84672ac97cdSTom Musta     #else
84772ac97cdSTom Musta     /* DECDPUN==1 */
84872ac97cdSTom Musta     up=res;			   /* -> lsu */
84972ac97cdSTom Musta     for (c=last; c>=cfirst; c--) { /* over each character, from least */
85072ac97cdSTom Musta       if (*c=='.') continue;	   /* ignore . [don't step up] */
85172ac97cdSTom Musta       *up=(Unit)((Int)*c-(Int)'0');
85272ac97cdSTom Musta       up++;
85372ac97cdSTom Musta       } /* c */
85472ac97cdSTom Musta     #endif
85572ac97cdSTom Musta 
85672ac97cdSTom Musta     dn->bits=bits;
85772ac97cdSTom Musta     dn->exponent=exponent;
85872ac97cdSTom Musta     dn->digits=d;
85972ac97cdSTom Musta 
86072ac97cdSTom Musta     /* if not in number (too long) shorten into the number */
86172ac97cdSTom Musta     if (d>set->digits) {
86272ac97cdSTom Musta       residue=0;
86372ac97cdSTom Musta       decSetCoeff(dn, set, res, d, &residue, &status);
86472ac97cdSTom Musta       /* always check for overflow or subnormal and round as needed */
86572ac97cdSTom Musta       decFinalize(dn, set, &residue, &status);
86672ac97cdSTom Musta       }
86772ac97cdSTom Musta      else { /* no rounding, but may still have overflow or subnormal */
86872ac97cdSTom Musta       /* [these tests are just for performance; finalize repeats them] */
86972ac97cdSTom Musta       if ((dn->exponent-1<set->emin-dn->digits)
87072ac97cdSTom Musta        || (dn->exponent-1>set->emax-set->digits)) {
87172ac97cdSTom Musta 	residue=0;
87272ac97cdSTom Musta 	decFinalize(dn, set, &residue, &status);
87372ac97cdSTom Musta 	}
87472ac97cdSTom Musta       }
87572ac97cdSTom Musta     /* decNumberShow(dn); */
87672ac97cdSTom Musta     } while(0);				/* [for break] */
87772ac97cdSTom Musta 
87872ac97cdSTom Musta   if (allocres!=NULL) free(allocres);	/* drop any storage used */
87972ac97cdSTom Musta   if (status!=0) decStatus(dn, status, set);
88072ac97cdSTom Musta   return dn;
88172ac97cdSTom Musta   } /* decNumberFromString */
88272ac97cdSTom Musta 
88372ac97cdSTom Musta /* ================================================================== */
88472ac97cdSTom Musta /* Operators							      */
88572ac97cdSTom Musta /* ================================================================== */
88672ac97cdSTom Musta 
88772ac97cdSTom Musta /* ------------------------------------------------------------------ */
88872ac97cdSTom Musta /* decNumberAbs -- absolute value operator			      */
88972ac97cdSTom Musta /*								      */
89072ac97cdSTom Musta /*   This computes C = abs(A)					      */
89172ac97cdSTom Musta /*								      */
89272ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
89372ac97cdSTom Musta /*   rhs is A							      */
89472ac97cdSTom Musta /*   set is the context						      */
89572ac97cdSTom Musta /*								      */
89672ac97cdSTom Musta /* See also decNumberCopyAbs for a quiet bitwise version of this.     */
89772ac97cdSTom Musta /* C must have space for set->digits digits.			      */
89872ac97cdSTom Musta /* ------------------------------------------------------------------ */
89972ac97cdSTom Musta /* This has the same effect as decNumberPlus unless A is negative,    */
90072ac97cdSTom Musta /* in which case it has the same effect as decNumberMinus.	      */
90172ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberAbs(decNumber * res,const decNumber * rhs,decContext * set)90272ac97cdSTom Musta decNumber * decNumberAbs(decNumber *res, const decNumber *rhs,
90372ac97cdSTom Musta 			 decContext *set) {
90472ac97cdSTom Musta   decNumber dzero;			/* for 0 */
90572ac97cdSTom Musta   uInt status=0;			/* accumulator */
90672ac97cdSTom Musta 
90772ac97cdSTom Musta   #if DECCHECK
90872ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
90972ac97cdSTom Musta   #endif
91072ac97cdSTom Musta 
91172ac97cdSTom Musta   decNumberZero(&dzero);		/* set 0 */
91272ac97cdSTom Musta   dzero.exponent=rhs->exponent;		/* [no coefficient expansion] */
91372ac97cdSTom Musta   decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status);
91472ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
91572ac97cdSTom Musta   #if DECCHECK
91672ac97cdSTom Musta   decCheckInexact(res, set);
91772ac97cdSTom Musta   #endif
91872ac97cdSTom Musta   return res;
91972ac97cdSTom Musta   } /* decNumberAbs */
92072ac97cdSTom Musta 
92172ac97cdSTom Musta /* ------------------------------------------------------------------ */
92272ac97cdSTom Musta /* decNumberAdd -- add two Numbers				      */
92372ac97cdSTom Musta /*								      */
92472ac97cdSTom Musta /*   This computes C = A + B					      */
92572ac97cdSTom Musta /*								      */
92672ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X+X)	      */
92772ac97cdSTom Musta /*   lhs is A							      */
92872ac97cdSTom Musta /*   rhs is B							      */
92972ac97cdSTom Musta /*   set is the context						      */
93072ac97cdSTom Musta /*								      */
93172ac97cdSTom Musta /* C must have space for set->digits digits.			      */
93272ac97cdSTom Musta /* ------------------------------------------------------------------ */
93372ac97cdSTom Musta /* This just calls the routine shared with Subtract		      */
decNumberAdd(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)93472ac97cdSTom Musta decNumber * decNumberAdd(decNumber *res, const decNumber *lhs,
93572ac97cdSTom Musta 			 const decNumber *rhs, decContext *set) {
93672ac97cdSTom Musta   uInt status=0;			/* accumulator */
93772ac97cdSTom Musta   decAddOp(res, lhs, rhs, set, 0, &status);
93872ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
93972ac97cdSTom Musta   #if DECCHECK
94072ac97cdSTom Musta   decCheckInexact(res, set);
94172ac97cdSTom Musta   #endif
94272ac97cdSTom Musta   return res;
94372ac97cdSTom Musta   } /* decNumberAdd */
94472ac97cdSTom Musta 
94572ac97cdSTom Musta /* ------------------------------------------------------------------ */
94672ac97cdSTom Musta /* decNumberAnd -- AND two Numbers, digitwise			      */
94772ac97cdSTom Musta /*								      */
94872ac97cdSTom Musta /*   This computes C = A & B					      */
94972ac97cdSTom Musta /*								      */
95072ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X&X)	      */
95172ac97cdSTom Musta /*   lhs is A							      */
95272ac97cdSTom Musta /*   rhs is B							      */
95372ac97cdSTom Musta /*   set is the context (used for result length and error report)     */
95472ac97cdSTom Musta /*								      */
95572ac97cdSTom Musta /* C must have space for set->digits digits.			      */
95672ac97cdSTom Musta /*								      */
95772ac97cdSTom Musta /* Logical function restrictions apply (see above); a NaN is	      */
95872ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
95972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberAnd(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)96072ac97cdSTom Musta decNumber * decNumberAnd(decNumber *res, const decNumber *lhs,
96172ac97cdSTom Musta 			 const decNumber *rhs, decContext *set) {
96272ac97cdSTom Musta   const Unit *ua, *ub;			/* -> operands */
96372ac97cdSTom Musta   const Unit *msua, *msub;		/* -> operand msus */
96472ac97cdSTom Musta   Unit *uc,  *msuc;			/* -> result and its msu */
96572ac97cdSTom Musta   Int	msudigs;			/* digits in res msu */
96672ac97cdSTom Musta   #if DECCHECK
96772ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
96872ac97cdSTom Musta   #endif
96972ac97cdSTom Musta 
97072ac97cdSTom Musta   if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
97172ac97cdSTom Musta    || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
97272ac97cdSTom Musta     decStatus(res, DEC_Invalid_operation, set);
97372ac97cdSTom Musta     return res;
97472ac97cdSTom Musta     }
97572ac97cdSTom Musta 
97672ac97cdSTom Musta   /* operands are valid */
97772ac97cdSTom Musta   ua=lhs->lsu;				/* bottom-up */
97872ac97cdSTom Musta   ub=rhs->lsu;				/* .. */
97972ac97cdSTom Musta   uc=res->lsu;				/* .. */
98072ac97cdSTom Musta   msua=ua+D2U(lhs->digits)-1;		/* -> msu of lhs */
98172ac97cdSTom Musta   msub=ub+D2U(rhs->digits)-1;		/* -> msu of rhs */
98272ac97cdSTom Musta   msuc=uc+D2U(set->digits)-1;		/* -> msu of result */
98372ac97cdSTom Musta   msudigs=MSUDIGITS(set->digits);	/* [faster than remainder] */
98472ac97cdSTom Musta   for (; uc<=msuc; ua++, ub++, uc++) {	/* Unit loop */
98572ac97cdSTom Musta     Unit a, b;				/* extract units */
98672ac97cdSTom Musta     if (ua>msua) a=0;
98772ac97cdSTom Musta      else a=*ua;
98872ac97cdSTom Musta     if (ub>msub) b=0;
98972ac97cdSTom Musta      else b=*ub;
99072ac97cdSTom Musta     *uc=0;				/* can now write back */
99172ac97cdSTom Musta     if (a|b) {				/* maybe 1 bits to examine */
99272ac97cdSTom Musta       Int i, j;
99372ac97cdSTom Musta       *uc=0;				/* can now write back */
99472ac97cdSTom Musta       /* This loop could be unrolled and/or use BIN2BCD tables */
99572ac97cdSTom Musta       for (i=0; i<DECDPUN; i++) {
99672ac97cdSTom Musta 	if (a&b&1) *uc=*uc+(Unit)powers[i];  /* effect AND */
99772ac97cdSTom Musta 	j=a%10;
99872ac97cdSTom Musta 	a=a/10;
99972ac97cdSTom Musta 	j|=b%10;
100072ac97cdSTom Musta 	b=b/10;
100172ac97cdSTom Musta 	if (j>1) {
100272ac97cdSTom Musta 	  decStatus(res, DEC_Invalid_operation, set);
100372ac97cdSTom Musta 	  return res;
100472ac97cdSTom Musta 	  }
100572ac97cdSTom Musta 	if (uc==msuc && i==msudigs-1) break; /* just did final digit */
100672ac97cdSTom Musta 	} /* each digit */
100772ac97cdSTom Musta       } /* both OK */
100872ac97cdSTom Musta     } /* each unit */
100972ac97cdSTom Musta   /* [here uc-1 is the msu of the result] */
101072ac97cdSTom Musta   res->digits=decGetDigits(res->lsu, uc-res->lsu);
101172ac97cdSTom Musta   res->exponent=0;			/* integer */
101272ac97cdSTom Musta   res->bits=0;				/* sign=0 */
101372ac97cdSTom Musta   return res;  /* [no status to set] */
101472ac97cdSTom Musta   } /* decNumberAnd */
101572ac97cdSTom Musta 
101672ac97cdSTom Musta /* ------------------------------------------------------------------ */
101772ac97cdSTom Musta /* decNumberCompare -- compare two Numbers			      */
101872ac97cdSTom Musta /*								      */
101972ac97cdSTom Musta /*   This computes C = A ? B					      */
102072ac97cdSTom Musta /*								      */
102172ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
102272ac97cdSTom Musta /*   lhs is A							      */
102372ac97cdSTom Musta /*   rhs is B							      */
102472ac97cdSTom Musta /*   set is the context						      */
102572ac97cdSTom Musta /*								      */
102672ac97cdSTom Musta /* C must have space for one digit (or NaN).			      */
102772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberCompare(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)102872ac97cdSTom Musta decNumber * decNumberCompare(decNumber *res, const decNumber *lhs,
102972ac97cdSTom Musta 			     const decNumber *rhs, decContext *set) {
103072ac97cdSTom Musta   uInt status=0;			/* accumulator */
103172ac97cdSTom Musta   decCompareOp(res, lhs, rhs, set, COMPARE, &status);
103272ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
103372ac97cdSTom Musta   return res;
103472ac97cdSTom Musta   } /* decNumberCompare */
103572ac97cdSTom Musta 
103672ac97cdSTom Musta /* ------------------------------------------------------------------ */
103772ac97cdSTom Musta /* decNumberCompareSignal -- compare, signalling on all NaNs	      */
103872ac97cdSTom Musta /*								      */
103972ac97cdSTom Musta /*   This computes C = A ? B					      */
104072ac97cdSTom Musta /*								      */
104172ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
104272ac97cdSTom Musta /*   lhs is A							      */
104372ac97cdSTom Musta /*   rhs is B							      */
104472ac97cdSTom Musta /*   set is the context						      */
104572ac97cdSTom Musta /*								      */
104672ac97cdSTom Musta /* C must have space for one digit (or NaN).			      */
104772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberCompareSignal(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)104872ac97cdSTom Musta decNumber * decNumberCompareSignal(decNumber *res, const decNumber *lhs,
104972ac97cdSTom Musta 				   const decNumber *rhs, decContext *set) {
105072ac97cdSTom Musta   uInt status=0;			/* accumulator */
105172ac97cdSTom Musta   decCompareOp(res, lhs, rhs, set, COMPSIG, &status);
105272ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
105372ac97cdSTom Musta   return res;
105472ac97cdSTom Musta   } /* decNumberCompareSignal */
105572ac97cdSTom Musta 
105672ac97cdSTom Musta /* ------------------------------------------------------------------ */
105772ac97cdSTom Musta /* decNumberCompareTotal -- compare two Numbers, using total ordering */
105872ac97cdSTom Musta /*								      */
105972ac97cdSTom Musta /*   This computes C = A ? B, under total ordering		      */
106072ac97cdSTom Musta /*								      */
106172ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
106272ac97cdSTom Musta /*   lhs is A							      */
106372ac97cdSTom Musta /*   rhs is B							      */
106472ac97cdSTom Musta /*   set is the context						      */
106572ac97cdSTom Musta /*								      */
106672ac97cdSTom Musta /* C must have space for one digit; the result will always be one of  */
106772ac97cdSTom Musta /* -1, 0, or 1.							      */
106872ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberCompareTotal(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)106972ac97cdSTom Musta decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs,
107072ac97cdSTom Musta 				  const decNumber *rhs, decContext *set) {
107172ac97cdSTom Musta   uInt status=0;			/* accumulator */
107272ac97cdSTom Musta   decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
107372ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
107472ac97cdSTom Musta   return res;
107572ac97cdSTom Musta   } /* decNumberCompareTotal */
107672ac97cdSTom Musta 
107772ac97cdSTom Musta /* ------------------------------------------------------------------ */
107872ac97cdSTom Musta /* decNumberCompareTotalMag -- compare, total ordering of magnitudes  */
107972ac97cdSTom Musta /*								      */
108072ac97cdSTom Musta /*   This computes C = |A| ? |B|, under total ordering		      */
108172ac97cdSTom Musta /*								      */
108272ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
108372ac97cdSTom Musta /*   lhs is A							      */
108472ac97cdSTom Musta /*   rhs is B							      */
108572ac97cdSTom Musta /*   set is the context						      */
108672ac97cdSTom Musta /*								      */
108772ac97cdSTom Musta /* C must have space for one digit; the result will always be one of  */
108872ac97cdSTom Musta /* -1, 0, or 1.							      */
108972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberCompareTotalMag(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)109072ac97cdSTom Musta decNumber * decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
109172ac97cdSTom Musta 				     const decNumber *rhs, decContext *set) {
109272ac97cdSTom Musta   uInt status=0;		   /* accumulator */
109372ac97cdSTom Musta   uInt needbytes;		   /* for space calculations */
109472ac97cdSTom Musta   decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */
109572ac97cdSTom Musta   decNumber *allocbufa=NULL;	   /* -> allocated bufa, iff allocated */
109672ac97cdSTom Musta   decNumber bufb[D2N(DECBUFFER+1)];
109772ac97cdSTom Musta   decNumber *allocbufb=NULL;	   /* -> allocated bufb, iff allocated */
109872ac97cdSTom Musta   decNumber *a, *b;		   /* temporary pointers */
109972ac97cdSTom Musta 
110072ac97cdSTom Musta   #if DECCHECK
110172ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
110272ac97cdSTom Musta   #endif
110372ac97cdSTom Musta 
110472ac97cdSTom Musta   do {					/* protect allocated storage */
110572ac97cdSTom Musta     /* if either is negative, take a copy and absolute */
110672ac97cdSTom Musta     if (decNumberIsNegative(lhs)) {	/* lhs<0 */
110772ac97cdSTom Musta       a=bufa;
110872ac97cdSTom Musta       needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit);
110972ac97cdSTom Musta       if (needbytes>sizeof(bufa)) {	/* need malloc space */
111072ac97cdSTom Musta 	allocbufa=(decNumber *)malloc(needbytes);
111172ac97cdSTom Musta 	if (allocbufa==NULL) {		/* hopeless -- abandon */
111272ac97cdSTom Musta 	  status|=DEC_Insufficient_storage;
111372ac97cdSTom Musta 	  break;}
111472ac97cdSTom Musta 	a=allocbufa;			/* use the allocated space */
111572ac97cdSTom Musta 	}
111672ac97cdSTom Musta       decNumberCopy(a, lhs);		/* copy content */
111772ac97cdSTom Musta       a->bits&=~DECNEG;			/* .. and clear the sign */
111872ac97cdSTom Musta       lhs=a;				/* use copy from here on */
111972ac97cdSTom Musta       }
112072ac97cdSTom Musta     if (decNumberIsNegative(rhs)) {	/* rhs<0 */
112172ac97cdSTom Musta       b=bufb;
112272ac97cdSTom Musta       needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
112372ac97cdSTom Musta       if (needbytes>sizeof(bufb)) {	/* need malloc space */
112472ac97cdSTom Musta 	allocbufb=(decNumber *)malloc(needbytes);
112572ac97cdSTom Musta 	if (allocbufb==NULL) {		/* hopeless -- abandon */
112672ac97cdSTom Musta 	  status|=DEC_Insufficient_storage;
112772ac97cdSTom Musta 	  break;}
112872ac97cdSTom Musta 	b=allocbufb;			/* use the allocated space */
112972ac97cdSTom Musta 	}
113072ac97cdSTom Musta       decNumberCopy(b, rhs);		/* copy content */
113172ac97cdSTom Musta       b->bits&=~DECNEG;			/* .. and clear the sign */
113272ac97cdSTom Musta       rhs=b;				/* use copy from here on */
113372ac97cdSTom Musta       }
113472ac97cdSTom Musta     decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
113572ac97cdSTom Musta     } while(0);				/* end protected */
113672ac97cdSTom Musta 
113772ac97cdSTom Musta   if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
113872ac97cdSTom Musta   if (allocbufb!=NULL) free(allocbufb); /* .. */
113972ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
114072ac97cdSTom Musta   return res;
114172ac97cdSTom Musta   } /* decNumberCompareTotalMag */
114272ac97cdSTom Musta 
114372ac97cdSTom Musta /* ------------------------------------------------------------------ */
114472ac97cdSTom Musta /* decNumberDivide -- divide one number by another		      */
114572ac97cdSTom Musta /*								      */
114672ac97cdSTom Musta /*   This computes C = A / B					      */
114772ac97cdSTom Musta /*								      */
114872ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X/X)	      */
114972ac97cdSTom Musta /*   lhs is A							      */
115072ac97cdSTom Musta /*   rhs is B							      */
115172ac97cdSTom Musta /*   set is the context						      */
115272ac97cdSTom Musta /*								      */
115372ac97cdSTom Musta /* C must have space for set->digits digits.			      */
115472ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberDivide(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)115572ac97cdSTom Musta decNumber * decNumberDivide(decNumber *res, const decNumber *lhs,
115672ac97cdSTom Musta 			    const decNumber *rhs, decContext *set) {
115772ac97cdSTom Musta   uInt status=0;			/* accumulator */
115872ac97cdSTom Musta   decDivideOp(res, lhs, rhs, set, DIVIDE, &status);
115972ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
116072ac97cdSTom Musta   #if DECCHECK
116172ac97cdSTom Musta   decCheckInexact(res, set);
116272ac97cdSTom Musta   #endif
116372ac97cdSTom Musta   return res;
116472ac97cdSTom Musta   } /* decNumberDivide */
116572ac97cdSTom Musta 
116672ac97cdSTom Musta /* ------------------------------------------------------------------ */
116772ac97cdSTom Musta /* decNumberDivideInteger -- divide and return integer quotient	      */
116872ac97cdSTom Musta /*								      */
116972ac97cdSTom Musta /*   This computes C = A # B, where # is the integer divide operator  */
117072ac97cdSTom Musta /*								      */
117172ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X#X)	      */
117272ac97cdSTom Musta /*   lhs is A							      */
117372ac97cdSTom Musta /*   rhs is B							      */
117472ac97cdSTom Musta /*   set is the context						      */
117572ac97cdSTom Musta /*								      */
117672ac97cdSTom Musta /* C must have space for set->digits digits.			      */
117772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberDivideInteger(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)117872ac97cdSTom Musta decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs,
117972ac97cdSTom Musta 				   const decNumber *rhs, decContext *set) {
118072ac97cdSTom Musta   uInt status=0;			/* accumulator */
118172ac97cdSTom Musta   decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status);
118272ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
118372ac97cdSTom Musta   return res;
118472ac97cdSTom Musta   } /* decNumberDivideInteger */
118572ac97cdSTom Musta 
118672ac97cdSTom Musta /* ------------------------------------------------------------------ */
118772ac97cdSTom Musta /* decNumberExp -- exponentiation				      */
118872ac97cdSTom Musta /*								      */
118972ac97cdSTom Musta /*   This computes C = exp(A)					      */
119072ac97cdSTom Musta /*								      */
119172ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
119272ac97cdSTom Musta /*   rhs is A							      */
119372ac97cdSTom Musta /*   set is the context; note that rounding mode has no effect	      */
119472ac97cdSTom Musta /*								      */
119572ac97cdSTom Musta /* C must have space for set->digits digits.			      */
119672ac97cdSTom Musta /*								      */
119772ac97cdSTom Musta /* Mathematical function restrictions apply (see above); a NaN is     */
119872ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
119972ac97cdSTom Musta /*								      */
120072ac97cdSTom Musta /* Finite results will always be full precision and Inexact, except   */
120172ac97cdSTom Musta /* when A is a zero or -Infinity (giving 1 or 0 respectively).	      */
120272ac97cdSTom Musta /*								      */
120372ac97cdSTom Musta /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
120472ac97cdSTom Musta /* almost always be correctly rounded, but may be up to 1 ulp in      */
120572ac97cdSTom Musta /* error in rare cases.						      */
120672ac97cdSTom Musta /* ------------------------------------------------------------------ */
120772ac97cdSTom Musta /* This is a wrapper for decExpOp which can handle the slightly wider */
120872ac97cdSTom Musta /* (double) range needed by Ln (which has to be able to calculate     */
120972ac97cdSTom Musta /* exp(-a) where a can be the tiniest number (Ntiny).		      */
121072ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberExp(decNumber * res,const decNumber * rhs,decContext * set)121172ac97cdSTom Musta decNumber * decNumberExp(decNumber *res, const decNumber *rhs,
121272ac97cdSTom Musta 			 decContext *set) {
121372ac97cdSTom Musta   uInt status=0;			/* accumulator */
121472ac97cdSTom Musta   #if DECSUBSET
121572ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* non-NULL if rounded rhs allocated */
121672ac97cdSTom Musta   #endif
121772ac97cdSTom Musta 
121872ac97cdSTom Musta   #if DECCHECK
121972ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
122072ac97cdSTom Musta   #endif
122172ac97cdSTom Musta 
122272ac97cdSTom Musta   /* Check restrictions; these restrictions ensure that if h=8 (see */
122372ac97cdSTom Musta   /* decExpOp) then the result will either overflow or underflow to 0. */
122472ac97cdSTom Musta   /* Other math functions restrict the input range, too, for inverses. */
122572ac97cdSTom Musta   /* If not violated then carry out the operation. */
122672ac97cdSTom Musta   if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
122772ac97cdSTom Musta     #if DECSUBSET
122872ac97cdSTom Musta     if (!set->extended) {
122972ac97cdSTom Musta       /* reduce operand and set lostDigits status, as needed */
123072ac97cdSTom Musta       if (rhs->digits>set->digits) {
123172ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, &status);
123272ac97cdSTom Musta 	if (allocrhs==NULL) break;
123372ac97cdSTom Musta 	rhs=allocrhs;
123472ac97cdSTom Musta 	}
123572ac97cdSTom Musta       }
123672ac97cdSTom Musta     #endif
123772ac97cdSTom Musta     decExpOp(res, rhs, set, &status);
123872ac97cdSTom Musta     } while(0);				/* end protected */
123972ac97cdSTom Musta 
124072ac97cdSTom Musta   #if DECSUBSET
124172ac97cdSTom Musta   if (allocrhs !=NULL) free(allocrhs);	/* drop any storage used */
124272ac97cdSTom Musta   #endif
124372ac97cdSTom Musta   /* apply significant status */
124472ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
124572ac97cdSTom Musta   #if DECCHECK
124672ac97cdSTom Musta   decCheckInexact(res, set);
124772ac97cdSTom Musta   #endif
124872ac97cdSTom Musta   return res;
124972ac97cdSTom Musta   } /* decNumberExp */
125072ac97cdSTom Musta 
125172ac97cdSTom Musta /* ------------------------------------------------------------------ */
125272ac97cdSTom Musta /* decNumberFMA -- fused multiply add				      */
125372ac97cdSTom Musta /*								      */
125472ac97cdSTom Musta /*   This computes D = (A * B) + C with only one rounding	      */
125572ac97cdSTom Musta /*								      */
125672ac97cdSTom Musta /*   res is D, the result.  D may be A or B or C (e.g., X=FMA(X,X,X)) */
125772ac97cdSTom Musta /*   lhs is A							      */
125872ac97cdSTom Musta /*   rhs is B							      */
125972ac97cdSTom Musta /*   fhs is C [far hand side]					      */
126072ac97cdSTom Musta /*   set is the context						      */
126172ac97cdSTom Musta /*								      */
126272ac97cdSTom Musta /* Mathematical function restrictions apply (see above); a NaN is     */
126372ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
126472ac97cdSTom Musta /*								      */
126572ac97cdSTom Musta /* C must have space for set->digits digits.			      */
126672ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberFMA(decNumber * res,const decNumber * lhs,const decNumber * rhs,const decNumber * fhs,decContext * set)126772ac97cdSTom Musta decNumber * decNumberFMA(decNumber *res, const decNumber *lhs,
126872ac97cdSTom Musta 			 const decNumber *rhs, const decNumber *fhs,
126972ac97cdSTom Musta 			 decContext *set) {
127072ac97cdSTom Musta   uInt status=0;		   /* accumulator */
127172ac97cdSTom Musta   decContext dcmul;		   /* context for the multiplication */
127272ac97cdSTom Musta   uInt needbytes;		   /* for space calculations */
127372ac97cdSTom Musta   decNumber bufa[D2N(DECBUFFER*2+1)];
127472ac97cdSTom Musta   decNumber *allocbufa=NULL;	   /* -> allocated bufa, iff allocated */
127572ac97cdSTom Musta   decNumber *acc;		   /* accumulator pointer */
127672ac97cdSTom Musta   decNumber dzero;		   /* work */
127772ac97cdSTom Musta 
127872ac97cdSTom Musta   #if DECCHECK
127972ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
128072ac97cdSTom Musta   if (decCheckOperands(res, fhs, DECUNUSED, set)) return res;
128172ac97cdSTom Musta   #endif
128272ac97cdSTom Musta 
128372ac97cdSTom Musta   do {					/* protect allocated storage */
128472ac97cdSTom Musta     #if DECSUBSET
128572ac97cdSTom Musta     if (!set->extended) {		/* [undefined if subset] */
128672ac97cdSTom Musta       status|=DEC_Invalid_operation;
128772ac97cdSTom Musta       break;}
128872ac97cdSTom Musta     #endif
128972ac97cdSTom Musta     /* Check math restrictions [these ensure no overflow or underflow] */
129072ac97cdSTom Musta     if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status))
129172ac97cdSTom Musta      || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status))
129272ac97cdSTom Musta      || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break;
129372ac97cdSTom Musta     /* set up context for multiply */
129472ac97cdSTom Musta     dcmul=*set;
129572ac97cdSTom Musta     dcmul.digits=lhs->digits+rhs->digits; /* just enough */
129672ac97cdSTom Musta     /* [The above may be an over-estimate for subset arithmetic, but that's OK] */
129772ac97cdSTom Musta     dcmul.emax=DEC_MAX_EMAX;		/* effectively unbounded .. */
129872ac97cdSTom Musta     dcmul.emin=DEC_MIN_EMIN;		/* [thanks to Math restrictions] */
129972ac97cdSTom Musta     /* set up decNumber space to receive the result of the multiply */
130072ac97cdSTom Musta     acc=bufa;				/* may fit */
130172ac97cdSTom Musta     needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit);
130272ac97cdSTom Musta     if (needbytes>sizeof(bufa)) {	/* need malloc space */
130372ac97cdSTom Musta       allocbufa=(decNumber *)malloc(needbytes);
130472ac97cdSTom Musta       if (allocbufa==NULL) {		/* hopeless -- abandon */
130572ac97cdSTom Musta 	status|=DEC_Insufficient_storage;
130672ac97cdSTom Musta 	break;}
130772ac97cdSTom Musta       acc=allocbufa;			/* use the allocated space */
130872ac97cdSTom Musta       }
130972ac97cdSTom Musta     /* multiply with extended range and necessary precision */
131072ac97cdSTom Musta     /*printf("emin=%ld\n", dcmul.emin); */
131172ac97cdSTom Musta     decMultiplyOp(acc, lhs, rhs, &dcmul, &status);
131272ac97cdSTom Musta     /* Only Invalid operation (from sNaN or Inf * 0) is possible in */
131372ac97cdSTom Musta     /* status; if either is seen than ignore fhs (in case it is */
131472ac97cdSTom Musta     /* another sNaN) and set acc to NaN unless we had an sNaN */
131572ac97cdSTom Musta     /* [decMultiplyOp leaves that to caller] */
131672ac97cdSTom Musta     /* Note sNaN has to go through addOp to shorten payload if */
131772ac97cdSTom Musta     /* necessary */
131872ac97cdSTom Musta     if ((status&DEC_Invalid_operation)!=0) {
131972ac97cdSTom Musta       if (!(status&DEC_sNaN)) {		/* but be true invalid */
132072ac97cdSTom Musta 	decNumberZero(res);		/* acc not yet set */
132172ac97cdSTom Musta 	res->bits=DECNAN;
132272ac97cdSTom Musta 	break;
132372ac97cdSTom Musta 	}
132472ac97cdSTom Musta       decNumberZero(&dzero);		/* make 0 (any non-NaN would do) */
132572ac97cdSTom Musta       fhs=&dzero;			/* use that */
132672ac97cdSTom Musta       }
132772ac97cdSTom Musta     #if DECCHECK
132872ac97cdSTom Musta      else { /* multiply was OK */
132972ac97cdSTom Musta       if (status!=0) printf("Status=%08lx after FMA multiply\n", status);
133072ac97cdSTom Musta       }
133172ac97cdSTom Musta     #endif
133272ac97cdSTom Musta     /* add the third operand and result -> res, and all is done */
133372ac97cdSTom Musta     decAddOp(res, acc, fhs, set, 0, &status);
133472ac97cdSTom Musta     } while(0);				/* end protected */
133572ac97cdSTom Musta 
133672ac97cdSTom Musta   if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
133772ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
133872ac97cdSTom Musta   #if DECCHECK
133972ac97cdSTom Musta   decCheckInexact(res, set);
134072ac97cdSTom Musta   #endif
134172ac97cdSTom Musta   return res;
134272ac97cdSTom Musta   } /* decNumberFMA */
134372ac97cdSTom Musta 
134472ac97cdSTom Musta /* ------------------------------------------------------------------ */
134572ac97cdSTom Musta /* decNumberInvert -- invert a Number, digitwise		      */
134672ac97cdSTom Musta /*								      */
134772ac97cdSTom Musta /*   This computes C = ~A					      */
134872ac97cdSTom Musta /*								      */
134972ac97cdSTom Musta /*   res is C, the result.  C may be A (e.g., X=~X)		      */
135072ac97cdSTom Musta /*   rhs is A							      */
135172ac97cdSTom Musta /*   set is the context (used for result length and error report)     */
135272ac97cdSTom Musta /*								      */
135372ac97cdSTom Musta /* C must have space for set->digits digits.			      */
135472ac97cdSTom Musta /*								      */
135572ac97cdSTom Musta /* Logical function restrictions apply (see above); a NaN is	      */
135672ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
135772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberInvert(decNumber * res,const decNumber * rhs,decContext * set)135872ac97cdSTom Musta decNumber * decNumberInvert(decNumber *res, const decNumber *rhs,
135972ac97cdSTom Musta 			    decContext *set) {
136072ac97cdSTom Musta   const Unit *ua, *msua;		/* -> operand and its msu */
136172ac97cdSTom Musta   Unit	*uc, *msuc;			/* -> result and its msu */
136272ac97cdSTom Musta   Int	msudigs;			/* digits in res msu */
136372ac97cdSTom Musta   #if DECCHECK
136472ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
136572ac97cdSTom Musta   #endif
136672ac97cdSTom Musta 
136772ac97cdSTom Musta   if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
136872ac97cdSTom Musta     decStatus(res, DEC_Invalid_operation, set);
136972ac97cdSTom Musta     return res;
137072ac97cdSTom Musta     }
137172ac97cdSTom Musta   /* operand is valid */
137272ac97cdSTom Musta   ua=rhs->lsu;				/* bottom-up */
137372ac97cdSTom Musta   uc=res->lsu;				/* .. */
137472ac97cdSTom Musta   msua=ua+D2U(rhs->digits)-1;		/* -> msu of rhs */
137572ac97cdSTom Musta   msuc=uc+D2U(set->digits)-1;		/* -> msu of result */
137672ac97cdSTom Musta   msudigs=MSUDIGITS(set->digits);	/* [faster than remainder] */
137772ac97cdSTom Musta   for (; uc<=msuc; ua++, uc++) {	/* Unit loop */
137872ac97cdSTom Musta     Unit a;				/* extract unit */
137972ac97cdSTom Musta     Int	 i, j;				/* work */
138072ac97cdSTom Musta     if (ua>msua) a=0;
138172ac97cdSTom Musta      else a=*ua;
138272ac97cdSTom Musta     *uc=0;				/* can now write back */
138372ac97cdSTom Musta     /* always need to examine all bits in rhs */
138472ac97cdSTom Musta     /* This loop could be unrolled and/or use BIN2BCD tables */
138572ac97cdSTom Musta     for (i=0; i<DECDPUN; i++) {
138672ac97cdSTom Musta       if ((~a)&1) *uc=*uc+(Unit)powers[i];   /* effect INVERT */
138772ac97cdSTom Musta       j=a%10;
138872ac97cdSTom Musta       a=a/10;
138972ac97cdSTom Musta       if (j>1) {
139072ac97cdSTom Musta 	decStatus(res, DEC_Invalid_operation, set);
139172ac97cdSTom Musta 	return res;
139272ac97cdSTom Musta 	}
139372ac97cdSTom Musta       if (uc==msuc && i==msudigs-1) break;   /* just did final digit */
139472ac97cdSTom Musta       } /* each digit */
139572ac97cdSTom Musta     } /* each unit */
139672ac97cdSTom Musta   /* [here uc-1 is the msu of the result] */
139772ac97cdSTom Musta   res->digits=decGetDigits(res->lsu, uc-res->lsu);
139872ac97cdSTom Musta   res->exponent=0;			/* integer */
139972ac97cdSTom Musta   res->bits=0;				/* sign=0 */
140072ac97cdSTom Musta   return res;  /* [no status to set] */
140172ac97cdSTom Musta   } /* decNumberInvert */
140272ac97cdSTom Musta 
140372ac97cdSTom Musta /* ------------------------------------------------------------------ */
140472ac97cdSTom Musta /* decNumberLn -- natural logarithm				      */
140572ac97cdSTom Musta /*								      */
140672ac97cdSTom Musta /*   This computes C = ln(A)					      */
140772ac97cdSTom Musta /*								      */
140872ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
140972ac97cdSTom Musta /*   rhs is A							      */
141072ac97cdSTom Musta /*   set is the context; note that rounding mode has no effect	      */
141172ac97cdSTom Musta /*								      */
141272ac97cdSTom Musta /* C must have space for set->digits digits.			      */
141372ac97cdSTom Musta /*								      */
141472ac97cdSTom Musta /* Notable cases:						      */
141572ac97cdSTom Musta /*   A<0 -> Invalid						      */
141672ac97cdSTom Musta /*   A=0 -> -Infinity (Exact)					      */
141772ac97cdSTom Musta /*   A=+Infinity -> +Infinity (Exact)				      */
141872ac97cdSTom Musta /*   A=1 exactly -> 0 (Exact)					      */
141972ac97cdSTom Musta /*								      */
142072ac97cdSTom Musta /* Mathematical function restrictions apply (see above); a NaN is     */
142172ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
142272ac97cdSTom Musta /*								      */
142372ac97cdSTom Musta /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
142472ac97cdSTom Musta /* almost always be correctly rounded, but may be up to 1 ulp in      */
142572ac97cdSTom Musta /* error in rare cases.						      */
142672ac97cdSTom Musta /* ------------------------------------------------------------------ */
142772ac97cdSTom Musta /* This is a wrapper for decLnOp which can handle the slightly wider  */
142872ac97cdSTom Musta /* (+11) range needed by Ln, Log10, etc. (which may have to be able   */
142972ac97cdSTom Musta /* to calculate at p+e+2).					      */
143072ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberLn(decNumber * res,const decNumber * rhs,decContext * set)143172ac97cdSTom Musta decNumber * decNumberLn(decNumber *res, const decNumber *rhs,
143272ac97cdSTom Musta 			decContext *set) {
143372ac97cdSTom Musta   uInt status=0;		   /* accumulator */
143472ac97cdSTom Musta   #if DECSUBSET
143572ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* non-NULL if rounded rhs allocated */
143672ac97cdSTom Musta   #endif
143772ac97cdSTom Musta 
143872ac97cdSTom Musta   #if DECCHECK
143972ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
144072ac97cdSTom Musta   #endif
144172ac97cdSTom Musta 
144272ac97cdSTom Musta   /* Check restrictions; this is a math function; if not violated */
144372ac97cdSTom Musta   /* then carry out the operation. */
144472ac97cdSTom Musta   if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
144572ac97cdSTom Musta     #if DECSUBSET
144672ac97cdSTom Musta     if (!set->extended) {
144772ac97cdSTom Musta       /* reduce operand and set lostDigits status, as needed */
144872ac97cdSTom Musta       if (rhs->digits>set->digits) {
144972ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, &status);
145072ac97cdSTom Musta 	if (allocrhs==NULL) break;
145172ac97cdSTom Musta 	rhs=allocrhs;
145272ac97cdSTom Musta 	}
145372ac97cdSTom Musta       /* special check in subset for rhs=0 */
145472ac97cdSTom Musta       if (ISZERO(rhs)) {		/* +/- zeros -> error */
145572ac97cdSTom Musta 	status|=DEC_Invalid_operation;
145672ac97cdSTom Musta 	break;}
145772ac97cdSTom Musta       } /* extended=0 */
145872ac97cdSTom Musta     #endif
145972ac97cdSTom Musta     decLnOp(res, rhs, set, &status);
146072ac97cdSTom Musta     } while(0);				/* end protected */
146172ac97cdSTom Musta 
146272ac97cdSTom Musta   #if DECSUBSET
146372ac97cdSTom Musta   if (allocrhs !=NULL) free(allocrhs);	/* drop any storage used */
146472ac97cdSTom Musta   #endif
146572ac97cdSTom Musta   /* apply significant status */
146672ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
146772ac97cdSTom Musta   #if DECCHECK
146872ac97cdSTom Musta   decCheckInexact(res, set);
146972ac97cdSTom Musta   #endif
147072ac97cdSTom Musta   return res;
147172ac97cdSTom Musta   } /* decNumberLn */
147272ac97cdSTom Musta 
147372ac97cdSTom Musta /* ------------------------------------------------------------------ */
147472ac97cdSTom Musta /* decNumberLogB - get adjusted exponent, by 754r rules		      */
147572ac97cdSTom Musta /*								      */
147672ac97cdSTom Musta /*   This computes C = adjustedexponent(A)			      */
147772ac97cdSTom Musta /*								      */
147872ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
147972ac97cdSTom Musta /*   rhs is A							      */
148072ac97cdSTom Musta /*   set is the context, used only for digits and status	      */
148172ac97cdSTom Musta /*								      */
148272ac97cdSTom Musta /* C must have space for 10 digits (A might have 10**9 digits and     */
148372ac97cdSTom Musta /* an exponent of +999999999, or one digit and an exponent of	      */
148472ac97cdSTom Musta /* -1999999999).						      */
148572ac97cdSTom Musta /*								      */
148672ac97cdSTom Musta /* This returns the adjusted exponent of A after (in theory) padding  */
148772ac97cdSTom Musta /* with zeros on the right to set->digits digits while keeping the    */
148872ac97cdSTom Musta /* same value.	The exponent is not limited by emin/emax.	      */
148972ac97cdSTom Musta /*								      */
149072ac97cdSTom Musta /* Notable cases:						      */
149172ac97cdSTom Musta /*   A<0 -> Use |A|						      */
149272ac97cdSTom Musta /*   A=0 -> -Infinity (Division by zero)			      */
149372ac97cdSTom Musta /*   A=Infinite -> +Infinity (Exact)				      */
149472ac97cdSTom Musta /*   A=1 exactly -> 0 (Exact)					      */
149572ac97cdSTom Musta /*   NaNs are propagated as usual				      */
149672ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberLogB(decNumber * res,const decNumber * rhs,decContext * set)149772ac97cdSTom Musta decNumber * decNumberLogB(decNumber *res, const decNumber *rhs,
149872ac97cdSTom Musta 			  decContext *set) {
149972ac97cdSTom Musta   uInt status=0;		   /* accumulator */
150072ac97cdSTom Musta 
150172ac97cdSTom Musta   #if DECCHECK
150272ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
150372ac97cdSTom Musta   #endif
150472ac97cdSTom Musta 
150572ac97cdSTom Musta   /* NaNs as usual; Infinities return +Infinity; 0->oops */
150672ac97cdSTom Musta   if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status);
150772ac97cdSTom Musta    else if (decNumberIsInfinite(rhs)) decNumberCopyAbs(res, rhs);
150872ac97cdSTom Musta    else if (decNumberIsZero(rhs)) {
150972ac97cdSTom Musta     decNumberZero(res);			/* prepare for Infinity */
151072ac97cdSTom Musta     res->bits=DECNEG|DECINF;		/* -Infinity */
151172ac97cdSTom Musta     status|=DEC_Division_by_zero;	/* as per 754r */
151272ac97cdSTom Musta     }
151372ac97cdSTom Musta    else { /* finite non-zero */
151472ac97cdSTom Musta     Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */
151572ac97cdSTom Musta     decNumberFromInt32(res, ae);	/* lay it out */
151672ac97cdSTom Musta     }
151772ac97cdSTom Musta 
151872ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
151972ac97cdSTom Musta   return res;
152072ac97cdSTom Musta   } /* decNumberLogB */
152172ac97cdSTom Musta 
152272ac97cdSTom Musta /* ------------------------------------------------------------------ */
152372ac97cdSTom Musta /* decNumberLog10 -- logarithm in base 10			      */
152472ac97cdSTom Musta /*								      */
152572ac97cdSTom Musta /*   This computes C = log10(A)					      */
152672ac97cdSTom Musta /*								      */
152772ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
152872ac97cdSTom Musta /*   rhs is A							      */
152972ac97cdSTom Musta /*   set is the context; note that rounding mode has no effect	      */
153072ac97cdSTom Musta /*								      */
153172ac97cdSTom Musta /* C must have space for set->digits digits.			      */
153272ac97cdSTom Musta /*								      */
153372ac97cdSTom Musta /* Notable cases:						      */
153472ac97cdSTom Musta /*   A<0 -> Invalid						      */
153572ac97cdSTom Musta /*   A=0 -> -Infinity (Exact)					      */
153672ac97cdSTom Musta /*   A=+Infinity -> +Infinity (Exact)				      */
153772ac97cdSTom Musta /*   A=10**n (if n is an integer) -> n (Exact)			      */
153872ac97cdSTom Musta /*								      */
153972ac97cdSTom Musta /* Mathematical function restrictions apply (see above); a NaN is     */
154072ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
154172ac97cdSTom Musta /*								      */
154272ac97cdSTom Musta /* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
154372ac97cdSTom Musta /* almost always be correctly rounded, but may be up to 1 ulp in      */
154472ac97cdSTom Musta /* error in rare cases.						      */
154572ac97cdSTom Musta /* ------------------------------------------------------------------ */
154672ac97cdSTom Musta /* This calculates ln(A)/ln(10) using appropriate precision.  For     */
154772ac97cdSTom Musta /* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the      */
154872ac97cdSTom Musta /* requested digits and t is the number of digits in the exponent     */
154972ac97cdSTom Musta /* (maximum 6).	 For ln(10) it is p + 3; this is often handled by the */
155072ac97cdSTom Musta /* fastpath in decLnOp.	 The final division is done to the requested  */
155172ac97cdSTom Musta /* precision.							      */
155272ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberLog10(decNumber * res,const decNumber * rhs,decContext * set)155372ac97cdSTom Musta decNumber * decNumberLog10(decNumber *res, const decNumber *rhs,
155472ac97cdSTom Musta 			  decContext *set) {
155572ac97cdSTom Musta   uInt status=0, ignore=0;	   /* status accumulators */
155672ac97cdSTom Musta   uInt needbytes;		   /* for space calculations */
155772ac97cdSTom Musta   Int p;			   /* working precision */
155872ac97cdSTom Musta   Int t;			   /* digits in exponent of A */
155972ac97cdSTom Musta 
156072ac97cdSTom Musta   /* buffers for a and b working decimals */
156172ac97cdSTom Musta   /* (adjustment calculator, same size) */
156272ac97cdSTom Musta   decNumber bufa[D2N(DECBUFFER+2)];
156372ac97cdSTom Musta   decNumber *allocbufa=NULL;	   /* -> allocated bufa, iff allocated */
156472ac97cdSTom Musta   decNumber *a=bufa;		   /* temporary a */
156572ac97cdSTom Musta   decNumber bufb[D2N(DECBUFFER+2)];
156672ac97cdSTom Musta   decNumber *allocbufb=NULL;	   /* -> allocated bufb, iff allocated */
156772ac97cdSTom Musta   decNumber *b=bufb;		   /* temporary b */
156872ac97cdSTom Musta   decNumber bufw[D2N(10)];	   /* working 2-10 digit number */
156972ac97cdSTom Musta   decNumber *w=bufw;		   /* .. */
157072ac97cdSTom Musta   #if DECSUBSET
157172ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* non-NULL if rounded rhs allocated */
157272ac97cdSTom Musta   #endif
157372ac97cdSTom Musta 
157472ac97cdSTom Musta   decContext aset;		   /* working context */
157572ac97cdSTom Musta 
157672ac97cdSTom Musta   #if DECCHECK
157772ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
157872ac97cdSTom Musta   #endif
157972ac97cdSTom Musta 
158072ac97cdSTom Musta   /* Check restrictions; this is a math function; if not violated */
158172ac97cdSTom Musta   /* then carry out the operation. */
158272ac97cdSTom Musta   if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */
158372ac97cdSTom Musta     #if DECSUBSET
158472ac97cdSTom Musta     if (!set->extended) {
158572ac97cdSTom Musta       /* reduce operand and set lostDigits status, as needed */
158672ac97cdSTom Musta       if (rhs->digits>set->digits) {
158772ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, &status);
158872ac97cdSTom Musta 	if (allocrhs==NULL) break;
158972ac97cdSTom Musta 	rhs=allocrhs;
159072ac97cdSTom Musta 	}
159172ac97cdSTom Musta       /* special check in subset for rhs=0 */
159272ac97cdSTom Musta       if (ISZERO(rhs)) {		/* +/- zeros -> error */
159372ac97cdSTom Musta 	status|=DEC_Invalid_operation;
159472ac97cdSTom Musta 	break;}
159572ac97cdSTom Musta       } /* extended=0 */
159672ac97cdSTom Musta     #endif
159772ac97cdSTom Musta 
159872ac97cdSTom Musta     decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
159972ac97cdSTom Musta 
160072ac97cdSTom Musta     /* handle exact powers of 10; only check if +ve finite */
160172ac97cdSTom Musta     if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) {
160272ac97cdSTom Musta       Int residue=0;		   /* (no residue) */
160372ac97cdSTom Musta       uInt copystat=0;		   /* clean status */
160472ac97cdSTom Musta 
160572ac97cdSTom Musta       /* round to a single digit... */
160672ac97cdSTom Musta       aset.digits=1;
160772ac97cdSTom Musta       decCopyFit(w, rhs, &aset, &residue, &copystat); /* copy & shorten */
160872ac97cdSTom Musta       /* if exact and the digit is 1, rhs is a power of 10 */
160972ac97cdSTom Musta       if (!(copystat&DEC_Inexact) && w->lsu[0]==1) {
161072ac97cdSTom Musta 	/* the exponent, conveniently, is the power of 10; making */
161172ac97cdSTom Musta 	/* this the result needs a little care as it might not fit, */
161272ac97cdSTom Musta 	/* so first convert it into the working number, and then move */
161372ac97cdSTom Musta 	/* to res */
161472ac97cdSTom Musta 	decNumberFromInt32(w, w->exponent);
161572ac97cdSTom Musta 	residue=0;
161672ac97cdSTom Musta 	decCopyFit(res, w, set, &residue, &status); /* copy & round */
161772ac97cdSTom Musta 	decFinish(res, set, &residue, &status);	    /* cleanup/set flags */
161872ac97cdSTom Musta 	break;
161972ac97cdSTom Musta 	} /* not a power of 10 */
162072ac97cdSTom Musta       } /* not a candidate for exact */
162172ac97cdSTom Musta 
162272ac97cdSTom Musta     /* simplify the information-content calculation to use 'total */
162372ac97cdSTom Musta     /* number of digits in a, including exponent' as compared to the */
162472ac97cdSTom Musta     /* requested digits, as increasing this will only rarely cost an */
162572ac97cdSTom Musta     /* iteration in ln(a) anyway */
162672ac97cdSTom Musta     t=6;				/* it can never be >6 */
162772ac97cdSTom Musta 
162872ac97cdSTom Musta     /* allocate space when needed... */
162972ac97cdSTom Musta     p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3;
163072ac97cdSTom Musta     needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
163172ac97cdSTom Musta     if (needbytes>sizeof(bufa)) {	/* need malloc space */
163272ac97cdSTom Musta       allocbufa=(decNumber *)malloc(needbytes);
163372ac97cdSTom Musta       if (allocbufa==NULL) {		/* hopeless -- abandon */
163472ac97cdSTom Musta 	status|=DEC_Insufficient_storage;
163572ac97cdSTom Musta 	break;}
163672ac97cdSTom Musta       a=allocbufa;			/* use the allocated space */
163772ac97cdSTom Musta       }
163872ac97cdSTom Musta     aset.digits=p;			/* as calculated */
163972ac97cdSTom Musta     aset.emax=DEC_MAX_MATH;		/* usual bounds */
164072ac97cdSTom Musta     aset.emin=-DEC_MAX_MATH;		/* .. */
164172ac97cdSTom Musta     aset.clamp=0;			/* and no concrete format */
164272ac97cdSTom Musta     decLnOp(a, rhs, &aset, &status);	/* a=ln(rhs) */
164372ac97cdSTom Musta 
164472ac97cdSTom Musta     /* skip the division if the result so far is infinite, NaN, or */
164572ac97cdSTom Musta     /* zero, or there was an error; note NaN from sNaN needs copy */
164672ac97cdSTom Musta     if (status&DEC_NaNs && !(status&DEC_sNaN)) break;
164772ac97cdSTom Musta     if (a->bits&DECSPECIAL || ISZERO(a)) {
164872ac97cdSTom Musta       decNumberCopy(res, a);		/* [will fit] */
164972ac97cdSTom Musta       break;}
165072ac97cdSTom Musta 
165172ac97cdSTom Musta     /* for ln(10) an extra 3 digits of precision are needed */
165272ac97cdSTom Musta     p=set->digits+3;
165372ac97cdSTom Musta     needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
165472ac97cdSTom Musta     if (needbytes>sizeof(bufb)) {	/* need malloc space */
165572ac97cdSTom Musta       allocbufb=(decNumber *)malloc(needbytes);
165672ac97cdSTom Musta       if (allocbufb==NULL) {		/* hopeless -- abandon */
165772ac97cdSTom Musta 	status|=DEC_Insufficient_storage;
165872ac97cdSTom Musta 	break;}
165972ac97cdSTom Musta       b=allocbufb;			/* use the allocated space */
166072ac97cdSTom Musta       }
166172ac97cdSTom Musta     decNumberZero(w);			/* set up 10... */
166272ac97cdSTom Musta     #if DECDPUN==1
166372ac97cdSTom Musta     w->lsu[1]=1; w->lsu[0]=0;		/* .. */
166472ac97cdSTom Musta     #else
166572ac97cdSTom Musta     w->lsu[0]=10;			/* .. */
166672ac97cdSTom Musta     #endif
166772ac97cdSTom Musta     w->digits=2;			/* .. */
166872ac97cdSTom Musta 
166972ac97cdSTom Musta     aset.digits=p;
167072ac97cdSTom Musta     decLnOp(b, w, &aset, &ignore);	/* b=ln(10) */
167172ac97cdSTom Musta 
167272ac97cdSTom Musta     aset.digits=set->digits;		/* for final divide */
167372ac97cdSTom Musta     decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */
167472ac97cdSTom Musta     } while(0);				/* [for break] */
167572ac97cdSTom Musta 
167672ac97cdSTom Musta   if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
167772ac97cdSTom Musta   if (allocbufb!=NULL) free(allocbufb); /* .. */
167872ac97cdSTom Musta   #if DECSUBSET
167972ac97cdSTom Musta   if (allocrhs !=NULL) free(allocrhs);	/* .. */
168072ac97cdSTom Musta   #endif
168172ac97cdSTom Musta   /* apply significant status */
168272ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
168372ac97cdSTom Musta   #if DECCHECK
168472ac97cdSTom Musta   decCheckInexact(res, set);
168572ac97cdSTom Musta   #endif
168672ac97cdSTom Musta   return res;
168772ac97cdSTom Musta   } /* decNumberLog10 */
168872ac97cdSTom Musta 
168972ac97cdSTom Musta /* ------------------------------------------------------------------ */
169072ac97cdSTom Musta /* decNumberMax -- compare two Numbers and return the maximum	      */
169172ac97cdSTom Musta /*								      */
169272ac97cdSTom Musta /*   This computes C = A ? B, returning the maximum by 754R rules     */
169372ac97cdSTom Musta /*								      */
169472ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
169572ac97cdSTom Musta /*   lhs is A							      */
169672ac97cdSTom Musta /*   rhs is B							      */
169772ac97cdSTom Musta /*   set is the context						      */
169872ac97cdSTom Musta /*								      */
169972ac97cdSTom Musta /* C must have space for set->digits digits.			      */
170072ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberMax(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)170172ac97cdSTom Musta decNumber * decNumberMax(decNumber *res, const decNumber *lhs,
170272ac97cdSTom Musta 			 const decNumber *rhs, decContext *set) {
170372ac97cdSTom Musta   uInt status=0;			/* accumulator */
170472ac97cdSTom Musta   decCompareOp(res, lhs, rhs, set, COMPMAX, &status);
170572ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
170672ac97cdSTom Musta   #if DECCHECK
170772ac97cdSTom Musta   decCheckInexact(res, set);
170872ac97cdSTom Musta   #endif
170972ac97cdSTom Musta   return res;
171072ac97cdSTom Musta   } /* decNumberMax */
171172ac97cdSTom Musta 
171272ac97cdSTom Musta /* ------------------------------------------------------------------ */
171372ac97cdSTom Musta /* decNumberMaxMag -- compare and return the maximum by magnitude     */
171472ac97cdSTom Musta /*								      */
171572ac97cdSTom Musta /*   This computes C = A ? B, returning the maximum by 754R rules     */
171672ac97cdSTom Musta /*								      */
171772ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
171872ac97cdSTom Musta /*   lhs is A							      */
171972ac97cdSTom Musta /*   rhs is B							      */
172072ac97cdSTom Musta /*   set is the context						      */
172172ac97cdSTom Musta /*								      */
172272ac97cdSTom Musta /* C must have space for set->digits digits.			      */
172372ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberMaxMag(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)172472ac97cdSTom Musta decNumber * decNumberMaxMag(decNumber *res, const decNumber *lhs,
172572ac97cdSTom Musta 			 const decNumber *rhs, decContext *set) {
172672ac97cdSTom Musta   uInt status=0;			/* accumulator */
172772ac97cdSTom Musta   decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status);
172872ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
172972ac97cdSTom Musta   #if DECCHECK
173072ac97cdSTom Musta   decCheckInexact(res, set);
173172ac97cdSTom Musta   #endif
173272ac97cdSTom Musta   return res;
173372ac97cdSTom Musta   } /* decNumberMaxMag */
173472ac97cdSTom Musta 
173572ac97cdSTom Musta /* ------------------------------------------------------------------ */
173672ac97cdSTom Musta /* decNumberMin -- compare two Numbers and return the minimum	      */
173772ac97cdSTom Musta /*								      */
173872ac97cdSTom Musta /*   This computes C = A ? B, returning the minimum by 754R rules     */
173972ac97cdSTom Musta /*								      */
174072ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
174172ac97cdSTom Musta /*   lhs is A							      */
174272ac97cdSTom Musta /*   rhs is B							      */
174372ac97cdSTom Musta /*   set is the context						      */
174472ac97cdSTom Musta /*								      */
174572ac97cdSTom Musta /* C must have space for set->digits digits.			      */
174672ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberMin(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)174772ac97cdSTom Musta decNumber * decNumberMin(decNumber *res, const decNumber *lhs,
174872ac97cdSTom Musta 			 const decNumber *rhs, decContext *set) {
174972ac97cdSTom Musta   uInt status=0;			/* accumulator */
175072ac97cdSTom Musta   decCompareOp(res, lhs, rhs, set, COMPMIN, &status);
175172ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
175272ac97cdSTom Musta   #if DECCHECK
175372ac97cdSTom Musta   decCheckInexact(res, set);
175472ac97cdSTom Musta   #endif
175572ac97cdSTom Musta   return res;
175672ac97cdSTom Musta   } /* decNumberMin */
175772ac97cdSTom Musta 
175872ac97cdSTom Musta /* ------------------------------------------------------------------ */
175972ac97cdSTom Musta /* decNumberMinMag -- compare and return the minimum by magnitude     */
176072ac97cdSTom Musta /*								      */
176172ac97cdSTom Musta /*   This computes C = A ? B, returning the minimum by 754R rules     */
176272ac97cdSTom Musta /*								      */
176372ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
176472ac97cdSTom Musta /*   lhs is A							      */
176572ac97cdSTom Musta /*   rhs is B							      */
176672ac97cdSTom Musta /*   set is the context						      */
176772ac97cdSTom Musta /*								      */
176872ac97cdSTom Musta /* C must have space for set->digits digits.			      */
176972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberMinMag(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)177072ac97cdSTom Musta decNumber * decNumberMinMag(decNumber *res, const decNumber *lhs,
177172ac97cdSTom Musta 			 const decNumber *rhs, decContext *set) {
177272ac97cdSTom Musta   uInt status=0;			/* accumulator */
177372ac97cdSTom Musta   decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status);
177472ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
177572ac97cdSTom Musta   #if DECCHECK
177672ac97cdSTom Musta   decCheckInexact(res, set);
177772ac97cdSTom Musta   #endif
177872ac97cdSTom Musta   return res;
177972ac97cdSTom Musta   } /* decNumberMinMag */
178072ac97cdSTom Musta 
178172ac97cdSTom Musta /* ------------------------------------------------------------------ */
178272ac97cdSTom Musta /* decNumberMinus -- prefix minus operator			      */
178372ac97cdSTom Musta /*								      */
178472ac97cdSTom Musta /*   This computes C = 0 - A					      */
178572ac97cdSTom Musta /*								      */
178672ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
178772ac97cdSTom Musta /*   rhs is A							      */
178872ac97cdSTom Musta /*   set is the context						      */
178972ac97cdSTom Musta /*								      */
179072ac97cdSTom Musta /* See also decNumberCopyNegate for a quiet bitwise version of this.  */
179172ac97cdSTom Musta /* C must have space for set->digits digits.			      */
179272ac97cdSTom Musta /* ------------------------------------------------------------------ */
179372ac97cdSTom Musta /* Simply use AddOp for the subtract, which will do the necessary.    */
179472ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberMinus(decNumber * res,const decNumber * rhs,decContext * set)179572ac97cdSTom Musta decNumber * decNumberMinus(decNumber *res, const decNumber *rhs,
179672ac97cdSTom Musta 			   decContext *set) {
179772ac97cdSTom Musta   decNumber dzero;
179872ac97cdSTom Musta   uInt status=0;			/* accumulator */
179972ac97cdSTom Musta 
180072ac97cdSTom Musta   #if DECCHECK
180172ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
180272ac97cdSTom Musta   #endif
180372ac97cdSTom Musta 
180472ac97cdSTom Musta   decNumberZero(&dzero);		/* make 0 */
180572ac97cdSTom Musta   dzero.exponent=rhs->exponent;		/* [no coefficient expansion] */
180672ac97cdSTom Musta   decAddOp(res, &dzero, rhs, set, DECNEG, &status);
180772ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
180872ac97cdSTom Musta   #if DECCHECK
180972ac97cdSTom Musta   decCheckInexact(res, set);
181072ac97cdSTom Musta   #endif
181172ac97cdSTom Musta   return res;
181272ac97cdSTom Musta   } /* decNumberMinus */
181372ac97cdSTom Musta 
181472ac97cdSTom Musta /* ------------------------------------------------------------------ */
181572ac97cdSTom Musta /* decNumberNextMinus -- next towards -Infinity			      */
181672ac97cdSTom Musta /*								      */
181772ac97cdSTom Musta /*   This computes C = A - infinitesimal, rounded towards -Infinity   */
181872ac97cdSTom Musta /*								      */
181972ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
182072ac97cdSTom Musta /*   rhs is A							      */
182172ac97cdSTom Musta /*   set is the context						      */
182272ac97cdSTom Musta /*								      */
182372ac97cdSTom Musta /* This is a generalization of 754r NextDown.			      */
182472ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberNextMinus(decNumber * res,const decNumber * rhs,decContext * set)182572ac97cdSTom Musta decNumber * decNumberNextMinus(decNumber *res, const decNumber *rhs,
182672ac97cdSTom Musta 			       decContext *set) {
182772ac97cdSTom Musta   decNumber dtiny;			     /* constant */
182872ac97cdSTom Musta   decContext workset=*set;		     /* work */
182972ac97cdSTom Musta   uInt status=0;			     /* accumulator */
183072ac97cdSTom Musta   #if DECCHECK
183172ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
183272ac97cdSTom Musta   #endif
183372ac97cdSTom Musta 
183472ac97cdSTom Musta   /* +Infinity is the special case */
183572ac97cdSTom Musta   if ((rhs->bits&(DECINF|DECNEG))==DECINF) {
183672ac97cdSTom Musta     decSetMaxValue(res, set);		     /* is +ve */
183772ac97cdSTom Musta     /* there is no status to set */
183872ac97cdSTom Musta     return res;
183972ac97cdSTom Musta     }
184072ac97cdSTom Musta   decNumberZero(&dtiny);		     /* start with 0 */
184172ac97cdSTom Musta   dtiny.lsu[0]=1;			     /* make number that is .. */
184272ac97cdSTom Musta   dtiny.exponent=DEC_MIN_EMIN-1;	     /* .. smaller than tiniest */
184372ac97cdSTom Musta   workset.round=DEC_ROUND_FLOOR;
184472ac97cdSTom Musta   decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status);
184572ac97cdSTom Musta   status&=DEC_Invalid_operation|DEC_sNaN;    /* only sNaN Invalid please */
184672ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
184772ac97cdSTom Musta   return res;
184872ac97cdSTom Musta   } /* decNumberNextMinus */
184972ac97cdSTom Musta 
185072ac97cdSTom Musta /* ------------------------------------------------------------------ */
185172ac97cdSTom Musta /* decNumberNextPlus -- next towards +Infinity			      */
185272ac97cdSTom Musta /*								      */
185372ac97cdSTom Musta /*   This computes C = A + infinitesimal, rounded towards +Infinity   */
185472ac97cdSTom Musta /*								      */
185572ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
185672ac97cdSTom Musta /*   rhs is A							      */
185772ac97cdSTom Musta /*   set is the context						      */
185872ac97cdSTom Musta /*								      */
185972ac97cdSTom Musta /* This is a generalization of 754r NextUp.			      */
186072ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberNextPlus(decNumber * res,const decNumber * rhs,decContext * set)186172ac97cdSTom Musta decNumber * decNumberNextPlus(decNumber *res, const decNumber *rhs,
186272ac97cdSTom Musta 			      decContext *set) {
186372ac97cdSTom Musta   decNumber dtiny;			     /* constant */
186472ac97cdSTom Musta   decContext workset=*set;		     /* work */
186572ac97cdSTom Musta   uInt status=0;			     /* accumulator */
186672ac97cdSTom Musta   #if DECCHECK
186772ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
186872ac97cdSTom Musta   #endif
186972ac97cdSTom Musta 
187072ac97cdSTom Musta   /* -Infinity is the special case */
187172ac97cdSTom Musta   if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
187272ac97cdSTom Musta     decSetMaxValue(res, set);
187372ac97cdSTom Musta     res->bits=DECNEG;			     /* negative */
187472ac97cdSTom Musta     /* there is no status to set */
187572ac97cdSTom Musta     return res;
187672ac97cdSTom Musta     }
187772ac97cdSTom Musta   decNumberZero(&dtiny);		     /* start with 0 */
187872ac97cdSTom Musta   dtiny.lsu[0]=1;			     /* make number that is .. */
187972ac97cdSTom Musta   dtiny.exponent=DEC_MIN_EMIN-1;	     /* .. smaller than tiniest */
188072ac97cdSTom Musta   workset.round=DEC_ROUND_CEILING;
188172ac97cdSTom Musta   decAddOp(res, rhs, &dtiny, &workset, 0, &status);
188272ac97cdSTom Musta   status&=DEC_Invalid_operation|DEC_sNaN;    /* only sNaN Invalid please */
188372ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
188472ac97cdSTom Musta   return res;
188572ac97cdSTom Musta   } /* decNumberNextPlus */
188672ac97cdSTom Musta 
188772ac97cdSTom Musta /* ------------------------------------------------------------------ */
188872ac97cdSTom Musta /* decNumberNextToward -- next towards rhs			      */
188972ac97cdSTom Musta /*								      */
189072ac97cdSTom Musta /*   This computes C = A +/- infinitesimal, rounded towards	      */
189172ac97cdSTom Musta /*   +/-Infinity in the direction of B, as per 754r nextafter rules   */
189272ac97cdSTom Musta /*								      */
189372ac97cdSTom Musta /*   res is C, the result.  C may be A or B.			      */
189472ac97cdSTom Musta /*   lhs is A							      */
189572ac97cdSTom Musta /*   rhs is B							      */
189672ac97cdSTom Musta /*   set is the context						      */
189772ac97cdSTom Musta /*								      */
189872ac97cdSTom Musta /* This is a generalization of 754r NextAfter.			      */
189972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberNextToward(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)190072ac97cdSTom Musta decNumber * decNumberNextToward(decNumber *res, const decNumber *lhs,
190172ac97cdSTom Musta 				const decNumber *rhs, decContext *set) {
190272ac97cdSTom Musta   decNumber dtiny;			     /* constant */
190372ac97cdSTom Musta   decContext workset=*set;		     /* work */
190472ac97cdSTom Musta   Int result;				     /* .. */
190572ac97cdSTom Musta   uInt status=0;			     /* accumulator */
190672ac97cdSTom Musta   #if DECCHECK
190772ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
190872ac97cdSTom Musta   #endif
190972ac97cdSTom Musta 
191072ac97cdSTom Musta   if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) {
191172ac97cdSTom Musta     decNaNs(res, lhs, rhs, set, &status);
191272ac97cdSTom Musta     }
191372ac97cdSTom Musta    else { /* Is numeric, so no chance of sNaN Invalid, etc. */
191472ac97cdSTom Musta     result=decCompare(lhs, rhs, 0);	/* sign matters */
191572ac97cdSTom Musta     if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */
191672ac97cdSTom Musta      else { /* valid compare */
191772ac97cdSTom Musta       if (result==0) decNumberCopySign(res, lhs, rhs); /* easy */
191872ac97cdSTom Musta        else { /* differ: need NextPlus or NextMinus */
191972ac97cdSTom Musta 	uByte sub;			/* add or subtract */
192072ac97cdSTom Musta 	if (result<0) {			/* lhs<rhs, do nextplus */
192172ac97cdSTom Musta 	  /* -Infinity is the special case */
192272ac97cdSTom Musta 	  if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
192372ac97cdSTom Musta 	    decSetMaxValue(res, set);
192472ac97cdSTom Musta 	    res->bits=DECNEG;		/* negative */
192572ac97cdSTom Musta 	    return res;			/* there is no status to set */
192672ac97cdSTom Musta 	    }
192772ac97cdSTom Musta 	  workset.round=DEC_ROUND_CEILING;
192872ac97cdSTom Musta 	  sub=0;			/* add, please */
192972ac97cdSTom Musta 	  } /* plus */
193072ac97cdSTom Musta 	 else {				/* lhs>rhs, do nextminus */
193172ac97cdSTom Musta 	  /* +Infinity is the special case */
193272ac97cdSTom Musta 	  if ((lhs->bits&(DECINF|DECNEG))==DECINF) {
193372ac97cdSTom Musta 	    decSetMaxValue(res, set);
193472ac97cdSTom Musta 	    return res;			/* there is no status to set */
193572ac97cdSTom Musta 	    }
193672ac97cdSTom Musta 	  workset.round=DEC_ROUND_FLOOR;
193772ac97cdSTom Musta 	  sub=DECNEG;			/* subtract, please */
193872ac97cdSTom Musta 	  } /* minus */
193972ac97cdSTom Musta 	decNumberZero(&dtiny);		/* start with 0 */
194072ac97cdSTom Musta 	dtiny.lsu[0]=1;			/* make number that is .. */
194172ac97cdSTom Musta 	dtiny.exponent=DEC_MIN_EMIN-1;	/* .. smaller than tiniest */
194272ac97cdSTom Musta 	decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */
194372ac97cdSTom Musta 	/* turn off exceptions if the result is a normal number */
194472ac97cdSTom Musta 	/* (including Nmin), otherwise let all status through */
194572ac97cdSTom Musta 	if (decNumberIsNormal(res, set)) status=0;
194672ac97cdSTom Musta 	} /* unequal */
194772ac97cdSTom Musta       } /* compare OK */
194872ac97cdSTom Musta     } /* numeric */
194972ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
195072ac97cdSTom Musta   return res;
195172ac97cdSTom Musta   } /* decNumberNextToward */
195272ac97cdSTom Musta 
195372ac97cdSTom Musta /* ------------------------------------------------------------------ */
195472ac97cdSTom Musta /* decNumberOr -- OR two Numbers, digitwise			      */
195572ac97cdSTom Musta /*								      */
195672ac97cdSTom Musta /*   This computes C = A | B					      */
195772ac97cdSTom Musta /*								      */
195872ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X|X)	      */
195972ac97cdSTom Musta /*   lhs is A							      */
196072ac97cdSTom Musta /*   rhs is B							      */
196172ac97cdSTom Musta /*   set is the context (used for result length and error report)     */
196272ac97cdSTom Musta /*								      */
196372ac97cdSTom Musta /* C must have space for set->digits digits.			      */
196472ac97cdSTom Musta /*								      */
196572ac97cdSTom Musta /* Logical function restrictions apply (see above); a NaN is	      */
196672ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
196772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberOr(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)196872ac97cdSTom Musta decNumber * decNumberOr(decNumber *res, const decNumber *lhs,
196972ac97cdSTom Musta 			const decNumber *rhs, decContext *set) {
197072ac97cdSTom Musta   const Unit *ua, *ub;			/* -> operands */
197172ac97cdSTom Musta   const Unit *msua, *msub;		/* -> operand msus */
197272ac97cdSTom Musta   Unit	*uc, *msuc;			/* -> result and its msu */
197372ac97cdSTom Musta   Int	msudigs;			/* digits in res msu */
197472ac97cdSTom Musta   #if DECCHECK
197572ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
197672ac97cdSTom Musta   #endif
197772ac97cdSTom Musta 
197872ac97cdSTom Musta   if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
197972ac97cdSTom Musta    || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
198072ac97cdSTom Musta     decStatus(res, DEC_Invalid_operation, set);
198172ac97cdSTom Musta     return res;
198272ac97cdSTom Musta     }
198372ac97cdSTom Musta   /* operands are valid */
198472ac97cdSTom Musta   ua=lhs->lsu;				/* bottom-up */
198572ac97cdSTom Musta   ub=rhs->lsu;				/* .. */
198672ac97cdSTom Musta   uc=res->lsu;				/* .. */
198772ac97cdSTom Musta   msua=ua+D2U(lhs->digits)-1;		/* -> msu of lhs */
198872ac97cdSTom Musta   msub=ub+D2U(rhs->digits)-1;		/* -> msu of rhs */
198972ac97cdSTom Musta   msuc=uc+D2U(set->digits)-1;		/* -> msu of result */
199072ac97cdSTom Musta   msudigs=MSUDIGITS(set->digits);	/* [faster than remainder] */
199172ac97cdSTom Musta   for (; uc<=msuc; ua++, ub++, uc++) {	/* Unit loop */
199272ac97cdSTom Musta     Unit a, b;				/* extract units */
199372ac97cdSTom Musta     if (ua>msua) a=0;
199472ac97cdSTom Musta      else a=*ua;
199572ac97cdSTom Musta     if (ub>msub) b=0;
199672ac97cdSTom Musta      else b=*ub;
199772ac97cdSTom Musta     *uc=0;				/* can now write back */
199872ac97cdSTom Musta     if (a|b) {				/* maybe 1 bits to examine */
199972ac97cdSTom Musta       Int i, j;
200072ac97cdSTom Musta       /* This loop could be unrolled and/or use BIN2BCD tables */
200172ac97cdSTom Musta       for (i=0; i<DECDPUN; i++) {
200272ac97cdSTom Musta 	if ((a|b)&1) *uc=*uc+(Unit)powers[i];	  /* effect OR */
200372ac97cdSTom Musta 	j=a%10;
200472ac97cdSTom Musta 	a=a/10;
200572ac97cdSTom Musta 	j|=b%10;
200672ac97cdSTom Musta 	b=b/10;
200772ac97cdSTom Musta 	if (j>1) {
200872ac97cdSTom Musta 	  decStatus(res, DEC_Invalid_operation, set);
200972ac97cdSTom Musta 	  return res;
201072ac97cdSTom Musta 	  }
201172ac97cdSTom Musta 	if (uc==msuc && i==msudigs-1) break;	  /* just did final digit */
201272ac97cdSTom Musta 	} /* each digit */
201372ac97cdSTom Musta       } /* non-zero */
201472ac97cdSTom Musta     } /* each unit */
201572ac97cdSTom Musta   /* [here uc-1 is the msu of the result] */
201672ac97cdSTom Musta   res->digits=decGetDigits(res->lsu, uc-res->lsu);
201772ac97cdSTom Musta   res->exponent=0;			/* integer */
201872ac97cdSTom Musta   res->bits=0;				/* sign=0 */
201972ac97cdSTom Musta   return res;  /* [no status to set] */
202072ac97cdSTom Musta   } /* decNumberOr */
202172ac97cdSTom Musta 
202272ac97cdSTom Musta /* ------------------------------------------------------------------ */
202372ac97cdSTom Musta /* decNumberPlus -- prefix plus operator			      */
202472ac97cdSTom Musta /*								      */
202572ac97cdSTom Musta /*   This computes C = 0 + A					      */
202672ac97cdSTom Musta /*								      */
202772ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
202872ac97cdSTom Musta /*   rhs is A							      */
202972ac97cdSTom Musta /*   set is the context						      */
203072ac97cdSTom Musta /*								      */
203172ac97cdSTom Musta /* See also decNumberCopy for a quiet bitwise version of this.	      */
203272ac97cdSTom Musta /* C must have space for set->digits digits.			      */
203372ac97cdSTom Musta /* ------------------------------------------------------------------ */
203472ac97cdSTom Musta /* This simply uses AddOp; Add will take fast path after preparing A. */
203572ac97cdSTom Musta /* Performance is a concern here, as this routine is often used to    */
203672ac97cdSTom Musta /* check operands and apply rounding and overflow/underflow testing.  */
203772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberPlus(decNumber * res,const decNumber * rhs,decContext * set)203872ac97cdSTom Musta decNumber * decNumberPlus(decNumber *res, const decNumber *rhs,
203972ac97cdSTom Musta 			  decContext *set) {
204072ac97cdSTom Musta   decNumber dzero;
204172ac97cdSTom Musta   uInt status=0;			/* accumulator */
204272ac97cdSTom Musta   #if DECCHECK
204372ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
204472ac97cdSTom Musta   #endif
204572ac97cdSTom Musta 
204672ac97cdSTom Musta   decNumberZero(&dzero);		/* make 0 */
204772ac97cdSTom Musta   dzero.exponent=rhs->exponent;		/* [no coefficient expansion] */
204872ac97cdSTom Musta   decAddOp(res, &dzero, rhs, set, 0, &status);
204972ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
205072ac97cdSTom Musta   #if DECCHECK
205172ac97cdSTom Musta   decCheckInexact(res, set);
205272ac97cdSTom Musta   #endif
205372ac97cdSTom Musta   return res;
205472ac97cdSTom Musta   } /* decNumberPlus */
205572ac97cdSTom Musta 
205672ac97cdSTom Musta /* ------------------------------------------------------------------ */
205772ac97cdSTom Musta /* decNumberMultiply -- multiply two Numbers			      */
205872ac97cdSTom Musta /*								      */
205972ac97cdSTom Musta /*   This computes C = A x B					      */
206072ac97cdSTom Musta /*								      */
206172ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X+X)	      */
206272ac97cdSTom Musta /*   lhs is A							      */
206372ac97cdSTom Musta /*   rhs is B							      */
206472ac97cdSTom Musta /*   set is the context						      */
206572ac97cdSTom Musta /*								      */
206672ac97cdSTom Musta /* C must have space for set->digits digits.			      */
206772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberMultiply(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)206872ac97cdSTom Musta decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs,
206972ac97cdSTom Musta 			      const decNumber *rhs, decContext *set) {
207072ac97cdSTom Musta   uInt status=0;		   /* accumulator */
207172ac97cdSTom Musta   decMultiplyOp(res, lhs, rhs, set, &status);
207272ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
207372ac97cdSTom Musta   #if DECCHECK
207472ac97cdSTom Musta   decCheckInexact(res, set);
207572ac97cdSTom Musta   #endif
207672ac97cdSTom Musta   return res;
207772ac97cdSTom Musta   } /* decNumberMultiply */
207872ac97cdSTom Musta 
207972ac97cdSTom Musta /* ------------------------------------------------------------------ */
208072ac97cdSTom Musta /* decNumberPower -- raise a number to a power			      */
208172ac97cdSTom Musta /*								      */
208272ac97cdSTom Musta /*   This computes C = A ** B					      */
208372ac97cdSTom Musta /*								      */
208472ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X**X)	      */
208572ac97cdSTom Musta /*   lhs is A							      */
208672ac97cdSTom Musta /*   rhs is B							      */
208772ac97cdSTom Musta /*   set is the context						      */
208872ac97cdSTom Musta /*								      */
208972ac97cdSTom Musta /* C must have space for set->digits digits.			      */
209072ac97cdSTom Musta /*								      */
209172ac97cdSTom Musta /* Mathematical function restrictions apply (see above); a NaN is     */
209272ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
209372ac97cdSTom Musta /*								      */
209472ac97cdSTom Musta /* However, if 1999999997<=B<=999999999 and B is an integer then the  */
209572ac97cdSTom Musta /* restrictions on A and the context are relaxed to the usual bounds, */
209672ac97cdSTom Musta /* for compatibility with the earlier (integer power only) version    */
209772ac97cdSTom Musta /* of this function.						      */
209872ac97cdSTom Musta /*								      */
209972ac97cdSTom Musta /* When B is an integer, the result may be exact, even if rounded.    */
210072ac97cdSTom Musta /*								      */
210172ac97cdSTom Musta /* The final result is rounded according to the context; it will      */
210272ac97cdSTom Musta /* almost always be correctly rounded, but may be up to 1 ulp in      */
210372ac97cdSTom Musta /* error in rare cases.						      */
210472ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberPower(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)210572ac97cdSTom Musta decNumber * decNumberPower(decNumber *res, const decNumber *lhs,
210672ac97cdSTom Musta 			   const decNumber *rhs, decContext *set) {
210772ac97cdSTom Musta   #if DECSUBSET
210872ac97cdSTom Musta   decNumber *alloclhs=NULL;	   /* non-NULL if rounded lhs allocated */
210972ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* .., rhs */
211072ac97cdSTom Musta   #endif
211172ac97cdSTom Musta   decNumber *allocdac=NULL;	   /* -> allocated acc buffer, iff used */
211272ac97cdSTom Musta   decNumber *allocinv=NULL;	   /* -> allocated 1/x buffer, iff used */
211372ac97cdSTom Musta   Int	reqdigits=set->digits;	   /* requested DIGITS */
211472ac97cdSTom Musta   Int	n;			   /* rhs in binary */
211572ac97cdSTom Musta   Flag	rhsint=0;		   /* 1 if rhs is an integer */
211672ac97cdSTom Musta   Flag	useint=0;		   /* 1 if can use integer calculation */
211772ac97cdSTom Musta   Flag	isoddint=0;		   /* 1 if rhs is an integer and odd */
211872ac97cdSTom Musta   Int	i;			   /* work */
211972ac97cdSTom Musta   #if DECSUBSET
212072ac97cdSTom Musta   Int	dropped;		   /* .. */
212172ac97cdSTom Musta   #endif
212272ac97cdSTom Musta   uInt	needbytes;		   /* buffer size needed */
212372ac97cdSTom Musta   Flag	seenbit;		   /* seen a bit while powering */
212472ac97cdSTom Musta   Int	residue=0;		   /* rounding residue */
212572ac97cdSTom Musta   uInt	status=0;		   /* accumulators */
212672ac97cdSTom Musta   uByte bits=0;			   /* result sign if errors */
212772ac97cdSTom Musta   decContext aset;		   /* working context */
212872ac97cdSTom Musta   decNumber dnOne;		   /* work value 1... */
212972ac97cdSTom Musta   /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */
213072ac97cdSTom Musta   decNumber dacbuff[D2N(DECBUFFER+9)];
213172ac97cdSTom Musta   decNumber *dac=dacbuff;	   /* -> result accumulator */
213272ac97cdSTom Musta   /* same again for possible 1/lhs calculation */
213372ac97cdSTom Musta   decNumber invbuff[D2N(DECBUFFER+9)];
213472ac97cdSTom Musta 
213572ac97cdSTom Musta   #if DECCHECK
213672ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
213772ac97cdSTom Musta   #endif
213872ac97cdSTom Musta 
213972ac97cdSTom Musta   do {				   /* protect allocated storage */
214072ac97cdSTom Musta     #if DECSUBSET
214172ac97cdSTom Musta     if (!set->extended) { /* reduce operands and set status, as needed */
214272ac97cdSTom Musta       if (lhs->digits>reqdigits) {
214372ac97cdSTom Musta 	alloclhs=decRoundOperand(lhs, set, &status);
214472ac97cdSTom Musta 	if (alloclhs==NULL) break;
214572ac97cdSTom Musta 	lhs=alloclhs;
214672ac97cdSTom Musta 	}
214772ac97cdSTom Musta       if (rhs->digits>reqdigits) {
214872ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, &status);
214972ac97cdSTom Musta 	if (allocrhs==NULL) break;
215072ac97cdSTom Musta 	rhs=allocrhs;
215172ac97cdSTom Musta 	}
215272ac97cdSTom Musta       }
215372ac97cdSTom Musta     #endif
215472ac97cdSTom Musta     /* [following code does not require input rounding] */
215572ac97cdSTom Musta 
215672ac97cdSTom Musta     /* handle NaNs and rhs Infinity (lhs infinity is harder) */
215772ac97cdSTom Musta     if (SPECIALARGS) {
215872ac97cdSTom Musta       if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */
215972ac97cdSTom Musta 	decNaNs(res, lhs, rhs, set, &status);
216072ac97cdSTom Musta 	break;}
216172ac97cdSTom Musta       if (decNumberIsInfinite(rhs)) {	/* rhs Infinity */
216272ac97cdSTom Musta 	Flag rhsneg=rhs->bits&DECNEG;	/* save rhs sign */
216372ac97cdSTom Musta 	if (decNumberIsNegative(lhs)	/* lhs<0 */
216472ac97cdSTom Musta 	 && !decNumberIsZero(lhs))	/* .. */
216572ac97cdSTom Musta 	  status|=DEC_Invalid_operation;
216672ac97cdSTom Musta 	 else {				/* lhs >=0 */
216772ac97cdSTom Musta 	  decNumberZero(&dnOne);	/* set up 1 */
216872ac97cdSTom Musta 	  dnOne.lsu[0]=1;
216972ac97cdSTom Musta 	  decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */
217072ac97cdSTom Musta 	  decNumberZero(res);		/* prepare for 0/1/Infinity */
217172ac97cdSTom Musta 	  if (decNumberIsNegative(dac)) {    /* lhs<1 */
217272ac97cdSTom Musta 	    if (rhsneg) res->bits|=DECINF;   /* +Infinity [else is +0] */
217372ac97cdSTom Musta 	    }
217472ac97cdSTom Musta 	   else if (dac->lsu[0]==0) {	     /* lhs=1 */
217572ac97cdSTom Musta 	    /* 1**Infinity is inexact, so return fully-padded 1.0000 */
217672ac97cdSTom Musta 	    Int shift=set->digits-1;
217772ac97cdSTom Musta 	    *res->lsu=1;		     /* was 0, make int 1 */
217872ac97cdSTom Musta 	    res->digits=decShiftToMost(res->lsu, 1, shift);
217972ac97cdSTom Musta 	    res->exponent=-shift;	     /* make 1.0000... */
218072ac97cdSTom Musta 	    status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */
218172ac97cdSTom Musta 	    }
218272ac97cdSTom Musta 	   else {			     /* lhs>1 */
218372ac97cdSTom Musta 	    if (!rhsneg) res->bits|=DECINF;  /* +Infinity [else is +0] */
218472ac97cdSTom Musta 	    }
218572ac97cdSTom Musta 	  } /* lhs>=0 */
218672ac97cdSTom Musta 	break;}
218772ac97cdSTom Musta       /* [lhs infinity drops through] */
218872ac97cdSTom Musta       } /* specials */
218972ac97cdSTom Musta 
219072ac97cdSTom Musta     /* Original rhs may be an integer that fits and is in range */
219172ac97cdSTom Musta     n=decGetInt(rhs);
219272ac97cdSTom Musta     if (n!=BADINT) {			/* it is an integer */
219372ac97cdSTom Musta       rhsint=1;				/* record the fact for 1**n */
219472ac97cdSTom Musta       isoddint=(Flag)n&1;		/* [works even if big] */
219572ac97cdSTom Musta       if (n!=BIGEVEN && n!=BIGODD)	/* can use integer path? */
219672ac97cdSTom Musta 	useint=1;			/* looks good */
219772ac97cdSTom Musta       }
219872ac97cdSTom Musta 
219972ac97cdSTom Musta     if (decNumberIsNegative(lhs)	/* -x .. */
220072ac97cdSTom Musta       && isoddint) bits=DECNEG;		/* .. to an odd power */
220172ac97cdSTom Musta 
220272ac97cdSTom Musta     /* handle LHS infinity */
220372ac97cdSTom Musta     if (decNumberIsInfinite(lhs)) {	/* [NaNs already handled] */
220472ac97cdSTom Musta       uByte rbits=rhs->bits;		/* save */
220572ac97cdSTom Musta       decNumberZero(res);		/* prepare */
220672ac97cdSTom Musta       if (n==0) *res->lsu=1;		/* [-]Inf**0 => 1 */
220772ac97cdSTom Musta        else {
220872ac97cdSTom Musta 	/* -Inf**nonint -> error */
220972ac97cdSTom Musta 	if (!rhsint && decNumberIsNegative(lhs)) {
221072ac97cdSTom Musta 	  status|=DEC_Invalid_operation;     /* -Inf**nonint is error */
221172ac97cdSTom Musta 	  break;}
221272ac97cdSTom Musta 	if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */
221372ac97cdSTom Musta 	/* [otherwise will be 0 or -0] */
221472ac97cdSTom Musta 	res->bits=bits;
221572ac97cdSTom Musta 	}
221672ac97cdSTom Musta       break;}
221772ac97cdSTom Musta 
221872ac97cdSTom Musta     /* similarly handle LHS zero */
221972ac97cdSTom Musta     if (decNumberIsZero(lhs)) {
222072ac97cdSTom Musta       if (n==0) {			     /* 0**0 => Error */
222172ac97cdSTom Musta 	#if DECSUBSET
222272ac97cdSTom Musta 	if (!set->extended) {		     /* [unless subset] */
222372ac97cdSTom Musta 	  decNumberZero(res);
222472ac97cdSTom Musta 	  *res->lsu=1;			     /* return 1 */
222572ac97cdSTom Musta 	  break;}
222672ac97cdSTom Musta 	#endif
222772ac97cdSTom Musta 	status|=DEC_Invalid_operation;
222872ac97cdSTom Musta 	}
222972ac97cdSTom Musta        else {				     /* 0**x */
223072ac97cdSTom Musta 	uByte rbits=rhs->bits;		     /* save */
223172ac97cdSTom Musta 	if (rbits & DECNEG) {		     /* was a 0**(-n) */
223272ac97cdSTom Musta 	  #if DECSUBSET
223372ac97cdSTom Musta 	  if (!set->extended) {		     /* [bad if subset] */
223472ac97cdSTom Musta 	    status|=DEC_Invalid_operation;
223572ac97cdSTom Musta 	    break;}
223672ac97cdSTom Musta 	  #endif
223772ac97cdSTom Musta 	  bits|=DECINF;
223872ac97cdSTom Musta 	  }
223972ac97cdSTom Musta 	decNumberZero(res);		     /* prepare */
224072ac97cdSTom Musta 	/* [otherwise will be 0 or -0] */
224172ac97cdSTom Musta 	res->bits=bits;
224272ac97cdSTom Musta 	}
224372ac97cdSTom Musta       break;}
224472ac97cdSTom Musta 
224572ac97cdSTom Musta     /* here both lhs and rhs are finite; rhs==0 is handled in the */
224672ac97cdSTom Musta     /* integer path.  Next handle the non-integer cases */
224772ac97cdSTom Musta     if (!useint) {			/* non-integral rhs */
224872ac97cdSTom Musta       /* any -ve lhs is bad, as is either operand or context out of */
224972ac97cdSTom Musta       /* bounds */
225072ac97cdSTom Musta       if (decNumberIsNegative(lhs)) {
225172ac97cdSTom Musta 	status|=DEC_Invalid_operation;
225272ac97cdSTom Musta 	break;}
225372ac97cdSTom Musta       if (decCheckMath(lhs, set, &status)
225472ac97cdSTom Musta        || decCheckMath(rhs, set, &status)) break; /* variable status */
225572ac97cdSTom Musta 
225672ac97cdSTom Musta       decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
225772ac97cdSTom Musta       aset.emax=DEC_MAX_MATH;		/* usual bounds */
225872ac97cdSTom Musta       aset.emin=-DEC_MAX_MATH;		/* .. */
225972ac97cdSTom Musta       aset.clamp=0;			/* and no concrete format */
226072ac97cdSTom Musta 
226172ac97cdSTom Musta       /* calculate the result using exp(ln(lhs)*rhs), which can */
226272ac97cdSTom Musta       /* all be done into the accumulator, dac.	 The precision needed */
226372ac97cdSTom Musta       /* is enough to contain the full information in the lhs (which */
226472ac97cdSTom Musta       /* is the total digits, including exponent), or the requested */
226572ac97cdSTom Musta       /* precision, if larger, + 4; 6 is used for the exponent */
226672ac97cdSTom Musta       /* maximum length, and this is also used when it is shorter */
226772ac97cdSTom Musta       /* than the requested digits as it greatly reduces the >0.5 ulp */
226872ac97cdSTom Musta       /* cases at little cost (because Ln doubles digits each */
226972ac97cdSTom Musta       /* iteration so a few extra digits rarely causes an extra */
227072ac97cdSTom Musta       /* iteration) */
227172ac97cdSTom Musta       aset.digits=MAXI(lhs->digits, set->digits)+6+4;
227272ac97cdSTom Musta       } /* non-integer rhs */
227372ac97cdSTom Musta 
227472ac97cdSTom Musta      else { /* rhs is in-range integer */
227572ac97cdSTom Musta       if (n==0) {			/* x**0 = 1 */
227672ac97cdSTom Musta 	/* (0**0 was handled above) */
227772ac97cdSTom Musta 	decNumberZero(res);		/* result=1 */
227872ac97cdSTom Musta 	*res->lsu=1;			/* .. */
227972ac97cdSTom Musta 	break;}
228072ac97cdSTom Musta       /* rhs is a non-zero integer */
228172ac97cdSTom Musta       if (n<0) n=-n;			/* use abs(n) */
228272ac97cdSTom Musta 
228372ac97cdSTom Musta       aset=*set;			/* clone the context */
228472ac97cdSTom Musta       aset.round=DEC_ROUND_HALF_EVEN;	/* internally use balanced */
228572ac97cdSTom Musta       /* calculate the working DIGITS */
228672ac97cdSTom Musta       aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2;
228772ac97cdSTom Musta       #if DECSUBSET
228872ac97cdSTom Musta       if (!set->extended) aset.digits--;     /* use classic precision */
228972ac97cdSTom Musta       #endif
229072ac97cdSTom Musta       /* it's an error if this is more than can be handled */
229172ac97cdSTom Musta       if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;}
229272ac97cdSTom Musta       } /* integer path */
229372ac97cdSTom Musta 
229472ac97cdSTom Musta     /* aset.digits is the count of digits for the accumulator needed */
229572ac97cdSTom Musta     /* if accumulator is too long for local storage, then allocate */
229672ac97cdSTom Musta     needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit);
229772ac97cdSTom Musta     /* [needbytes also used below if 1/lhs needed] */
229872ac97cdSTom Musta     if (needbytes>sizeof(dacbuff)) {
229972ac97cdSTom Musta       allocdac=(decNumber *)malloc(needbytes);
230072ac97cdSTom Musta       if (allocdac==NULL) {   /* hopeless -- abandon */
230172ac97cdSTom Musta 	status|=DEC_Insufficient_storage;
230272ac97cdSTom Musta 	break;}
230372ac97cdSTom Musta       dac=allocdac;	      /* use the allocated space */
230472ac97cdSTom Musta       }
230572ac97cdSTom Musta     /* here, aset is set up and accumulator is ready for use */
230672ac97cdSTom Musta 
230772ac97cdSTom Musta     if (!useint) {			     /* non-integral rhs */
230872ac97cdSTom Musta       /* x ** y; special-case x=1 here as it will otherwise always */
230972ac97cdSTom Musta       /* reduce to integer 1; decLnOp has a fastpath which detects */
231072ac97cdSTom Musta       /* the case of x=1 */
231172ac97cdSTom Musta       decLnOp(dac, lhs, &aset, &status);     /* dac=ln(lhs) */
231272ac97cdSTom Musta       /* [no error possible, as lhs 0 already handled] */
231372ac97cdSTom Musta       if (ISZERO(dac)) {		     /* x==1, 1.0, etc. */
231472ac97cdSTom Musta 	/* need to return fully-padded 1.0000 etc., but rhsint->1 */
231572ac97cdSTom Musta 	*dac->lsu=1;			     /* was 0, make int 1 */
231672ac97cdSTom Musta 	if (!rhsint) {			     /* add padding */
231772ac97cdSTom Musta 	  Int shift=set->digits-1;
231872ac97cdSTom Musta 	  dac->digits=decShiftToMost(dac->lsu, 1, shift);
231972ac97cdSTom Musta 	  dac->exponent=-shift;		     /* make 1.0000... */
232072ac97cdSTom Musta 	  status|=DEC_Inexact|DEC_Rounded;   /* deemed inexact */
232172ac97cdSTom Musta 	  }
232272ac97cdSTom Musta 	}
232372ac97cdSTom Musta        else {
232472ac97cdSTom Musta 	decMultiplyOp(dac, dac, rhs, &aset, &status);  /* dac=dac*rhs */
232572ac97cdSTom Musta 	decExpOp(dac, dac, &aset, &status);	       /* dac=exp(dac) */
232672ac97cdSTom Musta 	}
232772ac97cdSTom Musta       /* and drop through for final rounding */
232872ac97cdSTom Musta       } /* non-integer rhs */
232972ac97cdSTom Musta 
233072ac97cdSTom Musta      else {				/* carry on with integer */
233172ac97cdSTom Musta       decNumberZero(dac);		/* acc=1 */
233272ac97cdSTom Musta       *dac->lsu=1;			/* .. */
233372ac97cdSTom Musta 
233472ac97cdSTom Musta       /* if a negative power the constant 1 is needed, and if not subset */
233572ac97cdSTom Musta       /* invert the lhs now rather than inverting the result later */
233672ac97cdSTom Musta       if (decNumberIsNegative(rhs)) {	/* was a **-n [hence digits>0] */
233767cc32ebSVeres Lajos 	decNumber *inv=invbuff;		/* assume use fixed buffer */
233872ac97cdSTom Musta 	decNumberCopy(&dnOne, dac);	/* dnOne=1;  [needed now or later] */
233972ac97cdSTom Musta 	#if DECSUBSET
234072ac97cdSTom Musta 	if (set->extended) {		/* need to calculate 1/lhs */
234172ac97cdSTom Musta 	#endif
234272ac97cdSTom Musta 	  /* divide lhs into 1, putting result in dac [dac=1/dac] */
234372ac97cdSTom Musta 	  decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status);
234472ac97cdSTom Musta 	  /* now locate or allocate space for the inverted lhs */
234572ac97cdSTom Musta 	  if (needbytes>sizeof(invbuff)) {
234672ac97cdSTom Musta 	    allocinv=(decNumber *)malloc(needbytes);
234772ac97cdSTom Musta 	    if (allocinv==NULL) {	/* hopeless -- abandon */
234872ac97cdSTom Musta 	      status|=DEC_Insufficient_storage;
234972ac97cdSTom Musta 	      break;}
235072ac97cdSTom Musta 	    inv=allocinv;		/* use the allocated space */
235172ac97cdSTom Musta 	    }
235272ac97cdSTom Musta 	  /* [inv now points to big-enough buffer or allocated storage] */
235372ac97cdSTom Musta 	  decNumberCopy(inv, dac);	/* copy the 1/lhs */
235472ac97cdSTom Musta 	  decNumberCopy(dac, &dnOne);	/* restore acc=1 */
235572ac97cdSTom Musta 	  lhs=inv;			/* .. and go forward with new lhs */
235672ac97cdSTom Musta 	#if DECSUBSET
235772ac97cdSTom Musta 	  }
235872ac97cdSTom Musta 	#endif
235972ac97cdSTom Musta 	}
236072ac97cdSTom Musta 
236172ac97cdSTom Musta       /* Raise-to-the-power loop... */
236272ac97cdSTom Musta       seenbit=0;		   /* set once a 1-bit is encountered */
236372ac97cdSTom Musta       for (i=1;;i++){		   /* for each bit [top bit ignored] */
236472ac97cdSTom Musta 	/* abandon if had overflow or terminal underflow */
236572ac97cdSTom Musta 	if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
236672ac97cdSTom Musta 	  if (status&DEC_Overflow || ISZERO(dac)) break;
236772ac97cdSTom Musta 	  }
236872ac97cdSTom Musta 	/* [the following two lines revealed an optimizer bug in a C++ */
236972ac97cdSTom Musta 	/* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */
237072ac97cdSTom Musta 	n=n<<1;			   /* move next bit to testable position */
237172ac97cdSTom Musta 	if (n<0) {		   /* top bit is set */
237272ac97cdSTom Musta 	  seenbit=1;		   /* OK, significant bit seen */
237372ac97cdSTom Musta 	  decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */
237472ac97cdSTom Musta 	  }
237572ac97cdSTom Musta 	if (i==31) break;	   /* that was the last bit */
237672ac97cdSTom Musta 	if (!seenbit) continue;	   /* no need to square 1 */
237772ac97cdSTom Musta 	decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */
237872ac97cdSTom Musta 	} /*i*/ /* 32 bits */
237972ac97cdSTom Musta 
238072ac97cdSTom Musta       /* complete internal overflow or underflow processing */
238172ac97cdSTom Musta       if (status & (DEC_Overflow|DEC_Underflow)) {
238272ac97cdSTom Musta 	#if DECSUBSET
238372ac97cdSTom Musta 	/* If subset, and power was negative, reverse the kind of -erflow */
238472ac97cdSTom Musta 	/* [1/x not yet done] */
238572ac97cdSTom Musta 	if (!set->extended && decNumberIsNegative(rhs)) {
238672ac97cdSTom Musta 	  if (status & DEC_Overflow)
238772ac97cdSTom Musta 	    status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal;
238872ac97cdSTom Musta 	   else { /* trickier -- Underflow may or may not be set */
238972ac97cdSTom Musta 	    status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */
239072ac97cdSTom Musta 	    status|=DEC_Overflow;
239172ac97cdSTom Musta 	    }
239272ac97cdSTom Musta 	  }
239372ac97cdSTom Musta 	#endif
239472ac97cdSTom Musta 	dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */
239572ac97cdSTom Musta 	/* round subnormals [to set.digits rather than aset.digits] */
239672ac97cdSTom Musta 	/* or set overflow result similarly as required */
239772ac97cdSTom Musta 	decFinalize(dac, set, &residue, &status);
239872ac97cdSTom Musta 	decNumberCopy(res, dac);   /* copy to result (is now OK length) */
239972ac97cdSTom Musta 	break;
240072ac97cdSTom Musta 	}
240172ac97cdSTom Musta 
240272ac97cdSTom Musta       #if DECSUBSET
240372ac97cdSTom Musta       if (!set->extended &&		     /* subset math */
240472ac97cdSTom Musta 	  decNumberIsNegative(rhs)) {	     /* was a **-n [hence digits>0] */
240572ac97cdSTom Musta 	/* so divide result into 1 [dac=1/dac] */
240672ac97cdSTom Musta 	decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status);
240772ac97cdSTom Musta 	}
240872ac97cdSTom Musta       #endif
240972ac97cdSTom Musta       } /* rhs integer path */
241072ac97cdSTom Musta 
241172ac97cdSTom Musta     /* reduce result to the requested length and copy to result */
241272ac97cdSTom Musta     decCopyFit(res, dac, set, &residue, &status);
241372ac97cdSTom Musta     decFinish(res, set, &residue, &status);  /* final cleanup */
241472ac97cdSTom Musta     #if DECSUBSET
241572ac97cdSTom Musta     if (!set->extended) decTrim(res, set, 0, &dropped); /* trailing zeros */
241672ac97cdSTom Musta     #endif
241772ac97cdSTom Musta     } while(0);				/* end protected */
241872ac97cdSTom Musta 
241972ac97cdSTom Musta   if (allocdac!=NULL) free(allocdac);	/* drop any storage used */
242072ac97cdSTom Musta   if (allocinv!=NULL) free(allocinv);	/* .. */
242172ac97cdSTom Musta   #if DECSUBSET
242272ac97cdSTom Musta   if (alloclhs!=NULL) free(alloclhs);	/* .. */
242372ac97cdSTom Musta   if (allocrhs!=NULL) free(allocrhs);	/* .. */
242472ac97cdSTom Musta   #endif
242572ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
242672ac97cdSTom Musta   #if DECCHECK
242772ac97cdSTom Musta   decCheckInexact(res, set);
242872ac97cdSTom Musta   #endif
242972ac97cdSTom Musta   return res;
243072ac97cdSTom Musta   } /* decNumberPower */
243172ac97cdSTom Musta 
243272ac97cdSTom Musta /* ------------------------------------------------------------------ */
243372ac97cdSTom Musta /* decNumberQuantize -- force exponent to requested value	      */
243472ac97cdSTom Musta /*								      */
243572ac97cdSTom Musta /*   This computes C = op(A, B), where op adjusts the coefficient     */
243672ac97cdSTom Musta /*   of C (by rounding or shifting) such that the exponent (-scale)   */
243772ac97cdSTom Musta /*   of C has exponent of B.  The numerical value of C will equal A,  */
243872ac97cdSTom Musta /*   except for the effects of any rounding that occurred.	      */
243972ac97cdSTom Musta /*								      */
244072ac97cdSTom Musta /*   res is C, the result.  C may be A or B			      */
244172ac97cdSTom Musta /*   lhs is A, the number to adjust				      */
244272ac97cdSTom Musta /*   rhs is B, the number with exponent to match		      */
244372ac97cdSTom Musta /*   set is the context						      */
244472ac97cdSTom Musta /*								      */
244572ac97cdSTom Musta /* C must have space for set->digits digits.			      */
244672ac97cdSTom Musta /*								      */
244772ac97cdSTom Musta /* Unless there is an error or the result is infinite, the exponent   */
244872ac97cdSTom Musta /* after the operation is guaranteed to be equal to that of B.	      */
244972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberQuantize(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)245072ac97cdSTom Musta decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs,
245172ac97cdSTom Musta 			      const decNumber *rhs, decContext *set) {
245272ac97cdSTom Musta   uInt status=0;			/* accumulator */
245372ac97cdSTom Musta   decQuantizeOp(res, lhs, rhs, set, 1, &status);
245472ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
245572ac97cdSTom Musta   return res;
245672ac97cdSTom Musta   } /* decNumberQuantize */
245772ac97cdSTom Musta 
245872ac97cdSTom Musta /* ------------------------------------------------------------------ */
245972ac97cdSTom Musta /* decNumberReduce -- remove trailing zeros			      */
246072ac97cdSTom Musta /*								      */
246172ac97cdSTom Musta /*   This computes C = 0 + A, and normalizes the result		      */
246272ac97cdSTom Musta /*								      */
246372ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
246472ac97cdSTom Musta /*   rhs is A							      */
246572ac97cdSTom Musta /*   set is the context						      */
246672ac97cdSTom Musta /*								      */
246772ac97cdSTom Musta /* C must have space for set->digits digits.			      */
246872ac97cdSTom Musta /* ------------------------------------------------------------------ */
246972ac97cdSTom Musta /* Previously known as Normalize */
decNumberNormalize(decNumber * res,const decNumber * rhs,decContext * set)247072ac97cdSTom Musta decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs,
247172ac97cdSTom Musta 			       decContext *set) {
247272ac97cdSTom Musta   return decNumberReduce(res, rhs, set);
247372ac97cdSTom Musta   } /* decNumberNormalize */
247472ac97cdSTom Musta 
decNumberReduce(decNumber * res,const decNumber * rhs,decContext * set)247572ac97cdSTom Musta decNumber * decNumberReduce(decNumber *res, const decNumber *rhs,
247672ac97cdSTom Musta 			    decContext *set) {
247772ac97cdSTom Musta   #if DECSUBSET
247872ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* non-NULL if rounded rhs allocated */
247972ac97cdSTom Musta   #endif
248072ac97cdSTom Musta   uInt status=0;		   /* as usual */
248172ac97cdSTom Musta   Int  residue=0;		   /* as usual */
248272ac97cdSTom Musta   Int  dropped;			   /* work */
248372ac97cdSTom Musta 
248472ac97cdSTom Musta   #if DECCHECK
248572ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
248672ac97cdSTom Musta   #endif
248772ac97cdSTom Musta 
248872ac97cdSTom Musta   do {				   /* protect allocated storage */
248972ac97cdSTom Musta     #if DECSUBSET
249072ac97cdSTom Musta     if (!set->extended) {
249172ac97cdSTom Musta       /* reduce operand and set lostDigits status, as needed */
249272ac97cdSTom Musta       if (rhs->digits>set->digits) {
249372ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, &status);
249472ac97cdSTom Musta 	if (allocrhs==NULL) break;
249572ac97cdSTom Musta 	rhs=allocrhs;
249672ac97cdSTom Musta 	}
249772ac97cdSTom Musta       }
249872ac97cdSTom Musta     #endif
249972ac97cdSTom Musta     /* [following code does not require input rounding] */
250072ac97cdSTom Musta 
250172ac97cdSTom Musta     /* Infinities copy through; NaNs need usual treatment */
250272ac97cdSTom Musta     if (decNumberIsNaN(rhs)) {
250372ac97cdSTom Musta       decNaNs(res, rhs, NULL, set, &status);
250472ac97cdSTom Musta       break;
250572ac97cdSTom Musta       }
250672ac97cdSTom Musta 
250772ac97cdSTom Musta     /* reduce result to the requested length and copy to result */
250872ac97cdSTom Musta     decCopyFit(res, rhs, set, &residue, &status); /* copy & round */
250972ac97cdSTom Musta     decFinish(res, set, &residue, &status);	  /* cleanup/set flags */
251072ac97cdSTom Musta     decTrim(res, set, 1, &dropped);		  /* normalize in place */
251172ac97cdSTom Musta     } while(0);				     /* end protected */
251272ac97cdSTom Musta 
251372ac97cdSTom Musta   #if DECSUBSET
251472ac97cdSTom Musta   if (allocrhs !=NULL) free(allocrhs);	     /* .. */
251572ac97cdSTom Musta   #endif
251672ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);/* then report status */
251772ac97cdSTom Musta   return res;
251872ac97cdSTom Musta   } /* decNumberReduce */
251972ac97cdSTom Musta 
252072ac97cdSTom Musta /* ------------------------------------------------------------------ */
252172ac97cdSTom Musta /* decNumberRescale -- force exponent to requested value	      */
252272ac97cdSTom Musta /*								      */
252372ac97cdSTom Musta /*   This computes C = op(A, B), where op adjusts the coefficient     */
252472ac97cdSTom Musta /*   of C (by rounding or shifting) such that the exponent (-scale)   */
252572ac97cdSTom Musta /*   of C has the value B.  The numerical value of C will equal A,    */
252672ac97cdSTom Musta /*   except for the effects of any rounding that occurred.	      */
252772ac97cdSTom Musta /*								      */
252872ac97cdSTom Musta /*   res is C, the result.  C may be A or B			      */
252972ac97cdSTom Musta /*   lhs is A, the number to adjust				      */
253072ac97cdSTom Musta /*   rhs is B, the requested exponent				      */
253172ac97cdSTom Musta /*   set is the context						      */
253272ac97cdSTom Musta /*								      */
253372ac97cdSTom Musta /* C must have space for set->digits digits.			      */
253472ac97cdSTom Musta /*								      */
253572ac97cdSTom Musta /* Unless there is an error or the result is infinite, the exponent   */
253672ac97cdSTom Musta /* after the operation is guaranteed to be equal to B.		      */
253772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberRescale(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)253872ac97cdSTom Musta decNumber * decNumberRescale(decNumber *res, const decNumber *lhs,
253972ac97cdSTom Musta 			     const decNumber *rhs, decContext *set) {
254072ac97cdSTom Musta   uInt status=0;			/* accumulator */
254172ac97cdSTom Musta   decQuantizeOp(res, lhs, rhs, set, 0, &status);
254272ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
254372ac97cdSTom Musta   return res;
254472ac97cdSTom Musta   } /* decNumberRescale */
254572ac97cdSTom Musta 
254672ac97cdSTom Musta /* ------------------------------------------------------------------ */
254772ac97cdSTom Musta /* decNumberRemainder -- divide and return remainder		      */
254872ac97cdSTom Musta /*								      */
254972ac97cdSTom Musta /*   This computes C = A % B					      */
255072ac97cdSTom Musta /*								      */
255172ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X%X)	      */
255272ac97cdSTom Musta /*   lhs is A							      */
255372ac97cdSTom Musta /*   rhs is B							      */
255472ac97cdSTom Musta /*   set is the context						      */
255572ac97cdSTom Musta /*								      */
255672ac97cdSTom Musta /* C must have space for set->digits digits.			      */
255772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberRemainder(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)255872ac97cdSTom Musta decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs,
255972ac97cdSTom Musta 			       const decNumber *rhs, decContext *set) {
256072ac97cdSTom Musta   uInt status=0;			/* accumulator */
256172ac97cdSTom Musta   decDivideOp(res, lhs, rhs, set, REMAINDER, &status);
256272ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
256372ac97cdSTom Musta   #if DECCHECK
256472ac97cdSTom Musta   decCheckInexact(res, set);
256572ac97cdSTom Musta   #endif
256672ac97cdSTom Musta   return res;
256772ac97cdSTom Musta   } /* decNumberRemainder */
256872ac97cdSTom Musta 
256972ac97cdSTom Musta /* ------------------------------------------------------------------ */
257072ac97cdSTom Musta /* decNumberRemainderNear -- divide and return remainder from nearest */
257172ac97cdSTom Musta /*								      */
257272ac97cdSTom Musta /*   This computes C = A % B, where % is the IEEE remainder operator  */
257372ac97cdSTom Musta /*								      */
257472ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X%X)	      */
257572ac97cdSTom Musta /*   lhs is A							      */
257672ac97cdSTom Musta /*   rhs is B							      */
257772ac97cdSTom Musta /*   set is the context						      */
257872ac97cdSTom Musta /*								      */
257972ac97cdSTom Musta /* C must have space for set->digits digits.			      */
258072ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberRemainderNear(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)258172ac97cdSTom Musta decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs,
258272ac97cdSTom Musta 				   const decNumber *rhs, decContext *set) {
258372ac97cdSTom Musta   uInt status=0;			/* accumulator */
258472ac97cdSTom Musta   decDivideOp(res, lhs, rhs, set, REMNEAR, &status);
258572ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
258672ac97cdSTom Musta   #if DECCHECK
258772ac97cdSTom Musta   decCheckInexact(res, set);
258872ac97cdSTom Musta   #endif
258972ac97cdSTom Musta   return res;
259072ac97cdSTom Musta   } /* decNumberRemainderNear */
259172ac97cdSTom Musta 
259272ac97cdSTom Musta /* ------------------------------------------------------------------ */
259372ac97cdSTom Musta /* decNumberRotate -- rotate the coefficient of a Number left/right   */
259472ac97cdSTom Musta /*								      */
259572ac97cdSTom Musta /*   This computes C = A rot B	(in base ten and rotating set->digits */
259672ac97cdSTom Musta /*   digits).							      */
259772ac97cdSTom Musta /*								      */
259872ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=XrotX)	      */
259972ac97cdSTom Musta /*   lhs is A							      */
260072ac97cdSTom Musta /*   rhs is B, the number of digits to rotate (-ve to right)	      */
260172ac97cdSTom Musta /*   set is the context						      */
260272ac97cdSTom Musta /*								      */
260372ac97cdSTom Musta /* The digits of the coefficient of A are rotated to the left (if B   */
260472ac97cdSTom Musta /* is positive) or to the right (if B is negative) without adjusting  */
260572ac97cdSTom Musta /* the exponent or the sign of A.  If lhs->digits is less than	      */
260672ac97cdSTom Musta /* set->digits the coefficient is padded with zeros on the left	      */
260772ac97cdSTom Musta /* before the rotate.  Any leading zeros in the result are removed    */
260872ac97cdSTom Musta /* as usual.							      */
260972ac97cdSTom Musta /*								      */
261072ac97cdSTom Musta /* B must be an integer (q=0) and in the range -set->digits through   */
261172ac97cdSTom Musta /* +set->digits.						      */
261272ac97cdSTom Musta /* C must have space for set->digits digits.			      */
261372ac97cdSTom Musta /* NaNs are propagated as usual.  Infinities are unaffected (but      */
261472ac97cdSTom Musta /* B must be valid).  No status is set unless B is invalid or an      */
261572ac97cdSTom Musta /* operand is an sNaN.						      */
261672ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberRotate(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)261772ac97cdSTom Musta decNumber * decNumberRotate(decNumber *res, const decNumber *lhs,
261872ac97cdSTom Musta 			   const decNumber *rhs, decContext *set) {
261972ac97cdSTom Musta   uInt status=0;	      /* accumulator */
262072ac97cdSTom Musta   Int  rotate;		      /* rhs as an Int */
262172ac97cdSTom Musta 
262272ac97cdSTom Musta   #if DECCHECK
262372ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
262472ac97cdSTom Musta   #endif
262572ac97cdSTom Musta 
262672ac97cdSTom Musta   /* NaNs propagate as normal */
262772ac97cdSTom Musta   if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
262872ac97cdSTom Musta     decNaNs(res, lhs, rhs, set, &status);
262972ac97cdSTom Musta    /* rhs must be an integer */
263072ac97cdSTom Musta    else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
263172ac97cdSTom Musta     status=DEC_Invalid_operation;
263272ac97cdSTom Musta    else { /* both numeric, rhs is an integer */
263372ac97cdSTom Musta     rotate=decGetInt(rhs);		     /* [cannot fail] */
263472ac97cdSTom Musta     if (rotate==BADINT			     /* something bad .. */
263572ac97cdSTom Musta      || rotate==BIGODD || rotate==BIGEVEN    /* .. very big .. */
263672ac97cdSTom Musta      || abs(rotate)>set->digits)	     /* .. or out of range */
263772ac97cdSTom Musta       status=DEC_Invalid_operation;
263872ac97cdSTom Musta      else {				     /* rhs is OK */
263972ac97cdSTom Musta       decNumberCopy(res, lhs);
264072ac97cdSTom Musta       /* convert -ve rotate to equivalent positive rotation */
264172ac97cdSTom Musta       if (rotate<0) rotate=set->digits+rotate;
264272ac97cdSTom Musta       if (rotate!=0 && rotate!=set->digits   /* zero or full rotation */
264372ac97cdSTom Musta        && !decNumberIsInfinite(res)) {	     /* lhs was infinite */
264472ac97cdSTom Musta 	/* left-rotate to do; 0 < rotate < set->digits */
264572ac97cdSTom Musta 	uInt units, shift;		     /* work */
264672ac97cdSTom Musta 	uInt msudigits;			     /* digits in result msu */
264772ac97cdSTom Musta 	Unit *msu=res->lsu+D2U(res->digits)-1;	  /* current msu */
264872ac97cdSTom Musta 	Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */
264972ac97cdSTom Musta 	for (msu++; msu<=msumax; msu++) *msu=0;	  /* ensure high units=0 */
265072ac97cdSTom Musta 	res->digits=set->digits;		  /* now full-length */
265172ac97cdSTom Musta 	msudigits=MSUDIGITS(res->digits);	  /* actual digits in msu */
265272ac97cdSTom Musta 
265372ac97cdSTom Musta 	/* rotation here is done in-place, in three steps */
265472ac97cdSTom Musta 	/* 1. shift all to least up to one unit to unit-align final */
265572ac97cdSTom Musta 	/*    lsd [any digits shifted out are rotated to the left, */
265672ac97cdSTom Musta 	/*    abutted to the original msd (which may require split)] */
265772ac97cdSTom Musta 	/* */
265872ac97cdSTom Musta 	/*    [if there are no whole units left to rotate, the */
265972ac97cdSTom Musta 	/*    rotation is now complete] */
266072ac97cdSTom Musta 	/* */
266172ac97cdSTom Musta 	/* 2. shift to least, from below the split point only, so that */
266272ac97cdSTom Musta 	/*    the final msd is in the right place in its Unit [any */
266372ac97cdSTom Musta 	/*    digits shifted out will fit exactly in the current msu, */
266472ac97cdSTom Musta 	/*    left aligned, no split required] */
266572ac97cdSTom Musta 	/* */
266672ac97cdSTom Musta 	/* 3. rotate all the units by reversing left part, right */
266772ac97cdSTom Musta 	/*    part, and then whole */
266872ac97cdSTom Musta 	/* */
266972ac97cdSTom Musta 	/* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */
267072ac97cdSTom Musta 	/* */
267172ac97cdSTom Musta 	/*   start: 00a bcd efg hij klm npq */
267272ac97cdSTom Musta 	/* */
267372ac97cdSTom Musta 	/*	1a  000 0ab cde fgh|ijk lmn [pq saved] */
267472ac97cdSTom Musta 	/*	1b  00p qab cde fgh|ijk lmn */
267572ac97cdSTom Musta 	/* */
267672ac97cdSTom Musta 	/*	2a  00p qab cde fgh|00i jkl [mn saved] */
267772ac97cdSTom Musta 	/*	2b  mnp qab cde fgh|00i jkl */
267872ac97cdSTom Musta 	/* */
267972ac97cdSTom Musta 	/*	3a  fgh cde qab mnp|00i jkl */
268072ac97cdSTom Musta 	/*	3b  fgh cde qab mnp|jkl 00i */
268172ac97cdSTom Musta 	/*	3c  00i jkl mnp qab cde fgh */
268272ac97cdSTom Musta 
268372ac97cdSTom Musta 	/* Step 1: amount to shift is the partial right-rotate count */
268472ac97cdSTom Musta 	rotate=set->digits-rotate;	/* make it right-rotate */
268572ac97cdSTom Musta 	units=rotate/DECDPUN;		/* whole units to rotate */
268672ac97cdSTom Musta 	shift=rotate%DECDPUN;		/* left-over digits count */
268772ac97cdSTom Musta 	if (shift>0) {			/* not an exact number of units */
268872ac97cdSTom Musta 	  uInt save=res->lsu[0]%powers[shift];	  /* save low digit(s) */
268972ac97cdSTom Musta 	  decShiftToLeast(res->lsu, D2U(res->digits), shift);
269072ac97cdSTom Musta 	  if (shift>msudigits) {	/* msumax-1 needs >0 digits */
269172ac97cdSTom Musta 	    uInt rem=save%powers[shift-msudigits];/* split save */
269272ac97cdSTom Musta 	    *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */
269372ac97cdSTom Musta 	    *(msumax-1)=*(msumax-1)
269472ac97cdSTom Musta 		       +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */
269572ac97cdSTom Musta 	    }
269672ac97cdSTom Musta 	   else { /* all fits in msumax */
269772ac97cdSTom Musta 	    *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */
269872ac97cdSTom Musta 	    }
269972ac97cdSTom Musta 	  } /* digits shift needed */
270072ac97cdSTom Musta 
270172ac97cdSTom Musta 	/* If whole units to rotate... */
270272ac97cdSTom Musta 	if (units>0) {			/* some to do */
270372ac97cdSTom Musta 	  /* Step 2: the units to touch are the whole ones in rotate, */
270472ac97cdSTom Musta 	  /*   if any, and the shift is DECDPUN-msudigits (which may be */
270572ac97cdSTom Musta 	  /*   0, again) */
270672ac97cdSTom Musta 	  shift=DECDPUN-msudigits;
270772ac97cdSTom Musta 	  if (shift>0) {		/* not an exact number of units */
270872ac97cdSTom Musta 	    uInt save=res->lsu[0]%powers[shift];  /* save low digit(s) */
270972ac97cdSTom Musta 	    decShiftToLeast(res->lsu, units, shift);
271072ac97cdSTom Musta 	    *msumax=*msumax+(Unit)(save*powers[msudigits]);
271172ac97cdSTom Musta 	    } /* partial shift needed */
271272ac97cdSTom Musta 
271372ac97cdSTom Musta 	  /* Step 3: rotate the units array using triple reverse */
271472ac97cdSTom Musta 	  /* (reversing is easy and fast) */
271572ac97cdSTom Musta 	  decReverse(res->lsu+units, msumax);	  /* left part */
271672ac97cdSTom Musta 	  decReverse(res->lsu, res->lsu+units-1); /* right part */
271772ac97cdSTom Musta 	  decReverse(res->lsu, msumax);		  /* whole */
271872ac97cdSTom Musta 	  } /* whole units to rotate */
271972ac97cdSTom Musta 	/* the rotation may have left an undetermined number of zeros */
272072ac97cdSTom Musta 	/* on the left, so true length needs to be calculated */
272172ac97cdSTom Musta 	res->digits=decGetDigits(res->lsu, msumax-res->lsu+1);
272272ac97cdSTom Musta 	} /* rotate needed */
272372ac97cdSTom Musta       } /* rhs OK */
272472ac97cdSTom Musta     } /* numerics */
272572ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
272672ac97cdSTom Musta   return res;
272772ac97cdSTom Musta   } /* decNumberRotate */
272872ac97cdSTom Musta 
272972ac97cdSTom Musta /* ------------------------------------------------------------------ */
273072ac97cdSTom Musta /* decNumberSameQuantum -- test for equal exponents		      */
273172ac97cdSTom Musta /*								      */
273272ac97cdSTom Musta /*   res is the result number, which will contain either 0 or 1	      */
273372ac97cdSTom Musta /*   lhs is a number to test					      */
273472ac97cdSTom Musta /*   rhs is the second (usually a pattern)			      */
273572ac97cdSTom Musta /*								      */
273672ac97cdSTom Musta /* No errors are possible and no context is needed.		      */
273772ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberSameQuantum(decNumber * res,const decNumber * lhs,const decNumber * rhs)273872ac97cdSTom Musta decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs,
273972ac97cdSTom Musta 				 const decNumber *rhs) {
274072ac97cdSTom Musta   Unit ret=0;			   /* return value */
274172ac97cdSTom Musta 
274272ac97cdSTom Musta   #if DECCHECK
274372ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res;
274472ac97cdSTom Musta   #endif
274572ac97cdSTom Musta 
274672ac97cdSTom Musta   if (SPECIALARGS) {
274772ac97cdSTom Musta     if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1;
274872ac97cdSTom Musta      else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1;
274972ac97cdSTom Musta      /* [anything else with a special gives 0] */
275072ac97cdSTom Musta     }
275172ac97cdSTom Musta    else if (lhs->exponent==rhs->exponent) ret=1;
275272ac97cdSTom Musta 
275372ac97cdSTom Musta   decNumberZero(res);		   /* OK to overwrite an operand now */
275472ac97cdSTom Musta   *res->lsu=ret;
275572ac97cdSTom Musta   return res;
275672ac97cdSTom Musta   } /* decNumberSameQuantum */
275772ac97cdSTom Musta 
275872ac97cdSTom Musta /* ------------------------------------------------------------------ */
275972ac97cdSTom Musta /* decNumberScaleB -- multiply by a power of 10			      */
276072ac97cdSTom Musta /*								      */
276172ac97cdSTom Musta /* This computes C = A x 10**B where B is an integer (q=0) with	      */
276272ac97cdSTom Musta /* maximum magnitude 2*(emax+digits)				      */
276372ac97cdSTom Musta /*								      */
276472ac97cdSTom Musta /*   res is C, the result.  C may be A or B			      */
276572ac97cdSTom Musta /*   lhs is A, the number to adjust				      */
276672ac97cdSTom Musta /*   rhs is B, the requested power of ten to use		      */
276772ac97cdSTom Musta /*   set is the context						      */
276872ac97cdSTom Musta /*								      */
276972ac97cdSTom Musta /* C must have space for set->digits digits.			      */
277072ac97cdSTom Musta /*								      */
277172ac97cdSTom Musta /* The result may underflow or overflow.			      */
277272ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberScaleB(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)277372ac97cdSTom Musta decNumber * decNumberScaleB(decNumber *res, const decNumber *lhs,
277472ac97cdSTom Musta 			    const decNumber *rhs, decContext *set) {
277572ac97cdSTom Musta   Int  reqexp;		      /* requested exponent change [B] */
277672ac97cdSTom Musta   uInt status=0;	      /* accumulator */
277772ac97cdSTom Musta   Int  residue;		      /* work */
277872ac97cdSTom Musta 
277972ac97cdSTom Musta   #if DECCHECK
278072ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
278172ac97cdSTom Musta   #endif
278272ac97cdSTom Musta 
278372ac97cdSTom Musta   /* Handle special values except lhs infinite */
278472ac97cdSTom Musta   if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
278572ac97cdSTom Musta     decNaNs(res, lhs, rhs, set, &status);
278672ac97cdSTom Musta     /* rhs must be an integer */
278772ac97cdSTom Musta    else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
278872ac97cdSTom Musta     status=DEC_Invalid_operation;
278972ac97cdSTom Musta    else {
279072ac97cdSTom Musta     /* lhs is a number; rhs is a finite with q==0 */
279172ac97cdSTom Musta     reqexp=decGetInt(rhs);		     /* [cannot fail] */
279272ac97cdSTom Musta     if (reqexp==BADINT			     /* something bad .. */
279372ac97cdSTom Musta      || reqexp==BIGODD || reqexp==BIGEVEN    /* .. very big .. */
279472ac97cdSTom Musta      || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */
279572ac97cdSTom Musta       status=DEC_Invalid_operation;
279672ac97cdSTom Musta      else {				     /* rhs is OK */
279772ac97cdSTom Musta       decNumberCopy(res, lhs);		     /* all done if infinite lhs */
279872ac97cdSTom Musta       if (!decNumberIsInfinite(res)) {	     /* prepare to scale */
279972ac97cdSTom Musta 	res->exponent+=reqexp;		     /* adjust the exponent */
280072ac97cdSTom Musta 	residue=0;
280172ac97cdSTom Musta 	decFinalize(res, set, &residue, &status); /* .. and check */
280272ac97cdSTom Musta 	} /* finite LHS */
280372ac97cdSTom Musta       } /* rhs OK */
280472ac97cdSTom Musta     } /* rhs finite */
280572ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
280672ac97cdSTom Musta   return res;
280772ac97cdSTom Musta   } /* decNumberScaleB */
280872ac97cdSTom Musta 
280972ac97cdSTom Musta /* ------------------------------------------------------------------ */
281072ac97cdSTom Musta /* decNumberShift -- shift the coefficient of a Number left or right  */
281172ac97cdSTom Musta /*								      */
281272ac97cdSTom Musta /*   This computes C = A << B or C = A >> -B  (in base ten).	      */
281372ac97cdSTom Musta /*								      */
281472ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X<<X)	      */
281572ac97cdSTom Musta /*   lhs is A							      */
281672ac97cdSTom Musta /*   rhs is B, the number of digits to shift (-ve to right)	      */
281772ac97cdSTom Musta /*   set is the context						      */
281872ac97cdSTom Musta /*								      */
281972ac97cdSTom Musta /* The digits of the coefficient of A are shifted to the left (if B   */
282072ac97cdSTom Musta /* is positive) or to the right (if B is negative) without adjusting  */
282172ac97cdSTom Musta /* the exponent or the sign of A.				      */
282272ac97cdSTom Musta /*								      */
282372ac97cdSTom Musta /* B must be an integer (q=0) and in the range -set->digits through   */
282472ac97cdSTom Musta /* +set->digits.						      */
282572ac97cdSTom Musta /* C must have space for set->digits digits.			      */
282672ac97cdSTom Musta /* NaNs are propagated as usual.  Infinities are unaffected (but      */
282772ac97cdSTom Musta /* B must be valid).  No status is set unless B is invalid or an      */
282872ac97cdSTom Musta /* operand is an sNaN.						      */
282972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberShift(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)283072ac97cdSTom Musta decNumber * decNumberShift(decNumber *res, const decNumber *lhs,
283172ac97cdSTom Musta 			   const decNumber *rhs, decContext *set) {
283272ac97cdSTom Musta   uInt status=0;	      /* accumulator */
283372ac97cdSTom Musta   Int  shift;		      /* rhs as an Int */
283472ac97cdSTom Musta 
283572ac97cdSTom Musta   #if DECCHECK
283672ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
283772ac97cdSTom Musta   #endif
283872ac97cdSTom Musta 
283972ac97cdSTom Musta   /* NaNs propagate as normal */
284072ac97cdSTom Musta   if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
284172ac97cdSTom Musta     decNaNs(res, lhs, rhs, set, &status);
284272ac97cdSTom Musta    /* rhs must be an integer */
284372ac97cdSTom Musta    else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
284472ac97cdSTom Musta     status=DEC_Invalid_operation;
284572ac97cdSTom Musta    else { /* both numeric, rhs is an integer */
284672ac97cdSTom Musta     shift=decGetInt(rhs);		     /* [cannot fail] */
284772ac97cdSTom Musta     if (shift==BADINT			     /* something bad .. */
284872ac97cdSTom Musta      || shift==BIGODD || shift==BIGEVEN	     /* .. very big .. */
284972ac97cdSTom Musta      || abs(shift)>set->digits)		     /* .. or out of range */
285072ac97cdSTom Musta       status=DEC_Invalid_operation;
285172ac97cdSTom Musta      else {				     /* rhs is OK */
285272ac97cdSTom Musta       decNumberCopy(res, lhs);
285372ac97cdSTom Musta       if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */
285472ac97cdSTom Musta 	if (shift>0) {			     /* to left */
285572ac97cdSTom Musta 	  if (shift==set->digits) {	     /* removing all */
285672ac97cdSTom Musta 	    *res->lsu=0;		     /* so place 0 */
285772ac97cdSTom Musta 	    res->digits=1;		     /* .. */
285872ac97cdSTom Musta 	    }
285972ac97cdSTom Musta 	   else {			     /* */
286072ac97cdSTom Musta 	    /* first remove leading digits if necessary */
286172ac97cdSTom Musta 	    if (res->digits+shift>set->digits) {
286272ac97cdSTom Musta 	      decDecap(res, res->digits+shift-set->digits);
286372ac97cdSTom Musta 	      /* that updated res->digits; may have gone to 1 (for a */
286472ac97cdSTom Musta 	      /* single digit or for zero */
286572ac97cdSTom Musta 	      }
286672ac97cdSTom Musta 	    if (res->digits>1 || *res->lsu)  /* if non-zero.. */
286772ac97cdSTom Musta 	      res->digits=decShiftToMost(res->lsu, res->digits, shift);
286872ac97cdSTom Musta 	    } /* partial left */
286972ac97cdSTom Musta 	  } /* left */
287072ac97cdSTom Musta 	 else { /* to right */
287172ac97cdSTom Musta 	  if (-shift>=res->digits) {	     /* discarding all */
287272ac97cdSTom Musta 	    *res->lsu=0;		     /* so place 0 */
287372ac97cdSTom Musta 	    res->digits=1;		     /* .. */
287472ac97cdSTom Musta 	    }
287572ac97cdSTom Musta 	   else {
287672ac97cdSTom Musta 	    decShiftToLeast(res->lsu, D2U(res->digits), -shift);
287772ac97cdSTom Musta 	    res->digits-=(-shift);
287872ac97cdSTom Musta 	    }
287972ac97cdSTom Musta 	  } /* to right */
288072ac97cdSTom Musta 	} /* non-0 non-Inf shift */
288172ac97cdSTom Musta       } /* rhs OK */
288272ac97cdSTom Musta     } /* numerics */
288372ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
288472ac97cdSTom Musta   return res;
288572ac97cdSTom Musta   } /* decNumberShift */
288672ac97cdSTom Musta 
288772ac97cdSTom Musta /* ------------------------------------------------------------------ */
288872ac97cdSTom Musta /* decNumberSquareRoot -- square root operator			      */
288972ac97cdSTom Musta /*								      */
289072ac97cdSTom Musta /*   This computes C = squareroot(A)				      */
289172ac97cdSTom Musta /*								      */
289272ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
289372ac97cdSTom Musta /*   rhs is A							      */
289472ac97cdSTom Musta /*   set is the context; note that rounding mode has no effect	      */
289572ac97cdSTom Musta /*								      */
289672ac97cdSTom Musta /* C must have space for set->digits digits.			      */
289772ac97cdSTom Musta /* ------------------------------------------------------------------ */
289872ac97cdSTom Musta /* This uses the following varying-precision algorithm in:	      */
289972ac97cdSTom Musta /*								      */
290072ac97cdSTom Musta /*   Properly Rounded Variable Precision Square Root, T. E. Hull and  */
290172ac97cdSTom Musta /*   A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */
290272ac97cdSTom Musta /*   pp229-237, ACM, September 1985.				      */
290372ac97cdSTom Musta /*								      */
290472ac97cdSTom Musta /* The square-root is calculated using Newton's method, after which   */
290572ac97cdSTom Musta /* a check is made to ensure the result is correctly rounded.	      */
290672ac97cdSTom Musta /*								      */
290772ac97cdSTom Musta /* % [Reformatted original Numerical Turing source code follows.]     */
290872ac97cdSTom Musta /* function sqrt(x : real) : real				      */
290972ac97cdSTom Musta /* % sqrt(x) returns the properly rounded approximation to the square */
291072ac97cdSTom Musta /* % root of x, in the precision of the calling environment, or it    */
291172ac97cdSTom Musta /* % fails if x < 0.						      */
291272ac97cdSTom Musta /* % t e hull and a abrham, august, 1984			      */
291372ac97cdSTom Musta /* if x <= 0 then						      */
291472ac97cdSTom Musta /*   if x < 0 then						      */
291572ac97cdSTom Musta /*     assert false						      */
291672ac97cdSTom Musta /*   else							      */
291772ac97cdSTom Musta /*     result 0							      */
291872ac97cdSTom Musta /*   end if							      */
291972ac97cdSTom Musta /* end if							      */
292072ac97cdSTom Musta /* var f := setexp(x, 0)  % fraction part of x	 [0.1 <= x < 1]	      */
292172ac97cdSTom Musta /* var e := getexp(x)	  % exponent part of x			      */
292272ac97cdSTom Musta /* var approx : real						      */
292372ac97cdSTom Musta /* if e mod 2 = 0  then						      */
292472ac97cdSTom Musta /*   approx := .259 + .819 * f	 % approx to root of f		      */
292572ac97cdSTom Musta /* else								      */
292672ac97cdSTom Musta /*   f := f/l0			 % adjustments			      */
292772ac97cdSTom Musta /*   e := e + 1			 %   for odd			      */
292872ac97cdSTom Musta /*   approx := .0819 + 2.59 * f	 %   exponent			      */
292972ac97cdSTom Musta /* end if							      */
293072ac97cdSTom Musta /*								      */
293172ac97cdSTom Musta /* var p:= 3							      */
293272ac97cdSTom Musta /* const maxp := currentprecision + 2				      */
293372ac97cdSTom Musta /* loop								      */
293472ac97cdSTom Musta /*   p := min(2*p - 2, maxp)	 % p = 4,6,10, . . . , maxp	      */
293572ac97cdSTom Musta /*   precision p						      */
293672ac97cdSTom Musta /*   approx := .5 * (approx + f/approx)				      */
293772ac97cdSTom Musta /*   exit when p = maxp						      */
293872ac97cdSTom Musta /* end loop							      */
293972ac97cdSTom Musta /*								      */
294072ac97cdSTom Musta /* % approx is now within 1 ulp of the properly rounded square root   */
294172ac97cdSTom Musta /* % of f; to ensure proper rounding, compare squares of (approx -    */
294272ac97cdSTom Musta /* % l/2 ulp) and (approx + l/2 ulp) with f.			      */
294372ac97cdSTom Musta /* p := currentprecision					      */
294472ac97cdSTom Musta /* begin							      */
294572ac97cdSTom Musta /*   precision p + 2						      */
294672ac97cdSTom Musta /*   const approxsubhalf := approx - setexp(.5, -p)		      */
294772ac97cdSTom Musta /*   if mulru(approxsubhalf, approxsubhalf) > f then		      */
294872ac97cdSTom Musta /*     approx := approx - setexp(.l, -p + 1)			      */
294972ac97cdSTom Musta /*   else							      */
295072ac97cdSTom Musta /*     const approxaddhalf := approx + setexp(.5, -p)		      */
295172ac97cdSTom Musta /*     if mulrd(approxaddhalf, approxaddhalf) < f then		      */
295272ac97cdSTom Musta /*	 approx := approx + setexp(.l, -p + 1)			      */
295372ac97cdSTom Musta /*     end if							      */
295472ac97cdSTom Musta /*   end if							      */
295572ac97cdSTom Musta /* end								      */
295672ac97cdSTom Musta /* result setexp(approx, e div 2)  % fix exponent		      */
295772ac97cdSTom Musta /* end sqrt							      */
295872ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberSquareRoot(decNumber * res,const decNumber * rhs,decContext * set)295972ac97cdSTom Musta decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs,
296072ac97cdSTom Musta 				decContext *set) {
296172ac97cdSTom Musta   decContext workset, approxset;   /* work contexts */
296272ac97cdSTom Musta   decNumber dzero;		   /* used for constant zero */
296372ac97cdSTom Musta   Int  maxp;			   /* largest working precision */
296472ac97cdSTom Musta   Int  workp;			   /* working precision */
296572ac97cdSTom Musta   Int  residue=0;		   /* rounding residue */
296672ac97cdSTom Musta   uInt status=0, ignore=0;	   /* status accumulators */
296772ac97cdSTom Musta   uInt rstatus;			   /* .. */
296872ac97cdSTom Musta   Int  exp;			   /* working exponent */
296972ac97cdSTom Musta   Int  ideal;			   /* ideal (preferred) exponent */
297072ac97cdSTom Musta   Int  needbytes;		   /* work */
297172ac97cdSTom Musta   Int  dropped;			   /* .. */
297272ac97cdSTom Musta 
297372ac97cdSTom Musta   #if DECSUBSET
297472ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* non-NULL if rounded rhs allocated */
297572ac97cdSTom Musta   #endif
297672ac97cdSTom Musta   /* buffer for f [needs +1 in case DECBUFFER 0] */
297772ac97cdSTom Musta   decNumber buff[D2N(DECBUFFER+1)];
297872ac97cdSTom Musta   /* buffer for a [needs +2 to match likely maxp] */
297972ac97cdSTom Musta   decNumber bufa[D2N(DECBUFFER+2)];
298072ac97cdSTom Musta   /* buffer for temporary, b [must be same size as a] */
298172ac97cdSTom Musta   decNumber bufb[D2N(DECBUFFER+2)];
298272ac97cdSTom Musta   decNumber *allocbuff=NULL;	   /* -> allocated buff, iff allocated */
298372ac97cdSTom Musta   decNumber *allocbufa=NULL;	   /* -> allocated bufa, iff allocated */
298472ac97cdSTom Musta   decNumber *allocbufb=NULL;	   /* -> allocated bufb, iff allocated */
298572ac97cdSTom Musta   decNumber *f=buff;		   /* reduced fraction */
298672ac97cdSTom Musta   decNumber *a=bufa;		   /* approximation to result */
298772ac97cdSTom Musta   decNumber *b=bufb;		   /* intermediate result */
298872ac97cdSTom Musta   /* buffer for temporary variable, up to 3 digits */
298972ac97cdSTom Musta   decNumber buft[D2N(3)];
299072ac97cdSTom Musta   decNumber *t=buft;		   /* up-to-3-digit constant or work */
299172ac97cdSTom Musta 
299272ac97cdSTom Musta   #if DECCHECK
299372ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
299472ac97cdSTom Musta   #endif
299572ac97cdSTom Musta 
299672ac97cdSTom Musta   do {				   /* protect allocated storage */
299772ac97cdSTom Musta     #if DECSUBSET
299872ac97cdSTom Musta     if (!set->extended) {
299972ac97cdSTom Musta       /* reduce operand and set lostDigits status, as needed */
300072ac97cdSTom Musta       if (rhs->digits>set->digits) {
300172ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, &status);
300272ac97cdSTom Musta 	if (allocrhs==NULL) break;
300372ac97cdSTom Musta 	/* [Note: 'f' allocation below could reuse this buffer if */
300472ac97cdSTom Musta 	/* used, but as this is rare they are kept separate for clarity.] */
300572ac97cdSTom Musta 	rhs=allocrhs;
300672ac97cdSTom Musta 	}
300772ac97cdSTom Musta       }
300872ac97cdSTom Musta     #endif
300972ac97cdSTom Musta     /* [following code does not require input rounding] */
301072ac97cdSTom Musta 
301172ac97cdSTom Musta     /* handle infinities and NaNs */
301272ac97cdSTom Musta     if (SPECIALARG) {
301372ac97cdSTom Musta       if (decNumberIsInfinite(rhs)) {	      /* an infinity */
301472ac97cdSTom Musta 	if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation;
301572ac97cdSTom Musta 	 else decNumberCopy(res, rhs);	      /* +Infinity */
301672ac97cdSTom Musta 	}
301772ac97cdSTom Musta        else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
301872ac97cdSTom Musta       break;
301972ac97cdSTom Musta       }
302072ac97cdSTom Musta 
302172ac97cdSTom Musta     /* calculate the ideal (preferred) exponent [floor(exp/2)] */
302272ac97cdSTom Musta     /* [We would like to write: ideal=rhs->exponent>>1, but this */
302372ac97cdSTom Musta     /* generates a compiler warning.  Generated code is the same.] */
302472ac97cdSTom Musta     ideal=(rhs->exponent&~1)/2;		/* target */
302572ac97cdSTom Musta 
302672ac97cdSTom Musta     /* handle zeros */
302772ac97cdSTom Musta     if (ISZERO(rhs)) {
302872ac97cdSTom Musta       decNumberCopy(res, rhs);		/* could be 0 or -0 */
302972ac97cdSTom Musta       res->exponent=ideal;		/* use the ideal [safe] */
303072ac97cdSTom Musta       /* use decFinish to clamp any out-of-range exponent, etc. */
303172ac97cdSTom Musta       decFinish(res, set, &residue, &status);
303272ac97cdSTom Musta       break;
303372ac97cdSTom Musta       }
303472ac97cdSTom Musta 
303572ac97cdSTom Musta     /* any other -x is an oops */
303672ac97cdSTom Musta     if (decNumberIsNegative(rhs)) {
303772ac97cdSTom Musta       status|=DEC_Invalid_operation;
303872ac97cdSTom Musta       break;
303972ac97cdSTom Musta       }
304072ac97cdSTom Musta 
304172ac97cdSTom Musta     /* space is needed for three working variables */
304272ac97cdSTom Musta     /*	 f -- the same precision as the RHS, reduced to 0.01->0.99... */
304372ac97cdSTom Musta     /*	 a -- Hull's approximation -- precision, when assigned, is */
304472ac97cdSTom Musta     /*	      currentprecision+1 or the input argument precision, */
304572ac97cdSTom Musta     /*	      whichever is larger (+2 for use as temporary) */
304672ac97cdSTom Musta     /*	 b -- intermediate temporary result (same size as a) */
304772ac97cdSTom Musta     /* if any is too long for local storage, then allocate */
304872ac97cdSTom Musta     workp=MAXI(set->digits+1, rhs->digits);  /* actual rounding precision */
304972ac97cdSTom Musta     maxp=workp+2;			     /* largest working precision */
305072ac97cdSTom Musta 
305172ac97cdSTom Musta     needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
305272ac97cdSTom Musta     if (needbytes>(Int)sizeof(buff)) {
305372ac97cdSTom Musta       allocbuff=(decNumber *)malloc(needbytes);
305472ac97cdSTom Musta       if (allocbuff==NULL) {  /* hopeless -- abandon */
305572ac97cdSTom Musta 	status|=DEC_Insufficient_storage;
305672ac97cdSTom Musta 	break;}
305772ac97cdSTom Musta       f=allocbuff;	      /* use the allocated space */
305872ac97cdSTom Musta       }
305972ac97cdSTom Musta     /* a and b both need to be able to hold a maxp-length number */
306072ac97cdSTom Musta     needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit);
306172ac97cdSTom Musta     if (needbytes>(Int)sizeof(bufa)) {		  /* [same applies to b] */
306272ac97cdSTom Musta       allocbufa=(decNumber *)malloc(needbytes);
306372ac97cdSTom Musta       allocbufb=(decNumber *)malloc(needbytes);
306472ac97cdSTom Musta       if (allocbufa==NULL || allocbufb==NULL) {	  /* hopeless */
306572ac97cdSTom Musta 	status|=DEC_Insufficient_storage;
306672ac97cdSTom Musta 	break;}
306772ac97cdSTom Musta       a=allocbufa;	      /* use the allocated spaces */
306872ac97cdSTom Musta       b=allocbufb;	      /* .. */
306972ac97cdSTom Musta       }
307072ac97cdSTom Musta 
307172ac97cdSTom Musta     /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */
307272ac97cdSTom Musta     decNumberCopy(f, rhs);
307372ac97cdSTom Musta     exp=f->exponent+f->digits;		     /* adjusted to Hull rules */
307472ac97cdSTom Musta     f->exponent=-(f->digits);		     /* to range */
307572ac97cdSTom Musta 
307672ac97cdSTom Musta     /* set up working context */
307772ac97cdSTom Musta     decContextDefault(&workset, DEC_INIT_DECIMAL64);
307872ac97cdSTom Musta 
307972ac97cdSTom Musta     /* [Until further notice, no error is possible and status bits */
308072ac97cdSTom Musta     /* (Rounded, etc.) should be ignored, not accumulated.] */
308172ac97cdSTom Musta 
308272ac97cdSTom Musta     /* Calculate initial approximation, and allow for odd exponent */
308372ac97cdSTom Musta     workset.digits=workp;		     /* p for initial calculation */
308472ac97cdSTom Musta     t->bits=0; t->digits=3;
308572ac97cdSTom Musta     a->bits=0; a->digits=3;
308672ac97cdSTom Musta     if ((exp & 1)==0) {			     /* even exponent */
308772ac97cdSTom Musta       /* Set t=0.259, a=0.819 */
308872ac97cdSTom Musta       t->exponent=-3;
308972ac97cdSTom Musta       a->exponent=-3;
309072ac97cdSTom Musta       #if DECDPUN>=3
309172ac97cdSTom Musta 	t->lsu[0]=259;
309272ac97cdSTom Musta 	a->lsu[0]=819;
309372ac97cdSTom Musta       #elif DECDPUN==2
309472ac97cdSTom Musta 	t->lsu[0]=59; t->lsu[1]=2;
309572ac97cdSTom Musta 	a->lsu[0]=19; a->lsu[1]=8;
309672ac97cdSTom Musta       #else
309772ac97cdSTom Musta 	t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2;
309872ac97cdSTom Musta 	a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8;
309972ac97cdSTom Musta       #endif
310072ac97cdSTom Musta       }
310172ac97cdSTom Musta      else {				     /* odd exponent */
310272ac97cdSTom Musta       /* Set t=0.0819, a=2.59 */
310372ac97cdSTom Musta       f->exponent--;			     /* f=f/10 */
310472ac97cdSTom Musta       exp++;				     /* e=e+1 */
310572ac97cdSTom Musta       t->exponent=-4;
310672ac97cdSTom Musta       a->exponent=-2;
310772ac97cdSTom Musta       #if DECDPUN>=3
310872ac97cdSTom Musta 	t->lsu[0]=819;
310972ac97cdSTom Musta 	a->lsu[0]=259;
311072ac97cdSTom Musta       #elif DECDPUN==2
311172ac97cdSTom Musta 	t->lsu[0]=19; t->lsu[1]=8;
311272ac97cdSTom Musta 	a->lsu[0]=59; a->lsu[1]=2;
311372ac97cdSTom Musta       #else
311472ac97cdSTom Musta 	t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8;
311572ac97cdSTom Musta 	a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2;
311672ac97cdSTom Musta       #endif
311772ac97cdSTom Musta       }
311872ac97cdSTom Musta     decMultiplyOp(a, a, f, &workset, &ignore);	  /* a=a*f */
311972ac97cdSTom Musta     decAddOp(a, a, t, &workset, 0, &ignore);	  /* ..+t */
312072ac97cdSTom Musta     /* [a is now the initial approximation for sqrt(f), calculated with */
312172ac97cdSTom Musta     /* currentprecision, which is also a's precision.] */
312272ac97cdSTom Musta 
312372ac97cdSTom Musta     /* the main calculation loop */
312472ac97cdSTom Musta     decNumberZero(&dzero);		     /* make 0 */
312572ac97cdSTom Musta     decNumberZero(t);			     /* set t = 0.5 */
312672ac97cdSTom Musta     t->lsu[0]=5;			     /* .. */
312772ac97cdSTom Musta     t->exponent=-1;			     /* .. */
312872ac97cdSTom Musta     workset.digits=3;			     /* initial p */
312972ac97cdSTom Musta     for (;;) {
313072ac97cdSTom Musta       /* set p to min(2*p - 2, maxp)  [hence 3; or: 4, 6, 10, ... , maxp] */
313172ac97cdSTom Musta       workset.digits=workset.digits*2-2;
313272ac97cdSTom Musta       if (workset.digits>maxp) workset.digits=maxp;
313372ac97cdSTom Musta       /* a = 0.5 * (a + f/a) */
313472ac97cdSTom Musta       /* [calculated at p then rounded to currentprecision] */
313572ac97cdSTom Musta       decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */
313672ac97cdSTom Musta       decAddOp(b, b, a, &workset, 0, &ignore);	  /* b=b+a */
313772ac97cdSTom Musta       decMultiplyOp(a, b, t, &workset, &ignore);  /* a=b*0.5 */
313872ac97cdSTom Musta       if (a->digits==maxp) break;	     /* have required digits */
313972ac97cdSTom Musta       } /* loop */
314072ac97cdSTom Musta 
314172ac97cdSTom Musta     /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */
314272ac97cdSTom Musta     /* now reduce to length, etc.; this needs to be done with a */
314372ac97cdSTom Musta     /* having the correct exponent so as to handle subnormals */
314472ac97cdSTom Musta     /* correctly */
314572ac97cdSTom Musta     approxset=*set;			     /* get emin, emax, etc. */
314672ac97cdSTom Musta     approxset.round=DEC_ROUND_HALF_EVEN;
314772ac97cdSTom Musta     a->exponent+=exp/2;			     /* set correct exponent */
314872ac97cdSTom Musta 
314972ac97cdSTom Musta     rstatus=0;				     /* clear status */
315072ac97cdSTom Musta     residue=0;				     /* .. and accumulator */
315172ac97cdSTom Musta     decCopyFit(a, a, &approxset, &residue, &rstatus);  /* reduce (if needed) */
315272ac97cdSTom Musta     decFinish(a, &approxset, &residue, &rstatus);      /* clean and finalize */
315372ac97cdSTom Musta 
315472ac97cdSTom Musta     /* Overflow was possible if the input exponent was out-of-range, */
315572ac97cdSTom Musta     /* in which case quit */
315672ac97cdSTom Musta     if (rstatus&DEC_Overflow) {
315772ac97cdSTom Musta       status=rstatus;			     /* use the status as-is */
315872ac97cdSTom Musta       decNumberCopy(res, a);		     /* copy to result */
315972ac97cdSTom Musta       break;
316072ac97cdSTom Musta       }
316172ac97cdSTom Musta 
316272ac97cdSTom Musta     /* Preserve status except Inexact/Rounded */
316372ac97cdSTom Musta     status|=(rstatus & ~(DEC_Rounded|DEC_Inexact));
316472ac97cdSTom Musta 
316572ac97cdSTom Musta     /* Carry out the Hull correction */
316672ac97cdSTom Musta     a->exponent-=exp/2;			     /* back to 0.1->1 */
316772ac97cdSTom Musta 
316872ac97cdSTom Musta     /* a is now at final precision and within 1 ulp of the properly */
316972ac97cdSTom Musta     /* rounded square root of f; to ensure proper rounding, compare */
317072ac97cdSTom Musta     /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */
317172ac97cdSTom Musta     /* Here workset.digits=maxp and t=0.5, and a->digits determines */
317272ac97cdSTom Musta     /* the ulp */
317372ac97cdSTom Musta     workset.digits--;				  /* maxp-1 is OK now */
317472ac97cdSTom Musta     t->exponent=-a->digits-1;			  /* make 0.5 ulp */
317572ac97cdSTom Musta     decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */
317672ac97cdSTom Musta     workset.round=DEC_ROUND_UP;
317772ac97cdSTom Musta     decMultiplyOp(b, b, b, &workset, &ignore);	  /* b = mulru(b, b) */
317872ac97cdSTom Musta     decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */
317972ac97cdSTom Musta     if (decNumberIsNegative(b)) {		  /* f < b [i.e., b > f] */
318072ac97cdSTom Musta       /* this is the more common adjustment, though both are rare */
318172ac97cdSTom Musta       t->exponent++;				  /* make 1.0 ulp */
318272ac97cdSTom Musta       t->lsu[0]=1;				  /* .. */
318372ac97cdSTom Musta       decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */
318472ac97cdSTom Musta       /* assign to approx [round to length] */
318572ac97cdSTom Musta       approxset.emin-=exp/2;			  /* adjust to match a */
318672ac97cdSTom Musta       approxset.emax-=exp/2;
318772ac97cdSTom Musta       decAddOp(a, &dzero, a, &approxset, 0, &ignore);
318872ac97cdSTom Musta       }
318972ac97cdSTom Musta      else {
319072ac97cdSTom Musta       decAddOp(b, a, t, &workset, 0, &ignore);	  /* b = a + 0.5 ulp */
319172ac97cdSTom Musta       workset.round=DEC_ROUND_DOWN;
319272ac97cdSTom Musta       decMultiplyOp(b, b, b, &workset, &ignore);  /* b = mulrd(b, b) */
319372ac97cdSTom Musta       decCompareOp(b, b, f, &workset, COMPARE, &ignore);   /* b ? f */
319472ac97cdSTom Musta       if (decNumberIsNegative(b)) {		  /* b < f */
319572ac97cdSTom Musta 	t->exponent++;				  /* make 1.0 ulp */
319672ac97cdSTom Musta 	t->lsu[0]=1;				  /* .. */
319772ac97cdSTom Musta 	decAddOp(a, a, t, &workset, 0, &ignore);  /* a = a + 1 ulp */
319872ac97cdSTom Musta 	/* assign to approx [round to length] */
319972ac97cdSTom Musta 	approxset.emin-=exp/2;			  /* adjust to match a */
320072ac97cdSTom Musta 	approxset.emax-=exp/2;
320172ac97cdSTom Musta 	decAddOp(a, &dzero, a, &approxset, 0, &ignore);
320272ac97cdSTom Musta 	}
320372ac97cdSTom Musta       }
320472ac97cdSTom Musta     /* [no errors are possible in the above, and rounding/inexact during */
320572ac97cdSTom Musta     /* estimation are irrelevant, so status was not accumulated] */
320672ac97cdSTom Musta 
320772ac97cdSTom Musta     /* Here, 0.1 <= a < 1  (still), so adjust back */
320872ac97cdSTom Musta     a->exponent+=exp/2;			     /* set correct exponent */
320972ac97cdSTom Musta 
321072ac97cdSTom Musta     /* count droppable zeros [after any subnormal rounding] by */
321172ac97cdSTom Musta     /* trimming a copy */
321272ac97cdSTom Musta     decNumberCopy(b, a);
321372ac97cdSTom Musta     decTrim(b, set, 1, &dropped);	     /* [drops trailing zeros] */
321472ac97cdSTom Musta 
321572ac97cdSTom Musta     /* Set Inexact and Rounded.	 The answer can only be exact if */
321672ac97cdSTom Musta     /* it is short enough so that squaring it could fit in workp digits, */
321772ac97cdSTom Musta     /* and it cannot have trailing zeros due to clamping, so these are */
321872ac97cdSTom Musta     /* the only (relatively rare) conditions a careful check is needed */
321972ac97cdSTom Musta     if (b->digits*2-1 > workp && !set->clamp) { /* cannot fit */
322072ac97cdSTom Musta       status|=DEC_Inexact|DEC_Rounded;
322172ac97cdSTom Musta       }
322272ac97cdSTom Musta      else {				     /* could be exact/unrounded */
322372ac97cdSTom Musta       uInt mstatus=0;			     /* local status */
322472ac97cdSTom Musta       decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */
322572ac97cdSTom Musta       if (mstatus&DEC_Overflow) {	     /* result just won't fit */
322672ac97cdSTom Musta 	status|=DEC_Inexact|DEC_Rounded;
322772ac97cdSTom Musta 	}
322872ac97cdSTom Musta        else {				     /* plausible */
322972ac97cdSTom Musta 	decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */
323072ac97cdSTom Musta 	if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */
323172ac97cdSTom Musta 	 else {				     /* is Exact */
323272ac97cdSTom Musta 	  /* here, dropped is the count of trailing zeros in 'a' */
323372ac97cdSTom Musta 	  /* use closest exponent to ideal... */
323472ac97cdSTom Musta 	  Int todrop=ideal-a->exponent;	     /* most that can be dropped */
323572ac97cdSTom Musta 	  if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */
323672ac97cdSTom Musta 	   else {			     /* unrounded */
323772ac97cdSTom Musta 	    if (dropped<todrop) {	     /* clamp to those available */
323872ac97cdSTom Musta 	      todrop=dropped;
323972ac97cdSTom Musta 	      status|=DEC_Clamped;
324072ac97cdSTom Musta 	      }
324172ac97cdSTom Musta 	    if (todrop>0) {		     /* have some to drop */
324272ac97cdSTom Musta 	      decShiftToLeast(a->lsu, D2U(a->digits), todrop);
324372ac97cdSTom Musta 	      a->exponent+=todrop;	     /* maintain numerical value */
324472ac97cdSTom Musta 	      a->digits-=todrop;	     /* new length */
324572ac97cdSTom Musta 	      }
324672ac97cdSTom Musta 	    }
324772ac97cdSTom Musta 	  }
324872ac97cdSTom Musta 	}
324972ac97cdSTom Musta       }
325072ac97cdSTom Musta 
325172ac97cdSTom Musta     /* double-check Underflow, as perhaps the result could not have */
325272ac97cdSTom Musta     /* been subnormal (initial argument too big), or it is now Exact */
325372ac97cdSTom Musta     if (status&DEC_Underflow) {
325472ac97cdSTom Musta       Int ae=rhs->exponent+rhs->digits-1;    /* adjusted exponent */
325572ac97cdSTom Musta       /* check if truly subnormal */
325672ac97cdSTom Musta       #if DECEXTFLAG			     /* DEC_Subnormal too */
325772ac97cdSTom Musta 	if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow);
325872ac97cdSTom Musta       #else
325972ac97cdSTom Musta 	if (ae>=set->emin*2) status&=~DEC_Underflow;
326072ac97cdSTom Musta       #endif
326172ac97cdSTom Musta       /* check if truly inexact */
326272ac97cdSTom Musta       if (!(status&DEC_Inexact)) status&=~DEC_Underflow;
326372ac97cdSTom Musta       }
326472ac97cdSTom Musta 
326572ac97cdSTom Musta     decNumberCopy(res, a);		     /* a is now the result */
326672ac97cdSTom Musta     } while(0);				     /* end protected */
326772ac97cdSTom Musta 
326872ac97cdSTom Musta   if (allocbuff!=NULL) free(allocbuff);	     /* drop any storage used */
326972ac97cdSTom Musta   if (allocbufa!=NULL) free(allocbufa);	     /* .. */
327072ac97cdSTom Musta   if (allocbufb!=NULL) free(allocbufb);	     /* .. */
327172ac97cdSTom Musta   #if DECSUBSET
327272ac97cdSTom Musta   if (allocrhs !=NULL) free(allocrhs);	     /* .. */
327372ac97cdSTom Musta   #endif
327472ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);/* then report status */
327572ac97cdSTom Musta   #if DECCHECK
327672ac97cdSTom Musta   decCheckInexact(res, set);
327772ac97cdSTom Musta   #endif
327872ac97cdSTom Musta   return res;
327972ac97cdSTom Musta   } /* decNumberSquareRoot */
328072ac97cdSTom Musta 
328172ac97cdSTom Musta /* ------------------------------------------------------------------ */
328272ac97cdSTom Musta /* decNumberSubtract -- subtract two Numbers			      */
328372ac97cdSTom Musta /*								      */
328472ac97cdSTom Musta /*   This computes C = A - B					      */
328572ac97cdSTom Musta /*								      */
328672ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X-X)	      */
328772ac97cdSTom Musta /*   lhs is A							      */
328872ac97cdSTom Musta /*   rhs is B							      */
328972ac97cdSTom Musta /*   set is the context						      */
329072ac97cdSTom Musta /*								      */
329172ac97cdSTom Musta /* C must have space for set->digits digits.			      */
329272ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberSubtract(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)329372ac97cdSTom Musta decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs,
329472ac97cdSTom Musta 			      const decNumber *rhs, decContext *set) {
329572ac97cdSTom Musta   uInt status=0;			/* accumulator */
329672ac97cdSTom Musta 
329772ac97cdSTom Musta   decAddOp(res, lhs, rhs, set, DECNEG, &status);
329872ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
329972ac97cdSTom Musta   #if DECCHECK
330072ac97cdSTom Musta   decCheckInexact(res, set);
330172ac97cdSTom Musta   #endif
330272ac97cdSTom Musta   return res;
330372ac97cdSTom Musta   } /* decNumberSubtract */
330472ac97cdSTom Musta 
330572ac97cdSTom Musta /* ------------------------------------------------------------------ */
330672ac97cdSTom Musta /* decNumberToIntegralExact -- round-to-integral-value with InExact   */
330772ac97cdSTom Musta /* decNumberToIntegralValue -- round-to-integral-value		      */
330872ac97cdSTom Musta /*								      */
330972ac97cdSTom Musta /*   res is the result						      */
331072ac97cdSTom Musta /*   rhs is input number					      */
331172ac97cdSTom Musta /*   set is the context						      */
331272ac97cdSTom Musta /*								      */
331372ac97cdSTom Musta /* res must have space for any value of rhs.			      */
331472ac97cdSTom Musta /*								      */
331572ac97cdSTom Musta /* This implements the IEEE special operators and therefore treats    */
331672ac97cdSTom Musta /* special values as valid.  For finite numbers it returns	      */
331772ac97cdSTom Musta /* rescale(rhs, 0) if rhs->exponent is <0.			      */
331872ac97cdSTom Musta /* Otherwise the result is rhs (so no error is possible, except for   */
331972ac97cdSTom Musta /* sNaN).							      */
332072ac97cdSTom Musta /*								      */
332172ac97cdSTom Musta /* The context is used for rounding mode and status after sNaN, but   */
332272ac97cdSTom Musta /* the digits setting is ignored.  The Exact version will signal      */
332372ac97cdSTom Musta /* Inexact if the result differs numerically from rhs; the other      */
332472ac97cdSTom Musta /* never signals Inexact.					      */
332572ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberToIntegralExact(decNumber * res,const decNumber * rhs,decContext * set)332672ac97cdSTom Musta decNumber * decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
332772ac97cdSTom Musta 				     decContext *set) {
332872ac97cdSTom Musta   decNumber dn;
332972ac97cdSTom Musta   decContext workset;		   /* working context */
333072ac97cdSTom Musta   uInt status=0;		   /* accumulator */
333172ac97cdSTom Musta 
333272ac97cdSTom Musta   #if DECCHECK
333372ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
333472ac97cdSTom Musta   #endif
333572ac97cdSTom Musta 
333672ac97cdSTom Musta   /* handle infinities and NaNs */
333772ac97cdSTom Musta   if (SPECIALARG) {
333872ac97cdSTom Musta     if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); /* an Infinity */
333972ac97cdSTom Musta      else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
334072ac97cdSTom Musta     }
334172ac97cdSTom Musta    else { /* finite */
334272ac97cdSTom Musta     /* have a finite number; no error possible (res must be big enough) */
334372ac97cdSTom Musta     if (rhs->exponent>=0) return decNumberCopy(res, rhs);
334472ac97cdSTom Musta     /* that was easy, but if negative exponent there is work to do... */
334572ac97cdSTom Musta     workset=*set;		   /* clone rounding, etc. */
334672ac97cdSTom Musta     workset.digits=rhs->digits;	   /* no length rounding */
334772ac97cdSTom Musta     workset.traps=0;		   /* no traps */
334872ac97cdSTom Musta     decNumberZero(&dn);		   /* make a number with exponent 0 */
334972ac97cdSTom Musta     decNumberQuantize(res, rhs, &dn, &workset);
335072ac97cdSTom Musta     status|=workset.status;
335172ac97cdSTom Musta     }
335272ac97cdSTom Musta   if (status!=0) decStatus(res, status, set);
335372ac97cdSTom Musta   return res;
335472ac97cdSTom Musta   } /* decNumberToIntegralExact */
335572ac97cdSTom Musta 
decNumberToIntegralValue(decNumber * res,const decNumber * rhs,decContext * set)335672ac97cdSTom Musta decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
335772ac97cdSTom Musta 				     decContext *set) {
335872ac97cdSTom Musta   decContext workset=*set;	   /* working context */
335972ac97cdSTom Musta   workset.traps=0;		   /* no traps */
336072ac97cdSTom Musta   decNumberToIntegralExact(res, rhs, &workset);
336172ac97cdSTom Musta   /* this never affects set, except for sNaNs; NaN will have been set */
336272ac97cdSTom Musta   /* or propagated already, so no need to call decStatus */
336372ac97cdSTom Musta   set->status|=workset.status&DEC_Invalid_operation;
336472ac97cdSTom Musta   return res;
336572ac97cdSTom Musta   } /* decNumberToIntegralValue */
336672ac97cdSTom Musta 
336772ac97cdSTom Musta /* ------------------------------------------------------------------ */
336872ac97cdSTom Musta /* decNumberXor -- XOR two Numbers, digitwise			      */
336972ac97cdSTom Musta /*								      */
337072ac97cdSTom Musta /*   This computes C = A ^ B					      */
337172ac97cdSTom Musta /*								      */
337272ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X^X)	      */
337372ac97cdSTom Musta /*   lhs is A							      */
337472ac97cdSTom Musta /*   rhs is B							      */
337572ac97cdSTom Musta /*   set is the context (used for result length and error report)     */
337672ac97cdSTom Musta /*								      */
337772ac97cdSTom Musta /* C must have space for set->digits digits.			      */
337872ac97cdSTom Musta /*								      */
337972ac97cdSTom Musta /* Logical function restrictions apply (see above); a NaN is	      */
338072ac97cdSTom Musta /* returned with Invalid_operation if a restriction is violated.      */
338172ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberXor(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set)338272ac97cdSTom Musta decNumber * decNumberXor(decNumber *res, const decNumber *lhs,
338372ac97cdSTom Musta 			 const decNumber *rhs, decContext *set) {
338472ac97cdSTom Musta   const Unit *ua, *ub;			/* -> operands */
338572ac97cdSTom Musta   const Unit *msua, *msub;		/* -> operand msus */
338672ac97cdSTom Musta   Unit	*uc, *msuc;			/* -> result and its msu */
338772ac97cdSTom Musta   Int	msudigs;			/* digits in res msu */
338872ac97cdSTom Musta   #if DECCHECK
338972ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
339072ac97cdSTom Musta   #endif
339172ac97cdSTom Musta 
339272ac97cdSTom Musta   if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
339372ac97cdSTom Musta    || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
339472ac97cdSTom Musta     decStatus(res, DEC_Invalid_operation, set);
339572ac97cdSTom Musta     return res;
339672ac97cdSTom Musta     }
339772ac97cdSTom Musta   /* operands are valid */
339872ac97cdSTom Musta   ua=lhs->lsu;				/* bottom-up */
339972ac97cdSTom Musta   ub=rhs->lsu;				/* .. */
340072ac97cdSTom Musta   uc=res->lsu;				/* .. */
340172ac97cdSTom Musta   msua=ua+D2U(lhs->digits)-1;		/* -> msu of lhs */
340272ac97cdSTom Musta   msub=ub+D2U(rhs->digits)-1;		/* -> msu of rhs */
340372ac97cdSTom Musta   msuc=uc+D2U(set->digits)-1;		/* -> msu of result */
340472ac97cdSTom Musta   msudigs=MSUDIGITS(set->digits);	/* [faster than remainder] */
340572ac97cdSTom Musta   for (; uc<=msuc; ua++, ub++, uc++) {	/* Unit loop */
340672ac97cdSTom Musta     Unit a, b;				/* extract units */
340772ac97cdSTom Musta     if (ua>msua) a=0;
340872ac97cdSTom Musta      else a=*ua;
340972ac97cdSTom Musta     if (ub>msub) b=0;
341072ac97cdSTom Musta      else b=*ub;
341172ac97cdSTom Musta     *uc=0;				/* can now write back */
341272ac97cdSTom Musta     if (a|b) {				/* maybe 1 bits to examine */
341372ac97cdSTom Musta       Int i, j;
341472ac97cdSTom Musta       /* This loop could be unrolled and/or use BIN2BCD tables */
341572ac97cdSTom Musta       for (i=0; i<DECDPUN; i++) {
341672ac97cdSTom Musta 	if ((a^b)&1) *uc=*uc+(Unit)powers[i];	  /* effect XOR */
341772ac97cdSTom Musta 	j=a%10;
341872ac97cdSTom Musta 	a=a/10;
341972ac97cdSTom Musta 	j|=b%10;
342072ac97cdSTom Musta 	b=b/10;
342172ac97cdSTom Musta 	if (j>1) {
342272ac97cdSTom Musta 	  decStatus(res, DEC_Invalid_operation, set);
342372ac97cdSTom Musta 	  return res;
342472ac97cdSTom Musta 	  }
342572ac97cdSTom Musta 	if (uc==msuc && i==msudigs-1) break;	  /* just did final digit */
342672ac97cdSTom Musta 	} /* each digit */
342772ac97cdSTom Musta       } /* non-zero */
342872ac97cdSTom Musta     } /* each unit */
342972ac97cdSTom Musta   /* [here uc-1 is the msu of the result] */
343072ac97cdSTom Musta   res->digits=decGetDigits(res->lsu, uc-res->lsu);
343172ac97cdSTom Musta   res->exponent=0;			/* integer */
343272ac97cdSTom Musta   res->bits=0;				/* sign=0 */
343372ac97cdSTom Musta   return res;  /* [no status to set] */
343472ac97cdSTom Musta   } /* decNumberXor */
343572ac97cdSTom Musta 
343672ac97cdSTom Musta 
343772ac97cdSTom Musta /* ================================================================== */
343872ac97cdSTom Musta /* Utility routines						      */
343972ac97cdSTom Musta /* ================================================================== */
344072ac97cdSTom Musta 
344172ac97cdSTom Musta /* ------------------------------------------------------------------ */
344272ac97cdSTom Musta /* decNumberClass -- return the decClass of a decNumber		      */
344372ac97cdSTom Musta /*   dn -- the decNumber to test				      */
344472ac97cdSTom Musta /*   set -- the context to use for Emin				      */
344572ac97cdSTom Musta /*   returns the decClass enum					      */
344672ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberClass(const decNumber * dn,decContext * set)344772ac97cdSTom Musta enum decClass decNumberClass(const decNumber *dn, decContext *set) {
344872ac97cdSTom Musta   if (decNumberIsSpecial(dn)) {
344972ac97cdSTom Musta     if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN;
345072ac97cdSTom Musta     if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN;
345172ac97cdSTom Musta     /* must be an infinity */
345272ac97cdSTom Musta     if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF;
345372ac97cdSTom Musta     return DEC_CLASS_POS_INF;
345472ac97cdSTom Musta     }
345572ac97cdSTom Musta   /* is finite */
345672ac97cdSTom Musta   if (decNumberIsNormal(dn, set)) { /* most common */
345772ac97cdSTom Musta     if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL;
345872ac97cdSTom Musta     return DEC_CLASS_POS_NORMAL;
345972ac97cdSTom Musta     }
346072ac97cdSTom Musta   /* is subnormal or zero */
346172ac97cdSTom Musta   if (decNumberIsZero(dn)) {	/* most common */
346272ac97cdSTom Musta     if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO;
346372ac97cdSTom Musta     return DEC_CLASS_POS_ZERO;
346472ac97cdSTom Musta     }
346572ac97cdSTom Musta   if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL;
346672ac97cdSTom Musta   return DEC_CLASS_POS_SUBNORMAL;
346772ac97cdSTom Musta   } /* decNumberClass */
346872ac97cdSTom Musta 
346972ac97cdSTom Musta /* ------------------------------------------------------------------ */
347072ac97cdSTom Musta /* decNumberClassToString -- convert decClass to a string	      */
347172ac97cdSTom Musta /*								      */
347272ac97cdSTom Musta /*  eclass is a valid decClass					      */
347372ac97cdSTom Musta /*  returns a constant string describing the class (max 13+1 chars)   */
347472ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberClassToString(enum decClass eclass)347572ac97cdSTom Musta const char *decNumberClassToString(enum decClass eclass) {
347672ac97cdSTom Musta   if (eclass==DEC_CLASS_POS_NORMAL)    return DEC_ClassString_PN;
347772ac97cdSTom Musta   if (eclass==DEC_CLASS_NEG_NORMAL)    return DEC_ClassString_NN;
347872ac97cdSTom Musta   if (eclass==DEC_CLASS_POS_ZERO)      return DEC_ClassString_PZ;
347972ac97cdSTom Musta   if (eclass==DEC_CLASS_NEG_ZERO)      return DEC_ClassString_NZ;
348072ac97cdSTom Musta   if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS;
348172ac97cdSTom Musta   if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS;
348272ac97cdSTom Musta   if (eclass==DEC_CLASS_POS_INF)       return DEC_ClassString_PI;
348372ac97cdSTom Musta   if (eclass==DEC_CLASS_NEG_INF)       return DEC_ClassString_NI;
348472ac97cdSTom Musta   if (eclass==DEC_CLASS_QNAN)	       return DEC_ClassString_QN;
348572ac97cdSTom Musta   if (eclass==DEC_CLASS_SNAN)	       return DEC_ClassString_SN;
348672ac97cdSTom Musta   return DEC_ClassString_UN;	       /* Unknown */
348772ac97cdSTom Musta   } /* decNumberClassToString */
348872ac97cdSTom Musta 
348972ac97cdSTom Musta /* ------------------------------------------------------------------ */
349072ac97cdSTom Musta /* decNumberCopy -- copy a number				      */
349172ac97cdSTom Musta /*								      */
349272ac97cdSTom Musta /*   dest is the target decNumber				      */
349372ac97cdSTom Musta /*   src  is the source decNumber				      */
349472ac97cdSTom Musta /*   returns dest						      */
349572ac97cdSTom Musta /*								      */
349672ac97cdSTom Musta /* (dest==src is allowed and is a no-op)			      */
349772ac97cdSTom Musta /* All fields are updated as required.	This is a utility operation,  */
349872ac97cdSTom Musta /* so special values are unchanged and no error is possible.	      */
349972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberCopy(decNumber * dest,const decNumber * src)350072ac97cdSTom Musta decNumber * decNumberCopy(decNumber *dest, const decNumber *src) {
350172ac97cdSTom Musta 
350272ac97cdSTom Musta   #if DECCHECK
350372ac97cdSTom Musta   if (src==NULL) return decNumberZero(dest);
350472ac97cdSTom Musta   #endif
350572ac97cdSTom Musta 
350672ac97cdSTom Musta   if (dest==src) return dest;		     /* no copy required */
350772ac97cdSTom Musta 
350872ac97cdSTom Musta   /* Use explicit assignments here as structure assignment could copy */
350972ac97cdSTom Musta   /* more than just the lsu (for small DECDPUN).  This would not affect */
351072ac97cdSTom Musta   /* the value of the results, but could disturb test harness spill */
351172ac97cdSTom Musta   /* checking. */
351272ac97cdSTom Musta   dest->bits=src->bits;
351372ac97cdSTom Musta   dest->exponent=src->exponent;
351472ac97cdSTom Musta   dest->digits=src->digits;
351572ac97cdSTom Musta   dest->lsu[0]=src->lsu[0];
351672ac97cdSTom Musta   if (src->digits>DECDPUN) {		     /* more Units to come */
351772ac97cdSTom Musta     const Unit *smsup, *s;		     /* work */
351872ac97cdSTom Musta     Unit  *d;				     /* .. */
351972ac97cdSTom Musta     /* memcpy for the remaining Units would be safe as they cannot */
352072ac97cdSTom Musta     /* overlap.	 However, this explicit loop is faster in short cases. */
352172ac97cdSTom Musta     d=dest->lsu+1;			     /* -> first destination */
352272ac97cdSTom Musta     smsup=src->lsu+D2U(src->digits);	     /* -> source msu+1 */
352372ac97cdSTom Musta     for (s=src->lsu+1; s<smsup; s++, d++) *d=*s;
352472ac97cdSTom Musta     }
352572ac97cdSTom Musta   return dest;
352672ac97cdSTom Musta   } /* decNumberCopy */
352772ac97cdSTom Musta 
352872ac97cdSTom Musta /* ------------------------------------------------------------------ */
352972ac97cdSTom Musta /* decNumberCopyAbs -- quiet absolute value operator		      */
353072ac97cdSTom Musta /*								      */
353172ac97cdSTom Musta /*   This sets C = abs(A)					      */
353272ac97cdSTom Musta /*								      */
353372ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
353472ac97cdSTom Musta /*   rhs is A							      */
353572ac97cdSTom Musta /*								      */
353672ac97cdSTom Musta /* C must have space for set->digits digits.			      */
353772ac97cdSTom Musta /* No exception or error can occur; this is a quiet bitwise operation.*/
353872ac97cdSTom Musta /* See also decNumberAbs for a checking version of this.	      */
353972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberCopyAbs(decNumber * res,const decNumber * rhs)354072ac97cdSTom Musta decNumber * decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
354172ac97cdSTom Musta   #if DECCHECK
354272ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
354372ac97cdSTom Musta   #endif
354472ac97cdSTom Musta   decNumberCopy(res, rhs);
354572ac97cdSTom Musta   res->bits&=~DECNEG;			/* turn off sign */
354672ac97cdSTom Musta   return res;
354772ac97cdSTom Musta   } /* decNumberCopyAbs */
354872ac97cdSTom Musta 
354972ac97cdSTom Musta /* ------------------------------------------------------------------ */
355072ac97cdSTom Musta /* decNumberCopyNegate -- quiet negate value operator		      */
355172ac97cdSTom Musta /*								      */
355272ac97cdSTom Musta /*   This sets C = negate(A)					      */
355372ac97cdSTom Musta /*								      */
355472ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
355572ac97cdSTom Musta /*   rhs is A							      */
355672ac97cdSTom Musta /*								      */
355772ac97cdSTom Musta /* C must have space for set->digits digits.			      */
355872ac97cdSTom Musta /* No exception or error can occur; this is a quiet bitwise operation.*/
355972ac97cdSTom Musta /* See also decNumberMinus for a checking version of this.	      */
356072ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberCopyNegate(decNumber * res,const decNumber * rhs)356172ac97cdSTom Musta decNumber * decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
356272ac97cdSTom Musta   #if DECCHECK
356372ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
356472ac97cdSTom Musta   #endif
356572ac97cdSTom Musta   decNumberCopy(res, rhs);
356672ac97cdSTom Musta   res->bits^=DECNEG;			/* invert the sign */
356772ac97cdSTom Musta   return res;
356872ac97cdSTom Musta   } /* decNumberCopyNegate */
356972ac97cdSTom Musta 
357072ac97cdSTom Musta /* ------------------------------------------------------------------ */
357172ac97cdSTom Musta /* decNumberCopySign -- quiet copy and set sign operator	      */
357272ac97cdSTom Musta /*								      */
357372ac97cdSTom Musta /*   This sets C = A with the sign of B				      */
357472ac97cdSTom Musta /*								      */
357572ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
357672ac97cdSTom Musta /*   lhs is A							      */
357772ac97cdSTom Musta /*   rhs is B							      */
357872ac97cdSTom Musta /*								      */
357972ac97cdSTom Musta /* C must have space for set->digits digits.			      */
358072ac97cdSTom Musta /* No exception or error can occur; this is a quiet bitwise operation.*/
358172ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberCopySign(decNumber * res,const decNumber * lhs,const decNumber * rhs)358272ac97cdSTom Musta decNumber * decNumberCopySign(decNumber *res, const decNumber *lhs,
358372ac97cdSTom Musta 			      const decNumber *rhs) {
358472ac97cdSTom Musta   uByte sign;				/* rhs sign */
358572ac97cdSTom Musta   #if DECCHECK
358672ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
358772ac97cdSTom Musta   #endif
358872ac97cdSTom Musta   sign=rhs->bits & DECNEG;		/* save sign bit */
358972ac97cdSTom Musta   decNumberCopy(res, lhs);
359072ac97cdSTom Musta   res->bits&=~DECNEG;			/* clear the sign */
359172ac97cdSTom Musta   res->bits|=sign;			/* set from rhs */
359272ac97cdSTom Musta   return res;
359372ac97cdSTom Musta   } /* decNumberCopySign */
359472ac97cdSTom Musta 
359572ac97cdSTom Musta /* ------------------------------------------------------------------ */
359672ac97cdSTom Musta /* decNumberGetBCD -- get the coefficient in BCD8		      */
359772ac97cdSTom Musta /*   dn is the source decNumber					      */
359872ac97cdSTom Musta /*   bcd is the uInt array that will receive dn->digits BCD bytes,    */
359972ac97cdSTom Musta /*     most-significant at offset 0				      */
360072ac97cdSTom Musta /*   returns bcd						      */
360172ac97cdSTom Musta /*								      */
360272ac97cdSTom Musta /* bcd must have at least dn->digits bytes.  No error is possible; if */
360372ac97cdSTom Musta /* dn is a NaN or Infinite, digits must be 1 and the coefficient 0.   */
360472ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberGetBCD(const decNumber * dn,uint8_t * bcd)360572ac97cdSTom Musta uByte * decNumberGetBCD(const decNumber *dn, uint8_t *bcd) {
360672ac97cdSTom Musta   uByte *ub=bcd+dn->digits-1;	   /* -> lsd */
360772ac97cdSTom Musta   const Unit *up=dn->lsu;	   /* Unit pointer, -> lsu */
360872ac97cdSTom Musta 
360972ac97cdSTom Musta   #if DECDPUN==1		   /* trivial simple copy */
361072ac97cdSTom Musta     for (; ub>=bcd; ub--, up++) *ub=*up;
361172ac97cdSTom Musta   #else				   /* chopping needed */
361272ac97cdSTom Musta     uInt u=*up;			   /* work */
361372ac97cdSTom Musta     uInt cut=DECDPUN;		   /* downcounter through unit */
361472ac97cdSTom Musta     for (; ub>=bcd; ub--) {
361572ac97cdSTom Musta       *ub=(uByte)(u%10);	   /* [*6554 trick inhibits, here] */
361672ac97cdSTom Musta       u=u/10;
361772ac97cdSTom Musta       cut--;
361872ac97cdSTom Musta       if (cut>0) continue;	   /* more in this unit */
361972ac97cdSTom Musta       up++;
362072ac97cdSTom Musta       u=*up;
362172ac97cdSTom Musta       cut=DECDPUN;
362272ac97cdSTom Musta       }
362372ac97cdSTom Musta   #endif
362472ac97cdSTom Musta   return bcd;
362572ac97cdSTom Musta   } /* decNumberGetBCD */
362672ac97cdSTom Musta 
362772ac97cdSTom Musta /* ------------------------------------------------------------------ */
362872ac97cdSTom Musta /* decNumberSetBCD -- set (replace) the coefficient from BCD8	      */
362972ac97cdSTom Musta /*   dn is the target decNumber					      */
363072ac97cdSTom Musta /*   bcd is the uInt array that will source n BCD bytes, most-	      */
363172ac97cdSTom Musta /*     significant at offset 0					      */
363272ac97cdSTom Musta /*   n is the number of digits in the source BCD array (bcd)	      */
363372ac97cdSTom Musta /*   returns dn							      */
363472ac97cdSTom Musta /*								      */
363572ac97cdSTom Musta /* dn must have space for at least n digits.  No error is possible;   */
363672ac97cdSTom Musta /* if dn is a NaN, or Infinite, or is to become a zero, n must be 1   */
363772ac97cdSTom Musta /* and bcd[0] zero.						      */
363872ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberSetBCD(decNumber * dn,const uByte * bcd,uInt n)363972ac97cdSTom Musta decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
36400a322e7eSTom Musta   Unit *up = dn->lsu + D2U(n) - 1;      /* -> msu [target pointer] */
364172ac97cdSTom Musta   const uByte *ub=bcd;			/* -> source msd */
364272ac97cdSTom Musta 
364372ac97cdSTom Musta   #if DECDPUN==1			/* trivial simple copy */
364472ac97cdSTom Musta     for (; ub<bcd+n; ub++, up--) *up=*ub;
364572ac97cdSTom Musta   #else					/* some assembly needed */
364672ac97cdSTom Musta     /* calculate how many digits in msu, and hence first cut */
364772ac97cdSTom Musta     Int cut=MSUDIGITS(n);		/* [faster than remainder] */
364872ac97cdSTom Musta     for (;up>=dn->lsu; up--) {		/* each Unit from msu */
364972ac97cdSTom Musta       *up=0;				/* will take <=DECDPUN digits */
365072ac97cdSTom Musta       for (; cut>0; ub++, cut--) *up=X10(*up)+*ub;
365172ac97cdSTom Musta       cut=DECDPUN;			/* next Unit has all digits */
365272ac97cdSTom Musta       }
365372ac97cdSTom Musta   #endif
365472ac97cdSTom Musta   dn->digits=n;				/* set digit count */
365572ac97cdSTom Musta   return dn;
365672ac97cdSTom Musta   } /* decNumberSetBCD */
365772ac97cdSTom Musta 
365872ac97cdSTom Musta /* ------------------------------------------------------------------ */
365972ac97cdSTom Musta /* decNumberIsNormal -- test normality of a decNumber		      */
366072ac97cdSTom Musta /*   dn is the decNumber to test				      */
366172ac97cdSTom Musta /*   set is the context to use for Emin				      */
366272ac97cdSTom Musta /*   returns 1 if |dn| is finite and >=Nmin, 0 otherwise	      */
366372ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberIsNormal(const decNumber * dn,decContext * set)366472ac97cdSTom Musta Int decNumberIsNormal(const decNumber *dn, decContext *set) {
366572ac97cdSTom Musta   Int ae;				/* adjusted exponent */
366672ac97cdSTom Musta   #if DECCHECK
366772ac97cdSTom Musta   if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
366872ac97cdSTom Musta   #endif
366972ac97cdSTom Musta 
367072ac97cdSTom Musta   if (decNumberIsSpecial(dn)) return 0; /* not finite */
367172ac97cdSTom Musta   if (decNumberIsZero(dn)) return 0;	/* not non-zero */
367272ac97cdSTom Musta 
367372ac97cdSTom Musta   ae=dn->exponent+dn->digits-1;		/* adjusted exponent */
367472ac97cdSTom Musta   if (ae<set->emin) return 0;		/* is subnormal */
367572ac97cdSTom Musta   return 1;
367672ac97cdSTom Musta   } /* decNumberIsNormal */
367772ac97cdSTom Musta 
367872ac97cdSTom Musta /* ------------------------------------------------------------------ */
367972ac97cdSTom Musta /* decNumberIsSubnormal -- test subnormality of a decNumber	      */
368072ac97cdSTom Musta /*   dn is the decNumber to test				      */
368172ac97cdSTom Musta /*   set is the context to use for Emin				      */
368272ac97cdSTom Musta /*   returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise    */
368372ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberIsSubnormal(const decNumber * dn,decContext * set)368472ac97cdSTom Musta Int decNumberIsSubnormal(const decNumber *dn, decContext *set) {
368572ac97cdSTom Musta   Int ae;				/* adjusted exponent */
368672ac97cdSTom Musta   #if DECCHECK
368772ac97cdSTom Musta   if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
368872ac97cdSTom Musta   #endif
368972ac97cdSTom Musta 
369072ac97cdSTom Musta   if (decNumberIsSpecial(dn)) return 0; /* not finite */
369172ac97cdSTom Musta   if (decNumberIsZero(dn)) return 0;	/* not non-zero */
369272ac97cdSTom Musta 
369372ac97cdSTom Musta   ae=dn->exponent+dn->digits-1;		/* adjusted exponent */
369472ac97cdSTom Musta   if (ae<set->emin) return 1;		/* is subnormal */
369572ac97cdSTom Musta   return 0;
369672ac97cdSTom Musta   } /* decNumberIsSubnormal */
369772ac97cdSTom Musta 
369872ac97cdSTom Musta /* ------------------------------------------------------------------ */
369972ac97cdSTom Musta /* decNumberTrim -- remove insignificant zeros			      */
370072ac97cdSTom Musta /*								      */
370172ac97cdSTom Musta /*   dn is the number to trim					      */
370272ac97cdSTom Musta /*   returns dn							      */
370372ac97cdSTom Musta /*								      */
370472ac97cdSTom Musta /* All fields are updated as required.	This is a utility operation,  */
370572ac97cdSTom Musta /* so special values are unchanged and no error is possible.	      */
370672ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberTrim(decNumber * dn)370772ac97cdSTom Musta decNumber * decNumberTrim(decNumber *dn) {
370872ac97cdSTom Musta   Int  dropped;			   /* work */
370972ac97cdSTom Musta   decContext set;		   /* .. */
371072ac97cdSTom Musta   #if DECCHECK
371172ac97cdSTom Musta   if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn;
371272ac97cdSTom Musta   #endif
371372ac97cdSTom Musta   decContextDefault(&set, DEC_INIT_BASE);    /* clamp=0 */
371472ac97cdSTom Musta   return decTrim(dn, &set, 0, &dropped);
371572ac97cdSTom Musta   } /* decNumberTrim */
371672ac97cdSTom Musta 
371772ac97cdSTom Musta /* ------------------------------------------------------------------ */
371872ac97cdSTom Musta /* decNumberVersion -- return the name and version of this module     */
371972ac97cdSTom Musta /*								      */
372072ac97cdSTom Musta /* No error is possible.					      */
372172ac97cdSTom Musta /* ------------------------------------------------------------------ */
decNumberVersion(void)372272ac97cdSTom Musta const char * decNumberVersion(void) {
372372ac97cdSTom Musta   return DECVERSION;
372472ac97cdSTom Musta   } /* decNumberVersion */
372572ac97cdSTom Musta 
372672ac97cdSTom Musta /* ------------------------------------------------------------------ */
372772ac97cdSTom Musta /* decNumberZero -- set a number to 0				      */
372872ac97cdSTom Musta /*								      */
372972ac97cdSTom Musta /*   dn is the number to set, with space for one digit		      */
373072ac97cdSTom Musta /*   returns dn							      */
373172ac97cdSTom Musta /*								      */
373272ac97cdSTom Musta /* No error is possible.					      */
373372ac97cdSTom Musta /* ------------------------------------------------------------------ */
373472ac97cdSTom Musta /* Memset is not used as it is much slower in some environments. */
decNumberZero(decNumber * dn)373572ac97cdSTom Musta decNumber * decNumberZero(decNumber *dn) {
373672ac97cdSTom Musta 
373772ac97cdSTom Musta   #if DECCHECK
373872ac97cdSTom Musta   if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
373972ac97cdSTom Musta   #endif
374072ac97cdSTom Musta 
374172ac97cdSTom Musta   dn->bits=0;
374272ac97cdSTom Musta   dn->exponent=0;
374372ac97cdSTom Musta   dn->digits=1;
374472ac97cdSTom Musta   dn->lsu[0]=0;
374572ac97cdSTom Musta   return dn;
374672ac97cdSTom Musta   } /* decNumberZero */
374772ac97cdSTom Musta 
374872ac97cdSTom Musta /* ================================================================== */
374972ac97cdSTom Musta /* Local routines						      */
375072ac97cdSTom Musta /* ================================================================== */
375172ac97cdSTom Musta 
375272ac97cdSTom Musta /* ------------------------------------------------------------------ */
375372ac97cdSTom Musta /* decToString -- lay out a number into a string		      */
375472ac97cdSTom Musta /*								      */
375572ac97cdSTom Musta /*   dn	    is the number to lay out				      */
375672ac97cdSTom Musta /*   string is where to lay out the number			      */
375772ac97cdSTom Musta /*   eng    is 1 if Engineering, 0 if Scientific		      */
375872ac97cdSTom Musta /*								      */
375972ac97cdSTom Musta /* string must be at least dn->digits+14 characters long	      */
376072ac97cdSTom Musta /* No error is possible.					      */
376172ac97cdSTom Musta /*								      */
376272ac97cdSTom Musta /* Note that this routine can generate a -0 or 0.000.  These are      */
376372ac97cdSTom Musta /* never generated in subset to-number or arithmetic, but can occur   */
376472ac97cdSTom Musta /* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234).	      */
376572ac97cdSTom Musta /* ------------------------------------------------------------------ */
376672ac97cdSTom Musta /* If DECCHECK is enabled the string "?" is returned if a number is */
376772ac97cdSTom Musta /* invalid. */
decToString(const decNumber * dn,char * string,Flag eng)376872ac97cdSTom Musta static void decToString(const decNumber *dn, char *string, Flag eng) {
376972ac97cdSTom Musta   Int exp=dn->exponent;	      /* local copy */
377072ac97cdSTom Musta   Int e;		      /* E-part value */
377172ac97cdSTom Musta   Int pre;		      /* digits before the '.' */
377272ac97cdSTom Musta   Int cut;		      /* for counting digits in a Unit */
377372ac97cdSTom Musta   char *c=string;	      /* work [output pointer] */
377472ac97cdSTom Musta   const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */
377572ac97cdSTom Musta   uInt u, pow;		      /* work */
377672ac97cdSTom Musta 
377772ac97cdSTom Musta   #if DECCHECK
377872ac97cdSTom Musta   if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) {
377972ac97cdSTom Musta     strcpy(string, "?");
378072ac97cdSTom Musta     return;}
378172ac97cdSTom Musta   #endif
378272ac97cdSTom Musta 
378372ac97cdSTom Musta   if (decNumberIsNegative(dn)) {   /* Negatives get a minus */
378472ac97cdSTom Musta     *c='-';
378572ac97cdSTom Musta     c++;
378672ac97cdSTom Musta     }
378772ac97cdSTom Musta   if (dn->bits&DECSPECIAL) {	   /* Is a special value */
378872ac97cdSTom Musta     if (decNumberIsInfinite(dn)) {
378972ac97cdSTom Musta       strcpy(c,	  "Inf");
379072ac97cdSTom Musta       strcpy(c+3, "inity");
379172ac97cdSTom Musta       return;}
379272ac97cdSTom Musta     /* a NaN */
379372ac97cdSTom Musta     if (dn->bits&DECSNAN) {	   /* signalling NaN */
379472ac97cdSTom Musta       *c='s';
379572ac97cdSTom Musta       c++;
379672ac97cdSTom Musta       }
379772ac97cdSTom Musta     strcpy(c, "NaN");
379872ac97cdSTom Musta     c+=3;			   /* step past */
379972ac97cdSTom Musta     /* if not a clean non-zero coefficient, that's all there is in a */
380072ac97cdSTom Musta     /* NaN string */
380172ac97cdSTom Musta     if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return;
380272ac97cdSTom Musta     /* [drop through to add integer] */
380372ac97cdSTom Musta     }
380472ac97cdSTom Musta 
380572ac97cdSTom Musta   /* calculate how many digits in msu, and hence first cut */
380672ac97cdSTom Musta   cut=MSUDIGITS(dn->digits);	   /* [faster than remainder] */
380772ac97cdSTom Musta   cut--;			   /* power of ten for digit */
380872ac97cdSTom Musta 
380972ac97cdSTom Musta   if (exp==0) {			   /* simple integer [common fastpath] */
381072ac97cdSTom Musta     for (;up>=dn->lsu; up--) {	   /* each Unit from msu */
381172ac97cdSTom Musta       u=*up;			   /* contains DECDPUN digits to lay out */
381272ac97cdSTom Musta       for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow);
381372ac97cdSTom Musta       cut=DECDPUN-1;		   /* next Unit has all digits */
381472ac97cdSTom Musta       }
381572ac97cdSTom Musta     *c='\0';			   /* terminate the string */
381672ac97cdSTom Musta     return;}
381772ac97cdSTom Musta 
381872ac97cdSTom Musta   /* non-0 exponent -- assume plain form */
381972ac97cdSTom Musta   pre=dn->digits+exp;		   /* digits before '.' */
382072ac97cdSTom Musta   e=0;				   /* no E */
382172ac97cdSTom Musta   if ((exp>0) || (pre<-5)) {	   /* need exponential form */
382272ac97cdSTom Musta     e=exp+dn->digits-1;		   /* calculate E value */
382372ac97cdSTom Musta     pre=1;			   /* assume one digit before '.' */
382472ac97cdSTom Musta     if (eng && (e!=0)) {	   /* engineering: may need to adjust */
382572ac97cdSTom Musta       Int adj;			   /* adjustment */
382672ac97cdSTom Musta       /* The C remainder operator is undefined for negative numbers, so */
382772ac97cdSTom Musta       /* a positive remainder calculation must be used here */
382872ac97cdSTom Musta       if (e<0) {
382972ac97cdSTom Musta 	adj=(-e)%3;
383072ac97cdSTom Musta 	if (adj!=0) adj=3-adj;
383172ac97cdSTom Musta 	}
383272ac97cdSTom Musta        else { /* e>0 */
383372ac97cdSTom Musta 	adj=e%3;
383472ac97cdSTom Musta 	}
383572ac97cdSTom Musta       e=e-adj;
383672ac97cdSTom Musta       /* if dealing with zero still produce an exponent which is a */
383772ac97cdSTom Musta       /* multiple of three, as expected, but there will only be the */
383872ac97cdSTom Musta       /* one zero before the E, still.	Otherwise note the padding. */
383972ac97cdSTom Musta       if (!ISZERO(dn)) pre+=adj;
384072ac97cdSTom Musta        else {  /* is zero */
384172ac97cdSTom Musta 	if (adj!=0) {		   /* 0.00Esnn needed */
384272ac97cdSTom Musta 	  e=e+3;
384372ac97cdSTom Musta 	  pre=-(2-adj);
384472ac97cdSTom Musta 	  }
384572ac97cdSTom Musta 	} /* zero */
384672ac97cdSTom Musta       } /* eng */
384772ac97cdSTom Musta     } /* need exponent */
384872ac97cdSTom Musta 
384972ac97cdSTom Musta   /* lay out the digits of the coefficient, adding 0s and . as needed */
385072ac97cdSTom Musta   u=*up;
385172ac97cdSTom Musta   if (pre>0) {			   /* xxx.xxx or xx00 (engineering) form */
385272ac97cdSTom Musta     Int n=pre;
385372ac97cdSTom Musta     for (; pre>0; pre--, c++, cut--) {
385472ac97cdSTom Musta       if (cut<0) {		   /* need new Unit */
385572ac97cdSTom Musta 	if (up==dn->lsu) break;	   /* out of input digits (pre>digits) */
385672ac97cdSTom Musta 	up--;
385772ac97cdSTom Musta 	cut=DECDPUN-1;
385872ac97cdSTom Musta 	u=*up;
385972ac97cdSTom Musta 	}
386072ac97cdSTom Musta       TODIGIT(u, cut, c, pow);
386172ac97cdSTom Musta       }
386272ac97cdSTom Musta     if (n<dn->digits) {		   /* more to come, after '.' */
386372ac97cdSTom Musta       *c='.'; c++;
386472ac97cdSTom Musta       for (;; c++, cut--) {
386572ac97cdSTom Musta 	if (cut<0) {		   /* need new Unit */
386672ac97cdSTom Musta 	  if (up==dn->lsu) break;  /* out of input digits */
386772ac97cdSTom Musta 	  up--;
386872ac97cdSTom Musta 	  cut=DECDPUN-1;
386972ac97cdSTom Musta 	  u=*up;
387072ac97cdSTom Musta 	  }
387172ac97cdSTom Musta 	TODIGIT(u, cut, c, pow);
387272ac97cdSTom Musta 	}
387372ac97cdSTom Musta       }
387472ac97cdSTom Musta      else for (; pre>0; pre--, c++) *c='0'; /* 0 padding (for engineering) needed */
387572ac97cdSTom Musta     }
387672ac97cdSTom Musta    else {			   /* 0.xxx or 0.000xxx form */
387772ac97cdSTom Musta     *c='0'; c++;
387872ac97cdSTom Musta     *c='.'; c++;
387972ac97cdSTom Musta     for (; pre<0; pre++, c++) *c='0';	/* add any 0's after '.' */
388072ac97cdSTom Musta     for (; ; c++, cut--) {
388172ac97cdSTom Musta       if (cut<0) {		   /* need new Unit */
388272ac97cdSTom Musta 	if (up==dn->lsu) break;	   /* out of input digits */
388372ac97cdSTom Musta 	up--;
388472ac97cdSTom Musta 	cut=DECDPUN-1;
388572ac97cdSTom Musta 	u=*up;
388672ac97cdSTom Musta 	}
388772ac97cdSTom Musta       TODIGIT(u, cut, c, pow);
388872ac97cdSTom Musta       }
388972ac97cdSTom Musta     }
389072ac97cdSTom Musta 
389172ac97cdSTom Musta   /* Finally add the E-part, if needed.	 It will never be 0, has a
389272ac97cdSTom Musta      base maximum and minimum of +999999999 through -999999999, but
389372ac97cdSTom Musta      could range down to -1999999998 for anormal numbers */
389472ac97cdSTom Musta   if (e!=0) {
389572ac97cdSTom Musta     Flag had=0;		      /* 1=had non-zero */
389672ac97cdSTom Musta     *c='E'; c++;
389772ac97cdSTom Musta     *c='+'; c++;	      /* assume positive */
389872ac97cdSTom Musta     u=e;		      /* .. */
389972ac97cdSTom Musta     if (e<0) {
390072ac97cdSTom Musta       *(c-1)='-';	      /* oops, need - */
390172ac97cdSTom Musta       u=-e;		      /* uInt, please */
390272ac97cdSTom Musta       }
390372ac97cdSTom Musta     /* lay out the exponent [_itoa or equivalent is not ANSI C] */
390472ac97cdSTom Musta     for (cut=9; cut>=0; cut--) {
390572ac97cdSTom Musta       TODIGIT(u, cut, c, pow);
390672ac97cdSTom Musta       if (*c=='0' && !had) continue;	/* skip leading zeros */
390772ac97cdSTom Musta       had=1;				/* had non-0 */
390872ac97cdSTom Musta       c++;				/* step for next */
390972ac97cdSTom Musta       } /* cut */
391072ac97cdSTom Musta     }
391172ac97cdSTom Musta   *c='\0';	    /* terminate the string (all paths) */
391272ac97cdSTom Musta   return;
391372ac97cdSTom Musta   } /* decToString */
391472ac97cdSTom Musta 
391572ac97cdSTom Musta /* ------------------------------------------------------------------ */
391672ac97cdSTom Musta /* decAddOp -- add/subtract operation				      */
391772ac97cdSTom Musta /*								      */
391872ac97cdSTom Musta /*   This computes C = A + B					      */
391972ac97cdSTom Musta /*								      */
392072ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X+X)	      */
392172ac97cdSTom Musta /*   lhs is A							      */
392272ac97cdSTom Musta /*   rhs is B							      */
392372ac97cdSTom Musta /*   set is the context						      */
392472ac97cdSTom Musta /*   negate is DECNEG if rhs should be negated, or 0 otherwise	      */
392572ac97cdSTom Musta /*   status accumulates status for the caller			      */
392672ac97cdSTom Musta /*								      */
392772ac97cdSTom Musta /* C must have space for set->digits digits.			      */
392872ac97cdSTom Musta /* Inexact in status must be 0 for correct Exact zero sign in result  */
392972ac97cdSTom Musta /* ------------------------------------------------------------------ */
393072ac97cdSTom Musta /* If possible, the coefficient is calculated directly into C.	      */
393172ac97cdSTom Musta /* However, if:							      */
393272ac97cdSTom Musta /*   -- a digits+1 calculation is needed because the numbers are      */
393372ac97cdSTom Musta /*	unaligned and span more than set->digits digits		      */
393472ac97cdSTom Musta /*   -- a carry to digits+1 digits looks possible		      */
393572ac97cdSTom Musta /*   -- C is the same as A or B, and the result would destructively   */
393672ac97cdSTom Musta /*	overlap the A or B coefficient				      */
393772ac97cdSTom Musta /* then the result must be calculated into a temporary buffer.	In    */
393872ac97cdSTom Musta /* this case a local (stack) buffer is used if possible, and only if  */
393972ac97cdSTom Musta /* too long for that does malloc become the final resort.	      */
394072ac97cdSTom Musta /*								      */
394172ac97cdSTom Musta /* Misalignment is handled as follows:				      */
394272ac97cdSTom Musta /*   Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp.    */
394372ac97cdSTom Musta /*   BPad: Apply the padding by a combination of shifting (whole      */
394472ac97cdSTom Musta /*	   units) and multiplication (part units).		      */
394572ac97cdSTom Musta /*								      */
394672ac97cdSTom Musta /* Addition, especially x=x+1, is speed-critical.		      */
394772ac97cdSTom Musta /* The static buffer is larger than might be expected to allow for    */
394867cc32ebSVeres Lajos /* calls from higher-level functions (notably exp).		      */
394972ac97cdSTom Musta /* ------------------------------------------------------------------ */
decAddOp(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set,uByte negate,uInt * status)395072ac97cdSTom Musta static decNumber * decAddOp(decNumber *res, const decNumber *lhs,
395172ac97cdSTom Musta 			    const decNumber *rhs, decContext *set,
395272ac97cdSTom Musta 			    uByte negate, uInt *status) {
395372ac97cdSTom Musta   #if DECSUBSET
395472ac97cdSTom Musta   decNumber *alloclhs=NULL;	   /* non-NULL if rounded lhs allocated */
395572ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* .., rhs */
395672ac97cdSTom Musta   #endif
395772ac97cdSTom Musta   Int	rhsshift;		   /* working shift (in Units) */
395872ac97cdSTom Musta   Int	maxdigits;		   /* longest logical length */
395972ac97cdSTom Musta   Int	mult;			   /* multiplier */
396072ac97cdSTom Musta   Int	residue;		   /* rounding accumulator */
396172ac97cdSTom Musta   uByte bits;			   /* result bits */
396272ac97cdSTom Musta   Flag	diffsign;		   /* non-0 if arguments have different sign */
396372ac97cdSTom Musta   Unit	*acc;			   /* accumulator for result */
396472ac97cdSTom Musta   Unit	accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */
396572ac97cdSTom Musta 				   /* allocations when called from */
396672ac97cdSTom Musta 				   /* other operations, notable exp] */
396772ac97cdSTom Musta   Unit	*allocacc=NULL;		   /* -> allocated acc buffer, iff allocated */
396872ac97cdSTom Musta   Int	reqdigits=set->digits;	   /* local copy; requested DIGITS */
396972ac97cdSTom Musta   Int	padding;		   /* work */
397072ac97cdSTom Musta 
397172ac97cdSTom Musta   #if DECCHECK
397272ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
397372ac97cdSTom Musta   #endif
397472ac97cdSTom Musta 
397572ac97cdSTom Musta   do {				   /* protect allocated storage */
397672ac97cdSTom Musta     #if DECSUBSET
397772ac97cdSTom Musta     if (!set->extended) {
397872ac97cdSTom Musta       /* reduce operands and set lostDigits status, as needed */
397972ac97cdSTom Musta       if (lhs->digits>reqdigits) {
398072ac97cdSTom Musta 	alloclhs=decRoundOperand(lhs, set, status);
398172ac97cdSTom Musta 	if (alloclhs==NULL) break;
398272ac97cdSTom Musta 	lhs=alloclhs;
398372ac97cdSTom Musta 	}
398472ac97cdSTom Musta       if (rhs->digits>reqdigits) {
398572ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, status);
398672ac97cdSTom Musta 	if (allocrhs==NULL) break;
398772ac97cdSTom Musta 	rhs=allocrhs;
398872ac97cdSTom Musta 	}
398972ac97cdSTom Musta       }
399072ac97cdSTom Musta     #endif
399172ac97cdSTom Musta     /* [following code does not require input rounding] */
399272ac97cdSTom Musta 
399372ac97cdSTom Musta     /* note whether signs differ [used all paths] */
399472ac97cdSTom Musta     diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG);
399572ac97cdSTom Musta 
399672ac97cdSTom Musta     /* handle infinities and NaNs */
399772ac97cdSTom Musta     if (SPECIALARGS) {			/* a special bit set */
399872ac97cdSTom Musta       if (SPECIALARGS & (DECSNAN | DECNAN))  /* a NaN */
399972ac97cdSTom Musta 	decNaNs(res, lhs, rhs, set, status);
400072ac97cdSTom Musta        else { /* one or two infinities */
400172ac97cdSTom Musta 	if (decNumberIsInfinite(lhs)) { /* LHS is infinity */
400272ac97cdSTom Musta 	  /* two infinities with different signs is invalid */
400372ac97cdSTom Musta 	  if (decNumberIsInfinite(rhs) && diffsign) {
400472ac97cdSTom Musta 	    *status|=DEC_Invalid_operation;
400572ac97cdSTom Musta 	    break;
400672ac97cdSTom Musta 	    }
400772ac97cdSTom Musta 	  bits=lhs->bits & DECNEG;	/* get sign from LHS */
400872ac97cdSTom Musta 	  }
400972ac97cdSTom Musta 	 else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */
401072ac97cdSTom Musta 	bits|=DECINF;
401172ac97cdSTom Musta 	decNumberZero(res);
401272ac97cdSTom Musta 	res->bits=bits;			/* set +/- infinity */
401372ac97cdSTom Musta 	} /* an infinity */
401472ac97cdSTom Musta       break;
401572ac97cdSTom Musta       }
401672ac97cdSTom Musta 
401772ac97cdSTom Musta     /* Quick exit for add 0s; return the non-0, modified as need be */
401872ac97cdSTom Musta     if (ISZERO(lhs)) {
401972ac97cdSTom Musta       Int adjust;			/* work */
402072ac97cdSTom Musta       Int lexp=lhs->exponent;		/* save in case LHS==RES */
402172ac97cdSTom Musta       bits=lhs->bits;			/* .. */
402272ac97cdSTom Musta       residue=0;			/* clear accumulator */
402372ac97cdSTom Musta       decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */
402472ac97cdSTom Musta       res->bits^=negate;		/* flip if rhs was negated */
402572ac97cdSTom Musta       #if DECSUBSET
402672ac97cdSTom Musta       if (set->extended) {		/* exponents on zeros count */
402772ac97cdSTom Musta       #endif
402872ac97cdSTom Musta 	/* exponent will be the lower of the two */
402972ac97cdSTom Musta 	adjust=lexp-res->exponent;	/* adjustment needed [if -ve] */
403072ac97cdSTom Musta 	if (ISZERO(res)) {		/* both 0: special IEEE 854 rules */
403172ac97cdSTom Musta 	  if (adjust<0) res->exponent=lexp;  /* set exponent */
403272ac97cdSTom Musta 	  /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */
403372ac97cdSTom Musta 	  if (diffsign) {
403472ac97cdSTom Musta 	    if (set->round!=DEC_ROUND_FLOOR) res->bits=0;
403572ac97cdSTom Musta 	     else res->bits=DECNEG;	/* preserve 0 sign */
403672ac97cdSTom Musta 	    }
403772ac97cdSTom Musta 	  }
403872ac97cdSTom Musta 	 else { /* non-0 res */
403972ac97cdSTom Musta 	  if (adjust<0) {     /* 0-padding needed */
404072ac97cdSTom Musta 	    if ((res->digits-adjust)>set->digits) {
404172ac97cdSTom Musta 	      adjust=res->digits-set->digits;	  /* to fit exactly */
404272ac97cdSTom Musta 	      *status|=DEC_Rounded;		  /* [but exact] */
404372ac97cdSTom Musta 	      }
404472ac97cdSTom Musta 	    res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
404572ac97cdSTom Musta 	    res->exponent+=adjust;		  /* set the exponent. */
404672ac97cdSTom Musta 	    }
404772ac97cdSTom Musta 	  } /* non-0 res */
404872ac97cdSTom Musta       #if DECSUBSET
404972ac97cdSTom Musta 	} /* extended */
405072ac97cdSTom Musta       #endif
405172ac97cdSTom Musta       decFinish(res, set, &residue, status);	  /* clean and finalize */
405272ac97cdSTom Musta       break;}
405372ac97cdSTom Musta 
405472ac97cdSTom Musta     if (ISZERO(rhs)) {			/* [lhs is non-zero] */
405572ac97cdSTom Musta       Int adjust;			/* work */
405672ac97cdSTom Musta       Int rexp=rhs->exponent;		/* save in case RHS==RES */
405772ac97cdSTom Musta       bits=rhs->bits;			/* be clean */
405872ac97cdSTom Musta       residue=0;			/* clear accumulator */
405972ac97cdSTom Musta       decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */
406072ac97cdSTom Musta       #if DECSUBSET
406172ac97cdSTom Musta       if (set->extended) {		/* exponents on zeros count */
406272ac97cdSTom Musta       #endif
406372ac97cdSTom Musta 	/* exponent will be the lower of the two */
406472ac97cdSTom Musta 	/* [0-0 case handled above] */
406572ac97cdSTom Musta 	adjust=rexp-res->exponent;	/* adjustment needed [if -ve] */
406672ac97cdSTom Musta 	if (adjust<0) {	    /* 0-padding needed */
406772ac97cdSTom Musta 	  if ((res->digits-adjust)>set->digits) {
406872ac97cdSTom Musta 	    adjust=res->digits-set->digits;	/* to fit exactly */
406972ac97cdSTom Musta 	    *status|=DEC_Rounded;		/* [but exact] */
407072ac97cdSTom Musta 	    }
407172ac97cdSTom Musta 	  res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
407272ac97cdSTom Musta 	  res->exponent+=adjust;		/* set the exponent. */
407372ac97cdSTom Musta 	  }
407472ac97cdSTom Musta       #if DECSUBSET
407572ac97cdSTom Musta 	} /* extended */
407672ac97cdSTom Musta       #endif
407772ac97cdSTom Musta       decFinish(res, set, &residue, status);	  /* clean and finalize */
407872ac97cdSTom Musta       break;}
407972ac97cdSTom Musta 
408072ac97cdSTom Musta     /* [NB: both fastpath and mainpath code below assume these cases */
408172ac97cdSTom Musta     /* (notably 0-0) have already been handled] */
408272ac97cdSTom Musta 
408372ac97cdSTom Musta     /* calculate the padding needed to align the operands */
408472ac97cdSTom Musta     padding=rhs->exponent-lhs->exponent;
408572ac97cdSTom Musta 
408672ac97cdSTom Musta     /* Fastpath cases where the numbers are aligned and normal, the RHS */
408772ac97cdSTom Musta     /* is all in one unit, no operand rounding is needed, and no carry, */
408872ac97cdSTom Musta     /* lengthening, or borrow is needed */
408972ac97cdSTom Musta     if (padding==0
409072ac97cdSTom Musta 	&& rhs->digits<=DECDPUN
409172ac97cdSTom Musta 	&& rhs->exponent>=set->emin	/* [some normals drop through] */
409272ac97cdSTom Musta 	&& rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */
409372ac97cdSTom Musta 	&& rhs->digits<=reqdigits
409472ac97cdSTom Musta 	&& lhs->digits<=reqdigits) {
409572ac97cdSTom Musta       Int partial=*lhs->lsu;
409672ac97cdSTom Musta       if (!diffsign) {			/* adding */
409772ac97cdSTom Musta 	partial+=*rhs->lsu;
409872ac97cdSTom Musta 	if ((partial<=DECDPUNMAX)	/* result fits in unit */
409972ac97cdSTom Musta 	 && (lhs->digits>=DECDPUN ||	/* .. and no digits-count change */
410072ac97cdSTom Musta 	     partial<(Int)powers[lhs->digits])) { /* .. */
410172ac97cdSTom Musta 	  if (res!=lhs) decNumberCopy(res, lhs);  /* not in place */
410272ac97cdSTom Musta 	  *res->lsu=(Unit)partial;	/* [copy could have overwritten RHS] */
410372ac97cdSTom Musta 	  break;
410472ac97cdSTom Musta 	  }
410572ac97cdSTom Musta 	/* else drop out for careful add */
410672ac97cdSTom Musta 	}
410772ac97cdSTom Musta        else {				/* signs differ */
410872ac97cdSTom Musta 	partial-=*rhs->lsu;
410972ac97cdSTom Musta 	if (partial>0) { /* no borrow needed, and non-0 result */
411072ac97cdSTom Musta 	  if (res!=lhs) decNumberCopy(res, lhs);  /* not in place */
411172ac97cdSTom Musta 	  *res->lsu=(Unit)partial;
411272ac97cdSTom Musta 	  /* this could have reduced digits [but result>0] */
411372ac97cdSTom Musta 	  res->digits=decGetDigits(res->lsu, D2U(res->digits));
411472ac97cdSTom Musta 	  break;
411572ac97cdSTom Musta 	  }
411672ac97cdSTom Musta 	/* else drop out for careful subtract */
411772ac97cdSTom Musta 	}
411872ac97cdSTom Musta       }
411972ac97cdSTom Musta 
412072ac97cdSTom Musta     /* Now align (pad) the lhs or rhs so they can be added or */
412172ac97cdSTom Musta     /* subtracted, as necessary.  If one number is much larger than */
412272ac97cdSTom Musta     /* the other (that is, if in plain form there is a least one */
412372ac97cdSTom Musta     /* digit between the lowest digit of one and the highest of the */
412472ac97cdSTom Musta     /* other) padding with up to DIGITS-1 trailing zeros may be */
412572ac97cdSTom Musta     /* needed; then apply rounding (as exotic rounding modes may be */
412672ac97cdSTom Musta     /* affected by the residue). */
412772ac97cdSTom Musta     rhsshift=0;		      /* rhs shift to left (padding) in Units */
412872ac97cdSTom Musta     bits=lhs->bits;	      /* assume sign is that of LHS */
412972ac97cdSTom Musta     mult=1;		      /* likely multiplier */
413072ac97cdSTom Musta 
413172ac97cdSTom Musta     /* [if padding==0 the operands are aligned; no padding is needed] */
413272ac97cdSTom Musta     if (padding!=0) {
413372ac97cdSTom Musta       /* some padding needed; always pad the RHS, as any required */
413472ac97cdSTom Musta       /* padding can then be effected by a simple combination of */
413572ac97cdSTom Musta       /* shifts and a multiply */
413672ac97cdSTom Musta       Flag swapped=0;
413772ac97cdSTom Musta       if (padding<0) {			/* LHS needs the padding */
413872ac97cdSTom Musta 	const decNumber *t;
413972ac97cdSTom Musta 	padding=-padding;		/* will be +ve */
414072ac97cdSTom Musta 	bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */
414172ac97cdSTom Musta 	t=lhs; lhs=rhs; rhs=t;
414272ac97cdSTom Musta 	swapped=1;
414372ac97cdSTom Musta 	}
414472ac97cdSTom Musta 
414572ac97cdSTom Musta       /* If, after pad, rhs would be longer than lhs by digits+1 or */
414672ac97cdSTom Musta       /* more then lhs cannot affect the answer, except as a residue, */
414772ac97cdSTom Musta       /* so only need to pad up to a length of DIGITS+1. */
414872ac97cdSTom Musta       if (rhs->digits+padding > lhs->digits+reqdigits+1) {
414972ac97cdSTom Musta 	/* The RHS is sufficient */
415072ac97cdSTom Musta 	/* for residue use the relative sign indication... */
415172ac97cdSTom Musta 	Int shift=reqdigits-rhs->digits;     /* left shift needed */
415272ac97cdSTom Musta 	residue=1;			     /* residue for rounding */
415372ac97cdSTom Musta 	if (diffsign) residue=-residue;	     /* signs differ */
415472ac97cdSTom Musta 	/* copy, shortening if necessary */
415572ac97cdSTom Musta 	decCopyFit(res, rhs, set, &residue, status);
415672ac97cdSTom Musta 	/* if it was already shorter, then need to pad with zeros */
415772ac97cdSTom Musta 	if (shift>0) {
415872ac97cdSTom Musta 	  res->digits=decShiftToMost(res->lsu, res->digits, shift);
415972ac97cdSTom Musta 	  res->exponent-=shift;		     /* adjust the exponent. */
416072ac97cdSTom Musta 	  }
416172ac97cdSTom Musta 	/* flip the result sign if unswapped and rhs was negated */
416272ac97cdSTom Musta 	if (!swapped) res->bits^=negate;
416372ac97cdSTom Musta 	decFinish(res, set, &residue, status);	  /* done */
416472ac97cdSTom Musta 	break;}
416572ac97cdSTom Musta 
416672ac97cdSTom Musta       /* LHS digits may affect result */
416772ac97cdSTom Musta       rhsshift=D2U(padding+1)-1;	/* this much by Unit shift .. */
416872ac97cdSTom Musta       mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */
416972ac97cdSTom Musta       } /* padding needed */
417072ac97cdSTom Musta 
417172ac97cdSTom Musta     if (diffsign) mult=-mult;		/* signs differ */
417272ac97cdSTom Musta 
417372ac97cdSTom Musta     /* determine the longer operand */
417472ac97cdSTom Musta     maxdigits=rhs->digits+padding;	/* virtual length of RHS */
417572ac97cdSTom Musta     if (lhs->digits>maxdigits) maxdigits=lhs->digits;
417672ac97cdSTom Musta 
417772ac97cdSTom Musta     /* Decide on the result buffer to use; if possible place directly */
417872ac97cdSTom Musta     /* into result. */
417972ac97cdSTom Musta     acc=res->lsu;			/* assume add direct to result */
418072ac97cdSTom Musta     /* If destructive overlap, or the number is too long, or a carry or */
418172ac97cdSTom Musta     /* borrow to DIGITS+1 might be possible, a buffer must be used. */
418272ac97cdSTom Musta     /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */
418372ac97cdSTom Musta     if ((maxdigits>=reqdigits)		/* is, or could be, too large */
418472ac97cdSTom Musta      || (res==rhs && rhsshift>0)) {	/* destructive overlap */
418572ac97cdSTom Musta       /* buffer needed, choose it; units for maxdigits digits will be */
418672ac97cdSTom Musta       /* needed, +1 Unit for carry or borrow */
418772ac97cdSTom Musta       Int need=D2U(maxdigits)+1;
418872ac97cdSTom Musta       acc=accbuff;			/* assume use local buffer */
418972ac97cdSTom Musta       if (need*sizeof(Unit)>sizeof(accbuff)) {
419072ac97cdSTom Musta 	/* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */
419172ac97cdSTom Musta 	allocacc=(Unit *)malloc(need*sizeof(Unit));
419272ac97cdSTom Musta 	if (allocacc==NULL) {		/* hopeless -- abandon */
419372ac97cdSTom Musta 	  *status|=DEC_Insufficient_storage;
419472ac97cdSTom Musta 	  break;}
419572ac97cdSTom Musta 	acc=allocacc;
419672ac97cdSTom Musta 	}
419772ac97cdSTom Musta       }
419872ac97cdSTom Musta 
419972ac97cdSTom Musta     res->bits=(uByte)(bits&DECNEG);	/* it's now safe to overwrite.. */
420072ac97cdSTom Musta     res->exponent=lhs->exponent;	/* .. operands (even if aliased) */
420172ac97cdSTom Musta 
420272ac97cdSTom Musta     #if DECTRACE
420372ac97cdSTom Musta       decDumpAr('A', lhs->lsu, D2U(lhs->digits));
420472ac97cdSTom Musta       decDumpAr('B', rhs->lsu, D2U(rhs->digits));
420572ac97cdSTom Musta       printf("	:h: %ld %ld\n", rhsshift, mult);
420672ac97cdSTom Musta     #endif
420772ac97cdSTom Musta 
420872ac97cdSTom Musta     /* add [A+B*m] or subtract [A+B*(-m)] */
420972ac97cdSTom Musta     res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits),
421072ac97cdSTom Musta 			      rhs->lsu, D2U(rhs->digits),
421172ac97cdSTom Musta 			      rhsshift, acc, mult)
421272ac97cdSTom Musta 	       *DECDPUN;	   /* [units -> digits] */
421372ac97cdSTom Musta     if (res->digits<0) {	   /* borrowed... */
421472ac97cdSTom Musta       res->digits=-res->digits;
421572ac97cdSTom Musta       res->bits^=DECNEG;	   /* flip the sign */
421672ac97cdSTom Musta       }
421772ac97cdSTom Musta     #if DECTRACE
421872ac97cdSTom Musta       decDumpAr('+', acc, D2U(res->digits));
421972ac97cdSTom Musta     #endif
422072ac97cdSTom Musta 
422172ac97cdSTom Musta     /* If a buffer was used the result must be copied back, possibly */
422272ac97cdSTom Musta     /* shortening.  (If no buffer was used then the result must have */
422372ac97cdSTom Musta     /* fit, so can't need rounding and residue must be 0.) */
422472ac97cdSTom Musta     residue=0;			   /* clear accumulator */
422572ac97cdSTom Musta     if (acc!=res->lsu) {
422672ac97cdSTom Musta       #if DECSUBSET
422772ac97cdSTom Musta       if (set->extended) {	   /* round from first significant digit */
422872ac97cdSTom Musta       #endif
422972ac97cdSTom Musta 	/* remove leading zeros that were added due to rounding up to */
423072ac97cdSTom Musta 	/* integral Units -- before the test for rounding. */
423172ac97cdSTom Musta 	if (res->digits>reqdigits)
423272ac97cdSTom Musta 	  res->digits=decGetDigits(acc, D2U(res->digits));
423372ac97cdSTom Musta 	decSetCoeff(res, set, acc, res->digits, &residue, status);
423472ac97cdSTom Musta       #if DECSUBSET
423572ac97cdSTom Musta 	}
423672ac97cdSTom Musta        else { /* subset arithmetic rounds from original significant digit */
423772ac97cdSTom Musta 	/* May have an underestimate.  This only occurs when both */
423872ac97cdSTom Musta 	/* numbers fit in DECDPUN digits and are padding with a */
423972ac97cdSTom Musta 	/* negative multiple (-10, -100...) and the top digit(s) become */
424072ac97cdSTom Musta 	/* 0.  (This only matters when using X3.274 rules where the */
424172ac97cdSTom Musta 	/* leading zero could be included in the rounding.) */
424272ac97cdSTom Musta 	if (res->digits<maxdigits) {
424372ac97cdSTom Musta 	  *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */
424472ac97cdSTom Musta 	  res->digits=maxdigits;
424572ac97cdSTom Musta 	  }
424672ac97cdSTom Musta 	 else {
424772ac97cdSTom Musta 	  /* remove leading zeros that added due to rounding up to */
424872ac97cdSTom Musta 	  /* integral Units (but only those in excess of the original */
424972ac97cdSTom Musta 	  /* maxdigits length, unless extended) before test for rounding. */
425072ac97cdSTom Musta 	  if (res->digits>reqdigits) {
425172ac97cdSTom Musta 	    res->digits=decGetDigits(acc, D2U(res->digits));
425272ac97cdSTom Musta 	    if (res->digits<maxdigits) res->digits=maxdigits;
425372ac97cdSTom Musta 	    }
425472ac97cdSTom Musta 	  }
425572ac97cdSTom Musta 	decSetCoeff(res, set, acc, res->digits, &residue, status);
425672ac97cdSTom Musta 	/* Now apply rounding if needed before removing leading zeros. */
425772ac97cdSTom Musta 	/* This is safe because subnormals are not a possibility */
425872ac97cdSTom Musta 	if (residue!=0) {
425972ac97cdSTom Musta 	  decApplyRound(res, set, residue, status);
426072ac97cdSTom Musta 	  residue=0;		     /* did what needed to be done */
426172ac97cdSTom Musta 	  }
426272ac97cdSTom Musta 	} /* subset */
426372ac97cdSTom Musta       #endif
426472ac97cdSTom Musta       } /* used buffer */
426572ac97cdSTom Musta 
426672ac97cdSTom Musta     /* strip leading zeros [these were left on in case of subset subtract] */
426772ac97cdSTom Musta     res->digits=decGetDigits(res->lsu, D2U(res->digits));
426872ac97cdSTom Musta 
426972ac97cdSTom Musta     /* apply checks and rounding */
427072ac97cdSTom Musta     decFinish(res, set, &residue, status);
427172ac97cdSTom Musta 
427272ac97cdSTom Musta     /* "When the sum of two operands with opposite signs is exactly */
427372ac97cdSTom Musta     /* zero, the sign of that sum shall be '+' in all rounding modes */
427472ac97cdSTom Musta     /* except round toward -Infinity, in which mode that sign shall be */
427572ac97cdSTom Musta     /* '-'."  [Subset zeros also never have '-', set by decFinish.] */
427672ac97cdSTom Musta     if (ISZERO(res) && diffsign
427772ac97cdSTom Musta      #if DECSUBSET
427872ac97cdSTom Musta      && set->extended
427972ac97cdSTom Musta      #endif
428072ac97cdSTom Musta      && (*status&DEC_Inexact)==0) {
428172ac97cdSTom Musta       if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG;   /* sign - */
428272ac97cdSTom Musta 				  else res->bits&=~DECNEG;  /* sign + */
428372ac97cdSTom Musta       }
428472ac97cdSTom Musta     } while(0);				     /* end protected */
428572ac97cdSTom Musta 
428672ac97cdSTom Musta   if (allocacc!=NULL) free(allocacc);	     /* drop any storage used */
428772ac97cdSTom Musta   #if DECSUBSET
428872ac97cdSTom Musta   if (allocrhs!=NULL) free(allocrhs);	     /* .. */
428972ac97cdSTom Musta   if (alloclhs!=NULL) free(alloclhs);	     /* .. */
429072ac97cdSTom Musta   #endif
429172ac97cdSTom Musta   return res;
429272ac97cdSTom Musta   } /* decAddOp */
429372ac97cdSTom Musta 
429472ac97cdSTom Musta /* ------------------------------------------------------------------ */
429572ac97cdSTom Musta /* decDivideOp -- division operation				      */
429672ac97cdSTom Musta /*								      */
429772ac97cdSTom Musta /*  This routine performs the calculations for all four division      */
429872ac97cdSTom Musta /*  operators (divide, divideInteger, remainder, remainderNear).      */
429972ac97cdSTom Musta /*								      */
430072ac97cdSTom Musta /*  C=A op B							      */
430172ac97cdSTom Musta /*								      */
430272ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X/X)	      */
430372ac97cdSTom Musta /*   lhs is A							      */
430472ac97cdSTom Musta /*   rhs is B							      */
430572ac97cdSTom Musta /*   set is the context						      */
430672ac97cdSTom Musta /*   op	 is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively.    */
430772ac97cdSTom Musta /*   status is the usual accumulator				      */
430872ac97cdSTom Musta /*								      */
430972ac97cdSTom Musta /* C must have space for set->digits digits.			      */
431072ac97cdSTom Musta /*								      */
431172ac97cdSTom Musta /* ------------------------------------------------------------------ */
431272ac97cdSTom Musta /*   The underlying algorithm of this routine is the same as in the   */
431372ac97cdSTom Musta /*   1981 S/370 implementation, that is, non-restoring long division  */
431472ac97cdSTom Musta /*   with bi-unit (rather than bi-digit) estimation for each unit     */
431572ac97cdSTom Musta /*   multiplier.  In this pseudocode overview, complications for the  */
431672ac97cdSTom Musta /*   Remainder operators and division residues for exact rounding are */
431772ac97cdSTom Musta /*   omitted for clarity.					      */
431872ac97cdSTom Musta /*								      */
431972ac97cdSTom Musta /*     Prepare operands and handle special values		      */
432072ac97cdSTom Musta /*     Test for x/0 and then 0/x				      */
432172ac97cdSTom Musta /*     Exp =Exp1 - Exp2						      */
432272ac97cdSTom Musta /*     Exp =Exp +len(var1) -len(var2)				      */
432372ac97cdSTom Musta /*     Sign=Sign1 * Sign2					      */
432472ac97cdSTom Musta /*     Pad accumulator (Var1) to double-length with 0's (pad1)	      */
432572ac97cdSTom Musta /*     Pad Var2 to same length as Var1				      */
432672ac97cdSTom Musta /*     msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round  */
432772ac97cdSTom Musta /*     have=0							      */
432872ac97cdSTom Musta /*     Do until (have=digits+1 OR residue=0)			      */
432972ac97cdSTom Musta /*	 if exp<0 then if integer divide/residue then leave	      */
433072ac97cdSTom Musta /*	 this_unit=0						      */
433172ac97cdSTom Musta /*	 Do forever						      */
433272ac97cdSTom Musta /*	    compare numbers					      */
433372ac97cdSTom Musta /*	    if <0 then leave inner_loop				      */
433472ac97cdSTom Musta /*	    if =0 then (* quick exit without subtract *) do	      */
433572ac97cdSTom Musta /*	       this_unit=this_unit+1; output this_unit		      */
433672ac97cdSTom Musta /*	       leave outer_loop; end				      */
433772ac97cdSTom Musta /*	    Compare lengths of numbers (mantissae):		      */
433872ac97cdSTom Musta /*	    If same then tops2=msu2pair -- {units 1&2 of var2}	      */
433972ac97cdSTom Musta /*		    else tops2=msu2plus -- {0, unit 1 of var2}	      */
434072ac97cdSTom Musta /*	    tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */
434172ac97cdSTom Musta /*	    mult=tops1/tops2  -- Good and safe guess at divisor	      */
434272ac97cdSTom Musta /*	    if mult=0 then mult=1				      */
434372ac97cdSTom Musta /*	    this_unit=this_unit+mult				      */
434472ac97cdSTom Musta /*	    subtract						      */
434572ac97cdSTom Musta /*	    end inner_loop					      */
434672ac97cdSTom Musta /*	  if have\=0 | this_unit\=0 then do			      */
434772ac97cdSTom Musta /*	    output this_unit					      */
434872ac97cdSTom Musta /*	    have=have+1; end					      */
434972ac97cdSTom Musta /*	  var2=var2/10						      */
435072ac97cdSTom Musta /*	  exp=exp-1						      */
435172ac97cdSTom Musta /*	  end outer_loop					      */
435272ac97cdSTom Musta /*     exp=exp+1   -- set the proper exponent			      */
435372ac97cdSTom Musta /*     if have=0 then generate answer=0				      */
435472ac97cdSTom Musta /*     Return (Result is defined by Var1)			      */
435572ac97cdSTom Musta /*								      */
435672ac97cdSTom Musta /* ------------------------------------------------------------------ */
435772ac97cdSTom Musta /* Two working buffers are needed during the division; one (digits+   */
435872ac97cdSTom Musta /* 1) to accumulate the result, and the other (up to 2*digits+1) for  */
435972ac97cdSTom Musta /* long subtractions.  These are acc and var1 respectively.	      */
436072ac97cdSTom Musta /* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/
436172ac97cdSTom Musta /* The static buffers may be larger than might be expected to allow   */
436267cc32ebSVeres Lajos /* for calls from higher-level functions (notably exp).		      */
436372ac97cdSTom Musta /* ------------------------------------------------------------------ */
decDivideOp(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set,Flag op,uInt * status)436472ac97cdSTom Musta static decNumber * decDivideOp(decNumber *res,
436572ac97cdSTom Musta 			       const decNumber *lhs, const decNumber *rhs,
436672ac97cdSTom Musta 			       decContext *set, Flag op, uInt *status) {
436772ac97cdSTom Musta   #if DECSUBSET
436872ac97cdSTom Musta   decNumber *alloclhs=NULL;	   /* non-NULL if rounded lhs allocated */
436972ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* .., rhs */
437072ac97cdSTom Musta   #endif
437172ac97cdSTom Musta   Unit	accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */
437272ac97cdSTom Musta   Unit	*acc=accbuff;		   /* -> accumulator array for result */
437372ac97cdSTom Musta   Unit	*allocacc=NULL;		   /* -> allocated buffer, iff allocated */
437472ac97cdSTom Musta   Unit	*accnext;		   /* -> where next digit will go */
437572ac97cdSTom Musta   Int	acclength;		   /* length of acc needed [Units] */
437672ac97cdSTom Musta   Int	accunits;		   /* count of units accumulated */
437772ac97cdSTom Musta   Int	accdigits;		   /* count of digits accumulated */
437872ac97cdSTom Musta 
437972ac97cdSTom Musta   Unit	varbuff[SD2U(DECBUFFER*2+DECDPUN)*sizeof(Unit)]; /* buffer for var1 */
438072ac97cdSTom Musta   Unit	*var1=varbuff;		   /* -> var1 array for long subtraction */
438172ac97cdSTom Musta   Unit	*varalloc=NULL;		   /* -> allocated buffer, iff used */
438272ac97cdSTom Musta   Unit	*msu1;			   /* -> msu of var1 */
438372ac97cdSTom Musta 
438472ac97cdSTom Musta   const Unit *var2;		   /* -> var2 array */
438572ac97cdSTom Musta   const Unit *msu2;		   /* -> msu of var2 */
438672ac97cdSTom Musta   Int	msu2plus;		   /* msu2 plus one [does not vary] */
438772ac97cdSTom Musta   eInt	msu2pair;		   /* msu2 pair plus one [does not vary] */
438872ac97cdSTom Musta 
438972ac97cdSTom Musta   Int	var1units, var2units;	   /* actual lengths */
439072ac97cdSTom Musta   Int	var2ulen;		   /* logical length (units) */
439172ac97cdSTom Musta   Int	var1initpad=0;		   /* var1 initial padding (digits) */
439272ac97cdSTom Musta   Int	maxdigits;		   /* longest LHS or required acc length */
439372ac97cdSTom Musta   Int	mult;			   /* multiplier for subtraction */
439472ac97cdSTom Musta   Unit	thisunit;		   /* current unit being accumulated */
439572ac97cdSTom Musta   Int	residue;		   /* for rounding */
439672ac97cdSTom Musta   Int	reqdigits=set->digits;	   /* requested DIGITS */
439772ac97cdSTom Musta   Int	exponent;		   /* working exponent */
439872ac97cdSTom Musta   Int	maxexponent=0;		   /* DIVIDE maximum exponent if unrounded */
439972ac97cdSTom Musta   uByte bits;			   /* working sign */
440072ac97cdSTom Musta   Unit	*target;		   /* work */
440172ac97cdSTom Musta   const Unit *source;		   /* .. */
440279af3572STom Musta   uLong const *pow;                /* .. */
440372ac97cdSTom Musta   Int	shift, cut;		   /* .. */
440472ac97cdSTom Musta   #if DECSUBSET
440572ac97cdSTom Musta   Int	dropped;		   /* work */
440672ac97cdSTom Musta   #endif
440772ac97cdSTom Musta 
440872ac97cdSTom Musta   #if DECCHECK
440972ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
441072ac97cdSTom Musta   #endif
441172ac97cdSTom Musta 
441272ac97cdSTom Musta   do {				   /* protect allocated storage */
441372ac97cdSTom Musta     #if DECSUBSET
441472ac97cdSTom Musta     if (!set->extended) {
441572ac97cdSTom Musta       /* reduce operands and set lostDigits status, as needed */
441672ac97cdSTom Musta       if (lhs->digits>reqdigits) {
441772ac97cdSTom Musta 	alloclhs=decRoundOperand(lhs, set, status);
441872ac97cdSTom Musta 	if (alloclhs==NULL) break;
441972ac97cdSTom Musta 	lhs=alloclhs;
442072ac97cdSTom Musta 	}
442172ac97cdSTom Musta       if (rhs->digits>reqdigits) {
442272ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, status);
442372ac97cdSTom Musta 	if (allocrhs==NULL) break;
442472ac97cdSTom Musta 	rhs=allocrhs;
442572ac97cdSTom Musta 	}
442672ac97cdSTom Musta       }
442772ac97cdSTom Musta     #endif
442872ac97cdSTom Musta     /* [following code does not require input rounding] */
442972ac97cdSTom Musta 
443072ac97cdSTom Musta     bits=(lhs->bits^rhs->bits)&DECNEG;	/* assumed sign for divisions */
443172ac97cdSTom Musta 
443272ac97cdSTom Musta     /* handle infinities and NaNs */
443372ac97cdSTom Musta     if (SPECIALARGS) {			/* a special bit set */
443472ac97cdSTom Musta       if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
443572ac97cdSTom Musta 	decNaNs(res, lhs, rhs, set, status);
443672ac97cdSTom Musta 	break;
443772ac97cdSTom Musta 	}
443872ac97cdSTom Musta       /* one or two infinities */
443972ac97cdSTom Musta       if (decNumberIsInfinite(lhs)) {	/* LHS (dividend) is infinite */
444072ac97cdSTom Musta 	if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */
444172ac97cdSTom Musta 	    op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */
444272ac97cdSTom Musta 	  *status|=DEC_Invalid_operation;
444372ac97cdSTom Musta 	  break;
444472ac97cdSTom Musta 	  }
444572ac97cdSTom Musta 	/* [Note that infinity/0 raises no exceptions] */
444672ac97cdSTom Musta 	decNumberZero(res);
444772ac97cdSTom Musta 	res->bits=bits|DECINF;		/* set +/- infinity */
444872ac97cdSTom Musta 	break;
444972ac97cdSTom Musta 	}
445072ac97cdSTom Musta        else {				/* RHS (divisor) is infinite */
445172ac97cdSTom Musta 	residue=0;
445272ac97cdSTom Musta 	if (op&(REMAINDER|REMNEAR)) {
445372ac97cdSTom Musta 	  /* result is [finished clone of] lhs */
445472ac97cdSTom Musta 	  decCopyFit(res, lhs, set, &residue, status);
445572ac97cdSTom Musta 	  }
445672ac97cdSTom Musta 	 else {	 /* a division */
445772ac97cdSTom Musta 	  decNumberZero(res);
445872ac97cdSTom Musta 	  res->bits=bits;		/* set +/- zero */
445972ac97cdSTom Musta 	  /* for DIVIDEINT the exponent is always 0.  For DIVIDE, result */
446072ac97cdSTom Musta 	  /* is a 0 with infinitely negative exponent, clamped to minimum */
446172ac97cdSTom Musta 	  if (op&DIVIDE) {
446272ac97cdSTom Musta 	    res->exponent=set->emin-set->digits+1;
446372ac97cdSTom Musta 	    *status|=DEC_Clamped;
446472ac97cdSTom Musta 	    }
446572ac97cdSTom Musta 	  }
446672ac97cdSTom Musta 	decFinish(res, set, &residue, status);
446772ac97cdSTom Musta 	break;
446872ac97cdSTom Musta 	}
446972ac97cdSTom Musta       }
447072ac97cdSTom Musta 
447172ac97cdSTom Musta     /* handle 0 rhs (x/0) */
447272ac97cdSTom Musta     if (ISZERO(rhs)) {			/* x/0 is always exceptional */
447372ac97cdSTom Musta       if (ISZERO(lhs)) {
447472ac97cdSTom Musta 	decNumberZero(res);		/* [after lhs test] */
447572ac97cdSTom Musta 	*status|=DEC_Division_undefined;/* 0/0 will become NaN */
447672ac97cdSTom Musta 	}
447772ac97cdSTom Musta        else {
447872ac97cdSTom Musta 	decNumberZero(res);
447972ac97cdSTom Musta 	if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation;
448072ac97cdSTom Musta 	 else {
448172ac97cdSTom Musta 	  *status|=DEC_Division_by_zero; /* x/0 */
448272ac97cdSTom Musta 	  res->bits=bits|DECINF;	 /* .. is +/- Infinity */
448372ac97cdSTom Musta 	  }
448472ac97cdSTom Musta 	}
448572ac97cdSTom Musta       break;}
448672ac97cdSTom Musta 
448772ac97cdSTom Musta     /* handle 0 lhs (0/x) */
448872ac97cdSTom Musta     if (ISZERO(lhs)) {			/* 0/x [x!=0] */
448972ac97cdSTom Musta       #if DECSUBSET
449072ac97cdSTom Musta       if (!set->extended) decNumberZero(res);
449172ac97cdSTom Musta        else {
449272ac97cdSTom Musta       #endif
449372ac97cdSTom Musta 	if (op&DIVIDE) {
449472ac97cdSTom Musta 	  residue=0;
449572ac97cdSTom Musta 	  exponent=lhs->exponent-rhs->exponent; /* ideal exponent */
449672ac97cdSTom Musta 	  decNumberCopy(res, lhs);	/* [zeros always fit] */
449772ac97cdSTom Musta 	  res->bits=bits;		/* sign as computed */
449872ac97cdSTom Musta 	  res->exponent=exponent;	/* exponent, too */
449972ac97cdSTom Musta 	  decFinalize(res, set, &residue, status);   /* check exponent */
450072ac97cdSTom Musta 	  }
450172ac97cdSTom Musta 	 else if (op&DIVIDEINT) {
450272ac97cdSTom Musta 	  decNumberZero(res);		/* integer 0 */
450372ac97cdSTom Musta 	  res->bits=bits;		/* sign as computed */
450472ac97cdSTom Musta 	  }
450572ac97cdSTom Musta 	 else {				/* a remainder */
450672ac97cdSTom Musta 	  exponent=rhs->exponent;	/* [save in case overwrite] */
450772ac97cdSTom Musta 	  decNumberCopy(res, lhs);	/* [zeros always fit] */
450872ac97cdSTom Musta 	  if (exponent<res->exponent) res->exponent=exponent; /* use lower */
450972ac97cdSTom Musta 	  }
451072ac97cdSTom Musta       #if DECSUBSET
451172ac97cdSTom Musta 	}
451272ac97cdSTom Musta       #endif
451372ac97cdSTom Musta       break;}
451472ac97cdSTom Musta 
451572ac97cdSTom Musta     /* Precalculate exponent.  This starts off adjusted (and hence fits */
451672ac97cdSTom Musta     /* in 31 bits) and becomes the usual unadjusted exponent as the */
451772ac97cdSTom Musta     /* division proceeds.  The order of evaluation is important, here, */
451872ac97cdSTom Musta     /* to avoid wrap. */
451972ac97cdSTom Musta     exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits);
452072ac97cdSTom Musta 
452172ac97cdSTom Musta     /* If the working exponent is -ve, then some quick exits are */
452272ac97cdSTom Musta     /* possible because the quotient is known to be <1 */
452372ac97cdSTom Musta     /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */
452472ac97cdSTom Musta     if (exponent<0 && !(op==DIVIDE)) {
452572ac97cdSTom Musta       if (op&DIVIDEINT) {
452672ac97cdSTom Musta 	decNumberZero(res);		     /* integer part is 0 */
452772ac97cdSTom Musta 	#if DECSUBSET
452872ac97cdSTom Musta 	if (set->extended)
452972ac97cdSTom Musta 	#endif
453072ac97cdSTom Musta 	  res->bits=bits;		     /* set +/- zero */
453172ac97cdSTom Musta 	break;}
453272ac97cdSTom Musta       /* fastpath remainders so long as the lhs has the smaller */
453372ac97cdSTom Musta       /* (or equal) exponent */
453472ac97cdSTom Musta       if (lhs->exponent<=rhs->exponent) {
453572ac97cdSTom Musta 	if (op&REMAINDER || exponent<-1) {
453672ac97cdSTom Musta 	  /* It is REMAINDER or safe REMNEAR; result is [finished */
453772ac97cdSTom Musta 	  /* clone of] lhs  (r = x - 0*y) */
453872ac97cdSTom Musta 	  residue=0;
453972ac97cdSTom Musta 	  decCopyFit(res, lhs, set, &residue, status);
454072ac97cdSTom Musta 	  decFinish(res, set, &residue, status);
454172ac97cdSTom Musta 	  break;
454272ac97cdSTom Musta 	  }
454372ac97cdSTom Musta 	/* [unsafe REMNEAR drops through] */
454472ac97cdSTom Musta 	}
454572ac97cdSTom Musta       } /* fastpaths */
454672ac97cdSTom Musta 
454772ac97cdSTom Musta     /* Long (slow) division is needed; roll up the sleeves... */
454872ac97cdSTom Musta 
454972ac97cdSTom Musta     /* The accumulator will hold the quotient of the division. */
455072ac97cdSTom Musta     /* If it needs to be too long for stack storage, then allocate. */
455172ac97cdSTom Musta     acclength=D2U(reqdigits+DECDPUN);	/* in Units */
455272ac97cdSTom Musta     if (acclength*sizeof(Unit)>sizeof(accbuff)) {
455372ac97cdSTom Musta       /* printf("malloc dvacc %ld units\n", acclength); */
455472ac97cdSTom Musta       allocacc=(Unit *)malloc(acclength*sizeof(Unit));
455572ac97cdSTom Musta       if (allocacc==NULL) {		/* hopeless -- abandon */
455672ac97cdSTom Musta 	*status|=DEC_Insufficient_storage;
455772ac97cdSTom Musta 	break;}
455872ac97cdSTom Musta       acc=allocacc;			/* use the allocated space */
455972ac97cdSTom Musta       }
456072ac97cdSTom Musta 
456172ac97cdSTom Musta     /* var1 is the padded LHS ready for subtractions. */
456272ac97cdSTom Musta     /* If it needs to be too long for stack storage, then allocate. */
456372ac97cdSTom Musta     /* The maximum units needed for var1 (long subtraction) is: */
456472ac97cdSTom Musta     /* Enough for */
456572ac97cdSTom Musta     /*	   (rhs->digits+reqdigits-1) -- to allow full slide to right */
456672ac97cdSTom Musta     /* or  (lhs->digits)	     -- to allow for long lhs */
456772ac97cdSTom Musta     /* whichever is larger */
456872ac97cdSTom Musta     /*	 +1		   -- for rounding of slide to right */
456972ac97cdSTom Musta     /*	 +1		   -- for leading 0s */
457072ac97cdSTom Musta     /*	 +1		   -- for pre-adjust if a remainder or DIVIDEINT */
457172ac97cdSTom Musta     /* [Note: unused units do not participate in decUnitAddSub data] */
457272ac97cdSTom Musta     maxdigits=rhs->digits+reqdigits-1;
457372ac97cdSTom Musta     if (lhs->digits>maxdigits) maxdigits=lhs->digits;
457472ac97cdSTom Musta     var1units=D2U(maxdigits)+2;
457572ac97cdSTom Musta     /* allocate a guard unit above msu1 for REMAINDERNEAR */
457672ac97cdSTom Musta     if (!(op&DIVIDE)) var1units++;
457772ac97cdSTom Musta     if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) {
457872ac97cdSTom Musta       /* printf("malloc dvvar %ld units\n", var1units+1); */
457972ac97cdSTom Musta       varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit));
458072ac97cdSTom Musta       if (varalloc==NULL) {		/* hopeless -- abandon */
458172ac97cdSTom Musta 	*status|=DEC_Insufficient_storage;
458272ac97cdSTom Musta 	break;}
458372ac97cdSTom Musta       var1=varalloc;			/* use the allocated space */
458472ac97cdSTom Musta       }
458572ac97cdSTom Musta 
458672ac97cdSTom Musta     /* Extend the lhs and rhs to full long subtraction length.	The lhs */
458772ac97cdSTom Musta     /* is truly extended into the var1 buffer, with 0 padding, so a */
458872ac97cdSTom Musta     /* subtract in place is always possible.  The rhs (var2) has */
458972ac97cdSTom Musta     /* virtual padding (implemented by decUnitAddSub). */
459072ac97cdSTom Musta     /* One guard unit was allocated above msu1 for rem=rem+rem in */
459172ac97cdSTom Musta     /* REMAINDERNEAR. */
459272ac97cdSTom Musta     msu1=var1+var1units-1;		/* msu of var1 */
459372ac97cdSTom Musta     source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */
459472ac97cdSTom Musta     for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source;
459572ac97cdSTom Musta     for (; target>=var1; target--) *target=0;
459672ac97cdSTom Musta 
459772ac97cdSTom Musta     /* rhs (var2) is left-aligned with var1 at the start */
459872ac97cdSTom Musta     var2ulen=var1units;			/* rhs logical length (units) */
459972ac97cdSTom Musta     var2units=D2U(rhs->digits);		/* rhs actual length (units) */
460072ac97cdSTom Musta     var2=rhs->lsu;			/* -> rhs array */
460172ac97cdSTom Musta     msu2=var2+var2units-1;		/* -> msu of var2 [never changes] */
460272ac97cdSTom Musta     /* now set up the variables which will be used for estimating the */
460372ac97cdSTom Musta     /* multiplication factor.  If these variables are not exact, add */
460472ac97cdSTom Musta     /* 1 to make sure that the multiplier is never overestimated. */
460572ac97cdSTom Musta     msu2plus=*msu2;			/* it's value .. */
460672ac97cdSTom Musta     if (var2units>1) msu2plus++;	/* .. +1 if any more */
460772ac97cdSTom Musta     msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */
460872ac97cdSTom Musta     if (var2units>1) {			/* .. [else treat 2nd as 0] */
460972ac97cdSTom Musta       msu2pair+=*(msu2-1);		/* .. */
461072ac97cdSTom Musta       if (var2units>2) msu2pair++;	/* .. +1 if any more */
461172ac97cdSTom Musta       }
461272ac97cdSTom Musta 
461372ac97cdSTom Musta     /* The calculation is working in units, which may have leading zeros, */
461472ac97cdSTom Musta     /* but the exponent was calculated on the assumption that they are */
461572ac97cdSTom Musta     /* both left-aligned.  Adjust the exponent to compensate: add the */
461672ac97cdSTom Musta     /* number of leading zeros in var1 msu and subtract those in var2 msu. */
461772ac97cdSTom Musta     /* [This is actually done by counting the digits and negating, as */
461872ac97cdSTom Musta     /* lead1=DECDPUN-digits1, and similarly for lead2.] */
461972ac97cdSTom Musta     for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--;
462072ac97cdSTom Musta     for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++;
462172ac97cdSTom Musta 
462272ac97cdSTom Musta     /* Now, if doing an integer divide or remainder, ensure that */
462372ac97cdSTom Musta     /* the result will be Unit-aligned.	 To do this, shift the var1 */
462472ac97cdSTom Musta     /* accumulator towards least if need be.  (It's much easier to */
462572ac97cdSTom Musta     /* do this now than to reassemble the residue afterwards, if */
462672ac97cdSTom Musta     /* doing a remainder.)  Also ensure the exponent is not negative. */
462772ac97cdSTom Musta     if (!(op&DIVIDE)) {
462872ac97cdSTom Musta       Unit *u;				/* work */
462972ac97cdSTom Musta       /* save the initial 'false' padding of var1, in digits */
463072ac97cdSTom Musta       var1initpad=(var1units-D2U(lhs->digits))*DECDPUN;
463172ac97cdSTom Musta       /* Determine the shift to do. */
463272ac97cdSTom Musta       if (exponent<0) cut=-exponent;
463372ac97cdSTom Musta        else cut=DECDPUN-exponent%DECDPUN;
463472ac97cdSTom Musta       decShiftToLeast(var1, var1units, cut);
463572ac97cdSTom Musta       exponent+=cut;			/* maintain numerical value */
463672ac97cdSTom Musta       var1initpad-=cut;			/* .. and reduce padding */
463772ac97cdSTom Musta       /* clean any most-significant units which were just emptied */
463872ac97cdSTom Musta       for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0;
463972ac97cdSTom Musta       } /* align */
464072ac97cdSTom Musta      else { /* is DIVIDE */
464172ac97cdSTom Musta       maxexponent=lhs->exponent-rhs->exponent;	  /* save */
464272ac97cdSTom Musta       /* optimization: if the first iteration will just produce 0, */
464372ac97cdSTom Musta       /* preadjust to skip it [valid for DIVIDE only] */
464472ac97cdSTom Musta       if (*msu1<*msu2) {
464572ac97cdSTom Musta 	var2ulen--;			/* shift down */
464672ac97cdSTom Musta 	exponent-=DECDPUN;		/* update the exponent */
464772ac97cdSTom Musta 	}
464872ac97cdSTom Musta       }
464972ac97cdSTom Musta 
465072ac97cdSTom Musta     /* ---- start the long-division loops ------------------------------ */
465172ac97cdSTom Musta     accunits=0;				/* no units accumulated yet */
465272ac97cdSTom Musta     accdigits=0;			/* .. or digits */
465372ac97cdSTom Musta     accnext=acc+acclength-1;		/* -> msu of acc [NB: allows digits+1] */
465472ac97cdSTom Musta     for (;;) {				/* outer forever loop */
465572ac97cdSTom Musta       thisunit=0;			/* current unit assumed 0 */
465672ac97cdSTom Musta       /* find the next unit */
465772ac97cdSTom Musta       for (;;) {			/* inner forever loop */
465872ac97cdSTom Musta 	/* strip leading zero units [from either pre-adjust or from */
465972ac97cdSTom Musta 	/* subtract last time around].	Leave at least one unit. */
466072ac97cdSTom Musta 	for (; *msu1==0 && msu1>var1; msu1--) var1units--;
466172ac97cdSTom Musta 
466272ac97cdSTom Musta 	if (var1units<var2ulen) break;	     /* var1 too low for subtract */
466372ac97cdSTom Musta 	if (var1units==var2ulen) {	     /* unit-by-unit compare needed */
466472ac97cdSTom Musta 	  /* compare the two numbers, from msu */
466572ac97cdSTom Musta 	  const Unit *pv1, *pv2;
466672ac97cdSTom Musta 	  Unit v2;			     /* units to compare */
466772ac97cdSTom Musta 	  pv2=msu2;			     /* -> msu */
466872ac97cdSTom Musta 	  for (pv1=msu1; ; pv1--, pv2--) {
466972ac97cdSTom Musta 	    /* v1=*pv1 -- always OK */
467072ac97cdSTom Musta 	    v2=0;			     /* assume in padding */
467172ac97cdSTom Musta 	    if (pv2>=var2) v2=*pv2;	     /* in range */
467272ac97cdSTom Musta 	    if (*pv1!=v2) break;	     /* no longer the same */
467372ac97cdSTom Musta 	    if (pv1==var1) break;	     /* done; leave pv1 as is */
467472ac97cdSTom Musta 	    }
467572ac97cdSTom Musta 	  /* here when all inspected or a difference seen */
467672ac97cdSTom Musta 	  if (*pv1<v2) break;		     /* var1 too low to subtract */
467772ac97cdSTom Musta 	  if (*pv1==v2) {		     /* var1 == var2 */
467872ac97cdSTom Musta 	    /* reach here if var1 and var2 are identical; subtraction */
467972ac97cdSTom Musta 	    /* would increase digit by one, and the residue will be 0 so */
468072ac97cdSTom Musta 	    /* the calculation is done; leave the loop with residue=0. */
468172ac97cdSTom Musta 	    thisunit++;			     /* as though subtracted */
468272ac97cdSTom Musta 	    *var1=0;			     /* set var1 to 0 */
468372ac97cdSTom Musta 	    var1units=1;		     /* .. */
468472ac97cdSTom Musta 	    break;  /* from inner */
468572ac97cdSTom Musta 	    } /* var1 == var2 */
468672ac97cdSTom Musta 	  /* *pv1>v2.  Prepare for real subtraction; the lengths are equal */
468772ac97cdSTom Musta 	  /* Estimate the multiplier (there's always a msu1-1)... */
468872ac97cdSTom Musta 	  /* Bring in two units of var2 to provide a good estimate. */
468972ac97cdSTom Musta 	  mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair);
469072ac97cdSTom Musta 	  } /* lengths the same */
469172ac97cdSTom Musta 	 else { /* var1units > var2ulen, so subtraction is safe */
469272ac97cdSTom Musta 	  /* The var2 msu is one unit towards the lsu of the var1 msu, */
469372ac97cdSTom Musta 	  /* so only one unit for var2 can be used. */
469472ac97cdSTom Musta 	  mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus);
469572ac97cdSTom Musta 	  }
469672ac97cdSTom Musta 	if (mult==0) mult=1;		     /* must always be at least 1 */
469772ac97cdSTom Musta 	/* subtraction needed; var1 is > var2 */
469872ac97cdSTom Musta 	thisunit=(Unit)(thisunit+mult);	     /* accumulate */
469972ac97cdSTom Musta 	/* subtract var1-var2, into var1; only the overlap needs */
470072ac97cdSTom Musta 	/* processing, as this is an in-place calculation */
470172ac97cdSTom Musta 	shift=var2ulen-var2units;
470272ac97cdSTom Musta 	#if DECTRACE
470372ac97cdSTom Musta 	  decDumpAr('1', &var1[shift], var1units-shift);
470472ac97cdSTom Musta 	  decDumpAr('2', var2, var2units);
470572ac97cdSTom Musta 	  printf("m=%ld\n", -mult);
470672ac97cdSTom Musta 	#endif
470772ac97cdSTom Musta 	decUnitAddSub(&var1[shift], var1units-shift,
470872ac97cdSTom Musta 		      var2, var2units, 0,
470972ac97cdSTom Musta 		      &var1[shift], -mult);
471072ac97cdSTom Musta 	#if DECTRACE
471172ac97cdSTom Musta 	  decDumpAr('#', &var1[shift], var1units-shift);
471272ac97cdSTom Musta 	#endif
471372ac97cdSTom Musta 	/* var1 now probably has leading zeros; these are removed at the */
471472ac97cdSTom Musta 	/* top of the inner loop. */
471572ac97cdSTom Musta 	} /* inner loop */
471672ac97cdSTom Musta 
471772ac97cdSTom Musta       /* The next unit has been calculated in full; unless it's a */
471872ac97cdSTom Musta       /* leading zero, add to acc */
471972ac97cdSTom Musta       if (accunits!=0 || thisunit!=0) {	     /* is first or non-zero */
472072ac97cdSTom Musta 	*accnext=thisunit;		     /* store in accumulator */
472172ac97cdSTom Musta 	/* account exactly for the new digits */
472272ac97cdSTom Musta 	if (accunits==0) {
472372ac97cdSTom Musta 	  accdigits++;			     /* at least one */
472472ac97cdSTom Musta 	  for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++;
472572ac97cdSTom Musta 	  }
472672ac97cdSTom Musta 	 else accdigits+=DECDPUN;
472772ac97cdSTom Musta 	accunits++;			     /* update count */
472872ac97cdSTom Musta 	accnext--;			     /* ready for next */
472972ac97cdSTom Musta 	if (accdigits>reqdigits) break;	     /* have enough digits */
473072ac97cdSTom Musta 	}
473172ac97cdSTom Musta 
473272ac97cdSTom Musta       /* if the residue is zero, the operation is done (unless divide */
473372ac97cdSTom Musta       /* or divideInteger and still not enough digits yet) */
473472ac97cdSTom Musta       if (*var1==0 && var1units==1) {	     /* residue is 0 */
473572ac97cdSTom Musta 	if (op&(REMAINDER|REMNEAR)) break;
473672ac97cdSTom Musta 	if ((op&DIVIDE) && (exponent<=maxexponent)) break;
473772ac97cdSTom Musta 	/* [drop through if divideInteger] */
473872ac97cdSTom Musta 	}
473972ac97cdSTom Musta       /* also done enough if calculating remainder or integer */
474072ac97cdSTom Musta       /* divide and just did the last ('units') unit */
474172ac97cdSTom Musta       if (exponent==0 && !(op&DIVIDE)) break;
474272ac97cdSTom Musta 
474372ac97cdSTom Musta       /* to get here, var1 is less than var2, so divide var2 by the per- */
474472ac97cdSTom Musta       /* Unit power of ten and go for the next digit */
474572ac97cdSTom Musta       var2ulen--;			     /* shift down */
474672ac97cdSTom Musta       exponent-=DECDPUN;		     /* update the exponent */
474772ac97cdSTom Musta       } /* outer loop */
474872ac97cdSTom Musta 
474972ac97cdSTom Musta     /* ---- division is complete --------------------------------------- */
475072ac97cdSTom Musta     /* here: acc      has at least reqdigits+1 of good results (or fewer */
475172ac97cdSTom Musta     /*		      if early stop), starting at accnext+1 (its lsu) */
475272ac97cdSTom Musta     /*	     var1     has any residue at the stopping point */
475372ac97cdSTom Musta     /*	     accunits is the number of digits collected in acc */
475472ac97cdSTom Musta     if (accunits==0) {		   /* acc is 0 */
475572ac97cdSTom Musta       accunits=1;		   /* show have a unit .. */
475672ac97cdSTom Musta       accdigits=1;		   /* .. */
475772ac97cdSTom Musta       *accnext=0;		   /* .. whose value is 0 */
475872ac97cdSTom Musta       }
475972ac97cdSTom Musta      else accnext++;		   /* back to last placed */
476072ac97cdSTom Musta     /* accnext now -> lowest unit of result */
476172ac97cdSTom Musta 
476272ac97cdSTom Musta     residue=0;			   /* assume no residue */
476372ac97cdSTom Musta     if (op&DIVIDE) {
476472ac97cdSTom Musta       /* record the presence of any residue, for rounding */
476572ac97cdSTom Musta       if (*var1!=0 || var1units>1) residue=1;
476672ac97cdSTom Musta        else { /* no residue */
476772ac97cdSTom Musta 	/* Had an exact division; clean up spurious trailing 0s. */
476872ac97cdSTom Musta 	/* There will be at most DECDPUN-1, from the final multiply, */
476972ac97cdSTom Musta 	/* and then only if the result is non-0 (and even) and the */
477072ac97cdSTom Musta 	/* exponent is 'loose'. */
477172ac97cdSTom Musta 	#if DECDPUN>1
477272ac97cdSTom Musta 	Unit lsu=*accnext;
477372ac97cdSTom Musta 	if (!(lsu&0x01) && (lsu!=0)) {
477472ac97cdSTom Musta 	  /* count the trailing zeros */
477572ac97cdSTom Musta 	  Int drop=0;
477672ac97cdSTom Musta 	  for (;; drop++) {    /* [will terminate because lsu!=0] */
477772ac97cdSTom Musta 	    if (exponent>=maxexponent) break;	  /* don't chop real 0s */
477872ac97cdSTom Musta 	    #if DECDPUN<=4
477972ac97cdSTom Musta 	      if ((lsu-QUOT10(lsu, drop+1)
478072ac97cdSTom Musta 		  *powers[drop+1])!=0) break;	  /* found non-0 digit */
478172ac97cdSTom Musta 	    #else
478272ac97cdSTom Musta 	      if (lsu%powers[drop+1]!=0) break;	  /* found non-0 digit */
478372ac97cdSTom Musta 	    #endif
478472ac97cdSTom Musta 	    exponent++;
478572ac97cdSTom Musta 	    }
478672ac97cdSTom Musta 	  if (drop>0) {
478772ac97cdSTom Musta 	    accunits=decShiftToLeast(accnext, accunits, drop);
478872ac97cdSTom Musta 	    accdigits=decGetDigits(accnext, accunits);
478972ac97cdSTom Musta 	    accunits=D2U(accdigits);
479072ac97cdSTom Musta 	    /* [exponent was adjusted in the loop] */
479172ac97cdSTom Musta 	    }
479272ac97cdSTom Musta 	  } /* neither odd nor 0 */
479372ac97cdSTom Musta 	#endif
479472ac97cdSTom Musta 	} /* exact divide */
479572ac97cdSTom Musta       } /* divide */
479672ac97cdSTom Musta      else /* op!=DIVIDE */ {
479772ac97cdSTom Musta       /* check for coefficient overflow */
479872ac97cdSTom Musta       if (accdigits+exponent>reqdigits) {
479972ac97cdSTom Musta 	*status|=DEC_Division_impossible;
480072ac97cdSTom Musta 	break;
480172ac97cdSTom Musta 	}
480272ac97cdSTom Musta       if (op & (REMAINDER|REMNEAR)) {
480372ac97cdSTom Musta 	/* [Here, the exponent will be 0, because var1 was adjusted */
480472ac97cdSTom Musta 	/* appropriately.] */
480572ac97cdSTom Musta 	Int postshift;			     /* work */
480672ac97cdSTom Musta 	Flag wasodd=0;			     /* integer was odd */
480772ac97cdSTom Musta 	Unit *quotlsu;			     /* for save */
480872ac97cdSTom Musta 	Int  quotdigits;		     /* .. */
480972ac97cdSTom Musta 
481072ac97cdSTom Musta 	bits=lhs->bits;			     /* remainder sign is always as lhs */
481172ac97cdSTom Musta 
481272ac97cdSTom Musta 	/* Fastpath when residue is truly 0 is worthwhile [and */
481372ac97cdSTom Musta 	/* simplifies the code below] */
481472ac97cdSTom Musta 	if (*var1==0 && var1units==1) {	     /* residue is 0 */
481572ac97cdSTom Musta 	  Int exp=lhs->exponent;	     /* save min(exponents) */
481672ac97cdSTom Musta 	  if (rhs->exponent<exp) exp=rhs->exponent;
481772ac97cdSTom Musta 	  decNumberZero(res);		     /* 0 coefficient */
481872ac97cdSTom Musta 	  #if DECSUBSET
481972ac97cdSTom Musta 	  if (set->extended)
482072ac97cdSTom Musta 	  #endif
482172ac97cdSTom Musta 	  res->exponent=exp;		     /* .. with proper exponent */
482272ac97cdSTom Musta 	  res->bits=(uByte)(bits&DECNEG);	   /* [cleaned] */
482372ac97cdSTom Musta 	  decFinish(res, set, &residue, status);   /* might clamp */
482472ac97cdSTom Musta 	  break;
482572ac97cdSTom Musta 	  }
482672ac97cdSTom Musta 	/* note if the quotient was odd */
482772ac97cdSTom Musta 	if (*accnext & 0x01) wasodd=1;	     /* acc is odd */
482872ac97cdSTom Musta 	quotlsu=accnext;		     /* save in case need to reinspect */
482972ac97cdSTom Musta 	quotdigits=accdigits;		     /* .. */
483072ac97cdSTom Musta 
483172ac97cdSTom Musta 	/* treat the residue, in var1, as the value to return, via acc */
483272ac97cdSTom Musta 	/* calculate the unused zero digits.  This is the smaller of: */
483372ac97cdSTom Musta 	/*   var1 initial padding (saved above) */
483472ac97cdSTom Musta 	/*   var2 residual padding, which happens to be given by: */
483572ac97cdSTom Musta 	postshift=var1initpad+exponent-lhs->exponent+rhs->exponent;
483672ac97cdSTom Musta 	/* [the 'exponent' term accounts for the shifts during divide] */
483772ac97cdSTom Musta 	if (var1initpad<postshift) postshift=var1initpad;
483872ac97cdSTom Musta 
483972ac97cdSTom Musta 	/* shift var1 the requested amount, and adjust its digits */
484072ac97cdSTom Musta 	var1units=decShiftToLeast(var1, var1units, postshift);
484172ac97cdSTom Musta 	accnext=var1;
484272ac97cdSTom Musta 	accdigits=decGetDigits(var1, var1units);
484372ac97cdSTom Musta 	accunits=D2U(accdigits);
484472ac97cdSTom Musta 
484572ac97cdSTom Musta 	exponent=lhs->exponent;		/* exponent is smaller of lhs & rhs */
484672ac97cdSTom Musta 	if (rhs->exponent<exponent) exponent=rhs->exponent;
484772ac97cdSTom Musta 
484872ac97cdSTom Musta 	/* Now correct the result if doing remainderNear; if it */
484972ac97cdSTom Musta 	/* (looking just at coefficients) is > rhs/2, or == rhs/2 and */
485072ac97cdSTom Musta 	/* the integer was odd then the result should be rem-rhs. */
485172ac97cdSTom Musta 	if (op&REMNEAR) {
485272ac97cdSTom Musta 	  Int compare, tarunits;	/* work */
485372ac97cdSTom Musta 	  Unit *up;			/* .. */
485472ac97cdSTom Musta 	  /* calculate remainder*2 into the var1 buffer (which has */
485572ac97cdSTom Musta 	  /* 'headroom' of an extra unit and hence enough space) */
485672ac97cdSTom Musta 	  /* [a dedicated 'double' loop would be faster, here] */
485772ac97cdSTom Musta 	  tarunits=decUnitAddSub(accnext, accunits, accnext, accunits,
485872ac97cdSTom Musta 				 0, accnext, 1);
485972ac97cdSTom Musta 	  /* decDumpAr('r', accnext, tarunits); */
486072ac97cdSTom Musta 
486172ac97cdSTom Musta 	  /* Here, accnext (var1) holds tarunits Units with twice the */
486272ac97cdSTom Musta 	  /* remainder's coefficient, which must now be compared to the */
486372ac97cdSTom Musta 	  /* RHS.  The remainder's exponent may be smaller than the RHS's. */
486472ac97cdSTom Musta 	  compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits),
486572ac97cdSTom Musta 				 rhs->exponent-exponent);
486672ac97cdSTom Musta 	  if (compare==BADINT) {	     /* deep trouble */
486772ac97cdSTom Musta 	    *status|=DEC_Insufficient_storage;
486872ac97cdSTom Musta 	    break;}
486972ac97cdSTom Musta 
487072ac97cdSTom Musta 	  /* now restore the remainder by dividing by two; the lsu */
487172ac97cdSTom Musta 	  /* is known to be even. */
487272ac97cdSTom Musta 	  for (up=accnext; up<accnext+tarunits; up++) {
487372ac97cdSTom Musta 	    Int half;		   /* half to add to lower unit */
487472ac97cdSTom Musta 	    half=*up & 0x01;
487572ac97cdSTom Musta 	    *up/=2;		   /* [shift] */
487672ac97cdSTom Musta 	    if (!half) continue;
48776402cbbbSMarc-André Lureau 	    *(up-1)+=DIV_ROUND_UP(DECDPUNMAX, 2);
487872ac97cdSTom Musta 	    }
487972ac97cdSTom Musta 	  /* [accunits still describes the original remainder length] */
488072ac97cdSTom Musta 
488172ac97cdSTom Musta 	  if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */
488272ac97cdSTom Musta 	    Int exp, expunits, exprem;	     /* work */
488372ac97cdSTom Musta 	    /* This is effectively causing round-up of the quotient, */
488472ac97cdSTom Musta 	    /* so if it was the rare case where it was full and all */
488572ac97cdSTom Musta 	    /* nines, it would overflow and hence division-impossible */
488672ac97cdSTom Musta 	    /* should be raised */
488772ac97cdSTom Musta 	    Flag allnines=0;		     /* 1 if quotient all nines */
488872ac97cdSTom Musta 	    if (quotdigits==reqdigits) {     /* could be borderline */
488972ac97cdSTom Musta 	      for (up=quotlsu; ; up++) {
489072ac97cdSTom Musta 		if (quotdigits>DECDPUN) {
489172ac97cdSTom Musta 		  if (*up!=DECDPUNMAX) break;/* non-nines */
489272ac97cdSTom Musta 		  }
489372ac97cdSTom Musta 		 else {			     /* this is the last Unit */
489472ac97cdSTom Musta 		  if (*up==powers[quotdigits]-1) allnines=1;
489572ac97cdSTom Musta 		  break;
489672ac97cdSTom Musta 		  }
489772ac97cdSTom Musta 		quotdigits-=DECDPUN;	     /* checked those digits */
489872ac97cdSTom Musta 		} /* up */
489972ac97cdSTom Musta 	      } /* borderline check */
490072ac97cdSTom Musta 	    if (allnines) {
490172ac97cdSTom Musta 	      *status|=DEC_Division_impossible;
490272ac97cdSTom Musta 	      break;}
490372ac97cdSTom Musta 
490472ac97cdSTom Musta 	    /* rem-rhs is needed; the sign will invert.	 Again, var1 */
490572ac97cdSTom Musta 	    /* can safely be used for the working Units array. */
490672ac97cdSTom Musta 	    exp=rhs->exponent-exponent;	     /* RHS padding needed */
490772ac97cdSTom Musta 	    /* Calculate units and remainder from exponent. */
490872ac97cdSTom Musta 	    expunits=exp/DECDPUN;
490972ac97cdSTom Musta 	    exprem=exp%DECDPUN;
491072ac97cdSTom Musta 	    /* subtract [A+B*(-m)]; the result will always be negative */
491172ac97cdSTom Musta 	    accunits=-decUnitAddSub(accnext, accunits,
491272ac97cdSTom Musta 				    rhs->lsu, D2U(rhs->digits),
491372ac97cdSTom Musta 				    expunits, accnext, -(Int)powers[exprem]);
491472ac97cdSTom Musta 	    accdigits=decGetDigits(accnext, accunits); /* count digits exactly */
491572ac97cdSTom Musta 	    accunits=D2U(accdigits);	/* and recalculate the units for copy */
491672ac97cdSTom Musta 	    /* [exponent is as for original remainder] */
491772ac97cdSTom Musta 	    bits^=DECNEG;		/* flip the sign */
491872ac97cdSTom Musta 	    }
491972ac97cdSTom Musta 	  } /* REMNEAR */
492072ac97cdSTom Musta 	} /* REMAINDER or REMNEAR */
492172ac97cdSTom Musta       } /* not DIVIDE */
492272ac97cdSTom Musta 
492372ac97cdSTom Musta     /* Set exponent and bits */
492472ac97cdSTom Musta     res->exponent=exponent;
492572ac97cdSTom Musta     res->bits=(uByte)(bits&DECNEG);	     /* [cleaned] */
492672ac97cdSTom Musta 
492772ac97cdSTom Musta     /* Now the coefficient. */
492872ac97cdSTom Musta     decSetCoeff(res, set, accnext, accdigits, &residue, status);
492972ac97cdSTom Musta 
493072ac97cdSTom Musta     decFinish(res, set, &residue, status);   /* final cleanup */
493172ac97cdSTom Musta 
493272ac97cdSTom Musta     #if DECSUBSET
493372ac97cdSTom Musta     /* If a divide then strip trailing zeros if subset [after round] */
493472ac97cdSTom Musta     if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, &dropped);
493572ac97cdSTom Musta     #endif
493672ac97cdSTom Musta     } while(0);				     /* end protected */
493772ac97cdSTom Musta 
493872ac97cdSTom Musta   if (varalloc!=NULL) free(varalloc);	/* drop any storage used */
493972ac97cdSTom Musta   if (allocacc!=NULL) free(allocacc);	/* .. */
494072ac97cdSTom Musta   #if DECSUBSET
494172ac97cdSTom Musta   if (allocrhs!=NULL) free(allocrhs);	/* .. */
494272ac97cdSTom Musta   if (alloclhs!=NULL) free(alloclhs);	/* .. */
494372ac97cdSTom Musta   #endif
494472ac97cdSTom Musta   return res;
494572ac97cdSTom Musta   } /* decDivideOp */
494672ac97cdSTom Musta 
494772ac97cdSTom Musta /* ------------------------------------------------------------------ */
494872ac97cdSTom Musta /* decMultiplyOp -- multiplication operation			      */
494972ac97cdSTom Musta /*								      */
495072ac97cdSTom Musta /*  This routine performs the multiplication C=A x B.		      */
495172ac97cdSTom Musta /*								      */
495272ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X*X)	      */
495372ac97cdSTom Musta /*   lhs is A							      */
495472ac97cdSTom Musta /*   rhs is B							      */
495572ac97cdSTom Musta /*   set is the context						      */
495672ac97cdSTom Musta /*   status is the usual accumulator				      */
495772ac97cdSTom Musta /*								      */
495872ac97cdSTom Musta /* C must have space for set->digits digits.			      */
495972ac97cdSTom Musta /*								      */
496072ac97cdSTom Musta /* ------------------------------------------------------------------ */
496172ac97cdSTom Musta /* 'Classic' multiplication is used rather than Karatsuba, as the     */
496272ac97cdSTom Musta /* latter would give only a minor improvement for the short numbers   */
496372ac97cdSTom Musta /* expected to be handled most (and uses much more memory).	      */
496472ac97cdSTom Musta /*								      */
496572ac97cdSTom Musta /* There are two major paths here: the general-purpose ('old code')   */
496672ac97cdSTom Musta /* path which handles all DECDPUN values, and a fastpath version      */
496772ac97cdSTom Musta /* which is used if 64-bit ints are available, DECDPUN<=4, and more   */
496872ac97cdSTom Musta /* than two calls to decUnitAddSub would be made.		      */
496972ac97cdSTom Musta /*								      */
497072ac97cdSTom Musta /* The fastpath version lumps units together into 8-digit or 9-digit  */
497172ac97cdSTom Musta /* chunks, and also uses a lazy carry strategy to minimise expensive  */
497272ac97cdSTom Musta /* 64-bit divisions.  The chunks are then broken apart again into     */
497372ac97cdSTom Musta /* units for continuing processing.  Despite this overhead, the	      */
497472ac97cdSTom Musta /* fastpath can speed up some 16-digit operations by 10x (and much    */
497572ac97cdSTom Musta /* more for higher-precision calculations).			      */
497672ac97cdSTom Musta /*								      */
497772ac97cdSTom Musta /* A buffer always has to be used for the accumulator; in the	      */
497872ac97cdSTom Musta /* fastpath, buffers are also always needed for the chunked copies of */
497972ac97cdSTom Musta /* of the operand coefficients.					      */
498072ac97cdSTom Musta /* Static buffers are larger than needed just for multiply, to allow  */
498172ac97cdSTom Musta /* for calls from other operations (notably exp).		      */
498272ac97cdSTom Musta /* ------------------------------------------------------------------ */
498372ac97cdSTom Musta #define FASTMUL (DECUSE64 && DECDPUN<5)
decMultiplyOp(decNumber * res,const decNumber * lhs,const decNumber * rhs,decContext * set,uInt * status)498472ac97cdSTom Musta static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs,
498572ac97cdSTom Musta 				 const decNumber *rhs, decContext *set,
498672ac97cdSTom Musta 				 uInt *status) {
498772ac97cdSTom Musta   Int	 accunits;		   /* Units of accumulator in use */
498872ac97cdSTom Musta   Int	 exponent;		   /* work */
498972ac97cdSTom Musta   Int	 residue=0;		   /* rounding residue */
499072ac97cdSTom Musta   uByte	 bits;			   /* result sign */
499172ac97cdSTom Musta   Unit	*acc;			   /* -> accumulator Unit array */
499272ac97cdSTom Musta   Int	 needbytes;		   /* size calculator */
499372ac97cdSTom Musta   void	*allocacc=NULL;		   /* -> allocated accumulator, iff allocated */
499472ac97cdSTom Musta   Unit	accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */
499572ac97cdSTom Musta 				   /* *4 for calls from other operations) */
499672ac97cdSTom Musta   const Unit *mer, *mermsup;	   /* work */
499772ac97cdSTom Musta   Int	madlength;		   /* Units in multiplicand */
499872ac97cdSTom Musta   Int	shift;			   /* Units to shift multiplicand by */
499972ac97cdSTom Musta 
500072ac97cdSTom Musta   #if FASTMUL
500172ac97cdSTom Musta     /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */
500272ac97cdSTom Musta     /* (DECDPUN is 2 or 4) then work in base 10**8 */
500372ac97cdSTom Musta     #if DECDPUN & 1		   /* odd */
500472ac97cdSTom Musta       #define FASTBASE 1000000000  /* base */
500572ac97cdSTom Musta       #define FASTDIGS		9  /* digits in base */
500672ac97cdSTom Musta       #define FASTLAZY	       18  /* carry resolution point [1->18] */
500772ac97cdSTom Musta     #else
500872ac97cdSTom Musta       #define FASTBASE	100000000
500972ac97cdSTom Musta       #define FASTDIGS		8
501072ac97cdSTom Musta       #define FASTLAZY	     1844  /* carry resolution point [1->1844] */
501172ac97cdSTom Musta     #endif
501272ac97cdSTom Musta     /* three buffers are used, two for chunked copies of the operands */
501372ac97cdSTom Musta     /* (base 10**8 or base 10**9) and one base 2**64 accumulator with */
501472ac97cdSTom Musta     /* lazy carry evaluation */
501572ac97cdSTom Musta     uInt   zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
501672ac97cdSTom Musta     uInt  *zlhi=zlhibuff;		  /* -> lhs array */
501772ac97cdSTom Musta     uInt  *alloclhi=NULL;		  /* -> allocated buffer, iff allocated */
501872ac97cdSTom Musta     uInt   zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
501972ac97cdSTom Musta     uInt  *zrhi=zrhibuff;		  /* -> rhs array */
502072ac97cdSTom Musta     uInt  *allocrhi=NULL;		  /* -> allocated buffer, iff allocated */
502172ac97cdSTom Musta     uLong  zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */
502272ac97cdSTom Musta     /* [allocacc is shared for both paths, as only one will run] */
502372ac97cdSTom Musta     uLong *zacc=zaccbuff;	   /* -> accumulator array for exact result */
502472ac97cdSTom Musta     #if DECDPUN==1
502572ac97cdSTom Musta     Int	   zoff;		   /* accumulator offset */
502672ac97cdSTom Musta     #endif
502772ac97cdSTom Musta     uInt  *lip, *rip;		   /* item pointers */
502872ac97cdSTom Musta     uInt  *lmsi, *rmsi;		   /* most significant items */
502972ac97cdSTom Musta     Int	   ilhs, irhs, iacc;	   /* item counts in the arrays */
503072ac97cdSTom Musta     Int	   lazy;		   /* lazy carry counter */
503172ac97cdSTom Musta     uLong  lcarry;		   /* uLong carry */
503272ac97cdSTom Musta     uInt   carry;		   /* carry (NB not uLong) */
503372ac97cdSTom Musta     Int	   count;		   /* work */
503472ac97cdSTom Musta     const  Unit *cup;		   /* .. */
503572ac97cdSTom Musta     Unit  *up;			   /* .. */
503672ac97cdSTom Musta     uLong *lp;			   /* .. */
503772ac97cdSTom Musta     Int	   p;			   /* .. */
503872ac97cdSTom Musta   #endif
503972ac97cdSTom Musta 
504072ac97cdSTom Musta   #if DECSUBSET
504172ac97cdSTom Musta     decNumber *alloclhs=NULL;	   /* -> allocated buffer, iff allocated */
504272ac97cdSTom Musta     decNumber *allocrhs=NULL;	   /* -> allocated buffer, iff allocated */
504372ac97cdSTom Musta   #endif
504472ac97cdSTom Musta 
504572ac97cdSTom Musta   #if DECCHECK
504672ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
504772ac97cdSTom Musta   #endif
504872ac97cdSTom Musta 
504972ac97cdSTom Musta   /* precalculate result sign */
505072ac97cdSTom Musta   bits=(uByte)((lhs->bits^rhs->bits)&DECNEG);
505172ac97cdSTom Musta 
505272ac97cdSTom Musta   /* handle infinities and NaNs */
505372ac97cdSTom Musta   if (SPECIALARGS) {		   /* a special bit set */
505472ac97cdSTom Musta     if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
505572ac97cdSTom Musta       decNaNs(res, lhs, rhs, set, status);
505672ac97cdSTom Musta       return res;}
505772ac97cdSTom Musta     /* one or two infinities; Infinity * 0 is invalid */
505872ac97cdSTom Musta     if (((lhs->bits & DECINF)==0 && ISZERO(lhs))
505972ac97cdSTom Musta       ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) {
506072ac97cdSTom Musta       *status|=DEC_Invalid_operation;
506172ac97cdSTom Musta       return res;}
506272ac97cdSTom Musta     decNumberZero(res);
506372ac97cdSTom Musta     res->bits=bits|DECINF;	   /* infinity */
506472ac97cdSTom Musta     return res;}
506572ac97cdSTom Musta 
506672ac97cdSTom Musta   /* For best speed, as in DMSRCN [the original Rexx numerics */
506772ac97cdSTom Musta   /* module], use the shorter number as the multiplier (rhs) and */
506872ac97cdSTom Musta   /* the longer as the multiplicand (lhs) to minimise the number of */
506972ac97cdSTom Musta   /* adds (partial products) */
507072ac97cdSTom Musta   if (lhs->digits<rhs->digits) {   /* swap... */
507172ac97cdSTom Musta     const decNumber *hold=lhs;
507272ac97cdSTom Musta     lhs=rhs;
507372ac97cdSTom Musta     rhs=hold;
507472ac97cdSTom Musta     }
507572ac97cdSTom Musta 
507672ac97cdSTom Musta   do {				   /* protect allocated storage */
507772ac97cdSTom Musta     #if DECSUBSET
507872ac97cdSTom Musta     if (!set->extended) {
507972ac97cdSTom Musta       /* reduce operands and set lostDigits status, as needed */
508072ac97cdSTom Musta       if (lhs->digits>set->digits) {
508172ac97cdSTom Musta 	alloclhs=decRoundOperand(lhs, set, status);
508272ac97cdSTom Musta 	if (alloclhs==NULL) break;
508372ac97cdSTom Musta 	lhs=alloclhs;
508472ac97cdSTom Musta 	}
508572ac97cdSTom Musta       if (rhs->digits>set->digits) {
508672ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, status);
508772ac97cdSTom Musta 	if (allocrhs==NULL) break;
508872ac97cdSTom Musta 	rhs=allocrhs;
508972ac97cdSTom Musta 	}
509072ac97cdSTom Musta       }
509172ac97cdSTom Musta     #endif
509272ac97cdSTom Musta     /* [following code does not require input rounding] */
509372ac97cdSTom Musta 
509472ac97cdSTom Musta     #if FASTMUL			   /* fastpath can be used */
509572ac97cdSTom Musta     /* use the fast path if there are enough digits in the shorter */
509672ac97cdSTom Musta     /* operand to make the setup and takedown worthwhile */
509772ac97cdSTom Musta     #define NEEDTWO (DECDPUN*2)	   /* within two decUnitAddSub calls */
509872ac97cdSTom Musta     if (rhs->digits>NEEDTWO) {	   /* use fastpath... */
509972ac97cdSTom Musta       /* calculate the number of elements in each array */
510072ac97cdSTom Musta       ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */
510172ac97cdSTom Musta       irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */
510272ac97cdSTom Musta       iacc=ilhs+irhs;
510372ac97cdSTom Musta 
510472ac97cdSTom Musta       /* allocate buffers if required, as usual */
510572ac97cdSTom Musta       needbytes=ilhs*sizeof(uInt);
510672ac97cdSTom Musta       if (needbytes>(Int)sizeof(zlhibuff)) {
510772ac97cdSTom Musta 	alloclhi=(uInt *)malloc(needbytes);
510872ac97cdSTom Musta 	zlhi=alloclhi;}
510972ac97cdSTom Musta       needbytes=irhs*sizeof(uInt);
511072ac97cdSTom Musta       if (needbytes>(Int)sizeof(zrhibuff)) {
511172ac97cdSTom Musta 	allocrhi=(uInt *)malloc(needbytes);
511272ac97cdSTom Musta 	zrhi=allocrhi;}
511372ac97cdSTom Musta 
511472ac97cdSTom Musta       /* Allocating the accumulator space needs a special case when */
511572ac97cdSTom Musta       /* DECDPUN=1 because when converting the accumulator to Units */
511672ac97cdSTom Musta       /* after the multiplication each 8-byte item becomes 9 1-byte */
511772ac97cdSTom Musta       /* units.	 Therefore iacc extra bytes are needed at the front */
511872ac97cdSTom Musta       /* (rounded up to a multiple of 8 bytes), and the uLong */
511972ac97cdSTom Musta       /* accumulator starts offset the appropriate number of units */
512072ac97cdSTom Musta       /* to the right to avoid overwrite during the unchunking. */
512172ac97cdSTom Musta       needbytes=iacc*sizeof(uLong);
512272ac97cdSTom Musta       #if DECDPUN==1
512372ac97cdSTom Musta       zoff=(iacc+7)/8;	      /* items to offset by */
512472ac97cdSTom Musta       needbytes+=zoff*8;
512572ac97cdSTom Musta       #endif
512672ac97cdSTom Musta       if (needbytes>(Int)sizeof(zaccbuff)) {
512772ac97cdSTom Musta 	allocacc=(uLong *)malloc(needbytes);
512872ac97cdSTom Musta 	zacc=(uLong *)allocacc;}
512972ac97cdSTom Musta       if (zlhi==NULL||zrhi==NULL||zacc==NULL) {
513072ac97cdSTom Musta 	*status|=DEC_Insufficient_storage;
513172ac97cdSTom Musta 	break;}
513272ac97cdSTom Musta 
513372ac97cdSTom Musta       acc=(Unit *)zacc;	      /* -> target Unit array */
513472ac97cdSTom Musta       #if DECDPUN==1
513572ac97cdSTom Musta       zacc+=zoff;	      /* start uLong accumulator to right */
513672ac97cdSTom Musta       #endif
513772ac97cdSTom Musta 
513872ac97cdSTom Musta       /* assemble the chunked copies of the left and right sides */
513972ac97cdSTom Musta       for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++)
514072ac97cdSTom Musta 	for (p=0, *lip=0; p<FASTDIGS && count>0;
514172ac97cdSTom Musta 	     p+=DECDPUN, cup++, count-=DECDPUN)
514272ac97cdSTom Musta 	  *lip+=*cup*powers[p];
514372ac97cdSTom Musta       lmsi=lip-1;     /* save -> msi */
514472ac97cdSTom Musta       for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++)
514572ac97cdSTom Musta 	for (p=0, *rip=0; p<FASTDIGS && count>0;
514672ac97cdSTom Musta 	     p+=DECDPUN, cup++, count-=DECDPUN)
514772ac97cdSTom Musta 	  *rip+=*cup*powers[p];
514872ac97cdSTom Musta       rmsi=rip-1;     /* save -> msi */
514972ac97cdSTom Musta 
515072ac97cdSTom Musta       /* zero the accumulator */
515172ac97cdSTom Musta       for (lp=zacc; lp<zacc+iacc; lp++) *lp=0;
515272ac97cdSTom Musta 
515372ac97cdSTom Musta       /* Start the multiplication */
515472ac97cdSTom Musta       /* Resolving carries can dominate the cost of accumulating the */
515572ac97cdSTom Musta       /* partial products, so this is only done when necessary. */
515672ac97cdSTom Musta       /* Each uLong item in the accumulator can hold values up to */
515772ac97cdSTom Musta       /* 2**64-1, and each partial product can be as large as */
515872ac97cdSTom Musta       /* (10**FASTDIGS-1)**2.  When FASTDIGS=9, this can be added to */
515972ac97cdSTom Musta       /* itself 18.4 times in a uLong without overflowing, so during */
516072ac97cdSTom Musta       /* the main calculation resolution is carried out every 18th */
516172ac97cdSTom Musta       /* add -- every 162 digits.  Similarly, when FASTDIGS=8, the */
516272ac97cdSTom Musta       /* partial products can be added to themselves 1844.6 times in */
516372ac97cdSTom Musta       /* a uLong without overflowing, so intermediate carry */
516472ac97cdSTom Musta       /* resolution occurs only every 14752 digits.  Hence for common */
516572ac97cdSTom Musta       /* short numbers usually only the one final carry resolution */
516672ac97cdSTom Musta       /* occurs. */
516772ac97cdSTom Musta       /* (The count is set via FASTLAZY to simplify experiments to */
516872ac97cdSTom Musta       /* measure the value of this approach: a 35% improvement on a */
516972ac97cdSTom Musta       /* [34x34] multiply.) */
517072ac97cdSTom Musta       lazy=FASTLAZY;			     /* carry delay count */
517172ac97cdSTom Musta       for (rip=zrhi; rip<=rmsi; rip++) {     /* over each item in rhs */
517272ac97cdSTom Musta 	lp=zacc+(rip-zrhi);		     /* where to add the lhs */
517372ac97cdSTom Musta 	for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */
517472ac97cdSTom Musta 	  *lp+=(uLong)(*lip)*(*rip);	     /* [this should in-line] */
517572ac97cdSTom Musta 	  } /* lip loop */
517672ac97cdSTom Musta 	lazy--;
517772ac97cdSTom Musta 	if (lazy>0 && rip!=rmsi) continue;
517872ac97cdSTom Musta 	lazy=FASTLAZY;			     /* reset delay count */
517972ac97cdSTom Musta 	/* spin up the accumulator resolving overflows */
518072ac97cdSTom Musta 	for (lp=zacc; lp<zacc+iacc; lp++) {
518172ac97cdSTom Musta 	  if (*lp<FASTBASE) continue;	     /* it fits */
518272ac97cdSTom Musta 	  lcarry=*lp/FASTBASE;		     /* top part [slow divide] */
518372ac97cdSTom Musta 	  /* lcarry can exceed 2**32-1, so check again; this check */
518472ac97cdSTom Musta 	  /* and occasional extra divide (slow) is well worth it, as */
518572ac97cdSTom Musta 	  /* it allows FASTLAZY to be increased to 18 rather than 4 */
518672ac97cdSTom Musta 	  /* in the FASTDIGS=9 case */
518772ac97cdSTom Musta 	  if (lcarry<FASTBASE) carry=(uInt)lcarry;  /* [usual] */
518872ac97cdSTom Musta 	   else { /* two-place carry [fairly rare] */
518972ac97cdSTom Musta 	    uInt carry2=(uInt)(lcarry/FASTBASE);    /* top top part */
519072ac97cdSTom Musta 	    *(lp+2)+=carry2;			    /* add to item+2 */
519172ac97cdSTom Musta 	    *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */
519272ac97cdSTom Musta 	    carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */
519372ac97cdSTom Musta 	    }
519472ac97cdSTom Musta 	  *(lp+1)+=carry;		     /* add to item above [inline] */
519572ac97cdSTom Musta 	  *lp-=((uLong)FASTBASE*carry);	     /* [inline] */
519672ac97cdSTom Musta 	  } /* carry resolution */
519772ac97cdSTom Musta 	} /* rip loop */
519872ac97cdSTom Musta 
519972ac97cdSTom Musta       /* The multiplication is complete; time to convert back into */
520072ac97cdSTom Musta       /* units.	 This can be done in-place in the accumulator and in */
520172ac97cdSTom Musta       /* 32-bit operations, because carries were resolved after the */
520272ac97cdSTom Musta       /* final add.  This needs N-1 divides and multiplies for */
520372ac97cdSTom Musta       /* each item in the accumulator (which will become up to N */
520472ac97cdSTom Musta       /* units, where 2<=N<=9). */
520572ac97cdSTom Musta       for (lp=zacc, up=acc; lp<zacc+iacc; lp++) {
520672ac97cdSTom Musta 	uInt item=(uInt)*lp;		     /* decapitate to uInt */
520772ac97cdSTom Musta 	for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) {
520872ac97cdSTom Musta 	  uInt part=item/(DECDPUNMAX+1);
520972ac97cdSTom Musta 	  *up=(Unit)(item-(part*(DECDPUNMAX+1)));
521072ac97cdSTom Musta 	  item=part;
521172ac97cdSTom Musta 	  } /* p */
521272ac97cdSTom Musta 	*up=(Unit)item; up++;		     /* [final needs no division] */
521372ac97cdSTom Musta 	} /* lp */
521472ac97cdSTom Musta       accunits=up-acc;			     /* count of units */
521572ac97cdSTom Musta       }
521672ac97cdSTom Musta      else { /* here to use units directly, without chunking ['old code'] */
521772ac97cdSTom Musta     #endif
521872ac97cdSTom Musta 
521972ac97cdSTom Musta       /* if accumulator will be too long for local storage, then allocate */
522072ac97cdSTom Musta       acc=accbuff;		   /* -> assume buffer for accumulator */
522172ac97cdSTom Musta       needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit);
522272ac97cdSTom Musta       if (needbytes>(Int)sizeof(accbuff)) {
522372ac97cdSTom Musta 	allocacc=(Unit *)malloc(needbytes);
522472ac97cdSTom Musta 	if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;}
522572ac97cdSTom Musta 	acc=(Unit *)allocacc;		     /* use the allocated space */
522672ac97cdSTom Musta 	}
522772ac97cdSTom Musta 
522872ac97cdSTom Musta       /* Now the main long multiplication loop */
522972ac97cdSTom Musta       /* Unlike the equivalent in the IBM Java implementation, there */
523072ac97cdSTom Musta       /* is no advantage in calculating from msu to lsu.  So, do it */
523172ac97cdSTom Musta       /* by the book, as it were. */
523272ac97cdSTom Musta       /* Each iteration calculates ACC=ACC+MULTAND*MULT */
523372ac97cdSTom Musta       accunits=1;		   /* accumulator starts at '0' */
523472ac97cdSTom Musta       *acc=0;			   /* .. (lsu=0) */
523572ac97cdSTom Musta       shift=0;			   /* no multiplicand shift at first */
523672ac97cdSTom Musta       madlength=D2U(lhs->digits);  /* this won't change */
523772ac97cdSTom Musta       mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */
523872ac97cdSTom Musta 
523972ac97cdSTom Musta       for (mer=rhs->lsu; mer<mermsup; mer++) {
524072ac97cdSTom Musta 	/* Here, *mer is the next Unit in the multiplier to use */
524172ac97cdSTom Musta 	/* If non-zero [optimization] add it... */
524272ac97cdSTom Musta 	if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift,
524372ac97cdSTom Musta 					    lhs->lsu, madlength, 0,
524472ac97cdSTom Musta 					    &acc[shift], *mer)
524572ac97cdSTom Musta 					    + shift;
524672ac97cdSTom Musta 	 else { /* extend acc with a 0; it will be used shortly */
524772ac97cdSTom Musta 	  *(acc+accunits)=0;	   /* [this avoids length of <=0 later] */
524872ac97cdSTom Musta 	  accunits++;
524972ac97cdSTom Musta 	  }
525072ac97cdSTom Musta 	/* multiply multiplicand by 10**DECDPUN for next Unit to left */
525172ac97cdSTom Musta 	shift++;		   /* add this for 'logical length' */
525272ac97cdSTom Musta 	} /* n */
525372ac97cdSTom Musta     #if FASTMUL
525472ac97cdSTom Musta       } /* unchunked units */
525572ac97cdSTom Musta     #endif
525672ac97cdSTom Musta     /* common end-path */
525772ac97cdSTom Musta     #if DECTRACE
525872ac97cdSTom Musta       decDumpAr('*', acc, accunits);	     /* Show exact result */
525972ac97cdSTom Musta     #endif
526072ac97cdSTom Musta 
526172ac97cdSTom Musta     /* acc now contains the exact result of the multiplication, */
526272ac97cdSTom Musta     /* possibly with a leading zero unit; build the decNumber from */
526372ac97cdSTom Musta     /* it, noting if any residue */
526472ac97cdSTom Musta     res->bits=bits;			     /* set sign */
526572ac97cdSTom Musta     res->digits=decGetDigits(acc, accunits); /* count digits exactly */
526672ac97cdSTom Musta 
526772ac97cdSTom Musta     /* There can be a 31-bit wrap in calculating the exponent. */
526872ac97cdSTom Musta     /* This can only happen if both input exponents are negative and */
526972ac97cdSTom Musta     /* both their magnitudes are large.	 If there was a wrap, set a */
527072ac97cdSTom Musta     /* safe very negative exponent, from which decFinalize() will */
527172ac97cdSTom Musta     /* raise a hard underflow shortly. */
527272ac97cdSTom Musta     exponent=lhs->exponent+rhs->exponent;    /* calculate exponent */
527372ac97cdSTom Musta     if (lhs->exponent<0 && rhs->exponent<0 && exponent>0)
527472ac97cdSTom Musta       exponent=-2*DECNUMMAXE;		     /* force underflow */
527572ac97cdSTom Musta     res->exponent=exponent;		     /* OK to overwrite now */
527672ac97cdSTom Musta 
527772ac97cdSTom Musta 
527872ac97cdSTom Musta     /* Set the coefficient.  If any rounding, residue records */
527972ac97cdSTom Musta     decSetCoeff(res, set, acc, res->digits, &residue, status);
528072ac97cdSTom Musta     decFinish(res, set, &residue, status);   /* final cleanup */
528172ac97cdSTom Musta     } while(0);				/* end protected */
528272ac97cdSTom Musta 
528372ac97cdSTom Musta   if (allocacc!=NULL) free(allocacc);	/* drop any storage used */
528472ac97cdSTom Musta   #if DECSUBSET
528572ac97cdSTom Musta   if (allocrhs!=NULL) free(allocrhs);	/* .. */
528672ac97cdSTom Musta   if (alloclhs!=NULL) free(alloclhs);	/* .. */
528772ac97cdSTom Musta   #endif
528872ac97cdSTom Musta   #if FASTMUL
528972ac97cdSTom Musta   if (allocrhi!=NULL) free(allocrhi);	/* .. */
529072ac97cdSTom Musta   if (alloclhi!=NULL) free(alloclhi);	/* .. */
529172ac97cdSTom Musta   #endif
529272ac97cdSTom Musta   return res;
529372ac97cdSTom Musta   } /* decMultiplyOp */
529472ac97cdSTom Musta 
529572ac97cdSTom Musta /* ------------------------------------------------------------------ */
529672ac97cdSTom Musta /* decExpOp -- effect exponentiation				      */
529772ac97cdSTom Musta /*								      */
529872ac97cdSTom Musta /*   This computes C = exp(A)					      */
529972ac97cdSTom Musta /*								      */
530072ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
530172ac97cdSTom Musta /*   rhs is A							      */
530272ac97cdSTom Musta /*   set is the context; note that rounding mode has no effect	      */
530372ac97cdSTom Musta /*								      */
530472ac97cdSTom Musta /* C must have space for set->digits digits. status is updated but    */
530572ac97cdSTom Musta /* not set.							      */
530672ac97cdSTom Musta /*								      */
530772ac97cdSTom Musta /* Restrictions:						      */
530872ac97cdSTom Musta /*								      */
530972ac97cdSTom Musta /*   digits, emax, and -emin in the context must be less than	      */
531072ac97cdSTom Musta /*   2*DEC_MAX_MATH (1999998), and the rhs must be within these	      */
531172ac97cdSTom Musta /*   bounds or a zero.	This is an internal routine, so these	      */
531272ac97cdSTom Musta /*   restrictions are contractual and not enforced.		      */
531372ac97cdSTom Musta /*								      */
531472ac97cdSTom Musta /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will      */
531572ac97cdSTom Musta /* almost always be correctly rounded, but may be up to 1 ulp in      */
531672ac97cdSTom Musta /* error in rare cases.						      */
531772ac97cdSTom Musta /*								      */
531872ac97cdSTom Musta /* Finite results will always be full precision and Inexact, except   */
531972ac97cdSTom Musta /* when A is a zero or -Infinity (giving 1 or 0 respectively).	      */
532072ac97cdSTom Musta /* ------------------------------------------------------------------ */
532172ac97cdSTom Musta /* This approach used here is similar to the algorithm described in   */
532272ac97cdSTom Musta /*								      */
532372ac97cdSTom Musta /*   Variable Precision Exponential Function, T. E. Hull and	      */
532472ac97cdSTom Musta /*   A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */
532572ac97cdSTom Musta /*   pp79-91, ACM, June 1986.					      */
532672ac97cdSTom Musta /*								      */
532772ac97cdSTom Musta /* with the main difference being that the iterations in the series   */
532872ac97cdSTom Musta /* evaluation are terminated dynamically (which does not require the  */
532972ac97cdSTom Musta /* extra variable-precision variables which are expensive in this     */
533072ac97cdSTom Musta /* context).							      */
533172ac97cdSTom Musta /*								      */
533272ac97cdSTom Musta /* The error analysis in Hull & Abrham's paper applies except for the */
533372ac97cdSTom Musta /* round-off error accumulation during the series evaluation.  This   */
533472ac97cdSTom Musta /* code does not precalculate the number of iterations and so cannot  */
533572ac97cdSTom Musta /* use Horner's scheme.	 Instead, the accumulation is done at double- */
533672ac97cdSTom Musta /* precision, which ensures that the additions of the terms are exact */
533772ac97cdSTom Musta /* and do not accumulate round-off (and any round-off errors in the   */
533872ac97cdSTom Musta /* terms themselves move 'to the right' faster than they can	      */
533972ac97cdSTom Musta /* accumulate).	 This code also extends the calculation by allowing,  */
534072ac97cdSTom Musta /* in the spirit of other decNumber operators, the input to be more   */
534172ac97cdSTom Musta /* precise than the result (the precision used is based on the more   */
534272ac97cdSTom Musta /* precise of the input or requested result).			      */
534372ac97cdSTom Musta /*								      */
534472ac97cdSTom Musta /* Implementation notes:					      */
534572ac97cdSTom Musta /*								      */
534672ac97cdSTom Musta /* 1. This is separated out as decExpOp so it can be called from      */
534772ac97cdSTom Musta /*    other Mathematical functions (notably Ln) with a wider range    */
534872ac97cdSTom Musta /*    than normal.  In particular, it can handle the slightly wider   */
534972ac97cdSTom Musta /*    (double) range needed by Ln (which has to be able to calculate  */
535072ac97cdSTom Musta /*    exp(-x) where x can be the tiniest number (Ntiny).	      */
535172ac97cdSTom Musta /*								      */
535272ac97cdSTom Musta /* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop	      */
535367cc32ebSVeres Lajos /*    iterations by approximately a third with additional (although    */
535472ac97cdSTom Musta /*    diminishing) returns as the range is reduced to even smaller    */
535572ac97cdSTom Musta /*    fractions.  However, h (the power of 10 used to correct the     */
535672ac97cdSTom Musta /*    result at the end, see below) must be kept <=8 as otherwise     */
535772ac97cdSTom Musta /*    the final result cannot be computed.  Hence the leverage is a   */
535872ac97cdSTom Musta /*    sliding value (8-h), where potentially the range is reduced     */
535972ac97cdSTom Musta /*    more for smaller values.					      */
536072ac97cdSTom Musta /*								      */
536172ac97cdSTom Musta /*    The leverage that can be applied in this way is severely	      */
536272ac97cdSTom Musta /*    limited by the cost of the raise-to-the power at the end,	      */
536372ac97cdSTom Musta /*    which dominates when the number of iterations is small (less    */
536472ac97cdSTom Musta /*    than ten) or when rhs is short.  As an example, the adjustment  */
536572ac97cdSTom Musta /*    x**10,000,000 needs 31 multiplications, all but one full-width. */
536672ac97cdSTom Musta /*								      */
536772ac97cdSTom Musta /* 3. The restrictions (especially precision) could be raised with    */
536872ac97cdSTom Musta /*    care, but the full decNumber range seems very hard within the   */
536972ac97cdSTom Musta /*    32-bit limits.						      */
537072ac97cdSTom Musta /*								      */
537172ac97cdSTom Musta /* 4. The working precisions for the static buffers are twice the     */
537272ac97cdSTom Musta /*    obvious size to allow for calls from decNumberPower.	      */
537372ac97cdSTom Musta /* ------------------------------------------------------------------ */
decExpOp(decNumber * res,const decNumber * rhs,decContext * set,uInt * status)5374d072cdf3SStefan Weil static decNumber *decExpOp(decNumber *res, const decNumber *rhs,
537572ac97cdSTom Musta                            decContext *set, uInt *status) {
537672ac97cdSTom Musta   uInt ignore=0;		   /* working status */
537772ac97cdSTom Musta   Int h;			   /* adjusted exponent for 0.xxxx */
537872ac97cdSTom Musta   Int p;			   /* working precision */
537972ac97cdSTom Musta   Int residue;			   /* rounding residue */
538072ac97cdSTom Musta   uInt needbytes;		   /* for space calculations */
538172ac97cdSTom Musta   const decNumber *x=rhs;	   /* (may point to safe copy later) */
538272ac97cdSTom Musta   decContext aset, tset, dset;	   /* working contexts */
538372ac97cdSTom Musta   Int comp;			   /* work */
538472ac97cdSTom Musta 
538572ac97cdSTom Musta   /* the argument is often copied to normalize it, so (unusually) it */
538672ac97cdSTom Musta   /* is treated like other buffers, using DECBUFFER, +1 in case */
538772ac97cdSTom Musta   /* DECBUFFER is 0 */
538872ac97cdSTom Musta   decNumber bufr[D2N(DECBUFFER*2+1)];
538972ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* non-NULL if rhs buffer allocated */
539072ac97cdSTom Musta 
539172ac97cdSTom Musta   /* the working precision will be no more than set->digits+8+1 */
539272ac97cdSTom Musta   /* so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER */
539372ac97cdSTom Musta   /* is 0 (and twice that for the accumulator) */
539472ac97cdSTom Musta 
539572ac97cdSTom Musta   /* buffer for t, term (working precision plus) */
539672ac97cdSTom Musta   decNumber buft[D2N(DECBUFFER*2+9+1)];
539772ac97cdSTom Musta   decNumber *allocbuft=NULL;	   /* -> allocated buft, iff allocated */
539872ac97cdSTom Musta   decNumber *t=buft;		   /* term */
539972ac97cdSTom Musta   /* buffer for a, accumulator (working precision * 2), at least 9 */
540072ac97cdSTom Musta   decNumber bufa[D2N(DECBUFFER*4+18+1)];
540172ac97cdSTom Musta   decNumber *allocbufa=NULL;	   /* -> allocated bufa, iff allocated */
540272ac97cdSTom Musta   decNumber *a=bufa;		   /* accumulator */
540372ac97cdSTom Musta   /* decNumber for the divisor term; this needs at most 9 digits */
540472ac97cdSTom Musta   /* and so can be fixed size [16 so can use standard context] */
540572ac97cdSTom Musta   decNumber bufd[D2N(16)];
540672ac97cdSTom Musta   decNumber *d=bufd;		   /* divisor */
540772ac97cdSTom Musta   decNumber numone;		   /* constant 1 */
540872ac97cdSTom Musta 
540972ac97cdSTom Musta   #if DECCHECK
541072ac97cdSTom Musta   Int iterations=0;		   /* for later sanity check */
541172ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
541272ac97cdSTom Musta   #endif
541372ac97cdSTom Musta 
541472ac97cdSTom Musta   do {					/* protect allocated storage */
541572ac97cdSTom Musta     if (SPECIALARG) {			/* handle infinities and NaNs */
541672ac97cdSTom Musta       if (decNumberIsInfinite(rhs)) {	/* an infinity */
541772ac97cdSTom Musta 	if (decNumberIsNegative(rhs))	/* -Infinity -> +0 */
541872ac97cdSTom Musta 	  decNumberZero(res);
541972ac97cdSTom Musta 	 else decNumberCopy(res, rhs);	/* +Infinity -> self */
542072ac97cdSTom Musta 	}
542172ac97cdSTom Musta        else decNaNs(res, rhs, NULL, set, status); /* a NaN */
542272ac97cdSTom Musta       break;}
542372ac97cdSTom Musta 
542472ac97cdSTom Musta     if (ISZERO(rhs)) {			/* zeros -> exact 1 */
542572ac97cdSTom Musta       decNumberZero(res);		/* make clean 1 */
542672ac97cdSTom Musta       *res->lsu=1;			/* .. */
542772ac97cdSTom Musta       break;}				/* [no status to set] */
542872ac97cdSTom Musta 
542972ac97cdSTom Musta     /* e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path */
543072ac97cdSTom Musta     /* positive and negative tiny cases which will result in inexact */
543172ac97cdSTom Musta     /* 1.  This also allows the later add-accumulate to always be */
543272ac97cdSTom Musta     /* exact (because its length will never be more than twice the */
543372ac97cdSTom Musta     /* working precision). */
543472ac97cdSTom Musta     /* The comparator (tiny) needs just one digit, so use the */
543572ac97cdSTom Musta     /* decNumber d for it (reused as the divisor, etc., below); its */
543672ac97cdSTom Musta     /* exponent is such that if x is positive it will have */
543772ac97cdSTom Musta     /* set->digits-1 zeros between the decimal point and the digit, */
543872ac97cdSTom Musta     /* which is 4, and if x is negative one more zero there as the */
543972ac97cdSTom Musta     /* more precise result will be of the form 0.9999999 rather than */
544072ac97cdSTom Musta     /* 1.0000001.  Hence, tiny will be 0.0000004  if digits=7 and x>0 */
544172ac97cdSTom Musta     /* or 0.00000004 if digits=7 and x<0.  If RHS not larger than */
544272ac97cdSTom Musta     /* this then the result will be 1.000000 */
544372ac97cdSTom Musta     decNumberZero(d);			/* clean */
544472ac97cdSTom Musta     *d->lsu=4;				/* set 4 .. */
544572ac97cdSTom Musta     d->exponent=-set->digits;		/* * 10**(-d) */
544672ac97cdSTom Musta     if (decNumberIsNegative(rhs)) d->exponent--;  /* negative case */
544772ac97cdSTom Musta     comp=decCompare(d, rhs, 1);		/* signless compare */
544872ac97cdSTom Musta     if (comp==BADINT) {
544972ac97cdSTom Musta       *status|=DEC_Insufficient_storage;
545072ac97cdSTom Musta       break;}
545172ac97cdSTom Musta     if (comp>=0) {			/* rhs < d */
545272ac97cdSTom Musta       Int shift=set->digits-1;
545372ac97cdSTom Musta       decNumberZero(res);		/* set 1 */
545472ac97cdSTom Musta       *res->lsu=1;			/* .. */
545572ac97cdSTom Musta       res->digits=decShiftToMost(res->lsu, 1, shift);
545672ac97cdSTom Musta       res->exponent=-shift;		     /* make 1.0000... */
545772ac97cdSTom Musta       *status|=DEC_Inexact | DEC_Rounded;    /* .. inexactly */
545872ac97cdSTom Musta       break;} /* tiny */
545972ac97cdSTom Musta 
546072ac97cdSTom Musta     /* set up the context to be used for calculating a, as this is */
546172ac97cdSTom Musta     /* used on both paths below */
546272ac97cdSTom Musta     decContextDefault(&aset, DEC_INIT_DECIMAL64);
546372ac97cdSTom Musta     /* accumulator bounds are as requested (could underflow) */
546472ac97cdSTom Musta     aset.emax=set->emax;		/* usual bounds */
546572ac97cdSTom Musta     aset.emin=set->emin;		/* .. */
546672ac97cdSTom Musta     aset.clamp=0;			/* and no concrete format */
546772ac97cdSTom Musta 
546872ac97cdSTom Musta     /* calculate the adjusted (Hull & Abrham) exponent (where the */
546972ac97cdSTom Musta     /* decimal point is just to the left of the coefficient msd) */
547072ac97cdSTom Musta     h=rhs->exponent+rhs->digits;
547172ac97cdSTom Musta     /* if h>8 then 10**h cannot be calculated safely; however, when */
547272ac97cdSTom Musta     /* h=8 then exp(|rhs|) will be at least exp(1E+7) which is at */
547372ac97cdSTom Musta     /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */
547472ac97cdSTom Musta     /* overflow (or underflow to 0) is guaranteed -- so this case can */
547572ac97cdSTom Musta     /* be handled by simply forcing the appropriate excess */
547672ac97cdSTom Musta     if (h>8) {				/* overflow/underflow */
547772ac97cdSTom Musta       /* set up here so Power call below will over or underflow to */
547872ac97cdSTom Musta       /* zero; set accumulator to either 2 or 0.02 */
547972ac97cdSTom Musta       /* [stack buffer for a is always big enough for this] */
548072ac97cdSTom Musta       decNumberZero(a);
548172ac97cdSTom Musta       *a->lsu=2;			/* not 1 but < exp(1) */
548272ac97cdSTom Musta       if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */
548372ac97cdSTom Musta       h=8;				/* clamp so 10**h computable */
548472ac97cdSTom Musta       p=9;				/* set a working precision */
548572ac97cdSTom Musta       }
548672ac97cdSTom Musta      else {				/* h<=8 */
548772ac97cdSTom Musta       Int maxlever=(rhs->digits>8?1:0);
548872ac97cdSTom Musta       /* [could/should increase this for precisions >40 or so, too] */
548972ac97cdSTom Musta 
549072ac97cdSTom Musta       /* if h is 8, cannot normalize to a lower upper limit because */
549172ac97cdSTom Musta       /* the final result will not be computable (see notes above), */
549272ac97cdSTom Musta       /* but leverage can be applied whenever h is less than 8. */
549372ac97cdSTom Musta       /* Apply as much as possible, up to a MAXLEVER digits, which */
549472ac97cdSTom Musta       /* sets the tradeoff against the cost of the later a**(10**h). */
549572ac97cdSTom Musta       /* As h is increased, the working precision below also */
549672ac97cdSTom Musta       /* increases to compensate for the "constant digits at the */
549772ac97cdSTom Musta       /* front" effect. */
549872ac97cdSTom Musta       Int lever=MINI(8-h, maxlever);	/* leverage attainable */
549972ac97cdSTom Musta       Int use=-rhs->digits-lever;	/* exponent to use for RHS */
550072ac97cdSTom Musta       h+=lever;				/* apply leverage selected */
550172ac97cdSTom Musta       if (h<0) {			/* clamp */
550272ac97cdSTom Musta 	use+=h;				/* [may end up subnormal] */
550372ac97cdSTom Musta 	h=0;
550472ac97cdSTom Musta 	}
550572ac97cdSTom Musta       /* Take a copy of RHS if it needs normalization (true whenever x>=1) */
550672ac97cdSTom Musta       if (rhs->exponent!=use) {
550772ac97cdSTom Musta 	decNumber *newrhs=bufr;		/* assume will fit on stack */
550872ac97cdSTom Musta 	needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
550972ac97cdSTom Musta 	if (needbytes>sizeof(bufr)) {	/* need malloc space */
551072ac97cdSTom Musta 	  allocrhs=(decNumber *)malloc(needbytes);
551172ac97cdSTom Musta 	  if (allocrhs==NULL) {		/* hopeless -- abandon */
551272ac97cdSTom Musta 	    *status|=DEC_Insufficient_storage;
551372ac97cdSTom Musta 	    break;}
551472ac97cdSTom Musta 	  newrhs=allocrhs;		/* use the allocated space */
551572ac97cdSTom Musta 	  }
551672ac97cdSTom Musta 	decNumberCopy(newrhs, rhs);	/* copy to safe space */
551772ac97cdSTom Musta 	newrhs->exponent=use;		/* normalize; now <1 */
551872ac97cdSTom Musta 	x=newrhs;			/* ready for use */
551972ac97cdSTom Musta 	/* decNumberShow(x); */
552072ac97cdSTom Musta 	}
552172ac97cdSTom Musta 
552272ac97cdSTom Musta       /* Now use the usual power series to evaluate exp(x).  The */
552372ac97cdSTom Musta       /* series starts as 1 + x + x^2/2 ... so prime ready for the */
552472ac97cdSTom Musta       /* third term by setting the term variable t=x, the accumulator */
552572ac97cdSTom Musta       /* a=1, and the divisor d=2. */
552672ac97cdSTom Musta 
552772ac97cdSTom Musta       /* First determine the working precision.	 From Hull & Abrham */
552872ac97cdSTom Musta       /* this is set->digits+h+2.  However, if x is 'over-precise' we */
552972ac97cdSTom Musta       /* need to allow for all its digits to potentially participate */
553072ac97cdSTom Musta       /* (consider an x where all the excess digits are 9s) so in */
553172ac97cdSTom Musta       /* this case use x->digits+h+2 */
553272ac97cdSTom Musta       p=MAXI(x->digits, set->digits)+h+2;    /* [h<=8] */
553372ac97cdSTom Musta 
553472ac97cdSTom Musta       /* a and t are variable precision, and depend on p, so space */
553572ac97cdSTom Musta       /* must be allocated for them if necessary */
553672ac97cdSTom Musta 
553772ac97cdSTom Musta       /* the accumulator needs to be able to hold 2p digits so that */
553872ac97cdSTom Musta       /* the additions on the second and subsequent iterations are */
553972ac97cdSTom Musta       /* sufficiently exact. */
554072ac97cdSTom Musta       needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit);
554172ac97cdSTom Musta       if (needbytes>sizeof(bufa)) {	/* need malloc space */
554272ac97cdSTom Musta 	allocbufa=(decNumber *)malloc(needbytes);
554372ac97cdSTom Musta 	if (allocbufa==NULL) {		/* hopeless -- abandon */
554472ac97cdSTom Musta 	  *status|=DEC_Insufficient_storage;
554572ac97cdSTom Musta 	  break;}
554672ac97cdSTom Musta 	a=allocbufa;			/* use the allocated space */
554772ac97cdSTom Musta 	}
554872ac97cdSTom Musta       /* the term needs to be able to hold p digits (which is */
554972ac97cdSTom Musta       /* guaranteed to be larger than x->digits, so the initial copy */
555072ac97cdSTom Musta       /* is safe); it may also be used for the raise-to-power */
555172ac97cdSTom Musta       /* calculation below, which needs an extra two digits */
555272ac97cdSTom Musta       needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit);
555372ac97cdSTom Musta       if (needbytes>sizeof(buft)) {	/* need malloc space */
555472ac97cdSTom Musta 	allocbuft=(decNumber *)malloc(needbytes);
555572ac97cdSTom Musta 	if (allocbuft==NULL) {		/* hopeless -- abandon */
555672ac97cdSTom Musta 	  *status|=DEC_Insufficient_storage;
555772ac97cdSTom Musta 	  break;}
555872ac97cdSTom Musta 	t=allocbuft;			/* use the allocated space */
555972ac97cdSTom Musta 	}
556072ac97cdSTom Musta 
556172ac97cdSTom Musta       decNumberCopy(t, x);		/* term=x */
556272ac97cdSTom Musta       decNumberZero(a); *a->lsu=1;	/* accumulator=1 */
556372ac97cdSTom Musta       decNumberZero(d); *d->lsu=2;	/* divisor=2 */
556472ac97cdSTom Musta       decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */
556572ac97cdSTom Musta 
556672ac97cdSTom Musta       /* set up the contexts for calculating a, t, and d */
556772ac97cdSTom Musta       decContextDefault(&tset, DEC_INIT_DECIMAL64);
556872ac97cdSTom Musta       dset=tset;
556972ac97cdSTom Musta       /* accumulator bounds are set above, set precision now */
557072ac97cdSTom Musta       aset.digits=p*2;			/* double */
557172ac97cdSTom Musta       /* term bounds avoid any underflow or overflow */
557272ac97cdSTom Musta       tset.digits=p;
557372ac97cdSTom Musta       tset.emin=DEC_MIN_EMIN;		/* [emax is plenty] */
557472ac97cdSTom Musta       /* [dset.digits=16, etc., are sufficient] */
557572ac97cdSTom Musta 
557672ac97cdSTom Musta       /* finally ready to roll */
557772ac97cdSTom Musta       for (;;) {
557872ac97cdSTom Musta 	#if DECCHECK
557972ac97cdSTom Musta 	iterations++;
558072ac97cdSTom Musta 	#endif
558172ac97cdSTom Musta 	/* only the status from the accumulation is interesting */
558272ac97cdSTom Musta 	/* [but it should remain unchanged after first add] */
558372ac97cdSTom Musta 	decAddOp(a, a, t, &aset, 0, status);	       /* a=a+t */
558472ac97cdSTom Musta 	decMultiplyOp(t, t, x, &tset, &ignore);	       /* t=t*x */
558572ac97cdSTom Musta 	decDivideOp(t, t, d, &tset, DIVIDE, &ignore);  /* t=t/d */
558672ac97cdSTom Musta 	/* the iteration ends when the term cannot affect the result, */
558772ac97cdSTom Musta 	/* if rounded to p digits, which is when its value is smaller */
558872ac97cdSTom Musta 	/* than the accumulator by p+1 digits.	There must also be */
558972ac97cdSTom Musta 	/* full precision in a. */
559072ac97cdSTom Musta 	if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1))
559172ac97cdSTom Musta 	    && (a->digits>=p)) break;
559272ac97cdSTom Musta 	decAddOp(d, d, &numone, &dset, 0, &ignore);    /* d=d+1 */
559372ac97cdSTom Musta 	} /* iterate */
559472ac97cdSTom Musta 
559572ac97cdSTom Musta       #if DECCHECK
559672ac97cdSTom Musta       /* just a sanity check; comment out test to show always */
559772ac97cdSTom Musta       if (iterations>p+3)
559872ac97cdSTom Musta 	printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
559972ac97cdSTom Musta 	       iterations, *status, p, x->digits);
560072ac97cdSTom Musta       #endif
560172ac97cdSTom Musta       } /* h<=8 */
560272ac97cdSTom Musta 
560372ac97cdSTom Musta     /* apply postconditioning: a=a**(10**h) -- this is calculated */
560472ac97cdSTom Musta     /* at a slightly higher precision than Hull & Abrham suggest */
560572ac97cdSTom Musta     if (h>0) {
560672ac97cdSTom Musta       Int seenbit=0;		   /* set once a 1-bit is seen */
560772ac97cdSTom Musta       Int i;			   /* counter */
560872ac97cdSTom Musta       Int n=powers[h];		   /* always positive */
560972ac97cdSTom Musta       aset.digits=p+2;		   /* sufficient precision */
561072ac97cdSTom Musta       /* avoid the overhead and many extra digits of decNumberPower */
561172ac97cdSTom Musta       /* as all that is needed is the short 'multipliers' loop; here */
561272ac97cdSTom Musta       /* accumulate the answer into t */
561372ac97cdSTom Musta       decNumberZero(t); *t->lsu=1; /* acc=1 */
561472ac97cdSTom Musta       for (i=1;;i++){		   /* for each bit [top bit ignored] */
561572ac97cdSTom Musta 	/* abandon if have had overflow or terminal underflow */
561672ac97cdSTom Musta 	if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
561772ac97cdSTom Musta 	  if (*status&DEC_Overflow || ISZERO(t)) break;}
561872ac97cdSTom Musta 	n=n<<1;			   /* move next bit to testable position */
561972ac97cdSTom Musta 	if (n<0) {		   /* top bit is set */
562072ac97cdSTom Musta 	  seenbit=1;		   /* OK, have a significant bit */
562172ac97cdSTom Musta 	  decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */
562272ac97cdSTom Musta 	  }
562372ac97cdSTom Musta 	if (i==31) break;	   /* that was the last bit */
562472ac97cdSTom Musta 	if (!seenbit) continue;	   /* no need to square 1 */
562572ac97cdSTom Musta 	decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */
562672ac97cdSTom Musta 	} /*i*/ /* 32 bits */
562772ac97cdSTom Musta       /* decNumberShow(t); */
562872ac97cdSTom Musta       a=t;			   /* and carry on using t instead of a */
562972ac97cdSTom Musta       }
563072ac97cdSTom Musta 
563172ac97cdSTom Musta     /* Copy and round the result to res */
563272ac97cdSTom Musta     residue=1;				/* indicate dirt to right .. */
563372ac97cdSTom Musta     if (ISZERO(a)) residue=0;		/* .. unless underflowed to 0 */
563472ac97cdSTom Musta     aset.digits=set->digits;		/* [use default rounding] */
563572ac97cdSTom Musta     decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
563672ac97cdSTom Musta     decFinish(res, set, &residue, status);	 /* cleanup/set flags */
563772ac97cdSTom Musta     } while(0);				/* end protected */
563872ac97cdSTom Musta 
563972ac97cdSTom Musta   if (allocrhs !=NULL) free(allocrhs);	/* drop any storage used */
564072ac97cdSTom Musta   if (allocbufa!=NULL) free(allocbufa); /* .. */
564172ac97cdSTom Musta   if (allocbuft!=NULL) free(allocbuft); /* .. */
564272ac97cdSTom Musta   /* [status is handled by caller] */
564372ac97cdSTom Musta   return res;
564472ac97cdSTom Musta   } /* decExpOp */
564572ac97cdSTom Musta 
564672ac97cdSTom Musta /* ------------------------------------------------------------------ */
564772ac97cdSTom Musta /* Initial-estimate natural logarithm table			      */
564872ac97cdSTom Musta /*								      */
564972ac97cdSTom Musta /*   LNnn -- 90-entry 16-bit table for values from .10 through .99.   */
565072ac97cdSTom Musta /*	     The result is a 4-digit encode of the coefficient (c=the */
565172ac97cdSTom Musta /*	     top 14 bits encoding 0-9999) and a 2-digit encode of the */
565272ac97cdSTom Musta /*	     exponent (e=the bottom 2 bits encoding 0-3)	      */
565372ac97cdSTom Musta /*								      */
565472ac97cdSTom Musta /*	     The resulting value is given by:			      */
565572ac97cdSTom Musta /*								      */
565672ac97cdSTom Musta /*	       v = -c * 10**(-e-3)				      */
565772ac97cdSTom Musta /*								      */
565872ac97cdSTom Musta /*	     where e and c are extracted from entry k = LNnn[x-10]    */
565972ac97cdSTom Musta /*	     where x is truncated (NB) into the range 10 through 99,  */
566072ac97cdSTom Musta /*	     and then c = k>>2 and e = k&3.			      */
566172ac97cdSTom Musta /* ------------------------------------------------------------------ */
5662d072cdf3SStefan Weil static const uShort LNnn[90] = {
5663d072cdf3SStefan Weil   9016,  8652,  8316,  8008,  7724,  7456,  7208,
566472ac97cdSTom Musta   6972,	 6748,	6540,  6340,  6148,  5968,  5792,  5628,  5464,	 5312,
566572ac97cdSTom Musta   5164,	 5020,	4884,  4748,  4620,  4496,  4376,  4256,  4144,	 4032,
566672ac97cdSTom Musta  39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629,
566772ac97cdSTom Musta  29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837,
566872ac97cdSTom Musta  22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321,
566972ac97cdSTom Musta  15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717,
567072ac97cdSTom Musta  10197,	 9685,	9177,  8677,  8185,  7697,  7213,  6737,  6269,	 5801,
567172ac97cdSTom Musta   5341,	 4889,	4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254,
567272ac97cdSTom Musta  10130,	 6046, 20055};
567372ac97cdSTom Musta 
567472ac97cdSTom Musta /* ------------------------------------------------------------------ */
567572ac97cdSTom Musta /* decLnOp -- effect natural logarithm				      */
567672ac97cdSTom Musta /*								      */
567772ac97cdSTom Musta /*   This computes C = ln(A)					      */
567872ac97cdSTom Musta /*								      */
567972ac97cdSTom Musta /*   res is C, the result.  C may be A				      */
568072ac97cdSTom Musta /*   rhs is A							      */
568172ac97cdSTom Musta /*   set is the context; note that rounding mode has no effect	      */
568272ac97cdSTom Musta /*								      */
568372ac97cdSTom Musta /* C must have space for set->digits digits.			      */
568472ac97cdSTom Musta /*								      */
568572ac97cdSTom Musta /* Notable cases:						      */
568672ac97cdSTom Musta /*   A<0 -> Invalid						      */
568772ac97cdSTom Musta /*   A=0 -> -Infinity (Exact)					      */
568872ac97cdSTom Musta /*   A=+Infinity -> +Infinity (Exact)				      */
568972ac97cdSTom Musta /*   A=1 exactly -> 0 (Exact)					      */
569072ac97cdSTom Musta /*								      */
569172ac97cdSTom Musta /* Restrictions (as for Exp):					      */
569272ac97cdSTom Musta /*								      */
569372ac97cdSTom Musta /*   digits, emax, and -emin in the context must be less than	      */
569472ac97cdSTom Musta /*   DEC_MAX_MATH+11 (1000010), and the rhs must be within these      */
569572ac97cdSTom Musta /*   bounds or a zero.	This is an internal routine, so these	      */
569672ac97cdSTom Musta /*   restrictions are contractual and not enforced.		      */
569772ac97cdSTom Musta /*								      */
569872ac97cdSTom Musta /* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will      */
569972ac97cdSTom Musta /* almost always be correctly rounded, but may be up to 1 ulp in      */
570072ac97cdSTom Musta /* error in rare cases.						      */
570172ac97cdSTom Musta /* ------------------------------------------------------------------ */
570272ac97cdSTom Musta /* The result is calculated using Newton's method, with each	      */
570372ac97cdSTom Musta /* iteration calculating a' = a + x * exp(-a) - 1.  See, for example, */
570472ac97cdSTom Musta /* Epperson 1989.						      */
570572ac97cdSTom Musta /*								      */
570672ac97cdSTom Musta /* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */
570772ac97cdSTom Musta /* This has to be calculated at the sum of the precision of x and the */
570872ac97cdSTom Musta /* working precision.						      */
570972ac97cdSTom Musta /*								      */
571072ac97cdSTom Musta /* Implementation notes:					      */
571172ac97cdSTom Musta /*								      */
571272ac97cdSTom Musta /* 1. This is separated out as decLnOp so it can be called from	      */
571372ac97cdSTom Musta /*    other Mathematical functions (e.g., Log 10) with a wider range  */
571472ac97cdSTom Musta /*    than normal.  In particular, it can handle the slightly wider   */
571572ac97cdSTom Musta /*    (+9+2) range needed by a power function.			      */
571672ac97cdSTom Musta /*								      */
571772ac97cdSTom Musta /* 2. The speed of this function is about 10x slower than exp, as     */
571872ac97cdSTom Musta /*    it typically needs 4-6 iterations for short numbers, and the    */
571972ac97cdSTom Musta /*    extra precision needed adds a squaring effect, twice.	      */
572072ac97cdSTom Musta /*								      */
572172ac97cdSTom Musta /* 3. Fastpaths are included for ln(10) and ln(2), up to length 40,   */
572272ac97cdSTom Musta /*    as these are common requests.  ln(10) is used by log10(x).      */
572372ac97cdSTom Musta /*								      */
572472ac97cdSTom Musta /* 4. An iteration might be saved by widening the LNnn table, and     */
572572ac97cdSTom Musta /*    would certainly save at least one if it were made ten times     */
572672ac97cdSTom Musta /*    bigger, too (for truncated fractions 0.100 through 0.999).      */
572772ac97cdSTom Musta /*    However, for most practical evaluations, at least four or five  */
5728e3a6e0daSzhaolichang /*    iterations will be needed -- so this would only speed up by      */
572972ac97cdSTom Musta /*    20-25% and that probably does not justify increasing the table  */
573072ac97cdSTom Musta /*    size.							      */
573172ac97cdSTom Musta /*								      */
573272ac97cdSTom Musta /* 5. The static buffers are larger than might be expected to allow   */
573372ac97cdSTom Musta /*    for calls from decNumberPower.				      */
573472ac97cdSTom Musta /* ------------------------------------------------------------------ */
decLnOp(decNumber * res,const decNumber * rhs,decContext * set,uInt * status)5735d072cdf3SStefan Weil static decNumber *decLnOp(decNumber *res, const decNumber *rhs,
573672ac97cdSTom Musta                           decContext *set, uInt *status) {
573772ac97cdSTom Musta   uInt ignore=0;		   /* working status accumulator */
573872ac97cdSTom Musta   uInt needbytes;		   /* for space calculations */
573972ac97cdSTom Musta   Int residue;			   /* rounding residue */
574072ac97cdSTom Musta   Int r;			   /* rhs=f*10**r [see below] */
574172ac97cdSTom Musta   Int p;			   /* working precision */
574272ac97cdSTom Musta   Int pp;			   /* precision for iteration */
574372ac97cdSTom Musta   Int t;			   /* work */
574472ac97cdSTom Musta 
574572ac97cdSTom Musta   /* buffers for a (accumulator, typically precision+2) and b */
574672ac97cdSTom Musta   /* (adjustment calculator, same size) */
574772ac97cdSTom Musta   decNumber bufa[D2N(DECBUFFER+12)];
574872ac97cdSTom Musta   decNumber *allocbufa=NULL;	   /* -> allocated bufa, iff allocated */
574972ac97cdSTom Musta   decNumber *a=bufa;		   /* accumulator/work */
575072ac97cdSTom Musta   decNumber bufb[D2N(DECBUFFER*2+2)];
575172ac97cdSTom Musta   decNumber *allocbufb=NULL;	   /* -> allocated bufa, iff allocated */
575272ac97cdSTom Musta   decNumber *b=bufb;		   /* adjustment/work */
575372ac97cdSTom Musta 
575472ac97cdSTom Musta   decNumber  numone;		   /* constant 1 */
575572ac97cdSTom Musta   decNumber  cmp;		   /* work */
575672ac97cdSTom Musta   decContext aset, bset;	   /* working contexts */
575772ac97cdSTom Musta 
575872ac97cdSTom Musta   #if DECCHECK
575972ac97cdSTom Musta   Int iterations=0;		   /* for later sanity check */
576072ac97cdSTom Musta   if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
576172ac97cdSTom Musta   #endif
576272ac97cdSTom Musta 
576372ac97cdSTom Musta   do {					/* protect allocated storage */
576472ac97cdSTom Musta     if (SPECIALARG) {			/* handle infinities and NaNs */
576572ac97cdSTom Musta       if (decNumberIsInfinite(rhs)) {	/* an infinity */
576672ac97cdSTom Musta 	if (decNumberIsNegative(rhs))	/* -Infinity -> error */
576772ac97cdSTom Musta 	  *status|=DEC_Invalid_operation;
576872ac97cdSTom Musta 	 else decNumberCopy(res, rhs);	/* +Infinity -> self */
576972ac97cdSTom Musta 	}
577072ac97cdSTom Musta        else decNaNs(res, rhs, NULL, set, status); /* a NaN */
577172ac97cdSTom Musta       break;}
577272ac97cdSTom Musta 
577372ac97cdSTom Musta     if (ISZERO(rhs)) {			/* +/- zeros -> -Infinity */
577472ac97cdSTom Musta       decNumberZero(res);		/* make clean */
577572ac97cdSTom Musta       res->bits=DECINF|DECNEG;		/* set - infinity */
577672ac97cdSTom Musta       break;}				/* [no status to set] */
577772ac97cdSTom Musta 
577872ac97cdSTom Musta     /* Non-zero negatives are bad... */
577972ac97cdSTom Musta     if (decNumberIsNegative(rhs)) {	/* -x -> error */
578072ac97cdSTom Musta       *status|=DEC_Invalid_operation;
578172ac97cdSTom Musta       break;}
578272ac97cdSTom Musta 
578372ac97cdSTom Musta     /* Here, rhs is positive, finite, and in range */
578472ac97cdSTom Musta 
578572ac97cdSTom Musta     /* lookaside fastpath code for ln(2) and ln(10) at common lengths */
578672ac97cdSTom Musta     if (rhs->exponent==0 && set->digits<=40) {
578772ac97cdSTom Musta       #if DECDPUN==1
578872ac97cdSTom Musta       if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */
578972ac97cdSTom Musta       #else
579072ac97cdSTom Musta       if (rhs->lsu[0]==10 && rhs->digits==2) {			/* ln(10) */
579172ac97cdSTom Musta       #endif
579272ac97cdSTom Musta 	aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
579372ac97cdSTom Musta 	#define LN10 "2.302585092994045684017991454684364207601"
579472ac97cdSTom Musta 	decNumberFromString(res, LN10, &aset);
579572ac97cdSTom Musta 	*status|=(DEC_Inexact | DEC_Rounded); /* is inexact */
579672ac97cdSTom Musta 	break;}
579772ac97cdSTom Musta       if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */
579872ac97cdSTom Musta 	aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
579972ac97cdSTom Musta 	#define LN2 "0.6931471805599453094172321214581765680755"
580072ac97cdSTom Musta 	decNumberFromString(res, LN2, &aset);
580172ac97cdSTom Musta 	*status|=(DEC_Inexact | DEC_Rounded);
580272ac97cdSTom Musta 	break;}
580372ac97cdSTom Musta       } /* integer and short */
580472ac97cdSTom Musta 
580572ac97cdSTom Musta     /* Determine the working precision.	 This is normally the */
580672ac97cdSTom Musta     /* requested precision + 2, with a minimum of 9.  However, if */
580772ac97cdSTom Musta     /* the rhs is 'over-precise' then allow for all its digits to */
580872ac97cdSTom Musta     /* potentially participate (consider an rhs where all the excess */
580972ac97cdSTom Musta     /* digits are 9s) so in this case use rhs->digits+2. */
581072ac97cdSTom Musta     p=MAXI(rhs->digits, MAXI(set->digits, 7))+2;
581172ac97cdSTom Musta 
581272ac97cdSTom Musta     /* Allocate space for the accumulator and the high-precision */
581372ac97cdSTom Musta     /* adjustment calculator, if necessary.  The accumulator must */
581472ac97cdSTom Musta     /* be able to hold p digits, and the adjustment up to */
581572ac97cdSTom Musta     /* rhs->digits+p digits.  They are also made big enough for 16 */
581672ac97cdSTom Musta     /* digits so that they can be used for calculating the initial */
581772ac97cdSTom Musta     /* estimate. */
581872ac97cdSTom Musta     needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit);
581972ac97cdSTom Musta     if (needbytes>sizeof(bufa)) {     /* need malloc space */
582072ac97cdSTom Musta       allocbufa=(decNumber *)malloc(needbytes);
582172ac97cdSTom Musta       if (allocbufa==NULL) {	      /* hopeless -- abandon */
582272ac97cdSTom Musta 	*status|=DEC_Insufficient_storage;
582372ac97cdSTom Musta 	break;}
582472ac97cdSTom Musta       a=allocbufa;		      /* use the allocated space */
582572ac97cdSTom Musta       }
582672ac97cdSTom Musta     pp=p+rhs->digits;
582772ac97cdSTom Musta     needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit);
582872ac97cdSTom Musta     if (needbytes>sizeof(bufb)) {     /* need malloc space */
582972ac97cdSTom Musta       allocbufb=(decNumber *)malloc(needbytes);
583072ac97cdSTom Musta       if (allocbufb==NULL) {	      /* hopeless -- abandon */
583172ac97cdSTom Musta 	*status|=DEC_Insufficient_storage;
583272ac97cdSTom Musta 	break;}
583372ac97cdSTom Musta       b=allocbufb;		      /* use the allocated space */
583472ac97cdSTom Musta       }
583572ac97cdSTom Musta 
583672ac97cdSTom Musta     /* Prepare an initial estimate in acc. Calculate this by */
583772ac97cdSTom Musta     /* considering the coefficient of x to be a normalized fraction, */
583872ac97cdSTom Musta     /* f, with the decimal point at far left and multiplied by */
583972ac97cdSTom Musta     /* 10**r.  Then, rhs=f*10**r and 0.1<=f<1, and */
584072ac97cdSTom Musta     /*	 ln(x) = ln(f) + ln(10)*r */
584172ac97cdSTom Musta     /* Get the initial estimate for ln(f) from a small lookup */
584272ac97cdSTom Musta     /* table (see above) indexed by the first two digits of f, */
584372ac97cdSTom Musta     /* truncated. */
584472ac97cdSTom Musta 
584572ac97cdSTom Musta     decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */
584672ac97cdSTom Musta     r=rhs->exponent+rhs->digits;	/* 'normalised' exponent */
584772ac97cdSTom Musta     decNumberFromInt32(a, r);		/* a=r */
584872ac97cdSTom Musta     decNumberFromInt32(b, 2302585);	/* b=ln(10) (2.302585) */
584972ac97cdSTom Musta     b->exponent=-6;			/*  .. */
585072ac97cdSTom Musta     decMultiplyOp(a, a, b, &aset, &ignore);  /* a=a*b */
585172ac97cdSTom Musta     /* now get top two digits of rhs into b by simple truncate and */
585272ac97cdSTom Musta     /* force to integer */
585372ac97cdSTom Musta     residue=0;				/* (no residue) */
585472ac97cdSTom Musta     aset.digits=2; aset.round=DEC_ROUND_DOWN;
585572ac97cdSTom Musta     decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */
585672ac97cdSTom Musta     b->exponent=0;			/* make integer */
585772ac97cdSTom Musta     t=decGetInt(b);			/* [cannot fail] */
585872ac97cdSTom Musta     if (t<10) t=X10(t);			/* adjust single-digit b */
585972ac97cdSTom Musta     t=LNnn[t-10];			/* look up ln(b) */
586072ac97cdSTom Musta     decNumberFromInt32(b, t>>2);	/* b=ln(b) coefficient */
586172ac97cdSTom Musta     b->exponent=-(t&3)-3;		/* set exponent */
586272ac97cdSTom Musta     b->bits=DECNEG;			/* ln(0.10)->ln(0.99) always -ve */
586372ac97cdSTom Musta     aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */
586472ac97cdSTom Musta     decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */
586572ac97cdSTom Musta     /* the initial estimate is now in a, with up to 4 digits correct. */
586672ac97cdSTom Musta     /* When rhs is at or near Nmax the estimate will be low, so we */
586772ac97cdSTom Musta     /* will approach it from below, avoiding overflow when calling exp. */
586872ac97cdSTom Musta 
586972ac97cdSTom Musta     decNumberZero(&numone); *numone.lsu=1;   /* constant 1 for adjustment */
587072ac97cdSTom Musta 
587172ac97cdSTom Musta     /* accumulator bounds are as requested (could underflow, but */
587272ac97cdSTom Musta     /* cannot overflow) */
587372ac97cdSTom Musta     aset.emax=set->emax;
587472ac97cdSTom Musta     aset.emin=set->emin;
587572ac97cdSTom Musta     aset.clamp=0;			/* no concrete format */
587672ac97cdSTom Musta     /* set up a context to be used for the multiply and subtract */
587772ac97cdSTom Musta     bset=aset;
587872ac97cdSTom Musta     bset.emax=DEC_MAX_MATH*2;		/* use double bounds for the */
587972ac97cdSTom Musta     bset.emin=-DEC_MAX_MATH*2;		/* adjustment calculation */
588072ac97cdSTom Musta 					/* [see decExpOp call below] */
588172ac97cdSTom Musta     /* for each iteration double the number of digits to calculate, */
588272ac97cdSTom Musta     /* up to a maximum of p */
588372ac97cdSTom Musta     pp=9;				/* initial precision */
588472ac97cdSTom Musta     /* [initially 9 as then the sequence starts 7+2, 16+2, and */
588572ac97cdSTom Musta     /* 34+2, which is ideal for standard-sized numbers] */
588672ac97cdSTom Musta     aset.digits=pp;			/* working context */
588772ac97cdSTom Musta     bset.digits=pp+rhs->digits;		/* wider context */
588872ac97cdSTom Musta     for (;;) {				/* iterate */
588972ac97cdSTom Musta       #if DECCHECK
589072ac97cdSTom Musta       iterations++;
589172ac97cdSTom Musta       if (iterations>24) break;		/* consider 9 * 2**24 */
589272ac97cdSTom Musta       #endif
589372ac97cdSTom Musta       /* calculate the adjustment (exp(-a)*x-1) into b.	 This is a */
589472ac97cdSTom Musta       /* catastrophic subtraction but it really is the difference */
589572ac97cdSTom Musta       /* from 1 that is of interest. */
589672ac97cdSTom Musta       /* Use the internal entry point to Exp as it allows the double */
589772ac97cdSTom Musta       /* range for calculating exp(-a) when a is the tiniest subnormal. */
589872ac97cdSTom Musta       a->bits^=DECNEG;			/* make -a */
589972ac97cdSTom Musta       decExpOp(b, a, &bset, &ignore);	/* b=exp(-a) */
590072ac97cdSTom Musta       a->bits^=DECNEG;			/* restore sign of a */
590172ac97cdSTom Musta       /* now multiply by rhs and subtract 1, at the wider precision */
590272ac97cdSTom Musta       decMultiplyOp(b, b, rhs, &bset, &ignore);	       /* b=b*rhs */
590372ac97cdSTom Musta       decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */
590472ac97cdSTom Musta 
590572ac97cdSTom Musta       /* the iteration ends when the adjustment cannot affect the */
590672ac97cdSTom Musta       /* result by >=0.5 ulp (at the requested digits), which */
590772ac97cdSTom Musta       /* is when its value is smaller than the accumulator by */
590872ac97cdSTom Musta       /* set->digits+1 digits (or it is zero) -- this is a looser */
590972ac97cdSTom Musta       /* requirement than for Exp because all that happens to the */
591072ac97cdSTom Musta       /* accumulator after this is the final rounding (but note that */
591172ac97cdSTom Musta       /* there must also be full precision in a, or a=0). */
591272ac97cdSTom Musta 
591372ac97cdSTom Musta       if (decNumberIsZero(b) ||
591472ac97cdSTom Musta 	  (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) {
591572ac97cdSTom Musta 	if (a->digits==p) break;
591672ac97cdSTom Musta 	if (decNumberIsZero(a)) {
591772ac97cdSTom Musta 	  decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */
591872ac97cdSTom Musta 	  if (cmp.lsu[0]==0) a->exponent=0;	       /* yes, exact 0 */
591972ac97cdSTom Musta 	   else *status|=(DEC_Inexact | DEC_Rounded);  /* no, inexact */
592072ac97cdSTom Musta 	  break;
592172ac97cdSTom Musta 	  }
592272ac97cdSTom Musta 	/* force padding if adjustment has gone to 0 before full length */
592372ac97cdSTom Musta 	if (decNumberIsZero(b)) b->exponent=a->exponent-p;
592472ac97cdSTom Musta 	}
592572ac97cdSTom Musta 
592672ac97cdSTom Musta       /* not done yet ... */
592772ac97cdSTom Musta       decAddOp(a, a, b, &aset, 0, &ignore);  /* a=a+b for next estimate */
592872ac97cdSTom Musta       if (pp==p) continue;		     /* precision is at maximum */
592972ac97cdSTom Musta       /* lengthen the next calculation */
593072ac97cdSTom Musta       pp=pp*2;				     /* double precision */
593172ac97cdSTom Musta       if (pp>p) pp=p;			     /* clamp to maximum */
593272ac97cdSTom Musta       aset.digits=pp;			     /* working context */
593372ac97cdSTom Musta       bset.digits=pp+rhs->digits;	     /* wider context */
593472ac97cdSTom Musta       } /* Newton's iteration */
593572ac97cdSTom Musta 
593672ac97cdSTom Musta     #if DECCHECK
593772ac97cdSTom Musta     /* just a sanity check; remove the test to show always */
593872ac97cdSTom Musta     if (iterations>24)
593972ac97cdSTom Musta       printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
594072ac97cdSTom Musta 	    iterations, *status, p, rhs->digits);
594172ac97cdSTom Musta     #endif
594272ac97cdSTom Musta 
594372ac97cdSTom Musta     /* Copy and round the result to res */
594472ac97cdSTom Musta     residue=1;				/* indicate dirt to right */
594572ac97cdSTom Musta     if (ISZERO(a)) residue=0;		/* .. unless underflowed to 0 */
594672ac97cdSTom Musta     aset.digits=set->digits;		/* [use default rounding] */
594772ac97cdSTom Musta     decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
594872ac97cdSTom Musta     decFinish(res, set, &residue, status);	 /* cleanup/set flags */
594972ac97cdSTom Musta     } while(0);				/* end protected */
595072ac97cdSTom Musta 
595172ac97cdSTom Musta   if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
595272ac97cdSTom Musta   if (allocbufb!=NULL) free(allocbufb); /* .. */
595372ac97cdSTom Musta   /* [status is handled by caller] */
595472ac97cdSTom Musta   return res;
595572ac97cdSTom Musta   } /* decLnOp */
595672ac97cdSTom Musta 
595772ac97cdSTom Musta /* ------------------------------------------------------------------ */
595872ac97cdSTom Musta /* decQuantizeOp  -- force exponent to requested value		      */
595972ac97cdSTom Musta /*								      */
596072ac97cdSTom Musta /*   This computes C = op(A, B), where op adjusts the coefficient     */
596172ac97cdSTom Musta /*   of C (by rounding or shifting) such that the exponent (-scale)   */
596272ac97cdSTom Musta /*   of C has the value B or matches the exponent of B.		      */
596372ac97cdSTom Musta /*   The numerical value of C will equal A, except for the effects of */
596472ac97cdSTom Musta /*   any rounding that occurred.				      */
596572ac97cdSTom Musta /*								      */
596672ac97cdSTom Musta /*   res is C, the result.  C may be A or B			      */
596772ac97cdSTom Musta /*   lhs is A, the number to adjust				      */
596872ac97cdSTom Musta /*   rhs is B, the requested exponent				      */
596972ac97cdSTom Musta /*   set is the context						      */
597072ac97cdSTom Musta /*   quant is 1 for quantize or 0 for rescale			      */
597172ac97cdSTom Musta /*   status is the status accumulator (this can be called without     */
597272ac97cdSTom Musta /*	    risk of control loss)				      */
597372ac97cdSTom Musta /*								      */
597472ac97cdSTom Musta /* C must have space for set->digits digits.			      */
597572ac97cdSTom Musta /*								      */
597672ac97cdSTom Musta /* Unless there is an error or the result is infinite, the exponent   */
597772ac97cdSTom Musta /* after the operation is guaranteed to be that requested.	      */
597872ac97cdSTom Musta /* ------------------------------------------------------------------ */
597972ac97cdSTom Musta static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs,
598072ac97cdSTom Musta 				 const decNumber *rhs, decContext *set,
598172ac97cdSTom Musta 				 Flag quant, uInt *status) {
598272ac97cdSTom Musta   #if DECSUBSET
598372ac97cdSTom Musta   decNumber *alloclhs=NULL;	   /* non-NULL if rounded lhs allocated */
598472ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* .., rhs */
598572ac97cdSTom Musta   #endif
598672ac97cdSTom Musta   const decNumber *inrhs=rhs;	   /* save original rhs */
598772ac97cdSTom Musta   Int	reqdigits=set->digits;	   /* requested DIGITS */
598872ac97cdSTom Musta   Int	reqexp;			   /* requested exponent [-scale] */
598972ac97cdSTom Musta   Int	residue=0;		   /* rounding residue */
599072ac97cdSTom Musta   Int	etiny=set->emin-(reqdigits-1);
599172ac97cdSTom Musta 
599272ac97cdSTom Musta   #if DECCHECK
599372ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
599472ac97cdSTom Musta   #endif
599572ac97cdSTom Musta 
599672ac97cdSTom Musta   do {				   /* protect allocated storage */
599772ac97cdSTom Musta     #if DECSUBSET
599872ac97cdSTom Musta     if (!set->extended) {
599972ac97cdSTom Musta       /* reduce operands and set lostDigits status, as needed */
600072ac97cdSTom Musta       if (lhs->digits>reqdigits) {
600172ac97cdSTom Musta 	alloclhs=decRoundOperand(lhs, set, status);
600272ac97cdSTom Musta 	if (alloclhs==NULL) break;
600372ac97cdSTom Musta 	lhs=alloclhs;
600472ac97cdSTom Musta 	}
600572ac97cdSTom Musta       if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */
600672ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, status);
600772ac97cdSTom Musta 	if (allocrhs==NULL) break;
600872ac97cdSTom Musta 	rhs=allocrhs;
600972ac97cdSTom Musta 	}
601072ac97cdSTom Musta       }
601172ac97cdSTom Musta     #endif
601272ac97cdSTom Musta     /* [following code does not require input rounding] */
601372ac97cdSTom Musta 
601472ac97cdSTom Musta     /* Handle special values */
601572ac97cdSTom Musta     if (SPECIALARGS) {
601672ac97cdSTom Musta       /* NaNs get usual processing */
601772ac97cdSTom Musta       if (SPECIALARGS & (DECSNAN | DECNAN))
601872ac97cdSTom Musta 	decNaNs(res, lhs, rhs, set, status);
601972ac97cdSTom Musta       /* one infinity but not both is bad */
602072ac97cdSTom Musta       else if ((lhs->bits ^ rhs->bits) & DECINF)
602172ac97cdSTom Musta 	*status|=DEC_Invalid_operation;
602272ac97cdSTom Musta       /* both infinity: return lhs */
602372ac97cdSTom Musta       else decNumberCopy(res, lhs);	     /* [nop if in place] */
602472ac97cdSTom Musta       break;
602572ac97cdSTom Musta       }
602672ac97cdSTom Musta 
602772ac97cdSTom Musta     /* set requested exponent */
602872ac97cdSTom Musta     if (quant) reqexp=inrhs->exponent;	/* quantize -- match exponents */
602972ac97cdSTom Musta      else {				/* rescale -- use value of rhs */
603072ac97cdSTom Musta       /* Original rhs must be an integer that fits and is in range, */
603172ac97cdSTom Musta       /* which could be from -1999999997 to +999999999, thanks to */
603272ac97cdSTom Musta       /* subnormals */
603372ac97cdSTom Musta       reqexp=decGetInt(inrhs);		     /* [cannot fail] */
603472ac97cdSTom Musta       }
603572ac97cdSTom Musta 
603672ac97cdSTom Musta     #if DECSUBSET
603772ac97cdSTom Musta     if (!set->extended) etiny=set->emin;     /* no subnormals */
603872ac97cdSTom Musta     #endif
603972ac97cdSTom Musta 
604072ac97cdSTom Musta     if (reqexp==BADINT			     /* bad (rescale only) or .. */
604172ac97cdSTom Musta      || reqexp==BIGODD || reqexp==BIGEVEN    /* very big (ditto) or .. */
604272ac97cdSTom Musta      || (reqexp<etiny)			     /* < lowest */
604372ac97cdSTom Musta      || (reqexp>set->emax)) {		     /* > emax */
604472ac97cdSTom Musta       *status|=DEC_Invalid_operation;
604572ac97cdSTom Musta       break;}
604672ac97cdSTom Musta 
604772ac97cdSTom Musta     /* the RHS has been processed, so it can be overwritten now if necessary */
604872ac97cdSTom Musta     if (ISZERO(lhs)) {			     /* zero coefficient unchanged */
604972ac97cdSTom Musta       decNumberCopy(res, lhs);		     /* [nop if in place] */
605072ac97cdSTom Musta       res->exponent=reqexp;		     /* .. just set exponent */
605172ac97cdSTom Musta       #if DECSUBSET
605272ac97cdSTom Musta       if (!set->extended) res->bits=0;	     /* subset specification; no -0 */
605372ac97cdSTom Musta       #endif
605472ac97cdSTom Musta       }
605572ac97cdSTom Musta      else {				     /* non-zero lhs */
605672ac97cdSTom Musta       Int adjust=reqexp-lhs->exponent;	     /* digit adjustment needed */
605772ac97cdSTom Musta       /* if adjusted coefficient will definitely not fit, give up now */
605872ac97cdSTom Musta       if ((lhs->digits-adjust)>reqdigits) {
605972ac97cdSTom Musta 	*status|=DEC_Invalid_operation;
606072ac97cdSTom Musta 	break;
606172ac97cdSTom Musta 	}
606272ac97cdSTom Musta 
606372ac97cdSTom Musta       if (adjust>0) {			     /* increasing exponent */
606472ac97cdSTom Musta 	/* this will decrease the length of the coefficient by adjust */
606572ac97cdSTom Musta 	/* digits, and must round as it does so */
606672ac97cdSTom Musta 	decContext workset;		     /* work */
606772ac97cdSTom Musta 	workset=*set;			     /* clone rounding, etc. */
606872ac97cdSTom Musta 	workset.digits=lhs->digits-adjust;   /* set requested length */
606972ac97cdSTom Musta 	/* [note that the latter can be <1, here] */
607072ac97cdSTom Musta 	decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */
607172ac97cdSTom Musta 	decApplyRound(res, &workset, residue, status);	  /* .. and round */
607272ac97cdSTom Musta 	residue=0;					  /* [used] */
607372ac97cdSTom Musta 	/* If just rounded a 999s case, exponent will be off by one; */
607472ac97cdSTom Musta 	/* adjust back (after checking space), if so. */
607572ac97cdSTom Musta 	if (res->exponent>reqexp) {
607672ac97cdSTom Musta 	  /* re-check needed, e.g., for quantize(0.9999, 0.001) under */
607772ac97cdSTom Musta 	  /* set->digits==3 */
607872ac97cdSTom Musta 	  if (res->digits==reqdigits) {	     /* cannot shift by 1 */
607972ac97cdSTom Musta 	    *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */
608072ac97cdSTom Musta 	    *status|=DEC_Invalid_operation;
608172ac97cdSTom Musta 	    break;
608272ac97cdSTom Musta 	    }
608372ac97cdSTom Musta 	  res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */
608472ac97cdSTom Musta 	  res->exponent--;		     /* (re)adjust the exponent. */
608572ac97cdSTom Musta 	  }
608672ac97cdSTom Musta 	#if DECSUBSET
608772ac97cdSTom Musta 	if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */
608872ac97cdSTom Musta 	#endif
608972ac97cdSTom Musta 	} /* increase */
609072ac97cdSTom Musta        else /* adjust<=0 */ {		     /* decreasing or = exponent */
609172ac97cdSTom Musta 	/* this will increase the length of the coefficient by -adjust */
609272ac97cdSTom Musta 	/* digits, by adding zero or more trailing zeros; this is */
609372ac97cdSTom Musta 	/* already checked for fit, above */
609472ac97cdSTom Musta 	decNumberCopy(res, lhs);	     /* [it will fit] */
609572ac97cdSTom Musta 	/* if padding needed (adjust<0), add it now... */
609672ac97cdSTom Musta 	if (adjust<0) {
609772ac97cdSTom Musta 	  res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
609872ac97cdSTom Musta 	  res->exponent+=adjust;	     /* adjust the exponent */
609972ac97cdSTom Musta 	  }
610072ac97cdSTom Musta 	} /* decrease */
610172ac97cdSTom Musta       } /* non-zero */
610272ac97cdSTom Musta 
610372ac97cdSTom Musta     /* Check for overflow [do not use Finalize in this case, as an */
610472ac97cdSTom Musta     /* overflow here is a "don't fit" situation] */
610572ac97cdSTom Musta     if (res->exponent>set->emax-res->digits+1) {  /* too big */
610672ac97cdSTom Musta       *status|=DEC_Invalid_operation;
610772ac97cdSTom Musta       break;
610872ac97cdSTom Musta       }
610972ac97cdSTom Musta      else {
611072ac97cdSTom Musta       decFinalize(res, set, &residue, status);	  /* set subnormal flags */
611172ac97cdSTom Musta       *status&=~DEC_Underflow;		/* suppress Underflow [754r] */
611272ac97cdSTom Musta       }
611372ac97cdSTom Musta     } while(0);				/* end protected */
611472ac97cdSTom Musta 
611572ac97cdSTom Musta   #if DECSUBSET
611672ac97cdSTom Musta   if (allocrhs!=NULL) free(allocrhs);	/* drop any storage used */
611772ac97cdSTom Musta   if (alloclhs!=NULL) free(alloclhs);	/* .. */
611872ac97cdSTom Musta   #endif
611972ac97cdSTom Musta   return res;
612072ac97cdSTom Musta   } /* decQuantizeOp */
612172ac97cdSTom Musta 
612272ac97cdSTom Musta /* ------------------------------------------------------------------ */
612372ac97cdSTom Musta /* decCompareOp -- compare, min, or max two Numbers		      */
612472ac97cdSTom Musta /*								      */
612572ac97cdSTom Musta /*   This computes C = A ? B and carries out one of four operations:  */
612672ac97cdSTom Musta /*     COMPARE	  -- returns the signum (as a number) giving the      */
612772ac97cdSTom Musta /*		     result of a comparison unless one or both	      */
612872ac97cdSTom Musta /*		     operands is a NaN (in which case a NaN results)  */
612972ac97cdSTom Musta /*     COMPSIG	  -- as COMPARE except that a quiet NaN raises	      */
613072ac97cdSTom Musta /*		     Invalid operation.				      */
613172ac97cdSTom Musta /*     COMPMAX	  -- returns the larger of the operands, using the    */
613272ac97cdSTom Musta /*		     754r maxnum operation			      */
613372ac97cdSTom Musta /*     COMPMAXMAG -- ditto, comparing absolute values		      */
613472ac97cdSTom Musta /*     COMPMIN	  -- the 754r minnum operation			      */
613572ac97cdSTom Musta /*     COMPMINMAG -- ditto, comparing absolute values		      */
613672ac97cdSTom Musta /*     COMTOTAL	  -- returns the signum (as a number) giving the      */
613772ac97cdSTom Musta /*		     result of a comparison using 754r total ordering */
613872ac97cdSTom Musta /*								      */
613972ac97cdSTom Musta /*   res is C, the result.  C may be A and/or B (e.g., X=X?X)	      */
614072ac97cdSTom Musta /*   lhs is A							      */
614172ac97cdSTom Musta /*   rhs is B							      */
614272ac97cdSTom Musta /*   set is the context						      */
614372ac97cdSTom Musta /*   op	 is the operation flag					      */
614472ac97cdSTom Musta /*   status is the usual accumulator				      */
614572ac97cdSTom Musta /*								      */
614672ac97cdSTom Musta /* C must have space for one digit for COMPARE or set->digits for     */
614772ac97cdSTom Musta /* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG.			      */
614872ac97cdSTom Musta /* ------------------------------------------------------------------ */
614972ac97cdSTom Musta /* The emphasis here is on speed for common cases, and avoiding	      */
615072ac97cdSTom Musta /* coefficient comparison if possible.				      */
615172ac97cdSTom Musta /* ------------------------------------------------------------------ */
6152d072cdf3SStefan Weil static decNumber *decCompareOp(decNumber *res, const decNumber *lhs,
615372ac97cdSTom Musta                                const decNumber *rhs, decContext *set,
615472ac97cdSTom Musta                                Flag op, uInt *status) {
615572ac97cdSTom Musta   #if DECSUBSET
615672ac97cdSTom Musta   decNumber *alloclhs=NULL;	   /* non-NULL if rounded lhs allocated */
615772ac97cdSTom Musta   decNumber *allocrhs=NULL;	   /* .., rhs */
615872ac97cdSTom Musta   #endif
615972ac97cdSTom Musta   Int	result=0;		   /* default result value */
616072ac97cdSTom Musta   uByte merged;			   /* work */
616172ac97cdSTom Musta 
616272ac97cdSTom Musta   #if DECCHECK
616372ac97cdSTom Musta   if (decCheckOperands(res, lhs, rhs, set)) return res;
616472ac97cdSTom Musta   #endif
616572ac97cdSTom Musta 
616672ac97cdSTom Musta   do {				   /* protect allocated storage */
616772ac97cdSTom Musta     #if DECSUBSET
616872ac97cdSTom Musta     if (!set->extended) {
616972ac97cdSTom Musta       /* reduce operands and set lostDigits status, as needed */
617072ac97cdSTom Musta       if (lhs->digits>set->digits) {
617172ac97cdSTom Musta 	alloclhs=decRoundOperand(lhs, set, status);
617272ac97cdSTom Musta 	if (alloclhs==NULL) {result=BADINT; break;}
617372ac97cdSTom Musta 	lhs=alloclhs;
617472ac97cdSTom Musta 	}
617572ac97cdSTom Musta       if (rhs->digits>set->digits) {
617672ac97cdSTom Musta 	allocrhs=decRoundOperand(rhs, set, status);
617772ac97cdSTom Musta 	if (allocrhs==NULL) {result=BADINT; break;}
617872ac97cdSTom Musta 	rhs=allocrhs;
617972ac97cdSTom Musta 	}
618072ac97cdSTom Musta       }
618172ac97cdSTom Musta     #endif
618272ac97cdSTom Musta     /* [following code does not require input rounding] */
618372ac97cdSTom Musta 
618472ac97cdSTom Musta     /* If total ordering then handle differing signs 'up front' */
618572ac97cdSTom Musta     if (op==COMPTOTAL) {		/* total ordering */
6186d072cdf3SStefan Weil       if (decNumberIsNegative(lhs) && !decNumberIsNegative(rhs)) {
618772ac97cdSTom Musta 	result=-1;
618872ac97cdSTom Musta 	break;
618972ac97cdSTom Musta 	}
6190d072cdf3SStefan Weil       if (!decNumberIsNegative(lhs) && decNumberIsNegative(rhs)) {
619172ac97cdSTom Musta 	result=+1;
619272ac97cdSTom Musta 	break;
619372ac97cdSTom Musta 	}
619472ac97cdSTom Musta       }
619572ac97cdSTom Musta 
619672ac97cdSTom Musta     /* handle NaNs specially; let infinities drop through */
619772ac97cdSTom Musta     /* This assumes sNaN (even just one) leads to NaN. */
619872ac97cdSTom Musta     merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN);
619972ac97cdSTom Musta     if (merged) {			/* a NaN bit set */
620072ac97cdSTom Musta       if (op==COMPARE);			/* result will be NaN */
620172ac97cdSTom Musta        else if (op==COMPSIG)		/* treat qNaN as sNaN */
620272ac97cdSTom Musta 	*status|=DEC_Invalid_operation | DEC_sNaN;
620372ac97cdSTom Musta        else if (op==COMPTOTAL) {	/* total ordering, always finite */
620472ac97cdSTom Musta 	/* signs are known to be the same; compute the ordering here */
620572ac97cdSTom Musta 	/* as if the signs are both positive, then invert for negatives */
620672ac97cdSTom Musta 	if (!decNumberIsNaN(lhs)) result=-1;
620772ac97cdSTom Musta 	 else if (!decNumberIsNaN(rhs)) result=+1;
620872ac97cdSTom Musta 	 /* here if both NaNs */
620972ac97cdSTom Musta 	 else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1;
621072ac97cdSTom Musta 	 else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1;
621172ac97cdSTom Musta 	 else { /* both NaN or both sNaN */
621272ac97cdSTom Musta 	  /* now it just depends on the payload */
621372ac97cdSTom Musta 	  result=decUnitCompare(lhs->lsu, D2U(lhs->digits),
621472ac97cdSTom Musta 				rhs->lsu, D2U(rhs->digits), 0);
621572ac97cdSTom Musta 	  /* [Error not possible, as these are 'aligned'] */
621672ac97cdSTom Musta 	  } /* both same NaNs */
621772ac97cdSTom Musta 	if (decNumberIsNegative(lhs)) result=-result;
621872ac97cdSTom Musta 	break;
621972ac97cdSTom Musta 	} /* total order */
622072ac97cdSTom Musta 
622172ac97cdSTom Musta        else if (merged & DECSNAN);	     /* sNaN -> qNaN */
622272ac97cdSTom Musta        else { /* here if MIN or MAX and one or two quiet NaNs */
622372ac97cdSTom Musta 	/* min or max -- 754r rules ignore single NaN */
622472ac97cdSTom Musta 	if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) {
622572ac97cdSTom Musta 	  /* just one NaN; force choice to be the non-NaN operand */
622672ac97cdSTom Musta 	  op=COMPMAX;
622772ac97cdSTom Musta 	  if (lhs->bits & DECNAN) result=-1; /* pick rhs */
622872ac97cdSTom Musta 			     else result=+1; /* pick lhs */
622972ac97cdSTom Musta 	  break;
623072ac97cdSTom Musta 	  }
623172ac97cdSTom Musta 	} /* max or min */
623272ac97cdSTom Musta       op=COMPNAN;			     /* use special path */
623372ac97cdSTom Musta       decNaNs(res, lhs, rhs, set, status);   /* propagate NaN */
623472ac97cdSTom Musta       break;
623572ac97cdSTom Musta       }
623672ac97cdSTom Musta     /* have numbers */
623772ac97cdSTom Musta     if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1);
623872ac97cdSTom Musta      else result=decCompare(lhs, rhs, 0);    /* sign matters */
623972ac97cdSTom Musta     } while(0);				     /* end protected */
624072ac97cdSTom Musta 
624172ac97cdSTom Musta   if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */
624272ac97cdSTom Musta    else {
624372ac97cdSTom Musta     if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */
624472ac97cdSTom Musta       if (op==COMPTOTAL && result==0) {
624572ac97cdSTom Musta 	/* operands are numerically equal or same NaN (and same sign, */
624672ac97cdSTom Musta 	/* tested first); if identical, leave result 0 */
624772ac97cdSTom Musta 	if (lhs->exponent!=rhs->exponent) {
624872ac97cdSTom Musta 	  if (lhs->exponent<rhs->exponent) result=-1;
624972ac97cdSTom Musta 	   else result=+1;
625072ac97cdSTom Musta 	  if (decNumberIsNegative(lhs)) result=-result;
625172ac97cdSTom Musta 	  } /* lexp!=rexp */
625272ac97cdSTom Musta 	} /* total-order by exponent */
625372ac97cdSTom Musta       decNumberZero(res);		/* [always a valid result] */
625472ac97cdSTom Musta       if (result!=0) {			/* must be -1 or +1 */
625572ac97cdSTom Musta 	*res->lsu=1;
625672ac97cdSTom Musta 	if (result<0) res->bits=DECNEG;
625772ac97cdSTom Musta 	}
625872ac97cdSTom Musta       }
625972ac97cdSTom Musta      else if (op==COMPNAN);		/* special, drop through */
626072ac97cdSTom Musta      else {				/* MAX or MIN, non-NaN result */
626172ac97cdSTom Musta       Int residue=0;			/* rounding accumulator */
626272ac97cdSTom Musta       /* choose the operand for the result */
626372ac97cdSTom Musta       const decNumber *choice;
626472ac97cdSTom Musta       if (result==0) { /* operands are numerically equal */
626572ac97cdSTom Musta 	/* choose according to sign then exponent (see 754r) */
626672ac97cdSTom Musta 	uByte slhs=(lhs->bits & DECNEG);
626772ac97cdSTom Musta 	uByte srhs=(rhs->bits & DECNEG);
626872ac97cdSTom Musta 	#if DECSUBSET
626972ac97cdSTom Musta 	if (!set->extended) {		/* subset: force left-hand */
627072ac97cdSTom Musta 	  op=COMPMAX;
627172ac97cdSTom Musta 	  result=+1;
627272ac97cdSTom Musta 	  }
627372ac97cdSTom Musta 	else
627472ac97cdSTom Musta 	#endif
627572ac97cdSTom Musta 	if (slhs!=srhs) {	   /* signs differ */
627672ac97cdSTom Musta 	  if (slhs) result=-1;	   /* rhs is max */
627772ac97cdSTom Musta 	       else result=+1;	   /* lhs is max */
627872ac97cdSTom Musta 	  }
627972ac97cdSTom Musta 	 else if (slhs && srhs) {  /* both negative */
628072ac97cdSTom Musta 	  if (lhs->exponent<rhs->exponent) result=+1;
628172ac97cdSTom Musta 				      else result=-1;
628272ac97cdSTom Musta 	  /* [if equal, use lhs, technically identical] */
628372ac97cdSTom Musta 	  }
628472ac97cdSTom Musta 	 else {			   /* both positive */
628572ac97cdSTom Musta 	  if (lhs->exponent>rhs->exponent) result=+1;
628672ac97cdSTom Musta 				      else result=-1;
628772ac97cdSTom Musta 	  /* [ditto] */
628872ac97cdSTom Musta 	  }
628972ac97cdSTom Musta 	} /* numerically equal */
629072ac97cdSTom Musta       /* here result will be non-0; reverse if looking for MIN */
629172ac97cdSTom Musta       if (op==COMPMIN || op==COMPMINMAG) result=-result;
629272ac97cdSTom Musta       choice=(result>0 ? lhs : rhs);	/* choose */
629372ac97cdSTom Musta       /* copy chosen to result, rounding if need be */
629472ac97cdSTom Musta       decCopyFit(res, choice, set, &residue, status);
629572ac97cdSTom Musta       decFinish(res, set, &residue, status);
629672ac97cdSTom Musta       }
629772ac97cdSTom Musta     }
629872ac97cdSTom Musta   #if DECSUBSET
629972ac97cdSTom Musta   if (allocrhs!=NULL) free(allocrhs);	/* free any storage used */
630072ac97cdSTom Musta   if (alloclhs!=NULL) free(alloclhs);	/* .. */
630172ac97cdSTom Musta   #endif
630272ac97cdSTom Musta   return res;
630372ac97cdSTom Musta   } /* decCompareOp */
630472ac97cdSTom Musta 
630572ac97cdSTom Musta /* ------------------------------------------------------------------ */
630672ac97cdSTom Musta /* decCompare -- compare two decNumbers by numerical value	      */
630772ac97cdSTom Musta /*								      */
630872ac97cdSTom Musta /*  This routine compares A ? B without altering them.		      */
630972ac97cdSTom Musta /*								      */
631072ac97cdSTom Musta /*  Arg1 is A, a decNumber which is not a NaN			      */
631172ac97cdSTom Musta /*  Arg2 is B, a decNumber which is not a NaN			      */
631272ac97cdSTom Musta /*  Arg3 is 1 for a sign-independent compare, 0 otherwise	      */
631372ac97cdSTom Musta /*								      */
631472ac97cdSTom Musta /*  returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure   */
631572ac97cdSTom Musta /*  (the only possible failure is an allocation error)		      */
631672ac97cdSTom Musta /* ------------------------------------------------------------------ */
631772ac97cdSTom Musta static Int decCompare(const decNumber *lhs, const decNumber *rhs,
631872ac97cdSTom Musta 		      Flag abs) {
631972ac97cdSTom Musta   Int	result;			   /* result value */
632072ac97cdSTom Musta   Int	sigr;			   /* rhs signum */
632172ac97cdSTom Musta   Int	compare;		   /* work */
632272ac97cdSTom Musta 
632372ac97cdSTom Musta   result=1;				     /* assume signum(lhs) */
632472ac97cdSTom Musta   if (ISZERO(lhs)) result=0;
632572ac97cdSTom Musta   if (abs) {
632672ac97cdSTom Musta     if (ISZERO(rhs)) return result;	     /* LHS wins or both 0 */
632772ac97cdSTom Musta     /* RHS is non-zero */
632872ac97cdSTom Musta     if (result==0) return -1;		     /* LHS is 0; RHS wins */
632972ac97cdSTom Musta     /* [here, both non-zero, result=1] */
633072ac97cdSTom Musta     }
633172ac97cdSTom Musta    else {				     /* signs matter */
633272ac97cdSTom Musta     if (result && decNumberIsNegative(lhs)) result=-1;
633372ac97cdSTom Musta     sigr=1;				     /* compute signum(rhs) */
633472ac97cdSTom Musta     if (ISZERO(rhs)) sigr=0;
633572ac97cdSTom Musta      else if (decNumberIsNegative(rhs)) sigr=-1;
633672ac97cdSTom Musta     if (result > sigr) return +1;	     /* L > R, return 1 */
633772ac97cdSTom Musta     if (result < sigr) return -1;	     /* L < R, return -1 */
633872ac97cdSTom Musta     if (result==0) return 0;		       /* both 0 */
633972ac97cdSTom Musta     }
634072ac97cdSTom Musta 
634172ac97cdSTom Musta   /* signums are the same; both are non-zero */
634272ac97cdSTom Musta   if ((lhs->bits | rhs->bits) & DECINF) {    /* one or more infinities */
634372ac97cdSTom Musta     if (decNumberIsInfinite(rhs)) {
634472ac97cdSTom Musta       if (decNumberIsInfinite(lhs)) result=0;/* both infinite */
634572ac97cdSTom Musta        else result=-result;		     /* only rhs infinite */
634672ac97cdSTom Musta       }
634772ac97cdSTom Musta     return result;
634872ac97cdSTom Musta     }
634972ac97cdSTom Musta   /* must compare the coefficients, allowing for exponents */
635072ac97cdSTom Musta   if (lhs->exponent>rhs->exponent) {	     /* LHS exponent larger */
635172ac97cdSTom Musta     /* swap sides, and sign */
635272ac97cdSTom Musta     const decNumber *temp=lhs;
635372ac97cdSTom Musta     lhs=rhs;
635472ac97cdSTom Musta     rhs=temp;
635572ac97cdSTom Musta     result=-result;
635672ac97cdSTom Musta     }
635772ac97cdSTom Musta   compare=decUnitCompare(lhs->lsu, D2U(lhs->digits),
635872ac97cdSTom Musta 			 rhs->lsu, D2U(rhs->digits),
635972ac97cdSTom Musta 			 rhs->exponent-lhs->exponent);
636072ac97cdSTom Musta   if (compare!=BADINT) compare*=result;	     /* comparison succeeded */
636172ac97cdSTom Musta   return compare;
636272ac97cdSTom Musta   } /* decCompare */
636372ac97cdSTom Musta 
636472ac97cdSTom Musta /* ------------------------------------------------------------------ */
636572ac97cdSTom Musta /* decUnitCompare -- compare two >=0 integers in Unit arrays	      */
636672ac97cdSTom Musta /*								      */
636772ac97cdSTom Musta /*  This routine compares A ? B*10**E where A and B are unit arrays   */
636872ac97cdSTom Musta /*  A is a plain integer					      */
636972ac97cdSTom Musta /*  B has an exponent of E (which must be non-negative)		      */
637072ac97cdSTom Musta /*								      */
637172ac97cdSTom Musta /*  Arg1 is A first Unit (lsu)					      */
637272ac97cdSTom Musta /*  Arg2 is A length in Units					      */
637372ac97cdSTom Musta /*  Arg3 is B first Unit (lsu)					      */
637472ac97cdSTom Musta /*  Arg4 is B length in Units					      */
637572ac97cdSTom Musta /*  Arg5 is E (0 if the units are aligned)			      */
637672ac97cdSTom Musta /*								      */
637772ac97cdSTom Musta /*  returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure   */
637872ac97cdSTom Musta /*  (the only possible failure is an allocation error, which can      */
637972ac97cdSTom Musta /*  only occur if E!=0)						      */
638072ac97cdSTom Musta /* ------------------------------------------------------------------ */
638172ac97cdSTom Musta static Int decUnitCompare(const Unit *a, Int alength,
638272ac97cdSTom Musta 			  const Unit *b, Int blength, Int exp) {
638372ac97cdSTom Musta   Unit	*acc;			   /* accumulator for result */
638472ac97cdSTom Musta   Unit	accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */
638572ac97cdSTom Musta   Unit	*allocacc=NULL;		   /* -> allocated acc buffer, iff allocated */
638672ac97cdSTom Musta   Int	accunits, need;		   /* units in use or needed for acc */
638772ac97cdSTom Musta   const Unit *l, *r, *u;	   /* work */
638872ac97cdSTom Musta   Int	expunits, exprem, result;  /* .. */
638972ac97cdSTom Musta 
639072ac97cdSTom Musta   if (exp==0) {			   /* aligned; fastpath */
639172ac97cdSTom Musta     if (alength>blength) return 1;
639272ac97cdSTom Musta     if (alength<blength) return -1;
639372ac97cdSTom Musta     /* same number of units in both -- need unit-by-unit compare */
639472ac97cdSTom Musta     l=a+alength-1;
639572ac97cdSTom Musta     r=b+alength-1;
639672ac97cdSTom Musta     for (;l>=a; l--, r--) {
639772ac97cdSTom Musta       if (*l>*r) return 1;
639872ac97cdSTom Musta       if (*l<*r) return -1;
639972ac97cdSTom Musta       }
640072ac97cdSTom Musta     return 0;			   /* all units match */
640172ac97cdSTom Musta     } /* aligned */
640272ac97cdSTom Musta 
640372ac97cdSTom Musta   /* Unaligned.	 If one is >1 unit longer than the other, padded */
640472ac97cdSTom Musta   /* approximately, then can return easily */
640572ac97cdSTom Musta   if (alength>blength+(Int)D2U(exp)) return 1;
640672ac97cdSTom Musta   if (alength+1<blength+(Int)D2U(exp)) return -1;
640772ac97cdSTom Musta 
640872ac97cdSTom Musta   /* Need to do a real subtract.  For this, a result buffer is needed */
640972ac97cdSTom Musta   /* even though only the sign is of interest.	Its length needs */
641072ac97cdSTom Musta   /* to be the larger of alength and padded blength, +2 */
641172ac97cdSTom Musta   need=blength+D2U(exp);		/* maximum real length of B */
641272ac97cdSTom Musta   if (need<alength) need=alength;
641372ac97cdSTom Musta   need+=2;
641472ac97cdSTom Musta   acc=accbuff;				/* assume use local buffer */
641572ac97cdSTom Musta   if (need*sizeof(Unit)>sizeof(accbuff)) {
641672ac97cdSTom Musta     allocacc=(Unit *)malloc(need*sizeof(Unit));
641772ac97cdSTom Musta     if (allocacc==NULL) return BADINT;	/* hopeless -- abandon */
641872ac97cdSTom Musta     acc=allocacc;
641972ac97cdSTom Musta     }
642072ac97cdSTom Musta   /* Calculate units and remainder from exponent. */
642172ac97cdSTom Musta   expunits=exp/DECDPUN;
642272ac97cdSTom Musta   exprem=exp%DECDPUN;
642372ac97cdSTom Musta   /* subtract [A+B*(-m)] */
642472ac97cdSTom Musta   accunits=decUnitAddSub(a, alength, b, blength, expunits, acc,
642572ac97cdSTom Musta 			 -(Int)powers[exprem]);
642672ac97cdSTom Musta   /* [UnitAddSub result may have leading zeros, even on zero] */
642772ac97cdSTom Musta   if (accunits<0) result=-1;		/* negative result */
642872ac97cdSTom Musta    else {				/* non-negative result */
642972ac97cdSTom Musta     /* check units of the result before freeing any storage */
643072ac97cdSTom Musta     for (u=acc; u<acc+accunits-1 && *u==0;) u++;
643172ac97cdSTom Musta     result=(*u==0 ? 0 : +1);
643272ac97cdSTom Musta     }
643372ac97cdSTom Musta   /* clean up and return the result */
643472ac97cdSTom Musta   if (allocacc!=NULL) free(allocacc);	/* drop any storage used */
643572ac97cdSTom Musta   return result;
643672ac97cdSTom Musta   } /* decUnitCompare */
643772ac97cdSTom Musta 
643872ac97cdSTom Musta /* ------------------------------------------------------------------ */
643972ac97cdSTom Musta /* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays   */
644072ac97cdSTom Musta /*								      */
644172ac97cdSTom Musta /*  This routine performs the calculation:			      */
644272ac97cdSTom Musta /*								      */
644372ac97cdSTom Musta /*  C=A+(B*M)							      */
644472ac97cdSTom Musta /*								      */
644572ac97cdSTom Musta /*  Where M is in the range -DECDPUNMAX through +DECDPUNMAX.	      */
644672ac97cdSTom Musta /*								      */
644772ac97cdSTom Musta /*  A may be shorter or longer than B.				      */
644872ac97cdSTom Musta /*								      */
644972ac97cdSTom Musta /*  Leading zeros are not removed after a calculation.	The result is */
645072ac97cdSTom Musta /*  either the same length as the longer of A and B (adding any	      */
645172ac97cdSTom Musta /*  shift), or one Unit longer than that (if a Unit carry occurred).  */
645272ac97cdSTom Musta /*								      */
645372ac97cdSTom Musta /*  A and B content are not altered unless C is also A or B.	      */
645472ac97cdSTom Musta /*  C may be the same array as A or B, but only if no zero padding is */
645572ac97cdSTom Musta /*  requested (that is, C may be B only if bshift==0).		      */
645672ac97cdSTom Musta /*  C is filled from the lsu; only those units necessary to complete  */
645772ac97cdSTom Musta /*  the calculation are referenced.				      */
645872ac97cdSTom Musta /*								      */
645972ac97cdSTom Musta /*  Arg1 is A first Unit (lsu)					      */
646072ac97cdSTom Musta /*  Arg2 is A length in Units					      */
646172ac97cdSTom Musta /*  Arg3 is B first Unit (lsu)					      */
646272ac97cdSTom Musta /*  Arg4 is B length in Units					      */
646372ac97cdSTom Musta /*  Arg5 is B shift in Units  (>=0; pads with 0 units if positive)    */
646472ac97cdSTom Musta /*  Arg6 is C first Unit (lsu)					      */
646572ac97cdSTom Musta /*  Arg7 is M, the multiplier					      */
646672ac97cdSTom Musta /*								      */
646772ac97cdSTom Musta /*  returns the count of Units written to C, which will be non-zero   */
646872ac97cdSTom Musta /*  and negated if the result is negative.  That is, the sign of the  */
646972ac97cdSTom Musta /*  returned Int is the sign of the result (positive for zero) and    */
647072ac97cdSTom Musta /*  the absolute value of the Int is the count of Units.	      */
647172ac97cdSTom Musta /*								      */
647272ac97cdSTom Musta /*  It is the caller's responsibility to make sure that C size is     */
647372ac97cdSTom Musta /*  safe, allowing space if necessary for a one-Unit carry.	      */
647472ac97cdSTom Musta /*								      */
647572ac97cdSTom Musta /*  This routine is severely performance-critical; *any* change here  */
647672ac97cdSTom Musta /*  must be measured (timed) to assure no performance degradation.    */
647772ac97cdSTom Musta /*  In particular, trickery here tends to be counter-productive, as   */
647872ac97cdSTom Musta /*  increased complexity of code hurts register optimizations on      */
647972ac97cdSTom Musta /*  register-poor architectures.  Avoiding divisions is nearly	      */
648072ac97cdSTom Musta /*  always a Good Idea, however.				      */
648172ac97cdSTom Musta /*								      */
648272ac97cdSTom Musta /* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark  */
648372ac97cdSTom Musta /* (IBM Warwick, UK) for some of the ideas used in this routine.      */
648472ac97cdSTom Musta /* ------------------------------------------------------------------ */
648572ac97cdSTom Musta static Int decUnitAddSub(const Unit *a, Int alength,
648672ac97cdSTom Musta 			 const Unit *b, Int blength, Int bshift,
648772ac97cdSTom Musta 			 Unit *c, Int m) {
648872ac97cdSTom Musta   const Unit *alsu=a;		   /* A lsu [need to remember it] */
648972ac97cdSTom Musta   Unit *clsu=c;			   /* C ditto */
649072ac97cdSTom Musta   Unit *minC;			   /* low water mark for C */
649172ac97cdSTom Musta   Unit *maxC;			   /* high water mark for C */
649272ac97cdSTom Musta   eInt carry=0;			   /* carry integer (could be Long) */
649372ac97cdSTom Musta   Int  add;			   /* work */
649472ac97cdSTom Musta   #if DECDPUN<=4		   /* myriadal, millenary, etc. */
649572ac97cdSTom Musta   Int  est;			   /* estimated quotient */
649672ac97cdSTom Musta   #endif
649772ac97cdSTom Musta 
649872ac97cdSTom Musta   #if DECTRACE
649972ac97cdSTom Musta   if (alength<1 || blength<1)
650072ac97cdSTom Musta     printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m);
650172ac97cdSTom Musta   #endif
650272ac97cdSTom Musta 
650372ac97cdSTom Musta   maxC=c+alength;		   /* A is usually the longer */
650472ac97cdSTom Musta   minC=c+blength;		   /* .. and B the shorter */
650572ac97cdSTom Musta   if (bshift!=0) {		   /* B is shifted; low As copy across */
650672ac97cdSTom Musta     minC+=bshift;
650772ac97cdSTom Musta     /* if in place [common], skip copy unless there's a gap [rare] */
650872ac97cdSTom Musta     if (a==c && bshift<=alength) {
650972ac97cdSTom Musta       c+=bshift;
651072ac97cdSTom Musta       a+=bshift;
651172ac97cdSTom Musta       }
651272ac97cdSTom Musta      else for (; c<clsu+bshift; a++, c++) {  /* copy needed */
651372ac97cdSTom Musta       if (a<alsu+alength) *c=*a;
651472ac97cdSTom Musta        else *c=0;
651572ac97cdSTom Musta       }
651672ac97cdSTom Musta     }
651772ac97cdSTom Musta   if (minC>maxC) { /* swap */
651872ac97cdSTom Musta     Unit *hold=minC;
651972ac97cdSTom Musta     minC=maxC;
652072ac97cdSTom Musta     maxC=hold;
652172ac97cdSTom Musta     }
652272ac97cdSTom Musta 
652372ac97cdSTom Musta   /* For speed, do the addition as two loops; the first where both A */
652472ac97cdSTom Musta   /* and B contribute, and the second (if necessary) where only one or */
652572ac97cdSTom Musta   /* other of the numbers contribute. */
652672ac97cdSTom Musta   /* Carry handling is the same (i.e., duplicated) in each case. */
652772ac97cdSTom Musta   for (; c<minC; c++) {
652872ac97cdSTom Musta     carry+=*a;
652972ac97cdSTom Musta     a++;
653072ac97cdSTom Musta     carry+=((eInt)*b)*m;		/* [special-casing m=1/-1 */
653172ac97cdSTom Musta     b++;				/* here is not a win] */
653272ac97cdSTom Musta     /* here carry is new Unit of digits; it could be +ve or -ve */
653372ac97cdSTom Musta     if ((ueInt)carry<=DECDPUNMAX) {	/* fastpath 0-DECDPUNMAX */
653472ac97cdSTom Musta       *c=(Unit)carry;
653572ac97cdSTom Musta       carry=0;
653672ac97cdSTom Musta       continue;
653772ac97cdSTom Musta       }
653872ac97cdSTom Musta     #if DECDPUN==4			     /* use divide-by-multiply */
653972ac97cdSTom Musta       if (carry>=0) {
654072ac97cdSTom Musta 	est=(((ueInt)carry>>11)*53687)>>18;
654172ac97cdSTom Musta 	*c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
654272ac97cdSTom Musta 	carry=est;			     /* likely quotient [89%] */
654372ac97cdSTom Musta 	if (*c<DECDPUNMAX+1) continue;	     /* estimate was correct */
654472ac97cdSTom Musta 	carry++;
654572ac97cdSTom Musta 	*c-=DECDPUNMAX+1;
654672ac97cdSTom Musta 	continue;
654772ac97cdSTom Musta 	}
654872ac97cdSTom Musta       /* negative case */
654972ac97cdSTom Musta       carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
655072ac97cdSTom Musta       est=(((ueInt)carry>>11)*53687)>>18;
655172ac97cdSTom Musta       *c=(Unit)(carry-est*(DECDPUNMAX+1));
655272ac97cdSTom Musta       carry=est-(DECDPUNMAX+1);		     /* correctly negative */
655372ac97cdSTom Musta       if (*c<DECDPUNMAX+1) continue;	     /* was OK */
655472ac97cdSTom Musta       carry++;
655572ac97cdSTom Musta       *c-=DECDPUNMAX+1;
655672ac97cdSTom Musta     #elif DECDPUN==3
655772ac97cdSTom Musta       if (carry>=0) {
655872ac97cdSTom Musta 	est=(((ueInt)carry>>3)*16777)>>21;
655972ac97cdSTom Musta 	*c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
656072ac97cdSTom Musta 	carry=est;			     /* likely quotient [99%] */
656172ac97cdSTom Musta 	if (*c<DECDPUNMAX+1) continue;	     /* estimate was correct */
656272ac97cdSTom Musta 	carry++;
656372ac97cdSTom Musta 	*c-=DECDPUNMAX+1;
656472ac97cdSTom Musta 	continue;
656572ac97cdSTom Musta 	}
656672ac97cdSTom Musta       /* negative case */
656772ac97cdSTom Musta       carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
656872ac97cdSTom Musta       est=(((ueInt)carry>>3)*16777)>>21;
656972ac97cdSTom Musta       *c=(Unit)(carry-est*(DECDPUNMAX+1));
657072ac97cdSTom Musta       carry=est-(DECDPUNMAX+1);		     /* correctly negative */
657172ac97cdSTom Musta       if (*c<DECDPUNMAX+1) continue;	     /* was OK */
657272ac97cdSTom Musta       carry++;
657372ac97cdSTom Musta       *c-=DECDPUNMAX+1;
657472ac97cdSTom Musta     #elif DECDPUN<=2
657572ac97cdSTom Musta       /* Can use QUOT10 as carry <= 4 digits */
657672ac97cdSTom Musta       if (carry>=0) {
657772ac97cdSTom Musta 	est=QUOT10(carry, DECDPUN);
657872ac97cdSTom Musta 	*c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
657972ac97cdSTom Musta 	carry=est;			     /* quotient */
658072ac97cdSTom Musta 	continue;
658172ac97cdSTom Musta 	}
658272ac97cdSTom Musta       /* negative case */
658372ac97cdSTom Musta       carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
658472ac97cdSTom Musta       est=QUOT10(carry, DECDPUN);
658572ac97cdSTom Musta       *c=(Unit)(carry-est*(DECDPUNMAX+1));
658672ac97cdSTom Musta       carry=est-(DECDPUNMAX+1);		     /* correctly negative */
658772ac97cdSTom Musta     #else
658872ac97cdSTom Musta       /* remainder operator is undefined if negative, so must test */
658972ac97cdSTom Musta       if ((ueInt)carry<(DECDPUNMAX+1)*2) {   /* fastpath carry +1 */
659072ac97cdSTom Musta 	*c=(Unit)(carry-(DECDPUNMAX+1));     /* [helps additions] */
659172ac97cdSTom Musta 	carry=1;
659272ac97cdSTom Musta 	continue;
659372ac97cdSTom Musta 	}
659472ac97cdSTom Musta       if (carry>=0) {
659572ac97cdSTom Musta 	*c=(Unit)(carry%(DECDPUNMAX+1));
659672ac97cdSTom Musta 	carry=carry/(DECDPUNMAX+1);
659772ac97cdSTom Musta 	continue;
659872ac97cdSTom Musta 	}
659972ac97cdSTom Musta       /* negative case */
660072ac97cdSTom Musta       carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
660172ac97cdSTom Musta       *c=(Unit)(carry%(DECDPUNMAX+1));
660272ac97cdSTom Musta       carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
660372ac97cdSTom Musta     #endif
660472ac97cdSTom Musta     } /* c */
660572ac97cdSTom Musta 
660672ac97cdSTom Musta   /* now may have one or other to complete */
660772ac97cdSTom Musta   /* [pretest to avoid loop setup/shutdown] */
660872ac97cdSTom Musta   if (c<maxC) for (; c<maxC; c++) {
660972ac97cdSTom Musta     if (a<alsu+alength) {		/* still in A */
661072ac97cdSTom Musta       carry+=*a;
661172ac97cdSTom Musta       a++;
661272ac97cdSTom Musta       }
661372ac97cdSTom Musta      else {				/* inside B */
661472ac97cdSTom Musta       carry+=((eInt)*b)*m;
661572ac97cdSTom Musta       b++;
661672ac97cdSTom Musta       }
661772ac97cdSTom Musta     /* here carry is new Unit of digits; it could be +ve or -ve and */
661872ac97cdSTom Musta     /* magnitude up to DECDPUNMAX squared */
661972ac97cdSTom Musta     if ((ueInt)carry<=DECDPUNMAX) {	/* fastpath 0-DECDPUNMAX */
662072ac97cdSTom Musta       *c=(Unit)carry;
662172ac97cdSTom Musta       carry=0;
662272ac97cdSTom Musta       continue;
662372ac97cdSTom Musta       }
662472ac97cdSTom Musta     /* result for this unit is negative or >DECDPUNMAX */
662572ac97cdSTom Musta     #if DECDPUN==4			     /* use divide-by-multiply */
662672ac97cdSTom Musta       if (carry>=0) {
662772ac97cdSTom Musta 	est=(((ueInt)carry>>11)*53687)>>18;
662872ac97cdSTom Musta 	*c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
662972ac97cdSTom Musta 	carry=est;			     /* likely quotient [79.7%] */
663072ac97cdSTom Musta 	if (*c<DECDPUNMAX+1) continue;	     /* estimate was correct */
663172ac97cdSTom Musta 	carry++;
663272ac97cdSTom Musta 	*c-=DECDPUNMAX+1;
663372ac97cdSTom Musta 	continue;
663472ac97cdSTom Musta 	}
663572ac97cdSTom Musta       /* negative case */
663672ac97cdSTom Musta       carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
663772ac97cdSTom Musta       est=(((ueInt)carry>>11)*53687)>>18;
663872ac97cdSTom Musta       *c=(Unit)(carry-est*(DECDPUNMAX+1));
663972ac97cdSTom Musta       carry=est-(DECDPUNMAX+1);		     /* correctly negative */
664072ac97cdSTom Musta       if (*c<DECDPUNMAX+1) continue;	     /* was OK */
664172ac97cdSTom Musta       carry++;
664272ac97cdSTom Musta       *c-=DECDPUNMAX+1;
664372ac97cdSTom Musta     #elif DECDPUN==3
664472ac97cdSTom Musta       if (carry>=0) {
664572ac97cdSTom Musta 	est=(((ueInt)carry>>3)*16777)>>21;
664672ac97cdSTom Musta 	*c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
664772ac97cdSTom Musta 	carry=est;			     /* likely quotient [99%] */
664872ac97cdSTom Musta 	if (*c<DECDPUNMAX+1) continue;	     /* estimate was correct */
664972ac97cdSTom Musta 	carry++;
665072ac97cdSTom Musta 	*c-=DECDPUNMAX+1;
665172ac97cdSTom Musta 	continue;
665272ac97cdSTom Musta 	}
665372ac97cdSTom Musta       /* negative case */
665472ac97cdSTom Musta       carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
665572ac97cdSTom Musta       est=(((ueInt)carry>>3)*16777)>>21;
665672ac97cdSTom Musta       *c=(Unit)(carry-est*(DECDPUNMAX+1));
665772ac97cdSTom Musta       carry=est-(DECDPUNMAX+1);		     /* correctly negative */
665872ac97cdSTom Musta       if (*c<DECDPUNMAX+1) continue;	     /* was OK */
665972ac97cdSTom Musta       carry++;
666072ac97cdSTom Musta       *c-=DECDPUNMAX+1;
666172ac97cdSTom Musta     #elif DECDPUN<=2
666272ac97cdSTom Musta       if (carry>=0) {
666372ac97cdSTom Musta 	est=QUOT10(carry, DECDPUN);
666472ac97cdSTom Musta 	*c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
666572ac97cdSTom Musta 	carry=est;			     /* quotient */
666672ac97cdSTom Musta 	continue;
666772ac97cdSTom Musta 	}
666872ac97cdSTom Musta       /* negative case */
666972ac97cdSTom Musta       carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
667072ac97cdSTom Musta       est=QUOT10(carry, DECDPUN);
667172ac97cdSTom Musta       *c=(Unit)(carry-est*(DECDPUNMAX+1));
667272ac97cdSTom Musta       carry=est-(DECDPUNMAX+1);		     /* correctly negative */
667372ac97cdSTom Musta     #else
667472ac97cdSTom Musta       if ((ueInt)carry<(DECDPUNMAX+1)*2){    /* fastpath carry 1 */
667572ac97cdSTom Musta 	*c=(Unit)(carry-(DECDPUNMAX+1));
667672ac97cdSTom Musta 	carry=1;
667772ac97cdSTom Musta 	continue;
667872ac97cdSTom Musta 	}
667972ac97cdSTom Musta       /* remainder operator is undefined if negative, so must test */
668072ac97cdSTom Musta       if (carry>=0) {
668172ac97cdSTom Musta 	*c=(Unit)(carry%(DECDPUNMAX+1));
668272ac97cdSTom Musta 	carry=carry/(DECDPUNMAX+1);
668372ac97cdSTom Musta 	continue;
668472ac97cdSTom Musta 	}
668572ac97cdSTom Musta       /* negative case */
668672ac97cdSTom Musta       carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
668772ac97cdSTom Musta       *c=(Unit)(carry%(DECDPUNMAX+1));
668872ac97cdSTom Musta       carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
668972ac97cdSTom Musta     #endif
669072ac97cdSTom Musta     } /* c */
669172ac97cdSTom Musta 
669272ac97cdSTom Musta   /* OK, all A and B processed; might still have carry or borrow */
669372ac97cdSTom Musta   /* return number of Units in the result, negated if a borrow */
669472ac97cdSTom Musta   if (carry==0) return c-clsu;	   /* no carry, so no more to do */
669572ac97cdSTom Musta   if (carry>0) {		   /* positive carry */
669672ac97cdSTom Musta     *c=(Unit)carry;		   /* place as new unit */
669772ac97cdSTom Musta     c++;			   /* .. */
669872ac97cdSTom Musta     return c-clsu;
669972ac97cdSTom Musta     }
670072ac97cdSTom Musta   /* -ve carry: it's a borrow; complement needed */
670172ac97cdSTom Musta   add=1;			   /* temporary carry... */
670272ac97cdSTom Musta   for (c=clsu; c<maxC; c++) {
670372ac97cdSTom Musta     add=DECDPUNMAX+add-*c;
670472ac97cdSTom Musta     if (add<=DECDPUNMAX) {
670572ac97cdSTom Musta       *c=(Unit)add;
670672ac97cdSTom Musta       add=0;
670772ac97cdSTom Musta       }
670872ac97cdSTom Musta      else {
670972ac97cdSTom Musta       *c=0;
671072ac97cdSTom Musta       add=1;
671172ac97cdSTom Musta       }
671272ac97cdSTom Musta     }
671372ac97cdSTom Musta   /* add an extra unit iff it would be non-zero */
671472ac97cdSTom Musta   #if DECTRACE
671572ac97cdSTom Musta     printf("UAS borrow: add %ld, carry %ld\n", add, carry);
671672ac97cdSTom Musta   #endif
671772ac97cdSTom Musta   if ((add-carry-1)!=0) {
671872ac97cdSTom Musta     *c=(Unit)(add-carry-1);
671972ac97cdSTom Musta     c++;		      /* interesting, include it */
672072ac97cdSTom Musta     }
672172ac97cdSTom Musta   return clsu-c;	      /* -ve result indicates borrowed */
672272ac97cdSTom Musta   } /* decUnitAddSub */
672372ac97cdSTom Musta 
672472ac97cdSTom Musta /* ------------------------------------------------------------------ */
672572ac97cdSTom Musta /* decTrim -- trim trailing zeros or normalize			      */
672672ac97cdSTom Musta /*								      */
672772ac97cdSTom Musta /*   dn is the number to trim or normalize			      */
672872ac97cdSTom Musta /*   set is the context to use to check for clamp		      */
672972ac97cdSTom Musta /*   all is 1 to remove all trailing zeros, 0 for just fraction ones  */
673072ac97cdSTom Musta /*   dropped returns the number of discarded trailing zeros	      */
673172ac97cdSTom Musta /*   returns dn							      */
673272ac97cdSTom Musta /*								      */
673372ac97cdSTom Musta /* If clamp is set in the context then the number of zeros trimmed    */
673472ac97cdSTom Musta /* may be limited if the exponent is high.			      */
673572ac97cdSTom Musta /* All fields are updated as required.	This is a utility operation,  */
673672ac97cdSTom Musta /* so special values are unchanged and no error is possible.	      */
673772ac97cdSTom Musta /* ------------------------------------------------------------------ */
673872ac97cdSTom Musta static decNumber * decTrim(decNumber *dn, decContext *set, Flag all,
673972ac97cdSTom Musta 			   Int *dropped) {
674072ac97cdSTom Musta   Int	d, exp;			   /* work */
674172ac97cdSTom Musta   uInt	cut;			   /* .. */
674272ac97cdSTom Musta   Unit	*up;			   /* -> current Unit */
674372ac97cdSTom Musta 
674472ac97cdSTom Musta   #if DECCHECK
674572ac97cdSTom Musta   if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
674672ac97cdSTom Musta   #endif
674772ac97cdSTom Musta 
674872ac97cdSTom Musta   *dropped=0;				/* assume no zeros dropped */
674972ac97cdSTom Musta   if ((dn->bits & DECSPECIAL)		/* fast exit if special .. */
675072ac97cdSTom Musta     || (*dn->lsu & 0x01)) return dn;	/* .. or odd */
675172ac97cdSTom Musta   if (ISZERO(dn)) {			/* .. or 0 */
675272ac97cdSTom Musta     dn->exponent=0;			/* (sign is preserved) */
675372ac97cdSTom Musta     return dn;
675472ac97cdSTom Musta     }
675572ac97cdSTom Musta 
675672ac97cdSTom Musta   /* have a finite number which is even */
675772ac97cdSTom Musta   exp=dn->exponent;
675872ac97cdSTom Musta   cut=1;			   /* digit (1-DECDPUN) in Unit */
675972ac97cdSTom Musta   up=dn->lsu;			   /* -> current Unit */
676072ac97cdSTom Musta   for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */
676172ac97cdSTom Musta     /* slice by powers */
676272ac97cdSTom Musta     #if DECDPUN<=4
676372ac97cdSTom Musta       uInt quot=QUOT10(*up, cut);
676472ac97cdSTom Musta       if ((*up-quot*powers[cut])!=0) break;  /* found non-0 digit */
676572ac97cdSTom Musta     #else
676672ac97cdSTom Musta       if (*up%powers[cut]!=0) break;	     /* found non-0 digit */
676772ac97cdSTom Musta     #endif
676872ac97cdSTom Musta     /* have a trailing 0 */
676972ac97cdSTom Musta     if (!all) {			   /* trimming */
677072ac97cdSTom Musta       /* [if exp>0 then all trailing 0s are significant for trim] */
677172ac97cdSTom Musta       if (exp<=0) {		   /* if digit might be significant */
677272ac97cdSTom Musta 	if (exp==0) break;	   /* then quit */
677372ac97cdSTom Musta 	exp++;			   /* next digit might be significant */
677472ac97cdSTom Musta 	}
677572ac97cdSTom Musta       }
677672ac97cdSTom Musta     cut++;			   /* next power */
677772ac97cdSTom Musta     if (cut>DECDPUN) {		   /* need new Unit */
677872ac97cdSTom Musta       up++;
677972ac97cdSTom Musta       cut=1;
678072ac97cdSTom Musta       }
678172ac97cdSTom Musta     } /* d */
678272ac97cdSTom Musta   if (d==0) return dn;		   /* none to drop */
678372ac97cdSTom Musta 
678472ac97cdSTom Musta   /* may need to limit drop if clamping */
678572ac97cdSTom Musta   if (set->clamp) {
678672ac97cdSTom Musta     Int maxd=set->emax-set->digits+1-dn->exponent;
678772ac97cdSTom Musta     if (maxd<=0) return dn;	   /* nothing possible */
678872ac97cdSTom Musta     if (d>maxd) d=maxd;
678972ac97cdSTom Musta     }
679072ac97cdSTom Musta 
679172ac97cdSTom Musta   /* effect the drop */
679272ac97cdSTom Musta   decShiftToLeast(dn->lsu, D2U(dn->digits), d);
679372ac97cdSTom Musta   dn->exponent+=d;		   /* maintain numerical value */
679472ac97cdSTom Musta   dn->digits-=d;		   /* new length */
679572ac97cdSTom Musta   *dropped=d;			   /* report the count */
679672ac97cdSTom Musta   return dn;
679772ac97cdSTom Musta   } /* decTrim */
679872ac97cdSTom Musta 
679972ac97cdSTom Musta /* ------------------------------------------------------------------ */
680072ac97cdSTom Musta /* decReverse -- reverse a Unit array in place			      */
680172ac97cdSTom Musta /*								      */
680272ac97cdSTom Musta /*   ulo    is the start of the array				      */
680372ac97cdSTom Musta /*   uhi    is the end of the array (highest Unit to include)	      */
680472ac97cdSTom Musta /*								      */
680572ac97cdSTom Musta /* The units ulo through uhi are reversed in place (if the number     */
680672ac97cdSTom Musta /* of units is odd, the middle one is untouched).  Note that the      */
680772ac97cdSTom Musta /* digit(s) in each unit are unaffected.			      */
680872ac97cdSTom Musta /* ------------------------------------------------------------------ */
680972ac97cdSTom Musta static void decReverse(Unit *ulo, Unit *uhi) {
681072ac97cdSTom Musta   Unit temp;
681172ac97cdSTom Musta   for (; ulo<uhi; ulo++, uhi--) {
681272ac97cdSTom Musta     temp=*ulo;
681372ac97cdSTom Musta     *ulo=*uhi;
681472ac97cdSTom Musta     *uhi=temp;
681572ac97cdSTom Musta     }
681672ac97cdSTom Musta   return;
681772ac97cdSTom Musta   } /* decReverse */
681872ac97cdSTom Musta 
681972ac97cdSTom Musta /* ------------------------------------------------------------------ */
682072ac97cdSTom Musta /* decShiftToMost -- shift digits in array towards most significant   */
682172ac97cdSTom Musta /*								      */
682272ac97cdSTom Musta /*   uar    is the array					      */
682372ac97cdSTom Musta /*   digits is the count of digits in use in the array		      */
682472ac97cdSTom Musta /*   shift  is the number of zeros to pad with (least significant);   */
682572ac97cdSTom Musta /*     it must be zero or positive				      */
682672ac97cdSTom Musta /*								      */
682772ac97cdSTom Musta /*   returns the new length of the integer in the array, in digits    */
682872ac97cdSTom Musta /*								      */
682972ac97cdSTom Musta /* No overflow is permitted (that is, the uar array must be known to  */
683072ac97cdSTom Musta /* be large enough to hold the result, after shifting).		      */
683172ac97cdSTom Musta /* ------------------------------------------------------------------ */
683272ac97cdSTom Musta static Int decShiftToMost(Unit *uar, Int digits, Int shift) {
683372ac97cdSTom Musta   Unit	*target, *source, *first;  /* work */
683472ac97cdSTom Musta   Int	cut;			   /* odd 0's to add */
683572ac97cdSTom Musta   uInt	next;			   /* work */
683672ac97cdSTom Musta 
683772ac97cdSTom Musta   if (shift==0) return digits;	   /* [fastpath] nothing to do */
683872ac97cdSTom Musta   if ((digits+shift)<=DECDPUN) {   /* [fastpath] single-unit case */
683972ac97cdSTom Musta     *uar=(Unit)(*uar*powers[shift]);
684072ac97cdSTom Musta     return digits+shift;
684172ac97cdSTom Musta     }
684272ac97cdSTom Musta 
684372ac97cdSTom Musta   next=0;			   /* all paths */
684472ac97cdSTom Musta   source=uar+D2U(digits)-1;	   /* where msu comes from */
684572ac97cdSTom Musta   target=source+D2U(shift);	   /* where upper part of first cut goes */
684672ac97cdSTom Musta   cut=DECDPUN-MSUDIGITS(shift);	   /* where to slice */
684772ac97cdSTom Musta   if (cut==0) {			   /* unit-boundary case */
684872ac97cdSTom Musta     for (; source>=uar; source--, target--) *target=*source;
684972ac97cdSTom Musta     }
685072ac97cdSTom Musta    else {
685172ac97cdSTom Musta     first=uar+D2U(digits+shift)-1; /* where msu of source will end up */
685272ac97cdSTom Musta     for (; source>=uar; source--, target--) {
685372ac97cdSTom Musta       /* split the source Unit and accumulate remainder for next */
685472ac97cdSTom Musta       #if DECDPUN<=4
685572ac97cdSTom Musta 	uInt quot=QUOT10(*source, cut);
685672ac97cdSTom Musta 	uInt rem=*source-quot*powers[cut];
685772ac97cdSTom Musta 	next+=quot;
685872ac97cdSTom Musta       #else
685972ac97cdSTom Musta 	uInt rem=*source%powers[cut];
686072ac97cdSTom Musta 	next+=*source/powers[cut];
686172ac97cdSTom Musta       #endif
686272ac97cdSTom Musta       if (target<=first) *target=(Unit)next;   /* write to target iff valid */
686372ac97cdSTom Musta       next=rem*powers[DECDPUN-cut];	       /* save remainder for next Unit */
686472ac97cdSTom Musta       }
686572ac97cdSTom Musta     } /* shift-move */
686672ac97cdSTom Musta 
686772ac97cdSTom Musta   /* propagate any partial unit to one below and clear the rest */
686872ac97cdSTom Musta   for (; target>=uar; target--) {
686972ac97cdSTom Musta     *target=(Unit)next;
687072ac97cdSTom Musta     next=0;
687172ac97cdSTom Musta     }
687272ac97cdSTom Musta   return digits+shift;
687372ac97cdSTom Musta   } /* decShiftToMost */
687472ac97cdSTom Musta 
687572ac97cdSTom Musta /* ------------------------------------------------------------------ */
687672ac97cdSTom Musta /* decShiftToLeast -- shift digits in array towards least significant */
687772ac97cdSTom Musta /*								      */
687872ac97cdSTom Musta /*   uar   is the array						      */
687972ac97cdSTom Musta /*   units is length of the array, in units			      */
688072ac97cdSTom Musta /*   shift is the number of digits to remove from the lsu end; it     */
688172ac97cdSTom Musta /*     must be zero or positive and <= than units*DECDPUN.	      */
688272ac97cdSTom Musta /*								      */
688372ac97cdSTom Musta /*   returns the new length of the integer in the array, in units     */
688472ac97cdSTom Musta /*								      */
688572ac97cdSTom Musta /* Removed digits are discarded (lost).	 Units not required to hold   */
688672ac97cdSTom Musta /* the final result are unchanged.				      */
688772ac97cdSTom Musta /* ------------------------------------------------------------------ */
688872ac97cdSTom Musta static Int decShiftToLeast(Unit *uar, Int units, Int shift) {
688972ac97cdSTom Musta   Unit	*target, *up;		   /* work */
689072ac97cdSTom Musta   Int	cut, count;		   /* work */
689172ac97cdSTom Musta   Int	quot, rem;		   /* for division */
689272ac97cdSTom Musta 
689372ac97cdSTom Musta   if (shift==0) return units;	   /* [fastpath] nothing to do */
689472ac97cdSTom Musta   if (shift==units*DECDPUN) {	   /* [fastpath] little to do */
689572ac97cdSTom Musta     *uar=0;			   /* all digits cleared gives zero */
689672ac97cdSTom Musta     return 1;			   /* leaves just the one */
689772ac97cdSTom Musta     }
689872ac97cdSTom Musta 
689972ac97cdSTom Musta   target=uar;			   /* both paths */
690072ac97cdSTom Musta   cut=MSUDIGITS(shift);
690172ac97cdSTom Musta   if (cut==DECDPUN) {		   /* unit-boundary case; easy */
690272ac97cdSTom Musta     up=uar+D2U(shift);
690372ac97cdSTom Musta     for (; up<uar+units; target++, up++) *target=*up;
690472ac97cdSTom Musta     return target-uar;
690572ac97cdSTom Musta     }
690672ac97cdSTom Musta 
690772ac97cdSTom Musta   /* messier */
690872ac97cdSTom Musta   up=uar+D2U(shift-cut);	   /* source; correct to whole Units */
690972ac97cdSTom Musta   count=units*DECDPUN-shift;	   /* the maximum new length */
691072ac97cdSTom Musta   #if DECDPUN<=4
691172ac97cdSTom Musta     quot=QUOT10(*up, cut);
691272ac97cdSTom Musta   #else
691372ac97cdSTom Musta     quot=*up/powers[cut];
691472ac97cdSTom Musta   #endif
691572ac97cdSTom Musta   for (; ; target++) {
691672ac97cdSTom Musta     *target=(Unit)quot;
691772ac97cdSTom Musta     count-=(DECDPUN-cut);
691872ac97cdSTom Musta     if (count<=0) break;
691972ac97cdSTom Musta     up++;
692072ac97cdSTom Musta     quot=*up;
692172ac97cdSTom Musta     #if DECDPUN<=4
692272ac97cdSTom Musta       quot=QUOT10(quot, cut);
692372ac97cdSTom Musta       rem=*up-quot*powers[cut];
692472ac97cdSTom Musta     #else
692572ac97cdSTom Musta       rem=quot%powers[cut];
692672ac97cdSTom Musta       quot=quot/powers[cut];
692772ac97cdSTom Musta     #endif
692872ac97cdSTom Musta     *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
692972ac97cdSTom Musta     count-=cut;
693072ac97cdSTom Musta     if (count<=0) break;
693172ac97cdSTom Musta     }
693272ac97cdSTom Musta   return target-uar+1;
693372ac97cdSTom Musta   } /* decShiftToLeast */
693472ac97cdSTom Musta 
693572ac97cdSTom Musta #if DECSUBSET
693672ac97cdSTom Musta /* ------------------------------------------------------------------ */
693772ac97cdSTom Musta /* decRoundOperand -- round an operand	[used for subset only]	      */
693872ac97cdSTom Musta /*								      */
693972ac97cdSTom Musta /*   dn is the number to round (dn->digits is > set->digits)	      */
694072ac97cdSTom Musta /*   set is the relevant context				      */
694172ac97cdSTom Musta /*   status is the status accumulator				      */
694272ac97cdSTom Musta /*								      */
694372ac97cdSTom Musta /*   returns an allocated decNumber with the rounded result.	      */
694472ac97cdSTom Musta /*								      */
694572ac97cdSTom Musta /* lostDigits and other status may be set by this.		      */
694672ac97cdSTom Musta /*								      */
694772ac97cdSTom Musta /* Since the input is an operand, it must not be modified.	      */
694872ac97cdSTom Musta /* Instead, return an allocated decNumber, rounded as required.	      */
694972ac97cdSTom Musta /* It is the caller's responsibility to free the allocated storage.   */
695072ac97cdSTom Musta /*								      */
695172ac97cdSTom Musta /* If no storage is available then the result cannot be used, so NULL */
695272ac97cdSTom Musta /* is returned.							      */
695372ac97cdSTom Musta /* ------------------------------------------------------------------ */
695472ac97cdSTom Musta static decNumber *decRoundOperand(const decNumber *dn, decContext *set,
695572ac97cdSTom Musta 				  uInt *status) {
695672ac97cdSTom Musta   decNumber *res;			/* result structure */
695772ac97cdSTom Musta   uInt newstatus=0;			/* status from round */
695872ac97cdSTom Musta   Int  residue=0;			/* rounding accumulator */
695972ac97cdSTom Musta 
696072ac97cdSTom Musta   /* Allocate storage for the returned decNumber, big enough for the */
696172ac97cdSTom Musta   /* length specified by the context */
696272ac97cdSTom Musta   res=(decNumber *)malloc(sizeof(decNumber)
696372ac97cdSTom Musta 			  +(D2U(set->digits)-1)*sizeof(Unit));
696472ac97cdSTom Musta   if (res==NULL) {
696572ac97cdSTom Musta     *status|=DEC_Insufficient_storage;
696672ac97cdSTom Musta     return NULL;
696772ac97cdSTom Musta     }
696872ac97cdSTom Musta   decCopyFit(res, dn, set, &residue, &newstatus);
696972ac97cdSTom Musta   decApplyRound(res, set, residue, &newstatus);
697072ac97cdSTom Musta 
697172ac97cdSTom Musta   /* If that set Inexact then "lost digits" is raised... */
697272ac97cdSTom Musta   if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits;
697372ac97cdSTom Musta   *status|=newstatus;
697472ac97cdSTom Musta   return res;
697572ac97cdSTom Musta   } /* decRoundOperand */
697672ac97cdSTom Musta #endif
697772ac97cdSTom Musta 
697872ac97cdSTom Musta /* ------------------------------------------------------------------ */
697972ac97cdSTom Musta /* decCopyFit -- copy a number, truncating the coefficient if needed  */
698072ac97cdSTom Musta /*								      */
698172ac97cdSTom Musta /*   dest is the target decNumber				      */
698272ac97cdSTom Musta /*   src  is the source decNumber				      */
698372ac97cdSTom Musta /*   set is the context [used for length (digits) and rounding mode]  */
698472ac97cdSTom Musta /*   residue is the residue accumulator				      */
698572ac97cdSTom Musta /*   status contains the current status to be updated		      */
698672ac97cdSTom Musta /*								      */
698772ac97cdSTom Musta /* (dest==src is allowed and will be a no-op if fits)		      */
698872ac97cdSTom Musta /* All fields are updated as required.				      */
698972ac97cdSTom Musta /* ------------------------------------------------------------------ */
699072ac97cdSTom Musta static void decCopyFit(decNumber *dest, const decNumber *src,
699172ac97cdSTom Musta 		       decContext *set, Int *residue, uInt *status) {
699272ac97cdSTom Musta   dest->bits=src->bits;
699372ac97cdSTom Musta   dest->exponent=src->exponent;
699472ac97cdSTom Musta   decSetCoeff(dest, set, src->lsu, src->digits, residue, status);
699572ac97cdSTom Musta   } /* decCopyFit */
699672ac97cdSTom Musta 
699772ac97cdSTom Musta /* ------------------------------------------------------------------ */
699872ac97cdSTom Musta /* decSetCoeff -- set the coefficient of a number		      */
699972ac97cdSTom Musta /*								      */
700072ac97cdSTom Musta /*   dn	   is the number whose coefficient array is to be set.	      */
700172ac97cdSTom Musta /*	   It must have space for set->digits digits		      */
700272ac97cdSTom Musta /*   set   is the context [for size]				      */
700372ac97cdSTom Musta /*   lsu   -> lsu of the source coefficient [may be dn->lsu]	      */
700472ac97cdSTom Musta /*   len   is digits in the source coefficient [may be dn->digits]    */
700572ac97cdSTom Musta /*   residue is the residue accumulator.  This has values as in	      */
700672ac97cdSTom Musta /*	   decApplyRound, and will be unchanged unless the	      */
700772ac97cdSTom Musta /*	   target size is less than len.  In this case, the	      */
700872ac97cdSTom Musta /*	   coefficient is truncated and the residue is updated to     */
700972ac97cdSTom Musta /*	   reflect the previous residue and the dropped digits.	      */
701072ac97cdSTom Musta /*   status is the status accumulator, as usual			      */
701172ac97cdSTom Musta /*								      */
701272ac97cdSTom Musta /* The coefficient may already be in the number, or it can be an      */
701372ac97cdSTom Musta /* external intermediate array.	 If it is in the number, lsu must ==  */
701472ac97cdSTom Musta /* dn->lsu and len must == dn->digits.				      */
701572ac97cdSTom Musta /*								      */
701672ac97cdSTom Musta /* Note that the coefficient length (len) may be < set->digits, and   */
701772ac97cdSTom Musta /* in this case this merely copies the coefficient (or is a no-op     */
701872ac97cdSTom Musta /* if dn->lsu==lsu).						      */
701972ac97cdSTom Musta /*								      */
702072ac97cdSTom Musta /* Note also that (only internally, from decQuantizeOp and	      */
702172ac97cdSTom Musta /* decSetSubnormal) the value of set->digits may be less than one,    */
702272ac97cdSTom Musta /* indicating a round to left.	This routine handles that case	      */
702372ac97cdSTom Musta /* correctly; caller ensures space.				      */
702472ac97cdSTom Musta /*								      */
702572ac97cdSTom Musta /* dn->digits, dn->lsu (and as required), and dn->exponent are	      */
702672ac97cdSTom Musta /* updated as necessary.   dn->bits (sign) is unchanged.	      */
702772ac97cdSTom Musta /*								      */
702872ac97cdSTom Musta /* DEC_Rounded status is set if any digits are discarded.	      */
702972ac97cdSTom Musta /* DEC_Inexact status is set if any non-zero digits are discarded, or */
703072ac97cdSTom Musta /*			 incoming residue was non-0 (implies rounded) */
703172ac97cdSTom Musta /* ------------------------------------------------------------------ */
703272ac97cdSTom Musta /* mapping array: maps 0-9 to canonical residues, so that a residue */
703372ac97cdSTom Musta /* can be adjusted in the range [-1, +1] and achieve correct rounding */
703472ac97cdSTom Musta /*			       0  1  2	3  4  5	 6  7  8  9 */
703572ac97cdSTom Musta static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7};
703672ac97cdSTom Musta static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu,
703772ac97cdSTom Musta 			Int len, Int *residue, uInt *status) {
703872ac97cdSTom Musta   Int	discard;	      /* number of digits to discard */
703972ac97cdSTom Musta   uInt	cut;		      /* cut point in Unit */
704072ac97cdSTom Musta   const Unit *up;	      /* work */
704172ac97cdSTom Musta   Unit	*target;	      /* .. */
704272ac97cdSTom Musta   Int	count;		      /* .. */
704372ac97cdSTom Musta   #if DECDPUN<=4
704472ac97cdSTom Musta   uInt	temp;		      /* .. */
704572ac97cdSTom Musta   #endif
704672ac97cdSTom Musta 
704772ac97cdSTom Musta   discard=len-set->digits;    /* digits to discard */
704872ac97cdSTom Musta   if (discard<=0) {	      /* no digits are being discarded */
704972ac97cdSTom Musta     if (dn->lsu!=lsu) {	      /* copy needed */
705072ac97cdSTom Musta       /* copy the coefficient array to the result number; no shift needed */
705172ac97cdSTom Musta       count=len;	      /* avoids D2U */
705272ac97cdSTom Musta       up=lsu;
705372ac97cdSTom Musta       for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
705472ac97cdSTom Musta 	*target=*up;
705572ac97cdSTom Musta       dn->digits=len;	      /* set the new length */
705672ac97cdSTom Musta       }
705772ac97cdSTom Musta     /* dn->exponent and residue are unchanged, record any inexactitude */
705872ac97cdSTom Musta     if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded);
705972ac97cdSTom Musta     return;
706072ac97cdSTom Musta     }
706172ac97cdSTom Musta 
706272ac97cdSTom Musta   /* some digits must be discarded ... */
706372ac97cdSTom Musta   dn->exponent+=discard;      /* maintain numerical value */
706472ac97cdSTom Musta   *status|=DEC_Rounded;	      /* accumulate Rounded status */
706572ac97cdSTom Musta   if (*residue>1) *residue=1; /* previous residue now to right, so reduce */
706672ac97cdSTom Musta 
706772ac97cdSTom Musta   if (discard>len) {	      /* everything, +1, is being discarded */
706872ac97cdSTom Musta     /* guard digit is 0 */
706972ac97cdSTom Musta     /* residue is all the number [NB could be all 0s] */
707072ac97cdSTom Musta     if (*residue<=0) {	      /* not already positive */
707172ac97cdSTom Musta       count=len;	      /* avoids D2U */
707272ac97cdSTom Musta       for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */
707372ac97cdSTom Musta 	*residue=1;
707472ac97cdSTom Musta 	break;		      /* no need to check any others */
707572ac97cdSTom Musta 	}
707672ac97cdSTom Musta       }
707772ac97cdSTom Musta     if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
707872ac97cdSTom Musta     *dn->lsu=0;		      /* coefficient will now be 0 */
707972ac97cdSTom Musta     dn->digits=1;	      /* .. */
708072ac97cdSTom Musta     return;
708172ac97cdSTom Musta     } /* total discard */
708272ac97cdSTom Musta 
708372ac97cdSTom Musta   /* partial discard [most common case] */
708472ac97cdSTom Musta   /* here, at least the first (most significant) discarded digit exists */
708572ac97cdSTom Musta 
708672ac97cdSTom Musta   /* spin up the number, noting residue during the spin, until get to */
708772ac97cdSTom Musta   /* the Unit with the first discarded digit.  When reach it, extract */
708872ac97cdSTom Musta   /* it and remember its position */
708972ac97cdSTom Musta   count=0;
709072ac97cdSTom Musta   for (up=lsu;; up++) {
709172ac97cdSTom Musta     count+=DECDPUN;
709272ac97cdSTom Musta     if (count>=discard) break; /* full ones all checked */
709372ac97cdSTom Musta     if (*up!=0) *residue=1;
709472ac97cdSTom Musta     } /* up */
709572ac97cdSTom Musta 
709672ac97cdSTom Musta   /* here up -> Unit with first discarded digit */
709772ac97cdSTom Musta   cut=discard-(count-DECDPUN)-1;
709872ac97cdSTom Musta   if (cut==DECDPUN-1) {	      /* unit-boundary case (fast) */
709972ac97cdSTom Musta     Unit half=(Unit)powers[DECDPUN]>>1;
710072ac97cdSTom Musta     /* set residue directly */
710172ac97cdSTom Musta     if (*up>=half) {
710272ac97cdSTom Musta       if (*up>half) *residue=7;
710372ac97cdSTom Musta       else *residue+=5;	      /* add sticky bit */
710472ac97cdSTom Musta       }
710572ac97cdSTom Musta      else { /* <half */
710672ac97cdSTom Musta       if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */
710772ac97cdSTom Musta       }
710872ac97cdSTom Musta     if (set->digits<=0) {     /* special for Quantize/Subnormal :-( */
710972ac97cdSTom Musta       *dn->lsu=0;	      /* .. result is 0 */
711072ac97cdSTom Musta       dn->digits=1;	      /* .. */
711172ac97cdSTom Musta       }
711272ac97cdSTom Musta      else {		      /* shift to least */
711372ac97cdSTom Musta       count=set->digits;      /* now digits to end up with */
711472ac97cdSTom Musta       dn->digits=count;	      /* set the new length */
711572ac97cdSTom Musta       up++;		      /* move to next */
711672ac97cdSTom Musta       /* on unit boundary, so shift-down copy loop is simple */
711772ac97cdSTom Musta       for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
711872ac97cdSTom Musta 	*target=*up;
711972ac97cdSTom Musta       }
712072ac97cdSTom Musta     } /* unit-boundary case */
712172ac97cdSTom Musta 
712272ac97cdSTom Musta    else { /* discard digit is in low digit(s), and not top digit */
712372ac97cdSTom Musta     uInt  discard1;		   /* first discarded digit */
712472ac97cdSTom Musta     uInt  quot, rem;		   /* for divisions */
712572ac97cdSTom Musta     if (cut==0) quot=*up;	   /* is at bottom of unit */
712672ac97cdSTom Musta      else /* cut>0 */ {		   /* it's not at bottom of unit */
712772ac97cdSTom Musta       #if DECDPUN<=4
712872ac97cdSTom Musta 	quot=QUOT10(*up, cut);
712972ac97cdSTom Musta 	rem=*up-quot*powers[cut];
713072ac97cdSTom Musta       #else
713172ac97cdSTom Musta 	rem=*up%powers[cut];
713272ac97cdSTom Musta 	quot=*up/powers[cut];
713372ac97cdSTom Musta       #endif
713472ac97cdSTom Musta       if (rem!=0) *residue=1;
713572ac97cdSTom Musta       }
713672ac97cdSTom Musta     /* discard digit is now at bottom of quot */
713772ac97cdSTom Musta     #if DECDPUN<=4
713872ac97cdSTom Musta       temp=(quot*6554)>>16;	   /* fast /10 */
713972ac97cdSTom Musta       /* Vowels algorithm here not a win (9 instructions) */
714072ac97cdSTom Musta       discard1=quot-X10(temp);
714172ac97cdSTom Musta       quot=temp;
714272ac97cdSTom Musta     #else
714372ac97cdSTom Musta       discard1=quot%10;
714472ac97cdSTom Musta       quot=quot/10;
714572ac97cdSTom Musta     #endif
714672ac97cdSTom Musta     /* here, discard1 is the guard digit, and residue is everything */
714772ac97cdSTom Musta     /* else [use mapping array to accumulate residue safely] */
714872ac97cdSTom Musta     *residue+=resmap[discard1];
714972ac97cdSTom Musta     cut++;			   /* update cut */
715072ac97cdSTom Musta     /* here: up -> Unit of the array with bottom digit */
715172ac97cdSTom Musta     /*	     cut is the division point for each Unit */
715272ac97cdSTom Musta     /*	     quot holds the uncut high-order digits for the current unit */
715372ac97cdSTom Musta     if (set->digits<=0) {	   /* special for Quantize/Subnormal :-( */
715472ac97cdSTom Musta       *dn->lsu=0;		   /* .. result is 0 */
715572ac97cdSTom Musta       dn->digits=1;		   /* .. */
715672ac97cdSTom Musta       }
715772ac97cdSTom Musta      else {			   /* shift to least needed */
715872ac97cdSTom Musta       count=set->digits;	   /* now digits to end up with */
715972ac97cdSTom Musta       dn->digits=count;		   /* set the new length */
716072ac97cdSTom Musta       /* shift-copy the coefficient array to the result number */
716172ac97cdSTom Musta       for (target=dn->lsu; ; target++) {
716272ac97cdSTom Musta 	*target=(Unit)quot;
716372ac97cdSTom Musta 	count-=(DECDPUN-cut);
716472ac97cdSTom Musta 	if (count<=0) break;
716572ac97cdSTom Musta 	up++;
716672ac97cdSTom Musta 	quot=*up;
716772ac97cdSTom Musta 	#if DECDPUN<=4
716872ac97cdSTom Musta 	  quot=QUOT10(quot, cut);
716972ac97cdSTom Musta 	  rem=*up-quot*powers[cut];
717072ac97cdSTom Musta 	#else
717172ac97cdSTom Musta 	  rem=quot%powers[cut];
717272ac97cdSTom Musta 	  quot=quot/powers[cut];
717372ac97cdSTom Musta 	#endif
717472ac97cdSTom Musta 	*target=(Unit)(*target+rem*powers[DECDPUN-cut]);
717572ac97cdSTom Musta 	count-=cut;
717672ac97cdSTom Musta 	if (count<=0) break;
717772ac97cdSTom Musta 	} /* shift-copy loop */
717872ac97cdSTom Musta       } /* shift to least */
717972ac97cdSTom Musta     } /* not unit boundary */
718072ac97cdSTom Musta 
718172ac97cdSTom Musta   if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
718272ac97cdSTom Musta   return;
718372ac97cdSTom Musta   } /* decSetCoeff */
718472ac97cdSTom Musta 
718572ac97cdSTom Musta /* ------------------------------------------------------------------ */
718672ac97cdSTom Musta /* decApplyRound -- apply pending rounding to a number		      */
718772ac97cdSTom Musta /*								      */
718872ac97cdSTom Musta /*   dn	   is the number, with space for set->digits digits	      */
718972ac97cdSTom Musta /*   set   is the context [for size and rounding mode]		      */
719072ac97cdSTom Musta /*   residue indicates pending rounding, being any accumulated	      */
719172ac97cdSTom Musta /*	   guard and sticky information.  It may be:		      */
719272ac97cdSTom Musta /*	   6-9: rounding digit is >5				      */
719372ac97cdSTom Musta /*	   5:	rounding digit is exactly half-way		      */
719472ac97cdSTom Musta /*	   1-4: rounding digit is <5 and >0			      */
719572ac97cdSTom Musta /*	   0:	the coefficient is exact			      */
719672ac97cdSTom Musta /*	  -1:	as 1, but the hidden digits are subtractive, that     */
719772ac97cdSTom Musta /*		is, of the opposite sign to dn.	 In this case the     */
719872ac97cdSTom Musta /*		coefficient must be non-0.  This case occurs when     */
719972ac97cdSTom Musta /*		subtracting a small number (which can be reduced to   */
720072ac97cdSTom Musta /*		a sticky bit); see decAddOp.			      */
720172ac97cdSTom Musta /*   status is the status accumulator, as usual			      */
720272ac97cdSTom Musta /*								      */
720372ac97cdSTom Musta /* This routine applies rounding while keeping the length of the      */
720472ac97cdSTom Musta /* coefficient constant.  The exponent and status are unchanged	      */
720572ac97cdSTom Musta /* except if:							      */
720672ac97cdSTom Musta /*								      */
720772ac97cdSTom Musta /*   -- the coefficient was increased and is all nines (in which      */
720872ac97cdSTom Musta /*	case Overflow could occur, and is handled directly here so    */
720972ac97cdSTom Musta /*	the caller does not need to re-test for overflow)	      */
721072ac97cdSTom Musta /*								      */
721172ac97cdSTom Musta /*   -- the coefficient was decreased and becomes all nines (in which */
721272ac97cdSTom Musta /*	case Underflow could occur, and is also handled directly).    */
721372ac97cdSTom Musta /*								      */
721472ac97cdSTom Musta /* All fields in dn are updated as required.			      */
721572ac97cdSTom Musta /*								      */
721672ac97cdSTom Musta /* ------------------------------------------------------------------ */
721772ac97cdSTom Musta static void decApplyRound(decNumber *dn, decContext *set, Int residue,
721872ac97cdSTom Musta 			  uInt *status) {
721972ac97cdSTom Musta   Int  bump;		      /* 1 if coefficient needs to be incremented */
722072ac97cdSTom Musta 			      /* -1 if coefficient needs to be decremented */
722172ac97cdSTom Musta 
722272ac97cdSTom Musta   if (residue==0) return;     /* nothing to apply */
722372ac97cdSTom Musta 
722472ac97cdSTom Musta   bump=0;		      /* assume a smooth ride */
722572ac97cdSTom Musta 
722672ac97cdSTom Musta   /* now decide whether, and how, to round, depending on mode */
722772ac97cdSTom Musta   switch (set->round) {
722872ac97cdSTom Musta     case DEC_ROUND_05UP: {    /* round zero or five up (for reround) */
722972ac97cdSTom Musta       /* This is the same as DEC_ROUND_DOWN unless there is a */
723072ac97cdSTom Musta       /* positive residue and the lsd of dn is 0 or 5, in which case */
723172ac97cdSTom Musta       /* it is bumped; when residue is <0, the number is therefore */
723272ac97cdSTom Musta       /* bumped down unless the final digit was 1 or 6 (in which */
723372ac97cdSTom Musta       /* case it is bumped down and then up -- a no-op) */
723472ac97cdSTom Musta       Int lsd5=*dn->lsu%5;     /* get lsd and quintate */
723572ac97cdSTom Musta       if (residue<0 && lsd5!=1) bump=-1;
723672ac97cdSTom Musta        else if (residue>0 && lsd5==0) bump=1;
723772ac97cdSTom Musta       /* [bump==1 could be applied directly; use common path for clarity] */
723872ac97cdSTom Musta       break;} /* r-05 */
723972ac97cdSTom Musta 
724072ac97cdSTom Musta     case DEC_ROUND_DOWN: {
724172ac97cdSTom Musta       /* no change, except if negative residue */
724272ac97cdSTom Musta       if (residue<0) bump=-1;
724372ac97cdSTom Musta       break;} /* r-d */
724472ac97cdSTom Musta 
724572ac97cdSTom Musta     case DEC_ROUND_HALF_DOWN: {
724672ac97cdSTom Musta       if (residue>5) bump=1;
724772ac97cdSTom Musta       break;} /* r-h-d */
724872ac97cdSTom Musta 
724972ac97cdSTom Musta     case DEC_ROUND_HALF_EVEN: {
725072ac97cdSTom Musta       if (residue>5) bump=1;		/* >0.5 goes up */
725172ac97cdSTom Musta        else if (residue==5) {		/* exactly 0.5000... */
725272ac97cdSTom Musta 	/* 0.5 goes up iff [new] lsd is odd */
725372ac97cdSTom Musta 	if (*dn->lsu & 0x01) bump=1;
725472ac97cdSTom Musta 	}
725572ac97cdSTom Musta       break;} /* r-h-e */
725672ac97cdSTom Musta 
725772ac97cdSTom Musta     case DEC_ROUND_HALF_UP: {
725872ac97cdSTom Musta       if (residue>=5) bump=1;
725972ac97cdSTom Musta       break;} /* r-h-u */
726072ac97cdSTom Musta 
726172ac97cdSTom Musta     case DEC_ROUND_UP: {
726272ac97cdSTom Musta       if (residue>0) bump=1;
726372ac97cdSTom Musta       break;} /* r-u */
726472ac97cdSTom Musta 
726572ac97cdSTom Musta     case DEC_ROUND_CEILING: {
726672ac97cdSTom Musta       /* same as _UP for positive numbers, and as _DOWN for negatives */
726772ac97cdSTom Musta       /* [negative residue cannot occur on 0] */
726872ac97cdSTom Musta       if (decNumberIsNegative(dn)) {
726972ac97cdSTom Musta 	if (residue<0) bump=-1;
727072ac97cdSTom Musta 	}
727172ac97cdSTom Musta        else {
727272ac97cdSTom Musta 	if (residue>0) bump=1;
727372ac97cdSTom Musta 	}
727472ac97cdSTom Musta       break;} /* r-c */
727572ac97cdSTom Musta 
727672ac97cdSTom Musta     case DEC_ROUND_FLOOR: {
727772ac97cdSTom Musta       /* same as _UP for negative numbers, and as _DOWN for positive */
727872ac97cdSTom Musta       /* [negative residue cannot occur on 0] */
727972ac97cdSTom Musta       if (!decNumberIsNegative(dn)) {
728072ac97cdSTom Musta 	if (residue<0) bump=-1;
728172ac97cdSTom Musta 	}
728272ac97cdSTom Musta        else {
728372ac97cdSTom Musta 	if (residue>0) bump=1;
728472ac97cdSTom Musta 	}
728572ac97cdSTom Musta       break;} /* r-f */
728672ac97cdSTom Musta 
728772ac97cdSTom Musta     default: {	    /* e.g., DEC_ROUND_MAX */
728872ac97cdSTom Musta       *status|=DEC_Invalid_context;
728972ac97cdSTom Musta       #if DECTRACE || (DECCHECK && DECVERB)
729072ac97cdSTom Musta       printf("Unknown rounding mode: %d\n", set->round);
729172ac97cdSTom Musta       #endif
729272ac97cdSTom Musta       break;}
729372ac97cdSTom Musta     } /* switch */
729472ac97cdSTom Musta 
729572ac97cdSTom Musta   /* now bump the number, up or down, if need be */
729672ac97cdSTom Musta   if (bump==0) return;			     /* no action required */
729772ac97cdSTom Musta 
729872ac97cdSTom Musta   /* Simply use decUnitAddSub unless bumping up and the number is */
729972ac97cdSTom Musta   /* all nines.	 In this special case set to 100... explicitly */
730072ac97cdSTom Musta   /* and adjust the exponent by one (as otherwise could overflow */
730172ac97cdSTom Musta   /* the array) */
730272ac97cdSTom Musta   /* Similarly handle all-nines result if bumping down. */
730372ac97cdSTom Musta   if (bump>0) {
730472ac97cdSTom Musta     Unit *up;				     /* work */
730572ac97cdSTom Musta     uInt count=dn->digits;		     /* digits to be checked */
730672ac97cdSTom Musta     for (up=dn->lsu; ; up++) {
730772ac97cdSTom Musta       if (count<=DECDPUN) {
730872ac97cdSTom Musta 	/* this is the last Unit (the msu) */
730972ac97cdSTom Musta 	if (*up!=powers[count]-1) break;     /* not still 9s */
731072ac97cdSTom Musta 	/* here if it, too, is all nines */
731172ac97cdSTom Musta 	*up=(Unit)powers[count-1];	     /* here 999 -> 100 etc. */
731272ac97cdSTom Musta 	for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */
731372ac97cdSTom Musta 	dn->exponent++;			     /* and bump exponent */
731472ac97cdSTom Musta 	/* [which, very rarely, could cause Overflow...] */
731572ac97cdSTom Musta 	if ((dn->exponent+dn->digits)>set->emax+1) {
731672ac97cdSTom Musta 	  decSetOverflow(dn, set, status);
731772ac97cdSTom Musta 	  }
731872ac97cdSTom Musta 	return;				     /* done */
731972ac97cdSTom Musta 	}
732072ac97cdSTom Musta       /* a full unit to check, with more to come */
732172ac97cdSTom Musta       if (*up!=DECDPUNMAX) break;	     /* not still 9s */
732272ac97cdSTom Musta       count-=DECDPUN;
732372ac97cdSTom Musta       } /* up */
732472ac97cdSTom Musta     } /* bump>0 */
732572ac97cdSTom Musta    else {				     /* -1 */
732672ac97cdSTom Musta     /* here checking for a pre-bump of 1000... (leading 1, all */
732772ac97cdSTom Musta     /* other digits zero) */
732872ac97cdSTom Musta     Unit *up, *sup;			     /* work */
732972ac97cdSTom Musta     uInt count=dn->digits;		     /* digits to be checked */
733072ac97cdSTom Musta     for (up=dn->lsu; ; up++) {
733172ac97cdSTom Musta       if (count<=DECDPUN) {
733272ac97cdSTom Musta 	/* this is the last Unit (the msu) */
733372ac97cdSTom Musta 	if (*up!=powers[count-1]) break;     /* not 100.. */
733472ac97cdSTom Musta 	/* here if have the 1000... case */
733572ac97cdSTom Musta 	sup=up;				     /* save msu pointer */
733672ac97cdSTom Musta 	*up=(Unit)powers[count]-1;	     /* here 100 in msu -> 999 */
733772ac97cdSTom Musta 	/* others all to all-nines, too */
733872ac97cdSTom Musta 	for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1;
733972ac97cdSTom Musta 	dn->exponent--;			     /* and bump exponent */
734072ac97cdSTom Musta 
734172ac97cdSTom Musta 	/* iff the number was at the subnormal boundary (exponent=etiny) */
734272ac97cdSTom Musta 	/* then the exponent is now out of range, so it will in fact get */
734372ac97cdSTom Musta 	/* clamped to etiny and the final 9 dropped. */
734472ac97cdSTom Musta 	/* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */
734572ac97cdSTom Musta 	/*	  dn->exponent, set->digits); */
734672ac97cdSTom Musta 	if (dn->exponent+1==set->emin-set->digits+1) {
734772ac97cdSTom Musta 	  if (count==1 && dn->digits==1) *sup=0;  /* here 9 -> 0[.9] */
734872ac97cdSTom Musta 	   else {
734972ac97cdSTom Musta 	    *sup=(Unit)powers[count-1]-1;    /* here 999.. in msu -> 99.. */
735072ac97cdSTom Musta 	    dn->digits--;
735172ac97cdSTom Musta 	    }
735272ac97cdSTom Musta 	  dn->exponent++;
735372ac97cdSTom Musta 	  *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
735472ac97cdSTom Musta 	  }
735572ac97cdSTom Musta 	return;				     /* done */
735672ac97cdSTom Musta 	}
735772ac97cdSTom Musta 
735872ac97cdSTom Musta       /* a full unit to check, with more to come */
735972ac97cdSTom Musta       if (*up!=0) break;		     /* not still 0s */
736072ac97cdSTom Musta       count-=DECDPUN;
736172ac97cdSTom Musta       } /* up */
736272ac97cdSTom Musta 
736372ac97cdSTom Musta     } /* bump<0 */
736472ac97cdSTom Musta 
736572ac97cdSTom Musta   /* Actual bump needed.  Do it. */
736672ac97cdSTom Musta   decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump);
736772ac97cdSTom Musta   } /* decApplyRound */
736872ac97cdSTom Musta 
736972ac97cdSTom Musta #if DECSUBSET
737072ac97cdSTom Musta /* ------------------------------------------------------------------ */
737172ac97cdSTom Musta /* decFinish -- finish processing a number			      */
737272ac97cdSTom Musta /*								      */
737372ac97cdSTom Musta /*   dn is the number						      */
737472ac97cdSTom Musta /*   set is the context						      */
737572ac97cdSTom Musta /*   residue is the rounding accumulator (as in decApplyRound)	      */
737672ac97cdSTom Musta /*   status is the accumulator					      */
737772ac97cdSTom Musta /*								      */
737872ac97cdSTom Musta /* This finishes off the current number by:			      */
737972ac97cdSTom Musta /*    1. If not extended:					      */
738072ac97cdSTom Musta /*	 a. Converting a zero result to clean '0'		      */
738172ac97cdSTom Musta /*	 b. Reducing positive exponents to 0, if would fit in digits  */
738272ac97cdSTom Musta /*    2. Checking for overflow and subnormals (always)		      */
738372ac97cdSTom Musta /* Note this is just Finalize when no subset arithmetic.	      */
738472ac97cdSTom Musta /* All fields are updated as required.				      */
738572ac97cdSTom Musta /* ------------------------------------------------------------------ */
738672ac97cdSTom Musta static void decFinish(decNumber *dn, decContext *set, Int *residue,
738772ac97cdSTom Musta 		      uInt *status) {
738872ac97cdSTom Musta   if (!set->extended) {
738972ac97cdSTom Musta     if ISZERO(dn) {		   /* value is zero */
739072ac97cdSTom Musta       dn->exponent=0;		   /* clean exponent .. */
739172ac97cdSTom Musta       dn->bits=0;		   /* .. and sign */
739272ac97cdSTom Musta       return;			   /* no error possible */
739372ac97cdSTom Musta       }
739472ac97cdSTom Musta     if (dn->exponent>=0) {	   /* non-negative exponent */
739572ac97cdSTom Musta       /* >0; reduce to integer if possible */
739672ac97cdSTom Musta       if (set->digits >= (dn->exponent+dn->digits)) {
739772ac97cdSTom Musta 	dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent);
739872ac97cdSTom Musta 	dn->exponent=0;
739972ac97cdSTom Musta 	}
740072ac97cdSTom Musta       }
740172ac97cdSTom Musta     } /* !extended */
740272ac97cdSTom Musta 
740372ac97cdSTom Musta   decFinalize(dn, set, residue, status);
740472ac97cdSTom Musta   } /* decFinish */
740572ac97cdSTom Musta #endif
740672ac97cdSTom Musta 
740772ac97cdSTom Musta /* ------------------------------------------------------------------ */
740872ac97cdSTom Musta /* decFinalize -- final check, clamp, and round of a number	      */
740972ac97cdSTom Musta /*								      */
741072ac97cdSTom Musta /*   dn is the number						      */
741172ac97cdSTom Musta /*   set is the context						      */
741272ac97cdSTom Musta /*   residue is the rounding accumulator (as in decApplyRound)	      */
741372ac97cdSTom Musta /*   status is the status accumulator				      */
741472ac97cdSTom Musta /*								      */
741572ac97cdSTom Musta /* This finishes off the current number by checking for subnormal     */
741672ac97cdSTom Musta /* results, applying any pending rounding, checking for overflow,     */
741772ac97cdSTom Musta /* and applying any clamping.					      */
741872ac97cdSTom Musta /* Underflow and overflow conditions are raised as appropriate.	      */
741972ac97cdSTom Musta /* All fields are updated as required.				      */
742072ac97cdSTom Musta /* ------------------------------------------------------------------ */
742172ac97cdSTom Musta static void decFinalize(decNumber *dn, decContext *set, Int *residue,
742272ac97cdSTom Musta 			uInt *status) {
742372ac97cdSTom Musta   Int shift;				/* shift needed if clamping */
742472ac97cdSTom Musta   Int tinyexp=set->emin-dn->digits+1;	/* precalculate subnormal boundary */
742572ac97cdSTom Musta 
742672ac97cdSTom Musta   /* Must be careful, here, when checking the exponent as the */
742772ac97cdSTom Musta   /* adjusted exponent could overflow 31 bits [because it may already */
742872ac97cdSTom Musta   /* be up to twice the expected]. */
742972ac97cdSTom Musta 
743072ac97cdSTom Musta   /* First test for subnormal.	This must be done before any final */
743172ac97cdSTom Musta   /* round as the result could be rounded to Nmin or 0. */
743272ac97cdSTom Musta   if (dn->exponent<=tinyexp) {		/* prefilter */
743372ac97cdSTom Musta     Int comp;
743472ac97cdSTom Musta     decNumber nmin;
743572ac97cdSTom Musta     /* A very nasty case here is dn == Nmin and residue<0 */
743672ac97cdSTom Musta     if (dn->exponent<tinyexp) {
743772ac97cdSTom Musta       /* Go handle subnormals; this will apply round if needed. */
743872ac97cdSTom Musta       decSetSubnormal(dn, set, residue, status);
743972ac97cdSTom Musta       return;
744072ac97cdSTom Musta       }
744172ac97cdSTom Musta     /* Equals case: only subnormal if dn=Nmin and negative residue */
744272ac97cdSTom Musta     decNumberZero(&nmin);
744372ac97cdSTom Musta     nmin.lsu[0]=1;
744472ac97cdSTom Musta     nmin.exponent=set->emin;
744572ac97cdSTom Musta     comp=decCompare(dn, &nmin, 1);		  /* (signless compare) */
744672ac97cdSTom Musta     if (comp==BADINT) {				  /* oops */
744772ac97cdSTom Musta       *status|=DEC_Insufficient_storage;	  /* abandon... */
744872ac97cdSTom Musta       return;
744972ac97cdSTom Musta       }
745072ac97cdSTom Musta     if (*residue<0 && comp==0) {		  /* neg residue and dn==Nmin */
745172ac97cdSTom Musta       decApplyRound(dn, set, *residue, status);	  /* might force down */
745272ac97cdSTom Musta       decSetSubnormal(dn, set, residue, status);
745372ac97cdSTom Musta       return;
745472ac97cdSTom Musta       }
745572ac97cdSTom Musta     }
745672ac97cdSTom Musta 
745772ac97cdSTom Musta   /* now apply any pending round (this could raise overflow). */
745872ac97cdSTom Musta   if (*residue!=0) decApplyRound(dn, set, *residue, status);
745972ac97cdSTom Musta 
746072ac97cdSTom Musta   /* Check for overflow [redundant in the 'rare' case] or clamp */
746172ac97cdSTom Musta   if (dn->exponent<=set->emax-set->digits+1) return;   /* neither needed */
746272ac97cdSTom Musta 
746372ac97cdSTom Musta 
746472ac97cdSTom Musta   /* here when might have an overflow or clamp to do */
746572ac97cdSTom Musta   if (dn->exponent>set->emax-dn->digits+1) {	       /* too big */
746672ac97cdSTom Musta     decSetOverflow(dn, set, status);
746772ac97cdSTom Musta     return;
746872ac97cdSTom Musta     }
746972ac97cdSTom Musta   /* here when the result is normal but in clamp range */
747072ac97cdSTom Musta   if (!set->clamp) return;
747172ac97cdSTom Musta 
747272ac97cdSTom Musta   /* here when need to apply the IEEE exponent clamp (fold-down) */
747372ac97cdSTom Musta   shift=dn->exponent-(set->emax-set->digits+1);
747472ac97cdSTom Musta 
747572ac97cdSTom Musta   /* shift coefficient (if non-zero) */
747672ac97cdSTom Musta   if (!ISZERO(dn)) {
747772ac97cdSTom Musta     dn->digits=decShiftToMost(dn->lsu, dn->digits, shift);
747872ac97cdSTom Musta     }
747972ac97cdSTom Musta   dn->exponent-=shift;	 /* adjust the exponent to match */
748072ac97cdSTom Musta   *status|=DEC_Clamped;	 /* and record the dirty deed */
748172ac97cdSTom Musta   return;
748272ac97cdSTom Musta   } /* decFinalize */
748372ac97cdSTom Musta 
748472ac97cdSTom Musta /* ------------------------------------------------------------------ */
748572ac97cdSTom Musta /* decSetOverflow -- set number to proper overflow value	      */
748672ac97cdSTom Musta /*								      */
748772ac97cdSTom Musta /*   dn is the number (used for sign [only] and result)		      */
748872ac97cdSTom Musta /*   set is the context [used for the rounding mode, etc.]	      */
748972ac97cdSTom Musta /*   status contains the current status to be updated		      */
749072ac97cdSTom Musta /*								      */
749172ac97cdSTom Musta /* This sets the sign of a number and sets its value to either	      */
749272ac97cdSTom Musta /* Infinity or the maximum finite value, depending on the sign of     */
749372ac97cdSTom Musta /* dn and the rounding mode, following IEEE 854 rules.		      */
749472ac97cdSTom Musta /* ------------------------------------------------------------------ */
749572ac97cdSTom Musta static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) {
749672ac97cdSTom Musta   Flag needmax=0;		   /* result is maximum finite value */
749772ac97cdSTom Musta   uByte sign=dn->bits&DECNEG;	   /* clean and save sign bit */
749872ac97cdSTom Musta 
749972ac97cdSTom Musta   if (ISZERO(dn)) {		   /* zero does not overflow magnitude */
750072ac97cdSTom Musta     Int emax=set->emax;			     /* limit value */
750172ac97cdSTom Musta     if (set->clamp) emax-=set->digits-1;     /* lower if clamping */
750272ac97cdSTom Musta     if (dn->exponent>emax) {		     /* clamp required */
750372ac97cdSTom Musta       dn->exponent=emax;
750472ac97cdSTom Musta       *status|=DEC_Clamped;
750572ac97cdSTom Musta       }
750672ac97cdSTom Musta     return;
750772ac97cdSTom Musta     }
750872ac97cdSTom Musta 
750972ac97cdSTom Musta   decNumberZero(dn);
751072ac97cdSTom Musta   switch (set->round) {
751172ac97cdSTom Musta     case DEC_ROUND_DOWN: {
751272ac97cdSTom Musta       needmax=1;		   /* never Infinity */
751372ac97cdSTom Musta       break;} /* r-d */
751472ac97cdSTom Musta     case DEC_ROUND_05UP: {
751572ac97cdSTom Musta       needmax=1;		   /* never Infinity */
751672ac97cdSTom Musta       break;} /* r-05 */
751772ac97cdSTom Musta     case DEC_ROUND_CEILING: {
751872ac97cdSTom Musta       if (sign) needmax=1;	   /* Infinity if non-negative */
751972ac97cdSTom Musta       break;} /* r-c */
752072ac97cdSTom Musta     case DEC_ROUND_FLOOR: {
752172ac97cdSTom Musta       if (!sign) needmax=1;	   /* Infinity if negative */
752272ac97cdSTom Musta       break;} /* r-f */
752372ac97cdSTom Musta     default: break;		   /* Infinity in all other cases */
752472ac97cdSTom Musta     }
752572ac97cdSTom Musta   if (needmax) {
752672ac97cdSTom Musta     decSetMaxValue(dn, set);
752772ac97cdSTom Musta     dn->bits=sign;		   /* set sign */
752872ac97cdSTom Musta     }
752972ac97cdSTom Musta    else dn->bits=sign|DECINF;	   /* Value is +/-Infinity */
753072ac97cdSTom Musta   *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded;
753172ac97cdSTom Musta   } /* decSetOverflow */
753272ac97cdSTom Musta 
753372ac97cdSTom Musta /* ------------------------------------------------------------------ */
753472ac97cdSTom Musta /* decSetMaxValue -- set number to +Nmax (maximum normal value)	      */
753572ac97cdSTom Musta /*								      */
753672ac97cdSTom Musta /*   dn is the number to set					      */
753772ac97cdSTom Musta /*   set is the context [used for digits and emax]		      */
753872ac97cdSTom Musta /*								      */
753972ac97cdSTom Musta /* This sets the number to the maximum positive value.		      */
754072ac97cdSTom Musta /* ------------------------------------------------------------------ */
754172ac97cdSTom Musta static void decSetMaxValue(decNumber *dn, decContext *set) {
754272ac97cdSTom Musta   Unit *up;			   /* work */
754372ac97cdSTom Musta   Int count=set->digits;	   /* nines to add */
754472ac97cdSTom Musta   dn->digits=count;
754572ac97cdSTom Musta   /* fill in all nines to set maximum value */
754672ac97cdSTom Musta   for (up=dn->lsu; ; up++) {
754772ac97cdSTom Musta     if (count>DECDPUN) *up=DECDPUNMAX;	/* unit full o'nines */
754872ac97cdSTom Musta      else {				/* this is the msu */
754972ac97cdSTom Musta       *up=(Unit)(powers[count]-1);
755072ac97cdSTom Musta       break;
755172ac97cdSTom Musta       }
755272ac97cdSTom Musta     count-=DECDPUN;		   /* filled those digits */
755372ac97cdSTom Musta     } /* up */
755472ac97cdSTom Musta   dn->bits=0;			   /* + sign */
755572ac97cdSTom Musta   dn->exponent=set->emax-set->digits+1;
755672ac97cdSTom Musta   } /* decSetMaxValue */
755772ac97cdSTom Musta 
755872ac97cdSTom Musta /* ------------------------------------------------------------------ */
755972ac97cdSTom Musta /* decSetSubnormal -- process value whose exponent is <Emin	      */
756072ac97cdSTom Musta /*								      */
756172ac97cdSTom Musta /*   dn is the number (used as input as well as output; it may have   */
756272ac97cdSTom Musta /*	   an allowed subnormal value, which may need to be rounded)  */
756372ac97cdSTom Musta /*   set is the context [used for the rounding mode]		      */
756472ac97cdSTom Musta /*   residue is any pending residue				      */
756572ac97cdSTom Musta /*   status contains the current status to be updated		      */
756672ac97cdSTom Musta /*								      */
756772ac97cdSTom Musta /* If subset mode, set result to zero and set Underflow flags.	      */
756872ac97cdSTom Musta /*								      */
756972ac97cdSTom Musta /* Value may be zero with a low exponent; this does not set Subnormal */
757072ac97cdSTom Musta /* but the exponent will be clamped to Etiny.			      */
757172ac97cdSTom Musta /*								      */
757272ac97cdSTom Musta /* Otherwise ensure exponent is not out of range, and round as	      */
757372ac97cdSTom Musta /* necessary.  Underflow is set if the result is Inexact.	      */
757472ac97cdSTom Musta /* ------------------------------------------------------------------ */
757572ac97cdSTom Musta static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
757672ac97cdSTom Musta 			    uInt *status) {
757772ac97cdSTom Musta   decContext workset;	      /* work */
757872ac97cdSTom Musta   Int	     etiny, adjust;   /* .. */
757972ac97cdSTom Musta 
758072ac97cdSTom Musta   #if DECSUBSET
758172ac97cdSTom Musta   /* simple set to zero and 'hard underflow' for subset */
758272ac97cdSTom Musta   if (!set->extended) {
758372ac97cdSTom Musta     decNumberZero(dn);
758472ac97cdSTom Musta     /* always full overflow */
758572ac97cdSTom Musta     *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
758672ac97cdSTom Musta     return;
758772ac97cdSTom Musta     }
758872ac97cdSTom Musta   #endif
758972ac97cdSTom Musta 
759072ac97cdSTom Musta   /* Full arithmetic -- allow subnormals, rounded to minimum exponent */
759172ac97cdSTom Musta   /* (Etiny) if needed */
759272ac97cdSTom Musta   etiny=set->emin-(set->digits-1);	/* smallest allowed exponent */
759372ac97cdSTom Musta 
759472ac97cdSTom Musta   if ISZERO(dn) {			/* value is zero */
759572ac97cdSTom Musta     /* residue can never be non-zero here */
759672ac97cdSTom Musta     #if DECCHECK
759772ac97cdSTom Musta       if (*residue!=0) {
759872ac97cdSTom Musta 	printf("++ Subnormal 0 residue %ld\n", (LI)*residue);
759972ac97cdSTom Musta 	*status|=DEC_Invalid_operation;
760072ac97cdSTom Musta 	}
760172ac97cdSTom Musta     #endif
760272ac97cdSTom Musta     if (dn->exponent<etiny) {		/* clamp required */
760372ac97cdSTom Musta       dn->exponent=etiny;
760472ac97cdSTom Musta       *status|=DEC_Clamped;
760572ac97cdSTom Musta       }
760672ac97cdSTom Musta     return;
760772ac97cdSTom Musta     }
760872ac97cdSTom Musta 
760972ac97cdSTom Musta   *status|=DEC_Subnormal;		/* have a non-zero subnormal */
761072ac97cdSTom Musta   adjust=etiny-dn->exponent;		/* calculate digits to remove */
761172ac97cdSTom Musta   if (adjust<=0) {			/* not out of range; unrounded */
761272ac97cdSTom Musta     /* residue can never be non-zero here, except in the Nmin-residue */
761372ac97cdSTom Musta     /* case (which is a subnormal result), so can take fast-path here */
761472ac97cdSTom Musta     /* it may already be inexact (from setting the coefficient) */
761572ac97cdSTom Musta     if (*status&DEC_Inexact) *status|=DEC_Underflow;
761672ac97cdSTom Musta     return;
761772ac97cdSTom Musta     }
761872ac97cdSTom Musta 
761972ac97cdSTom Musta   /* adjust>0, so need to rescale the result so exponent becomes Etiny */
762072ac97cdSTom Musta   /* [this code is similar to that in rescale] */
762172ac97cdSTom Musta   workset=*set;				/* clone rounding, etc. */
762272ac97cdSTom Musta   workset.digits=dn->digits-adjust;	/* set requested length */
762372ac97cdSTom Musta   workset.emin-=adjust;			/* and adjust emin to match */
762472ac97cdSTom Musta   /* [note that the latter can be <1, here, similar to Rescale case] */
762572ac97cdSTom Musta   decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status);
762672ac97cdSTom Musta   decApplyRound(dn, &workset, *residue, status);
762772ac97cdSTom Musta 
762872ac97cdSTom Musta   /* Use 754R/854 default rule: Underflow is set iff Inexact */
762972ac97cdSTom Musta   /* [independent of whether trapped] */
763072ac97cdSTom Musta   if (*status&DEC_Inexact) *status|=DEC_Underflow;
763172ac97cdSTom Musta 
763272ac97cdSTom Musta   /* if rounded up a 999s case, exponent will be off by one; adjust */
763372ac97cdSTom Musta   /* back if so [it will fit, because it was shortened earlier] */
763472ac97cdSTom Musta   if (dn->exponent>etiny) {
763572ac97cdSTom Musta     dn->digits=decShiftToMost(dn->lsu, dn->digits, 1);
763672ac97cdSTom Musta     dn->exponent--;			/* (re)adjust the exponent. */
763772ac97cdSTom Musta     }
763872ac97cdSTom Musta 
763972ac97cdSTom Musta   /* if rounded to zero, it is by definition clamped... */
764072ac97cdSTom Musta   if (ISZERO(dn)) *status|=DEC_Clamped;
764172ac97cdSTom Musta   } /* decSetSubnormal */
764272ac97cdSTom Musta 
764372ac97cdSTom Musta /* ------------------------------------------------------------------ */
764472ac97cdSTom Musta /* decCheckMath - check entry conditions for a math function	      */
764572ac97cdSTom Musta /*								      */
764672ac97cdSTom Musta /*   This checks the context and the operand			      */
764772ac97cdSTom Musta /*								      */
764872ac97cdSTom Musta /*   rhs is the operand to check				      */
764972ac97cdSTom Musta /*   set is the context to check				      */
765072ac97cdSTom Musta /*   status is unchanged if both are good			      */
765172ac97cdSTom Musta /*								      */
765272ac97cdSTom Musta /* returns non-zero if status is changed, 0 otherwise		      */
765372ac97cdSTom Musta /*								      */
765472ac97cdSTom Musta /* Restrictions enforced:					      */
765572ac97cdSTom Musta /*								      */
765672ac97cdSTom Musta /*   digits, emax, and -emin in the context must be less than	      */
765772ac97cdSTom Musta /*   DEC_MAX_MATH (999999), and A must be within these bounds if      */
765872ac97cdSTom Musta /*   non-zero.	Invalid_operation is set in the status if a	      */
765972ac97cdSTom Musta /*   restriction is violated.					      */
766072ac97cdSTom Musta /* ------------------------------------------------------------------ */
766172ac97cdSTom Musta static uInt decCheckMath(const decNumber *rhs, decContext *set,
766272ac97cdSTom Musta 			 uInt *status) {
766372ac97cdSTom Musta   uInt save=*status;			     /* record */
766472ac97cdSTom Musta   if (set->digits>DEC_MAX_MATH
766572ac97cdSTom Musta    || set->emax>DEC_MAX_MATH
766672ac97cdSTom Musta    || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context;
766772ac97cdSTom Musta    else if ((rhs->digits>DEC_MAX_MATH
766872ac97cdSTom Musta      || rhs->exponent+rhs->digits>DEC_MAX_MATH+1
766972ac97cdSTom Musta      || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH))
767072ac97cdSTom Musta      && !ISZERO(rhs)) *status|=DEC_Invalid_operation;
767172ac97cdSTom Musta   return (*status!=save);
767272ac97cdSTom Musta   } /* decCheckMath */
767372ac97cdSTom Musta 
767472ac97cdSTom Musta /* ------------------------------------------------------------------ */
767572ac97cdSTom Musta /* decGetInt -- get integer from a number			      */
767672ac97cdSTom Musta /*								      */
767772ac97cdSTom Musta /*   dn is the number [which will not be altered]		      */
767872ac97cdSTom Musta /*								      */
767972ac97cdSTom Musta /*   returns one of:						      */
768072ac97cdSTom Musta /*     BADINT if there is a non-zero fraction			      */
768172ac97cdSTom Musta /*     the converted integer					      */
768272ac97cdSTom Musta /*     BIGEVEN if the integer is even and magnitude > 2*10**9	      */
768372ac97cdSTom Musta /*     BIGODD  if the integer is odd  and magnitude > 2*10**9	      */
768472ac97cdSTom Musta /*								      */
768572ac97cdSTom Musta /* This checks and gets a whole number from the input decNumber.      */
768672ac97cdSTom Musta /* The sign can be determined from dn by the caller when BIGEVEN or   */
768772ac97cdSTom Musta /* BIGODD is returned.						      */
768872ac97cdSTom Musta /* ------------------------------------------------------------------ */
768972ac97cdSTom Musta static Int decGetInt(const decNumber *dn) {
769072ac97cdSTom Musta   Int  theInt;				/* result accumulator */
769172ac97cdSTom Musta   const Unit *up;			/* work */
769272ac97cdSTom Musta   Int  got;				/* digits (real or not) processed */
769372ac97cdSTom Musta   Int  ilength=dn->digits+dn->exponent; /* integral length */
769472ac97cdSTom Musta   Flag neg=decNumberIsNegative(dn);	/* 1 if -ve */
769572ac97cdSTom Musta 
769672ac97cdSTom Musta   /* The number must be an integer that fits in 10 digits */
769772ac97cdSTom Musta   /* Assert, here, that 10 is enough for any rescale Etiny */
769872ac97cdSTom Musta   #if DEC_MAX_EMAX > 999999999
769972ac97cdSTom Musta     #error GetInt may need updating [for Emax]
770072ac97cdSTom Musta   #endif
770172ac97cdSTom Musta   #if DEC_MIN_EMIN < -999999999
770272ac97cdSTom Musta     #error GetInt may need updating [for Emin]
770372ac97cdSTom Musta   #endif
770472ac97cdSTom Musta   if (ISZERO(dn)) return 0;		/* zeros are OK, with any exponent */
770572ac97cdSTom Musta 
770672ac97cdSTom Musta   up=dn->lsu;				/* ready for lsu */
770772ac97cdSTom Musta   theInt=0;				/* ready to accumulate */
770872ac97cdSTom Musta   if (dn->exponent>=0) {		/* relatively easy */
770972ac97cdSTom Musta     /* no fractional part [usual]; allow for positive exponent */
771072ac97cdSTom Musta     got=dn->exponent;
771172ac97cdSTom Musta     }
771272ac97cdSTom Musta    else { /* -ve exponent; some fractional part to check and discard */
771372ac97cdSTom Musta     Int count=-dn->exponent;		/* digits to discard */
771472ac97cdSTom Musta     /* spin up whole units until reach the Unit with the unit digit */
771572ac97cdSTom Musta     for (; count>=DECDPUN; up++) {
771672ac97cdSTom Musta       if (*up!=0) return BADINT;	/* non-zero Unit to discard */
771772ac97cdSTom Musta       count-=DECDPUN;
771872ac97cdSTom Musta       }
771972ac97cdSTom Musta     if (count==0) got=0;		/* [a multiple of DECDPUN] */
772072ac97cdSTom Musta      else {				/* [not multiple of DECDPUN] */
772172ac97cdSTom Musta       Int rem;				/* work */
772272ac97cdSTom Musta       /* slice off fraction digits and check for non-zero */
772372ac97cdSTom Musta       #if DECDPUN<=4
772472ac97cdSTom Musta 	theInt=QUOT10(*up, count);
772572ac97cdSTom Musta 	rem=*up-theInt*powers[count];
772672ac97cdSTom Musta       #else
772772ac97cdSTom Musta 	rem=*up%powers[count];		/* slice off discards */
772872ac97cdSTom Musta 	theInt=*up/powers[count];
772972ac97cdSTom Musta       #endif
773072ac97cdSTom Musta       if (rem!=0) return BADINT;	/* non-zero fraction */
773172ac97cdSTom Musta       /* it looks good */
773272ac97cdSTom Musta       got=DECDPUN-count;		/* number of digits so far */
773372ac97cdSTom Musta       up++;				/* ready for next */
773472ac97cdSTom Musta       }
773572ac97cdSTom Musta     }
773672ac97cdSTom Musta   /* now it's known there's no fractional part */
773772ac97cdSTom Musta 
773872ac97cdSTom Musta   /* tricky code now, to accumulate up to 9.3 digits */
773972ac97cdSTom Musta   if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */
774072ac97cdSTom Musta 
774172ac97cdSTom Musta   if (ilength<11) {
774272ac97cdSTom Musta     Int save=theInt;
774372ac97cdSTom Musta     /* collect any remaining unit(s) */
774472ac97cdSTom Musta     for (; got<ilength; up++) {
774572ac97cdSTom Musta       theInt+=*up*powers[got];
774672ac97cdSTom Musta       got+=DECDPUN;
774772ac97cdSTom Musta       }
774872ac97cdSTom Musta     if (ilength==10) {			/* need to check for wrap */
774972ac97cdSTom Musta       if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11;
775072ac97cdSTom Musta 	 /* [that test also disallows the BADINT result case] */
775172ac97cdSTom Musta        else if (neg && theInt>1999999997) ilength=11;
775272ac97cdSTom Musta        else if (!neg && theInt>999999999) ilength=11;
775372ac97cdSTom Musta       if (ilength==11) theInt=save;	/* restore correct low bit */
775472ac97cdSTom Musta       }
775572ac97cdSTom Musta     }
775672ac97cdSTom Musta 
775772ac97cdSTom Musta   if (ilength>10) {			/* too big */
775872ac97cdSTom Musta     if (theInt&1) return BIGODD;	/* bottom bit 1 */
775972ac97cdSTom Musta     return BIGEVEN;			/* bottom bit 0 */
776072ac97cdSTom Musta     }
776172ac97cdSTom Musta 
776272ac97cdSTom Musta   if (neg) theInt=-theInt;		/* apply sign */
776372ac97cdSTom Musta   return theInt;
776472ac97cdSTom Musta   } /* decGetInt */
776572ac97cdSTom Musta 
776672ac97cdSTom Musta /* ------------------------------------------------------------------ */
776772ac97cdSTom Musta /* decDecap -- decapitate the coefficient of a number		      */
776872ac97cdSTom Musta /*								      */
776972ac97cdSTom Musta /*   dn	  is the number to be decapitated			      */
777072ac97cdSTom Musta /*   drop is the number of digits to be removed from the left of dn;  */
777172ac97cdSTom Musta /*     this must be <= dn->digits (if equal, the coefficient is	      */
777272ac97cdSTom Musta /*     set to 0)						      */
777372ac97cdSTom Musta /*								      */
777472ac97cdSTom Musta /* Returns dn; dn->digits will be <= the initial digits less drop     */
777572ac97cdSTom Musta /* (after removing drop digits there may be leading zero digits	      */
777672ac97cdSTom Musta /* which will also be removed).	 Only dn->lsu and dn->digits change.  */
777772ac97cdSTom Musta /* ------------------------------------------------------------------ */
777872ac97cdSTom Musta static decNumber *decDecap(decNumber *dn, Int drop) {
777972ac97cdSTom Musta   Unit *msu;				/* -> target cut point */
778072ac97cdSTom Musta   Int cut;				/* work */
778172ac97cdSTom Musta   if (drop>=dn->digits) {		/* losing the whole thing */
778272ac97cdSTom Musta     #if DECCHECK
778372ac97cdSTom Musta     if (drop>dn->digits)
778472ac97cdSTom Musta       printf("decDecap called with drop>digits [%ld>%ld]\n",
778572ac97cdSTom Musta 	     (LI)drop, (LI)dn->digits);
778672ac97cdSTom Musta     #endif
778772ac97cdSTom Musta     dn->lsu[0]=0;
778872ac97cdSTom Musta     dn->digits=1;
778972ac97cdSTom Musta     return dn;
779072ac97cdSTom Musta     }
779172ac97cdSTom Musta   msu=dn->lsu+D2U(dn->digits-drop)-1;	/* -> likely msu */
779272ac97cdSTom Musta   cut=MSUDIGITS(dn->digits-drop);	/* digits to be in use in msu */
779372ac97cdSTom Musta   if (cut!=DECDPUN) *msu%=powers[cut];	/* clear left digits */
779472ac97cdSTom Musta   /* that may have left leading zero digits, so do a proper count... */
779572ac97cdSTom Musta   dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1);
779672ac97cdSTom Musta   return dn;
779772ac97cdSTom Musta   } /* decDecap */
779872ac97cdSTom Musta 
779972ac97cdSTom Musta /* ------------------------------------------------------------------ */
780072ac97cdSTom Musta /* decBiStr -- compare string with pairwise options		      */
780172ac97cdSTom Musta /*								      */
780272ac97cdSTom Musta /*   targ is the string to compare				      */
780372ac97cdSTom Musta /*   str1 is one of the strings to compare against (length may be 0)  */
780472ac97cdSTom Musta /*   str2 is the other; it must be the same length as str1	      */
780572ac97cdSTom Musta /*								      */
780672ac97cdSTom Musta /*   returns 1 if strings compare equal, (that is, it is the same     */
780772ac97cdSTom Musta /*   length as str1 and str2, and each character of targ is in either */
780872ac97cdSTom Musta /*   str1 or str2 in the corresponding position), or 0 otherwise      */
780972ac97cdSTom Musta /*								      */
781072ac97cdSTom Musta /* This is used for generic caseless compare, including the awkward   */
781172ac97cdSTom Musta /* case of the Turkish dotted and dotless Is.  Use as (for example):  */
781272ac97cdSTom Musta /*   if (decBiStr(test, "mike", "MIKE")) ...			      */
781372ac97cdSTom Musta /* ------------------------------------------------------------------ */
781472ac97cdSTom Musta static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
781572ac97cdSTom Musta   for (;;targ++, str1++, str2++) {
781672ac97cdSTom Musta     if (*targ!=*str1 && *targ!=*str2) return 0;
781772ac97cdSTom Musta     /* *targ has a match in one (or both, if terminator) */
781872ac97cdSTom Musta     if (*targ=='\0') break;
781972ac97cdSTom Musta     } /* forever */
782072ac97cdSTom Musta   return 1;
782172ac97cdSTom Musta   } /* decBiStr */
782272ac97cdSTom Musta 
782372ac97cdSTom Musta /* ------------------------------------------------------------------ */
782472ac97cdSTom Musta /* decNaNs -- handle NaN operand or operands			      */
782572ac97cdSTom Musta /*								      */
782672ac97cdSTom Musta /*   res     is the result number				      */
782772ac97cdSTom Musta /*   lhs     is the first operand				      */
782872ac97cdSTom Musta /*   rhs     is the second operand, or NULL if none		      */
782972ac97cdSTom Musta /*   context is used to limit payload length			      */
783072ac97cdSTom Musta /*   status  contains the current status			      */
783172ac97cdSTom Musta /*   returns res in case convenient				      */
783272ac97cdSTom Musta /*								      */
783372ac97cdSTom Musta /* Called when one or both operands is a NaN, and propagates the      */
783472ac97cdSTom Musta /* appropriate result to res.  When an sNaN is found, it is changed   */
783572ac97cdSTom Musta /* to a qNaN and Invalid operation is set.			      */
783672ac97cdSTom Musta /* ------------------------------------------------------------------ */
783772ac97cdSTom Musta static decNumber * decNaNs(decNumber *res, const decNumber *lhs,
783872ac97cdSTom Musta 			   const decNumber *rhs, decContext *set,
783972ac97cdSTom Musta 			   uInt *status) {
784072ac97cdSTom Musta   /* This decision tree ends up with LHS being the source pointer, */
784172ac97cdSTom Musta   /* and status updated if need be */
784272ac97cdSTom Musta   if (lhs->bits & DECSNAN)
784372ac97cdSTom Musta     *status|=DEC_Invalid_operation | DEC_sNaN;
784472ac97cdSTom Musta    else if (rhs==NULL);
784572ac97cdSTom Musta    else if (rhs->bits & DECSNAN) {
784672ac97cdSTom Musta     lhs=rhs;
784772ac97cdSTom Musta     *status|=DEC_Invalid_operation | DEC_sNaN;
784872ac97cdSTom Musta     }
784972ac97cdSTom Musta    else if (lhs->bits & DECNAN);
785072ac97cdSTom Musta    else lhs=rhs;
785172ac97cdSTom Musta 
785272ac97cdSTom Musta   /* propagate the payload */
785372ac97cdSTom Musta   if (lhs->digits<=set->digits) decNumberCopy(res, lhs); /* easy */
785472ac97cdSTom Musta    else { /* too long */
785572ac97cdSTom Musta     const Unit *ul;
785672ac97cdSTom Musta     Unit *ur, *uresp1;
785772ac97cdSTom Musta     /* copy safe number of units, then decapitate */
785872ac97cdSTom Musta     res->bits=lhs->bits;		/* need sign etc. */
785972ac97cdSTom Musta     uresp1=res->lsu+D2U(set->digits);
786072ac97cdSTom Musta     for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul;
786172ac97cdSTom Musta     res->digits=D2U(set->digits)*DECDPUN;
786272ac97cdSTom Musta     /* maybe still too long */
786372ac97cdSTom Musta     if (res->digits>set->digits) decDecap(res, res->digits-set->digits);
786472ac97cdSTom Musta     }
786572ac97cdSTom Musta 
786672ac97cdSTom Musta   res->bits&=~DECSNAN;	      /* convert any sNaN to NaN, while */
786772ac97cdSTom Musta   res->bits|=DECNAN;	      /* .. preserving sign */
786872ac97cdSTom Musta   res->exponent=0;	      /* clean exponent */
786972ac97cdSTom Musta 			      /* [coefficient was copied/decapitated] */
787072ac97cdSTom Musta   return res;
787172ac97cdSTom Musta   } /* decNaNs */
787272ac97cdSTom Musta 
787372ac97cdSTom Musta /* ------------------------------------------------------------------ */
787472ac97cdSTom Musta /* decStatus -- apply non-zero status				      */
787572ac97cdSTom Musta /*								      */
787672ac97cdSTom Musta /*   dn	    is the number to set if error			      */
787772ac97cdSTom Musta /*   status contains the current status (not yet in context)	      */
787872ac97cdSTom Musta /*   set    is the context					      */
787972ac97cdSTom Musta /*								      */
788072ac97cdSTom Musta /* If the status is an error status, the number is set to a NaN,      */
788172ac97cdSTom Musta /* unless the error was an overflow, divide-by-zero, or underflow,    */
788272ac97cdSTom Musta /* in which case the number will have already been set.		      */
788372ac97cdSTom Musta /*								      */
788472ac97cdSTom Musta /* The context status is then updated with the new status.  Note that */
788572ac97cdSTom Musta /* this may raise a signal, so control may never return from this     */
788672ac97cdSTom Musta /* routine (hence resources must be recovered before it is called).   */
788772ac97cdSTom Musta /* ------------------------------------------------------------------ */
788872ac97cdSTom Musta static void decStatus(decNumber *dn, uInt status, decContext *set) {
788972ac97cdSTom Musta   if (status & DEC_NaNs) {		/* error status -> NaN */
789072ac97cdSTom Musta     /* if cause was an sNaN, clear and propagate [NaN is already set up] */
789172ac97cdSTom Musta     if (status & DEC_sNaN) status&=~DEC_sNaN;
789272ac97cdSTom Musta      else {
789372ac97cdSTom Musta       decNumberZero(dn);		/* other error: clean throughout */
789472ac97cdSTom Musta       dn->bits=DECNAN;			/* and make a quiet NaN */
789572ac97cdSTom Musta       }
789672ac97cdSTom Musta     }
789772ac97cdSTom Musta   decContextSetStatus(set, status);	/* [may not return] */
789872ac97cdSTom Musta   return;
789972ac97cdSTom Musta   } /* decStatus */
790072ac97cdSTom Musta 
790172ac97cdSTom Musta /* ------------------------------------------------------------------ */
790272ac97cdSTom Musta /* decGetDigits -- count digits in a Units array		      */
790372ac97cdSTom Musta /*								      */
790472ac97cdSTom Musta /*   uar is the Unit array holding the number (this is often an	      */
790572ac97cdSTom Musta /*	    accumulator of some sort)				      */
790672ac97cdSTom Musta /*   len is the length of the array in units [>=1]		      */
790772ac97cdSTom Musta /*								      */
790872ac97cdSTom Musta /*   returns the number of (significant) digits in the array	      */
790972ac97cdSTom Musta /*								      */
791072ac97cdSTom Musta /* All leading zeros are excluded, except the last if the array has   */
791172ac97cdSTom Musta /* only zero Units.						      */
791272ac97cdSTom Musta /* ------------------------------------------------------------------ */
791372ac97cdSTom Musta /* This may be called twice during some operations. */
791472ac97cdSTom Musta static Int decGetDigits(Unit *uar, Int len) {
791572ac97cdSTom Musta   Unit *up=uar+(len-1);		   /* -> msu */
791672ac97cdSTom Musta   Int  digits=(len-1)*DECDPUN+1;   /* possible digits excluding msu */
791772ac97cdSTom Musta   #if DECDPUN>4
791872ac97cdSTom Musta   uInt const *pow;		   /* work */
791972ac97cdSTom Musta   #endif
792072ac97cdSTom Musta 				   /* (at least 1 in final msu) */
792172ac97cdSTom Musta   #if DECCHECK
792272ac97cdSTom Musta   if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len);
792372ac97cdSTom Musta   #endif
792472ac97cdSTom Musta 
792572ac97cdSTom Musta   for (; up>=uar; up--) {
792672ac97cdSTom Musta     if (*up==0) {		   /* unit is all 0s */
792772ac97cdSTom Musta       if (digits==1) break;	   /* a zero has one digit */
792872ac97cdSTom Musta       digits-=DECDPUN;		   /* adjust for 0 unit */
792972ac97cdSTom Musta       continue;}
793072ac97cdSTom Musta     /* found the first (most significant) non-zero Unit */
793172ac97cdSTom Musta     #if DECDPUN>1		   /* not done yet */
793272ac97cdSTom Musta     if (*up<10) break;		   /* is 1-9 */
793372ac97cdSTom Musta     digits++;
793472ac97cdSTom Musta     #if DECDPUN>2		   /* not done yet */
793572ac97cdSTom Musta     if (*up<100) break;		   /* is 10-99 */
793672ac97cdSTom Musta     digits++;
793772ac97cdSTom Musta     #if DECDPUN>3		   /* not done yet */
793872ac97cdSTom Musta     if (*up<1000) break;	   /* is 100-999 */
793972ac97cdSTom Musta     digits++;
794072ac97cdSTom Musta     #if DECDPUN>4		   /* count the rest ... */
794172ac97cdSTom Musta     for (pow=&powers[4]; *up>=*pow; pow++) digits++;
794272ac97cdSTom Musta     #endif
794372ac97cdSTom Musta     #endif
794472ac97cdSTom Musta     #endif
794572ac97cdSTom Musta     #endif
794672ac97cdSTom Musta     break;
794772ac97cdSTom Musta     } /* up */
794872ac97cdSTom Musta   return digits;
794972ac97cdSTom Musta   } /* decGetDigits */
795072ac97cdSTom Musta 
7951*21d7826fSLuis Pires /* ------------------------------------------------------------------ */
7952*21d7826fSLuis Pires /* mulUInt128ByPowOf10 -- multiply a 128-bit unsigned integer by a    */
7953*21d7826fSLuis Pires /* power of 10.                                                       */
7954*21d7826fSLuis Pires /*                                                                    */
7955*21d7826fSLuis Pires /*   The 128-bit factor composed of plow and phigh is multiplied      */
7956*21d7826fSLuis Pires /*   by 10^exp.                                                       */
7957*21d7826fSLuis Pires /*                                                                    */
7958*21d7826fSLuis Pires /*   plow   pointer to the low 64 bits of the first factor            */
7959*21d7826fSLuis Pires /*   phigh  pointer to the high 64 bits of the first factor           */
7960*21d7826fSLuis Pires /*   exp    the exponent of the power of 10 of the second factor      */
7961*21d7826fSLuis Pires /*                                                                    */
7962*21d7826fSLuis Pires /* If the result fits in 128 bits, returns false and the              */
7963*21d7826fSLuis Pires /* multiplication result through plow and phigh.                      */
7964*21d7826fSLuis Pires /* Otherwise, returns true.                                           */
7965*21d7826fSLuis Pires /* ------------------------------------------------------------------ */
7966*21d7826fSLuis Pires static bool mulUInt128ByPowOf10(uLong *plow, uLong *phigh, uInt pow10)
7967*21d7826fSLuis Pires {
7968*21d7826fSLuis Pires     while (pow10 >= ARRAY_SIZE(powers)) {
7969*21d7826fSLuis Pires         if (mulu128(plow, phigh, powers[ARRAY_SIZE(powers) - 1])) {
7970*21d7826fSLuis Pires             /* Overflow */
7971*21d7826fSLuis Pires             return true;
7972*21d7826fSLuis Pires         }
7973*21d7826fSLuis Pires         pow10 -= ARRAY_SIZE(powers) - 1;
7974*21d7826fSLuis Pires     }
7975*21d7826fSLuis Pires 
7976*21d7826fSLuis Pires     if (pow10 > 0) {
7977*21d7826fSLuis Pires         return mulu128(plow, phigh, powers[pow10]);
7978*21d7826fSLuis Pires     } else {
7979*21d7826fSLuis Pires         return false;
7980*21d7826fSLuis Pires     }
7981*21d7826fSLuis Pires }
7982*21d7826fSLuis Pires 
798372ac97cdSTom Musta #if DECTRACE | DECCHECK
798472ac97cdSTom Musta /* ------------------------------------------------------------------ */
798572ac97cdSTom Musta /* decNumberShow -- display a number [debug aid]		      */
798672ac97cdSTom Musta /*   dn is the number to show					      */
798772ac97cdSTom Musta /*								      */
798872ac97cdSTom Musta /* Shows: sign, exponent, coefficient (msu first), digits	      */
798972ac97cdSTom Musta /*    or: sign, special-value					      */
799072ac97cdSTom Musta /* ------------------------------------------------------------------ */
799172ac97cdSTom Musta /* this is public so other modules can use it */
799272ac97cdSTom Musta void decNumberShow(const decNumber *dn) {
799372ac97cdSTom Musta   const Unit *up;		   /* work */
799472ac97cdSTom Musta   uInt u, d;			   /* .. */
799572ac97cdSTom Musta   Int cut;			   /* .. */
799672ac97cdSTom Musta   char isign='+';		   /* main sign */
799772ac97cdSTom Musta   if (dn==NULL) {
799872ac97cdSTom Musta     printf("NULL\n");
799972ac97cdSTom Musta     return;}
800072ac97cdSTom Musta   if (decNumberIsNegative(dn)) isign='-';
800172ac97cdSTom Musta   printf(" >> %c ", isign);
800272ac97cdSTom Musta   if (dn->bits&DECSPECIAL) {	   /* Is a special value */
800372ac97cdSTom Musta     if (decNumberIsInfinite(dn)) printf("Infinity");
800472ac97cdSTom Musta      else {				     /* a NaN */
800572ac97cdSTom Musta       if (dn->bits&DECSNAN) printf("sNaN");  /* signalling NaN */
800672ac97cdSTom Musta        else printf("NaN");
800772ac97cdSTom Musta       }
800872ac97cdSTom Musta     /* if coefficient and exponent are 0, no more to do */
800972ac97cdSTom Musta     if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) {
801072ac97cdSTom Musta       printf("\n");
801172ac97cdSTom Musta       return;}
801272ac97cdSTom Musta     /* drop through to report other information */
801372ac97cdSTom Musta     printf(" ");
801472ac97cdSTom Musta     }
801572ac97cdSTom Musta 
801672ac97cdSTom Musta   /* now carefully display the coefficient */
801772ac97cdSTom Musta   up=dn->lsu+D2U(dn->digits)-1;		/* msu */
801872ac97cdSTom Musta   printf("%ld", (LI)*up);
801972ac97cdSTom Musta   for (up=up-1; up>=dn->lsu; up--) {
802072ac97cdSTom Musta     u=*up;
802172ac97cdSTom Musta     printf(":");
802272ac97cdSTom Musta     for (cut=DECDPUN-1; cut>=0; cut--) {
802372ac97cdSTom Musta       d=u/powers[cut];
802472ac97cdSTom Musta       u-=d*powers[cut];
802572ac97cdSTom Musta       printf("%ld", (LI)d);
802672ac97cdSTom Musta       } /* cut */
802772ac97cdSTom Musta     } /* up */
802872ac97cdSTom Musta   if (dn->exponent!=0) {
802972ac97cdSTom Musta     char esign='+';
803072ac97cdSTom Musta     if (dn->exponent<0) esign='-';
803172ac97cdSTom Musta     printf(" E%c%ld", esign, (LI)abs(dn->exponent));
803272ac97cdSTom Musta     }
803372ac97cdSTom Musta   printf(" [%ld]\n", (LI)dn->digits);
803472ac97cdSTom Musta   } /* decNumberShow */
803572ac97cdSTom Musta #endif
803672ac97cdSTom Musta 
803772ac97cdSTom Musta #if DECTRACE || DECCHECK
803872ac97cdSTom Musta /* ------------------------------------------------------------------ */
803972ac97cdSTom Musta /* decDumpAr -- display a unit array [debug/check aid]		      */
804072ac97cdSTom Musta /*   name is a single-character tag name			      */
804172ac97cdSTom Musta /*   ar	  is the array to display				      */
804272ac97cdSTom Musta /*   len  is the length of the array in Units			      */
804372ac97cdSTom Musta /* ------------------------------------------------------------------ */
804472ac97cdSTom Musta static void decDumpAr(char name, const Unit *ar, Int len) {
804572ac97cdSTom Musta   Int i;
804672ac97cdSTom Musta   const char *spec;
804772ac97cdSTom Musta   #if DECDPUN==9
804872ac97cdSTom Musta     spec="%09d ";
804972ac97cdSTom Musta   #elif DECDPUN==8
805072ac97cdSTom Musta     spec="%08d ";
805172ac97cdSTom Musta   #elif DECDPUN==7
805272ac97cdSTom Musta     spec="%07d ";
805372ac97cdSTom Musta   #elif DECDPUN==6
805472ac97cdSTom Musta     spec="%06d ";
805572ac97cdSTom Musta   #elif DECDPUN==5
805672ac97cdSTom Musta     spec="%05d ";
805772ac97cdSTom Musta   #elif DECDPUN==4
805872ac97cdSTom Musta     spec="%04d ";
805972ac97cdSTom Musta   #elif DECDPUN==3
806072ac97cdSTom Musta     spec="%03d ";
806172ac97cdSTom Musta   #elif DECDPUN==2
806272ac97cdSTom Musta     spec="%02d ";
806372ac97cdSTom Musta   #else
806472ac97cdSTom Musta     spec="%d ";
806572ac97cdSTom Musta   #endif
806672ac97cdSTom Musta   printf("  :%c: ", name);
806772ac97cdSTom Musta   for (i=len-1; i>=0; i--) {
806872ac97cdSTom Musta     if (i==len-1) printf("%ld ", (LI)ar[i]);
806972ac97cdSTom Musta      else printf(spec, ar[i]);
807072ac97cdSTom Musta     }
807172ac97cdSTom Musta   printf("\n");
807272ac97cdSTom Musta   return;}
807372ac97cdSTom Musta #endif
807472ac97cdSTom Musta 
807572ac97cdSTom Musta #if DECCHECK
807672ac97cdSTom Musta /* ------------------------------------------------------------------ */
807772ac97cdSTom Musta /* decCheckOperands -- check operand(s) to a routine		      */
807872ac97cdSTom Musta /*   res is the result structure (not checked; it will be set to      */
807972ac97cdSTom Musta /*	    quiet NaN if error found (and it is not NULL))	      */
808072ac97cdSTom Musta /*   lhs is the first operand (may be DECUNRESU)		      */
808172ac97cdSTom Musta /*   rhs is the second (may be DECUNUSED)			      */
808272ac97cdSTom Musta /*   set is the context (may be DECUNCONT)			      */
808372ac97cdSTom Musta /*   returns 0 if both operands, and the context are clean, or 1      */
808472ac97cdSTom Musta /*     otherwise (in which case the context will show an error,	      */
808572ac97cdSTom Musta /*     unless NULL).  Note that res is not cleaned; caller should     */
808672ac97cdSTom Musta /*     handle this so res=NULL case is safe.			      */
808772ac97cdSTom Musta /* The caller is expected to abandon immediately if 1 is returned.    */
808872ac97cdSTom Musta /* ------------------------------------------------------------------ */
808972ac97cdSTom Musta static Flag decCheckOperands(decNumber *res, const decNumber *lhs,
809072ac97cdSTom Musta 			     const decNumber *rhs, decContext *set) {
809172ac97cdSTom Musta   Flag bad=0;
809272ac97cdSTom Musta   if (set==NULL) {		   /* oops; hopeless */
809372ac97cdSTom Musta     #if DECTRACE || DECVERB
809472ac97cdSTom Musta     printf("Reference to context is NULL.\n");
809572ac97cdSTom Musta     #endif
809672ac97cdSTom Musta     bad=1;
809772ac97cdSTom Musta     return 1;}
809872ac97cdSTom Musta    else if (set!=DECUNCONT
809972ac97cdSTom Musta      && (set->digits<1 || set->round>=DEC_ROUND_MAX)) {
810072ac97cdSTom Musta     bad=1;
810172ac97cdSTom Musta     #if DECTRACE || DECVERB
810272ac97cdSTom Musta     printf("Bad context [digits=%ld round=%ld].\n",
810372ac97cdSTom Musta 	   (LI)set->digits, (LI)set->round);
810472ac97cdSTom Musta     #endif
810572ac97cdSTom Musta     }
810672ac97cdSTom Musta    else {
810772ac97cdSTom Musta     if (res==NULL) {
810872ac97cdSTom Musta       bad=1;
810972ac97cdSTom Musta       #if DECTRACE
811072ac97cdSTom Musta       /* this one not DECVERB as standard tests include NULL */
811172ac97cdSTom Musta       printf("Reference to result is NULL.\n");
811272ac97cdSTom Musta       #endif
811372ac97cdSTom Musta       }
811472ac97cdSTom Musta     if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs));
811572ac97cdSTom Musta     if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs));
811672ac97cdSTom Musta     }
811772ac97cdSTom Musta   if (bad) {
811872ac97cdSTom Musta     if (set!=DECUNCONT) decContextSetStatus(set, DEC_Invalid_operation);
811972ac97cdSTom Musta     if (res!=DECUNRESU && res!=NULL) {
812072ac97cdSTom Musta       decNumberZero(res);
812172ac97cdSTom Musta       res->bits=DECNAN;	      /* qNaN */
812272ac97cdSTom Musta       }
812372ac97cdSTom Musta     }
812472ac97cdSTom Musta   return bad;
812572ac97cdSTom Musta   } /* decCheckOperands */
812672ac97cdSTom Musta 
812772ac97cdSTom Musta /* ------------------------------------------------------------------ */
812872ac97cdSTom Musta /* decCheckNumber -- check a number				      */
812972ac97cdSTom Musta /*   dn is the number to check					      */
813072ac97cdSTom Musta /*   returns 0 if the number is clean, or 1 otherwise		      */
813172ac97cdSTom Musta /*								      */
813272ac97cdSTom Musta /* The number is considered valid if it could be a result from some   */
813372ac97cdSTom Musta /* operation in some valid context.				      */
813472ac97cdSTom Musta /* ------------------------------------------------------------------ */
813572ac97cdSTom Musta static Flag decCheckNumber(const decNumber *dn) {
813672ac97cdSTom Musta   const Unit *up;	      /* work */
813772ac97cdSTom Musta   uInt maxuint;		      /* .. */
813872ac97cdSTom Musta   Int ae, d, digits;	      /* .. */
813972ac97cdSTom Musta   Int emin, emax;	      /* .. */
814072ac97cdSTom Musta 
814172ac97cdSTom Musta   if (dn==NULL) {	      /* hopeless */
814272ac97cdSTom Musta     #if DECTRACE
814372ac97cdSTom Musta     /* this one not DECVERB as standard tests include NULL */
814472ac97cdSTom Musta     printf("Reference to decNumber is NULL.\n");
814572ac97cdSTom Musta     #endif
814672ac97cdSTom Musta     return 1;}
814772ac97cdSTom Musta 
814872ac97cdSTom Musta   /* check special values */
814972ac97cdSTom Musta   if (dn->bits & DECSPECIAL) {
815072ac97cdSTom Musta     if (dn->exponent!=0) {
815172ac97cdSTom Musta       #if DECTRACE || DECVERB
815272ac97cdSTom Musta       printf("Exponent %ld (not 0) for a special value [%02x].\n",
815372ac97cdSTom Musta 	     (LI)dn->exponent, dn->bits);
815472ac97cdSTom Musta       #endif
815572ac97cdSTom Musta       return 1;}
815672ac97cdSTom Musta 
815772ac97cdSTom Musta     /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */
815872ac97cdSTom Musta     if (decNumberIsInfinite(dn)) {
815972ac97cdSTom Musta       if (dn->digits!=1) {
816072ac97cdSTom Musta 	#if DECTRACE || DECVERB
816172ac97cdSTom Musta 	printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits);
816272ac97cdSTom Musta 	#endif
816372ac97cdSTom Musta 	return 1;}
816472ac97cdSTom Musta       if (*dn->lsu!=0) {
816572ac97cdSTom Musta 	#if DECTRACE || DECVERB
816672ac97cdSTom Musta 	printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu);
816772ac97cdSTom Musta 	#endif
816872ac97cdSTom Musta 	decDumpAr('I', dn->lsu, D2U(dn->digits));
816972ac97cdSTom Musta 	return 1;}
817072ac97cdSTom Musta       } /* Inf */
817172ac97cdSTom Musta     /* 2002.12.26: negative NaNs can now appear through proposed IEEE */
817272ac97cdSTom Musta     /*		   concrete formats (decimal64, etc.). */
817372ac97cdSTom Musta     return 0;
817472ac97cdSTom Musta     }
817572ac97cdSTom Musta 
817672ac97cdSTom Musta   /* check the coefficient */
817772ac97cdSTom Musta   if (dn->digits<1 || dn->digits>DECNUMMAXP) {
817872ac97cdSTom Musta     #if DECTRACE || DECVERB
817972ac97cdSTom Musta     printf("Digits %ld in number.\n", (LI)dn->digits);
818072ac97cdSTom Musta     #endif
818172ac97cdSTom Musta     return 1;}
818272ac97cdSTom Musta 
818372ac97cdSTom Musta   d=dn->digits;
818472ac97cdSTom Musta 
818572ac97cdSTom Musta   for (up=dn->lsu; d>0; up++) {
818672ac97cdSTom Musta     if (d>DECDPUN) maxuint=DECDPUNMAX;
818772ac97cdSTom Musta      else {		      /* reached the msu */
818872ac97cdSTom Musta       maxuint=powers[d]-1;
818972ac97cdSTom Musta       if (dn->digits>1 && *up<powers[d-1]) {
819072ac97cdSTom Musta 	#if DECTRACE || DECVERB
819172ac97cdSTom Musta 	printf("Leading 0 in number.\n");
819272ac97cdSTom Musta 	decNumberShow(dn);
819372ac97cdSTom Musta 	#endif
819472ac97cdSTom Musta 	return 1;}
819572ac97cdSTom Musta       }
819672ac97cdSTom Musta     if (*up>maxuint) {
819772ac97cdSTom Musta       #if DECTRACE || DECVERB
819872ac97cdSTom Musta       printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n",
819972ac97cdSTom Musta 	      (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint);
820072ac97cdSTom Musta       #endif
820172ac97cdSTom Musta       return 1;}
820272ac97cdSTom Musta     d-=DECDPUN;
820372ac97cdSTom Musta     }
820472ac97cdSTom Musta 
820572ac97cdSTom Musta   /* check the exponent.  Note that input operands can have exponents */
820672ac97cdSTom Musta   /* which are out of the set->emin/set->emax and set->digits range */
820772ac97cdSTom Musta   /* (just as they can have more digits than set->digits). */
820872ac97cdSTom Musta   ae=dn->exponent+dn->digits-1;	   /* adjusted exponent */
820972ac97cdSTom Musta   emax=DECNUMMAXE;
821072ac97cdSTom Musta   emin=DECNUMMINE;
821172ac97cdSTom Musta   digits=DECNUMMAXP;
821272ac97cdSTom Musta   if (ae<emin-(digits-1)) {
821372ac97cdSTom Musta     #if DECTRACE || DECVERB
821472ac97cdSTom Musta     printf("Adjusted exponent underflow [%ld].\n", (LI)ae);
821572ac97cdSTom Musta     decNumberShow(dn);
821672ac97cdSTom Musta     #endif
821772ac97cdSTom Musta     return 1;}
821872ac97cdSTom Musta   if (ae>+emax) {
821972ac97cdSTom Musta     #if DECTRACE || DECVERB
822072ac97cdSTom Musta     printf("Adjusted exponent overflow [%ld].\n", (LI)ae);
822172ac97cdSTom Musta     decNumberShow(dn);
822272ac97cdSTom Musta     #endif
822372ac97cdSTom Musta     return 1;}
822472ac97cdSTom Musta 
822572ac97cdSTom Musta   return 0;		 /* it's OK */
822672ac97cdSTom Musta   } /* decCheckNumber */
822772ac97cdSTom Musta 
822872ac97cdSTom Musta /* ------------------------------------------------------------------ */
822972ac97cdSTom Musta /* decCheckInexact -- check a normal finite inexact result has digits */
823072ac97cdSTom Musta /*   dn is the number to check					      */
823172ac97cdSTom Musta /*   set is the context (for status and precision)		      */
823272ac97cdSTom Musta /*   sets Invalid operation, etc., if some digits are missing	      */
823372ac97cdSTom Musta /* [this check is not made for DECSUBSET compilation or when	      */
823472ac97cdSTom Musta /* subnormal is not set]					      */
823572ac97cdSTom Musta /* ------------------------------------------------------------------ */
823672ac97cdSTom Musta static void decCheckInexact(const decNumber *dn, decContext *set) {
823772ac97cdSTom Musta   #if !DECSUBSET && DECEXTFLAG
823872ac97cdSTom Musta     if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact
823972ac97cdSTom Musta      && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) {
824072ac97cdSTom Musta       #if DECTRACE || DECVERB
824172ac97cdSTom Musta       printf("Insufficient digits [%ld] on normal Inexact result.\n",
824272ac97cdSTom Musta 	     (LI)dn->digits);
824372ac97cdSTom Musta       decNumberShow(dn);
824472ac97cdSTom Musta       #endif
824572ac97cdSTom Musta       decContextSetStatus(set, DEC_Invalid_operation);
824672ac97cdSTom Musta       }
824772ac97cdSTom Musta   #else
824872ac97cdSTom Musta     /* next is a noop for quiet compiler */
824972ac97cdSTom Musta     if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation;
825072ac97cdSTom Musta   #endif
825172ac97cdSTom Musta   return;
825272ac97cdSTom Musta   } /* decCheckInexact */
825372ac97cdSTom Musta #endif
825472ac97cdSTom Musta 
825572ac97cdSTom Musta #if DECALLOC
825672ac97cdSTom Musta #undef malloc
825772ac97cdSTom Musta #undef free
825872ac97cdSTom Musta /* ------------------------------------------------------------------ */
825972ac97cdSTom Musta /* decMalloc -- accountable allocation routine			      */
826072ac97cdSTom Musta /*   n is the number of bytes to allocate			      */
826172ac97cdSTom Musta /*								      */
826272ac97cdSTom Musta /* Semantics is the same as the stdlib malloc routine, but bytes      */
826372ac97cdSTom Musta /* allocated are accounted for globally, and corruption fences are    */
826472ac97cdSTom Musta /* added before and after the 'actual' storage.			      */
826572ac97cdSTom Musta /* ------------------------------------------------------------------ */
826672ac97cdSTom Musta /* This routine allocates storage with an extra twelve bytes; 8 are   */
826772ac97cdSTom Musta /* at the start and hold:					      */
826872ac97cdSTom Musta /*   0-3 the original length requested				      */
826972ac97cdSTom Musta /*   4-7 buffer corruption detection fence (DECFENCE, x4)	      */
827072ac97cdSTom Musta /* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */
827172ac97cdSTom Musta /* ------------------------------------------------------------------ */
827272ac97cdSTom Musta static void *decMalloc(size_t n) {
827372ac97cdSTom Musta   uInt	size=n+12;		   /* true size */
827472ac97cdSTom Musta   void	*alloc;			   /* -> allocated storage */
827572ac97cdSTom Musta   uInt	*j;			   /* work */
827672ac97cdSTom Musta   uByte *b, *b0;		   /* .. */
827772ac97cdSTom Musta 
827872ac97cdSTom Musta   alloc=malloc(size);		   /* -> allocated storage */
827972ac97cdSTom Musta   if (alloc==NULL) return NULL;	   /* out of strorage */
828072ac97cdSTom Musta   b0=(uByte *)alloc;		   /* as bytes */
828172ac97cdSTom Musta   decAllocBytes+=n;		   /* account for storage */
828272ac97cdSTom Musta   j=(uInt *)alloc;		   /* -> first four bytes */
828372ac97cdSTom Musta   *j=n;				   /* save n */
828472ac97cdSTom Musta   /* printf(" alloc ++ dAB: %ld (%d)\n", decAllocBytes, n); */
828572ac97cdSTom Musta   for (b=b0+4; b<b0+8; b++) *b=DECFENCE;
828672ac97cdSTom Musta   for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE;
828772ac97cdSTom Musta   return b0+8;			   /* -> play area */
828872ac97cdSTom Musta   } /* decMalloc */
828972ac97cdSTom Musta 
829072ac97cdSTom Musta /* ------------------------------------------------------------------ */
829172ac97cdSTom Musta /* decFree -- accountable free routine				      */
829272ac97cdSTom Musta /*   alloc is the storage to free				      */
829372ac97cdSTom Musta /*								      */
829472ac97cdSTom Musta /* Semantics is the same as the stdlib malloc routine, except that    */
829572ac97cdSTom Musta /* the global storage accounting is updated and the fences are	      */
829672ac97cdSTom Musta /* checked to ensure that no routine has written 'out of bounds'.     */
829772ac97cdSTom Musta /* ------------------------------------------------------------------ */
829872ac97cdSTom Musta /* This routine first checks that the fences have not been corrupted. */
829972ac97cdSTom Musta /* It then frees the storage using the 'truw' storage address (that   */
830072ac97cdSTom Musta /* is, offset by 8).						      */
830172ac97cdSTom Musta /* ------------------------------------------------------------------ */
830272ac97cdSTom Musta static void decFree(void *alloc) {
830372ac97cdSTom Musta   uInt	*j, n;			   /* pointer, original length */
830472ac97cdSTom Musta   uByte *b, *b0;		   /* work */
830572ac97cdSTom Musta 
830672ac97cdSTom Musta   if (alloc==NULL) return;	   /* allowed; it's a nop */
830772ac97cdSTom Musta   b0=(uByte *)alloc;		   /* as bytes */
830872ac97cdSTom Musta   b0-=8;			   /* -> true start of storage */
830972ac97cdSTom Musta   j=(uInt *)b0;			   /* -> first four bytes */
831072ac97cdSTom Musta   n=*j;				   /* lift */
831172ac97cdSTom Musta   for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE)
831272ac97cdSTom Musta     printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b,
831372ac97cdSTom Musta 	   b-b0-8, (Int)b0);
831472ac97cdSTom Musta   for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE)
831572ac97cdSTom Musta     printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b,
831672ac97cdSTom Musta 	   b-b0-8, (Int)b0, n);
831772ac97cdSTom Musta   free(b0);			   /* drop the storage */
831872ac97cdSTom Musta   decAllocBytes-=n;		   /* account for storage */
831972ac97cdSTom Musta   /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */
832072ac97cdSTom Musta   } /* decFree */
832172ac97cdSTom Musta #define malloc(a) decMalloc(a)
832272ac97cdSTom Musta #define free(a) decFree(a)
832372ac97cdSTom Musta #endif
8324