OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [libdecnumber/] [decNumber.c] - Diff between revs 827 and 840

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 827 Rev 840
/* Decimal number arithmetic module for the decNumber C Library.
/* Decimal number arithmetic module for the decNumber C Library.
   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
   Contributed by IBM Corporation.  Author Mike Cowlishaw.
   Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
 
   This file is part of GCC.
   This file is part of GCC.
 
 
   GCC is free software; you can redistribute it and/or modify it under
   GCC is free software; you can redistribute it and/or modify it under
   the terms of the GNU General Public License as published by the Free
   the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 2, or (at your option) any later
   Software Foundation; either version 2, or (at your option) any later
   version.
   version.
 
 
   In addition to the permissions in the GNU General Public License,
   In addition to the permissions in the GNU General Public License,
   the Free Software Foundation gives you unlimited permission to link
   the Free Software Foundation gives you unlimited permission to link
   the compiled version of this file into combinations with other
   the compiled version of this file into combinations with other
   programs, and to distribute those combinations without any
   programs, and to distribute those combinations without any
   restriction coming from the use of this file.  (The General Public
   restriction coming from the use of this file.  (The General Public
   License restrictions do apply in other respects; for example, they
   License restrictions do apply in other respects; for example, they
   cover modification of the file, and distribution when not linked
   cover modification of the file, and distribution when not linked
   into a combine executable.)
   into a combine executable.)
 
 
   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for more details.
   for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING.  If not, write to the Free
   along with GCC; see the file COPYING.  If not, write to the Free
   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* Decimal Number arithmetic module                                   */
/* Decimal Number arithmetic module                                   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This module comprises the routines for General Decimal Arithmetic  */
/* This module comprises the routines for General Decimal Arithmetic  */
/* as defined in the specification which may be found on the          */
/* as defined in the specification which may be found on the          */
/* http://www2.hursley.ibm.com/decimal web pages.  It implements both */
/* http://www2.hursley.ibm.com/decimal web pages.  It implements both */
/* the full ('extended') arithmetic and the simpler ('subset')        */
/* the full ('extended') arithmetic and the simpler ('subset')        */
/* arithmetic.                                                        */
/* arithmetic.                                                        */
/*                                                                    */
/*                                                                    */
/* Usage notes:                                                       */
/* Usage notes:                                                       */
/*                                                                    */
/*                                                                    */
/* 1. This code is ANSI C89 except:                                   */
/* 1. This code is ANSI C89 except:                                   */
/*                                                                    */
/*                                                                    */
/*       If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and       */
/*       If DECDPUN>4 or DECUSE64=1, the C99 64-bit int64_t and       */
/*       uint64_t types may be used.  To avoid these, set DECUSE64=0  */
/*       uint64_t types may be used.  To avoid these, set DECUSE64=0  */
/*       and DECDPUN<=4 (see documentation).                          */
/*       and DECDPUN<=4 (see documentation).                          */
/*                                                                    */
/*                                                                    */
/* 2. The decNumber format which this library uses is optimized for   */
/* 2. The decNumber format which this library uses is optimized for   */
/*    efficient processing of relatively short numbers; in particular */
/*    efficient processing of relatively short numbers; in particular */
/*    it allows the use of fixed sized structures and minimizes copy  */
/*    it allows the use of fixed sized structures and minimizes copy  */
/*    and move operations.  It does, however, support arbitrary       */
/*    and move operations.  It does, however, support arbitrary       */
/*    precision (up to 999,999,999 digits) and arbitrary exponent     */
/*    precision (up to 999,999,999 digits) and arbitrary exponent     */
/*    range (Emax in the range 0 through 999,999,999 and Emin in the  */
/*    range (Emax in the range 0 through 999,999,999 and Emin in the  */
/*    range -999,999,999 through 0).  Mathematical functions (for     */
/*    range -999,999,999 through 0).  Mathematical functions (for     */
/*    example decNumberExp) as identified below are restricted more   */
/*    example decNumberExp) as identified below are restricted more   */
/*    tightly: digits, emax, and -emin in the context must be <=      */
/*    tightly: digits, emax, and -emin in the context must be <=      */
/*    DEC_MAX_MATH (999999), and their operand(s) must be within      */
/*    DEC_MAX_MATH (999999), and their operand(s) must be within      */
/*    these bounds.                                                   */
/*    these bounds.                                                   */
/*                                                                    */
/*                                                                    */
/* 3. Logical functions are further restricted; their operands must   */
/* 3. Logical functions are further restricted; their operands must   */
/*    be finite, positive, have an exponent of zero, and all digits   */
/*    be finite, positive, have an exponent of zero, and all digits   */
/*    must be either 0 or 1.  The result will only contain digits     */
/*    must be either 0 or 1.  The result will only contain digits     */
/*    which are 0 or 1 (and will have exponent=0 and a sign of 0).    */
/*    which are 0 or 1 (and will have exponent=0 and a sign of 0).    */
/*                                                                    */
/*                                                                    */
/* 4. Operands to operator functions are never modified unless they   */
/* 4. Operands to operator functions are never modified unless they   */
/*    are also specified to be the result number (which is always     */
/*    are also specified to be the result number (which is always     */
/*    permitted).  Other than that case, operands must not overlap.   */
/*    permitted).  Other than that case, operands must not overlap.   */
/*                                                                    */
/*                                                                    */
/* 5. Error handling: the type of the error is ORed into the status   */
/* 5. Error handling: the type of the error is ORed into the status   */
/*    flags in the current context (decContext structure).  The       */
/*    flags in the current context (decContext structure).  The       */
/*    SIGFPE signal is then raised if the corresponding trap-enabler  */
/*    SIGFPE signal is then raised if the corresponding trap-enabler  */
/*    flag in the decContext is set (is 1).                           */
/*    flag in the decContext is set (is 1).                           */
/*                                                                    */
/*                                                                    */
/*    It is the responsibility of the caller to clear the status      */
/*    It is the responsibility of the caller to clear the status      */
/*    flags as required.                                              */
/*    flags as required.                                              */
/*                                                                    */
/*                                                                    */
/*    The result of any routine which returns a number will always    */
/*    The result of any routine which returns a number will always    */
/*    be a valid number (which may be a special value, such as an     */
/*    be a valid number (which may be a special value, such as an     */
/*    Infinity or NaN).                                               */
/*    Infinity or NaN).                                               */
/*                                                                    */
/*                                                                    */
/* 6. The decNumber format is not an exchangeable concrete            */
/* 6. The decNumber format is not an exchangeable concrete            */
/*    representation as it comprises fields which may be machine-     */
/*    representation as it comprises fields which may be machine-     */
/*    dependent (packed or unpacked, or special length, for example). */
/*    dependent (packed or unpacked, or special length, for example). */
/*    Canonical conversions to and from strings are provided; other   */
/*    Canonical conversions to and from strings are provided; other   */
/*    conversions are available in separate modules.                  */
/*    conversions are available in separate modules.                  */
/*                                                                    */
/*                                                                    */
/* 7. Normally, input operands are assumed to be valid.  Set DECCHECK */
/* 7. Normally, input operands are assumed to be valid.  Set DECCHECK */
/*    to 1 for extended operand checking (including NULL operands).   */
/*    to 1 for extended operand checking (including NULL operands).   */
/*    Results are undefined if a badly-formed structure (or a NULL    */
/*    Results are undefined if a badly-formed structure (or a NULL    */
/*    pointer to a structure) is provided, though with DECCHECK       */
/*    pointer to a structure) is provided, though with DECCHECK       */
/*    enabled the operator routines are protected against exceptions. */
/*    enabled the operator routines are protected against exceptions. */
/*    (Except if the result pointer is NULL, which is unrecoverable.) */
/*    (Except if the result pointer is NULL, which is unrecoverable.) */
/*                                                                    */
/*                                                                    */
/*    However, the routines will never cause exceptions if they are   */
/*    However, the routines will never cause exceptions if they are   */
/*    given well-formed operands, even if the value of the operands   */
/*    given well-formed operands, even if the value of the operands   */
/*    is inappropriate for the operation and DECCHECK is not set.     */
/*    is inappropriate for the operation and DECCHECK is not set.     */
/*    (Except for SIGFPE, as and where documented.)                   */
/*    (Except for SIGFPE, as and where documented.)                   */
/*                                                                    */
/*                                                                    */
/* 8. Subset arithmetic is available only if DECSUBSET is set to 1.   */
/* 8. Subset arithmetic is available only if DECSUBSET is set to 1.   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* Implementation notes for maintenance of this module:               */
/* Implementation notes for maintenance of this module:               */
/*                                                                    */
/*                                                                    */
/* 1. Storage leak protection:  Routines which use malloc are not     */
/* 1. Storage leak protection:  Routines which use malloc are not     */
/*    permitted to use return for fastpath or error exits (i.e.,      */
/*    permitted to use return for fastpath or error exits (i.e.,      */
/*    they follow strict structured programming conventions).         */
/*    they follow strict structured programming conventions).         */
/*    Instead they have a do{}while(0); construct surrounding the     */
/*    Instead they have a do{}while(0); construct surrounding the     */
/*    code which is protected -- break may be used to exit this.      */
/*    code which is protected -- break may be used to exit this.      */
/*    Other routines can safely use the return statement inline.      */
/*    Other routines can safely use the return statement inline.      */
/*                                                                    */
/*                                                                    */
/*    Storage leak accounting can be enabled using DECALLOC.          */
/*    Storage leak accounting can be enabled using DECALLOC.          */
/*                                                                    */
/*                                                                    */
/* 2. All loops use the for(;;) construct.  Any do construct does     */
/* 2. All loops use the for(;;) construct.  Any do construct does     */
/*    not loop; it is for allocation protection as just described.    */
/*    not loop; it is for allocation protection as just described.    */
/*                                                                    */
/*                                                                    */
/* 3. Setting status in the context must always be the very last      */
/* 3. Setting status in the context must always be the very last      */
/*    action in a routine, as non-0 status may raise a trap and hence */
/*    action in a routine, as non-0 status may raise a trap and hence */
/*    the call to set status may not return (if the handler uses long */
/*    the call to set status may not return (if the handler uses long */
/*    jump).  Therefore all cleanup must be done first.  In general,  */
/*    jump).  Therefore all cleanup must be done first.  In general,  */
/*    to achieve this status is accumulated and is only applied just  */
/*    to achieve this status is accumulated and is only applied just  */
/*    before return by calling decContextSetStatus (via decStatus).   */
/*    before return by calling decContextSetStatus (via decStatus).   */
/*                                                                    */
/*                                                                    */
/*    Routines which allocate storage cannot, in general, use the     */
/*    Routines which allocate storage cannot, in general, use the     */
/*    'top level' routines which could cause a non-returning          */
/*    'top level' routines which could cause a non-returning          */
/*    transfer of control.  The decXxxxOp routines are safe (do not   */
/*    transfer of control.  The decXxxxOp routines are safe (do not   */
/*    call decStatus even if traps are set in the context) and should */
/*    call decStatus even if traps are set in the context) and should */
/*    be used instead (they are also a little faster).                */
/*    be used instead (they are also a little faster).                */
/*                                                                    */
/*                                                                    */
/* 4. Exponent checking is minimized by allowing the exponent to      */
/* 4. Exponent checking is minimized by allowing the exponent to      */
/*    grow outside its limits during calculations, provided that      */
/*    grow outside its limits during calculations, provided that      */
/*    the decFinalize function is called later.  Multiplication and   */
/*    the decFinalize function is called later.  Multiplication and   */
/*    division, and intermediate calculations in exponentiation,      */
/*    division, and intermediate calculations in exponentiation,      */
/*    require more careful checks because of the risk of 31-bit       */
/*    require more careful checks because of the risk of 31-bit       */
/*    overflow (the most negative valid exponent is -1999999997, for  */
/*    overflow (the most negative valid exponent is -1999999997, for  */
/*    a 999999999-digit number with adjusted exponent of -999999999). */
/*    a 999999999-digit number with adjusted exponent of -999999999). */
/*                                                                    */
/*                                                                    */
/* 5. Rounding is deferred until finalization of results, with any    */
/* 5. Rounding is deferred until finalization of results, with any    */
/*    'off to the right' data being represented as a single digit     */
/*    'off to the right' data being represented as a single digit     */
/*    residue (in the range -1 through 9).  This avoids any double-   */
/*    residue (in the range -1 through 9).  This avoids any double-   */
/*    rounding when more than one shortening takes place (for         */
/*    rounding when more than one shortening takes place (for         */
/*    example, when a result is subnormal).                           */
/*    example, when a result is subnormal).                           */
/*                                                                    */
/*                                                                    */
/* 6. The digits count is allowed to rise to a multiple of DECDPUN    */
/* 6. The digits count is allowed to rise to a multiple of DECDPUN    */
/*    during many operations, so whole Units are handled and exact    */
/*    during many operations, so whole Units are handled and exact    */
/*    accounting of digits is not needed.  The correct digits value   */
/*    accounting of digits is not needed.  The correct digits value   */
/*    is found by decGetDigits, which accounts for leading zeros.     */
/*    is found by decGetDigits, which accounts for leading zeros.     */
/*    This must be called before any rounding if the number of digits */
/*    This must be called before any rounding if the number of digits */
/*    is not known exactly.                                           */
/*    is not known exactly.                                           */
/*                                                                    */
/*                                                                    */
/* 7. The multiply-by-reciprocal 'trick' is used for partitioning     */
/* 7. The multiply-by-reciprocal 'trick' is used for partitioning     */
/*    numbers up to four digits, using appropriate constants.  This   */
/*    numbers up to four digits, using appropriate constants.  This   */
/*    is not useful for longer numbers because overflow of 32 bits    */
/*    is not useful for longer numbers because overflow of 32 bits    */
/*    would lead to 4 multiplies, which is almost as expensive as     */
/*    would lead to 4 multiplies, which is almost as expensive as     */
/*    a divide (unless a floating-point or 64-bit multiply is         */
/*    a divide (unless a floating-point or 64-bit multiply is         */
/*    assumed to be available).                                       */
/*    assumed to be available).                                       */
/*                                                                    */
/*                                                                    */
/* 8. Unusual abbreviations that may be used in the commentary:       */
/* 8. Unusual abbreviations that may be used in the commentary:       */
/*      lhs -- left hand side (operand, of an operation)              */
/*      lhs -- left hand side (operand, of an operation)              */
/*      lsd -- least significant digit (of coefficient)               */
/*      lsd -- least significant digit (of coefficient)               */
/*      lsu -- least significant Unit (of coefficient)                */
/*      lsu -- least significant Unit (of coefficient)                */
/*      msd -- most significant digit (of coefficient)                */
/*      msd -- most significant digit (of coefficient)                */
/*      msi -- most significant item (in an array)                    */
/*      msi -- most significant item (in an array)                    */
/*      msu -- most significant Unit (of coefficient)                 */
/*      msu -- most significant Unit (of coefficient)                 */
/*      rhs -- right hand side (operand, of an operation)             */
/*      rhs -- right hand side (operand, of an operation)             */
/*      +ve -- positive                                               */
/*      +ve -- positive                                               */
/*      -ve -- negative                                               */
/*      -ve -- negative                                               */
/*      **  -- raise to the power                                     */
/*      **  -- raise to the power                                     */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
 
 
#include <stdlib.h>                /* for malloc, free, etc. */
#include <stdlib.h>                /* for malloc, free, etc. */
#include <stdio.h>                 /* for printf [if needed] */
#include <stdio.h>                 /* for printf [if needed] */
#include <string.h>                /* for strcpy */
#include <string.h>                /* for strcpy */
#include <ctype.h>                 /* for lower */
#include <ctype.h>                 /* for lower */
#include "config.h"                /* for GCC definitions */
#include "config.h"                /* for GCC definitions */
#include "decNumber.h"             /* base number library */
#include "decNumber.h"             /* base number library */
#include "decNumberLocal.h"        /* decNumber local types, etc. */
#include "decNumberLocal.h"        /* decNumber local types, etc. */
 
 
/* Constants */
/* Constants */
/* Public lookup table used by the D2U macro */
/* Public lookup table used by the D2U macro */
const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
 
 
#define DECVERB     1              /* set to 1 for verbose DECCHECK */
#define DECVERB     1              /* set to 1 for verbose DECCHECK */
#define powers      DECPOWERS      /* old internal name */
#define powers      DECPOWERS      /* old internal name */
 
 
/* Local constants */
/* Local constants */
#define DIVIDE      0x80           /* Divide operators */
#define DIVIDE      0x80           /* Divide operators */
#define REMAINDER   0x40           /* .. */
#define REMAINDER   0x40           /* .. */
#define DIVIDEINT   0x20           /* .. */
#define DIVIDEINT   0x20           /* .. */
#define REMNEAR     0x10           /* .. */
#define REMNEAR     0x10           /* .. */
#define COMPARE     0x01           /* Compare operators */
#define COMPARE     0x01           /* Compare operators */
#define COMPMAX     0x02           /* .. */
#define COMPMAX     0x02           /* .. */
#define COMPMIN     0x03           /* .. */
#define COMPMIN     0x03           /* .. */
#define COMPTOTAL   0x04           /* .. */
#define COMPTOTAL   0x04           /* .. */
#define COMPNAN     0x05           /* .. [NaN processing] */
#define COMPNAN     0x05           /* .. [NaN processing] */
#define COMPSIG     0x06           /* .. [signaling COMPARE] */
#define COMPSIG     0x06           /* .. [signaling COMPARE] */
#define COMPMAXMAG  0x07           /* .. */
#define COMPMAXMAG  0x07           /* .. */
#define COMPMINMAG  0x08           /* .. */
#define COMPMINMAG  0x08           /* .. */
 
 
#define DEC_sNaN     0x40000000    /* local status: sNaN signal */
#define DEC_sNaN     0x40000000    /* local status: sNaN signal */
#define BADINT  (Int)0x80000000    /* most-negative Int; error indicator */
#define BADINT  (Int)0x80000000    /* most-negative Int; error indicator */
/* Next two indicate an integer >= 10**6, and its parity (bottom bit) */
/* Next two indicate an integer >= 10**6, and its parity (bottom bit) */
#define BIGEVEN (Int)0x80000002
#define BIGEVEN (Int)0x80000002
#define BIGODD  (Int)0x80000003
#define BIGODD  (Int)0x80000003
 
 
static Unit uarrone[1]={1};   /* Unit array of 1, used for incrementing */
static Unit uarrone[1]={1};   /* Unit array of 1, used for incrementing */
 
 
/* Granularity-dependent code */
/* Granularity-dependent code */
#if DECDPUN<=4
#if DECDPUN<=4
  #define eInt  Int           /* extended integer */
  #define eInt  Int           /* extended integer */
  #define ueInt uInt          /* unsigned extended integer */
  #define ueInt uInt          /* unsigned extended integer */
  /* Constant multipliers for divide-by-power-of five using reciprocal */
  /* Constant multipliers for divide-by-power-of five using reciprocal */
  /* multiply, after removing powers of 2 by shifting, and final shift */
  /* multiply, after removing powers of 2 by shifting, and final shift */
  /* of 17 [we only need up to **4] */
  /* of 17 [we only need up to **4] */
  static const uInt multies[]={131073, 26215, 5243, 1049, 210};
  static const uInt multies[]={131073, 26215, 5243, 1049, 210};
  /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */
  /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */
  #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
  #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
#else
#else
  /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */
  /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */
  #if !DECUSE64
  #if !DECUSE64
    #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4
    #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4
  #endif
  #endif
  #define eInt  Long          /* extended integer */
  #define eInt  Long          /* extended integer */
  #define ueInt uLong         /* unsigned extended integer */
  #define ueInt uLong         /* unsigned extended integer */
#endif
#endif
 
 
/* Local routines */
/* Local routines */
static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *,
static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *,
                              decContext *, uByte, uInt *);
                              decContext *, uByte, uInt *);
static Flag        decBiStr(const char *, const char *, const char *);
static Flag        decBiStr(const char *, const char *, const char *);
static uInt        decCheckMath(const decNumber *, decContext *, uInt *);
static uInt        decCheckMath(const decNumber *, decContext *, uInt *);
static void        decApplyRound(decNumber *, decContext *, Int, uInt *);
static void        decApplyRound(decNumber *, decContext *, Int, uInt *);
static Int         decCompare(const decNumber *lhs, const decNumber *rhs, Flag);
static Int         decCompare(const decNumber *lhs, const decNumber *rhs, Flag);
static decNumber * decCompareOp(decNumber *, const decNumber *,
static decNumber * decCompareOp(decNumber *, const decNumber *,
                              const decNumber *, decContext *,
                              const decNumber *, decContext *,
                              Flag, uInt *);
                              Flag, uInt *);
static void        decCopyFit(decNumber *, const decNumber *, decContext *,
static void        decCopyFit(decNumber *, const decNumber *, decContext *,
                              Int *, uInt *);
                              Int *, uInt *);
static decNumber * decDecap(decNumber *, Int);
static decNumber * decDecap(decNumber *, Int);
static decNumber * decDivideOp(decNumber *, const decNumber *,
static decNumber * decDivideOp(decNumber *, const decNumber *,
                              const decNumber *, decContext *, Flag, uInt *);
                              const decNumber *, decContext *, Flag, uInt *);
static decNumber * decExpOp(decNumber *, const decNumber *,
static decNumber * decExpOp(decNumber *, const decNumber *,
                              decContext *, uInt *);
                              decContext *, uInt *);
static void        decFinalize(decNumber *, decContext *, Int *, uInt *);
static void        decFinalize(decNumber *, decContext *, Int *, uInt *);
static Int         decGetDigits(Unit *, Int);
static Int         decGetDigits(Unit *, Int);
static Int         decGetInt(const decNumber *);
static Int         decGetInt(const decNumber *);
static decNumber * decLnOp(decNumber *, const decNumber *,
static decNumber * decLnOp(decNumber *, const decNumber *,
                              decContext *, uInt *);
                              decContext *, uInt *);
static decNumber * decMultiplyOp(decNumber *, const decNumber *,
static decNumber * decMultiplyOp(decNumber *, const decNumber *,
                              const decNumber *, decContext *,
                              const decNumber *, decContext *,
                              uInt *);
                              uInt *);
static decNumber * decNaNs(decNumber *, const decNumber *,
static decNumber * decNaNs(decNumber *, const decNumber *,
                              const decNumber *, decContext *, uInt *);
                              const decNumber *, decContext *, uInt *);
static decNumber * decQuantizeOp(decNumber *, const decNumber *,
static decNumber * decQuantizeOp(decNumber *, const decNumber *,
                              const decNumber *, decContext *, Flag,
                              const decNumber *, decContext *, Flag,
                              uInt *);
                              uInt *);
static void        decReverse(Unit *, Unit *);
static void        decReverse(Unit *, Unit *);
static void        decSetCoeff(decNumber *, decContext *, const Unit *,
static void        decSetCoeff(decNumber *, decContext *, const Unit *,
                              Int, Int *, uInt *);
                              Int, Int *, uInt *);
static void        decSetMaxValue(decNumber *, decContext *);
static void        decSetMaxValue(decNumber *, decContext *);
static void        decSetOverflow(decNumber *, decContext *, uInt *);
static void        decSetOverflow(decNumber *, decContext *, uInt *);
static void        decSetSubnormal(decNumber *, decContext *, Int *, uInt *);
static void        decSetSubnormal(decNumber *, decContext *, Int *, uInt *);
static Int         decShiftToLeast(Unit *, Int, Int);
static Int         decShiftToLeast(Unit *, Int, Int);
static Int         decShiftToMost(Unit *, Int, Int);
static Int         decShiftToMost(Unit *, Int, Int);
static void        decStatus(decNumber *, uInt, decContext *);
static void        decStatus(decNumber *, uInt, decContext *);
static void        decToString(const decNumber *, char[], Flag);
static void        decToString(const decNumber *, char[], Flag);
static decNumber * decTrim(decNumber *, decContext *, Flag, Int *);
static decNumber * decTrim(decNumber *, decContext *, Flag, Int *);
static Int         decUnitAddSub(const Unit *, Int, const Unit *, Int, Int,
static Int         decUnitAddSub(const Unit *, Int, const Unit *, Int, Int,
                              Unit *, Int);
                              Unit *, Int);
static Int         decUnitCompare(const Unit *, Int, const Unit *, Int, Int);
static Int         decUnitCompare(const Unit *, Int, const Unit *, Int, Int);
 
 
#if !DECSUBSET
#if !DECSUBSET
/* decFinish == decFinalize when no subset arithmetic needed */
/* decFinish == decFinalize when no subset arithmetic needed */
#define decFinish(a,b,c,d) decFinalize(a,b,c,d)
#define decFinish(a,b,c,d) decFinalize(a,b,c,d)
#else
#else
static void        decFinish(decNumber *, decContext *, Int *, uInt *);
static void        decFinish(decNumber *, decContext *, Int *, uInt *);
static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *);
static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *);
#endif
#endif
 
 
/* Local macros */
/* Local macros */
/* masked special-values bits */
/* masked special-values bits */
#define SPECIALARG  (rhs->bits & DECSPECIAL)
#define SPECIALARG  (rhs->bits & DECSPECIAL)
#define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL)
#define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL)
 
 
/* Diagnostic macros, etc. */
/* Diagnostic macros, etc. */
#if DECALLOC
#if DECALLOC
/* Handle malloc/free accounting.  If enabled, our accountable routines */
/* Handle malloc/free accounting.  If enabled, our accountable routines */
/* are used; otherwise the code just goes straight to the system malloc */
/* are used; otherwise the code just goes straight to the system malloc */
/* and free routines. */
/* and free routines. */
#define malloc(a) decMalloc(a)
#define malloc(a) decMalloc(a)
#define free(a) decFree(a)
#define free(a) decFree(a)
#define DECFENCE 0x5a              /* corruption detector */
#define DECFENCE 0x5a              /* corruption detector */
/* 'Our' malloc and free: */
/* 'Our' malloc and free: */
static void *decMalloc(size_t);
static void *decMalloc(size_t);
static void  decFree(void *);
static void  decFree(void *);
uInt decAllocBytes=0;               /* count of bytes allocated */
uInt decAllocBytes=0;               /* count of bytes allocated */
/* Note that DECALLOC code only checks for storage buffer overflow. */
/* Note that DECALLOC code only checks for storage buffer overflow. */
/* To check for memory leaks, the decAllocBytes variable must be */
/* To check for memory leaks, the decAllocBytes variable must be */
/* checked to be 0 at appropriate times (e.g., after the test */
/* checked to be 0 at appropriate times (e.g., after the test */
/* harness completes a set of tests).  This checking may be unreliable */
/* harness completes a set of tests).  This checking may be unreliable */
/* if the testing is done in a multi-thread environment. */
/* if the testing is done in a multi-thread environment. */
#endif
#endif
 
 
#if DECCHECK
#if DECCHECK
/* Optional checking routines.  Enabling these means that decNumber */
/* Optional checking routines.  Enabling these means that decNumber */
/* and decContext operands to operator routines are checked for */
/* and decContext operands to operator routines are checked for */
/* correctness.  This roughly doubles the execution time of the */
/* correctness.  This roughly doubles the execution time of the */
/* fastest routines (and adds 600+ bytes), so should not normally be */
/* fastest routines (and adds 600+ bytes), so should not normally be */
/* used in 'production'. */
/* used in 'production'. */
/* decCheckInexact is used to check that inexact results have a full */
/* decCheckInexact is used to check that inexact results have a full */
/* complement of digits (where appropriate -- this is not the case */
/* complement of digits (where appropriate -- this is not the case */
/* for Quantize, for example) */
/* for Quantize, for example) */
#define DECUNRESU ((decNumber *)(void *)0xffffffff)
#define DECUNRESU ((decNumber *)(void *)0xffffffff)
#define DECUNUSED ((const decNumber *)(void *)0xffffffff)
#define DECUNUSED ((const decNumber *)(void *)0xffffffff)
#define DECUNCONT ((decContext *)(void *)(0xffffffff))
#define DECUNCONT ((decContext *)(void *)(0xffffffff))
static Flag decCheckOperands(decNumber *, const decNumber *,
static Flag decCheckOperands(decNumber *, const decNumber *,
                             const decNumber *, decContext *);
                             const decNumber *, decContext *);
static Flag decCheckNumber(const decNumber *);
static Flag decCheckNumber(const decNumber *);
static void decCheckInexact(const decNumber *, decContext *);
static void decCheckInexact(const decNumber *, decContext *);
#endif
#endif
 
 
#if DECTRACE || DECCHECK
#if DECTRACE || DECCHECK
/* Optional trace/debugging routines (may or may not be used) */
/* Optional trace/debugging routines (may or may not be used) */
void decNumberShow(const decNumber *);  /* displays the components of a number */
void decNumberShow(const decNumber *);  /* displays the components of a number */
static void decDumpAr(char, const Unit *, Int);
static void decDumpAr(char, const Unit *, Int);
#endif
#endif
 
 
/* ================================================================== */
/* ================================================================== */
/* Conversions                                                        */
/* Conversions                                                        */
/* ================================================================== */
/* ================================================================== */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* from-int32 -- conversion from Int or uInt                          */
/* from-int32 -- conversion from Int or uInt                          */
/*                                                                    */
/*                                                                    */
/*  dn is the decNumber to receive the integer                        */
/*  dn is the decNumber to receive the integer                        */
/*  in or uin is the integer to be converted                          */
/*  in or uin is the integer to be converted                          */
/*  returns dn                                                        */
/*  returns dn                                                        */
/*                                                                    */
/*                                                                    */
/* No error is possible.                                              */
/* No error is possible.                                              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberFromInt32(decNumber *dn, Int in) {
decNumber * decNumberFromInt32(decNumber *dn, Int in) {
  uInt unsig;
  uInt unsig;
  if (in>=0) unsig=in;
  if (in>=0) unsig=in;
   else {                               /* negative (possibly BADINT) */
   else {                               /* negative (possibly BADINT) */
    if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */
    if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */
     else unsig=-in;                    /* invert */
     else unsig=-in;                    /* invert */
    }
    }
  /* in is now positive */
  /* in is now positive */
  decNumberFromUInt32(dn, unsig);
  decNumberFromUInt32(dn, unsig);
  if (in<0) dn->bits=DECNEG;             /* sign needed */
  if (in<0) dn->bits=DECNEG;             /* sign needed */
  return dn;
  return dn;
  } /* decNumberFromInt32 */
  } /* decNumberFromInt32 */
 
 
decNumber * decNumberFromUInt32(decNumber *dn, uInt uin) {
decNumber * decNumberFromUInt32(decNumber *dn, uInt uin) {
  Unit *up;                             /* work pointer */
  Unit *up;                             /* work pointer */
  decNumberZero(dn);                    /* clean */
  decNumberZero(dn);                    /* clean */
  if (uin==0) return dn;         /* [or decGetDigits bad call] */
  if (uin==0) return dn;         /* [or decGetDigits bad call] */
  for (up=dn->lsu; uin>0; up++) {
  for (up=dn->lsu; uin>0; up++) {
    *up=(Unit)(uin%(DECDPUNMAX+1));
    *up=(Unit)(uin%(DECDPUNMAX+1));
    uin=uin/(DECDPUNMAX+1);
    uin=uin/(DECDPUNMAX+1);
    }
    }
  dn->digits=decGetDigits(dn->lsu, up-dn->lsu);
  dn->digits=decGetDigits(dn->lsu, up-dn->lsu);
  return dn;
  return dn;
  } /* decNumberFromUInt32 */
  } /* decNumberFromUInt32 */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* to-int32 -- conversion to Int or uInt                              */
/* to-int32 -- conversion to Int or uInt                              */
/*                                                                    */
/*                                                                    */
/*  dn is the decNumber to convert                                    */
/*  dn is the decNumber to convert                                    */
/*  set is the context for reporting errors                           */
/*  set is the context for reporting errors                           */
/*  returns the converted decNumber, or 0 if Invalid is set           */
/*  returns the converted decNumber, or 0 if Invalid is set           */
/*                                                                    */
/*                                                                    */
/* Invalid is set if the decNumber does not have exponent==0 or if    */
/* Invalid is set if the decNumber does not have exponent==0 or if    */
/* it is a NaN, Infinite, or out-of-range.                            */
/* it is a NaN, Infinite, or out-of-range.                            */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
Int decNumberToInt32(const decNumber *dn, decContext *set) {
Int decNumberToInt32(const decNumber *dn, decContext *set) {
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
  #endif
  #endif
 
 
  /* special or too many digits, or bad exponent */
  /* special or too many digits, or bad exponent */
  if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */
  if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */
   else { /* is a finite integer with 10 or fewer digits */
   else { /* is a finite integer with 10 or fewer digits */
    Int d;                         /* work */
    Int d;                         /* work */
    const Unit *up;                /* .. */
    const Unit *up;                /* .. */
    uInt hi=0, lo;                  /* .. */
    uInt hi=0, lo;                  /* .. */
    up=dn->lsu;                    /* -> lsu */
    up=dn->lsu;                    /* -> lsu */
    lo=*up;                        /* get 1 to 9 digits */
    lo=*up;                        /* get 1 to 9 digits */
    #if DECDPUN>1                  /* split to higher */
    #if DECDPUN>1                  /* split to higher */
      hi=lo/10;
      hi=lo/10;
      lo=lo%10;
      lo=lo%10;
    #endif
    #endif
    up++;
    up++;
    /* collect remaining Units, if any, into hi */
    /* collect remaining Units, if any, into hi */
    for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
    for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
    /* now low has the lsd, hi the remainder */
    /* now low has the lsd, hi the remainder */
    if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */
    if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */
      /* most-negative is a reprieve */
      /* most-negative is a reprieve */
      if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000;
      if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000;
      /* bad -- drop through */
      /* bad -- drop through */
      }
      }
     else { /* in-range always */
     else { /* in-range always */
      Int i=X10(hi)+lo;
      Int i=X10(hi)+lo;
      if (dn->bits&DECNEG) return -i;
      if (dn->bits&DECNEG) return -i;
      return i;
      return i;
      }
      }
    } /* integer */
    } /* integer */
  decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
  decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
  return 0;
  return 0;
  } /* decNumberToInt32 */
  } /* decNumberToInt32 */
 
 
uInt decNumberToUInt32(const decNumber *dn, decContext *set) {
uInt decNumberToUInt32(const decNumber *dn, decContext *set) {
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
  #endif
  #endif
  /* special or too many digits, or bad exponent, or negative (<0) */
  /* special or too many digits, or bad exponent, or negative (<0) */
  if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0
  if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0
    || (dn->bits&DECNEG && !ISZERO(dn)));                   /* bad */
    || (dn->bits&DECNEG && !ISZERO(dn)));                   /* bad */
   else { /* is a finite integer with 10 or fewer digits */
   else { /* is a finite integer with 10 or fewer digits */
    Int d;                         /* work */
    Int d;                         /* work */
    const Unit *up;                /* .. */
    const Unit *up;                /* .. */
    uInt hi=0, lo;                  /* .. */
    uInt hi=0, lo;                  /* .. */
    up=dn->lsu;                    /* -> lsu */
    up=dn->lsu;                    /* -> lsu */
    lo=*up;                        /* get 1 to 9 digits */
    lo=*up;                        /* get 1 to 9 digits */
    #if DECDPUN>1                  /* split to higher */
    #if DECDPUN>1                  /* split to higher */
      hi=lo/10;
      hi=lo/10;
      lo=lo%10;
      lo=lo%10;
    #endif
    #endif
    up++;
    up++;
    /* collect remaining Units, if any, into hi */
    /* collect remaining Units, if any, into hi */
    for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
    for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
 
 
    /* now low has the lsd, hi the remainder */
    /* now low has the lsd, hi the remainder */
    if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */
    if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */
     else return X10(hi)+lo;
     else return X10(hi)+lo;
    } /* integer */
    } /* integer */
  decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
  decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
  return 0;
  return 0;
  } /* decNumberToUInt32 */
  } /* decNumberToUInt32 */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* to-scientific-string -- conversion to numeric string               */
/* to-scientific-string -- conversion to numeric string               */
/* to-engineering-string -- conversion to numeric string              */
/* to-engineering-string -- conversion to numeric string              */
/*                                                                    */
/*                                                                    */
/*   decNumberToString(dn, string);                                   */
/*   decNumberToString(dn, string);                                   */
/*   decNumberToEngString(dn, string);                                */
/*   decNumberToEngString(dn, string);                                */
/*                                                                    */
/*                                                                    */
/*  dn is the decNumber to convert                                    */
/*  dn is the decNumber to convert                                    */
/*  string is the string where the result will be laid out            */
/*  string is the string where the result will be laid out            */
/*                                                                    */
/*                                                                    */
/*  string must be at least dn->digits+14 characters long             */
/*  string must be at least dn->digits+14 characters long             */
/*                                                                    */
/*                                                                    */
/*  No error is possible, and no status can be set.                   */
/*  No error is possible, and no status can be set.                   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
char * decNumberToString(const decNumber *dn, char *string){
char * decNumberToString(const decNumber *dn, char *string){
  decToString(dn, string, 0);
  decToString(dn, string, 0);
  return string;
  return string;
  } /* DecNumberToString */
  } /* DecNumberToString */
 
 
char * decNumberToEngString(const decNumber *dn, char *string){
char * decNumberToEngString(const decNumber *dn, char *string){
  decToString(dn, string, 1);
  decToString(dn, string, 1);
  return string;
  return string;
  } /* DecNumberToEngString */
  } /* DecNumberToEngString */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* to-number -- conversion from numeric string                        */
/* to-number -- conversion from numeric string                        */
/*                                                                    */
/*                                                                    */
/* decNumberFromString -- convert string to decNumber                 */
/* decNumberFromString -- convert string to decNumber                 */
/*   dn        -- the number structure to fill                        */
/*   dn        -- the number structure to fill                        */
/*   chars[]   -- the string to convert ('\0' terminated)             */
/*   chars[]   -- the string to convert ('\0' terminated)             */
/*   set       -- the context used for processing any error,          */
/*   set       -- the context used for processing any error,          */
/*                determining the maximum precision available         */
/*                determining the maximum precision available         */
/*                (set.digits), determining the maximum and minimum   */
/*                (set.digits), determining the maximum and minimum   */
/*                exponent (set.emax and set.emin), determining if    */
/*                exponent (set.emax and set.emin), determining if    */
/*                extended values are allowed, and checking the       */
/*                extended values are allowed, and checking the       */
/*                rounding mode if overflow occurs or rounding is     */
/*                rounding mode if overflow occurs or rounding is     */
/*                needed.                                             */
/*                needed.                                             */
/*                                                                    */
/*                                                                    */
/* The length of the coefficient and the size of the exponent are     */
/* The length of the coefficient and the size of the exponent are     */
/* checked by this routine, so the correct error (Underflow or        */
/* checked by this routine, so the correct error (Underflow or        */
/* Overflow) can be reported or rounding applied, as necessary.       */
/* Overflow) can be reported or rounding applied, as necessary.       */
/*                                                                    */
/*                                                                    */
/* If bad syntax is detected, the result will be a quiet NaN.         */
/* If bad syntax is detected, the result will be a quiet NaN.         */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberFromString(decNumber *dn, const char chars[],
decNumber * decNumberFromString(decNumber *dn, const char chars[],
                                decContext *set) {
                                decContext *set) {
  Int   exponent=0;                 /* working exponent [assume 0] */
  Int   exponent=0;                 /* working exponent [assume 0] */
  uByte bits=0;                     /* working flags [assume +ve] */
  uByte bits=0;                     /* working flags [assume +ve] */
  Unit  *res;                      /* where result will be built */
  Unit  *res;                      /* where result will be built */
  Unit  resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */
  Unit  resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */
                                   /* [+9 allows for ln() constants] */
                                   /* [+9 allows for ln() constants] */
  Unit  *allocres=NULL;            /* -> allocated result, iff allocated */
  Unit  *allocres=NULL;            /* -> allocated result, iff allocated */
  Int   d=0;                        /* count of digits found in decimal part */
  Int   d=0;                        /* count of digits found in decimal part */
  const char *dotchar=NULL;        /* where dot was found */
  const char *dotchar=NULL;        /* where dot was found */
  const char *cfirst=chars;        /* -> first character of decimal part */
  const char *cfirst=chars;        /* -> first character of decimal part */
  const char *last=NULL;           /* -> last digit of decimal part */
  const char *last=NULL;           /* -> last digit of decimal part */
  const char *c;                   /* work */
  const char *c;                   /* work */
  Unit  *up;                       /* .. */
  Unit  *up;                       /* .. */
  #if DECDPUN>1
  #if DECDPUN>1
  Int   cut, out;                  /* .. */
  Int   cut, out;                  /* .. */
  #endif
  #endif
  Int   residue;                   /* rounding residue */
  Int   residue;                   /* rounding residue */
  uInt  status=0;                   /* error code */
  uInt  status=0;                   /* error code */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set))
  if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set))
    return decNumberZero(dn);
    return decNumberZero(dn);
  #endif
  #endif
 
 
  do {                             /* status & malloc protection */
  do {                             /* status & malloc protection */
    for (c=chars;; c++) {          /* -> input character */
    for (c=chars;; c++) {          /* -> input character */
      if (*c>='0' && *c<='9') {    /* test for Arabic digit */
      if (*c>='0' && *c<='9') {    /* test for Arabic digit */
        last=c;
        last=c;
        d++;                       /* count of real digits */
        d++;                       /* count of real digits */
        continue;                  /* still in decimal part */
        continue;                  /* still in decimal part */
        }
        }
      if (*c=='.' && dotchar==NULL) { /* first '.' */
      if (*c=='.' && dotchar==NULL) { /* first '.' */
        dotchar=c;                 /* record offset into decimal part */
        dotchar=c;                 /* record offset into decimal part */
        if (c==cfirst) cfirst++;   /* first digit must follow */
        if (c==cfirst) cfirst++;   /* first digit must follow */
        continue;}
        continue;}
      if (c==chars) {              /* first in string... */
      if (c==chars) {              /* first in string... */
        if (*c=='-') {             /* valid - sign */
        if (*c=='-') {             /* valid - sign */
          cfirst++;
          cfirst++;
          bits=DECNEG;
          bits=DECNEG;
          continue;}
          continue;}
        if (*c=='+') {             /* valid + sign */
        if (*c=='+') {             /* valid + sign */
          cfirst++;
          cfirst++;
          continue;}
          continue;}
        }
        }
      /* *c is not a digit, or a valid +, -, or '.' */
      /* *c is not a digit, or a valid +, -, or '.' */
      break;
      break;
      } /* c */
      } /* c */
 
 
    if (last==NULL) {              /* no digits yet */
    if (last==NULL) {              /* no digits yet */
      status=DEC_Conversion_syntax;/* assume the worst */
      status=DEC_Conversion_syntax;/* assume the worst */
      if (*c=='\0') break;         /* and no more to come... */
      if (*c=='\0') break;         /* and no more to come... */
      #if DECSUBSET
      #if DECSUBSET
      /* if subset then infinities and NaNs are not allowed */
      /* if subset then infinities and NaNs are not allowed */
      if (!set->extended) break;   /* hopeless */
      if (!set->extended) break;   /* hopeless */
      #endif
      #endif
      /* Infinities and NaNs are possible, here */
      /* Infinities and NaNs are possible, here */
      if (dotchar!=NULL) break;    /* .. unless had a dot */
      if (dotchar!=NULL) break;    /* .. unless had a dot */
      decNumberZero(dn);           /* be optimistic */
      decNumberZero(dn);           /* be optimistic */
      if (decBiStr(c, "infinity", "INFINITY")
      if (decBiStr(c, "infinity", "INFINITY")
       || decBiStr(c, "inf", "INF")) {
       || decBiStr(c, "inf", "INF")) {
        dn->bits=bits | DECINF;
        dn->bits=bits | DECINF;
        status=0;                   /* is OK */
        status=0;                   /* is OK */
        break; /* all done */
        break; /* all done */
        }
        }
      /* a NaN expected */
      /* a NaN expected */
      /* 2003.09.10 NaNs are now permitted to have a sign */
      /* 2003.09.10 NaNs are now permitted to have a sign */
      dn->bits=bits | DECNAN;      /* assume simple NaN */
      dn->bits=bits | DECNAN;      /* assume simple NaN */
      if (*c=='s' || *c=='S') {    /* looks like an sNaN */
      if (*c=='s' || *c=='S') {    /* looks like an sNaN */
        c++;
        c++;
        dn->bits=bits | DECSNAN;
        dn->bits=bits | DECSNAN;
        }
        }
      if (*c!='n' && *c!='N') break;    /* check caseless "NaN" */
      if (*c!='n' && *c!='N') break;    /* check caseless "NaN" */
      c++;
      c++;
      if (*c!='a' && *c!='A') break;    /* .. */
      if (*c!='a' && *c!='A') break;    /* .. */
      c++;
      c++;
      if (*c!='n' && *c!='N') break;    /* .. */
      if (*c!='n' && *c!='N') break;    /* .. */
      c++;
      c++;
      /* now either nothing, or nnnn payload, expected */
      /* now either nothing, or nnnn payload, expected */
      /* -> start of integer and skip leading 0s [including plain 0] */
      /* -> start of integer and skip leading 0s [including plain 0] */
      for (cfirst=c; *cfirst=='0';) cfirst++;
      for (cfirst=c; *cfirst=='0';) cfirst++;
      if (*cfirst=='\0') {         /* "NaN" or "sNaN", maybe with all 0s */
      if (*cfirst=='\0') {         /* "NaN" or "sNaN", maybe with all 0s */
        status=0;                   /* it's good */
        status=0;                   /* it's good */
        break;                     /* .. */
        break;                     /* .. */
        }
        }
      /* something other than 0s; setup last and d as usual [no dots] */
      /* something other than 0s; setup last and d as usual [no dots] */
      for (c=cfirst;; c++, d++) {
      for (c=cfirst;; c++, d++) {
        if (*c<'0' || *c>'9') break; /* test for Arabic digit */
        if (*c<'0' || *c>'9') break; /* test for Arabic digit */
        last=c;
        last=c;
        }
        }
      if (*c!='\0') break;         /* not all digits */
      if (*c!='\0') break;         /* not all digits */
      if (d>set->digits-1) {
      if (d>set->digits-1) {
        /* [NB: payload in a decNumber can be full length unless */
        /* [NB: payload in a decNumber can be full length unless */
        /* clamped, in which case can only be digits-1] */
        /* clamped, in which case can only be digits-1] */
        if (set->clamp) break;
        if (set->clamp) break;
        if (d>set->digits) break;
        if (d>set->digits) break;
        } /* too many digits? */
        } /* too many digits? */
      /* good; drop through to convert the integer to coefficient */
      /* good; drop through to convert the integer to coefficient */
      status=0;                     /* syntax is OK */
      status=0;                     /* syntax is OK */
      bits=dn->bits;               /* for copy-back */
      bits=dn->bits;               /* for copy-back */
      } /* last==NULL */
      } /* last==NULL */
 
 
     else if (*c!='\0') {          /* more to process... */
     else if (*c!='\0') {          /* more to process... */
      /* had some digits; exponent is only valid sequence now */
      /* had some digits; exponent is only valid sequence now */
      Flag nege;                   /* 1=negative exponent */
      Flag nege;                   /* 1=negative exponent */
      const char *firstexp;        /* -> first significant exponent digit */
      const char *firstexp;        /* -> first significant exponent digit */
      status=DEC_Conversion_syntax;/* assume the worst */
      status=DEC_Conversion_syntax;/* assume the worst */
      if (*c!='e' && *c!='E') break;
      if (*c!='e' && *c!='E') break;
      /* Found 'e' or 'E' -- now process explicit exponent */
      /* Found 'e' or 'E' -- now process explicit exponent */
      /* 1998.07.11: sign no longer required */
      /* 1998.07.11: sign no longer required */
      nege=0;
      nege=0;
      c++;                         /* to (possible) sign */
      c++;                         /* to (possible) sign */
      if (*c=='-') {nege=1; c++;}
      if (*c=='-') {nege=1; c++;}
       else if (*c=='+') c++;
       else if (*c=='+') c++;
      if (*c=='\0') break;
      if (*c=='\0') break;
 
 
      for (; *c=='0' && *(c+1)!='\0';) c++;  /* strip insignificant zeros */
      for (; *c=='0' && *(c+1)!='\0';) c++;  /* strip insignificant zeros */
      firstexp=c;                            /* save exponent digit place */
      firstexp=c;                            /* save exponent digit place */
      for (; ;c++) {
      for (; ;c++) {
        if (*c<'0' || *c>'9') break;         /* not a digit */
        if (*c<'0' || *c>'9') break;         /* not a digit */
        exponent=X10(exponent)+(Int)*c-(Int)'0';
        exponent=X10(exponent)+(Int)*c-(Int)'0';
        } /* c */
        } /* c */
      /* if not now on a '\0', *c must not be a digit */
      /* if not now on a '\0', *c must not be a digit */
      if (*c!='\0') break;
      if (*c!='\0') break;
 
 
      /* (this next test must be after the syntax checks) */
      /* (this next test must be after the syntax checks) */
      /* if it was too long the exponent may have wrapped, so check */
      /* if it was too long the exponent may have wrapped, so check */
      /* carefully and set it to a certain overflow if wrap possible */
      /* carefully and set it to a certain overflow if wrap possible */
      if (c>=firstexp+9+1) {
      if (c>=firstexp+9+1) {
        if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2;
        if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2;
        /* [up to 1999999999 is OK, for example 1E-1000000998] */
        /* [up to 1999999999 is OK, for example 1E-1000000998] */
        }
        }
      if (nege) exponent=-exponent;     /* was negative */
      if (nege) exponent=-exponent;     /* was negative */
      status=0;                          /* is OK */
      status=0;                          /* is OK */
      } /* stuff after digits */
      } /* stuff after digits */
 
 
    /* Here when whole string has been inspected; syntax is good */
    /* Here when whole string has been inspected; syntax is good */
    /* cfirst->first digit (never dot), last->last digit (ditto) */
    /* cfirst->first digit (never dot), last->last digit (ditto) */
 
 
    /* strip leading zeros/dot [leave final 0 if all 0's] */
    /* strip leading zeros/dot [leave final 0 if all 0's] */
    if (*cfirst=='0') {                 /* [cfirst has stepped over .] */
    if (*cfirst=='0') {                 /* [cfirst has stepped over .] */
      for (c=cfirst; c<last; c++, cfirst++) {
      for (c=cfirst; c<last; c++, cfirst++) {
        if (*c=='.') continue;          /* ignore dots */
        if (*c=='.') continue;          /* ignore dots */
        if (*c!='0') break;             /* non-zero found */
        if (*c!='0') break;             /* non-zero found */
        d--;                            /* 0 stripped */
        d--;                            /* 0 stripped */
        } /* c */
        } /* c */
      #if DECSUBSET
      #if DECSUBSET
      /* make a rapid exit for easy zeros if !extended */
      /* make a rapid exit for easy zeros if !extended */
      if (*cfirst=='0' && !set->extended) {
      if (*cfirst=='0' && !set->extended) {
        decNumberZero(dn);              /* clean result */
        decNumberZero(dn);              /* clean result */
        break;                          /* [could be return] */
        break;                          /* [could be return] */
        }
        }
      #endif
      #endif
      } /* at least one leading 0 */
      } /* at least one leading 0 */
 
 
    /* Handle decimal point... */
    /* Handle decimal point... */
    if (dotchar!=NULL && dotchar<last)  /* non-trailing '.' found? */
    if (dotchar!=NULL && dotchar<last)  /* non-trailing '.' found? */
      exponent-=(last-dotchar);         /* adjust exponent */
      exponent-=(last-dotchar);         /* adjust exponent */
    /* [we can now ignore the .] */
    /* [we can now ignore the .] */
 
 
    /* OK, the digits string is good.  Assemble in the decNumber, or in */
    /* OK, the digits string is good.  Assemble in the decNumber, or in */
    /* a temporary units array if rounding is needed */
    /* a temporary units array if rounding is needed */
    if (d<=set->digits) res=dn->lsu;    /* fits into supplied decNumber */
    if (d<=set->digits) res=dn->lsu;    /* fits into supplied decNumber */
     else {                             /* rounding needed */
     else {                             /* rounding needed */
      Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */
      Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */
      res=resbuff;                      /* assume use local buffer */
      res=resbuff;                      /* assume use local buffer */
      if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */
      if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */
        allocres=(Unit *)malloc(needbytes);
        allocres=(Unit *)malloc(needbytes);
        if (allocres==NULL) {status|=DEC_Insufficient_storage; break;}
        if (allocres==NULL) {status|=DEC_Insufficient_storage; break;}
        res=allocres;
        res=allocres;
        }
        }
      }
      }
    /* res now -> number lsu, buffer, or allocated storage for Unit array */
    /* res now -> number lsu, buffer, or allocated storage for Unit array */
 
 
    /* Place the coefficient into the selected Unit array */
    /* Place the coefficient into the selected Unit array */
    /* [this is often 70% of the cost of this function when DECDPUN>1] */
    /* [this is often 70% of the cost of this function when DECDPUN>1] */
    #if DECDPUN>1
    #if DECDPUN>1
    out=0;                          /* accumulator */
    out=0;                          /* accumulator */
    up=res+D2U(d)-1;               /* -> msu */
    up=res+D2U(d)-1;               /* -> msu */
    cut=d-(up-res)*DECDPUN;        /* digits in top unit */
    cut=d-(up-res)*DECDPUN;        /* digits in top unit */
    for (c=cfirst;; c++) {         /* along the digits */
    for (c=cfirst;; c++) {         /* along the digits */
      if (*c=='.') continue;       /* ignore '.' [don't decrement cut] */
      if (*c=='.') continue;       /* ignore '.' [don't decrement cut] */
      out=X10(out)+(Int)*c-(Int)'0';
      out=X10(out)+(Int)*c-(Int)'0';
      if (c==last) break;          /* done [never get to trailing '.'] */
      if (c==last) break;          /* done [never get to trailing '.'] */
      cut--;
      cut--;
      if (cut>0) continue;          /* more for this unit */
      if (cut>0) continue;          /* more for this unit */
      *up=(Unit)out;               /* write unit */
      *up=(Unit)out;               /* write unit */
      up--;                        /* prepare for unit below.. */
      up--;                        /* prepare for unit below.. */
      cut=DECDPUN;                 /* .. */
      cut=DECDPUN;                 /* .. */
      out=0;                        /* .. */
      out=0;                        /* .. */
      } /* c */
      } /* c */
    *up=(Unit)out;                 /* write lsu */
    *up=(Unit)out;                 /* write lsu */
 
 
    #else
    #else
    /* DECDPUN==1 */
    /* DECDPUN==1 */
    up=res;                        /* -> lsu */
    up=res;                        /* -> lsu */
    for (c=last; c>=cfirst; c--) { /* over each character, from least */
    for (c=last; c>=cfirst; c--) { /* over each character, from least */
      if (*c=='.') continue;       /* ignore . [don't step up] */
      if (*c=='.') continue;       /* ignore . [don't step up] */
      *up=(Unit)((Int)*c-(Int)'0');
      *up=(Unit)((Int)*c-(Int)'0');
      up++;
      up++;
      } /* c */
      } /* c */
    #endif
    #endif
 
 
    dn->bits=bits;
    dn->bits=bits;
    dn->exponent=exponent;
    dn->exponent=exponent;
    dn->digits=d;
    dn->digits=d;
 
 
    /* if not in number (too long) shorten into the number */
    /* if not in number (too long) shorten into the number */
    if (d>set->digits) {
    if (d>set->digits) {
      residue=0;
      residue=0;
      decSetCoeff(dn, set, res, d, &residue, &status);
      decSetCoeff(dn, set, res, d, &residue, &status);
      /* always check for overflow or subnormal and round as needed */
      /* always check for overflow or subnormal and round as needed */
      decFinalize(dn, set, &residue, &status);
      decFinalize(dn, set, &residue, &status);
      }
      }
     else { /* no rounding, but may still have overflow or subnormal */
     else { /* no rounding, but may still have overflow or subnormal */
      /* [these tests are just for performance; finalize repeats them] */
      /* [these tests are just for performance; finalize repeats them] */
      if ((dn->exponent-1<set->emin-dn->digits)
      if ((dn->exponent-1<set->emin-dn->digits)
       || (dn->exponent-1>set->emax-set->digits)) {
       || (dn->exponent-1>set->emax-set->digits)) {
        residue=0;
        residue=0;
        decFinalize(dn, set, &residue, &status);
        decFinalize(dn, set, &residue, &status);
        }
        }
      }
      }
    /* decNumberShow(dn); */
    /* decNumberShow(dn); */
    } while(0);                          /* [for break] */
    } while(0);                          /* [for break] */
 
 
  if (allocres!=NULL) free(allocres);   /* drop any storage used */
  if (allocres!=NULL) free(allocres);   /* drop any storage used */
  if (status!=0) decStatus(dn, status, set);
  if (status!=0) decStatus(dn, status, set);
  return dn;
  return dn;
  } /* decNumberFromString */
  } /* decNumberFromString */
 
 
/* ================================================================== */
/* ================================================================== */
/* Operators                                                          */
/* Operators                                                          */
/* ================================================================== */
/* ================================================================== */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberAbs -- absolute value operator                            */
/* decNumberAbs -- absolute value operator                            */
/*                                                                    */
/*                                                                    */
/*   This computes C = abs(A)                                         */
/*   This computes C = abs(A)                                         */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* See also decNumberCopyAbs for a quiet bitwise version of this.     */
/* See also decNumberCopyAbs for a quiet bitwise version of this.     */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This has the same effect as decNumberPlus unless A is negative,    */
/* This has the same effect as decNumberPlus unless A is negative,    */
/* in which case it has the same effect as decNumberMinus.            */
/* in which case it has the same effect as decNumberMinus.            */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberAbs(decNumber *res, const decNumber *rhs,
decNumber * decNumberAbs(decNumber *res, const decNumber *rhs,
                         decContext *set) {
                         decContext *set) {
  decNumber dzero;                      /* for 0 */
  decNumber dzero;                      /* for 0 */
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  decNumberZero(&dzero);                /* set 0 */
  decNumberZero(&dzero);                /* set 0 */
  dzero.exponent=rhs->exponent;         /* [no coefficient expansion] */
  dzero.exponent=rhs->exponent;         /* [no coefficient expansion] */
  decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status);
  decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberAbs */
  } /* decNumberAbs */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberAdd -- add two Numbers                                    */
/* decNumberAdd -- add two Numbers                                    */
/*                                                                    */
/*                                                                    */
/*   This computes C = A + B                                          */
/*   This computes C = A + B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This just calls the routine shared with Subtract                   */
/* This just calls the routine shared with Subtract                   */
decNumber * decNumberAdd(decNumber *res, const decNumber *lhs,
decNumber * decNumberAdd(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, decContext *set) {
                         const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decAddOp(res, lhs, rhs, set, 0, &status);
  decAddOp(res, lhs, rhs, set, 0, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberAdd */
  } /* decNumberAdd */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberAnd -- AND two Numbers, digitwise                         */
/* decNumberAnd -- AND two Numbers, digitwise                         */
/*                                                                    */
/*                                                                    */
/*   This computes C = A & B                                          */
/*   This computes C = A & B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X&X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X&X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context (used for result length and error report)     */
/*   set is the context (used for result length and error report)     */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Logical function restrictions apply (see above); a NaN is          */
/* Logical function restrictions apply (see above); a NaN is          */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberAnd(decNumber *res, const decNumber *lhs,
decNumber * decNumberAnd(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, decContext *set) {
                         const decNumber *rhs, decContext *set) {
  const Unit *ua, *ub;                  /* -> operands */
  const Unit *ua, *ub;                  /* -> operands */
  const Unit *msua, *msub;              /* -> operand msus */
  const Unit *msua, *msub;              /* -> operand msus */
  Unit *uc,  *msuc;                     /* -> result and its msu */
  Unit *uc,  *msuc;                     /* -> result and its msu */
  Int   msudigs;                        /* digits in res msu */
  Int   msudigs;                        /* digits in res msu */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
    decStatus(res, DEC_Invalid_operation, set);
    decStatus(res, DEC_Invalid_operation, set);
    return res;
    return res;
    }
    }
 
 
  /* operands are valid */
  /* operands are valid */
  ua=lhs->lsu;                          /* bottom-up */
  ua=lhs->lsu;                          /* bottom-up */
  ub=rhs->lsu;                          /* .. */
  ub=rhs->lsu;                          /* .. */
  uc=res->lsu;                          /* .. */
  uc=res->lsu;                          /* .. */
  msua=ua+D2U(lhs->digits)-1;           /* -> msu of lhs */
  msua=ua+D2U(lhs->digits)-1;           /* -> msu of lhs */
  msub=ub+D2U(rhs->digits)-1;           /* -> msu of rhs */
  msub=ub+D2U(rhs->digits)-1;           /* -> msu of rhs */
  msuc=uc+D2U(set->digits)-1;           /* -> msu of result */
  msuc=uc+D2U(set->digits)-1;           /* -> msu of result */
  msudigs=MSUDIGITS(set->digits);       /* [faster than remainder] */
  msudigs=MSUDIGITS(set->digits);       /* [faster than remainder] */
  for (; uc<=msuc; ua++, ub++, uc++) {  /* Unit loop */
  for (; uc<=msuc; ua++, ub++, uc++) {  /* Unit loop */
    Unit a, b;                          /* extract units */
    Unit a, b;                          /* extract units */
    if (ua>msua) a=0;
    if (ua>msua) a=0;
     else a=*ua;
     else a=*ua;
    if (ub>msub) b=0;
    if (ub>msub) b=0;
     else b=*ub;
     else b=*ub;
    *uc=0;                               /* can now write back */
    *uc=0;                               /* can now write back */
    if (a|b) {                          /* maybe 1 bits to examine */
    if (a|b) {                          /* maybe 1 bits to examine */
      Int i, j;
      Int i, j;
      *uc=0;                             /* can now write back */
      *uc=0;                             /* can now write back */
      /* This loop could be unrolled and/or use BIN2BCD tables */
      /* This loop could be unrolled and/or use BIN2BCD tables */
      for (i=0; i<DECDPUN; i++) {
      for (i=0; i<DECDPUN; i++) {
        if (a&b&1) *uc=*uc+(Unit)powers[i];  /* effect AND */
        if (a&b&1) *uc=*uc+(Unit)powers[i];  /* effect AND */
        j=a%10;
        j=a%10;
        a=a/10;
        a=a/10;
        j|=b%10;
        j|=b%10;
        b=b/10;
        b=b/10;
        if (j>1) {
        if (j>1) {
          decStatus(res, DEC_Invalid_operation, set);
          decStatus(res, DEC_Invalid_operation, set);
          return res;
          return res;
          }
          }
        if (uc==msuc && i==msudigs-1) break; /* just did final digit */
        if (uc==msuc && i==msudigs-1) break; /* just did final digit */
        } /* each digit */
        } /* each digit */
      } /* both OK */
      } /* both OK */
    } /* each unit */
    } /* each unit */
  /* [here uc-1 is the msu of the result] */
  /* [here uc-1 is the msu of the result] */
  res->digits=decGetDigits(res->lsu, uc-res->lsu);
  res->digits=decGetDigits(res->lsu, uc-res->lsu);
  res->exponent=0;                       /* integer */
  res->exponent=0;                       /* integer */
  res->bits=0;                           /* sign=0 */
  res->bits=0;                           /* sign=0 */
  return res;  /* [no status to set] */
  return res;  /* [no status to set] */
  } /* decNumberAnd */
  } /* decNumberAnd */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberCompare -- compare two Numbers                            */
/* decNumberCompare -- compare two Numbers                            */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ? B                                          */
/*   This computes C = A ? B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for one digit (or NaN).                          */
/* C must have space for one digit (or NaN).                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberCompare(decNumber *res, const decNumber *lhs,
decNumber * decNumberCompare(decNumber *res, const decNumber *lhs,
                             const decNumber *rhs, decContext *set) {
                             const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decCompareOp(res, lhs, rhs, set, COMPARE, &status);
  decCompareOp(res, lhs, rhs, set, COMPARE, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberCompare */
  } /* decNumberCompare */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberCompareSignal -- compare, signalling on all NaNs          */
/* decNumberCompareSignal -- compare, signalling on all NaNs          */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ? B                                          */
/*   This computes C = A ? B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for one digit (or NaN).                          */
/* C must have space for one digit (or NaN).                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberCompareSignal(decNumber *res, const decNumber *lhs,
decNumber * decNumberCompareSignal(decNumber *res, const decNumber *lhs,
                                   const decNumber *rhs, decContext *set) {
                                   const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decCompareOp(res, lhs, rhs, set, COMPSIG, &status);
  decCompareOp(res, lhs, rhs, set, COMPSIG, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberCompareSignal */
  } /* decNumberCompareSignal */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberCompareTotal -- compare two Numbers, using total ordering */
/* decNumberCompareTotal -- compare two Numbers, using total ordering */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ? B, under total ordering                    */
/*   This computes C = A ? B, under total ordering                    */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for one digit; the result will always be one of  */
/* C must have space for one digit; the result will always be one of  */
/* -1, 0, or 1.                                                       */
/* -1, 0, or 1.                                                       */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs,
decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs,
                                  const decNumber *rhs, decContext *set) {
                                  const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
  decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberCompareTotal */
  } /* decNumberCompareTotal */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberCompareTotalMag -- compare, total ordering of magnitudes  */
/* decNumberCompareTotalMag -- compare, total ordering of magnitudes  */
/*                                                                    */
/*                                                                    */
/*   This computes C = |A| ? |B|, under total ordering                */
/*   This computes C = |A| ? |B|, under total ordering                */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for one digit; the result will always be one of  */
/* C must have space for one digit; the result will always be one of  */
/* -1, 0, or 1.                                                       */
/* -1, 0, or 1.                                                       */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
decNumber * decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
                                     const decNumber *rhs, decContext *set) {
                                     const decNumber *rhs, decContext *set) {
  uInt status=0;            /* accumulator */
  uInt status=0;            /* accumulator */
  uInt needbytes;                  /* for space calculations */
  uInt needbytes;                  /* for space calculations */
  decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */
  decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber bufb[D2N(DECBUFFER+1)];
  decNumber bufb[D2N(DECBUFFER+1)];
  decNumber *allocbufb=NULL;       /* -> allocated bufb, iff allocated */
  decNumber *allocbufb=NULL;       /* -> allocated bufb, iff allocated */
  decNumber *a, *b;                /* temporary pointers */
  decNumber *a, *b;                /* temporary pointers */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                                  /* protect allocated storage */
  do {                                  /* protect allocated storage */
    /* if either is negative, take a copy and absolute */
    /* if either is negative, take a copy and absolute */
    if (decNumberIsNegative(lhs)) {     /* lhs<0 */
    if (decNumberIsNegative(lhs)) {     /* lhs<0 */
      a=bufa;
      a=bufa;
      needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit);
      needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit);
      if (needbytes>sizeof(bufa)) {     /* need malloc space */
      if (needbytes>sizeof(bufa)) {     /* need malloc space */
        allocbufa=(decNumber *)malloc(needbytes);
        allocbufa=(decNumber *)malloc(needbytes);
        if (allocbufa==NULL) {          /* hopeless -- abandon */
        if (allocbufa==NULL) {          /* hopeless -- abandon */
          status|=DEC_Insufficient_storage;
          status|=DEC_Insufficient_storage;
          break;}
          break;}
        a=allocbufa;                    /* use the allocated space */
        a=allocbufa;                    /* use the allocated space */
        }
        }
      decNumberCopy(a, lhs);            /* copy content */
      decNumberCopy(a, lhs);            /* copy content */
      a->bits&=~DECNEG;                 /* .. and clear the sign */
      a->bits&=~DECNEG;                 /* .. and clear the sign */
      lhs=a;                            /* use copy from here on */
      lhs=a;                            /* use copy from here on */
      }
      }
    if (decNumberIsNegative(rhs)) {     /* rhs<0 */
    if (decNumberIsNegative(rhs)) {     /* rhs<0 */
      b=bufb;
      b=bufb;
      needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
      needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
      if (needbytes>sizeof(bufb)) {     /* need malloc space */
      if (needbytes>sizeof(bufb)) {     /* need malloc space */
        allocbufb=(decNumber *)malloc(needbytes);
        allocbufb=(decNumber *)malloc(needbytes);
        if (allocbufb==NULL) {          /* hopeless -- abandon */
        if (allocbufb==NULL) {          /* hopeless -- abandon */
          status|=DEC_Insufficient_storage;
          status|=DEC_Insufficient_storage;
          break;}
          break;}
        b=allocbufb;                    /* use the allocated space */
        b=allocbufb;                    /* use the allocated space */
        }
        }
      decNumberCopy(b, rhs);            /* copy content */
      decNumberCopy(b, rhs);            /* copy content */
      b->bits&=~DECNEG;                 /* .. and clear the sign */
      b->bits&=~DECNEG;                 /* .. and clear the sign */
      rhs=b;                            /* use copy from here on */
      rhs=b;                            /* use copy from here on */
      }
      }
    decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
    decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
  if (allocbufb!=NULL) free(allocbufb); /* .. */
  if (allocbufb!=NULL) free(allocbufb); /* .. */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberCompareTotalMag */
  } /* decNumberCompareTotalMag */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberDivide -- divide one number by another                    */
/* decNumberDivide -- divide one number by another                    */
/*                                                                    */
/*                                                                    */
/*   This computes C = A / B                                          */
/*   This computes C = A / B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X/X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X/X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberDivide(decNumber *res, const decNumber *lhs,
decNumber * decNumberDivide(decNumber *res, const decNumber *lhs,
                            const decNumber *rhs, decContext *set) {
                            const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decDivideOp(res, lhs, rhs, set, DIVIDE, &status);
  decDivideOp(res, lhs, rhs, set, DIVIDE, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberDivide */
  } /* decNumberDivide */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberDivideInteger -- divide and return integer quotient       */
/* decNumberDivideInteger -- divide and return integer quotient       */
/*                                                                    */
/*                                                                    */
/*   This computes C = A # B, where # is the integer divide operator  */
/*   This computes C = A # B, where # is the integer divide operator  */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X#X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X#X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs,
decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs,
                                   const decNumber *rhs, decContext *set) {
                                   const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status);
  decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberDivideInteger */
  } /* decNumberDivideInteger */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberExp -- exponentiation                                     */
/* decNumberExp -- exponentiation                                     */
/*                                                                    */
/*                                                                    */
/*   This computes C = exp(A)                                         */
/*   This computes C = exp(A)                                         */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context; note that rounding mode has no effect        */
/*   set is the context; note that rounding mode has no effect        */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/*                                                                    */
/*                                                                    */
/* Finite results will always be full precision and Inexact, except   */
/* Finite results will always be full precision and Inexact, except   */
/* when A is a zero or -Infinity (giving 1 or 0 respectively).        */
/* when A is a zero or -Infinity (giving 1 or 0 respectively).        */
/*                                                                    */
/*                                                                    */
/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* error in rare cases.                                               */
/* error in rare cases.                                               */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This is a wrapper for decExpOp which can handle the slightly wider */
/* This is a wrapper for decExpOp which can handle the slightly wider */
/* (double) range needed by Ln (which has to be able to calculate     */
/* (double) range needed by Ln (which has to be able to calculate     */
/* exp(-a) where a can be the tiniest number (Ntiny).                 */
/* exp(-a) where a can be the tiniest number (Ntiny).                 */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberExp(decNumber *res, const decNumber *rhs,
decNumber * decNumberExp(decNumber *res, const decNumber *rhs,
                         decContext *set) {
                         decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  #if DECSUBSET
  #if DECSUBSET
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  #endif
  #endif
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  /* Check restrictions; these restrictions ensure that if h=8 (see */
  /* Check restrictions; these restrictions ensure that if h=8 (see */
  /* decExpOp) then the result will either overflow or underflow to 0. */
  /* decExpOp) then the result will either overflow or underflow to 0. */
  /* Other math functions restrict the input range, too, for inverses. */
  /* Other math functions restrict the input range, too, for inverses. */
  /* If not violated then carry out the operation. */
  /* If not violated then carry out the operation. */
  if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
  if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operand and set lostDigits status, as needed */
      /* reduce operand and set lostDigits status, as needed */
      if (rhs->digits>set->digits) {
      if (rhs->digits>set->digits) {
        allocrhs=decRoundOperand(rhs, set, &status);
        allocrhs=decRoundOperand(rhs, set, &status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    decExpOp(res, rhs, set, &status);
    decExpOp(res, rhs, set, &status);
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs !=NULL) free(allocrhs);  /* drop any storage used */
  if (allocrhs !=NULL) free(allocrhs);  /* drop any storage used */
  #endif
  #endif
  /* apply significant status */
  /* apply significant status */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberExp */
  } /* decNumberExp */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberFMA -- fused multiply add                                 */
/* decNumberFMA -- fused multiply add                                 */
/*                                                                    */
/*                                                                    */
/*   This computes D = (A * B) + C with only one rounding             */
/*   This computes D = (A * B) + C with only one rounding             */
/*                                                                    */
/*                                                                    */
/*   res is D, the result.  D may be A or B or C (e.g., X=FMA(X,X,X)) */
/*   res is D, the result.  D may be A or B or C (e.g., X=FMA(X,X,X)) */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   fhs is C [far hand side]                                         */
/*   fhs is C [far hand side]                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberFMA(decNumber *res, const decNumber *lhs,
decNumber * decNumberFMA(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, const decNumber *fhs,
                         const decNumber *rhs, const decNumber *fhs,
                         decContext *set) {
                         decContext *set) {
  uInt status=0;            /* accumulator */
  uInt status=0;            /* accumulator */
  decContext dcmul;                /* context for the multiplication */
  decContext dcmul;                /* context for the multiplication */
  uInt needbytes;                  /* for space calculations */
  uInt needbytes;                  /* for space calculations */
  decNumber bufa[D2N(DECBUFFER*2+1)];
  decNumber bufa[D2N(DECBUFFER*2+1)];
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *acc;                  /* accumulator pointer */
  decNumber *acc;                  /* accumulator pointer */
  decNumber dzero;                 /* work */
  decNumber dzero;                 /* work */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, fhs, DECUNUSED, set)) return res;
  if (decCheckOperands(res, fhs, DECUNUSED, set)) return res;
  #endif
  #endif
 
 
  do {                                  /* protect allocated storage */
  do {                                  /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {               /* [undefined if subset] */
    if (!set->extended) {               /* [undefined if subset] */
      status|=DEC_Invalid_operation;
      status|=DEC_Invalid_operation;
      break;}
      break;}
    #endif
    #endif
    /* Check math restrictions [these ensure no overflow or underflow] */
    /* Check math restrictions [these ensure no overflow or underflow] */
    if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status))
    if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status))
     || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status))
     || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status))
     || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break;
     || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break;
    /* set up context for multiply */
    /* set up context for multiply */
    dcmul=*set;
    dcmul=*set;
    dcmul.digits=lhs->digits+rhs->digits; /* just enough */
    dcmul.digits=lhs->digits+rhs->digits; /* just enough */
    /* [The above may be an over-estimate for subset arithmetic, but that's OK] */
    /* [The above may be an over-estimate for subset arithmetic, but that's OK] */
    dcmul.emax=DEC_MAX_EMAX;            /* effectively unbounded .. */
    dcmul.emax=DEC_MAX_EMAX;            /* effectively unbounded .. */
    dcmul.emin=DEC_MIN_EMIN;            /* [thanks to Math restrictions] */
    dcmul.emin=DEC_MIN_EMIN;            /* [thanks to Math restrictions] */
    /* set up decNumber space to receive the result of the multiply */
    /* set up decNumber space to receive the result of the multiply */
    acc=bufa;                           /* may fit */
    acc=bufa;                           /* may fit */
    needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit);
    needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit);
    if (needbytes>sizeof(bufa)) {       /* need malloc space */
    if (needbytes>sizeof(bufa)) {       /* need malloc space */
      allocbufa=(decNumber *)malloc(needbytes);
      allocbufa=(decNumber *)malloc(needbytes);
      if (allocbufa==NULL) {            /* hopeless -- abandon */
      if (allocbufa==NULL) {            /* hopeless -- abandon */
        status|=DEC_Insufficient_storage;
        status|=DEC_Insufficient_storage;
        break;}
        break;}
      acc=allocbufa;                    /* use the allocated space */
      acc=allocbufa;                    /* use the allocated space */
      }
      }
    /* multiply with extended range and necessary precision */
    /* multiply with extended range and necessary precision */
    /*printf("emin=%ld\n", dcmul.emin); */
    /*printf("emin=%ld\n", dcmul.emin); */
    decMultiplyOp(acc, lhs, rhs, &dcmul, &status);
    decMultiplyOp(acc, lhs, rhs, &dcmul, &status);
    /* Only Invalid operation (from sNaN or Inf * 0) is possible in */
    /* Only Invalid operation (from sNaN or Inf * 0) is possible in */
    /* status; if either is seen than ignore fhs (in case it is */
    /* status; if either is seen than ignore fhs (in case it is */
    /* another sNaN) and set acc to NaN unless we had an sNaN */
    /* another sNaN) and set acc to NaN unless we had an sNaN */
    /* [decMultiplyOp leaves that to caller] */
    /* [decMultiplyOp leaves that to caller] */
    /* Note sNaN has to go through addOp to shorten payload if */
    /* Note sNaN has to go through addOp to shorten payload if */
    /* necessary */
    /* necessary */
    if ((status&DEC_Invalid_operation)!=0) {
    if ((status&DEC_Invalid_operation)!=0) {
      if (!(status&DEC_sNaN)) {         /* but be true invalid */
      if (!(status&DEC_sNaN)) {         /* but be true invalid */
        decNumberZero(res);             /* acc not yet set */
        decNumberZero(res);             /* acc not yet set */
        res->bits=DECNAN;
        res->bits=DECNAN;
        break;
        break;
        }
        }
      decNumberZero(&dzero);            /* make 0 (any non-NaN would do) */
      decNumberZero(&dzero);            /* make 0 (any non-NaN would do) */
      fhs=&dzero;                       /* use that */
      fhs=&dzero;                       /* use that */
      }
      }
    #if DECCHECK
    #if DECCHECK
     else { /* multiply was OK */
     else { /* multiply was OK */
      if (status!=0) printf("Status=%08lx after FMA multiply\n", status);
      if (status!=0) printf("Status=%08lx after FMA multiply\n", status);
      }
      }
    #endif
    #endif
    /* add the third operand and result -> res, and all is done */
    /* add the third operand and result -> res, and all is done */
    decAddOp(res, acc, fhs, set, 0, &status);
    decAddOp(res, acc, fhs, set, 0, &status);
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberFMA */
  } /* decNumberFMA */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberInvert -- invert a Number, digitwise                      */
/* decNumberInvert -- invert a Number, digitwise                      */
/*                                                                    */
/*                                                                    */
/*   This computes C = ~A                                             */
/*   This computes C = ~A                                             */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A (e.g., X=~X)                   */
/*   res is C, the result.  C may be A (e.g., X=~X)                   */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context (used for result length and error report)     */
/*   set is the context (used for result length and error report)     */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Logical function restrictions apply (see above); a NaN is          */
/* Logical function restrictions apply (see above); a NaN is          */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberInvert(decNumber *res, const decNumber *rhs,
decNumber * decNumberInvert(decNumber *res, const decNumber *rhs,
                            decContext *set) {
                            decContext *set) {
  const Unit *ua, *msua;                /* -> operand and its msu */
  const Unit *ua, *msua;                /* -> operand and its msu */
  Unit  *uc, *msuc;                     /* -> result and its msu */
  Unit  *uc, *msuc;                     /* -> result and its msu */
  Int   msudigs;                        /* digits in res msu */
  Int   msudigs;                        /* digits in res msu */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
  if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
    decStatus(res, DEC_Invalid_operation, set);
    decStatus(res, DEC_Invalid_operation, set);
    return res;
    return res;
    }
    }
  /* operand is valid */
  /* operand is valid */
  ua=rhs->lsu;                          /* bottom-up */
  ua=rhs->lsu;                          /* bottom-up */
  uc=res->lsu;                          /* .. */
  uc=res->lsu;                          /* .. */
  msua=ua+D2U(rhs->digits)-1;           /* -> msu of rhs */
  msua=ua+D2U(rhs->digits)-1;           /* -> msu of rhs */
  msuc=uc+D2U(set->digits)-1;           /* -> msu of result */
  msuc=uc+D2U(set->digits)-1;           /* -> msu of result */
  msudigs=MSUDIGITS(set->digits);       /* [faster than remainder] */
  msudigs=MSUDIGITS(set->digits);       /* [faster than remainder] */
  for (; uc<=msuc; ua++, uc++) {        /* Unit loop */
  for (; uc<=msuc; ua++, uc++) {        /* Unit loop */
    Unit a;                             /* extract unit */
    Unit a;                             /* extract unit */
    Int  i, j;                          /* work */
    Int  i, j;                          /* work */
    if (ua>msua) a=0;
    if (ua>msua) a=0;
     else a=*ua;
     else a=*ua;
    *uc=0;                               /* can now write back */
    *uc=0;                               /* can now write back */
    /* always need to examine all bits in rhs */
    /* always need to examine all bits in rhs */
    /* This loop could be unrolled and/or use BIN2BCD tables */
    /* This loop could be unrolled and/or use BIN2BCD tables */
    for (i=0; i<DECDPUN; i++) {
    for (i=0; i<DECDPUN; i++) {
      if ((~a)&1) *uc=*uc+(Unit)powers[i];   /* effect INVERT */
      if ((~a)&1) *uc=*uc+(Unit)powers[i];   /* effect INVERT */
      j=a%10;
      j=a%10;
      a=a/10;
      a=a/10;
      if (j>1) {
      if (j>1) {
        decStatus(res, DEC_Invalid_operation, set);
        decStatus(res, DEC_Invalid_operation, set);
        return res;
        return res;
        }
        }
      if (uc==msuc && i==msudigs-1) break;   /* just did final digit */
      if (uc==msuc && i==msudigs-1) break;   /* just did final digit */
      } /* each digit */
      } /* each digit */
    } /* each unit */
    } /* each unit */
  /* [here uc-1 is the msu of the result] */
  /* [here uc-1 is the msu of the result] */
  res->digits=decGetDigits(res->lsu, uc-res->lsu);
  res->digits=decGetDigits(res->lsu, uc-res->lsu);
  res->exponent=0;                       /* integer */
  res->exponent=0;                       /* integer */
  res->bits=0;                           /* sign=0 */
  res->bits=0;                           /* sign=0 */
  return res;  /* [no status to set] */
  return res;  /* [no status to set] */
  } /* decNumberInvert */
  } /* decNumberInvert */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberLn -- natural logarithm                                   */
/* decNumberLn -- natural logarithm                                   */
/*                                                                    */
/*                                                                    */
/*   This computes C = ln(A)                                          */
/*   This computes C = ln(A)                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context; note that rounding mode has no effect        */
/*   set is the context; note that rounding mode has no effect        */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Notable cases:                                                     */
/* Notable cases:                                                     */
/*   A<0 -> Invalid                                                   */
/*   A<0 -> Invalid                                                   */
/*   A=0 -> -Infinity (Exact)                                         */
/*   A=0 -> -Infinity (Exact)                                         */
/*   A=+Infinity -> +Infinity (Exact)                                 */
/*   A=+Infinity -> +Infinity (Exact)                                 */
/*   A=1 exactly -> 0 (Exact)                                         */
/*   A=1 exactly -> 0 (Exact)                                         */
/*                                                                    */
/*                                                                    */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/*                                                                    */
/*                                                                    */
/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* error in rare cases.                                               */
/* error in rare cases.                                               */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This is a wrapper for decLnOp which can handle the slightly wider  */
/* This is a wrapper for decLnOp which can handle the slightly wider  */
/* (+11) range needed by Ln, Log10, etc. (which may have to be able   */
/* (+11) range needed by Ln, Log10, etc. (which may have to be able   */
/* to calculate at p+e+2).                                            */
/* to calculate at p+e+2).                                            */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberLn(decNumber *res, const decNumber *rhs,
decNumber * decNumberLn(decNumber *res, const decNumber *rhs,
                        decContext *set) {
                        decContext *set) {
  uInt status=0;            /* accumulator */
  uInt status=0;            /* accumulator */
  #if DECSUBSET
  #if DECSUBSET
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  #endif
  #endif
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  /* Check restrictions; this is a math function; if not violated */
  /* Check restrictions; this is a math function; if not violated */
  /* then carry out the operation. */
  /* then carry out the operation. */
  if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
  if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operand and set lostDigits status, as needed */
      /* reduce operand and set lostDigits status, as needed */
      if (rhs->digits>set->digits) {
      if (rhs->digits>set->digits) {
        allocrhs=decRoundOperand(rhs, set, &status);
        allocrhs=decRoundOperand(rhs, set, &status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      /* special check in subset for rhs=0 */
      /* special check in subset for rhs=0 */
      if (ISZERO(rhs)) {                /* +/- zeros -> error */
      if (ISZERO(rhs)) {                /* +/- zeros -> error */
        status|=DEC_Invalid_operation;
        status|=DEC_Invalid_operation;
        break;}
        break;}
      } /* extended=0 */
      } /* extended=0 */
    #endif
    #endif
    decLnOp(res, rhs, set, &status);
    decLnOp(res, rhs, set, &status);
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs !=NULL) free(allocrhs);  /* drop any storage used */
  if (allocrhs !=NULL) free(allocrhs);  /* drop any storage used */
  #endif
  #endif
  /* apply significant status */
  /* apply significant status */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberLn */
  } /* decNumberLn */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberLogB - get adjusted exponent, by 754r rules               */
/* decNumberLogB - get adjusted exponent, by 754r rules               */
/*                                                                    */
/*                                                                    */
/*   This computes C = adjustedexponent(A)                            */
/*   This computes C = adjustedexponent(A)                            */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context, used only for digits and status              */
/*   set is the context, used only for digits and status              */
/*                                                                    */
/*                                                                    */
/* C must have space for 10 digits (A might have 10**9 digits and     */
/* C must have space for 10 digits (A might have 10**9 digits and     */
/* an exponent of +999999999, or one digit and an exponent of         */
/* an exponent of +999999999, or one digit and an exponent of         */
/* -1999999999).                                                      */
/* -1999999999).                                                      */
/*                                                                    */
/*                                                                    */
/* This returns the adjusted exponent of A after (in theory) padding  */
/* This returns the adjusted exponent of A after (in theory) padding  */
/* with zeros on the right to set->digits digits while keeping the    */
/* with zeros on the right to set->digits digits while keeping the    */
/* same value.  The exponent is not limited by emin/emax.             */
/* same value.  The exponent is not limited by emin/emax.             */
/*                                                                    */
/*                                                                    */
/* Notable cases:                                                     */
/* Notable cases:                                                     */
/*   A<0 -> Use |A|                                                   */
/*   A<0 -> Use |A|                                                   */
/*   A=0 -> -Infinity (Division by zero)                              */
/*   A=0 -> -Infinity (Division by zero)                              */
/*   A=Infinite -> +Infinity (Exact)                                  */
/*   A=Infinite -> +Infinity (Exact)                                  */
/*   A=1 exactly -> 0 (Exact)                                         */
/*   A=1 exactly -> 0 (Exact)                                         */
/*   NaNs are propagated as usual                                     */
/*   NaNs are propagated as usual                                     */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberLogB(decNumber *res, const decNumber *rhs,
decNumber * decNumberLogB(decNumber *res, const decNumber *rhs,
                          decContext *set) {
                          decContext *set) {
  uInt status=0;            /* accumulator */
  uInt status=0;            /* accumulator */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  /* NaNs as usual; Infinities return +Infinity; 0->oops */
  /* NaNs as usual; Infinities return +Infinity; 0->oops */
  if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status);
  if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status);
   else if (decNumberIsInfinite(rhs)) decNumberCopyAbs(res, rhs);
   else if (decNumberIsInfinite(rhs)) decNumberCopyAbs(res, rhs);
   else if (decNumberIsZero(rhs)) {
   else if (decNumberIsZero(rhs)) {
    decNumberZero(res);                 /* prepare for Infinity */
    decNumberZero(res);                 /* prepare for Infinity */
    res->bits=DECNEG|DECINF;            /* -Infinity */
    res->bits=DECNEG|DECINF;            /* -Infinity */
    status|=DEC_Division_by_zero;       /* as per 754r */
    status|=DEC_Division_by_zero;       /* as per 754r */
    }
    }
   else { /* finite non-zero */
   else { /* finite non-zero */
    Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */
    Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */
    decNumberFromInt32(res, ae);        /* lay it out */
    decNumberFromInt32(res, ae);        /* lay it out */
    }
    }
 
 
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberLogB */
  } /* decNumberLogB */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberLog10 -- logarithm in base 10                             */
/* decNumberLog10 -- logarithm in base 10                             */
/*                                                                    */
/*                                                                    */
/*   This computes C = log10(A)                                       */
/*   This computes C = log10(A)                                       */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context; note that rounding mode has no effect        */
/*   set is the context; note that rounding mode has no effect        */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Notable cases:                                                     */
/* Notable cases:                                                     */
/*   A<0 -> Invalid                                                   */
/*   A<0 -> Invalid                                                   */
/*   A=0 -> -Infinity (Exact)                                         */
/*   A=0 -> -Infinity (Exact)                                         */
/*   A=+Infinity -> +Infinity (Exact)                                 */
/*   A=+Infinity -> +Infinity (Exact)                                 */
/*   A=10**n (if n is an integer) -> n (Exact)                        */
/*   A=10**n (if n is an integer) -> n (Exact)                        */
/*                                                                    */
/*                                                                    */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/*                                                                    */
/*                                                                    */
/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
/* An Inexact result is rounded using DEC_ROUND_HALF_EVEN; it will    */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* error in rare cases.                                               */
/* error in rare cases.                                               */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This calculates ln(A)/ln(10) using appropriate precision.  For     */
/* This calculates ln(A)/ln(10) using appropriate precision.  For     */
/* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the      */
/* ln(A) this is the max(p, rhs->digits + t) + 3, where p is the      */
/* requested digits and t is the number of digits in the exponent     */
/* requested digits and t is the number of digits in the exponent     */
/* (maximum 6).  For ln(10) it is p + 3; this is often handled by the */
/* (maximum 6).  For ln(10) it is p + 3; this is often handled by the */
/* fastpath in decLnOp.  The final division is done to the requested  */
/* fastpath in decLnOp.  The final division is done to the requested  */
/* precision.                                                         */
/* precision.                                                         */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberLog10(decNumber *res, const decNumber *rhs,
decNumber * decNumberLog10(decNumber *res, const decNumber *rhs,
                          decContext *set) {
                          decContext *set) {
  uInt status=0, ignore=0;           /* status accumulators */
  uInt status=0, ignore=0;           /* status accumulators */
  uInt needbytes;                  /* for space calculations */
  uInt needbytes;                  /* for space calculations */
  Int p;                           /* working precision */
  Int p;                           /* working precision */
  Int t;                           /* digits in exponent of A */
  Int t;                           /* digits in exponent of A */
 
 
  /* buffers for a and b working decimals */
  /* buffers for a and b working decimals */
  /* (adjustment calculator, same size) */
  /* (adjustment calculator, same size) */
  decNumber bufa[D2N(DECBUFFER+2)];
  decNumber bufa[D2N(DECBUFFER+2)];
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *a=bufa;               /* temporary a */
  decNumber *a=bufa;               /* temporary a */
  decNumber bufb[D2N(DECBUFFER+2)];
  decNumber bufb[D2N(DECBUFFER+2)];
  decNumber *allocbufb=NULL;       /* -> allocated bufb, iff allocated */
  decNumber *allocbufb=NULL;       /* -> allocated bufb, iff allocated */
  decNumber *b=bufb;               /* temporary b */
  decNumber *b=bufb;               /* temporary b */
  decNumber bufw[D2N(10)];         /* working 2-10 digit number */
  decNumber bufw[D2N(10)];         /* working 2-10 digit number */
  decNumber *w=bufw;               /* .. */
  decNumber *w=bufw;               /* .. */
  #if DECSUBSET
  #if DECSUBSET
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  #endif
  #endif
 
 
  decContext aset;                 /* working context */
  decContext aset;                 /* working context */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  /* Check restrictions; this is a math function; if not violated */
  /* Check restrictions; this is a math function; if not violated */
  /* then carry out the operation. */
  /* then carry out the operation. */
  if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */
  if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operand and set lostDigits status, as needed */
      /* reduce operand and set lostDigits status, as needed */
      if (rhs->digits>set->digits) {
      if (rhs->digits>set->digits) {
        allocrhs=decRoundOperand(rhs, set, &status);
        allocrhs=decRoundOperand(rhs, set, &status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      /* special check in subset for rhs=0 */
      /* special check in subset for rhs=0 */
      if (ISZERO(rhs)) {                /* +/- zeros -> error */
      if (ISZERO(rhs)) {                /* +/- zeros -> error */
        status|=DEC_Invalid_operation;
        status|=DEC_Invalid_operation;
        break;}
        break;}
      } /* extended=0 */
      } /* extended=0 */
    #endif
    #endif
 
 
    decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
    decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
 
 
    /* handle exact powers of 10; only check if +ve finite */
    /* handle exact powers of 10; only check if +ve finite */
    if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) {
    if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) {
      Int residue=0;                /* (no residue) */
      Int residue=0;                /* (no residue) */
      uInt copystat=0;              /* clean status */
      uInt copystat=0;              /* clean status */
 
 
      /* round to a single digit... */
      /* round to a single digit... */
      aset.digits=1;
      aset.digits=1;
      decCopyFit(w, rhs, &aset, &residue, &copystat); /* copy & shorten */
      decCopyFit(w, rhs, &aset, &residue, &copystat); /* copy & shorten */
      /* if exact and the digit is 1, rhs is a power of 10 */
      /* if exact and the digit is 1, rhs is a power of 10 */
      if (!(copystat&DEC_Inexact) && w->lsu[0]==1) {
      if (!(copystat&DEC_Inexact) && w->lsu[0]==1) {
        /* the exponent, conveniently, is the power of 10; making */
        /* the exponent, conveniently, is the power of 10; making */
        /* this the result needs a little care as it might not fit, */
        /* this the result needs a little care as it might not fit, */
        /* so first convert it into the working number, and then move */
        /* so first convert it into the working number, and then move */
        /* to res */
        /* to res */
        decNumberFromInt32(w, w->exponent);
        decNumberFromInt32(w, w->exponent);
        residue=0;
        residue=0;
        decCopyFit(res, w, set, &residue, &status); /* copy & round */
        decCopyFit(res, w, set, &residue, &status); /* copy & round */
        decFinish(res, set, &residue, &status);     /* cleanup/set flags */
        decFinish(res, set, &residue, &status);     /* cleanup/set flags */
        break;
        break;
        } /* not a power of 10 */
        } /* not a power of 10 */
      } /* not a candidate for exact */
      } /* not a candidate for exact */
 
 
    /* simplify the information-content calculation to use 'total */
    /* simplify the information-content calculation to use 'total */
    /* number of digits in a, including exponent' as compared to the */
    /* number of digits in a, including exponent' as compared to the */
    /* requested digits, as increasing this will only rarely cost an */
    /* requested digits, as increasing this will only rarely cost an */
    /* iteration in ln(a) anyway */
    /* iteration in ln(a) anyway */
    t=6;                                /* it can never be >6 */
    t=6;                                /* it can never be >6 */
 
 
    /* allocate space when needed... */
    /* allocate space when needed... */
    p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3;
    p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3;
    needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
    needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
    if (needbytes>sizeof(bufa)) {       /* need malloc space */
    if (needbytes>sizeof(bufa)) {       /* need malloc space */
      allocbufa=(decNumber *)malloc(needbytes);
      allocbufa=(decNumber *)malloc(needbytes);
      if (allocbufa==NULL) {            /* hopeless -- abandon */
      if (allocbufa==NULL) {            /* hopeless -- abandon */
        status|=DEC_Insufficient_storage;
        status|=DEC_Insufficient_storage;
        break;}
        break;}
      a=allocbufa;                      /* use the allocated space */
      a=allocbufa;                      /* use the allocated space */
      }
      }
    aset.digits=p;                      /* as calculated */
    aset.digits=p;                      /* as calculated */
    aset.emax=DEC_MAX_MATH;             /* usual bounds */
    aset.emax=DEC_MAX_MATH;             /* usual bounds */
    aset.emin=-DEC_MAX_MATH;            /* .. */
    aset.emin=-DEC_MAX_MATH;            /* .. */
    aset.clamp=0;                        /* and no concrete format */
    aset.clamp=0;                        /* and no concrete format */
    decLnOp(a, rhs, &aset, &status);    /* a=ln(rhs) */
    decLnOp(a, rhs, &aset, &status);    /* a=ln(rhs) */
 
 
    /* skip the division if the result so far is infinite, NaN, or */
    /* skip the division if the result so far is infinite, NaN, or */
    /* zero, or there was an error; note NaN from sNaN needs copy */
    /* zero, or there was an error; note NaN from sNaN needs copy */
    if (status&DEC_NaNs && !(status&DEC_sNaN)) break;
    if (status&DEC_NaNs && !(status&DEC_sNaN)) break;
    if (a->bits&DECSPECIAL || ISZERO(a)) {
    if (a->bits&DECSPECIAL || ISZERO(a)) {
      decNumberCopy(res, a);            /* [will fit] */
      decNumberCopy(res, a);            /* [will fit] */
      break;}
      break;}
 
 
    /* for ln(10) an extra 3 digits of precision are needed */
    /* for ln(10) an extra 3 digits of precision are needed */
    p=set->digits+3;
    p=set->digits+3;
    needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
    needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
    if (needbytes>sizeof(bufb)) {       /* need malloc space */
    if (needbytes>sizeof(bufb)) {       /* need malloc space */
      allocbufb=(decNumber *)malloc(needbytes);
      allocbufb=(decNumber *)malloc(needbytes);
      if (allocbufb==NULL) {            /* hopeless -- abandon */
      if (allocbufb==NULL) {            /* hopeless -- abandon */
        status|=DEC_Insufficient_storage;
        status|=DEC_Insufficient_storage;
        break;}
        break;}
      b=allocbufb;                      /* use the allocated space */
      b=allocbufb;                      /* use the allocated space */
      }
      }
    decNumberZero(w);                   /* set up 10... */
    decNumberZero(w);                   /* set up 10... */
    #if DECDPUN==1
    #if DECDPUN==1
    w->lsu[1]=1; w->lsu[0]=0;             /* .. */
    w->lsu[1]=1; w->lsu[0]=0;             /* .. */
    #else
    #else
    w->lsu[0]=10;                        /* .. */
    w->lsu[0]=10;                        /* .. */
    #endif
    #endif
    w->digits=2;                        /* .. */
    w->digits=2;                        /* .. */
 
 
    aset.digits=p;
    aset.digits=p;
    decLnOp(b, w, &aset, &ignore);      /* b=ln(10) */
    decLnOp(b, w, &aset, &ignore);      /* b=ln(10) */
 
 
    aset.digits=set->digits;            /* for final divide */
    aset.digits=set->digits;            /* for final divide */
    decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */
    decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */
    } while(0);                          /* [for break] */
    } while(0);                          /* [for break] */
 
 
  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
  if (allocbufb!=NULL) free(allocbufb); /* .. */
  if (allocbufb!=NULL) free(allocbufb); /* .. */
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs !=NULL) free(allocrhs);  /* .. */
  if (allocrhs !=NULL) free(allocrhs);  /* .. */
  #endif
  #endif
  /* apply significant status */
  /* apply significant status */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberLog10 */
  } /* decNumberLog10 */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberMax -- compare two Numbers and return the maximum         */
/* decNumberMax -- compare two Numbers and return the maximum         */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ? B, returning the maximum by 754R rules     */
/*   This computes C = A ? B, returning the maximum by 754R rules     */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberMax(decNumber *res, const decNumber *lhs,
decNumber * decNumberMax(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, decContext *set) {
                         const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decCompareOp(res, lhs, rhs, set, COMPMAX, &status);
  decCompareOp(res, lhs, rhs, set, COMPMAX, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberMax */
  } /* decNumberMax */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberMaxMag -- compare and return the maximum by magnitude     */
/* decNumberMaxMag -- compare and return the maximum by magnitude     */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ? B, returning the maximum by 754R rules     */
/*   This computes C = A ? B, returning the maximum by 754R rules     */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberMaxMag(decNumber *res, const decNumber *lhs,
decNumber * decNumberMaxMag(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, decContext *set) {
                         const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status);
  decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberMaxMag */
  } /* decNumberMaxMag */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberMin -- compare two Numbers and return the minimum         */
/* decNumberMin -- compare two Numbers and return the minimum         */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ? B, returning the minimum by 754R rules     */
/*   This computes C = A ? B, returning the minimum by 754R rules     */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberMin(decNumber *res, const decNumber *lhs,
decNumber * decNumberMin(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, decContext *set) {
                         const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decCompareOp(res, lhs, rhs, set, COMPMIN, &status);
  decCompareOp(res, lhs, rhs, set, COMPMIN, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberMin */
  } /* decNumberMin */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberMinMag -- compare and return the minimum by magnitude     */
/* decNumberMinMag -- compare and return the minimum by magnitude     */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ? B, returning the minimum by 754R rules     */
/*   This computes C = A ? B, returning the minimum by 754R rules     */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberMinMag(decNumber *res, const decNumber *lhs,
decNumber * decNumberMinMag(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, decContext *set) {
                         const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status);
  decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberMinMag */
  } /* decNumberMinMag */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberMinus -- prefix minus operator                            */
/* decNumberMinus -- prefix minus operator                            */
/*                                                                    */
/*                                                                    */
/*   This computes C = 0 - A                                          */
/*   This computes C = 0 - A                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* See also decNumberCopyNegate for a quiet bitwise version of this.  */
/* See also decNumberCopyNegate for a quiet bitwise version of this.  */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* Simply use AddOp for the subtract, which will do the necessary.    */
/* Simply use AddOp for the subtract, which will do the necessary.    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberMinus(decNumber *res, const decNumber *rhs,
decNumber * decNumberMinus(decNumber *res, const decNumber *rhs,
                           decContext *set) {
                           decContext *set) {
  decNumber dzero;
  decNumber dzero;
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  decNumberZero(&dzero);                /* make 0 */
  decNumberZero(&dzero);                /* make 0 */
  dzero.exponent=rhs->exponent;         /* [no coefficient expansion] */
  dzero.exponent=rhs->exponent;         /* [no coefficient expansion] */
  decAddOp(res, &dzero, rhs, set, DECNEG, &status);
  decAddOp(res, &dzero, rhs, set, DECNEG, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberMinus */
  } /* decNumberMinus */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberNextMinus -- next towards -Infinity                       */
/* decNumberNextMinus -- next towards -Infinity                       */
/*                                                                    */
/*                                                                    */
/*   This computes C = A - infinitesimal, rounded towards -Infinity   */
/*   This computes C = A - infinitesimal, rounded towards -Infinity   */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* This is a generalization of 754r NextDown.                         */
/* This is a generalization of 754r NextDown.                         */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberNextMinus(decNumber *res, const decNumber *rhs,
decNumber * decNumberNextMinus(decNumber *res, const decNumber *rhs,
                               decContext *set) {
                               decContext *set) {
  decNumber dtiny;                           /* constant */
  decNumber dtiny;                           /* constant */
  decContext workset=*set;                   /* work */
  decContext workset=*set;                   /* work */
  uInt status=0;                      /* accumulator */
  uInt status=0;                      /* accumulator */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  /* +Infinity is the special case */
  /* +Infinity is the special case */
  if ((rhs->bits&(DECINF|DECNEG))==DECINF) {
  if ((rhs->bits&(DECINF|DECNEG))==DECINF) {
    decSetMaxValue(res, set);                /* is +ve */
    decSetMaxValue(res, set);                /* is +ve */
    /* there is no status to set */
    /* there is no status to set */
    return res;
    return res;
    }
    }
  decNumberZero(&dtiny);                     /* start with 0 */
  decNumberZero(&dtiny);                     /* start with 0 */
  dtiny.lsu[0]=1;                             /* make number that is .. */
  dtiny.lsu[0]=1;                             /* make number that is .. */
  dtiny.exponent=DEC_MIN_EMIN-1;             /* .. smaller than tiniest */
  dtiny.exponent=DEC_MIN_EMIN-1;             /* .. smaller than tiniest */
  workset.round=DEC_ROUND_FLOOR;
  workset.round=DEC_ROUND_FLOOR;
  decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status);
  decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status);
  status&=DEC_Invalid_operation|DEC_sNaN;    /* only sNaN Invalid please */
  status&=DEC_Invalid_operation|DEC_sNaN;    /* only sNaN Invalid please */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberNextMinus */
  } /* decNumberNextMinus */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberNextPlus -- next towards +Infinity                        */
/* decNumberNextPlus -- next towards +Infinity                        */
/*                                                                    */
/*                                                                    */
/*   This computes C = A + infinitesimal, rounded towards +Infinity   */
/*   This computes C = A + infinitesimal, rounded towards +Infinity   */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* This is a generalization of 754r NextUp.                           */
/* This is a generalization of 754r NextUp.                           */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberNextPlus(decNumber *res, const decNumber *rhs,
decNumber * decNumberNextPlus(decNumber *res, const decNumber *rhs,
                              decContext *set) {
                              decContext *set) {
  decNumber dtiny;                           /* constant */
  decNumber dtiny;                           /* constant */
  decContext workset=*set;                   /* work */
  decContext workset=*set;                   /* work */
  uInt status=0;                      /* accumulator */
  uInt status=0;                      /* accumulator */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  /* -Infinity is the special case */
  /* -Infinity is the special case */
  if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
  if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
    decSetMaxValue(res, set);
    decSetMaxValue(res, set);
    res->bits=DECNEG;                        /* negative */
    res->bits=DECNEG;                        /* negative */
    /* there is no status to set */
    /* there is no status to set */
    return res;
    return res;
    }
    }
  decNumberZero(&dtiny);                     /* start with 0 */
  decNumberZero(&dtiny);                     /* start with 0 */
  dtiny.lsu[0]=1;                             /* make number that is .. */
  dtiny.lsu[0]=1;                             /* make number that is .. */
  dtiny.exponent=DEC_MIN_EMIN-1;             /* .. smaller than tiniest */
  dtiny.exponent=DEC_MIN_EMIN-1;             /* .. smaller than tiniest */
  workset.round=DEC_ROUND_CEILING;
  workset.round=DEC_ROUND_CEILING;
  decAddOp(res, rhs, &dtiny, &workset, 0, &status);
  decAddOp(res, rhs, &dtiny, &workset, 0, &status);
  status&=DEC_Invalid_operation|DEC_sNaN;    /* only sNaN Invalid please */
  status&=DEC_Invalid_operation|DEC_sNaN;    /* only sNaN Invalid please */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberNextPlus */
  } /* decNumberNextPlus */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberNextToward -- next towards rhs                            */
/* decNumberNextToward -- next towards rhs                            */
/*                                                                    */
/*                                                                    */
/*   This computes C = A +/- infinitesimal, rounded towards           */
/*   This computes C = A +/- infinitesimal, rounded towards           */
/*   +/-Infinity in the direction of B, as per 754r nextafter rules   */
/*   +/-Infinity in the direction of B, as per 754r nextafter rules   */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A or B.                          */
/*   res is C, the result.  C may be A or B.                          */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* This is a generalization of 754r NextAfter.                        */
/* This is a generalization of 754r NextAfter.                        */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberNextToward(decNumber *res, const decNumber *lhs,
decNumber * decNumberNextToward(decNumber *res, const decNumber *lhs,
                                const decNumber *rhs, decContext *set) {
                                const decNumber *rhs, decContext *set) {
  decNumber dtiny;                           /* constant */
  decNumber dtiny;                           /* constant */
  decContext workset=*set;                   /* work */
  decContext workset=*set;                   /* work */
  Int result;                                /* .. */
  Int result;                                /* .. */
  uInt status=0;                      /* accumulator */
  uInt status=0;                      /* accumulator */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) {
  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) {
    decNaNs(res, lhs, rhs, set, &status);
    decNaNs(res, lhs, rhs, set, &status);
    }
    }
   else { /* Is numeric, so no chance of sNaN Invalid, etc. */
   else { /* Is numeric, so no chance of sNaN Invalid, etc. */
    result=decCompare(lhs, rhs, 0);      /* sign matters */
    result=decCompare(lhs, rhs, 0);      /* sign matters */
    if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */
    if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */
     else { /* valid compare */
     else { /* valid compare */
      if (result==0) decNumberCopySign(res, lhs, rhs); /* easy */
      if (result==0) decNumberCopySign(res, lhs, rhs); /* easy */
       else { /* differ: need NextPlus or NextMinus */
       else { /* differ: need NextPlus or NextMinus */
        uByte sub;                      /* add or subtract */
        uByte sub;                      /* add or subtract */
        if (result<0) {                  /* lhs<rhs, do nextplus */
        if (result<0) {                  /* lhs<rhs, do nextplus */
          /* -Infinity is the special case */
          /* -Infinity is the special case */
          if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
          if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
            decSetMaxValue(res, set);
            decSetMaxValue(res, set);
            res->bits=DECNEG;           /* negative */
            res->bits=DECNEG;           /* negative */
            return res;                 /* there is no status to set */
            return res;                 /* there is no status to set */
            }
            }
          workset.round=DEC_ROUND_CEILING;
          workset.round=DEC_ROUND_CEILING;
          sub=0;                 /* add, please */
          sub=0;                 /* add, please */
          } /* plus */
          } /* plus */
         else {                         /* lhs>rhs, do nextminus */
         else {                         /* lhs>rhs, do nextminus */
          /* +Infinity is the special case */
          /* +Infinity is the special case */
          if ((lhs->bits&(DECINF|DECNEG))==DECINF) {
          if ((lhs->bits&(DECINF|DECNEG))==DECINF) {
            decSetMaxValue(res, set);
            decSetMaxValue(res, set);
            return res;                 /* there is no status to set */
            return res;                 /* there is no status to set */
            }
            }
          workset.round=DEC_ROUND_FLOOR;
          workset.round=DEC_ROUND_FLOOR;
          sub=DECNEG;                   /* subtract, please */
          sub=DECNEG;                   /* subtract, please */
          } /* minus */
          } /* minus */
        decNumberZero(&dtiny);          /* start with 0 */
        decNumberZero(&dtiny);          /* start with 0 */
        dtiny.lsu[0]=1;                  /* make number that is .. */
        dtiny.lsu[0]=1;                  /* make number that is .. */
        dtiny.exponent=DEC_MIN_EMIN-1;  /* .. smaller than tiniest */
        dtiny.exponent=DEC_MIN_EMIN-1;  /* .. smaller than tiniest */
        decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */
        decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */
        /* turn off exceptions if the result is a normal number */
        /* turn off exceptions if the result is a normal number */
        /* (including Nmin), otherwise let all status through */
        /* (including Nmin), otherwise let all status through */
        if (decNumberIsNormal(res, set)) status=0;
        if (decNumberIsNormal(res, set)) status=0;
        } /* unequal */
        } /* unequal */
      } /* compare OK */
      } /* compare OK */
    } /* numeric */
    } /* numeric */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberNextToward */
  } /* decNumberNextToward */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberOr -- OR two Numbers, digitwise                           */
/* decNumberOr -- OR two Numbers, digitwise                           */
/*                                                                    */
/*                                                                    */
/*   This computes C = A | B                                          */
/*   This computes C = A | B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X|X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X|X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context (used for result length and error report)     */
/*   set is the context (used for result length and error report)     */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Logical function restrictions apply (see above); a NaN is          */
/* Logical function restrictions apply (see above); a NaN is          */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberOr(decNumber *res, const decNumber *lhs,
decNumber * decNumberOr(decNumber *res, const decNumber *lhs,
                        const decNumber *rhs, decContext *set) {
                        const decNumber *rhs, decContext *set) {
  const Unit *ua, *ub;                  /* -> operands */
  const Unit *ua, *ub;                  /* -> operands */
  const Unit *msua, *msub;              /* -> operand msus */
  const Unit *msua, *msub;              /* -> operand msus */
  Unit  *uc, *msuc;                     /* -> result and its msu */
  Unit  *uc, *msuc;                     /* -> result and its msu */
  Int   msudigs;                        /* digits in res msu */
  Int   msudigs;                        /* digits in res msu */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
    decStatus(res, DEC_Invalid_operation, set);
    decStatus(res, DEC_Invalid_operation, set);
    return res;
    return res;
    }
    }
  /* operands are valid */
  /* operands are valid */
  ua=lhs->lsu;                          /* bottom-up */
  ua=lhs->lsu;                          /* bottom-up */
  ub=rhs->lsu;                          /* .. */
  ub=rhs->lsu;                          /* .. */
  uc=res->lsu;                          /* .. */
  uc=res->lsu;                          /* .. */
  msua=ua+D2U(lhs->digits)-1;           /* -> msu of lhs */
  msua=ua+D2U(lhs->digits)-1;           /* -> msu of lhs */
  msub=ub+D2U(rhs->digits)-1;           /* -> msu of rhs */
  msub=ub+D2U(rhs->digits)-1;           /* -> msu of rhs */
  msuc=uc+D2U(set->digits)-1;           /* -> msu of result */
  msuc=uc+D2U(set->digits)-1;           /* -> msu of result */
  msudigs=MSUDIGITS(set->digits);       /* [faster than remainder] */
  msudigs=MSUDIGITS(set->digits);       /* [faster than remainder] */
  for (; uc<=msuc; ua++, ub++, uc++) {  /* Unit loop */
  for (; uc<=msuc; ua++, ub++, uc++) {  /* Unit loop */
    Unit a, b;                          /* extract units */
    Unit a, b;                          /* extract units */
    if (ua>msua) a=0;
    if (ua>msua) a=0;
     else a=*ua;
     else a=*ua;
    if (ub>msub) b=0;
    if (ub>msub) b=0;
     else b=*ub;
     else b=*ub;
    *uc=0;                               /* can now write back */
    *uc=0;                               /* can now write back */
    if (a|b) {                          /* maybe 1 bits to examine */
    if (a|b) {                          /* maybe 1 bits to examine */
      Int i, j;
      Int i, j;
      /* This loop could be unrolled and/or use BIN2BCD tables */
      /* This loop could be unrolled and/or use BIN2BCD tables */
      for (i=0; i<DECDPUN; i++) {
      for (i=0; i<DECDPUN; i++) {
        if ((a|b)&1) *uc=*uc+(Unit)powers[i];     /* effect OR */
        if ((a|b)&1) *uc=*uc+(Unit)powers[i];     /* effect OR */
        j=a%10;
        j=a%10;
        a=a/10;
        a=a/10;
        j|=b%10;
        j|=b%10;
        b=b/10;
        b=b/10;
        if (j>1) {
        if (j>1) {
          decStatus(res, DEC_Invalid_operation, set);
          decStatus(res, DEC_Invalid_operation, set);
          return res;
          return res;
          }
          }
        if (uc==msuc && i==msudigs-1) break;      /* just did final digit */
        if (uc==msuc && i==msudigs-1) break;      /* just did final digit */
        } /* each digit */
        } /* each digit */
      } /* non-zero */
      } /* non-zero */
    } /* each unit */
    } /* each unit */
  /* [here uc-1 is the msu of the result] */
  /* [here uc-1 is the msu of the result] */
  res->digits=decGetDigits(res->lsu, uc-res->lsu);
  res->digits=decGetDigits(res->lsu, uc-res->lsu);
  res->exponent=0;                       /* integer */
  res->exponent=0;                       /* integer */
  res->bits=0;                           /* sign=0 */
  res->bits=0;                           /* sign=0 */
  return res;  /* [no status to set] */
  return res;  /* [no status to set] */
  } /* decNumberOr */
  } /* decNumberOr */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberPlus -- prefix plus operator                              */
/* decNumberPlus -- prefix plus operator                              */
/*                                                                    */
/*                                                                    */
/*   This computes C = 0 + A                                          */
/*   This computes C = 0 + A                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* See also decNumberCopy for a quiet bitwise version of this.        */
/* See also decNumberCopy for a quiet bitwise version of this.        */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This simply uses AddOp; Add will take fast path after preparing A. */
/* This simply uses AddOp; Add will take fast path after preparing A. */
/* Performance is a concern here, as this routine is often used to    */
/* Performance is a concern here, as this routine is often used to    */
/* check operands and apply rounding and overflow/underflow testing.  */
/* check operands and apply rounding and overflow/underflow testing.  */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberPlus(decNumber *res, const decNumber *rhs,
decNumber * decNumberPlus(decNumber *res, const decNumber *rhs,
                          decContext *set) {
                          decContext *set) {
  decNumber dzero;
  decNumber dzero;
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  decNumberZero(&dzero);                /* make 0 */
  decNumberZero(&dzero);                /* make 0 */
  dzero.exponent=rhs->exponent;         /* [no coefficient expansion] */
  dzero.exponent=rhs->exponent;         /* [no coefficient expansion] */
  decAddOp(res, &dzero, rhs, set, 0, &status);
  decAddOp(res, &dzero, rhs, set, 0, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberPlus */
  } /* decNumberPlus */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberMultiply -- multiply two Numbers                          */
/* decNumberMultiply -- multiply two Numbers                          */
/*                                                                    */
/*                                                                    */
/*   This computes C = A x B                                          */
/*   This computes C = A x B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs,
decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs,
                              const decNumber *rhs, decContext *set) {
                              const decNumber *rhs, decContext *set) {
  uInt status=0;            /* accumulator */
  uInt status=0;            /* accumulator */
  decMultiplyOp(res, lhs, rhs, set, &status);
  decMultiplyOp(res, lhs, rhs, set, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberMultiply */
  } /* decNumberMultiply */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberPower -- raise a number to a power                        */
/* decNumberPower -- raise a number to a power                        */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ** B                                         */
/*   This computes C = A ** B                                         */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X**X)        */
/*   res is C, the result.  C may be A and/or B (e.g., X=X**X)        */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* Mathematical function restrictions apply (see above); a NaN is     */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/*                                                                    */
/*                                                                    */
/* However, if 1999999997<=B<=999999999 and B is an integer then the  */
/* However, if 1999999997<=B<=999999999 and B is an integer then the  */
/* restrictions on A and the context are relaxed to the usual bounds, */
/* restrictions on A and the context are relaxed to the usual bounds, */
/* for compatibility with the earlier (integer power only) version    */
/* for compatibility with the earlier (integer power only) version    */
/* of this function.                                                  */
/* of this function.                                                  */
/*                                                                    */
/*                                                                    */
/* When B is an integer, the result may be exact, even if rounded.    */
/* When B is an integer, the result may be exact, even if rounded.    */
/*                                                                    */
/*                                                                    */
/* The final result is rounded according to the context; it will      */
/* The final result is rounded according to the context; it will      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* error in rare cases.                                               */
/* error in rare cases.                                               */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberPower(decNumber *res, const decNumber *lhs,
decNumber * decNumberPower(decNumber *res, const decNumber *lhs,
                           const decNumber *rhs, decContext *set) {
                           const decNumber *rhs, decContext *set) {
  #if DECSUBSET
  #if DECSUBSET
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *allocrhs=NULL;        /* .., rhs */
  decNumber *allocrhs=NULL;        /* .., rhs */
  #endif
  #endif
  decNumber *allocdac=NULL;        /* -> allocated acc buffer, iff used */
  decNumber *allocdac=NULL;        /* -> allocated acc buffer, iff used */
  decNumber *allocinv=NULL;        /* -> allocated 1/x buffer, iff used */
  decNumber *allocinv=NULL;        /* -> allocated 1/x buffer, iff used */
  Int   reqdigits=set->digits;     /* requested DIGITS */
  Int   reqdigits=set->digits;     /* requested DIGITS */
  Int   n;                         /* rhs in binary */
  Int   n;                         /* rhs in binary */
  Flag  rhsint=0;                   /* 1 if rhs is an integer */
  Flag  rhsint=0;                   /* 1 if rhs is an integer */
  Flag  useint=0;                   /* 1 if can use integer calculation */
  Flag  useint=0;                   /* 1 if can use integer calculation */
  Flag  isoddint=0;                 /* 1 if rhs is an integer and odd */
  Flag  isoddint=0;                 /* 1 if rhs is an integer and odd */
  Int   i;                         /* work */
  Int   i;                         /* work */
  #if DECSUBSET
  #if DECSUBSET
  Int   dropped;                   /* .. */
  Int   dropped;                   /* .. */
  #endif
  #endif
  uInt  needbytes;                 /* buffer size needed */
  uInt  needbytes;                 /* buffer size needed */
  Flag  seenbit;                   /* seen a bit while powering */
  Flag  seenbit;                   /* seen a bit while powering */
  Int   residue=0;                  /* rounding residue */
  Int   residue=0;                  /* rounding residue */
  uInt  status=0;                   /* accumulators */
  uInt  status=0;                   /* accumulators */
  uByte bits=0;                     /* result sign if errors */
  uByte bits=0;                     /* result sign if errors */
  decContext aset;                 /* working context */
  decContext aset;                 /* working context */
  decNumber dnOne;                 /* work value 1... */
  decNumber dnOne;                 /* work value 1... */
  /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */
  /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */
  decNumber dacbuff[D2N(DECBUFFER+9)];
  decNumber dacbuff[D2N(DECBUFFER+9)];
  decNumber *dac=dacbuff;          /* -> result accumulator */
  decNumber *dac=dacbuff;          /* -> result accumulator */
  /* same again for possible 1/lhs calculation */
  /* same again for possible 1/lhs calculation */
  decNumber invbuff[D2N(DECBUFFER+9)];
  decNumber invbuff[D2N(DECBUFFER+9)];
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                             /* protect allocated storage */
  do {                             /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) { /* reduce operands and set status, as needed */
    if (!set->extended) { /* reduce operands and set status, as needed */
      if (lhs->digits>reqdigits) {
      if (lhs->digits>reqdigits) {
        alloclhs=decRoundOperand(lhs, set, &status);
        alloclhs=decRoundOperand(lhs, set, &status);
        if (alloclhs==NULL) break;
        if (alloclhs==NULL) break;
        lhs=alloclhs;
        lhs=alloclhs;
        }
        }
      if (rhs->digits>reqdigits) {
      if (rhs->digits>reqdigits) {
        allocrhs=decRoundOperand(rhs, set, &status);
        allocrhs=decRoundOperand(rhs, set, &status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    /* [following code does not require input rounding] */
    /* [following code does not require input rounding] */
 
 
    /* handle NaNs and rhs Infinity (lhs infinity is harder) */
    /* handle NaNs and rhs Infinity (lhs infinity is harder) */
    if (SPECIALARGS) {
    if (SPECIALARGS) {
      if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */
      if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */
        decNaNs(res, lhs, rhs, set, &status);
        decNaNs(res, lhs, rhs, set, &status);
        break;}
        break;}
      if (decNumberIsInfinite(rhs)) {   /* rhs Infinity */
      if (decNumberIsInfinite(rhs)) {   /* rhs Infinity */
        Flag rhsneg=rhs->bits&DECNEG;   /* save rhs sign */
        Flag rhsneg=rhs->bits&DECNEG;   /* save rhs sign */
        if (decNumberIsNegative(lhs)    /* lhs<0 */
        if (decNumberIsNegative(lhs)    /* lhs<0 */
         && !decNumberIsZero(lhs))      /* .. */
         && !decNumberIsZero(lhs))      /* .. */
          status|=DEC_Invalid_operation;
          status|=DEC_Invalid_operation;
         else {                         /* lhs >=0 */
         else {                         /* lhs >=0 */
          decNumberZero(&dnOne);        /* set up 1 */
          decNumberZero(&dnOne);        /* set up 1 */
          dnOne.lsu[0]=1;
          dnOne.lsu[0]=1;
          decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */
          decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */
          decNumberZero(res);           /* prepare for 0/1/Infinity */
          decNumberZero(res);           /* prepare for 0/1/Infinity */
          if (decNumberIsNegative(dac)) {    /* lhs<1 */
          if (decNumberIsNegative(dac)) {    /* lhs<1 */
            if (rhsneg) res->bits|=DECINF;   /* +Infinity [else is +0] */
            if (rhsneg) res->bits|=DECINF;   /* +Infinity [else is +0] */
            }
            }
           else if (dac->lsu[0]==0) {          /* lhs=1 */
           else if (dac->lsu[0]==0) {          /* lhs=1 */
            /* 1**Infinity is inexact, so return fully-padded 1.0000 */
            /* 1**Infinity is inexact, so return fully-padded 1.0000 */
            Int shift=set->digits-1;
            Int shift=set->digits-1;
            *res->lsu=1;                     /* was 0, make int 1 */
            *res->lsu=1;                     /* was 0, make int 1 */
            res->digits=decShiftToMost(res->lsu, 1, shift);
            res->digits=decShiftToMost(res->lsu, 1, shift);
            res->exponent=-shift;            /* make 1.0000... */
            res->exponent=-shift;            /* make 1.0000... */
            status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */
            status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */
            }
            }
           else {                            /* lhs>1 */
           else {                            /* lhs>1 */
            if (!rhsneg) res->bits|=DECINF;  /* +Infinity [else is +0] */
            if (!rhsneg) res->bits|=DECINF;  /* +Infinity [else is +0] */
            }
            }
          } /* lhs>=0 */
          } /* lhs>=0 */
        break;}
        break;}
      /* [lhs infinity drops through] */
      /* [lhs infinity drops through] */
      } /* specials */
      } /* specials */
 
 
    /* Original rhs may be an integer that fits and is in range */
    /* Original rhs may be an integer that fits and is in range */
    n=decGetInt(rhs);
    n=decGetInt(rhs);
    if (n!=BADINT) {                    /* it is an integer */
    if (n!=BADINT) {                    /* it is an integer */
      rhsint=1;                         /* record the fact for 1**n */
      rhsint=1;                         /* record the fact for 1**n */
      isoddint=(Flag)n&1;               /* [works even if big] */
      isoddint=(Flag)n&1;               /* [works even if big] */
      if (n!=BIGEVEN && n!=BIGODD)      /* can use integer path? */
      if (n!=BIGEVEN && n!=BIGODD)      /* can use integer path? */
        useint=1;                       /* looks good */
        useint=1;                       /* looks good */
      }
      }
 
 
    if (decNumberIsNegative(lhs)        /* -x .. */
    if (decNumberIsNegative(lhs)        /* -x .. */
      && isoddint) bits=DECNEG;         /* .. to an odd power */
      && isoddint) bits=DECNEG;         /* .. to an odd power */
 
 
    /* handle LHS infinity */
    /* handle LHS infinity */
    if (decNumberIsInfinite(lhs)) {     /* [NaNs already handled] */
    if (decNumberIsInfinite(lhs)) {     /* [NaNs already handled] */
      uByte rbits=rhs->bits;            /* save */
      uByte rbits=rhs->bits;            /* save */
      decNumberZero(res);               /* prepare */
      decNumberZero(res);               /* prepare */
      if (n==0) *res->lsu=1;             /* [-]Inf**0 => 1 */
      if (n==0) *res->lsu=1;             /* [-]Inf**0 => 1 */
       else {
       else {
        /* -Inf**nonint -> error */
        /* -Inf**nonint -> error */
        if (!rhsint && decNumberIsNegative(lhs)) {
        if (!rhsint && decNumberIsNegative(lhs)) {
          status|=DEC_Invalid_operation;     /* -Inf**nonint is error */
          status|=DEC_Invalid_operation;     /* -Inf**nonint is error */
          break;}
          break;}
        if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */
        if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */
        /* [otherwise will be 0 or -0] */
        /* [otherwise will be 0 or -0] */
        res->bits=bits;
        res->bits=bits;
        }
        }
      break;}
      break;}
 
 
    /* similarly handle LHS zero */
    /* similarly handle LHS zero */
    if (decNumberIsZero(lhs)) {
    if (decNumberIsZero(lhs)) {
      if (n==0) {                             /* 0**0 => Error */
      if (n==0) {                             /* 0**0 => Error */
        #if DECSUBSET
        #if DECSUBSET
        if (!set->extended) {                /* [unless subset] */
        if (!set->extended) {                /* [unless subset] */
          decNumberZero(res);
          decNumberZero(res);
          *res->lsu=1;                       /* return 1 */
          *res->lsu=1;                       /* return 1 */
          break;}
          break;}
        #endif
        #endif
        status|=DEC_Invalid_operation;
        status|=DEC_Invalid_operation;
        }
        }
       else {                                /* 0**x */
       else {                                /* 0**x */
        uByte rbits=rhs->bits;               /* save */
        uByte rbits=rhs->bits;               /* save */
        if (rbits & DECNEG) {                /* was a 0**(-n) */
        if (rbits & DECNEG) {                /* was a 0**(-n) */
          #if DECSUBSET
          #if DECSUBSET
          if (!set->extended) {              /* [bad if subset] */
          if (!set->extended) {              /* [bad if subset] */
            status|=DEC_Invalid_operation;
            status|=DEC_Invalid_operation;
            break;}
            break;}
          #endif
          #endif
          bits|=DECINF;
          bits|=DECINF;
          }
          }
        decNumberZero(res);                  /* prepare */
        decNumberZero(res);                  /* prepare */
        /* [otherwise will be 0 or -0] */
        /* [otherwise will be 0 or -0] */
        res->bits=bits;
        res->bits=bits;
        }
        }
      break;}
      break;}
 
 
    /* here both lhs and rhs are finite; rhs==0 is handled in the */
    /* here both lhs and rhs are finite; rhs==0 is handled in the */
    /* integer path.  Next handle the non-integer cases */
    /* integer path.  Next handle the non-integer cases */
    if (!useint) {                      /* non-integral rhs */
    if (!useint) {                      /* non-integral rhs */
      /* any -ve lhs is bad, as is either operand or context out of */
      /* any -ve lhs is bad, as is either operand or context out of */
      /* bounds */
      /* bounds */
      if (decNumberIsNegative(lhs)) {
      if (decNumberIsNegative(lhs)) {
        status|=DEC_Invalid_operation;
        status|=DEC_Invalid_operation;
        break;}
        break;}
      if (decCheckMath(lhs, set, &status)
      if (decCheckMath(lhs, set, &status)
       || decCheckMath(rhs, set, &status)) break; /* variable status */
       || decCheckMath(rhs, set, &status)) break; /* variable status */
 
 
      decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
      decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
      aset.emax=DEC_MAX_MATH;           /* usual bounds */
      aset.emax=DEC_MAX_MATH;           /* usual bounds */
      aset.emin=-DEC_MAX_MATH;          /* .. */
      aset.emin=-DEC_MAX_MATH;          /* .. */
      aset.clamp=0;                      /* and no concrete format */
      aset.clamp=0;                      /* and no concrete format */
 
 
      /* calculate the result using exp(ln(lhs)*rhs), which can */
      /* calculate the result using exp(ln(lhs)*rhs), which can */
      /* all be done into the accumulator, dac.  The precision needed */
      /* all be done into the accumulator, dac.  The precision needed */
      /* is enough to contain the full information in the lhs (which */
      /* is enough to contain the full information in the lhs (which */
      /* is the total digits, including exponent), or the requested */
      /* is the total digits, including exponent), or the requested */
      /* precision, if larger, + 4; 6 is used for the exponent */
      /* precision, if larger, + 4; 6 is used for the exponent */
      /* maximum length, and this is also used when it is shorter */
      /* maximum length, and this is also used when it is shorter */
      /* than the requested digits as it greatly reduces the >0.5 ulp */
      /* than the requested digits as it greatly reduces the >0.5 ulp */
      /* cases at little cost (because Ln doubles digits each */
      /* cases at little cost (because Ln doubles digits each */
      /* iteration so a few extra digits rarely causes an extra */
      /* iteration so a few extra digits rarely causes an extra */
      /* iteration) */
      /* iteration) */
      aset.digits=MAXI(lhs->digits, set->digits)+6+4;
      aset.digits=MAXI(lhs->digits, set->digits)+6+4;
      } /* non-integer rhs */
      } /* non-integer rhs */
 
 
     else { /* rhs is in-range integer */
     else { /* rhs is in-range integer */
      if (n==0) {                        /* x**0 = 1 */
      if (n==0) {                        /* x**0 = 1 */
        /* (0**0 was handled above) */
        /* (0**0 was handled above) */
        decNumberZero(res);             /* result=1 */
        decNumberZero(res);             /* result=1 */
        *res->lsu=1;                    /* .. */
        *res->lsu=1;                    /* .. */
        break;}
        break;}
      /* rhs is a non-zero integer */
      /* rhs is a non-zero integer */
      if (n<0) n=-n;                     /* use abs(n) */
      if (n<0) n=-n;                     /* use abs(n) */
 
 
      aset=*set;                        /* clone the context */
      aset=*set;                        /* clone the context */
      aset.round=DEC_ROUND_HALF_EVEN;   /* internally use balanced */
      aset.round=DEC_ROUND_HALF_EVEN;   /* internally use balanced */
      /* calculate the working DIGITS */
      /* calculate the working DIGITS */
      aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2;
      aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2;
      #if DECSUBSET
      #if DECSUBSET
      if (!set->extended) aset.digits--;     /* use classic precision */
      if (!set->extended) aset.digits--;     /* use classic precision */
      #endif
      #endif
      /* it's an error if this is more than can be handled */
      /* it's an error if this is more than can be handled */
      if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;}
      if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;}
      } /* integer path */
      } /* integer path */
 
 
    /* aset.digits is the count of digits for the accumulator needed */
    /* aset.digits is the count of digits for the accumulator needed */
    /* if accumulator is too long for local storage, then allocate */
    /* if accumulator is too long for local storage, then allocate */
    needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit);
    needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit);
    /* [needbytes also used below if 1/lhs needed] */
    /* [needbytes also used below if 1/lhs needed] */
    if (needbytes>sizeof(dacbuff)) {
    if (needbytes>sizeof(dacbuff)) {
      allocdac=(decNumber *)malloc(needbytes);
      allocdac=(decNumber *)malloc(needbytes);
      if (allocdac==NULL) {   /* hopeless -- abandon */
      if (allocdac==NULL) {   /* hopeless -- abandon */
        status|=DEC_Insufficient_storage;
        status|=DEC_Insufficient_storage;
        break;}
        break;}
      dac=allocdac;           /* use the allocated space */
      dac=allocdac;           /* use the allocated space */
      }
      }
    /* here, aset is set up and accumulator is ready for use */
    /* here, aset is set up and accumulator is ready for use */
 
 
    if (!useint) {                           /* non-integral rhs */
    if (!useint) {                           /* non-integral rhs */
      /* x ** y; special-case x=1 here as it will otherwise always */
      /* x ** y; special-case x=1 here as it will otherwise always */
      /* reduce to integer 1; decLnOp has a fastpath which detects */
      /* reduce to integer 1; decLnOp has a fastpath which detects */
      /* the case of x=1 */
      /* the case of x=1 */
      decLnOp(dac, lhs, &aset, &status);     /* dac=ln(lhs) */
      decLnOp(dac, lhs, &aset, &status);     /* dac=ln(lhs) */
      /* [no error possible, as lhs 0 already handled] */
      /* [no error possible, as lhs 0 already handled] */
      if (ISZERO(dac)) {                     /* x==1, 1.0, etc. */
      if (ISZERO(dac)) {                     /* x==1, 1.0, etc. */
        /* need to return fully-padded 1.0000 etc., but rhsint->1 */
        /* need to return fully-padded 1.0000 etc., but rhsint->1 */
        *dac->lsu=1;                         /* was 0, make int 1 */
        *dac->lsu=1;                         /* was 0, make int 1 */
        if (!rhsint) {                       /* add padding */
        if (!rhsint) {                       /* add padding */
          Int shift=set->digits-1;
          Int shift=set->digits-1;
          dac->digits=decShiftToMost(dac->lsu, 1, shift);
          dac->digits=decShiftToMost(dac->lsu, 1, shift);
          dac->exponent=-shift;              /* make 1.0000... */
          dac->exponent=-shift;              /* make 1.0000... */
          status|=DEC_Inexact|DEC_Rounded;   /* deemed inexact */
          status|=DEC_Inexact|DEC_Rounded;   /* deemed inexact */
          }
          }
        }
        }
       else {
       else {
        decMultiplyOp(dac, dac, rhs, &aset, &status);  /* dac=dac*rhs */
        decMultiplyOp(dac, dac, rhs, &aset, &status);  /* dac=dac*rhs */
        decExpOp(dac, dac, &aset, &status);            /* dac=exp(dac) */
        decExpOp(dac, dac, &aset, &status);            /* dac=exp(dac) */
        }
        }
      /* and drop through for final rounding */
      /* and drop through for final rounding */
      } /* non-integer rhs */
      } /* non-integer rhs */
 
 
     else {                             /* carry on with integer */
     else {                             /* carry on with integer */
      decNumberZero(dac);               /* acc=1 */
      decNumberZero(dac);               /* acc=1 */
      *dac->lsu=1;                      /* .. */
      *dac->lsu=1;                      /* .. */
 
 
      /* if a negative power the constant 1 is needed, and if not subset */
      /* if a negative power the constant 1 is needed, and if not subset */
      /* invert the lhs now rather than inverting the result later */
      /* invert the lhs now rather than inverting the result later */
      if (decNumberIsNegative(rhs)) {   /* was a **-n [hence digits>0] */
      if (decNumberIsNegative(rhs)) {   /* was a **-n [hence digits>0] */
        decNumber *inv=invbuff;         /* asssume use fixed buffer */
        decNumber *inv=invbuff;         /* asssume use fixed buffer */
        decNumberCopy(&dnOne, dac);     /* dnOne=1;  [needed now or later] */
        decNumberCopy(&dnOne, dac);     /* dnOne=1;  [needed now or later] */
        #if DECSUBSET
        #if DECSUBSET
        if (set->extended) {            /* need to calculate 1/lhs */
        if (set->extended) {            /* need to calculate 1/lhs */
        #endif
        #endif
          /* divide lhs into 1, putting result in dac [dac=1/dac] */
          /* divide lhs into 1, putting result in dac [dac=1/dac] */
          decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status);
          decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status);
          /* now locate or allocate space for the inverted lhs */
          /* now locate or allocate space for the inverted lhs */
          if (needbytes>sizeof(invbuff)) {
          if (needbytes>sizeof(invbuff)) {
            allocinv=(decNumber *)malloc(needbytes);
            allocinv=(decNumber *)malloc(needbytes);
            if (allocinv==NULL) {       /* hopeless -- abandon */
            if (allocinv==NULL) {       /* hopeless -- abandon */
              status|=DEC_Insufficient_storage;
              status|=DEC_Insufficient_storage;
              break;}
              break;}
            inv=allocinv;               /* use the allocated space */
            inv=allocinv;               /* use the allocated space */
            }
            }
          /* [inv now points to big-enough buffer or allocated storage] */
          /* [inv now points to big-enough buffer or allocated storage] */
          decNumberCopy(inv, dac);      /* copy the 1/lhs */
          decNumberCopy(inv, dac);      /* copy the 1/lhs */
          decNumberCopy(dac, &dnOne);   /* restore acc=1 */
          decNumberCopy(dac, &dnOne);   /* restore acc=1 */
          lhs=inv;                      /* .. and go forward with new lhs */
          lhs=inv;                      /* .. and go forward with new lhs */
        #if DECSUBSET
        #if DECSUBSET
          }
          }
        #endif
        #endif
        }
        }
 
 
      /* Raise-to-the-power loop... */
      /* Raise-to-the-power loop... */
      seenbit=0;            /* set once a 1-bit is encountered */
      seenbit=0;            /* set once a 1-bit is encountered */
      for (i=1;;i++){              /* for each bit [top bit ignored] */
      for (i=1;;i++){              /* for each bit [top bit ignored] */
        /* abandon if had overflow or terminal underflow */
        /* abandon if had overflow or terminal underflow */
        if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
        if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
          if (status&DEC_Overflow || ISZERO(dac)) break;
          if (status&DEC_Overflow || ISZERO(dac)) break;
          }
          }
        /* [the following two lines revealed an optimizer bug in a C++ */
        /* [the following two lines revealed an optimizer bug in a C++ */
        /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */
        /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */
        n=n<<1;                    /* move next bit to testable position */
        n=n<<1;                    /* move next bit to testable position */
        if (n<0) {                  /* top bit is set */
        if (n<0) {                  /* top bit is set */
          seenbit=1;               /* OK, significant bit seen */
          seenbit=1;               /* OK, significant bit seen */
          decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */
          decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */
          }
          }
        if (i==31) break;          /* that was the last bit */
        if (i==31) break;          /* that was the last bit */
        if (!seenbit) continue;    /* no need to square 1 */
        if (!seenbit) continue;    /* no need to square 1 */
        decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */
        decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */
        } /*i*/ /* 32 bits */
        } /*i*/ /* 32 bits */
 
 
      /* complete internal overflow or underflow processing */
      /* complete internal overflow or underflow processing */
      if (status & (DEC_Overflow|DEC_Underflow)) {
      if (status & (DEC_Overflow|DEC_Underflow)) {
        #if DECSUBSET
        #if DECSUBSET
        /* If subset, and power was negative, reverse the kind of -erflow */
        /* If subset, and power was negative, reverse the kind of -erflow */
        /* [1/x not yet done] */
        /* [1/x not yet done] */
        if (!set->extended && decNumberIsNegative(rhs)) {
        if (!set->extended && decNumberIsNegative(rhs)) {
          if (status & DEC_Overflow)
          if (status & DEC_Overflow)
            status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal;
            status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal;
           else { /* trickier -- Underflow may or may not be set */
           else { /* trickier -- Underflow may or may not be set */
            status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */
            status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */
            status|=DEC_Overflow;
            status|=DEC_Overflow;
            }
            }
          }
          }
        #endif
        #endif
        dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */
        dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */
        /* round subnormals [to set.digits rather than aset.digits] */
        /* round subnormals [to set.digits rather than aset.digits] */
        /* or set overflow result similarly as required */
        /* or set overflow result similarly as required */
        decFinalize(dac, set, &residue, &status);
        decFinalize(dac, set, &residue, &status);
        decNumberCopy(res, dac);   /* copy to result (is now OK length) */
        decNumberCopy(res, dac);   /* copy to result (is now OK length) */
        break;
        break;
        }
        }
 
 
      #if DECSUBSET
      #if DECSUBSET
      if (!set->extended &&                  /* subset math */
      if (!set->extended &&                  /* subset math */
          decNumberIsNegative(rhs)) {        /* was a **-n [hence digits>0] */
          decNumberIsNegative(rhs)) {        /* was a **-n [hence digits>0] */
        /* so divide result into 1 [dac=1/dac] */
        /* so divide result into 1 [dac=1/dac] */
        decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status);
        decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status);
        }
        }
      #endif
      #endif
      } /* rhs integer path */
      } /* rhs integer path */
 
 
    /* reduce result to the requested length and copy to result */
    /* reduce result to the requested length and copy to result */
    decCopyFit(res, dac, set, &residue, &status);
    decCopyFit(res, dac, set, &residue, &status);
    decFinish(res, set, &residue, &status);  /* final cleanup */
    decFinish(res, set, &residue, &status);  /* final cleanup */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) decTrim(res, set, 0, &dropped); /* trailing zeros */
    if (!set->extended) decTrim(res, set, 0, &dropped); /* trailing zeros */
    #endif
    #endif
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  if (allocdac!=NULL) free(allocdac);   /* drop any storage used */
  if (allocdac!=NULL) free(allocdac);   /* drop any storage used */
  if (allocinv!=NULL) free(allocinv);   /* .. */
  if (allocinv!=NULL) free(allocinv);   /* .. */
  #if DECSUBSET
  #if DECSUBSET
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  if (allocrhs!=NULL) free(allocrhs);   /* .. */
  if (allocrhs!=NULL) free(allocrhs);   /* .. */
  #endif
  #endif
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberPower */
  } /* decNumberPower */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberQuantize -- force exponent to requested value             */
/* decNumberQuantize -- force exponent to requested value             */
/*                                                                    */
/*                                                                    */
/*   This computes C = op(A, B), where op adjusts the coefficient     */
/*   This computes C = op(A, B), where op adjusts the coefficient     */
/*   of C (by rounding or shifting) such that the exponent (-scale)   */
/*   of C (by rounding or shifting) such that the exponent (-scale)   */
/*   of C has exponent of B.  The numerical value of C will equal A,  */
/*   of C has exponent of B.  The numerical value of C will equal A,  */
/*   except for the effects of any rounding that occurred.            */
/*   except for the effects of any rounding that occurred.            */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A or B                           */
/*   res is C, the result.  C may be A or B                           */
/*   lhs is A, the number to adjust                                   */
/*   lhs is A, the number to adjust                                   */
/*   rhs is B, the number with exponent to match                      */
/*   rhs is B, the number with exponent to match                      */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Unless there is an error or the result is infinite, the exponent   */
/* Unless there is an error or the result is infinite, the exponent   */
/* after the operation is guaranteed to be equal to that of B.        */
/* after the operation is guaranteed to be equal to that of B.        */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs,
decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs,
                              const decNumber *rhs, decContext *set) {
                              const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decQuantizeOp(res, lhs, rhs, set, 1, &status);
  decQuantizeOp(res, lhs, rhs, set, 1, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberQuantize */
  } /* decNumberQuantize */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberReduce -- remove trailing zeros                           */
/* decNumberReduce -- remove trailing zeros                           */
/*                                                                    */
/*                                                                    */
/*   This computes C = 0 + A, and normalizes the result               */
/*   This computes C = 0 + A, and normalizes the result               */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* Previously known as Normalize */
/* Previously known as Normalize */
decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs,
decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs,
                               decContext *set) {
                               decContext *set) {
  return decNumberReduce(res, rhs, set);
  return decNumberReduce(res, rhs, set);
  } /* decNumberNormalize */
  } /* decNumberNormalize */
 
 
decNumber * decNumberReduce(decNumber *res, const decNumber *rhs,
decNumber * decNumberReduce(decNumber *res, const decNumber *rhs,
                            decContext *set) {
                            decContext *set) {
  #if DECSUBSET
  #if DECSUBSET
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  #endif
  #endif
  uInt status=0;            /* as usual */
  uInt status=0;            /* as usual */
  Int  residue=0;                   /* as usual */
  Int  residue=0;                   /* as usual */
  Int  dropped;                    /* work */
  Int  dropped;                    /* work */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                             /* protect allocated storage */
  do {                             /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operand and set lostDigits status, as needed */
      /* reduce operand and set lostDigits status, as needed */
      if (rhs->digits>set->digits) {
      if (rhs->digits>set->digits) {
        allocrhs=decRoundOperand(rhs, set, &status);
        allocrhs=decRoundOperand(rhs, set, &status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    /* [following code does not require input rounding] */
    /* [following code does not require input rounding] */
 
 
    /* Infinities copy through; NaNs need usual treatment */
    /* Infinities copy through; NaNs need usual treatment */
    if (decNumberIsNaN(rhs)) {
    if (decNumberIsNaN(rhs)) {
      decNaNs(res, rhs, NULL, set, &status);
      decNaNs(res, rhs, NULL, set, &status);
      break;
      break;
      }
      }
 
 
    /* reduce result to the requested length and copy to result */
    /* reduce result to the requested length and copy to result */
    decCopyFit(res, rhs, set, &residue, &status); /* copy & round */
    decCopyFit(res, rhs, set, &residue, &status); /* copy & round */
    decFinish(res, set, &residue, &status);       /* cleanup/set flags */
    decFinish(res, set, &residue, &status);       /* cleanup/set flags */
    decTrim(res, set, 1, &dropped);               /* normalize in place */
    decTrim(res, set, 1, &dropped);               /* normalize in place */
    } while(0);                               /* end protected */
    } while(0);                               /* end protected */
 
 
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs !=NULL) free(allocrhs);       /* .. */
  if (allocrhs !=NULL) free(allocrhs);       /* .. */
  #endif
  #endif
  if (status!=0) decStatus(res, status, set);/* then report status */
  if (status!=0) decStatus(res, status, set);/* then report status */
  return res;
  return res;
  } /* decNumberReduce */
  } /* decNumberReduce */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberRescale -- force exponent to requested value              */
/* decNumberRescale -- force exponent to requested value              */
/*                                                                    */
/*                                                                    */
/*   This computes C = op(A, B), where op adjusts the coefficient     */
/*   This computes C = op(A, B), where op adjusts the coefficient     */
/*   of C (by rounding or shifting) such that the exponent (-scale)   */
/*   of C (by rounding or shifting) such that the exponent (-scale)   */
/*   of C has the value B.  The numerical value of C will equal A,    */
/*   of C has the value B.  The numerical value of C will equal A,    */
/*   except for the effects of any rounding that occurred.            */
/*   except for the effects of any rounding that occurred.            */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A or B                           */
/*   res is C, the result.  C may be A or B                           */
/*   lhs is A, the number to adjust                                   */
/*   lhs is A, the number to adjust                                   */
/*   rhs is B, the requested exponent                                 */
/*   rhs is B, the requested exponent                                 */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Unless there is an error or the result is infinite, the exponent   */
/* Unless there is an error or the result is infinite, the exponent   */
/* after the operation is guaranteed to be equal to B.                */
/* after the operation is guaranteed to be equal to B.                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberRescale(decNumber *res, const decNumber *lhs,
decNumber * decNumberRescale(decNumber *res, const decNumber *lhs,
                             const decNumber *rhs, decContext *set) {
                             const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decQuantizeOp(res, lhs, rhs, set, 0, &status);
  decQuantizeOp(res, lhs, rhs, set, 0, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberRescale */
  } /* decNumberRescale */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberRemainder -- divide and return remainder                  */
/* decNumberRemainder -- divide and return remainder                  */
/*                                                                    */
/*                                                                    */
/*   This computes C = A % B                                          */
/*   This computes C = A % B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X%X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X%X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs,
decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs,
                               const decNumber *rhs, decContext *set) {
                               const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decDivideOp(res, lhs, rhs, set, REMAINDER, &status);
  decDivideOp(res, lhs, rhs, set, REMAINDER, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberRemainder */
  } /* decNumberRemainder */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberRemainderNear -- divide and return remainder from nearest */
/* decNumberRemainderNear -- divide and return remainder from nearest */
/*                                                                    */
/*                                                                    */
/*   This computes C = A % B, where % is the IEEE remainder operator  */
/*   This computes C = A % B, where % is the IEEE remainder operator  */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X%X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X%X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs,
decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs,
                                   const decNumber *rhs, decContext *set) {
                                   const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
  decDivideOp(res, lhs, rhs, set, REMNEAR, &status);
  decDivideOp(res, lhs, rhs, set, REMNEAR, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberRemainderNear */
  } /* decNumberRemainderNear */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberRotate -- rotate the coefficient of a Number left/right   */
/* decNumberRotate -- rotate the coefficient of a Number left/right   */
/*                                                                    */
/*                                                                    */
/*   This computes C = A rot B  (in base ten and rotating set->digits */
/*   This computes C = A rot B  (in base ten and rotating set->digits */
/*   digits).                                                         */
/*   digits).                                                         */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=XrotX)       */
/*   res is C, the result.  C may be A and/or B (e.g., X=XrotX)       */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B, the number of digits to rotate (-ve to right)          */
/*   rhs is B, the number of digits to rotate (-ve to right)          */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* The digits of the coefficient of A are rotated to the left (if B   */
/* The digits of the coefficient of A are rotated to the left (if B   */
/* is positive) or to the right (if B is negative) without adjusting  */
/* is positive) or to the right (if B is negative) without adjusting  */
/* the exponent or the sign of A.  If lhs->digits is less than        */
/* the exponent or the sign of A.  If lhs->digits is less than        */
/* set->digits the coefficient is padded with zeros on the left       */
/* set->digits the coefficient is padded with zeros on the left       */
/* before the rotate.  Any leading zeros in the result are removed    */
/* before the rotate.  Any leading zeros in the result are removed    */
/* as usual.                                                          */
/* as usual.                                                          */
/*                                                                    */
/*                                                                    */
/* B must be an integer (q=0) and in the range -set->digits through   */
/* B must be an integer (q=0) and in the range -set->digits through   */
/* +set->digits.                                                      */
/* +set->digits.                                                      */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* NaNs are propagated as usual.  Infinities are unaffected (but      */
/* NaNs are propagated as usual.  Infinities are unaffected (but      */
/* B must be valid).  No status is set unless B is invalid or an      */
/* B must be valid).  No status is set unless B is invalid or an      */
/* operand is an sNaN.                                                */
/* operand is an sNaN.                                                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberRotate(decNumber *res, const decNumber *lhs,
decNumber * decNumberRotate(decNumber *res, const decNumber *lhs,
                           const decNumber *rhs, decContext *set) {
                           const decNumber *rhs, decContext *set) {
  uInt status=0;       /* accumulator */
  uInt status=0;       /* accumulator */
  Int  rotate;                /* rhs as an Int */
  Int  rotate;                /* rhs as an Int */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  /* NaNs propagate as normal */
  /* NaNs propagate as normal */
  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
    decNaNs(res, lhs, rhs, set, &status);
    decNaNs(res, lhs, rhs, set, &status);
   /* rhs must be an integer */
   /* rhs must be an integer */
   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
    status=DEC_Invalid_operation;
    status=DEC_Invalid_operation;
   else { /* both numeric, rhs is an integer */
   else { /* both numeric, rhs is an integer */
    rotate=decGetInt(rhs);                   /* [cannot fail] */
    rotate=decGetInt(rhs);                   /* [cannot fail] */
    if (rotate==BADINT                       /* something bad .. */
    if (rotate==BADINT                       /* something bad .. */
     || rotate==BIGODD || rotate==BIGEVEN    /* .. very big .. */
     || rotate==BIGODD || rotate==BIGEVEN    /* .. very big .. */
     || abs(rotate)>set->digits)             /* .. or out of range */
     || abs(rotate)>set->digits)             /* .. or out of range */
      status=DEC_Invalid_operation;
      status=DEC_Invalid_operation;
     else {                                  /* rhs is OK */
     else {                                  /* rhs is OK */
      decNumberCopy(res, lhs);
      decNumberCopy(res, lhs);
      /* convert -ve rotate to equivalent positive rotation */
      /* convert -ve rotate to equivalent positive rotation */
      if (rotate<0) rotate=set->digits+rotate;
      if (rotate<0) rotate=set->digits+rotate;
      if (rotate!=0 && rotate!=set->digits   /* zero or full rotation */
      if (rotate!=0 && rotate!=set->digits   /* zero or full rotation */
       && !decNumberIsInfinite(res)) {       /* lhs was infinite */
       && !decNumberIsInfinite(res)) {       /* lhs was infinite */
        /* left-rotate to do; 0 < rotate < set->digits */
        /* left-rotate to do; 0 < rotate < set->digits */
        uInt units, shift;                   /* work */
        uInt units, shift;                   /* work */
        uInt msudigits;                      /* digits in result msu */
        uInt msudigits;                      /* digits in result msu */
        Unit *msu=res->lsu+D2U(res->digits)-1;    /* current msu */
        Unit *msu=res->lsu+D2U(res->digits)-1;    /* current msu */
        Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */
        Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */
        for (msu++; msu<=msumax; msu++) *msu=0;    /* ensure high units=0 */
        for (msu++; msu<=msumax; msu++) *msu=0;    /* ensure high units=0 */
        res->digits=set->digits;                  /* now full-length */
        res->digits=set->digits;                  /* now full-length */
        msudigits=MSUDIGITS(res->digits);         /* actual digits in msu */
        msudigits=MSUDIGITS(res->digits);         /* actual digits in msu */
 
 
        /* rotation here is done in-place, in three steps */
        /* rotation here is done in-place, in three steps */
        /* 1. shift all to least up to one unit to unit-align final */
        /* 1. shift all to least up to one unit to unit-align final */
        /*    lsd [any digits shifted out are rotated to the left, */
        /*    lsd [any digits shifted out are rotated to the left, */
        /*    abutted to the original msd (which may require split)] */
        /*    abutted to the original msd (which may require split)] */
        /* */
        /* */
        /*    [if there are no whole units left to rotate, the */
        /*    [if there are no whole units left to rotate, the */
        /*    rotation is now complete] */
        /*    rotation is now complete] */
        /* */
        /* */
        /* 2. shift to least, from below the split point only, so that */
        /* 2. shift to least, from below the split point only, so that */
        /*    the final msd is in the right place in its Unit [any */
        /*    the final msd is in the right place in its Unit [any */
        /*    digits shifted out will fit exactly in the current msu, */
        /*    digits shifted out will fit exactly in the current msu, */
        /*    left aligned, no split required] */
        /*    left aligned, no split required] */
        /* */
        /* */
        /* 3. rotate all the units by reversing left part, right */
        /* 3. rotate all the units by reversing left part, right */
        /*    part, and then whole */
        /*    part, and then whole */
        /* */
        /* */
        /* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */
        /* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */
        /* */
        /* */
        /*   start: 00a bcd efg hij klm npq */
        /*   start: 00a bcd efg hij klm npq */
        /* */
        /* */
        /*      1a  000 0ab cde fgh|ijk lmn [pq saved] */
        /*      1a  000 0ab cde fgh|ijk lmn [pq saved] */
        /*      1b  00p qab cde fgh|ijk lmn */
        /*      1b  00p qab cde fgh|ijk lmn */
        /* */
        /* */
        /*      2a  00p qab cde fgh|00i jkl [mn saved] */
        /*      2a  00p qab cde fgh|00i jkl [mn saved] */
        /*      2b  mnp qab cde fgh|00i jkl */
        /*      2b  mnp qab cde fgh|00i jkl */
        /* */
        /* */
        /*      3a  fgh cde qab mnp|00i jkl */
        /*      3a  fgh cde qab mnp|00i jkl */
        /*      3b  fgh cde qab mnp|jkl 00i */
        /*      3b  fgh cde qab mnp|jkl 00i */
        /*      3c  00i jkl mnp qab cde fgh */
        /*      3c  00i jkl mnp qab cde fgh */
 
 
        /* Step 1: amount to shift is the partial right-rotate count */
        /* Step 1: amount to shift is the partial right-rotate count */
        rotate=set->digits-rotate;      /* make it right-rotate */
        rotate=set->digits-rotate;      /* make it right-rotate */
        units=rotate/DECDPUN;           /* whole units to rotate */
        units=rotate/DECDPUN;           /* whole units to rotate */
        shift=rotate%DECDPUN;           /* left-over digits count */
        shift=rotate%DECDPUN;           /* left-over digits count */
        if (shift>0) {                   /* not an exact number of units */
        if (shift>0) {                   /* not an exact number of units */
          uInt save=res->lsu[0]%powers[shift];     /* save low digit(s) */
          uInt save=res->lsu[0]%powers[shift];     /* save low digit(s) */
          decShiftToLeast(res->lsu, D2U(res->digits), shift);
          decShiftToLeast(res->lsu, D2U(res->digits), shift);
          if (shift>msudigits) {        /* msumax-1 needs >0 digits */
          if (shift>msudigits) {        /* msumax-1 needs >0 digits */
            uInt rem=save%powers[shift-msudigits];/* split save */
            uInt rem=save%powers[shift-msudigits];/* split save */
            *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */
            *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */
            *(msumax-1)=*(msumax-1)
            *(msumax-1)=*(msumax-1)
                       +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */
                       +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */
            }
            }
           else { /* all fits in msumax */
           else { /* all fits in msumax */
            *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */
            *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */
            }
            }
          } /* digits shift needed */
          } /* digits shift needed */
 
 
        /* If whole units to rotate... */
        /* If whole units to rotate... */
        if (units>0) {                   /* some to do */
        if (units>0) {                   /* some to do */
          /* Step 2: the units to touch are the whole ones in rotate, */
          /* Step 2: the units to touch are the whole ones in rotate, */
          /*   if any, and the shift is DECDPUN-msudigits (which may be */
          /*   if any, and the shift is DECDPUN-msudigits (which may be */
          /*   0, again) */
          /*   0, again) */
          shift=DECDPUN-msudigits;
          shift=DECDPUN-msudigits;
          if (shift>0) {         /* not an exact number of units */
          if (shift>0) {         /* not an exact number of units */
            uInt save=res->lsu[0]%powers[shift];  /* save low digit(s) */
            uInt save=res->lsu[0]%powers[shift];  /* save low digit(s) */
            decShiftToLeast(res->lsu, units, shift);
            decShiftToLeast(res->lsu, units, shift);
            *msumax=*msumax+(Unit)(save*powers[msudigits]);
            *msumax=*msumax+(Unit)(save*powers[msudigits]);
            } /* partial shift needed */
            } /* partial shift needed */
 
 
          /* Step 3: rotate the units array using triple reverse */
          /* Step 3: rotate the units array using triple reverse */
          /* (reversing is easy and fast) */
          /* (reversing is easy and fast) */
          decReverse(res->lsu+units, msumax);     /* left part */
          decReverse(res->lsu+units, msumax);     /* left part */
          decReverse(res->lsu, res->lsu+units-1); /* right part */
          decReverse(res->lsu, res->lsu+units-1); /* right part */
          decReverse(res->lsu, msumax);           /* whole */
          decReverse(res->lsu, msumax);           /* whole */
          } /* whole units to rotate */
          } /* whole units to rotate */
        /* the rotation may have left an undetermined number of zeros */
        /* the rotation may have left an undetermined number of zeros */
        /* on the left, so true length needs to be calculated */
        /* on the left, so true length needs to be calculated */
        res->digits=decGetDigits(res->lsu, msumax-res->lsu+1);
        res->digits=decGetDigits(res->lsu, msumax-res->lsu+1);
        } /* rotate needed */
        } /* rotate needed */
      } /* rhs OK */
      } /* rhs OK */
    } /* numerics */
    } /* numerics */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberRotate */
  } /* decNumberRotate */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberSameQuantum -- test for equal exponents                   */
/* decNumberSameQuantum -- test for equal exponents                   */
/*                                                                    */
/*                                                                    */
/*   res is the result number, which will contain either 0 or 1       */
/*   res is the result number, which will contain either 0 or 1       */
/*   lhs is a number to test                                          */
/*   lhs is a number to test                                          */
/*   rhs is the second (usually a pattern)                            */
/*   rhs is the second (usually a pattern)                            */
/*                                                                    */
/*                                                                    */
/* No errors are possible and no context is needed.                   */
/* No errors are possible and no context is needed.                   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs,
decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs,
                                 const decNumber *rhs) {
                                 const decNumber *rhs) {
  Unit ret=0;                       /* return value */
  Unit ret=0;                       /* return value */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res;
  if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res;
  #endif
  #endif
 
 
  if (SPECIALARGS) {
  if (SPECIALARGS) {
    if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1;
    if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1;
     else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1;
     else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1;
     /* [anything else with a special gives 0] */
     /* [anything else with a special gives 0] */
    }
    }
   else if (lhs->exponent==rhs->exponent) ret=1;
   else if (lhs->exponent==rhs->exponent) ret=1;
 
 
  decNumberZero(res);              /* OK to overwrite an operand now */
  decNumberZero(res);              /* OK to overwrite an operand now */
  *res->lsu=ret;
  *res->lsu=ret;
  return res;
  return res;
  } /* decNumberSameQuantum */
  } /* decNumberSameQuantum */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberScaleB -- multiply by a power of 10                       */
/* decNumberScaleB -- multiply by a power of 10                       */
/*                                                                    */
/*                                                                    */
/* This computes C = A x 10**B where B is an integer (q=0) with       */
/* This computes C = A x 10**B where B is an integer (q=0) with       */
/* maximum magnitude 2*(emax+digits)                                  */
/* maximum magnitude 2*(emax+digits)                                  */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A or B                           */
/*   res is C, the result.  C may be A or B                           */
/*   lhs is A, the number to adjust                                   */
/*   lhs is A, the number to adjust                                   */
/*   rhs is B, the requested power of ten to use                      */
/*   rhs is B, the requested power of ten to use                      */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* The result may underflow or overflow.                              */
/* The result may underflow or overflow.                              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberScaleB(decNumber *res, const decNumber *lhs,
decNumber * decNumberScaleB(decNumber *res, const decNumber *lhs,
                            const decNumber *rhs, decContext *set) {
                            const decNumber *rhs, decContext *set) {
  Int  reqexp;                /* requested exponent change [B] */
  Int  reqexp;                /* requested exponent change [B] */
  uInt status=0;       /* accumulator */
  uInt status=0;       /* accumulator */
  Int  residue;               /* work */
  Int  residue;               /* work */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  /* Handle special values except lhs infinite */
  /* Handle special values except lhs infinite */
  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
    decNaNs(res, lhs, rhs, set, &status);
    decNaNs(res, lhs, rhs, set, &status);
    /* rhs must be an integer */
    /* rhs must be an integer */
   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
    status=DEC_Invalid_operation;
    status=DEC_Invalid_operation;
   else {
   else {
    /* lhs is a number; rhs is a finite with q==0 */
    /* lhs is a number; rhs is a finite with q==0 */
    reqexp=decGetInt(rhs);                   /* [cannot fail] */
    reqexp=decGetInt(rhs);                   /* [cannot fail] */
    if (reqexp==BADINT                       /* something bad .. */
    if (reqexp==BADINT                       /* something bad .. */
     || reqexp==BIGODD || reqexp==BIGEVEN    /* .. very big .. */
     || reqexp==BIGODD || reqexp==BIGEVEN    /* .. very big .. */
     || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */
     || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */
      status=DEC_Invalid_operation;
      status=DEC_Invalid_operation;
     else {                                  /* rhs is OK */
     else {                                  /* rhs is OK */
      decNumberCopy(res, lhs);               /* all done if infinite lhs */
      decNumberCopy(res, lhs);               /* all done if infinite lhs */
      if (!decNumberIsInfinite(res)) {       /* prepare to scale */
      if (!decNumberIsInfinite(res)) {       /* prepare to scale */
        res->exponent+=reqexp;               /* adjust the exponent */
        res->exponent+=reqexp;               /* adjust the exponent */
        residue=0;
        residue=0;
        decFinalize(res, set, &residue, &status); /* .. and check */
        decFinalize(res, set, &residue, &status); /* .. and check */
        } /* finite LHS */
        } /* finite LHS */
      } /* rhs OK */
      } /* rhs OK */
    } /* rhs finite */
    } /* rhs finite */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberScaleB */
  } /* decNumberScaleB */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberShift -- shift the coefficient of a Number left or right  */
/* decNumberShift -- shift the coefficient of a Number left or right  */
/*                                                                    */
/*                                                                    */
/*   This computes C = A << B or C = A >> -B  (in base ten).          */
/*   This computes C = A << B or C = A >> -B  (in base ten).          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X<<X)        */
/*   res is C, the result.  C may be A and/or B (e.g., X=X<<X)        */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B, the number of digits to shift (-ve to right)           */
/*   rhs is B, the number of digits to shift (-ve to right)           */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* The digits of the coefficient of A are shifted to the left (if B   */
/* The digits of the coefficient of A are shifted to the left (if B   */
/* is positive) or to the right (if B is negative) without adjusting  */
/* is positive) or to the right (if B is negative) without adjusting  */
/* the exponent or the sign of A.                                     */
/* the exponent or the sign of A.                                     */
/*                                                                    */
/*                                                                    */
/* B must be an integer (q=0) and in the range -set->digits through   */
/* B must be an integer (q=0) and in the range -set->digits through   */
/* +set->digits.                                                      */
/* +set->digits.                                                      */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* NaNs are propagated as usual.  Infinities are unaffected (but      */
/* NaNs are propagated as usual.  Infinities are unaffected (but      */
/* B must be valid).  No status is set unless B is invalid or an      */
/* B must be valid).  No status is set unless B is invalid or an      */
/* operand is an sNaN.                                                */
/* operand is an sNaN.                                                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberShift(decNumber *res, const decNumber *lhs,
decNumber * decNumberShift(decNumber *res, const decNumber *lhs,
                           const decNumber *rhs, decContext *set) {
                           const decNumber *rhs, decContext *set) {
  uInt status=0;       /* accumulator */
  uInt status=0;       /* accumulator */
  Int  shift;                 /* rhs as an Int */
  Int  shift;                 /* rhs as an Int */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  /* NaNs propagate as normal */
  /* NaNs propagate as normal */
  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
    decNaNs(res, lhs, rhs, set, &status);
    decNaNs(res, lhs, rhs, set, &status);
   /* rhs must be an integer */
   /* rhs must be an integer */
   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
    status=DEC_Invalid_operation;
    status=DEC_Invalid_operation;
   else { /* both numeric, rhs is an integer */
   else { /* both numeric, rhs is an integer */
    shift=decGetInt(rhs);                    /* [cannot fail] */
    shift=decGetInt(rhs);                    /* [cannot fail] */
    if (shift==BADINT                        /* something bad .. */
    if (shift==BADINT                        /* something bad .. */
     || shift==BIGODD || shift==BIGEVEN      /* .. very big .. */
     || shift==BIGODD || shift==BIGEVEN      /* .. very big .. */
     || abs(shift)>set->digits)              /* .. or out of range */
     || abs(shift)>set->digits)              /* .. or out of range */
      status=DEC_Invalid_operation;
      status=DEC_Invalid_operation;
     else {                                  /* rhs is OK */
     else {                                  /* rhs is OK */
      decNumberCopy(res, lhs);
      decNumberCopy(res, lhs);
      if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */
      if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */
        if (shift>0) {                        /* to left */
        if (shift>0) {                        /* to left */
          if (shift==set->digits) {          /* removing all */
          if (shift==set->digits) {          /* removing all */
            *res->lsu=0;              /* so place 0 */
            *res->lsu=0;              /* so place 0 */
            res->digits=1;                   /* .. */
            res->digits=1;                   /* .. */
            }
            }
           else {                            /* */
           else {                            /* */
            /* first remove leading digits if necessary */
            /* first remove leading digits if necessary */
            if (res->digits+shift>set->digits) {
            if (res->digits+shift>set->digits) {
              decDecap(res, res->digits+shift-set->digits);
              decDecap(res, res->digits+shift-set->digits);
              /* that updated res->digits; may have gone to 1 (for a */
              /* that updated res->digits; may have gone to 1 (for a */
              /* single digit or for zero */
              /* single digit or for zero */
              }
              }
            if (res->digits>1 || *res->lsu)  /* if non-zero.. */
            if (res->digits>1 || *res->lsu)  /* if non-zero.. */
              res->digits=decShiftToMost(res->lsu, res->digits, shift);
              res->digits=decShiftToMost(res->lsu, res->digits, shift);
            } /* partial left */
            } /* partial left */
          } /* left */
          } /* left */
         else { /* to right */
         else { /* to right */
          if (-shift>=res->digits) {         /* discarding all */
          if (-shift>=res->digits) {         /* discarding all */
            *res->lsu=0;              /* so place 0 */
            *res->lsu=0;              /* so place 0 */
            res->digits=1;                   /* .. */
            res->digits=1;                   /* .. */
            }
            }
           else {
           else {
            decShiftToLeast(res->lsu, D2U(res->digits), -shift);
            decShiftToLeast(res->lsu, D2U(res->digits), -shift);
            res->digits-=(-shift);
            res->digits-=(-shift);
            }
            }
          } /* to right */
          } /* to right */
        } /* non-0 non-Inf shift */
        } /* non-0 non-Inf shift */
      } /* rhs OK */
      } /* rhs OK */
    } /* numerics */
    } /* numerics */
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberShift */
  } /* decNumberShift */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberSquareRoot -- square root operator                        */
/* decNumberSquareRoot -- square root operator                        */
/*                                                                    */
/*                                                                    */
/*   This computes C = squareroot(A)                                  */
/*   This computes C = squareroot(A)                                  */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context; note that rounding mode has no effect        */
/*   set is the context; note that rounding mode has no effect        */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This uses the following varying-precision algorithm in:            */
/* This uses the following varying-precision algorithm in:            */
/*                                                                    */
/*                                                                    */
/*   Properly Rounded Variable Precision Square Root, T. E. Hull and  */
/*   Properly Rounded Variable Precision Square Root, T. E. Hull and  */
/*   A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */
/*   A. Abrham, ACM Transactions on Mathematical Software, Vol 11 #3, */
/*   pp229-237, ACM, September 1985.                                  */
/*   pp229-237, ACM, September 1985.                                  */
/*                                                                    */
/*                                                                    */
/* The square-root is calculated using Newton's method, after which   */
/* The square-root is calculated using Newton's method, after which   */
/* a check is made to ensure the result is correctly rounded.         */
/* a check is made to ensure the result is correctly rounded.         */
/*                                                                    */
/*                                                                    */
/* % [Reformatted original Numerical Turing source code follows.]     */
/* % [Reformatted original Numerical Turing source code follows.]     */
/* function sqrt(x : real) : real                                     */
/* function sqrt(x : real) : real                                     */
/* % sqrt(x) returns the properly rounded approximation to the square */
/* % sqrt(x) returns the properly rounded approximation to the square */
/* % root of x, in the precision of the calling environment, or it    */
/* % root of x, in the precision of the calling environment, or it    */
/* % fails if x < 0.                                                  */
/* % fails if x < 0.                                                  */
/* % t e hull and a abrham, august, 1984                              */
/* % t e hull and a abrham, august, 1984                              */
/* if x <= 0 then                                                     */
/* if x <= 0 then                                                     */
/*   if x < 0 then                                                    */
/*   if x < 0 then                                                    */
/*     assert false                                                   */
/*     assert false                                                   */
/*   else                                                             */
/*   else                                                             */
/*     result 0                                                       */
/*     result 0                                                       */
/*   end if                                                           */
/*   end if                                                           */
/* end if                                                             */
/* end if                                                             */
/* var f := setexp(x, 0)  % fraction part of x   [0.1 <= x < 1]       */
/* var f := setexp(x, 0)  % fraction part of x   [0.1 <= x < 1]       */
/* var e := getexp(x)     % exponent part of x                        */
/* var e := getexp(x)     % exponent part of x                        */
/* var approx : real                                                  */
/* var approx : real                                                  */
/* if e mod 2 = 0  then                                               */
/* if e mod 2 = 0  then                                               */
/*   approx := .259 + .819 * f   % approx to root of f                */
/*   approx := .259 + .819 * f   % approx to root of f                */
/* else                                                               */
/* else                                                               */
/*   f := f/l0                   % adjustments                        */
/*   f := f/l0                   % adjustments                        */
/*   e := e + 1                  %   for odd                          */
/*   e := e + 1                  %   for odd                          */
/*   approx := .0819 + 2.59 * f  %   exponent                         */
/*   approx := .0819 + 2.59 * f  %   exponent                         */
/* end if                                                             */
/* end if                                                             */
/*                                                                    */
/*                                                                    */
/* var p:= 3                                                          */
/* var p:= 3                                                          */
/* const maxp := currentprecision + 2                                 */
/* const maxp := currentprecision + 2                                 */
/* loop                                                               */
/* loop                                                               */
/*   p := min(2*p - 2, maxp)     % p = 4,6,10, . . . , maxp           */
/*   p := min(2*p - 2, maxp)     % p = 4,6,10, . . . , maxp           */
/*   precision p                                                      */
/*   precision p                                                      */
/*   approx := .5 * (approx + f/approx)                               */
/*   approx := .5 * (approx + f/approx)                               */
/*   exit when p = maxp                                               */
/*   exit when p = maxp                                               */
/* end loop                                                           */
/* end loop                                                           */
/*                                                                    */
/*                                                                    */
/* % approx is now within 1 ulp of the properly rounded square root   */
/* % approx is now within 1 ulp of the properly rounded square root   */
/* % of f; to ensure proper rounding, compare squares of (approx -    */
/* % of f; to ensure proper rounding, compare squares of (approx -    */
/* % l/2 ulp) and (approx + l/2 ulp) with f.                          */
/* % l/2 ulp) and (approx + l/2 ulp) with f.                          */
/* p := currentprecision                                              */
/* p := currentprecision                                              */
/* begin                                                              */
/* begin                                                              */
/*   precision p + 2                                                  */
/*   precision p + 2                                                  */
/*   const approxsubhalf := approx - setexp(.5, -p)                   */
/*   const approxsubhalf := approx - setexp(.5, -p)                   */
/*   if mulru(approxsubhalf, approxsubhalf) > f then                  */
/*   if mulru(approxsubhalf, approxsubhalf) > f then                  */
/*     approx := approx - setexp(.l, -p + 1)                          */
/*     approx := approx - setexp(.l, -p + 1)                          */
/*   else                                                             */
/*   else                                                             */
/*     const approxaddhalf := approx + setexp(.5, -p)                 */
/*     const approxaddhalf := approx + setexp(.5, -p)                 */
/*     if mulrd(approxaddhalf, approxaddhalf) < f then                */
/*     if mulrd(approxaddhalf, approxaddhalf) < f then                */
/*       approx := approx + setexp(.l, -p + 1)                        */
/*       approx := approx + setexp(.l, -p + 1)                        */
/*     end if                                                         */
/*     end if                                                         */
/*   end if                                                           */
/*   end if                                                           */
/* end                                                                */
/* end                                                                */
/* result setexp(approx, e div 2)  % fix exponent                     */
/* result setexp(approx, e div 2)  % fix exponent                     */
/* end sqrt                                                           */
/* end sqrt                                                           */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs,
decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs,
                                decContext *set) {
                                decContext *set) {
  decContext workset, approxset;   /* work contexts */
  decContext workset, approxset;   /* work contexts */
  decNumber dzero;                 /* used for constant zero */
  decNumber dzero;                 /* used for constant zero */
  Int  maxp;                       /* largest working precision */
  Int  maxp;                       /* largest working precision */
  Int  workp;                      /* working precision */
  Int  workp;                      /* working precision */
  Int  residue=0;                   /* rounding residue */
  Int  residue=0;                   /* rounding residue */
  uInt status=0, ignore=0;           /* status accumulators */
  uInt status=0, ignore=0;           /* status accumulators */
  uInt rstatus;                    /* .. */
  uInt rstatus;                    /* .. */
  Int  exp;                        /* working exponent */
  Int  exp;                        /* working exponent */
  Int  ideal;                      /* ideal (preferred) exponent */
  Int  ideal;                      /* ideal (preferred) exponent */
  Int  needbytes;                  /* work */
  Int  needbytes;                  /* work */
  Int  dropped;                    /* .. */
  Int  dropped;                    /* .. */
 
 
  #if DECSUBSET
  #if DECSUBSET
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  decNumber *allocrhs=NULL;        /* non-NULL if rounded rhs allocated */
  #endif
  #endif
  /* buffer for f [needs +1 in case DECBUFFER 0] */
  /* buffer for f [needs +1 in case DECBUFFER 0] */
  decNumber buff[D2N(DECBUFFER+1)];
  decNumber buff[D2N(DECBUFFER+1)];
  /* buffer for a [needs +2 to match likely maxp] */
  /* buffer for a [needs +2 to match likely maxp] */
  decNumber bufa[D2N(DECBUFFER+2)];
  decNumber bufa[D2N(DECBUFFER+2)];
  /* buffer for temporary, b [must be same size as a] */
  /* buffer for temporary, b [must be same size as a] */
  decNumber bufb[D2N(DECBUFFER+2)];
  decNumber bufb[D2N(DECBUFFER+2)];
  decNumber *allocbuff=NULL;       /* -> allocated buff, iff allocated */
  decNumber *allocbuff=NULL;       /* -> allocated buff, iff allocated */
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *allocbufb=NULL;       /* -> allocated bufb, iff allocated */
  decNumber *allocbufb=NULL;       /* -> allocated bufb, iff allocated */
  decNumber *f=buff;               /* reduced fraction */
  decNumber *f=buff;               /* reduced fraction */
  decNumber *a=bufa;               /* approximation to result */
  decNumber *a=bufa;               /* approximation to result */
  decNumber *b=bufb;               /* intermediate result */
  decNumber *b=bufb;               /* intermediate result */
  /* buffer for temporary variable, up to 3 digits */
  /* buffer for temporary variable, up to 3 digits */
  decNumber buft[D2N(3)];
  decNumber buft[D2N(3)];
  decNumber *t=buft;               /* up-to-3-digit constant or work */
  decNumber *t=buft;               /* up-to-3-digit constant or work */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                             /* protect allocated storage */
  do {                             /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operand and set lostDigits status, as needed */
      /* reduce operand and set lostDigits status, as needed */
      if (rhs->digits>set->digits) {
      if (rhs->digits>set->digits) {
        allocrhs=decRoundOperand(rhs, set, &status);
        allocrhs=decRoundOperand(rhs, set, &status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        /* [Note: 'f' allocation below could reuse this buffer if */
        /* [Note: 'f' allocation below could reuse this buffer if */
        /* used, but as this is rare they are kept separate for clarity.] */
        /* used, but as this is rare they are kept separate for clarity.] */
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    /* [following code does not require input rounding] */
    /* [following code does not require input rounding] */
 
 
    /* handle infinities and NaNs */
    /* handle infinities and NaNs */
    if (SPECIALARG) {
    if (SPECIALARG) {
      if (decNumberIsInfinite(rhs)) {         /* an infinity */
      if (decNumberIsInfinite(rhs)) {         /* an infinity */
        if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation;
        if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation;
         else decNumberCopy(res, rhs);        /* +Infinity */
         else decNumberCopy(res, rhs);        /* +Infinity */
        }
        }
       else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
       else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
      break;
      break;
      }
      }
 
 
    /* calculate the ideal (preferred) exponent [floor(exp/2)] */
    /* calculate the ideal (preferred) exponent [floor(exp/2)] */
    /* [We would like to write: ideal=rhs->exponent>>1, but this */
    /* [We would like to write: ideal=rhs->exponent>>1, but this */
    /* generates a compiler warning.  Generated code is the same.] */
    /* generates a compiler warning.  Generated code is the same.] */
    ideal=(rhs->exponent&~1)/2;         /* target */
    ideal=(rhs->exponent&~1)/2;         /* target */
 
 
    /* handle zeros */
    /* handle zeros */
    if (ISZERO(rhs)) {
    if (ISZERO(rhs)) {
      decNumberCopy(res, rhs);          /* could be 0 or -0 */
      decNumberCopy(res, rhs);          /* could be 0 or -0 */
      res->exponent=ideal;              /* use the ideal [safe] */
      res->exponent=ideal;              /* use the ideal [safe] */
      /* use decFinish to clamp any out-of-range exponent, etc. */
      /* use decFinish to clamp any out-of-range exponent, etc. */
      decFinish(res, set, &residue, &status);
      decFinish(res, set, &residue, &status);
      break;
      break;
      }
      }
 
 
    /* any other -x is an oops */
    /* any other -x is an oops */
    if (decNumberIsNegative(rhs)) {
    if (decNumberIsNegative(rhs)) {
      status|=DEC_Invalid_operation;
      status|=DEC_Invalid_operation;
      break;
      break;
      }
      }
 
 
    /* space is needed for three working variables */
    /* space is needed for three working variables */
    /*   f -- the same precision as the RHS, reduced to 0.01->0.99... */
    /*   f -- the same precision as the RHS, reduced to 0.01->0.99... */
    /*   a -- Hull's approximation -- precision, when assigned, is */
    /*   a -- Hull's approximation -- precision, when assigned, is */
    /*        currentprecision+1 or the input argument precision, */
    /*        currentprecision+1 or the input argument precision, */
    /*        whichever is larger (+2 for use as temporary) */
    /*        whichever is larger (+2 for use as temporary) */
    /*   b -- intermediate temporary result (same size as a) */
    /*   b -- intermediate temporary result (same size as a) */
    /* if any is too long for local storage, then allocate */
    /* if any is too long for local storage, then allocate */
    workp=MAXI(set->digits+1, rhs->digits);  /* actual rounding precision */
    workp=MAXI(set->digits+1, rhs->digits);  /* actual rounding precision */
    maxp=workp+2;                            /* largest working precision */
    maxp=workp+2;                            /* largest working precision */
 
 
    needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
    needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
    if (needbytes>(Int)sizeof(buff)) {
    if (needbytes>(Int)sizeof(buff)) {
      allocbuff=(decNumber *)malloc(needbytes);
      allocbuff=(decNumber *)malloc(needbytes);
      if (allocbuff==NULL) {  /* hopeless -- abandon */
      if (allocbuff==NULL) {  /* hopeless -- abandon */
        status|=DEC_Insufficient_storage;
        status|=DEC_Insufficient_storage;
        break;}
        break;}
      f=allocbuff;            /* use the allocated space */
      f=allocbuff;            /* use the allocated space */
      }
      }
    /* a and b both need to be able to hold a maxp-length number */
    /* a and b both need to be able to hold a maxp-length number */
    needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit);
    needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit);
    if (needbytes>(Int)sizeof(bufa)) {            /* [same applies to b] */
    if (needbytes>(Int)sizeof(bufa)) {            /* [same applies to b] */
      allocbufa=(decNumber *)malloc(needbytes);
      allocbufa=(decNumber *)malloc(needbytes);
      allocbufb=(decNumber *)malloc(needbytes);
      allocbufb=(decNumber *)malloc(needbytes);
      if (allocbufa==NULL || allocbufb==NULL) {   /* hopeless */
      if (allocbufa==NULL || allocbufb==NULL) {   /* hopeless */
        status|=DEC_Insufficient_storage;
        status|=DEC_Insufficient_storage;
        break;}
        break;}
      a=allocbufa;            /* use the allocated spaces */
      a=allocbufa;            /* use the allocated spaces */
      b=allocbufb;            /* .. */
      b=allocbufb;            /* .. */
      }
      }
 
 
    /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */
    /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */
    decNumberCopy(f, rhs);
    decNumberCopy(f, rhs);
    exp=f->exponent+f->digits;               /* adjusted to Hull rules */
    exp=f->exponent+f->digits;               /* adjusted to Hull rules */
    f->exponent=-(f->digits);                /* to range */
    f->exponent=-(f->digits);                /* to range */
 
 
    /* set up working context */
    /* set up working context */
    decContextDefault(&workset, DEC_INIT_DECIMAL64);
    decContextDefault(&workset, DEC_INIT_DECIMAL64);
 
 
    /* [Until further notice, no error is possible and status bits */
    /* [Until further notice, no error is possible and status bits */
    /* (Rounded, etc.) should be ignored, not accumulated.] */
    /* (Rounded, etc.) should be ignored, not accumulated.] */
 
 
    /* Calculate initial approximation, and allow for odd exponent */
    /* Calculate initial approximation, and allow for odd exponent */
    workset.digits=workp;                    /* p for initial calculation */
    workset.digits=workp;                    /* p for initial calculation */
    t->bits=0; t->digits=3;
    t->bits=0; t->digits=3;
    a->bits=0; a->digits=3;
    a->bits=0; a->digits=3;
    if ((exp & 1)==0) {                       /* even exponent */
    if ((exp & 1)==0) {                       /* even exponent */
      /* Set t=0.259, a=0.819 */
      /* Set t=0.259, a=0.819 */
      t->exponent=-3;
      t->exponent=-3;
      a->exponent=-3;
      a->exponent=-3;
      #if DECDPUN>=3
      #if DECDPUN>=3
        t->lsu[0]=259;
        t->lsu[0]=259;
        a->lsu[0]=819;
        a->lsu[0]=819;
      #elif DECDPUN==2
      #elif DECDPUN==2
        t->lsu[0]=59; t->lsu[1]=2;
        t->lsu[0]=59; t->lsu[1]=2;
        a->lsu[0]=19; a->lsu[1]=8;
        a->lsu[0]=19; a->lsu[1]=8;
      #else
      #else
        t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2;
        t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2;
        a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8;
        a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8;
      #endif
      #endif
      }
      }
     else {                                  /* odd exponent */
     else {                                  /* odd exponent */
      /* Set t=0.0819, a=2.59 */
      /* Set t=0.0819, a=2.59 */
      f->exponent--;                         /* f=f/10 */
      f->exponent--;                         /* f=f/10 */
      exp++;                                 /* e=e+1 */
      exp++;                                 /* e=e+1 */
      t->exponent=-4;
      t->exponent=-4;
      a->exponent=-2;
      a->exponent=-2;
      #if DECDPUN>=3
      #if DECDPUN>=3
        t->lsu[0]=819;
        t->lsu[0]=819;
        a->lsu[0]=259;
        a->lsu[0]=259;
      #elif DECDPUN==2
      #elif DECDPUN==2
        t->lsu[0]=19; t->lsu[1]=8;
        t->lsu[0]=19; t->lsu[1]=8;
        a->lsu[0]=59; a->lsu[1]=2;
        a->lsu[0]=59; a->lsu[1]=2;
      #else
      #else
        t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8;
        t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8;
        a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2;
        a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2;
      #endif
      #endif
      }
      }
    decMultiplyOp(a, a, f, &workset, &ignore);    /* a=a*f */
    decMultiplyOp(a, a, f, &workset, &ignore);    /* a=a*f */
    decAddOp(a, a, t, &workset, 0, &ignore);       /* ..+t */
    decAddOp(a, a, t, &workset, 0, &ignore);       /* ..+t */
    /* [a is now the initial approximation for sqrt(f), calculated with */
    /* [a is now the initial approximation for sqrt(f), calculated with */
    /* currentprecision, which is also a's precision.] */
    /* currentprecision, which is also a's precision.] */
 
 
    /* the main calculation loop */
    /* the main calculation loop */
    decNumberZero(&dzero);                   /* make 0 */
    decNumberZero(&dzero);                   /* make 0 */
    decNumberZero(t);                        /* set t = 0.5 */
    decNumberZero(t);                        /* set t = 0.5 */
    t->lsu[0]=5;                      /* .. */
    t->lsu[0]=5;                      /* .. */
    t->exponent=-1;                          /* .. */
    t->exponent=-1;                          /* .. */
    workset.digits=3;                        /* initial p */
    workset.digits=3;                        /* initial p */
    for (;;) {
    for (;;) {
      /* set p to min(2*p - 2, maxp)  [hence 3; or: 4, 6, 10, ... , maxp] */
      /* set p to min(2*p - 2, maxp)  [hence 3; or: 4, 6, 10, ... , maxp] */
      workset.digits=workset.digits*2-2;
      workset.digits=workset.digits*2-2;
      if (workset.digits>maxp) workset.digits=maxp;
      if (workset.digits>maxp) workset.digits=maxp;
      /* a = 0.5 * (a + f/a) */
      /* a = 0.5 * (a + f/a) */
      /* [calculated at p then rounded to currentprecision] */
      /* [calculated at p then rounded to currentprecision] */
      decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */
      decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */
      decAddOp(b, b, a, &workset, 0, &ignore);     /* b=b+a */
      decAddOp(b, b, a, &workset, 0, &ignore);     /* b=b+a */
      decMultiplyOp(a, b, t, &workset, &ignore);  /* a=b*0.5 */
      decMultiplyOp(a, b, t, &workset, &ignore);  /* a=b*0.5 */
      if (a->digits==maxp) break;            /* have required digits */
      if (a->digits==maxp) break;            /* have required digits */
      } /* loop */
      } /* loop */
 
 
    /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */
    /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */
    /* now reduce to length, etc.; this needs to be done with a */
    /* now reduce to length, etc.; this needs to be done with a */
    /* having the correct exponent so as to handle subnormals */
    /* having the correct exponent so as to handle subnormals */
    /* correctly */
    /* correctly */
    approxset=*set;                          /* get emin, emax, etc. */
    approxset=*set;                          /* get emin, emax, etc. */
    approxset.round=DEC_ROUND_HALF_EVEN;
    approxset.round=DEC_ROUND_HALF_EVEN;
    a->exponent+=exp/2;                      /* set correct exponent */
    a->exponent+=exp/2;                      /* set correct exponent */
 
 
    rstatus=0;                                /* clear status */
    rstatus=0;                                /* clear status */
    residue=0;                                /* .. and accumulator */
    residue=0;                                /* .. and accumulator */
    decCopyFit(a, a, &approxset, &residue, &rstatus);  /* reduce (if needed) */
    decCopyFit(a, a, &approxset, &residue, &rstatus);  /* reduce (if needed) */
    decFinish(a, &approxset, &residue, &rstatus);      /* clean and finalize */
    decFinish(a, &approxset, &residue, &rstatus);      /* clean and finalize */
 
 
    /* Overflow was possible if the input exponent was out-of-range, */
    /* Overflow was possible if the input exponent was out-of-range, */
    /* in which case quit */
    /* in which case quit */
    if (rstatus&DEC_Overflow) {
    if (rstatus&DEC_Overflow) {
      status=rstatus;                        /* use the status as-is */
      status=rstatus;                        /* use the status as-is */
      decNumberCopy(res, a);                 /* copy to result */
      decNumberCopy(res, a);                 /* copy to result */
      break;
      break;
      }
      }
 
 
    /* Preserve status except Inexact/Rounded */
    /* Preserve status except Inexact/Rounded */
    status|=(rstatus & ~(DEC_Rounded|DEC_Inexact));
    status|=(rstatus & ~(DEC_Rounded|DEC_Inexact));
 
 
    /* Carry out the Hull correction */
    /* Carry out the Hull correction */
    a->exponent-=exp/2;                      /* back to 0.1->1 */
    a->exponent-=exp/2;                      /* back to 0.1->1 */
 
 
    /* a is now at final precision and within 1 ulp of the properly */
    /* a is now at final precision and within 1 ulp of the properly */
    /* rounded square root of f; to ensure proper rounding, compare */
    /* rounded square root of f; to ensure proper rounding, compare */
    /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */
    /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */
    /* Here workset.digits=maxp and t=0.5, and a->digits determines */
    /* Here workset.digits=maxp and t=0.5, and a->digits determines */
    /* the ulp */
    /* the ulp */
    workset.digits--;                             /* maxp-1 is OK now */
    workset.digits--;                             /* maxp-1 is OK now */
    t->exponent=-a->digits-1;                     /* make 0.5 ulp */
    t->exponent=-a->digits-1;                     /* make 0.5 ulp */
    decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */
    decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */
    workset.round=DEC_ROUND_UP;
    workset.round=DEC_ROUND_UP;
    decMultiplyOp(b, b, b, &workset, &ignore);    /* b = mulru(b, b) */
    decMultiplyOp(b, b, b, &workset, &ignore);    /* b = mulru(b, b) */
    decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */
    decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */
    if (decNumberIsNegative(b)) {                 /* f < b [i.e., b > f] */
    if (decNumberIsNegative(b)) {                 /* f < b [i.e., b > f] */
      /* this is the more common adjustment, though both are rare */
      /* this is the more common adjustment, though both are rare */
      t->exponent++;                              /* make 1.0 ulp */
      t->exponent++;                              /* make 1.0 ulp */
      t->lsu[0]=1;                                 /* .. */
      t->lsu[0]=1;                                 /* .. */
      decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */
      decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */
      /* assign to approx [round to length] */
      /* assign to approx [round to length] */
      approxset.emin-=exp/2;                      /* adjust to match a */
      approxset.emin-=exp/2;                      /* adjust to match a */
      approxset.emax-=exp/2;
      approxset.emax-=exp/2;
      decAddOp(a, &dzero, a, &approxset, 0, &ignore);
      decAddOp(a, &dzero, a, &approxset, 0, &ignore);
      }
      }
     else {
     else {
      decAddOp(b, a, t, &workset, 0, &ignore);     /* b = a + 0.5 ulp */
      decAddOp(b, a, t, &workset, 0, &ignore);     /* b = a + 0.5 ulp */
      workset.round=DEC_ROUND_DOWN;
      workset.round=DEC_ROUND_DOWN;
      decMultiplyOp(b, b, b, &workset, &ignore);  /* b = mulrd(b, b) */
      decMultiplyOp(b, b, b, &workset, &ignore);  /* b = mulrd(b, b) */
      decCompareOp(b, b, f, &workset, COMPARE, &ignore);   /* b ? f */
      decCompareOp(b, b, f, &workset, COMPARE, &ignore);   /* b ? f */
      if (decNumberIsNegative(b)) {               /* b < f */
      if (decNumberIsNegative(b)) {               /* b < f */
        t->exponent++;                            /* make 1.0 ulp */
        t->exponent++;                            /* make 1.0 ulp */
        t->lsu[0]=1;                               /* .. */
        t->lsu[0]=1;                               /* .. */
        decAddOp(a, a, t, &workset, 0, &ignore);  /* a = a + 1 ulp */
        decAddOp(a, a, t, &workset, 0, &ignore);  /* a = a + 1 ulp */
        /* assign to approx [round to length] */
        /* assign to approx [round to length] */
        approxset.emin-=exp/2;                    /* adjust to match a */
        approxset.emin-=exp/2;                    /* adjust to match a */
        approxset.emax-=exp/2;
        approxset.emax-=exp/2;
        decAddOp(a, &dzero, a, &approxset, 0, &ignore);
        decAddOp(a, &dzero, a, &approxset, 0, &ignore);
        }
        }
      }
      }
    /* [no errors are possible in the above, and rounding/inexact during */
    /* [no errors are possible in the above, and rounding/inexact during */
    /* estimation are irrelevant, so status was not accumulated] */
    /* estimation are irrelevant, so status was not accumulated] */
 
 
    /* Here, 0.1 <= a < 1  (still), so adjust back */
    /* Here, 0.1 <= a < 1  (still), so adjust back */
    a->exponent+=exp/2;                      /* set correct exponent */
    a->exponent+=exp/2;                      /* set correct exponent */
 
 
    /* count droppable zeros [after any subnormal rounding] by */
    /* count droppable zeros [after any subnormal rounding] by */
    /* trimming a copy */
    /* trimming a copy */
    decNumberCopy(b, a);
    decNumberCopy(b, a);
    decTrim(b, set, 1, &dropped);            /* [drops trailing zeros] */
    decTrim(b, set, 1, &dropped);            /* [drops trailing zeros] */
 
 
    /* Set Inexact and Rounded.  The answer can only be exact if */
    /* Set Inexact and Rounded.  The answer can only be exact if */
    /* it is short enough so that squaring it could fit in workp digits, */
    /* it is short enough so that squaring it could fit in workp digits, */
    /* and it cannot have trailing zeros due to clamping, so these are */
    /* and it cannot have trailing zeros due to clamping, so these are */
    /* the only (relatively rare) conditions a careful check is needed */
    /* the only (relatively rare) conditions a careful check is needed */
    if (b->digits*2-1 > workp && !set->clamp) { /* cannot fit */
    if (b->digits*2-1 > workp && !set->clamp) { /* cannot fit */
      status|=DEC_Inexact|DEC_Rounded;
      status|=DEC_Inexact|DEC_Rounded;
      }
      }
     else {                                  /* could be exact/unrounded */
     else {                                  /* could be exact/unrounded */
      uInt mstatus=0;                         /* local status */
      uInt mstatus=0;                         /* local status */
      decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */
      decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */
      if (mstatus&DEC_Overflow) {            /* result just won't fit */
      if (mstatus&DEC_Overflow) {            /* result just won't fit */
        status|=DEC_Inexact|DEC_Rounded;
        status|=DEC_Inexact|DEC_Rounded;
        }
        }
       else {                                /* plausible */
       else {                                /* plausible */
        decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */
        decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */
        if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */
        if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */
         else {                              /* is Exact */
         else {                              /* is Exact */
          /* here, dropped is the count of trailing zeros in 'a' */
          /* here, dropped is the count of trailing zeros in 'a' */
          /* use closest exponent to ideal... */
          /* use closest exponent to ideal... */
          Int todrop=ideal-a->exponent;      /* most that can be dropped */
          Int todrop=ideal-a->exponent;      /* most that can be dropped */
          if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */
          if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */
           else {                            /* unrounded */
           else {                            /* unrounded */
            if (dropped<todrop) {            /* clamp to those available */
            if (dropped<todrop) {            /* clamp to those available */
              todrop=dropped;
              todrop=dropped;
              status|=DEC_Clamped;
              status|=DEC_Clamped;
              }
              }
            if (todrop>0) {                   /* have some to drop */
            if (todrop>0) {                   /* have some to drop */
              decShiftToLeast(a->lsu, D2U(a->digits), todrop);
              decShiftToLeast(a->lsu, D2U(a->digits), todrop);
              a->exponent+=todrop;           /* maintain numerical value */
              a->exponent+=todrop;           /* maintain numerical value */
              a->digits-=todrop;             /* new length */
              a->digits-=todrop;             /* new length */
              }
              }
            }
            }
          }
          }
        }
        }
      }
      }
 
 
    /* double-check Underflow, as perhaps the result could not have */
    /* double-check Underflow, as perhaps the result could not have */
    /* been subnormal (initial argument too big), or it is now Exact */
    /* been subnormal (initial argument too big), or it is now Exact */
    if (status&DEC_Underflow) {
    if (status&DEC_Underflow) {
      Int ae=rhs->exponent+rhs->digits-1;    /* adjusted exponent */
      Int ae=rhs->exponent+rhs->digits-1;    /* adjusted exponent */
      /* check if truly subnormal */
      /* check if truly subnormal */
      #if DECEXTFLAG                         /* DEC_Subnormal too */
      #if DECEXTFLAG                         /* DEC_Subnormal too */
        if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow);
        if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow);
      #else
      #else
        if (ae>=set->emin*2) status&=~DEC_Underflow;
        if (ae>=set->emin*2) status&=~DEC_Underflow;
      #endif
      #endif
      /* check if truly inexact */
      /* check if truly inexact */
      if (!(status&DEC_Inexact)) status&=~DEC_Underflow;
      if (!(status&DEC_Inexact)) status&=~DEC_Underflow;
      }
      }
 
 
    decNumberCopy(res, a);                   /* a is now the result */
    decNumberCopy(res, a);                   /* a is now the result */
    } while(0);                               /* end protected */
    } while(0);                               /* end protected */
 
 
  if (allocbuff!=NULL) free(allocbuff);      /* drop any storage used */
  if (allocbuff!=NULL) free(allocbuff);      /* drop any storage used */
  if (allocbufa!=NULL) free(allocbufa);      /* .. */
  if (allocbufa!=NULL) free(allocbufa);      /* .. */
  if (allocbufb!=NULL) free(allocbufb);      /* .. */
  if (allocbufb!=NULL) free(allocbufb);      /* .. */
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs !=NULL) free(allocrhs);       /* .. */
  if (allocrhs !=NULL) free(allocrhs);       /* .. */
  #endif
  #endif
  if (status!=0) decStatus(res, status, set);/* then report status */
  if (status!=0) decStatus(res, status, set);/* then report status */
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberSquareRoot */
  } /* decNumberSquareRoot */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberSubtract -- subtract two Numbers                          */
/* decNumberSubtract -- subtract two Numbers                          */
/*                                                                    */
/*                                                                    */
/*   This computes C = A - B                                          */
/*   This computes C = A - B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X-X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X-X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs,
decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs,
                              const decNumber *rhs, decContext *set) {
                              const decNumber *rhs, decContext *set) {
  uInt status=0;                 /* accumulator */
  uInt status=0;                 /* accumulator */
 
 
  decAddOp(res, lhs, rhs, set, DECNEG, &status);
  decAddOp(res, lhs, rhs, set, DECNEG, &status);
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  #if DECCHECK
  #if DECCHECK
  decCheckInexact(res, set);
  decCheckInexact(res, set);
  #endif
  #endif
  return res;
  return res;
  } /* decNumberSubtract */
  } /* decNumberSubtract */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberToIntegralExact -- round-to-integral-value with InExact   */
/* decNumberToIntegralExact -- round-to-integral-value with InExact   */
/* decNumberToIntegralValue -- round-to-integral-value                */
/* decNumberToIntegralValue -- round-to-integral-value                */
/*                                                                    */
/*                                                                    */
/*   res is the result                                                */
/*   res is the result                                                */
/*   rhs is input number                                              */
/*   rhs is input number                                              */
/*   set is the context                                               */
/*   set is the context                                               */
/*                                                                    */
/*                                                                    */
/* res must have space for any value of rhs.                          */
/* res must have space for any value of rhs.                          */
/*                                                                    */
/*                                                                    */
/* This implements the IEEE special operators and therefore treats    */
/* This implements the IEEE special operators and therefore treats    */
/* special values as valid.  For finite numbers it returns            */
/* special values as valid.  For finite numbers it returns            */
/* rescale(rhs, 0) if rhs->exponent is <0.                            */
/* rescale(rhs, 0) if rhs->exponent is <0.                            */
/* Otherwise the result is rhs (so no error is possible, except for   */
/* Otherwise the result is rhs (so no error is possible, except for   */
/* sNaN).                                                             */
/* sNaN).                                                             */
/*                                                                    */
/*                                                                    */
/* The context is used for rounding mode and status after sNaN, but   */
/* The context is used for rounding mode and status after sNaN, but   */
/* the digits setting is ignored.  The Exact version will signal      */
/* the digits setting is ignored.  The Exact version will signal      */
/* Inexact if the result differs numerically from rhs; the other      */
/* Inexact if the result differs numerically from rhs; the other      */
/* never signals Inexact.                                             */
/* never signals Inexact.                                             */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
decNumber * decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
                                     decContext *set) {
                                     decContext *set) {
  decNumber dn;
  decNumber dn;
  decContext workset;              /* working context */
  decContext workset;              /* working context */
  uInt status=0;            /* accumulator */
  uInt status=0;            /* accumulator */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  /* handle infinities and NaNs */
  /* handle infinities and NaNs */
  if (SPECIALARG) {
  if (SPECIALARG) {
    if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); /* an Infinity */
    if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); /* an Infinity */
     else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
     else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
    }
    }
   else { /* finite */
   else { /* finite */
    /* have a finite number; no error possible (res must be big enough) */
    /* have a finite number; no error possible (res must be big enough) */
    if (rhs->exponent>=0) return decNumberCopy(res, rhs);
    if (rhs->exponent>=0) return decNumberCopy(res, rhs);
    /* that was easy, but if negative exponent there is work to do... */
    /* that was easy, but if negative exponent there is work to do... */
    workset=*set;                  /* clone rounding, etc. */
    workset=*set;                  /* clone rounding, etc. */
    workset.digits=rhs->digits;    /* no length rounding */
    workset.digits=rhs->digits;    /* no length rounding */
    workset.traps=0;                /* no traps */
    workset.traps=0;                /* no traps */
    decNumberZero(&dn);            /* make a number with exponent 0 */
    decNumberZero(&dn);            /* make a number with exponent 0 */
    decNumberQuantize(res, rhs, &dn, &workset);
    decNumberQuantize(res, rhs, &dn, &workset);
    status|=workset.status;
    status|=workset.status;
    }
    }
  if (status!=0) decStatus(res, status, set);
  if (status!=0) decStatus(res, status, set);
  return res;
  return res;
  } /* decNumberToIntegralExact */
  } /* decNumberToIntegralExact */
 
 
decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
                                     decContext *set) {
                                     decContext *set) {
  decContext workset=*set;         /* working context */
  decContext workset=*set;         /* working context */
  workset.traps=0;                  /* no traps */
  workset.traps=0;                  /* no traps */
  decNumberToIntegralExact(res, rhs, &workset);
  decNumberToIntegralExact(res, rhs, &workset);
  /* this never affects set, except for sNaNs; NaN will have been set */
  /* this never affects set, except for sNaNs; NaN will have been set */
  /* or propagated already, so no need to call decStatus */
  /* or propagated already, so no need to call decStatus */
  set->status|=workset.status&DEC_Invalid_operation;
  set->status|=workset.status&DEC_Invalid_operation;
  return res;
  return res;
  } /* decNumberToIntegralValue */
  } /* decNumberToIntegralValue */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberXor -- XOR two Numbers, digitwise                         */
/* decNumberXor -- XOR two Numbers, digitwise                         */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ^ B                                          */
/*   This computes C = A ^ B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X^X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X^X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context (used for result length and error report)     */
/*   set is the context (used for result length and error report)     */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Logical function restrictions apply (see above); a NaN is          */
/* Logical function restrictions apply (see above); a NaN is          */
/* returned with Invalid_operation if a restriction is violated.      */
/* returned with Invalid_operation if a restriction is violated.      */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberXor(decNumber *res, const decNumber *lhs,
decNumber * decNumberXor(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, decContext *set) {
                         const decNumber *rhs, decContext *set) {
  const Unit *ua, *ub;                  /* -> operands */
  const Unit *ua, *ub;                  /* -> operands */
  const Unit *msua, *msub;              /* -> operand msus */
  const Unit *msua, *msub;              /* -> operand msus */
  Unit  *uc, *msuc;                     /* -> result and its msu */
  Unit  *uc, *msuc;                     /* -> result and its msu */
  Int   msudigs;                        /* digits in res msu */
  Int   msudigs;                        /* digits in res msu */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
    decStatus(res, DEC_Invalid_operation, set);
    decStatus(res, DEC_Invalid_operation, set);
    return res;
    return res;
    }
    }
  /* operands are valid */
  /* operands are valid */
  ua=lhs->lsu;                          /* bottom-up */
  ua=lhs->lsu;                          /* bottom-up */
  ub=rhs->lsu;                          /* .. */
  ub=rhs->lsu;                          /* .. */
  uc=res->lsu;                          /* .. */
  uc=res->lsu;                          /* .. */
  msua=ua+D2U(lhs->digits)-1;           /* -> msu of lhs */
  msua=ua+D2U(lhs->digits)-1;           /* -> msu of lhs */
  msub=ub+D2U(rhs->digits)-1;           /* -> msu of rhs */
  msub=ub+D2U(rhs->digits)-1;           /* -> msu of rhs */
  msuc=uc+D2U(set->digits)-1;           /* -> msu of result */
  msuc=uc+D2U(set->digits)-1;           /* -> msu of result */
  msudigs=MSUDIGITS(set->digits);       /* [faster than remainder] */
  msudigs=MSUDIGITS(set->digits);       /* [faster than remainder] */
  for (; uc<=msuc; ua++, ub++, uc++) {  /* Unit loop */
  for (; uc<=msuc; ua++, ub++, uc++) {  /* Unit loop */
    Unit a, b;                          /* extract units */
    Unit a, b;                          /* extract units */
    if (ua>msua) a=0;
    if (ua>msua) a=0;
     else a=*ua;
     else a=*ua;
    if (ub>msub) b=0;
    if (ub>msub) b=0;
     else b=*ub;
     else b=*ub;
    *uc=0;                               /* can now write back */
    *uc=0;                               /* can now write back */
    if (a|b) {                          /* maybe 1 bits to examine */
    if (a|b) {                          /* maybe 1 bits to examine */
      Int i, j;
      Int i, j;
      /* This loop could be unrolled and/or use BIN2BCD tables */
      /* This loop could be unrolled and/or use BIN2BCD tables */
      for (i=0; i<DECDPUN; i++) {
      for (i=0; i<DECDPUN; i++) {
        if ((a^b)&1) *uc=*uc+(Unit)powers[i];     /* effect XOR */
        if ((a^b)&1) *uc=*uc+(Unit)powers[i];     /* effect XOR */
        j=a%10;
        j=a%10;
        a=a/10;
        a=a/10;
        j|=b%10;
        j|=b%10;
        b=b/10;
        b=b/10;
        if (j>1) {
        if (j>1) {
          decStatus(res, DEC_Invalid_operation, set);
          decStatus(res, DEC_Invalid_operation, set);
          return res;
          return res;
          }
          }
        if (uc==msuc && i==msudigs-1) break;      /* just did final digit */
        if (uc==msuc && i==msudigs-1) break;      /* just did final digit */
        } /* each digit */
        } /* each digit */
      } /* non-zero */
      } /* non-zero */
    } /* each unit */
    } /* each unit */
  /* [here uc-1 is the msu of the result] */
  /* [here uc-1 is the msu of the result] */
  res->digits=decGetDigits(res->lsu, uc-res->lsu);
  res->digits=decGetDigits(res->lsu, uc-res->lsu);
  res->exponent=0;                       /* integer */
  res->exponent=0;                       /* integer */
  res->bits=0;                           /* sign=0 */
  res->bits=0;                           /* sign=0 */
  return res;  /* [no status to set] */
  return res;  /* [no status to set] */
  } /* decNumberXor */
  } /* decNumberXor */
 
 
 
 
/* ================================================================== */
/* ================================================================== */
/* Utility routines                                                   */
/* Utility routines                                                   */
/* ================================================================== */
/* ================================================================== */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberClass -- return the decClass of a decNumber               */
/* decNumberClass -- return the decClass of a decNumber               */
/*   dn -- the decNumber to test                                      */
/*   dn -- the decNumber to test                                      */
/*   set -- the context to use for Emin                               */
/*   set -- the context to use for Emin                               */
/*   returns the decClass enum                                        */
/*   returns the decClass enum                                        */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
enum decClass decNumberClass(const decNumber *dn, decContext *set) {
enum decClass decNumberClass(const decNumber *dn, decContext *set) {
  if (decNumberIsSpecial(dn)) {
  if (decNumberIsSpecial(dn)) {
    if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN;
    if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN;
    if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN;
    if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN;
    /* must be an infinity */
    /* must be an infinity */
    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF;
    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF;
    return DEC_CLASS_POS_INF;
    return DEC_CLASS_POS_INF;
    }
    }
  /* is finite */
  /* is finite */
  if (decNumberIsNormal(dn, set)) { /* most common */
  if (decNumberIsNormal(dn, set)) { /* most common */
    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL;
    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL;
    return DEC_CLASS_POS_NORMAL;
    return DEC_CLASS_POS_NORMAL;
    }
    }
  /* is subnormal or zero */
  /* is subnormal or zero */
  if (decNumberIsZero(dn)) {    /* most common */
  if (decNumberIsZero(dn)) {    /* most common */
    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO;
    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO;
    return DEC_CLASS_POS_ZERO;
    return DEC_CLASS_POS_ZERO;
    }
    }
  if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL;
  if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL;
  return DEC_CLASS_POS_SUBNORMAL;
  return DEC_CLASS_POS_SUBNORMAL;
  } /* decNumberClass */
  } /* decNumberClass */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberClassToString -- convert decClass to a string             */
/* decNumberClassToString -- convert decClass to a string             */
/*                                                                    */
/*                                                                    */
/*  eclass is a valid decClass                                        */
/*  eclass is a valid decClass                                        */
/*  returns a constant string describing the class (max 13+1 chars)   */
/*  returns a constant string describing the class (max 13+1 chars)   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
const char *decNumberClassToString(enum decClass eclass) {
const char *decNumberClassToString(enum decClass eclass) {
  if (eclass==DEC_CLASS_POS_NORMAL)    return DEC_ClassString_PN;
  if (eclass==DEC_CLASS_POS_NORMAL)    return DEC_ClassString_PN;
  if (eclass==DEC_CLASS_NEG_NORMAL)    return DEC_ClassString_NN;
  if (eclass==DEC_CLASS_NEG_NORMAL)    return DEC_ClassString_NN;
  if (eclass==DEC_CLASS_POS_ZERO)      return DEC_ClassString_PZ;
  if (eclass==DEC_CLASS_POS_ZERO)      return DEC_ClassString_PZ;
  if (eclass==DEC_CLASS_NEG_ZERO)      return DEC_ClassString_NZ;
  if (eclass==DEC_CLASS_NEG_ZERO)      return DEC_ClassString_NZ;
  if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS;
  if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS;
  if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS;
  if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS;
  if (eclass==DEC_CLASS_POS_INF)       return DEC_ClassString_PI;
  if (eclass==DEC_CLASS_POS_INF)       return DEC_ClassString_PI;
  if (eclass==DEC_CLASS_NEG_INF)       return DEC_ClassString_NI;
  if (eclass==DEC_CLASS_NEG_INF)       return DEC_ClassString_NI;
  if (eclass==DEC_CLASS_QNAN)          return DEC_ClassString_QN;
  if (eclass==DEC_CLASS_QNAN)          return DEC_ClassString_QN;
  if (eclass==DEC_CLASS_SNAN)          return DEC_ClassString_SN;
  if (eclass==DEC_CLASS_SNAN)          return DEC_ClassString_SN;
  return DEC_ClassString_UN;           /* Unknown */
  return DEC_ClassString_UN;           /* Unknown */
  } /* decNumberClassToString */
  } /* decNumberClassToString */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberCopy -- copy a number                                     */
/* decNumberCopy -- copy a number                                     */
/*                                                                    */
/*                                                                    */
/*   dest is the target decNumber                                     */
/*   dest is the target decNumber                                     */
/*   src  is the source decNumber                                     */
/*   src  is the source decNumber                                     */
/*   returns dest                                                     */
/*   returns dest                                                     */
/*                                                                    */
/*                                                                    */
/* (dest==src is allowed and is a no-op)                              */
/* (dest==src is allowed and is a no-op)                              */
/* All fields are updated as required.  This is a utility operation,  */
/* All fields are updated as required.  This is a utility operation,  */
/* so special values are unchanged and no error is possible.          */
/* so special values are unchanged and no error is possible.          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberCopy(decNumber *dest, const decNumber *src) {
decNumber * decNumberCopy(decNumber *dest, const decNumber *src) {
 
 
  #if DECCHECK
  #if DECCHECK
  if (src==NULL) return decNumberZero(dest);
  if (src==NULL) return decNumberZero(dest);
  #endif
  #endif
 
 
  if (dest==src) return dest;                /* no copy required */
  if (dest==src) return dest;                /* no copy required */
 
 
  /* Use explicit assignments here as structure assignment could copy */
  /* Use explicit assignments here as structure assignment could copy */
  /* more than just the lsu (for small DECDPUN).  This would not affect */
  /* more than just the lsu (for small DECDPUN).  This would not affect */
  /* the value of the results, but could disturb test harness spill */
  /* the value of the results, but could disturb test harness spill */
  /* checking. */
  /* checking. */
  dest->bits=src->bits;
  dest->bits=src->bits;
  dest->exponent=src->exponent;
  dest->exponent=src->exponent;
  dest->digits=src->digits;
  dest->digits=src->digits;
  dest->lsu[0]=src->lsu[0];
  dest->lsu[0]=src->lsu[0];
  if (src->digits>DECDPUN) {                 /* more Units to come */
  if (src->digits>DECDPUN) {                 /* more Units to come */
    const Unit *smsup, *s;                   /* work */
    const Unit *smsup, *s;                   /* work */
    Unit  *d;                                /* .. */
    Unit  *d;                                /* .. */
    /* memcpy for the remaining Units would be safe as they cannot */
    /* memcpy for the remaining Units would be safe as they cannot */
    /* overlap.  However, this explicit loop is faster in short cases. */
    /* overlap.  However, this explicit loop is faster in short cases. */
    d=dest->lsu+1;                           /* -> first destination */
    d=dest->lsu+1;                           /* -> first destination */
    smsup=src->lsu+D2U(src->digits);         /* -> source msu+1 */
    smsup=src->lsu+D2U(src->digits);         /* -> source msu+1 */
    for (s=src->lsu+1; s<smsup; s++, d++) *d=*s;
    for (s=src->lsu+1; s<smsup; s++, d++) *d=*s;
    }
    }
  return dest;
  return dest;
  } /* decNumberCopy */
  } /* decNumberCopy */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberCopyAbs -- quiet absolute value operator                  */
/* decNumberCopyAbs -- quiet absolute value operator                  */
/*                                                                    */
/*                                                                    */
/*   This sets C = abs(A)                                             */
/*   This sets C = abs(A)                                             */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* No exception or error can occur; this is a quiet bitwise operation.*/
/* No exception or error can occur; this is a quiet bitwise operation.*/
/* See also decNumberAbs for a checking version of this.              */
/* See also decNumberAbs for a checking version of this.              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
decNumber * decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
  #endif
  #endif
  decNumberCopy(res, rhs);
  decNumberCopy(res, rhs);
  res->bits&=~DECNEG;                   /* turn off sign */
  res->bits&=~DECNEG;                   /* turn off sign */
  return res;
  return res;
  } /* decNumberCopyAbs */
  } /* decNumberCopyAbs */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberCopyNegate -- quiet negate value operator                 */
/* decNumberCopyNegate -- quiet negate value operator                 */
/*                                                                    */
/*                                                                    */
/*   This sets C = negate(A)                                          */
/*   This sets C = negate(A)                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* No exception or error can occur; this is a quiet bitwise operation.*/
/* No exception or error can occur; this is a quiet bitwise operation.*/
/* See also decNumberMinus for a checking version of this.            */
/* See also decNumberMinus for a checking version of this.            */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
decNumber * decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
  #endif
  #endif
  decNumberCopy(res, rhs);
  decNumberCopy(res, rhs);
  res->bits^=DECNEG;                    /* invert the sign */
  res->bits^=DECNEG;                    /* invert the sign */
  return res;
  return res;
  } /* decNumberCopyNegate */
  } /* decNumberCopyNegate */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberCopySign -- quiet copy and set sign operator              */
/* decNumberCopySign -- quiet copy and set sign operator              */
/*                                                                    */
/*                                                                    */
/*   This sets C = A with the sign of B                               */
/*   This sets C = A with the sign of B                               */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* No exception or error can occur; this is a quiet bitwise operation.*/
/* No exception or error can occur; this is a quiet bitwise operation.*/
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberCopySign(decNumber *res, const decNumber *lhs,
decNumber * decNumberCopySign(decNumber *res, const decNumber *lhs,
                              const decNumber *rhs) {
                              const decNumber *rhs) {
  uByte sign;                           /* rhs sign */
  uByte sign;                           /* rhs sign */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
  #endif
  #endif
  sign=rhs->bits & DECNEG;              /* save sign bit */
  sign=rhs->bits & DECNEG;              /* save sign bit */
  decNumberCopy(res, lhs);
  decNumberCopy(res, lhs);
  res->bits&=~DECNEG;                   /* clear the sign */
  res->bits&=~DECNEG;                   /* clear the sign */
  res->bits|=sign;                      /* set from rhs */
  res->bits|=sign;                      /* set from rhs */
  return res;
  return res;
  } /* decNumberCopySign */
  } /* decNumberCopySign */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberGetBCD -- get the coefficient in BCD8                     */
/* decNumberGetBCD -- get the coefficient in BCD8                     */
/*   dn is the source decNumber                                       */
/*   dn is the source decNumber                                       */
/*   bcd is the uInt array that will receive dn->digits BCD bytes,    */
/*   bcd is the uInt array that will receive dn->digits BCD bytes,    */
/*     most-significant at offset 0                                   */
/*     most-significant at offset 0                                   */
/*   returns bcd                                                      */
/*   returns bcd                                                      */
/*                                                                    */
/*                                                                    */
/* bcd must have at least dn->digits bytes.  No error is possible; if */
/* bcd must have at least dn->digits bytes.  No error is possible; if */
/* dn is a NaN or Infinite, digits must be 1 and the coefficient 0.   */
/* dn is a NaN or Infinite, digits must be 1 and the coefficient 0.   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
uByte * decNumberGetBCD(const decNumber *dn, uint8_t *bcd) {
uByte * decNumberGetBCD(const decNumber *dn, uint8_t *bcd) {
  uByte *ub=bcd+dn->digits-1;      /* -> lsd */
  uByte *ub=bcd+dn->digits-1;      /* -> lsd */
  const Unit *up=dn->lsu;          /* Unit pointer, -> lsu */
  const Unit *up=dn->lsu;          /* Unit pointer, -> lsu */
 
 
  #if DECDPUN==1                   /* trivial simple copy */
  #if DECDPUN==1                   /* trivial simple copy */
    for (; ub>=bcd; ub--, up++) *ub=*up;
    for (; ub>=bcd; ub--, up++) *ub=*up;
  #else                            /* chopping needed */
  #else                            /* chopping needed */
    uInt u=*up;                    /* work */
    uInt u=*up;                    /* work */
    uInt cut=DECDPUN;              /* downcounter through unit */
    uInt cut=DECDPUN;              /* downcounter through unit */
    for (; ub>=bcd; ub--) {
    for (; ub>=bcd; ub--) {
      *ub=(uByte)(u%10);           /* [*6554 trick inhibits, here] */
      *ub=(uByte)(u%10);           /* [*6554 trick inhibits, here] */
      u=u/10;
      u=u/10;
      cut--;
      cut--;
      if (cut>0) continue;          /* more in this unit */
      if (cut>0) continue;          /* more in this unit */
      up++;
      up++;
      u=*up;
      u=*up;
      cut=DECDPUN;
      cut=DECDPUN;
      }
      }
  #endif
  #endif
  return bcd;
  return bcd;
  } /* decNumberGetBCD */
  } /* decNumberGetBCD */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberSetBCD -- set (replace) the coefficient from BCD8         */
/* decNumberSetBCD -- set (replace) the coefficient from BCD8         */
/*   dn is the target decNumber                                       */
/*   dn is the target decNumber                                       */
/*   bcd is the uInt array that will source n BCD bytes, most-        */
/*   bcd is the uInt array that will source n BCD bytes, most-        */
/*     significant at offset 0                                        */
/*     significant at offset 0                                        */
/*   n is the number of digits in the source BCD array (bcd)          */
/*   n is the number of digits in the source BCD array (bcd)          */
/*   returns dn                                                       */
/*   returns dn                                                       */
/*                                                                    */
/*                                                                    */
/* dn must have space for at least n digits.  No error is possible;   */
/* dn must have space for at least n digits.  No error is possible;   */
/* if dn is a NaN, or Infinite, or is to become a zero, n must be 1   */
/* if dn is a NaN, or Infinite, or is to become a zero, n must be 1   */
/* and bcd[0] zero.                                                   */
/* and bcd[0] zero.                                                   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
  Unit *up=dn->lsu+D2U(dn->digits)-1;   /* -> msu [target pointer] */
  Unit *up=dn->lsu+D2U(dn->digits)-1;   /* -> msu [target pointer] */
  const uByte *ub=bcd;                  /* -> source msd */
  const uByte *ub=bcd;                  /* -> source msd */
 
 
  #if DECDPUN==1                        /* trivial simple copy */
  #if DECDPUN==1                        /* trivial simple copy */
    for (; ub<bcd+n; ub++, up--) *up=*ub;
    for (; ub<bcd+n; ub++, up--) *up=*ub;
  #else                                 /* some assembly needed */
  #else                                 /* some assembly needed */
    /* calculate how many digits in msu, and hence first cut */
    /* calculate how many digits in msu, and hence first cut */
    Int cut=MSUDIGITS(n);               /* [faster than remainder] */
    Int cut=MSUDIGITS(n);               /* [faster than remainder] */
    for (;up>=dn->lsu; up--) {          /* each Unit from msu */
    for (;up>=dn->lsu; up--) {          /* each Unit from msu */
      *up=0;                             /* will take <=DECDPUN digits */
      *up=0;                             /* will take <=DECDPUN digits */
      for (; cut>0; ub++, cut--) *up=X10(*up)+*ub;
      for (; cut>0; ub++, cut--) *up=X10(*up)+*ub;
      cut=DECDPUN;                      /* next Unit has all digits */
      cut=DECDPUN;                      /* next Unit has all digits */
      }
      }
  #endif
  #endif
  dn->digits=n;                         /* set digit count */
  dn->digits=n;                         /* set digit count */
  return dn;
  return dn;
  } /* decNumberSetBCD */
  } /* decNumberSetBCD */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberIsNormal -- test normality of a decNumber                 */
/* decNumberIsNormal -- test normality of a decNumber                 */
/*   dn is the decNumber to test                                      */
/*   dn is the decNumber to test                                      */
/*   set is the context to use for Emin                               */
/*   set is the context to use for Emin                               */
/*   returns 1 if |dn| is finite and >=Nmin, 0 otherwise              */
/*   returns 1 if |dn| is finite and >=Nmin, 0 otherwise              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
Int decNumberIsNormal(const decNumber *dn, decContext *set) {
Int decNumberIsNormal(const decNumber *dn, decContext *set) {
  Int ae;                               /* adjusted exponent */
  Int ae;                               /* adjusted exponent */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
  #endif
  #endif
 
 
  if (decNumberIsSpecial(dn)) return 0; /* not finite */
  if (decNumberIsSpecial(dn)) return 0; /* not finite */
  if (decNumberIsZero(dn)) return 0;     /* not non-zero */
  if (decNumberIsZero(dn)) return 0;     /* not non-zero */
 
 
  ae=dn->exponent+dn->digits-1;         /* adjusted exponent */
  ae=dn->exponent+dn->digits-1;         /* adjusted exponent */
  if (ae<set->emin) return 0;            /* is subnormal */
  if (ae<set->emin) return 0;            /* is subnormal */
  return 1;
  return 1;
  } /* decNumberIsNormal */
  } /* decNumberIsNormal */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberIsSubnormal -- test subnormality of a decNumber           */
/* decNumberIsSubnormal -- test subnormality of a decNumber           */
/*   dn is the decNumber to test                                      */
/*   dn is the decNumber to test                                      */
/*   set is the context to use for Emin                               */
/*   set is the context to use for Emin                               */
/*   returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise    */
/*   returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
Int decNumberIsSubnormal(const decNumber *dn, decContext *set) {
Int decNumberIsSubnormal(const decNumber *dn, decContext *set) {
  Int ae;                               /* adjusted exponent */
  Int ae;                               /* adjusted exponent */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
  #endif
  #endif
 
 
  if (decNumberIsSpecial(dn)) return 0; /* not finite */
  if (decNumberIsSpecial(dn)) return 0; /* not finite */
  if (decNumberIsZero(dn)) return 0;     /* not non-zero */
  if (decNumberIsZero(dn)) return 0;     /* not non-zero */
 
 
  ae=dn->exponent+dn->digits-1;         /* adjusted exponent */
  ae=dn->exponent+dn->digits-1;         /* adjusted exponent */
  if (ae<set->emin) return 1;           /* is subnormal */
  if (ae<set->emin) return 1;           /* is subnormal */
  return 0;
  return 0;
  } /* decNumberIsSubnormal */
  } /* decNumberIsSubnormal */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberTrim -- remove insignificant zeros                        */
/* decNumberTrim -- remove insignificant zeros                        */
/*                                                                    */
/*                                                                    */
/*   dn is the number to trim                                         */
/*   dn is the number to trim                                         */
/*   returns dn                                                       */
/*   returns dn                                                       */
/*                                                                    */
/*                                                                    */
/* All fields are updated as required.  This is a utility operation,  */
/* All fields are updated as required.  This is a utility operation,  */
/* so special values are unchanged and no error is possible.          */
/* so special values are unchanged and no error is possible.          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decNumberTrim(decNumber *dn) {
decNumber * decNumberTrim(decNumber *dn) {
  Int  dropped;                    /* work */
  Int  dropped;                    /* work */
  decContext set;                  /* .. */
  decContext set;                  /* .. */
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn;
  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn;
  #endif
  #endif
  decContextDefault(&set, DEC_INIT_BASE);    /* clamp=0 */
  decContextDefault(&set, DEC_INIT_BASE);    /* clamp=0 */
  return decTrim(dn, &set, 0, &dropped);
  return decTrim(dn, &set, 0, &dropped);
  } /* decNumberTrim */
  } /* decNumberTrim */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberVersion -- return the name and version of this module     */
/* decNumberVersion -- return the name and version of this module     */
/*                                                                    */
/*                                                                    */
/* No error is possible.                                              */
/* No error is possible.                                              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
const char * decNumberVersion(void) {
const char * decNumberVersion(void) {
  return DECVERSION;
  return DECVERSION;
  } /* decNumberVersion */
  } /* decNumberVersion */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberZero -- set a number to 0                                 */
/* decNumberZero -- set a number to 0                                 */
/*                                                                    */
/*                                                                    */
/*   dn is the number to set, with space for one digit                */
/*   dn is the number to set, with space for one digit                */
/*   returns dn                                                       */
/*   returns dn                                                       */
/*                                                                    */
/*                                                                    */
/* No error is possible.                                              */
/* No error is possible.                                              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* Memset is not used as it is much slower in some environments. */
/* Memset is not used as it is much slower in some environments. */
decNumber * decNumberZero(decNumber *dn) {
decNumber * decNumberZero(decNumber *dn) {
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
  if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
  #endif
  #endif
 
 
  dn->bits=0;
  dn->bits=0;
  dn->exponent=0;
  dn->exponent=0;
  dn->digits=1;
  dn->digits=1;
  dn->lsu[0]=0;
  dn->lsu[0]=0;
  return dn;
  return dn;
  } /* decNumberZero */
  } /* decNumberZero */
 
 
/* ================================================================== */
/* ================================================================== */
/* Local routines                                                     */
/* Local routines                                                     */
/* ================================================================== */
/* ================================================================== */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decToString -- lay out a number into a string                      */
/* decToString -- lay out a number into a string                      */
/*                                                                    */
/*                                                                    */
/*   dn     is the number to lay out                                  */
/*   dn     is the number to lay out                                  */
/*   string is where to lay out the number                            */
/*   string is where to lay out the number                            */
/*   eng    is 1 if Engineering, 0 if Scientific                      */
/*   eng    is 1 if Engineering, 0 if Scientific                      */
/*                                                                    */
/*                                                                    */
/* string must be at least dn->digits+14 characters long              */
/* string must be at least dn->digits+14 characters long              */
/* No error is possible.                                              */
/* No error is possible.                                              */
/*                                                                    */
/*                                                                    */
/* Note that this routine can generate a -0 or 0.000.  These are      */
/* Note that this routine can generate a -0 or 0.000.  These are      */
/* never generated in subset to-number or arithmetic, but can occur   */
/* never generated in subset to-number or arithmetic, but can occur   */
/* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234).              */
/* in non-subset arithmetic (e.g., -1*0 or 1.234-1.234).              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* If DECCHECK is enabled the string "?" is returned if a number is */
/* If DECCHECK is enabled the string "?" is returned if a number is */
/* invalid. */
/* invalid. */
static void decToString(const decNumber *dn, char *string, Flag eng) {
static void decToString(const decNumber *dn, char *string, Flag eng) {
  Int exp=dn->exponent;       /* local copy */
  Int exp=dn->exponent;       /* local copy */
  Int e;                      /* E-part value */
  Int e;                      /* E-part value */
  Int pre;                    /* digits before the '.' */
  Int pre;                    /* digits before the '.' */
  Int cut;                    /* for counting digits in a Unit */
  Int cut;                    /* for counting digits in a Unit */
  char *c=string;             /* work [output pointer] */
  char *c=string;             /* work [output pointer] */
  const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */
  const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */
  uInt u, pow;                /* work */
  uInt u, pow;                /* work */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) {
  if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) {
    strcpy(string, "?");
    strcpy(string, "?");
    return;}
    return;}
  #endif
  #endif
 
 
  if (decNumberIsNegative(dn)) {   /* Negatives get a minus */
  if (decNumberIsNegative(dn)) {   /* Negatives get a minus */
    *c='-';
    *c='-';
    c++;
    c++;
    }
    }
  if (dn->bits&DECSPECIAL) {       /* Is a special value */
  if (dn->bits&DECSPECIAL) {       /* Is a special value */
    if (decNumberIsInfinite(dn)) {
    if (decNumberIsInfinite(dn)) {
      strcpy(c,   "Inf");
      strcpy(c,   "Inf");
      strcpy(c+3, "inity");
      strcpy(c+3, "inity");
      return;}
      return;}
    /* a NaN */
    /* a NaN */
    if (dn->bits&DECSNAN) {        /* signalling NaN */
    if (dn->bits&DECSNAN) {        /* signalling NaN */
      *c='s';
      *c='s';
      c++;
      c++;
      }
      }
    strcpy(c, "NaN");
    strcpy(c, "NaN");
    c+=3;                          /* step past */
    c+=3;                          /* step past */
    /* if not a clean non-zero coefficient, that's all there is in a */
    /* if not a clean non-zero coefficient, that's all there is in a */
    /* NaN string */
    /* NaN string */
    if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return;
    if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return;
    /* [drop through to add integer] */
    /* [drop through to add integer] */
    }
    }
 
 
  /* calculate how many digits in msu, and hence first cut */
  /* calculate how many digits in msu, and hence first cut */
  cut=MSUDIGITS(dn->digits);       /* [faster than remainder] */
  cut=MSUDIGITS(dn->digits);       /* [faster than remainder] */
  cut--;                           /* power of ten for digit */
  cut--;                           /* power of ten for digit */
 
 
  if (exp==0) {                     /* simple integer [common fastpath] */
  if (exp==0) {                     /* simple integer [common fastpath] */
    for (;up>=dn->lsu; up--) {     /* each Unit from msu */
    for (;up>=dn->lsu; up--) {     /* each Unit from msu */
      u=*up;                       /* contains DECDPUN digits to lay out */
      u=*up;                       /* contains DECDPUN digits to lay out */
      for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow);
      for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow);
      cut=DECDPUN-1;               /* next Unit has all digits */
      cut=DECDPUN-1;               /* next Unit has all digits */
      }
      }
    *c='\0';                       /* terminate the string */
    *c='\0';                       /* terminate the string */
    return;}
    return;}
 
 
  /* non-0 exponent -- assume plain form */
  /* non-0 exponent -- assume plain form */
  pre=dn->digits+exp;              /* digits before '.' */
  pre=dn->digits+exp;              /* digits before '.' */
  e=0;                              /* no E */
  e=0;                              /* no E */
  if ((exp>0) || (pre<-5)) {        /* need exponential form */
  if ((exp>0) || (pre<-5)) {        /* need exponential form */
    e=exp+dn->digits-1;            /* calculate E value */
    e=exp+dn->digits-1;            /* calculate E value */
    pre=1;                         /* assume one digit before '.' */
    pre=1;                         /* assume one digit before '.' */
    if (eng && (e!=0)) {    /* engineering: may need to adjust */
    if (eng && (e!=0)) {    /* engineering: may need to adjust */
      Int adj;                     /* adjustment */
      Int adj;                     /* adjustment */
      /* The C remainder operator is undefined for negative numbers, so */
      /* The C remainder operator is undefined for negative numbers, so */
      /* a positive remainder calculation must be used here */
      /* a positive remainder calculation must be used here */
      if (e<0) {
      if (e<0) {
        adj=(-e)%3;
        adj=(-e)%3;
        if (adj!=0) adj=3-adj;
        if (adj!=0) adj=3-adj;
        }
        }
       else { /* e>0 */
       else { /* e>0 */
        adj=e%3;
        adj=e%3;
        }
        }
      e=e-adj;
      e=e-adj;
      /* if dealing with zero still produce an exponent which is a */
      /* if dealing with zero still produce an exponent which is a */
      /* multiple of three, as expected, but there will only be the */
      /* multiple of three, as expected, but there will only be the */
      /* one zero before the E, still.  Otherwise note the padding. */
      /* one zero before the E, still.  Otherwise note the padding. */
      if (!ISZERO(dn)) pre+=adj;
      if (!ISZERO(dn)) pre+=adj;
       else {  /* is zero */
       else {  /* is zero */
        if (adj!=0) {               /* 0.00Esnn needed */
        if (adj!=0) {               /* 0.00Esnn needed */
          e=e+3;
          e=e+3;
          pre=-(2-adj);
          pre=-(2-adj);
          }
          }
        } /* zero */
        } /* zero */
      } /* eng */
      } /* eng */
    } /* need exponent */
    } /* need exponent */
 
 
  /* lay out the digits of the coefficient, adding 0s and . as needed */
  /* lay out the digits of the coefficient, adding 0s and . as needed */
  u=*up;
  u=*up;
  if (pre>0) {                      /* xxx.xxx or xx00 (engineering) form */
  if (pre>0) {                      /* xxx.xxx or xx00 (engineering) form */
    Int n=pre;
    Int n=pre;
    for (; pre>0; pre--, c++, cut--) {
    for (; pre>0; pre--, c++, cut--) {
      if (cut<0) {                  /* need new Unit */
      if (cut<0) {                  /* need new Unit */
        if (up==dn->lsu) break;    /* out of input digits (pre>digits) */
        if (up==dn->lsu) break;    /* out of input digits (pre>digits) */
        up--;
        up--;
        cut=DECDPUN-1;
        cut=DECDPUN-1;
        u=*up;
        u=*up;
        }
        }
      TODIGIT(u, cut, c, pow);
      TODIGIT(u, cut, c, pow);
      }
      }
    if (n<dn->digits) {            /* more to come, after '.' */
    if (n<dn->digits) {            /* more to come, after '.' */
      *c='.'; c++;
      *c='.'; c++;
      for (;; c++, cut--) {
      for (;; c++, cut--) {
        if (cut<0) {                /* need new Unit */
        if (cut<0) {                /* need new Unit */
          if (up==dn->lsu) break;  /* out of input digits */
          if (up==dn->lsu) break;  /* out of input digits */
          up--;
          up--;
          cut=DECDPUN-1;
          cut=DECDPUN-1;
          u=*up;
          u=*up;
          }
          }
        TODIGIT(u, cut, c, pow);
        TODIGIT(u, cut, c, pow);
        }
        }
      }
      }
     else for (; pre>0; pre--, c++) *c='0'; /* 0 padding (for engineering) needed */
     else for (; pre>0; pre--, c++) *c='0'; /* 0 padding (for engineering) needed */
    }
    }
   else {                          /* 0.xxx or 0.000xxx form */
   else {                          /* 0.xxx or 0.000xxx form */
    *c='0'; c++;
    *c='0'; c++;
    *c='.'; c++;
    *c='.'; c++;
    for (; pre<0; pre++, c++) *c='0';    /* add any 0's after '.' */
    for (; pre<0; pre++, c++) *c='0';    /* add any 0's after '.' */
    for (; ; c++, cut--) {
    for (; ; c++, cut--) {
      if (cut<0) {                  /* need new Unit */
      if (cut<0) {                  /* need new Unit */
        if (up==dn->lsu) break;    /* out of input digits */
        if (up==dn->lsu) break;    /* out of input digits */
        up--;
        up--;
        cut=DECDPUN-1;
        cut=DECDPUN-1;
        u=*up;
        u=*up;
        }
        }
      TODIGIT(u, cut, c, pow);
      TODIGIT(u, cut, c, pow);
      }
      }
    }
    }
 
 
  /* Finally add the E-part, if needed.  It will never be 0, has a
  /* Finally add the E-part, if needed.  It will never be 0, has a
     base maximum and minimum of +999999999 through -999999999, but
     base maximum and minimum of +999999999 through -999999999, but
     could range down to -1999999998 for anormal numbers */
     could range down to -1999999998 for anormal numbers */
  if (e!=0) {
  if (e!=0) {
    Flag had=0;                /* 1=had non-zero */
    Flag had=0;                /* 1=had non-zero */
    *c='E'; c++;
    *c='E'; c++;
    *c='+'; c++;              /* assume positive */
    *c='+'; c++;              /* assume positive */
    u=e;                      /* .. */
    u=e;                      /* .. */
    if (e<0) {
    if (e<0) {
      *(c-1)='-';             /* oops, need - */
      *(c-1)='-';             /* oops, need - */
      u=-e;                   /* uInt, please */
      u=-e;                   /* uInt, please */
      }
      }
    /* lay out the exponent [_itoa or equivalent is not ANSI C] */
    /* lay out the exponent [_itoa or equivalent is not ANSI C] */
    for (cut=9; cut>=0; cut--) {
    for (cut=9; cut>=0; cut--) {
      TODIGIT(u, cut, c, pow);
      TODIGIT(u, cut, c, pow);
      if (*c=='0' && !had) continue;    /* skip leading zeros */
      if (*c=='0' && !had) continue;    /* skip leading zeros */
      had=1;                            /* had non-0 */
      had=1;                            /* had non-0 */
      c++;                              /* step for next */
      c++;                              /* step for next */
      } /* cut */
      } /* cut */
    }
    }
  *c='\0';          /* terminate the string (all paths) */
  *c='\0';          /* terminate the string (all paths) */
  return;
  return;
  } /* decToString */
  } /* decToString */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decAddOp -- add/subtract operation                                 */
/* decAddOp -- add/subtract operation                                 */
/*                                                                    */
/*                                                                    */
/*   This computes C = A + B                                          */
/*   This computes C = A + B                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*   negate is DECNEG if rhs should be negated, or 0 otherwise        */
/*   negate is DECNEG if rhs should be negated, or 0 otherwise        */
/*   status accumulates status for the caller                         */
/*   status accumulates status for the caller                         */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/* Inexact in status must be 0 for correct Exact zero sign in result  */
/* Inexact in status must be 0 for correct Exact zero sign in result  */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* If possible, the coefficient is calculated directly into C.        */
/* If possible, the coefficient is calculated directly into C.        */
/* However, if:                                                       */
/* However, if:                                                       */
/*   -- a digits+1 calculation is needed because the numbers are      */
/*   -- a digits+1 calculation is needed because the numbers are      */
/*      unaligned and span more than set->digits digits               */
/*      unaligned and span more than set->digits digits               */
/*   -- a carry to digits+1 digits looks possible                     */
/*   -- a carry to digits+1 digits looks possible                     */
/*   -- C is the same as A or B, and the result would destructively   */
/*   -- C is the same as A or B, and the result would destructively   */
/*      overlap the A or B coefficient                                */
/*      overlap the A or B coefficient                                */
/* then the result must be calculated into a temporary buffer.  In    */
/* then the result must be calculated into a temporary buffer.  In    */
/* this case a local (stack) buffer is used if possible, and only if  */
/* this case a local (stack) buffer is used if possible, and only if  */
/* too long for that does malloc become the final resort.             */
/* too long for that does malloc become the final resort.             */
/*                                                                    */
/*                                                                    */
/* Misalignment is handled as follows:                                */
/* Misalignment is handled as follows:                                */
/*   Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp.    */
/*   Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp.    */
/*   BPad: Apply the padding by a combination of shifting (whole      */
/*   BPad: Apply the padding by a combination of shifting (whole      */
/*         units) and multiplication (part units).                    */
/*         units) and multiplication (part units).                    */
/*                                                                    */
/*                                                                    */
/* Addition, especially x=x+1, is speed-critical.                     */
/* Addition, especially x=x+1, is speed-critical.                     */
/* The static buffer is larger than might be expected to allow for    */
/* The static buffer is larger than might be expected to allow for    */
/* calls from higher-level funtions (notable exp).                    */
/* calls from higher-level funtions (notable exp).                    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static decNumber * decAddOp(decNumber *res, const decNumber *lhs,
static decNumber * decAddOp(decNumber *res, const decNumber *lhs,
                            const decNumber *rhs, decContext *set,
                            const decNumber *rhs, decContext *set,
                            uByte negate, uInt *status) {
                            uByte negate, uInt *status) {
  #if DECSUBSET
  #if DECSUBSET
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *allocrhs=NULL;        /* .., rhs */
  decNumber *allocrhs=NULL;        /* .., rhs */
  #endif
  #endif
  Int   rhsshift;                  /* working shift (in Units) */
  Int   rhsshift;                  /* working shift (in Units) */
  Int   maxdigits;                 /* longest logical length */
  Int   maxdigits;                 /* longest logical length */
  Int   mult;                      /* multiplier */
  Int   mult;                      /* multiplier */
  Int   residue;                   /* rounding accumulator */
  Int   residue;                   /* rounding accumulator */
  uByte bits;                      /* result bits */
  uByte bits;                      /* result bits */
  Flag  diffsign;                  /* non-0 if arguments have different sign */
  Flag  diffsign;                  /* non-0 if arguments have different sign */
  Unit  *acc;                      /* accumulator for result */
  Unit  *acc;                      /* accumulator for result */
  Unit  accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */
  Unit  accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */
                                   /* allocations when called from */
                                   /* allocations when called from */
                                   /* other operations, notable exp] */
                                   /* other operations, notable exp] */
  Unit  *allocacc=NULL;            /* -> allocated acc buffer, iff allocated */
  Unit  *allocacc=NULL;            /* -> allocated acc buffer, iff allocated */
  Int   reqdigits=set->digits;     /* local copy; requested DIGITS */
  Int   reqdigits=set->digits;     /* local copy; requested DIGITS */
  Int   padding;                   /* work */
  Int   padding;                   /* work */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                             /* protect allocated storage */
  do {                             /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operands and set lostDigits status, as needed */
      /* reduce operands and set lostDigits status, as needed */
      if (lhs->digits>reqdigits) {
      if (lhs->digits>reqdigits) {
        alloclhs=decRoundOperand(lhs, set, status);
        alloclhs=decRoundOperand(lhs, set, status);
        if (alloclhs==NULL) break;
        if (alloclhs==NULL) break;
        lhs=alloclhs;
        lhs=alloclhs;
        }
        }
      if (rhs->digits>reqdigits) {
      if (rhs->digits>reqdigits) {
        allocrhs=decRoundOperand(rhs, set, status);
        allocrhs=decRoundOperand(rhs, set, status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    /* [following code does not require input rounding] */
    /* [following code does not require input rounding] */
 
 
    /* note whether signs differ [used all paths] */
    /* note whether signs differ [used all paths] */
    diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG);
    diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG);
 
 
    /* handle infinities and NaNs */
    /* handle infinities and NaNs */
    if (SPECIALARGS) {                  /* a special bit set */
    if (SPECIALARGS) {                  /* a special bit set */
      if (SPECIALARGS & (DECSNAN | DECNAN))  /* a NaN */
      if (SPECIALARGS & (DECSNAN | DECNAN))  /* a NaN */
        decNaNs(res, lhs, rhs, set, status);
        decNaNs(res, lhs, rhs, set, status);
       else { /* one or two infinities */
       else { /* one or two infinities */
        if (decNumberIsInfinite(lhs)) { /* LHS is infinity */
        if (decNumberIsInfinite(lhs)) { /* LHS is infinity */
          /* two infinities with different signs is invalid */
          /* two infinities with different signs is invalid */
          if (decNumberIsInfinite(rhs) && diffsign) {
          if (decNumberIsInfinite(rhs) && diffsign) {
            *status|=DEC_Invalid_operation;
            *status|=DEC_Invalid_operation;
            break;
            break;
            }
            }
          bits=lhs->bits & DECNEG;      /* get sign from LHS */
          bits=lhs->bits & DECNEG;      /* get sign from LHS */
          }
          }
         else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */
         else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */
        bits|=DECINF;
        bits|=DECINF;
        decNumberZero(res);
        decNumberZero(res);
        res->bits=bits;                 /* set +/- infinity */
        res->bits=bits;                 /* set +/- infinity */
        } /* an infinity */
        } /* an infinity */
      break;
      break;
      }
      }
 
 
    /* Quick exit for add 0s; return the non-0, modified as need be */
    /* Quick exit for add 0s; return the non-0, modified as need be */
    if (ISZERO(lhs)) {
    if (ISZERO(lhs)) {
      Int adjust;                       /* work */
      Int adjust;                       /* work */
      Int lexp=lhs->exponent;           /* save in case LHS==RES */
      Int lexp=lhs->exponent;           /* save in case LHS==RES */
      bits=lhs->bits;                   /* .. */
      bits=lhs->bits;                   /* .. */
      residue=0;                 /* clear accumulator */
      residue=0;                 /* clear accumulator */
      decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */
      decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */
      res->bits^=negate;                /* flip if rhs was negated */
      res->bits^=negate;                /* flip if rhs was negated */
      #if DECSUBSET
      #if DECSUBSET
      if (set->extended) {              /* exponents on zeros count */
      if (set->extended) {              /* exponents on zeros count */
      #endif
      #endif
        /* exponent will be the lower of the two */
        /* exponent will be the lower of the two */
        adjust=lexp-res->exponent;      /* adjustment needed [if -ve] */
        adjust=lexp-res->exponent;      /* adjustment needed [if -ve] */
        if (ISZERO(res)) {              /* both 0: special IEEE 854 rules */
        if (ISZERO(res)) {              /* both 0: special IEEE 854 rules */
          if (adjust<0) res->exponent=lexp;  /* set exponent */
          if (adjust<0) res->exponent=lexp;  /* set exponent */
          /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */
          /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */
          if (diffsign) {
          if (diffsign) {
            if (set->round!=DEC_ROUND_FLOOR) res->bits=0;
            if (set->round!=DEC_ROUND_FLOOR) res->bits=0;
             else res->bits=DECNEG;     /* preserve 0 sign */
             else res->bits=DECNEG;     /* preserve 0 sign */
            }
            }
          }
          }
         else { /* non-0 res */
         else { /* non-0 res */
          if (adjust<0) {     /* 0-padding needed */
          if (adjust<0) {     /* 0-padding needed */
            if ((res->digits-adjust)>set->digits) {
            if ((res->digits-adjust)>set->digits) {
              adjust=res->digits-set->digits;     /* to fit exactly */
              adjust=res->digits-set->digits;     /* to fit exactly */
              *status|=DEC_Rounded;               /* [but exact] */
              *status|=DEC_Rounded;               /* [but exact] */
              }
              }
            res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
            res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
            res->exponent+=adjust;                /* set the exponent. */
            res->exponent+=adjust;                /* set the exponent. */
            }
            }
          } /* non-0 res */
          } /* non-0 res */
      #if DECSUBSET
      #if DECSUBSET
        } /* extended */
        } /* extended */
      #endif
      #endif
      decFinish(res, set, &residue, status);      /* clean and finalize */
      decFinish(res, set, &residue, status);      /* clean and finalize */
      break;}
      break;}
 
 
    if (ISZERO(rhs)) {                  /* [lhs is non-zero] */
    if (ISZERO(rhs)) {                  /* [lhs is non-zero] */
      Int adjust;                       /* work */
      Int adjust;                       /* work */
      Int rexp=rhs->exponent;           /* save in case RHS==RES */
      Int rexp=rhs->exponent;           /* save in case RHS==RES */
      bits=rhs->bits;                   /* be clean */
      bits=rhs->bits;                   /* be clean */
      residue=0;                 /* clear accumulator */
      residue=0;                 /* clear accumulator */
      decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */
      decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */
      #if DECSUBSET
      #if DECSUBSET
      if (set->extended) {              /* exponents on zeros count */
      if (set->extended) {              /* exponents on zeros count */
      #endif
      #endif
        /* exponent will be the lower of the two */
        /* exponent will be the lower of the two */
        /* [0-0 case handled above] */
        /* [0-0 case handled above] */
        adjust=rexp-res->exponent;      /* adjustment needed [if -ve] */
        adjust=rexp-res->exponent;      /* adjustment needed [if -ve] */
        if (adjust<0) {      /* 0-padding needed */
        if (adjust<0) {      /* 0-padding needed */
          if ((res->digits-adjust)>set->digits) {
          if ((res->digits-adjust)>set->digits) {
            adjust=res->digits-set->digits;     /* to fit exactly */
            adjust=res->digits-set->digits;     /* to fit exactly */
            *status|=DEC_Rounded;               /* [but exact] */
            *status|=DEC_Rounded;               /* [but exact] */
            }
            }
          res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
          res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
          res->exponent+=adjust;                /* set the exponent. */
          res->exponent+=adjust;                /* set the exponent. */
          }
          }
      #if DECSUBSET
      #if DECSUBSET
        } /* extended */
        } /* extended */
      #endif
      #endif
      decFinish(res, set, &residue, status);      /* clean and finalize */
      decFinish(res, set, &residue, status);      /* clean and finalize */
      break;}
      break;}
 
 
    /* [NB: both fastpath and mainpath code below assume these cases */
    /* [NB: both fastpath and mainpath code below assume these cases */
    /* (notably 0-0) have already been handled] */
    /* (notably 0-0) have already been handled] */
 
 
    /* calculate the padding needed to align the operands */
    /* calculate the padding needed to align the operands */
    padding=rhs->exponent-lhs->exponent;
    padding=rhs->exponent-lhs->exponent;
 
 
    /* Fastpath cases where the numbers are aligned and normal, the RHS */
    /* Fastpath cases where the numbers are aligned and normal, the RHS */
    /* is all in one unit, no operand rounding is needed, and no carry, */
    /* is all in one unit, no operand rounding is needed, and no carry, */
    /* lengthening, or borrow is needed */
    /* lengthening, or borrow is needed */
    if (padding==0
    if (padding==0
        && rhs->digits<=DECDPUN
        && rhs->digits<=DECDPUN
        && rhs->exponent>=set->emin     /* [some normals drop through] */
        && rhs->exponent>=set->emin     /* [some normals drop through] */
        && rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */
        && rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */
        && rhs->digits<=reqdigits
        && rhs->digits<=reqdigits
        && lhs->digits<=reqdigits) {
        && lhs->digits<=reqdigits) {
      Int partial=*lhs->lsu;
      Int partial=*lhs->lsu;
      if (!diffsign) {                  /* adding */
      if (!diffsign) {                  /* adding */
        partial+=*rhs->lsu;
        partial+=*rhs->lsu;
        if ((partial<=DECDPUNMAX)       /* result fits in unit */
        if ((partial<=DECDPUNMAX)       /* result fits in unit */
         && (lhs->digits>=DECDPUN ||    /* .. and no digits-count change */
         && (lhs->digits>=DECDPUN ||    /* .. and no digits-count change */
             partial<(Int)powers[lhs->digits])) { /* .. */
             partial<(Int)powers[lhs->digits])) { /* .. */
          if (res!=lhs) decNumberCopy(res, lhs);  /* not in place */
          if (res!=lhs) decNumberCopy(res, lhs);  /* not in place */
          *res->lsu=(Unit)partial;      /* [copy could have overwritten RHS] */
          *res->lsu=(Unit)partial;      /* [copy could have overwritten RHS] */
          break;
          break;
          }
          }
        /* else drop out for careful add */
        /* else drop out for careful add */
        }
        }
       else {                           /* signs differ */
       else {                           /* signs differ */
        partial-=*rhs->lsu;
        partial-=*rhs->lsu;
        if (partial>0) { /* no borrow needed, and non-0 result */
        if (partial>0) { /* no borrow needed, and non-0 result */
          if (res!=lhs) decNumberCopy(res, lhs);  /* not in place */
          if (res!=lhs) decNumberCopy(res, lhs);  /* not in place */
          *res->lsu=(Unit)partial;
          *res->lsu=(Unit)partial;
          /* this could have reduced digits [but result>0] */
          /* this could have reduced digits [but result>0] */
          res->digits=decGetDigits(res->lsu, D2U(res->digits));
          res->digits=decGetDigits(res->lsu, D2U(res->digits));
          break;
          break;
          }
          }
        /* else drop out for careful subtract */
        /* else drop out for careful subtract */
        }
        }
      }
      }
 
 
    /* Now align (pad) the lhs or rhs so they can be added or */
    /* Now align (pad) the lhs or rhs so they can be added or */
    /* subtracted, as necessary.  If one number is much larger than */
    /* subtracted, as necessary.  If one number is much larger than */
    /* the other (that is, if in plain form there is a least one */
    /* the other (that is, if in plain form there is a least one */
    /* digit between the lowest digit of one and the highest of the */
    /* digit between the lowest digit of one and the highest of the */
    /* other) padding with up to DIGITS-1 trailing zeros may be */
    /* other) padding with up to DIGITS-1 trailing zeros may be */
    /* needed; then apply rounding (as exotic rounding modes may be */
    /* needed; then apply rounding (as exotic rounding modes may be */
    /* affected by the residue). */
    /* affected by the residue). */
    rhsshift=0;                /* rhs shift to left (padding) in Units */
    rhsshift=0;                /* rhs shift to left (padding) in Units */
    bits=lhs->bits;           /* assume sign is that of LHS */
    bits=lhs->bits;           /* assume sign is that of LHS */
    mult=1;                   /* likely multiplier */
    mult=1;                   /* likely multiplier */
 
 
    /* [if padding==0 the operands are aligned; no padding is needed] */
    /* [if padding==0 the operands are aligned; no padding is needed] */
    if (padding!=0) {
    if (padding!=0) {
      /* some padding needed; always pad the RHS, as any required */
      /* some padding needed; always pad the RHS, as any required */
      /* padding can then be effected by a simple combination of */
      /* padding can then be effected by a simple combination of */
      /* shifts and a multiply */
      /* shifts and a multiply */
      Flag swapped=0;
      Flag swapped=0;
      if (padding<0) {                   /* LHS needs the padding */
      if (padding<0) {                   /* LHS needs the padding */
        const decNumber *t;
        const decNumber *t;
        padding=-padding;               /* will be +ve */
        padding=-padding;               /* will be +ve */
        bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */
        bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */
        t=lhs; lhs=rhs; rhs=t;
        t=lhs; lhs=rhs; rhs=t;
        swapped=1;
        swapped=1;
        }
        }
 
 
      /* If, after pad, rhs would be longer than lhs by digits+1 or */
      /* If, after pad, rhs would be longer than lhs by digits+1 or */
      /* more then lhs cannot affect the answer, except as a residue, */
      /* more then lhs cannot affect the answer, except as a residue, */
      /* so only need to pad up to a length of DIGITS+1. */
      /* so only need to pad up to a length of DIGITS+1. */
      if (rhs->digits+padding > lhs->digits+reqdigits+1) {
      if (rhs->digits+padding > lhs->digits+reqdigits+1) {
        /* The RHS is sufficient */
        /* The RHS is sufficient */
        /* for residue use the relative sign indication... */
        /* for residue use the relative sign indication... */
        Int shift=reqdigits-rhs->digits;     /* left shift needed */
        Int shift=reqdigits-rhs->digits;     /* left shift needed */
        residue=1;                           /* residue for rounding */
        residue=1;                           /* residue for rounding */
        if (diffsign) residue=-residue;      /* signs differ */
        if (diffsign) residue=-residue;      /* signs differ */
        /* copy, shortening if necessary */
        /* copy, shortening if necessary */
        decCopyFit(res, rhs, set, &residue, status);
        decCopyFit(res, rhs, set, &residue, status);
        /* if it was already shorter, then need to pad with zeros */
        /* if it was already shorter, then need to pad with zeros */
        if (shift>0) {
        if (shift>0) {
          res->digits=decShiftToMost(res->lsu, res->digits, shift);
          res->digits=decShiftToMost(res->lsu, res->digits, shift);
          res->exponent-=shift;              /* adjust the exponent. */
          res->exponent-=shift;              /* adjust the exponent. */
          }
          }
        /* flip the result sign if unswapped and rhs was negated */
        /* flip the result sign if unswapped and rhs was negated */
        if (!swapped) res->bits^=negate;
        if (!swapped) res->bits^=negate;
        decFinish(res, set, &residue, status);    /* done */
        decFinish(res, set, &residue, status);    /* done */
        break;}
        break;}
 
 
      /* LHS digits may affect result */
      /* LHS digits may affect result */
      rhsshift=D2U(padding+1)-1;        /* this much by Unit shift .. */
      rhsshift=D2U(padding+1)-1;        /* this much by Unit shift .. */
      mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */
      mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */
      } /* padding needed */
      } /* padding needed */
 
 
    if (diffsign) mult=-mult;           /* signs differ */
    if (diffsign) mult=-mult;           /* signs differ */
 
 
    /* determine the longer operand */
    /* determine the longer operand */
    maxdigits=rhs->digits+padding;      /* virtual length of RHS */
    maxdigits=rhs->digits+padding;      /* virtual length of RHS */
    if (lhs->digits>maxdigits) maxdigits=lhs->digits;
    if (lhs->digits>maxdigits) maxdigits=lhs->digits;
 
 
    /* Decide on the result buffer to use; if possible place directly */
    /* Decide on the result buffer to use; if possible place directly */
    /* into result. */
    /* into result. */
    acc=res->lsu;                       /* assume add direct to result */
    acc=res->lsu;                       /* assume add direct to result */
    /* If destructive overlap, or the number is too long, or a carry or */
    /* If destructive overlap, or the number is too long, or a carry or */
    /* borrow to DIGITS+1 might be possible, a buffer must be used. */
    /* borrow to DIGITS+1 might be possible, a buffer must be used. */
    /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */
    /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */
    if ((maxdigits>=reqdigits)          /* is, or could be, too large */
    if ((maxdigits>=reqdigits)          /* is, or could be, too large */
     || (res==rhs && rhsshift>0)) {      /* destructive overlap */
     || (res==rhs && rhsshift>0)) {      /* destructive overlap */
      /* buffer needed, choose it; units for maxdigits digits will be */
      /* buffer needed, choose it; units for maxdigits digits will be */
      /* needed, +1 Unit for carry or borrow */
      /* needed, +1 Unit for carry or borrow */
      Int need=D2U(maxdigits)+1;
      Int need=D2U(maxdigits)+1;
      acc=accbuff;                      /* assume use local buffer */
      acc=accbuff;                      /* assume use local buffer */
      if (need*sizeof(Unit)>sizeof(accbuff)) {
      if (need*sizeof(Unit)>sizeof(accbuff)) {
        /* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */
        /* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */
        allocacc=(Unit *)malloc(need*sizeof(Unit));
        allocacc=(Unit *)malloc(need*sizeof(Unit));
        if (allocacc==NULL) {           /* hopeless -- abandon */
        if (allocacc==NULL) {           /* hopeless -- abandon */
          *status|=DEC_Insufficient_storage;
          *status|=DEC_Insufficient_storage;
          break;}
          break;}
        acc=allocacc;
        acc=allocacc;
        }
        }
      }
      }
 
 
    res->bits=(uByte)(bits&DECNEG);     /* it's now safe to overwrite.. */
    res->bits=(uByte)(bits&DECNEG);     /* it's now safe to overwrite.. */
    res->exponent=lhs->exponent;        /* .. operands (even if aliased) */
    res->exponent=lhs->exponent;        /* .. operands (even if aliased) */
 
 
    #if DECTRACE
    #if DECTRACE
      decDumpAr('A', lhs->lsu, D2U(lhs->digits));
      decDumpAr('A', lhs->lsu, D2U(lhs->digits));
      decDumpAr('B', rhs->lsu, D2U(rhs->digits));
      decDumpAr('B', rhs->lsu, D2U(rhs->digits));
      printf("  :h: %ld %ld\n", rhsshift, mult);
      printf("  :h: %ld %ld\n", rhsshift, mult);
    #endif
    #endif
 
 
    /* add [A+B*m] or subtract [A+B*(-m)] */
    /* add [A+B*m] or subtract [A+B*(-m)] */
    res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits),
    res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits),
                              rhs->lsu, D2U(rhs->digits),
                              rhs->lsu, D2U(rhs->digits),
                              rhsshift, acc, mult)
                              rhsshift, acc, mult)
               *DECDPUN;           /* [units -> digits] */
               *DECDPUN;           /* [units -> digits] */
    if (res->digits<0) {    /* borrowed... */
    if (res->digits<0) {    /* borrowed... */
      res->digits=-res->digits;
      res->digits=-res->digits;
      res->bits^=DECNEG;           /* flip the sign */
      res->bits^=DECNEG;           /* flip the sign */
      }
      }
    #if DECTRACE
    #if DECTRACE
      decDumpAr('+', acc, D2U(res->digits));
      decDumpAr('+', acc, D2U(res->digits));
    #endif
    #endif
 
 
    /* If a buffer was used the result must be copied back, possibly */
    /* If a buffer was used the result must be copied back, possibly */
    /* shortening.  (If no buffer was used then the result must have */
    /* shortening.  (If no buffer was used then the result must have */
    /* fit, so can't need rounding and residue must be 0.) */
    /* fit, so can't need rounding and residue must be 0.) */
    residue=0;                      /* clear accumulator */
    residue=0;                      /* clear accumulator */
    if (acc!=res->lsu) {
    if (acc!=res->lsu) {
      #if DECSUBSET
      #if DECSUBSET
      if (set->extended) {         /* round from first significant digit */
      if (set->extended) {         /* round from first significant digit */
      #endif
      #endif
        /* remove leading zeros that were added due to rounding up to */
        /* remove leading zeros that were added due to rounding up to */
        /* integral Units -- before the test for rounding. */
        /* integral Units -- before the test for rounding. */
        if (res->digits>reqdigits)
        if (res->digits>reqdigits)
          res->digits=decGetDigits(acc, D2U(res->digits));
          res->digits=decGetDigits(acc, D2U(res->digits));
        decSetCoeff(res, set, acc, res->digits, &residue, status);
        decSetCoeff(res, set, acc, res->digits, &residue, status);
      #if DECSUBSET
      #if DECSUBSET
        }
        }
       else { /* subset arithmetic rounds from original significant digit */
       else { /* subset arithmetic rounds from original significant digit */
        /* May have an underestimate.  This only occurs when both */
        /* May have an underestimate.  This only occurs when both */
        /* numbers fit in DECDPUN digits and are padding with a */
        /* numbers fit in DECDPUN digits and are padding with a */
        /* negative multiple (-10, -100...) and the top digit(s) become */
        /* negative multiple (-10, -100...) and the top digit(s) become */
        /* 0.  (This only matters when using X3.274 rules where the */
        /* 0.  (This only matters when using X3.274 rules where the */
        /* leading zero could be included in the rounding.) */
        /* leading zero could be included in the rounding.) */
        if (res->digits<maxdigits) {
        if (res->digits<maxdigits) {
          *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */
          *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */
          res->digits=maxdigits;
          res->digits=maxdigits;
          }
          }
         else {
         else {
          /* remove leading zeros that added due to rounding up to */
          /* remove leading zeros that added due to rounding up to */
          /* integral Units (but only those in excess of the original */
          /* integral Units (but only those in excess of the original */
          /* maxdigits length, unless extended) before test for rounding. */
          /* maxdigits length, unless extended) before test for rounding. */
          if (res->digits>reqdigits) {
          if (res->digits>reqdigits) {
            res->digits=decGetDigits(acc, D2U(res->digits));
            res->digits=decGetDigits(acc, D2U(res->digits));
            if (res->digits<maxdigits) res->digits=maxdigits;
            if (res->digits<maxdigits) res->digits=maxdigits;
            }
            }
          }
          }
        decSetCoeff(res, set, acc, res->digits, &residue, status);
        decSetCoeff(res, set, acc, res->digits, &residue, status);
        /* Now apply rounding if needed before removing leading zeros. */
        /* Now apply rounding if needed before removing leading zeros. */
        /* This is safe because subnormals are not a possibility */
        /* This is safe because subnormals are not a possibility */
        if (residue!=0) {
        if (residue!=0) {
          decApplyRound(res, set, residue, status);
          decApplyRound(res, set, residue, status);
          residue=0;                  /* did what needed to be done */
          residue=0;                  /* did what needed to be done */
          }
          }
        } /* subset */
        } /* subset */
      #endif
      #endif
      } /* used buffer */
      } /* used buffer */
 
 
    /* strip leading zeros [these were left on in case of subset subtract] */
    /* strip leading zeros [these were left on in case of subset subtract] */
    res->digits=decGetDigits(res->lsu, D2U(res->digits));
    res->digits=decGetDigits(res->lsu, D2U(res->digits));
 
 
    /* apply checks and rounding */
    /* apply checks and rounding */
    decFinish(res, set, &residue, status);
    decFinish(res, set, &residue, status);
 
 
    /* "When the sum of two operands with opposite signs is exactly */
    /* "When the sum of two operands with opposite signs is exactly */
    /* zero, the sign of that sum shall be '+' in all rounding modes */
    /* zero, the sign of that sum shall be '+' in all rounding modes */
    /* except round toward -Infinity, in which mode that sign shall be */
    /* except round toward -Infinity, in which mode that sign shall be */
    /* '-'."  [Subset zeros also never have '-', set by decFinish.] */
    /* '-'."  [Subset zeros also never have '-', set by decFinish.] */
    if (ISZERO(res) && diffsign
    if (ISZERO(res) && diffsign
     #if DECSUBSET
     #if DECSUBSET
     && set->extended
     && set->extended
     #endif
     #endif
     && (*status&DEC_Inexact)==0) {
     && (*status&DEC_Inexact)==0) {
      if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG;   /* sign - */
      if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG;   /* sign - */
                                  else res->bits&=~DECNEG;  /* sign + */
                                  else res->bits&=~DECNEG;  /* sign + */
      }
      }
    } while(0);                               /* end protected */
    } while(0);                               /* end protected */
 
 
  if (allocacc!=NULL) free(allocacc);        /* drop any storage used */
  if (allocacc!=NULL) free(allocacc);        /* drop any storage used */
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs!=NULL) free(allocrhs);        /* .. */
  if (allocrhs!=NULL) free(allocrhs);        /* .. */
  if (alloclhs!=NULL) free(alloclhs);        /* .. */
  if (alloclhs!=NULL) free(alloclhs);        /* .. */
  #endif
  #endif
  return res;
  return res;
  } /* decAddOp */
  } /* decAddOp */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decDivideOp -- division operation                                  */
/* decDivideOp -- division operation                                  */
/*                                                                    */
/*                                                                    */
/*  This routine performs the calculations for all four division      */
/*  This routine performs the calculations for all four division      */
/*  operators (divide, divideInteger, remainder, remainderNear).      */
/*  operators (divide, divideInteger, remainder, remainderNear).      */
/*                                                                    */
/*                                                                    */
/*  C=A op B                                                          */
/*  C=A op B                                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X/X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X/X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*   op  is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively.    */
/*   op  is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively.    */
/*   status is the usual accumulator                                  */
/*   status is the usual accumulator                                  */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/*   The underlying algorithm of this routine is the same as in the   */
/*   The underlying algorithm of this routine is the same as in the   */
/*   1981 S/370 implementation, that is, non-restoring long division  */
/*   1981 S/370 implementation, that is, non-restoring long division  */
/*   with bi-unit (rather than bi-digit) estimation for each unit     */
/*   with bi-unit (rather than bi-digit) estimation for each unit     */
/*   multiplier.  In this pseudocode overview, complications for the  */
/*   multiplier.  In this pseudocode overview, complications for the  */
/*   Remainder operators and division residues for exact rounding are */
/*   Remainder operators and division residues for exact rounding are */
/*   omitted for clarity.                                             */
/*   omitted for clarity.                                             */
/*                                                                    */
/*                                                                    */
/*     Prepare operands and handle special values                     */
/*     Prepare operands and handle special values                     */
/*     Test for x/0 and then 0/x                                      */
/*     Test for x/0 and then 0/x                                      */
/*     Exp =Exp1 - Exp2                                               */
/*     Exp =Exp1 - Exp2                                               */
/*     Exp =Exp +len(var1) -len(var2)                                 */
/*     Exp =Exp +len(var1) -len(var2)                                 */
/*     Sign=Sign1 * Sign2                                             */
/*     Sign=Sign1 * Sign2                                             */
/*     Pad accumulator (Var1) to double-length with 0's (pad1)        */
/*     Pad accumulator (Var1) to double-length with 0's (pad1)        */
/*     Pad Var2 to same length as Var1                                */
/*     Pad Var2 to same length as Var1                                */
/*     msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round  */
/*     msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round  */
/*     have=0                                                         */
/*     have=0                                                         */
/*     Do until (have=digits+1 OR residue=0)                          */
/*     Do until (have=digits+1 OR residue=0)                          */
/*       if exp<0 then if integer divide/residue then leave           */
/*       if exp<0 then if integer divide/residue then leave           */
/*       this_unit=0                                                  */
/*       this_unit=0                                                  */
/*       Do forever                                                   */
/*       Do forever                                                   */
/*          compare numbers                                           */
/*          compare numbers                                           */
/*          if <0 then leave inner_loop                               */
/*          if <0 then leave inner_loop                               */
/*          if =0 then (* quick exit without subtract *) do           */
/*          if =0 then (* quick exit without subtract *) do           */
/*             this_unit=this_unit+1; output this_unit                */
/*             this_unit=this_unit+1; output this_unit                */
/*             leave outer_loop; end                                  */
/*             leave outer_loop; end                                  */
/*          Compare lengths of numbers (mantissae):                   */
/*          Compare lengths of numbers (mantissae):                   */
/*          If same then tops2=msu2pair -- {units 1&2 of var2}        */
/*          If same then tops2=msu2pair -- {units 1&2 of var2}        */
/*                  else tops2=msu2plus -- {0, unit 1 of var2}        */
/*                  else tops2=msu2plus -- {0, unit 1 of var2}        */
/*          tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */
/*          tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */
/*          mult=tops1/tops2  -- Good and safe guess at divisor       */
/*          mult=tops1/tops2  -- Good and safe guess at divisor       */
/*          if mult=0 then mult=1                                     */
/*          if mult=0 then mult=1                                     */
/*          this_unit=this_unit+mult                                  */
/*          this_unit=this_unit+mult                                  */
/*          subtract                                                  */
/*          subtract                                                  */
/*          end inner_loop                                            */
/*          end inner_loop                                            */
/*        if have\=0 | this_unit\=0 then do                           */
/*        if have\=0 | this_unit\=0 then do                           */
/*          output this_unit                                          */
/*          output this_unit                                          */
/*          have=have+1; end                                          */
/*          have=have+1; end                                          */
/*        var2=var2/10                                                */
/*        var2=var2/10                                                */
/*        exp=exp-1                                                   */
/*        exp=exp-1                                                   */
/*        end outer_loop                                              */
/*        end outer_loop                                              */
/*     exp=exp+1   -- set the proper exponent                         */
/*     exp=exp+1   -- set the proper exponent                         */
/*     if have=0 then generate answer=0                               */
/*     if have=0 then generate answer=0                               */
/*     Return (Result is defined by Var1)                             */
/*     Return (Result is defined by Var1)                             */
/*                                                                    */
/*                                                                    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* Two working buffers are needed during the division; one (digits+   */
/* Two working buffers are needed during the division; one (digits+   */
/* 1) to accumulate the result, and the other (up to 2*digits+1) for  */
/* 1) to accumulate the result, and the other (up to 2*digits+1) for  */
/* long subtractions.  These are acc and var1 respectively.           */
/* long subtractions.  These are acc and var1 respectively.           */
/* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/
/* var1 is a copy of the lhs coefficient, var2 is the rhs coefficient.*/
/* The static buffers may be larger than might be expected to allow   */
/* The static buffers may be larger than might be expected to allow   */
/* for calls from higher-level funtions (notable exp).                */
/* for calls from higher-level funtions (notable exp).                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static decNumber * decDivideOp(decNumber *res,
static decNumber * decDivideOp(decNumber *res,
                               const decNumber *lhs, const decNumber *rhs,
                               const decNumber *lhs, const decNumber *rhs,
                               decContext *set, Flag op, uInt *status) {
                               decContext *set, Flag op, uInt *status) {
  #if DECSUBSET
  #if DECSUBSET
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *allocrhs=NULL;        /* .., rhs */
  decNumber *allocrhs=NULL;        /* .., rhs */
  #endif
  #endif
  Unit  accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */
  Unit  accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */
  Unit  *acc=accbuff;              /* -> accumulator array for result */
  Unit  *acc=accbuff;              /* -> accumulator array for result */
  Unit  *allocacc=NULL;            /* -> allocated buffer, iff allocated */
  Unit  *allocacc=NULL;            /* -> allocated buffer, iff allocated */
  Unit  *accnext;                  /* -> where next digit will go */
  Unit  *accnext;                  /* -> where next digit will go */
  Int   acclength;                 /* length of acc needed [Units] */
  Int   acclength;                 /* length of acc needed [Units] */
  Int   accunits;                  /* count of units accumulated */
  Int   accunits;                  /* count of units accumulated */
  Int   accdigits;                 /* count of digits accumulated */
  Int   accdigits;                 /* count of digits accumulated */
 
 
  Unit  varbuff[SD2U(DECBUFFER*2+DECDPUN)*sizeof(Unit)]; /* buffer for var1 */
  Unit  varbuff[SD2U(DECBUFFER*2+DECDPUN)*sizeof(Unit)]; /* buffer for var1 */
  Unit  *var1=varbuff;             /* -> var1 array for long subtraction */
  Unit  *var1=varbuff;             /* -> var1 array for long subtraction */
  Unit  *varalloc=NULL;            /* -> allocated buffer, iff used */
  Unit  *varalloc=NULL;            /* -> allocated buffer, iff used */
  Unit  *msu1;                     /* -> msu of var1 */
  Unit  *msu1;                     /* -> msu of var1 */
 
 
  const Unit *var2;                /* -> var2 array */
  const Unit *var2;                /* -> var2 array */
  const Unit *msu2;                /* -> msu of var2 */
  const Unit *msu2;                /* -> msu of var2 */
  Int   msu2plus;                  /* msu2 plus one [does not vary] */
  Int   msu2plus;                  /* msu2 plus one [does not vary] */
  eInt  msu2pair;                  /* msu2 pair plus one [does not vary] */
  eInt  msu2pair;                  /* msu2 pair plus one [does not vary] */
 
 
  Int   var1units, var2units;      /* actual lengths */
  Int   var1units, var2units;      /* actual lengths */
  Int   var2ulen;                  /* logical length (units) */
  Int   var2ulen;                  /* logical length (units) */
  Int   var1initpad=0;              /* var1 initial padding (digits) */
  Int   var1initpad=0;              /* var1 initial padding (digits) */
  Int   maxdigits;                 /* longest LHS or required acc length */
  Int   maxdigits;                 /* longest LHS or required acc length */
  Int   mult;                      /* multiplier for subtraction */
  Int   mult;                      /* multiplier for subtraction */
  Unit  thisunit;                  /* current unit being accumulated */
  Unit  thisunit;                  /* current unit being accumulated */
  Int   residue;                   /* for rounding */
  Int   residue;                   /* for rounding */
  Int   reqdigits=set->digits;     /* requested DIGITS */
  Int   reqdigits=set->digits;     /* requested DIGITS */
  Int   exponent;                  /* working exponent */
  Int   exponent;                  /* working exponent */
  Int   maxexponent=0;              /* DIVIDE maximum exponent if unrounded */
  Int   maxexponent=0;              /* DIVIDE maximum exponent if unrounded */
  uByte bits;                      /* working sign */
  uByte bits;                      /* working sign */
  Unit  *target;                   /* work */
  Unit  *target;                   /* work */
  const Unit *source;              /* .. */
  const Unit *source;              /* .. */
  uInt  const *pow;                /* .. */
  uInt  const *pow;                /* .. */
  Int   shift, cut;                /* .. */
  Int   shift, cut;                /* .. */
  #if DECSUBSET
  #if DECSUBSET
  Int   dropped;                   /* work */
  Int   dropped;                   /* work */
  #endif
  #endif
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                             /* protect allocated storage */
  do {                             /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operands and set lostDigits status, as needed */
      /* reduce operands and set lostDigits status, as needed */
      if (lhs->digits>reqdigits) {
      if (lhs->digits>reqdigits) {
        alloclhs=decRoundOperand(lhs, set, status);
        alloclhs=decRoundOperand(lhs, set, status);
        if (alloclhs==NULL) break;
        if (alloclhs==NULL) break;
        lhs=alloclhs;
        lhs=alloclhs;
        }
        }
      if (rhs->digits>reqdigits) {
      if (rhs->digits>reqdigits) {
        allocrhs=decRoundOperand(rhs, set, status);
        allocrhs=decRoundOperand(rhs, set, status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    /* [following code does not require input rounding] */
    /* [following code does not require input rounding] */
 
 
    bits=(lhs->bits^rhs->bits)&DECNEG;  /* assumed sign for divisions */
    bits=(lhs->bits^rhs->bits)&DECNEG;  /* assumed sign for divisions */
 
 
    /* handle infinities and NaNs */
    /* handle infinities and NaNs */
    if (SPECIALARGS) {                  /* a special bit set */
    if (SPECIALARGS) {                  /* a special bit set */
      if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
      if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
        decNaNs(res, lhs, rhs, set, status);
        decNaNs(res, lhs, rhs, set, status);
        break;
        break;
        }
        }
      /* one or two infinities */
      /* one or two infinities */
      if (decNumberIsInfinite(lhs)) {   /* LHS (dividend) is infinite */
      if (decNumberIsInfinite(lhs)) {   /* LHS (dividend) is infinite */
        if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */
        if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */
            op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */
            op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */
          *status|=DEC_Invalid_operation;
          *status|=DEC_Invalid_operation;
          break;
          break;
          }
          }
        /* [Note that infinity/0 raises no exceptions] */
        /* [Note that infinity/0 raises no exceptions] */
        decNumberZero(res);
        decNumberZero(res);
        res->bits=bits|DECINF;          /* set +/- infinity */
        res->bits=bits|DECINF;          /* set +/- infinity */
        break;
        break;
        }
        }
       else {                           /* RHS (divisor) is infinite */
       else {                           /* RHS (divisor) is infinite */
        residue=0;
        residue=0;
        if (op&(REMAINDER|REMNEAR)) {
        if (op&(REMAINDER|REMNEAR)) {
          /* result is [finished clone of] lhs */
          /* result is [finished clone of] lhs */
          decCopyFit(res, lhs, set, &residue, status);
          decCopyFit(res, lhs, set, &residue, status);
          }
          }
         else {  /* a division */
         else {  /* a division */
          decNumberZero(res);
          decNumberZero(res);
          res->bits=bits;               /* set +/- zero */
          res->bits=bits;               /* set +/- zero */
          /* for DIVIDEINT the exponent is always 0.  For DIVIDE, result */
          /* for DIVIDEINT the exponent is always 0.  For DIVIDE, result */
          /* is a 0 with infinitely negative exponent, clamped to minimum */
          /* is a 0 with infinitely negative exponent, clamped to minimum */
          if (op&DIVIDE) {
          if (op&DIVIDE) {
            res->exponent=set->emin-set->digits+1;
            res->exponent=set->emin-set->digits+1;
            *status|=DEC_Clamped;
            *status|=DEC_Clamped;
            }
            }
          }
          }
        decFinish(res, set, &residue, status);
        decFinish(res, set, &residue, status);
        break;
        break;
        }
        }
      }
      }
 
 
    /* handle 0 rhs (x/0) */
    /* handle 0 rhs (x/0) */
    if (ISZERO(rhs)) {                  /* x/0 is always exceptional */
    if (ISZERO(rhs)) {                  /* x/0 is always exceptional */
      if (ISZERO(lhs)) {
      if (ISZERO(lhs)) {
        decNumberZero(res);             /* [after lhs test] */
        decNumberZero(res);             /* [after lhs test] */
        *status|=DEC_Division_undefined;/* 0/0 will become NaN */
        *status|=DEC_Division_undefined;/* 0/0 will become NaN */
        }
        }
       else {
       else {
        decNumberZero(res);
        decNumberZero(res);
        if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation;
        if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation;
         else {
         else {
          *status|=DEC_Division_by_zero; /* x/0 */
          *status|=DEC_Division_by_zero; /* x/0 */
          res->bits=bits|DECINF;         /* .. is +/- Infinity */
          res->bits=bits|DECINF;         /* .. is +/- Infinity */
          }
          }
        }
        }
      break;}
      break;}
 
 
    /* handle 0 lhs (0/x) */
    /* handle 0 lhs (0/x) */
    if (ISZERO(lhs)) {                  /* 0/x [x!=0] */
    if (ISZERO(lhs)) {                  /* 0/x [x!=0] */
      #if DECSUBSET
      #if DECSUBSET
      if (!set->extended) decNumberZero(res);
      if (!set->extended) decNumberZero(res);
       else {
       else {
      #endif
      #endif
        if (op&DIVIDE) {
        if (op&DIVIDE) {
          residue=0;
          residue=0;
          exponent=lhs->exponent-rhs->exponent; /* ideal exponent */
          exponent=lhs->exponent-rhs->exponent; /* ideal exponent */
          decNumberCopy(res, lhs);      /* [zeros always fit] */
          decNumberCopy(res, lhs);      /* [zeros always fit] */
          res->bits=bits;               /* sign as computed */
          res->bits=bits;               /* sign as computed */
          res->exponent=exponent;       /* exponent, too */
          res->exponent=exponent;       /* exponent, too */
          decFinalize(res, set, &residue, status);   /* check exponent */
          decFinalize(res, set, &residue, status);   /* check exponent */
          }
          }
         else if (op&DIVIDEINT) {
         else if (op&DIVIDEINT) {
          decNumberZero(res);           /* integer 0 */
          decNumberZero(res);           /* integer 0 */
          res->bits=bits;               /* sign as computed */
          res->bits=bits;               /* sign as computed */
          }
          }
         else {                         /* a remainder */
         else {                         /* a remainder */
          exponent=rhs->exponent;       /* [save in case overwrite] */
          exponent=rhs->exponent;       /* [save in case overwrite] */
          decNumberCopy(res, lhs);      /* [zeros always fit] */
          decNumberCopy(res, lhs);      /* [zeros always fit] */
          if (exponent<res->exponent) res->exponent=exponent; /* use lower */
          if (exponent<res->exponent) res->exponent=exponent; /* use lower */
          }
          }
      #if DECSUBSET
      #if DECSUBSET
        }
        }
      #endif
      #endif
      break;}
      break;}
 
 
    /* Precalculate exponent.  This starts off adjusted (and hence fits */
    /* Precalculate exponent.  This starts off adjusted (and hence fits */
    /* in 31 bits) and becomes the usual unadjusted exponent as the */
    /* in 31 bits) and becomes the usual unadjusted exponent as the */
    /* division proceeds.  The order of evaluation is important, here, */
    /* division proceeds.  The order of evaluation is important, here, */
    /* to avoid wrap. */
    /* to avoid wrap. */
    exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits);
    exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits);
 
 
    /* If the working exponent is -ve, then some quick exits are */
    /* If the working exponent is -ve, then some quick exits are */
    /* possible because the quotient is known to be <1 */
    /* possible because the quotient is known to be <1 */
    /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */
    /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */
    if (exponent<0 && !(op==DIVIDE)) {
    if (exponent<0 && !(op==DIVIDE)) {
      if (op&DIVIDEINT) {
      if (op&DIVIDEINT) {
        decNumberZero(res);                  /* integer part is 0 */
        decNumberZero(res);                  /* integer part is 0 */
        #if DECSUBSET
        #if DECSUBSET
        if (set->extended)
        if (set->extended)
        #endif
        #endif
          res->bits=bits;                    /* set +/- zero */
          res->bits=bits;                    /* set +/- zero */
        break;}
        break;}
      /* fastpath remainders so long as the lhs has the smaller */
      /* fastpath remainders so long as the lhs has the smaller */
      /* (or equal) exponent */
      /* (or equal) exponent */
      if (lhs->exponent<=rhs->exponent) {
      if (lhs->exponent<=rhs->exponent) {
        if (op&REMAINDER || exponent<-1) {
        if (op&REMAINDER || exponent<-1) {
          /* It is REMAINDER or safe REMNEAR; result is [finished */
          /* It is REMAINDER or safe REMNEAR; result is [finished */
          /* clone of] lhs  (r = x - 0*y) */
          /* clone of] lhs  (r = x - 0*y) */
          residue=0;
          residue=0;
          decCopyFit(res, lhs, set, &residue, status);
          decCopyFit(res, lhs, set, &residue, status);
          decFinish(res, set, &residue, status);
          decFinish(res, set, &residue, status);
          break;
          break;
          }
          }
        /* [unsafe REMNEAR drops through] */
        /* [unsafe REMNEAR drops through] */
        }
        }
      } /* fastpaths */
      } /* fastpaths */
 
 
    /* Long (slow) division is needed; roll up the sleeves... */
    /* Long (slow) division is needed; roll up the sleeves... */
 
 
    /* The accumulator will hold the quotient of the division. */
    /* The accumulator will hold the quotient of the division. */
    /* If it needs to be too long for stack storage, then allocate. */
    /* If it needs to be too long for stack storage, then allocate. */
    acclength=D2U(reqdigits+DECDPUN);   /* in Units */
    acclength=D2U(reqdigits+DECDPUN);   /* in Units */
    if (acclength*sizeof(Unit)>sizeof(accbuff)) {
    if (acclength*sizeof(Unit)>sizeof(accbuff)) {
      /* printf("malloc dvacc %ld units\n", acclength); */
      /* printf("malloc dvacc %ld units\n", acclength); */
      allocacc=(Unit *)malloc(acclength*sizeof(Unit));
      allocacc=(Unit *)malloc(acclength*sizeof(Unit));
      if (allocacc==NULL) {             /* hopeless -- abandon */
      if (allocacc==NULL) {             /* hopeless -- abandon */
        *status|=DEC_Insufficient_storage;
        *status|=DEC_Insufficient_storage;
        break;}
        break;}
      acc=allocacc;                     /* use the allocated space */
      acc=allocacc;                     /* use the allocated space */
      }
      }
 
 
    /* var1 is the padded LHS ready for subtractions. */
    /* var1 is the padded LHS ready for subtractions. */
    /* If it needs to be too long for stack storage, then allocate. */
    /* If it needs to be too long for stack storage, then allocate. */
    /* The maximum units needed for var1 (long subtraction) is: */
    /* The maximum units needed for var1 (long subtraction) is: */
    /* Enough for */
    /* Enough for */
    /*     (rhs->digits+reqdigits-1) -- to allow full slide to right */
    /*     (rhs->digits+reqdigits-1) -- to allow full slide to right */
    /* or  (lhs->digits)             -- to allow for long lhs */
    /* or  (lhs->digits)             -- to allow for long lhs */
    /* whichever is larger */
    /* whichever is larger */
    /*   +1                -- for rounding of slide to right */
    /*   +1                -- for rounding of slide to right */
    /*   +1                -- for leading 0s */
    /*   +1                -- for leading 0s */
    /*   +1                -- for pre-adjust if a remainder or DIVIDEINT */
    /*   +1                -- for pre-adjust if a remainder or DIVIDEINT */
    /* [Note: unused units do not participate in decUnitAddSub data] */
    /* [Note: unused units do not participate in decUnitAddSub data] */
    maxdigits=rhs->digits+reqdigits-1;
    maxdigits=rhs->digits+reqdigits-1;
    if (lhs->digits>maxdigits) maxdigits=lhs->digits;
    if (lhs->digits>maxdigits) maxdigits=lhs->digits;
    var1units=D2U(maxdigits)+2;
    var1units=D2U(maxdigits)+2;
    /* allocate a guard unit above msu1 for REMAINDERNEAR */
    /* allocate a guard unit above msu1 for REMAINDERNEAR */
    if (!(op&DIVIDE)) var1units++;
    if (!(op&DIVIDE)) var1units++;
    if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) {
    if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) {
      /* printf("malloc dvvar %ld units\n", var1units+1); */
      /* printf("malloc dvvar %ld units\n", var1units+1); */
      varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit));
      varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit));
      if (varalloc==NULL) {             /* hopeless -- abandon */
      if (varalloc==NULL) {             /* hopeless -- abandon */
        *status|=DEC_Insufficient_storage;
        *status|=DEC_Insufficient_storage;
        break;}
        break;}
      var1=varalloc;                    /* use the allocated space */
      var1=varalloc;                    /* use the allocated space */
      }
      }
 
 
    /* Extend the lhs and rhs to full long subtraction length.  The lhs */
    /* Extend the lhs and rhs to full long subtraction length.  The lhs */
    /* is truly extended into the var1 buffer, with 0 padding, so a */
    /* is truly extended into the var1 buffer, with 0 padding, so a */
    /* subtract in place is always possible.  The rhs (var2) has */
    /* subtract in place is always possible.  The rhs (var2) has */
    /* virtual padding (implemented by decUnitAddSub). */
    /* virtual padding (implemented by decUnitAddSub). */
    /* One guard unit was allocated above msu1 for rem=rem+rem in */
    /* One guard unit was allocated above msu1 for rem=rem+rem in */
    /* REMAINDERNEAR. */
    /* REMAINDERNEAR. */
    msu1=var1+var1units-1;              /* msu of var1 */
    msu1=var1+var1units-1;              /* msu of var1 */
    source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */
    source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */
    for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source;
    for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source;
    for (; target>=var1; target--) *target=0;
    for (; target>=var1; target--) *target=0;
 
 
    /* rhs (var2) is left-aligned with var1 at the start */
    /* rhs (var2) is left-aligned with var1 at the start */
    var2ulen=var1units;                 /* rhs logical length (units) */
    var2ulen=var1units;                 /* rhs logical length (units) */
    var2units=D2U(rhs->digits);         /* rhs actual length (units) */
    var2units=D2U(rhs->digits);         /* rhs actual length (units) */
    var2=rhs->lsu;                      /* -> rhs array */
    var2=rhs->lsu;                      /* -> rhs array */
    msu2=var2+var2units-1;              /* -> msu of var2 [never changes] */
    msu2=var2+var2units-1;              /* -> msu of var2 [never changes] */
    /* now set up the variables which will be used for estimating the */
    /* now set up the variables which will be used for estimating the */
    /* multiplication factor.  If these variables are not exact, add */
    /* multiplication factor.  If these variables are not exact, add */
    /* 1 to make sure that the multiplier is never overestimated. */
    /* 1 to make sure that the multiplier is never overestimated. */
    msu2plus=*msu2;                     /* it's value .. */
    msu2plus=*msu2;                     /* it's value .. */
    if (var2units>1) msu2plus++;        /* .. +1 if any more */
    if (var2units>1) msu2plus++;        /* .. +1 if any more */
    msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */
    msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */
    if (var2units>1) {                  /* .. [else treat 2nd as 0] */
    if (var2units>1) {                  /* .. [else treat 2nd as 0] */
      msu2pair+=*(msu2-1);              /* .. */
      msu2pair+=*(msu2-1);              /* .. */
      if (var2units>2) msu2pair++;      /* .. +1 if any more */
      if (var2units>2) msu2pair++;      /* .. +1 if any more */
      }
      }
 
 
    /* The calculation is working in units, which may have leading zeros, */
    /* The calculation is working in units, which may have leading zeros, */
    /* but the exponent was calculated on the assumption that they are */
    /* but the exponent was calculated on the assumption that they are */
    /* both left-aligned.  Adjust the exponent to compensate: add the */
    /* both left-aligned.  Adjust the exponent to compensate: add the */
    /* number of leading zeros in var1 msu and subtract those in var2 msu. */
    /* number of leading zeros in var1 msu and subtract those in var2 msu. */
    /* [This is actually done by counting the digits and negating, as */
    /* [This is actually done by counting the digits and negating, as */
    /* lead1=DECDPUN-digits1, and similarly for lead2.] */
    /* lead1=DECDPUN-digits1, and similarly for lead2.] */
    for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--;
    for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--;
    for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++;
    for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++;
 
 
    /* Now, if doing an integer divide or remainder, ensure that */
    /* Now, if doing an integer divide or remainder, ensure that */
    /* the result will be Unit-aligned.  To do this, shift the var1 */
    /* the result will be Unit-aligned.  To do this, shift the var1 */
    /* accumulator towards least if need be.  (It's much easier to */
    /* accumulator towards least if need be.  (It's much easier to */
    /* do this now than to reassemble the residue afterwards, if */
    /* do this now than to reassemble the residue afterwards, if */
    /* doing a remainder.)  Also ensure the exponent is not negative. */
    /* doing a remainder.)  Also ensure the exponent is not negative. */
    if (!(op&DIVIDE)) {
    if (!(op&DIVIDE)) {
      Unit *u;                          /* work */
      Unit *u;                          /* work */
      /* save the initial 'false' padding of var1, in digits */
      /* save the initial 'false' padding of var1, in digits */
      var1initpad=(var1units-D2U(lhs->digits))*DECDPUN;
      var1initpad=(var1units-D2U(lhs->digits))*DECDPUN;
      /* Determine the shift to do. */
      /* Determine the shift to do. */
      if (exponent<0) cut=-exponent;
      if (exponent<0) cut=-exponent;
       else cut=DECDPUN-exponent%DECDPUN;
       else cut=DECDPUN-exponent%DECDPUN;
      decShiftToLeast(var1, var1units, cut);
      decShiftToLeast(var1, var1units, cut);
      exponent+=cut;                    /* maintain numerical value */
      exponent+=cut;                    /* maintain numerical value */
      var1initpad-=cut;                 /* .. and reduce padding */
      var1initpad-=cut;                 /* .. and reduce padding */
      /* clean any most-significant units which were just emptied */
      /* clean any most-significant units which were just emptied */
      for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0;
      for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0;
      } /* align */
      } /* align */
     else { /* is DIVIDE */
     else { /* is DIVIDE */
      maxexponent=lhs->exponent-rhs->exponent;    /* save */
      maxexponent=lhs->exponent-rhs->exponent;    /* save */
      /* optimization: if the first iteration will just produce 0, */
      /* optimization: if the first iteration will just produce 0, */
      /* preadjust to skip it [valid for DIVIDE only] */
      /* preadjust to skip it [valid for DIVIDE only] */
      if (*msu1<*msu2) {
      if (*msu1<*msu2) {
        var2ulen--;                     /* shift down */
        var2ulen--;                     /* shift down */
        exponent-=DECDPUN;              /* update the exponent */
        exponent-=DECDPUN;              /* update the exponent */
        }
        }
      }
      }
 
 
    /* ---- start the long-division loops ------------------------------ */
    /* ---- start the long-division loops ------------------------------ */
    accunits=0;                          /* no units accumulated yet */
    accunits=0;                          /* no units accumulated yet */
    accdigits=0;                 /* .. or digits */
    accdigits=0;                 /* .. or digits */
    accnext=acc+acclength-1;            /* -> msu of acc [NB: allows digits+1] */
    accnext=acc+acclength-1;            /* -> msu of acc [NB: allows digits+1] */
    for (;;) {                          /* outer forever loop */
    for (;;) {                          /* outer forever loop */
      thisunit=0;                        /* current unit assumed 0 */
      thisunit=0;                        /* current unit assumed 0 */
      /* find the next unit */
      /* find the next unit */
      for (;;) {                        /* inner forever loop */
      for (;;) {                        /* inner forever loop */
        /* strip leading zero units [from either pre-adjust or from */
        /* strip leading zero units [from either pre-adjust or from */
        /* subtract last time around].  Leave at least one unit. */
        /* subtract last time around].  Leave at least one unit. */
        for (; *msu1==0 && msu1>var1; msu1--) var1units--;
        for (; *msu1==0 && msu1>var1; msu1--) var1units--;
 
 
        if (var1units<var2ulen) break;       /* var1 too low for subtract */
        if (var1units<var2ulen) break;       /* var1 too low for subtract */
        if (var1units==var2ulen) {           /* unit-by-unit compare needed */
        if (var1units==var2ulen) {           /* unit-by-unit compare needed */
          /* compare the two numbers, from msu */
          /* compare the two numbers, from msu */
          const Unit *pv1, *pv2;
          const Unit *pv1, *pv2;
          Unit v2;                           /* units to compare */
          Unit v2;                           /* units to compare */
          pv2=msu2;                          /* -> msu */
          pv2=msu2;                          /* -> msu */
          for (pv1=msu1; ; pv1--, pv2--) {
          for (pv1=msu1; ; pv1--, pv2--) {
            /* v1=*pv1 -- always OK */
            /* v1=*pv1 -- always OK */
            v2=0;                             /* assume in padding */
            v2=0;                             /* assume in padding */
            if (pv2>=var2) v2=*pv2;          /* in range */
            if (pv2>=var2) v2=*pv2;          /* in range */
            if (*pv1!=v2) break;             /* no longer the same */
            if (*pv1!=v2) break;             /* no longer the same */
            if (pv1==var1) break;            /* done; leave pv1 as is */
            if (pv1==var1) break;            /* done; leave pv1 as is */
            }
            }
          /* here when all inspected or a difference seen */
          /* here when all inspected or a difference seen */
          if (*pv1<v2) break;                /* var1 too low to subtract */
          if (*pv1<v2) break;                /* var1 too low to subtract */
          if (*pv1==v2) {                    /* var1 == var2 */
          if (*pv1==v2) {                    /* var1 == var2 */
            /* reach here if var1 and var2 are identical; subtraction */
            /* reach here if var1 and var2 are identical; subtraction */
            /* would increase digit by one, and the residue will be 0 so */
            /* would increase digit by one, and the residue will be 0 so */
            /* the calculation is done; leave the loop with residue=0. */
            /* the calculation is done; leave the loop with residue=0. */
            thisunit++;                      /* as though subtracted */
            thisunit++;                      /* as though subtracted */
            *var1=0;                          /* set var1 to 0 */
            *var1=0;                          /* set var1 to 0 */
            var1units=1;                     /* .. */
            var1units=1;                     /* .. */
            break;  /* from inner */
            break;  /* from inner */
            } /* var1 == var2 */
            } /* var1 == var2 */
          /* *pv1>v2.  Prepare for real subtraction; the lengths are equal */
          /* *pv1>v2.  Prepare for real subtraction; the lengths are equal */
          /* Estimate the multiplier (there's always a msu1-1)... */
          /* Estimate the multiplier (there's always a msu1-1)... */
          /* Bring in two units of var2 to provide a good estimate. */
          /* Bring in two units of var2 to provide a good estimate. */
          mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair);
          mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair);
          } /* lengths the same */
          } /* lengths the same */
         else { /* var1units > var2ulen, so subtraction is safe */
         else { /* var1units > var2ulen, so subtraction is safe */
          /* The var2 msu is one unit towards the lsu of the var1 msu, */
          /* The var2 msu is one unit towards the lsu of the var1 msu, */
          /* so only one unit for var2 can be used. */
          /* so only one unit for var2 can be used. */
          mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus);
          mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus);
          }
          }
        if (mult==0) mult=1;                  /* must always be at least 1 */
        if (mult==0) mult=1;                  /* must always be at least 1 */
        /* subtraction needed; var1 is > var2 */
        /* subtraction needed; var1 is > var2 */
        thisunit=(Unit)(thisunit+mult);      /* accumulate */
        thisunit=(Unit)(thisunit+mult);      /* accumulate */
        /* subtract var1-var2, into var1; only the overlap needs */
        /* subtract var1-var2, into var1; only the overlap needs */
        /* processing, as this is an in-place calculation */
        /* processing, as this is an in-place calculation */
        shift=var2ulen-var2units;
        shift=var2ulen-var2units;
        #if DECTRACE
        #if DECTRACE
          decDumpAr('1', &var1[shift], var1units-shift);
          decDumpAr('1', &var1[shift], var1units-shift);
          decDumpAr('2', var2, var2units);
          decDumpAr('2', var2, var2units);
          printf("m=%ld\n", -mult);
          printf("m=%ld\n", -mult);
        #endif
        #endif
        decUnitAddSub(&var1[shift], var1units-shift,
        decUnitAddSub(&var1[shift], var1units-shift,
                      var2, var2units, 0,
                      var2, var2units, 0,
                      &var1[shift], -mult);
                      &var1[shift], -mult);
        #if DECTRACE
        #if DECTRACE
          decDumpAr('#', &var1[shift], var1units-shift);
          decDumpAr('#', &var1[shift], var1units-shift);
        #endif
        #endif
        /* var1 now probably has leading zeros; these are removed at the */
        /* var1 now probably has leading zeros; these are removed at the */
        /* top of the inner loop. */
        /* top of the inner loop. */
        } /* inner loop */
        } /* inner loop */
 
 
      /* The next unit has been calculated in full; unless it's a */
      /* The next unit has been calculated in full; unless it's a */
      /* leading zero, add to acc */
      /* leading zero, add to acc */
      if (accunits!=0 || thisunit!=0) {        /* is first or non-zero */
      if (accunits!=0 || thisunit!=0) {        /* is first or non-zero */
        *accnext=thisunit;                   /* store in accumulator */
        *accnext=thisunit;                   /* store in accumulator */
        /* account exactly for the new digits */
        /* account exactly for the new digits */
        if (accunits==0) {
        if (accunits==0) {
          accdigits++;                       /* at least one */
          accdigits++;                       /* at least one */
          for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++;
          for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++;
          }
          }
         else accdigits+=DECDPUN;
         else accdigits+=DECDPUN;
        accunits++;                          /* update count */
        accunits++;                          /* update count */
        accnext--;                           /* ready for next */
        accnext--;                           /* ready for next */
        if (accdigits>reqdigits) break;      /* have enough digits */
        if (accdigits>reqdigits) break;      /* have enough digits */
        }
        }
 
 
      /* if the residue is zero, the operation is done (unless divide */
      /* if the residue is zero, the operation is done (unless divide */
      /* or divideInteger and still not enough digits yet) */
      /* or divideInteger and still not enough digits yet) */
      if (*var1==0 && var1units==1) {         /* residue is 0 */
      if (*var1==0 && var1units==1) {         /* residue is 0 */
        if (op&(REMAINDER|REMNEAR)) break;
        if (op&(REMAINDER|REMNEAR)) break;
        if ((op&DIVIDE) && (exponent<=maxexponent)) break;
        if ((op&DIVIDE) && (exponent<=maxexponent)) break;
        /* [drop through if divideInteger] */
        /* [drop through if divideInteger] */
        }
        }
      /* also done enough if calculating remainder or integer */
      /* also done enough if calculating remainder or integer */
      /* divide and just did the last ('units') unit */
      /* divide and just did the last ('units') unit */
      if (exponent==0 && !(op&DIVIDE)) break;
      if (exponent==0 && !(op&DIVIDE)) break;
 
 
      /* to get here, var1 is less than var2, so divide var2 by the per- */
      /* to get here, var1 is less than var2, so divide var2 by the per- */
      /* Unit power of ten and go for the next digit */
      /* Unit power of ten and go for the next digit */
      var2ulen--;                            /* shift down */
      var2ulen--;                            /* shift down */
      exponent-=DECDPUN;                     /* update the exponent */
      exponent-=DECDPUN;                     /* update the exponent */
      } /* outer loop */
      } /* outer loop */
 
 
    /* ---- division is complete --------------------------------------- */
    /* ---- division is complete --------------------------------------- */
    /* here: acc      has at least reqdigits+1 of good results (or fewer */
    /* here: acc      has at least reqdigits+1 of good results (or fewer */
    /*                if early stop), starting at accnext+1 (its lsu) */
    /*                if early stop), starting at accnext+1 (its lsu) */
    /*       var1     has any residue at the stopping point */
    /*       var1     has any residue at the stopping point */
    /*       accunits is the number of digits collected in acc */
    /*       accunits is the number of digits collected in acc */
    if (accunits==0) {              /* acc is 0 */
    if (accunits==0) {              /* acc is 0 */
      accunits=1;                  /* show have a unit .. */
      accunits=1;                  /* show have a unit .. */
      accdigits=1;                 /* .. */
      accdigits=1;                 /* .. */
      *accnext=0;                   /* .. whose value is 0 */
      *accnext=0;                   /* .. whose value is 0 */
      }
      }
     else accnext++;               /* back to last placed */
     else accnext++;               /* back to last placed */
    /* accnext now -> lowest unit of result */
    /* accnext now -> lowest unit of result */
 
 
    residue=0;                      /* assume no residue */
    residue=0;                      /* assume no residue */
    if (op&DIVIDE) {
    if (op&DIVIDE) {
      /* record the presence of any residue, for rounding */
      /* record the presence of any residue, for rounding */
      if (*var1!=0 || var1units>1) residue=1;
      if (*var1!=0 || var1units>1) residue=1;
       else { /* no residue */
       else { /* no residue */
        /* Had an exact division; clean up spurious trailing 0s. */
        /* Had an exact division; clean up spurious trailing 0s. */
        /* There will be at most DECDPUN-1, from the final multiply, */
        /* There will be at most DECDPUN-1, from the final multiply, */
        /* and then only if the result is non-0 (and even) and the */
        /* and then only if the result is non-0 (and even) and the */
        /* exponent is 'loose'. */
        /* exponent is 'loose'. */
        #if DECDPUN>1
        #if DECDPUN>1
        Unit lsu=*accnext;
        Unit lsu=*accnext;
        if (!(lsu&0x01) && (lsu!=0)) {
        if (!(lsu&0x01) && (lsu!=0)) {
          /* count the trailing zeros */
          /* count the trailing zeros */
          Int drop=0;
          Int drop=0;
          for (;; drop++) {    /* [will terminate because lsu!=0] */
          for (;; drop++) {    /* [will terminate because lsu!=0] */
            if (exponent>=maxexponent) break;     /* don't chop real 0s */
            if (exponent>=maxexponent) break;     /* don't chop real 0s */
            #if DECDPUN<=4
            #if DECDPUN<=4
              if ((lsu-QUOT10(lsu, drop+1)
              if ((lsu-QUOT10(lsu, drop+1)
                  *powers[drop+1])!=0) break;      /* found non-0 digit */
                  *powers[drop+1])!=0) break;      /* found non-0 digit */
            #else
            #else
              if (lsu%powers[drop+1]!=0) break;    /* found non-0 digit */
              if (lsu%powers[drop+1]!=0) break;    /* found non-0 digit */
            #endif
            #endif
            exponent++;
            exponent++;
            }
            }
          if (drop>0) {
          if (drop>0) {
            accunits=decShiftToLeast(accnext, accunits, drop);
            accunits=decShiftToLeast(accnext, accunits, drop);
            accdigits=decGetDigits(accnext, accunits);
            accdigits=decGetDigits(accnext, accunits);
            accunits=D2U(accdigits);
            accunits=D2U(accdigits);
            /* [exponent was adjusted in the loop] */
            /* [exponent was adjusted in the loop] */
            }
            }
          } /* neither odd nor 0 */
          } /* neither odd nor 0 */
        #endif
        #endif
        } /* exact divide */
        } /* exact divide */
      } /* divide */
      } /* divide */
     else /* op!=DIVIDE */ {
     else /* op!=DIVIDE */ {
      /* check for coefficient overflow */
      /* check for coefficient overflow */
      if (accdigits+exponent>reqdigits) {
      if (accdigits+exponent>reqdigits) {
        *status|=DEC_Division_impossible;
        *status|=DEC_Division_impossible;
        break;
        break;
        }
        }
      if (op & (REMAINDER|REMNEAR)) {
      if (op & (REMAINDER|REMNEAR)) {
        /* [Here, the exponent will be 0, because var1 was adjusted */
        /* [Here, the exponent will be 0, because var1 was adjusted */
        /* appropriately.] */
        /* appropriately.] */
        Int postshift;                       /* work */
        Int postshift;                       /* work */
        Flag wasodd=0;                        /* integer was odd */
        Flag wasodd=0;                        /* integer was odd */
        Unit *quotlsu;                       /* for save */
        Unit *quotlsu;                       /* for save */
        Int  quotdigits;                     /* .. */
        Int  quotdigits;                     /* .. */
 
 
        bits=lhs->bits;                      /* remainder sign is always as lhs */
        bits=lhs->bits;                      /* remainder sign is always as lhs */
 
 
        /* Fastpath when residue is truly 0 is worthwhile [and */
        /* Fastpath when residue is truly 0 is worthwhile [and */
        /* simplifies the code below] */
        /* simplifies the code below] */
        if (*var1==0 && var1units==1) {       /* residue is 0 */
        if (*var1==0 && var1units==1) {       /* residue is 0 */
          Int exp=lhs->exponent;             /* save min(exponents) */
          Int exp=lhs->exponent;             /* save min(exponents) */
          if (rhs->exponent<exp) exp=rhs->exponent;
          if (rhs->exponent<exp) exp=rhs->exponent;
          decNumberZero(res);                /* 0 coefficient */
          decNumberZero(res);                /* 0 coefficient */
          #if DECSUBSET
          #if DECSUBSET
          if (set->extended)
          if (set->extended)
          #endif
          #endif
          res->exponent=exp;                 /* .. with proper exponent */
          res->exponent=exp;                 /* .. with proper exponent */
          res->bits=(uByte)(bits&DECNEG);          /* [cleaned] */
          res->bits=(uByte)(bits&DECNEG);          /* [cleaned] */
          decFinish(res, set, &residue, status);   /* might clamp */
          decFinish(res, set, &residue, status);   /* might clamp */
          break;
          break;
          }
          }
        /* note if the quotient was odd */
        /* note if the quotient was odd */
        if (*accnext & 0x01) wasodd=1;       /* acc is odd */
        if (*accnext & 0x01) wasodd=1;       /* acc is odd */
        quotlsu=accnext;                     /* save in case need to reinspect */
        quotlsu=accnext;                     /* save in case need to reinspect */
        quotdigits=accdigits;                /* .. */
        quotdigits=accdigits;                /* .. */
 
 
        /* treat the residue, in var1, as the value to return, via acc */
        /* treat the residue, in var1, as the value to return, via acc */
        /* calculate the unused zero digits.  This is the smaller of: */
        /* calculate the unused zero digits.  This is the smaller of: */
        /*   var1 initial padding (saved above) */
        /*   var1 initial padding (saved above) */
        /*   var2 residual padding, which happens to be given by: */
        /*   var2 residual padding, which happens to be given by: */
        postshift=var1initpad+exponent-lhs->exponent+rhs->exponent;
        postshift=var1initpad+exponent-lhs->exponent+rhs->exponent;
        /* [the 'exponent' term accounts for the shifts during divide] */
        /* [the 'exponent' term accounts for the shifts during divide] */
        if (var1initpad<postshift) postshift=var1initpad;
        if (var1initpad<postshift) postshift=var1initpad;
 
 
        /* shift var1 the requested amount, and adjust its digits */
        /* shift var1 the requested amount, and adjust its digits */
        var1units=decShiftToLeast(var1, var1units, postshift);
        var1units=decShiftToLeast(var1, var1units, postshift);
        accnext=var1;
        accnext=var1;
        accdigits=decGetDigits(var1, var1units);
        accdigits=decGetDigits(var1, var1units);
        accunits=D2U(accdigits);
        accunits=D2U(accdigits);
 
 
        exponent=lhs->exponent;         /* exponent is smaller of lhs & rhs */
        exponent=lhs->exponent;         /* exponent is smaller of lhs & rhs */
        if (rhs->exponent<exponent) exponent=rhs->exponent;
        if (rhs->exponent<exponent) exponent=rhs->exponent;
 
 
        /* Now correct the result if doing remainderNear; if it */
        /* Now correct the result if doing remainderNear; if it */
        /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */
        /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */
        /* the integer was odd then the result should be rem-rhs. */
        /* the integer was odd then the result should be rem-rhs. */
        if (op&REMNEAR) {
        if (op&REMNEAR) {
          Int compare, tarunits;        /* work */
          Int compare, tarunits;        /* work */
          Unit *up;                     /* .. */
          Unit *up;                     /* .. */
          /* calculate remainder*2 into the var1 buffer (which has */
          /* calculate remainder*2 into the var1 buffer (which has */
          /* 'headroom' of an extra unit and hence enough space) */
          /* 'headroom' of an extra unit and hence enough space) */
          /* [a dedicated 'double' loop would be faster, here] */
          /* [a dedicated 'double' loop would be faster, here] */
          tarunits=decUnitAddSub(accnext, accunits, accnext, accunits,
          tarunits=decUnitAddSub(accnext, accunits, accnext, accunits,
                                 0, accnext, 1);
                                 0, accnext, 1);
          /* decDumpAr('r', accnext, tarunits); */
          /* decDumpAr('r', accnext, tarunits); */
 
 
          /* Here, accnext (var1) holds tarunits Units with twice the */
          /* Here, accnext (var1) holds tarunits Units with twice the */
          /* remainder's coefficient, which must now be compared to the */
          /* remainder's coefficient, which must now be compared to the */
          /* RHS.  The remainder's exponent may be smaller than the RHS's. */
          /* RHS.  The remainder's exponent may be smaller than the RHS's. */
          compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits),
          compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits),
                                 rhs->exponent-exponent);
                                 rhs->exponent-exponent);
          if (compare==BADINT) {             /* deep trouble */
          if (compare==BADINT) {             /* deep trouble */
            *status|=DEC_Insufficient_storage;
            *status|=DEC_Insufficient_storage;
            break;}
            break;}
 
 
          /* now restore the remainder by dividing by two; the lsu */
          /* now restore the remainder by dividing by two; the lsu */
          /* is known to be even. */
          /* is known to be even. */
          for (up=accnext; up<accnext+tarunits; up++) {
          for (up=accnext; up<accnext+tarunits; up++) {
            Int half;              /* half to add to lower unit */
            Int half;              /* half to add to lower unit */
            half=*up & 0x01;
            half=*up & 0x01;
            *up/=2;                /* [shift] */
            *up/=2;                /* [shift] */
            if (!half) continue;
            if (!half) continue;
            *(up-1)+=(DECDPUNMAX+1)/2;
            *(up-1)+=(DECDPUNMAX+1)/2;
            }
            }
          /* [accunits still describes the original remainder length] */
          /* [accunits still describes the original remainder length] */
 
 
          if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */
          if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */
            Int exp, expunits, exprem;       /* work */
            Int exp, expunits, exprem;       /* work */
            /* This is effectively causing round-up of the quotient, */
            /* This is effectively causing round-up of the quotient, */
            /* so if it was the rare case where it was full and all */
            /* so if it was the rare case where it was full and all */
            /* nines, it would overflow and hence division-impossible */
            /* nines, it would overflow and hence division-impossible */
            /* should be raised */
            /* should be raised */
            Flag allnines=0;                  /* 1 if quotient all nines */
            Flag allnines=0;                  /* 1 if quotient all nines */
            if (quotdigits==reqdigits) {     /* could be borderline */
            if (quotdigits==reqdigits) {     /* could be borderline */
              for (up=quotlsu; ; up++) {
              for (up=quotlsu; ; up++) {
                if (quotdigits>DECDPUN) {
                if (quotdigits>DECDPUN) {
                  if (*up!=DECDPUNMAX) break;/* non-nines */
                  if (*up!=DECDPUNMAX) break;/* non-nines */
                  }
                  }
                 else {                      /* this is the last Unit */
                 else {                      /* this is the last Unit */
                  if (*up==powers[quotdigits]-1) allnines=1;
                  if (*up==powers[quotdigits]-1) allnines=1;
                  break;
                  break;
                  }
                  }
                quotdigits-=DECDPUN;         /* checked those digits */
                quotdigits-=DECDPUN;         /* checked those digits */
                } /* up */
                } /* up */
              } /* borderline check */
              } /* borderline check */
            if (allnines) {
            if (allnines) {
              *status|=DEC_Division_impossible;
              *status|=DEC_Division_impossible;
              break;}
              break;}
 
 
            /* rem-rhs is needed; the sign will invert.  Again, var1 */
            /* rem-rhs is needed; the sign will invert.  Again, var1 */
            /* can safely be used for the working Units array. */
            /* can safely be used for the working Units array. */
            exp=rhs->exponent-exponent;      /* RHS padding needed */
            exp=rhs->exponent-exponent;      /* RHS padding needed */
            /* Calculate units and remainder from exponent. */
            /* Calculate units and remainder from exponent. */
            expunits=exp/DECDPUN;
            expunits=exp/DECDPUN;
            exprem=exp%DECDPUN;
            exprem=exp%DECDPUN;
            /* subtract [A+B*(-m)]; the result will always be negative */
            /* subtract [A+B*(-m)]; the result will always be negative */
            accunits=-decUnitAddSub(accnext, accunits,
            accunits=-decUnitAddSub(accnext, accunits,
                                    rhs->lsu, D2U(rhs->digits),
                                    rhs->lsu, D2U(rhs->digits),
                                    expunits, accnext, -(Int)powers[exprem]);
                                    expunits, accnext, -(Int)powers[exprem]);
            accdigits=decGetDigits(accnext, accunits); /* count digits exactly */
            accdigits=decGetDigits(accnext, accunits); /* count digits exactly */
            accunits=D2U(accdigits);    /* and recalculate the units for copy */
            accunits=D2U(accdigits);    /* and recalculate the units for copy */
            /* [exponent is as for original remainder] */
            /* [exponent is as for original remainder] */
            bits^=DECNEG;               /* flip the sign */
            bits^=DECNEG;               /* flip the sign */
            }
            }
          } /* REMNEAR */
          } /* REMNEAR */
        } /* REMAINDER or REMNEAR */
        } /* REMAINDER or REMNEAR */
      } /* not DIVIDE */
      } /* not DIVIDE */
 
 
    /* Set exponent and bits */
    /* Set exponent and bits */
    res->exponent=exponent;
    res->exponent=exponent;
    res->bits=(uByte)(bits&DECNEG);          /* [cleaned] */
    res->bits=(uByte)(bits&DECNEG);          /* [cleaned] */
 
 
    /* Now the coefficient. */
    /* Now the coefficient. */
    decSetCoeff(res, set, accnext, accdigits, &residue, status);
    decSetCoeff(res, set, accnext, accdigits, &residue, status);
 
 
    decFinish(res, set, &residue, status);   /* final cleanup */
    decFinish(res, set, &residue, status);   /* final cleanup */
 
 
    #if DECSUBSET
    #if DECSUBSET
    /* If a divide then strip trailing zeros if subset [after round] */
    /* If a divide then strip trailing zeros if subset [after round] */
    if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, &dropped);
    if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, &dropped);
    #endif
    #endif
    } while(0);                               /* end protected */
    } while(0);                               /* end protected */
 
 
  if (varalloc!=NULL) free(varalloc);   /* drop any storage used */
  if (varalloc!=NULL) free(varalloc);   /* drop any storage used */
  if (allocacc!=NULL) free(allocacc);   /* .. */
  if (allocacc!=NULL) free(allocacc);   /* .. */
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs!=NULL) free(allocrhs);   /* .. */
  if (allocrhs!=NULL) free(allocrhs);   /* .. */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  #endif
  #endif
  return res;
  return res;
  } /* decDivideOp */
  } /* decDivideOp */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decMultiplyOp -- multiplication operation                          */
/* decMultiplyOp -- multiplication operation                          */
/*                                                                    */
/*                                                                    */
/*  This routine performs the multiplication C=A x B.                 */
/*  This routine performs the multiplication C=A x B.                 */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X*X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X*X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*   status is the usual accumulator                                  */
/*   status is the usual accumulator                                  */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* 'Classic' multiplication is used rather than Karatsuba, as the     */
/* 'Classic' multiplication is used rather than Karatsuba, as the     */
/* latter would give only a minor improvement for the short numbers   */
/* latter would give only a minor improvement for the short numbers   */
/* expected to be handled most (and uses much more memory).           */
/* expected to be handled most (and uses much more memory).           */
/*                                                                    */
/*                                                                    */
/* There are two major paths here: the general-purpose ('old code')   */
/* There are two major paths here: the general-purpose ('old code')   */
/* path which handles all DECDPUN values, and a fastpath version      */
/* path which handles all DECDPUN values, and a fastpath version      */
/* which is used if 64-bit ints are available, DECDPUN<=4, and more   */
/* which is used if 64-bit ints are available, DECDPUN<=4, and more   */
/* than two calls to decUnitAddSub would be made.                     */
/* than two calls to decUnitAddSub would be made.                     */
/*                                                                    */
/*                                                                    */
/* The fastpath version lumps units together into 8-digit or 9-digit  */
/* The fastpath version lumps units together into 8-digit or 9-digit  */
/* chunks, and also uses a lazy carry strategy to minimise expensive  */
/* chunks, and also uses a lazy carry strategy to minimise expensive  */
/* 64-bit divisions.  The chunks are then broken apart again into     */
/* 64-bit divisions.  The chunks are then broken apart again into     */
/* units for continuing processing.  Despite this overhead, the       */
/* units for continuing processing.  Despite this overhead, the       */
/* fastpath can speed up some 16-digit operations by 10x (and much    */
/* fastpath can speed up some 16-digit operations by 10x (and much    */
/* more for higher-precision calculations).                           */
/* more for higher-precision calculations).                           */
/*                                                                    */
/*                                                                    */
/* A buffer always has to be used for the accumulator; in the         */
/* A buffer always has to be used for the accumulator; in the         */
/* fastpath, buffers are also always needed for the chunked copies of */
/* fastpath, buffers are also always needed for the chunked copies of */
/* of the operand coefficients.                                       */
/* of the operand coefficients.                                       */
/* Static buffers are larger than needed just for multiply, to allow  */
/* Static buffers are larger than needed just for multiply, to allow  */
/* for calls from other operations (notably exp).                     */
/* for calls from other operations (notably exp).                     */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
#define FASTMUL (DECUSE64 && DECDPUN<5)
#define FASTMUL (DECUSE64 && DECDPUN<5)
static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs,
static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs,
                                 const decNumber *rhs, decContext *set,
                                 const decNumber *rhs, decContext *set,
                                 uInt *status) {
                                 uInt *status) {
  Int    accunits;                 /* Units of accumulator in use */
  Int    accunits;                 /* Units of accumulator in use */
  Int    exponent;                 /* work */
  Int    exponent;                 /* work */
  Int    residue=0;                 /* rounding residue */
  Int    residue=0;                 /* rounding residue */
  uByte  bits;                     /* result sign */
  uByte  bits;                     /* result sign */
  Unit  *acc;                      /* -> accumulator Unit array */
  Unit  *acc;                      /* -> accumulator Unit array */
  Int    needbytes;                /* size calculator */
  Int    needbytes;                /* size calculator */
  void  *allocacc=NULL;            /* -> allocated accumulator, iff allocated */
  void  *allocacc=NULL;            /* -> allocated accumulator, iff allocated */
  Unit  accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */
  Unit  accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */
                                   /* *4 for calls from other operations) */
                                   /* *4 for calls from other operations) */
  const Unit *mer, *mermsup;       /* work */
  const Unit *mer, *mermsup;       /* work */
  Int   madlength;                 /* Units in multiplicand */
  Int   madlength;                 /* Units in multiplicand */
  Int   shift;                     /* Units to shift multiplicand by */
  Int   shift;                     /* Units to shift multiplicand by */
 
 
  #if FASTMUL
  #if FASTMUL
    /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */
    /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */
    /* (DECDPUN is 2 or 4) then work in base 10**8 */
    /* (DECDPUN is 2 or 4) then work in base 10**8 */
    #if DECDPUN & 1                /* odd */
    #if DECDPUN & 1                /* odd */
      #define FASTBASE 1000000000  /* base */
      #define FASTBASE 1000000000  /* base */
      #define FASTDIGS          9  /* digits in base */
      #define FASTDIGS          9  /* digits in base */
      #define FASTLAZY         18  /* carry resolution point [1->18] */
      #define FASTLAZY         18  /* carry resolution point [1->18] */
    #else
    #else
      #define FASTBASE  100000000
      #define FASTBASE  100000000
      #define FASTDIGS          8
      #define FASTDIGS          8
      #define FASTLAZY       1844  /* carry resolution point [1->1844] */
      #define FASTLAZY       1844  /* carry resolution point [1->1844] */
    #endif
    #endif
    /* three buffers are used, two for chunked copies of the operands */
    /* three buffers are used, two for chunked copies of the operands */
    /* (base 10**8 or base 10**9) and one base 2**64 accumulator with */
    /* (base 10**8 or base 10**9) and one base 2**64 accumulator with */
    /* lazy carry evaluation */
    /* lazy carry evaluation */
    uInt   zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
    uInt   zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
    uInt  *zlhi=zlhibuff;                 /* -> lhs array */
    uInt  *zlhi=zlhibuff;                 /* -> lhs array */
    uInt  *alloclhi=NULL;                 /* -> allocated buffer, iff allocated */
    uInt  *alloclhi=NULL;                 /* -> allocated buffer, iff allocated */
    uInt   zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
    uInt   zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
    uInt  *zrhi=zrhibuff;                 /* -> rhs array */
    uInt  *zrhi=zrhibuff;                 /* -> rhs array */
    uInt  *allocrhi=NULL;                 /* -> allocated buffer, iff allocated */
    uInt  *allocrhi=NULL;                 /* -> allocated buffer, iff allocated */
    uLong  zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */
    uLong  zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */
    /* [allocacc is shared for both paths, as only one will run] */
    /* [allocacc is shared for both paths, as only one will run] */
    uLong *zacc=zaccbuff;          /* -> accumulator array for exact result */
    uLong *zacc=zaccbuff;          /* -> accumulator array for exact result */
    #if DECDPUN==1
    #if DECDPUN==1
    Int    zoff;                   /* accumulator offset */
    Int    zoff;                   /* accumulator offset */
    #endif
    #endif
    uInt  *lip, *rip;              /* item pointers */
    uInt  *lip, *rip;              /* item pointers */
    uInt  *lmsi, *rmsi;            /* most significant items */
    uInt  *lmsi, *rmsi;            /* most significant items */
    Int    ilhs, irhs, iacc;       /* item counts in the arrays */
    Int    ilhs, irhs, iacc;       /* item counts in the arrays */
    Int    lazy;                   /* lazy carry counter */
    Int    lazy;                   /* lazy carry counter */
    uLong  lcarry;                 /* uLong carry */
    uLong  lcarry;                 /* uLong carry */
    uInt   carry;                  /* carry (NB not uLong) */
    uInt   carry;                  /* carry (NB not uLong) */
    Int    count;                  /* work */
    Int    count;                  /* work */
    const  Unit *cup;              /* .. */
    const  Unit *cup;              /* .. */
    Unit  *up;                     /* .. */
    Unit  *up;                     /* .. */
    uLong *lp;                     /* .. */
    uLong *lp;                     /* .. */
    Int    p;                      /* .. */
    Int    p;                      /* .. */
  #endif
  #endif
 
 
  #if DECSUBSET
  #if DECSUBSET
    decNumber *alloclhs=NULL;      /* -> allocated buffer, iff allocated */
    decNumber *alloclhs=NULL;      /* -> allocated buffer, iff allocated */
    decNumber *allocrhs=NULL;      /* -> allocated buffer, iff allocated */
    decNumber *allocrhs=NULL;      /* -> allocated buffer, iff allocated */
  #endif
  #endif
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  /* precalculate result sign */
  /* precalculate result sign */
  bits=(uByte)((lhs->bits^rhs->bits)&DECNEG);
  bits=(uByte)((lhs->bits^rhs->bits)&DECNEG);
 
 
  /* handle infinities and NaNs */
  /* handle infinities and NaNs */
  if (SPECIALARGS) {               /* a special bit set */
  if (SPECIALARGS) {               /* a special bit set */
    if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
    if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
      decNaNs(res, lhs, rhs, set, status);
      decNaNs(res, lhs, rhs, set, status);
      return res;}
      return res;}
    /* one or two infinities; Infinity * 0 is invalid */
    /* one or two infinities; Infinity * 0 is invalid */
    if (((lhs->bits & DECINF)==0 && ISZERO(lhs))
    if (((lhs->bits & DECINF)==0 && ISZERO(lhs))
      ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) {
      ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) {
      *status|=DEC_Invalid_operation;
      *status|=DEC_Invalid_operation;
      return res;}
      return res;}
    decNumberZero(res);
    decNumberZero(res);
    res->bits=bits|DECINF;         /* infinity */
    res->bits=bits|DECINF;         /* infinity */
    return res;}
    return res;}
 
 
  /* For best speed, as in DMSRCN [the original Rexx numerics */
  /* For best speed, as in DMSRCN [the original Rexx numerics */
  /* module], use the shorter number as the multiplier (rhs) and */
  /* module], use the shorter number as the multiplier (rhs) and */
  /* the longer as the multiplicand (lhs) to minimise the number of */
  /* the longer as the multiplicand (lhs) to minimise the number of */
  /* adds (partial products) */
  /* adds (partial products) */
  if (lhs->digits<rhs->digits) {   /* swap... */
  if (lhs->digits<rhs->digits) {   /* swap... */
    const decNumber *hold=lhs;
    const decNumber *hold=lhs;
    lhs=rhs;
    lhs=rhs;
    rhs=hold;
    rhs=hold;
    }
    }
 
 
  do {                             /* protect allocated storage */
  do {                             /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operands and set lostDigits status, as needed */
      /* reduce operands and set lostDigits status, as needed */
      if (lhs->digits>set->digits) {
      if (lhs->digits>set->digits) {
        alloclhs=decRoundOperand(lhs, set, status);
        alloclhs=decRoundOperand(lhs, set, status);
        if (alloclhs==NULL) break;
        if (alloclhs==NULL) break;
        lhs=alloclhs;
        lhs=alloclhs;
        }
        }
      if (rhs->digits>set->digits) {
      if (rhs->digits>set->digits) {
        allocrhs=decRoundOperand(rhs, set, status);
        allocrhs=decRoundOperand(rhs, set, status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    /* [following code does not require input rounding] */
    /* [following code does not require input rounding] */
 
 
    #if FASTMUL                    /* fastpath can be used */
    #if FASTMUL                    /* fastpath can be used */
    /* use the fast path if there are enough digits in the shorter */
    /* use the fast path if there are enough digits in the shorter */
    /* operand to make the setup and takedown worthwhile */
    /* operand to make the setup and takedown worthwhile */
    #define NEEDTWO (DECDPUN*2)    /* within two decUnitAddSub calls */
    #define NEEDTWO (DECDPUN*2)    /* within two decUnitAddSub calls */
    if (rhs->digits>NEEDTWO) {     /* use fastpath... */
    if (rhs->digits>NEEDTWO) {     /* use fastpath... */
      /* calculate the number of elements in each array */
      /* calculate the number of elements in each array */
      ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */
      ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */
      irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */
      irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */
      iacc=ilhs+irhs;
      iacc=ilhs+irhs;
 
 
      /* allocate buffers if required, as usual */
      /* allocate buffers if required, as usual */
      needbytes=ilhs*sizeof(uInt);
      needbytes=ilhs*sizeof(uInt);
      if (needbytes>(Int)sizeof(zlhibuff)) {
      if (needbytes>(Int)sizeof(zlhibuff)) {
        alloclhi=(uInt *)malloc(needbytes);
        alloclhi=(uInt *)malloc(needbytes);
        zlhi=alloclhi;}
        zlhi=alloclhi;}
      needbytes=irhs*sizeof(uInt);
      needbytes=irhs*sizeof(uInt);
      if (needbytes>(Int)sizeof(zrhibuff)) {
      if (needbytes>(Int)sizeof(zrhibuff)) {
        allocrhi=(uInt *)malloc(needbytes);
        allocrhi=(uInt *)malloc(needbytes);
        zrhi=allocrhi;}
        zrhi=allocrhi;}
 
 
      /* Allocating the accumulator space needs a special case when */
      /* Allocating the accumulator space needs a special case when */
      /* DECDPUN=1 because when converting the accumulator to Units */
      /* DECDPUN=1 because when converting the accumulator to Units */
      /* after the multiplication each 8-byte item becomes 9 1-byte */
      /* after the multiplication each 8-byte item becomes 9 1-byte */
      /* units.  Therefore iacc extra bytes are needed at the front */
      /* units.  Therefore iacc extra bytes are needed at the front */
      /* (rounded up to a multiple of 8 bytes), and the uLong */
      /* (rounded up to a multiple of 8 bytes), and the uLong */
      /* accumulator starts offset the appropriate number of units */
      /* accumulator starts offset the appropriate number of units */
      /* to the right to avoid overwrite during the unchunking. */
      /* to the right to avoid overwrite during the unchunking. */
      needbytes=iacc*sizeof(uLong);
      needbytes=iacc*sizeof(uLong);
      #if DECDPUN==1
      #if DECDPUN==1
      zoff=(iacc+7)/8;        /* items to offset by */
      zoff=(iacc+7)/8;        /* items to offset by */
      needbytes+=zoff*8;
      needbytes+=zoff*8;
      #endif
      #endif
      if (needbytes>(Int)sizeof(zaccbuff)) {
      if (needbytes>(Int)sizeof(zaccbuff)) {
        allocacc=(uLong *)malloc(needbytes);
        allocacc=(uLong *)malloc(needbytes);
        zacc=(uLong *)allocacc;}
        zacc=(uLong *)allocacc;}
      if (zlhi==NULL||zrhi==NULL||zacc==NULL) {
      if (zlhi==NULL||zrhi==NULL||zacc==NULL) {
        *status|=DEC_Insufficient_storage;
        *status|=DEC_Insufficient_storage;
        break;}
        break;}
 
 
      acc=(Unit *)zacc;       /* -> target Unit array */
      acc=(Unit *)zacc;       /* -> target Unit array */
      #if DECDPUN==1
      #if DECDPUN==1
      zacc+=zoff;             /* start uLong accumulator to right */
      zacc+=zoff;             /* start uLong accumulator to right */
      #endif
      #endif
 
 
      /* assemble the chunked copies of the left and right sides */
      /* assemble the chunked copies of the left and right sides */
      for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++)
      for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++)
        for (p=0, *lip=0; p<FASTDIGS && count>0;
        for (p=0, *lip=0; p<FASTDIGS && count>0;
             p+=DECDPUN, cup++, count-=DECDPUN)
             p+=DECDPUN, cup++, count-=DECDPUN)
          *lip+=*cup*powers[p];
          *lip+=*cup*powers[p];
      lmsi=lip-1;     /* save -> msi */
      lmsi=lip-1;     /* save -> msi */
      for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++)
      for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++)
        for (p=0, *rip=0; p<FASTDIGS && count>0;
        for (p=0, *rip=0; p<FASTDIGS && count>0;
             p+=DECDPUN, cup++, count-=DECDPUN)
             p+=DECDPUN, cup++, count-=DECDPUN)
          *rip+=*cup*powers[p];
          *rip+=*cup*powers[p];
      rmsi=rip-1;     /* save -> msi */
      rmsi=rip-1;     /* save -> msi */
 
 
      /* zero the accumulator */
      /* zero the accumulator */
      for (lp=zacc; lp<zacc+iacc; lp++) *lp=0;
      for (lp=zacc; lp<zacc+iacc; lp++) *lp=0;
 
 
      /* Start the multiplication */
      /* Start the multiplication */
      /* Resolving carries can dominate the cost of accumulating the */
      /* Resolving carries can dominate the cost of accumulating the */
      /* partial products, so this is only done when necessary. */
      /* partial products, so this is only done when necessary. */
      /* Each uLong item in the accumulator can hold values up to */
      /* Each uLong item in the accumulator can hold values up to */
      /* 2**64-1, and each partial product can be as large as */
      /* 2**64-1, and each partial product can be as large as */
      /* (10**FASTDIGS-1)**2.  When FASTDIGS=9, this can be added to */
      /* (10**FASTDIGS-1)**2.  When FASTDIGS=9, this can be added to */
      /* itself 18.4 times in a uLong without overflowing, so during */
      /* itself 18.4 times in a uLong without overflowing, so during */
      /* the main calculation resolution is carried out every 18th */
      /* the main calculation resolution is carried out every 18th */
      /* add -- every 162 digits.  Similarly, when FASTDIGS=8, the */
      /* add -- every 162 digits.  Similarly, when FASTDIGS=8, the */
      /* partial products can be added to themselves 1844.6 times in */
      /* partial products can be added to themselves 1844.6 times in */
      /* a uLong without overflowing, so intermediate carry */
      /* a uLong without overflowing, so intermediate carry */
      /* resolution occurs only every 14752 digits.  Hence for common */
      /* resolution occurs only every 14752 digits.  Hence for common */
      /* short numbers usually only the one final carry resolution */
      /* short numbers usually only the one final carry resolution */
      /* occurs. */
      /* occurs. */
      /* (The count is set via FASTLAZY to simplify experiments to */
      /* (The count is set via FASTLAZY to simplify experiments to */
      /* measure the value of this approach: a 35% improvement on a */
      /* measure the value of this approach: a 35% improvement on a */
      /* [34x34] multiply.) */
      /* [34x34] multiply.) */
      lazy=FASTLAZY;                         /* carry delay count */
      lazy=FASTLAZY;                         /* carry delay count */
      for (rip=zrhi; rip<=rmsi; rip++) {     /* over each item in rhs */
      for (rip=zrhi; rip<=rmsi; rip++) {     /* over each item in rhs */
        lp=zacc+(rip-zrhi);                  /* where to add the lhs */
        lp=zacc+(rip-zrhi);                  /* where to add the lhs */
        for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */
        for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */
          *lp+=(uLong)(*lip)*(*rip);         /* [this should in-line] */
          *lp+=(uLong)(*lip)*(*rip);         /* [this should in-line] */
          } /* lip loop */
          } /* lip loop */
        lazy--;
        lazy--;
        if (lazy>0 && rip!=rmsi) continue;
        if (lazy>0 && rip!=rmsi) continue;
        lazy=FASTLAZY;                       /* reset delay count */
        lazy=FASTLAZY;                       /* reset delay count */
        /* spin up the accumulator resolving overflows */
        /* spin up the accumulator resolving overflows */
        for (lp=zacc; lp<zacc+iacc; lp++) {
        for (lp=zacc; lp<zacc+iacc; lp++) {
          if (*lp<FASTBASE) continue;        /* it fits */
          if (*lp<FASTBASE) continue;        /* it fits */
          lcarry=*lp/FASTBASE;               /* top part [slow divide] */
          lcarry=*lp/FASTBASE;               /* top part [slow divide] */
          /* lcarry can exceed 2**32-1, so check again; this check */
          /* lcarry can exceed 2**32-1, so check again; this check */
          /* and occasional extra divide (slow) is well worth it, as */
          /* and occasional extra divide (slow) is well worth it, as */
          /* it allows FASTLAZY to be increased to 18 rather than 4 */
          /* it allows FASTLAZY to be increased to 18 rather than 4 */
          /* in the FASTDIGS=9 case */
          /* in the FASTDIGS=9 case */
          if (lcarry<FASTBASE) carry=(uInt)lcarry;  /* [usual] */
          if (lcarry<FASTBASE) carry=(uInt)lcarry;  /* [usual] */
           else { /* two-place carry [fairly rare] */
           else { /* two-place carry [fairly rare] */
            uInt carry2=(uInt)(lcarry/FASTBASE);    /* top top part */
            uInt carry2=(uInt)(lcarry/FASTBASE);    /* top top part */
            *(lp+2)+=carry2;                        /* add to item+2 */
            *(lp+2)+=carry2;                        /* add to item+2 */
            *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */
            *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */
            carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */
            carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */
            }
            }
          *(lp+1)+=carry;                    /* add to item above [inline] */
          *(lp+1)+=carry;                    /* add to item above [inline] */
          *lp-=((uLong)FASTBASE*carry);      /* [inline] */
          *lp-=((uLong)FASTBASE*carry);      /* [inline] */
          } /* carry resolution */
          } /* carry resolution */
        } /* rip loop */
        } /* rip loop */
 
 
      /* The multiplication is complete; time to convert back into */
      /* The multiplication is complete; time to convert back into */
      /* units.  This can be done in-place in the accumulator and in */
      /* units.  This can be done in-place in the accumulator and in */
      /* 32-bit operations, because carries were resolved after the */
      /* 32-bit operations, because carries were resolved after the */
      /* final add.  This needs N-1 divides and multiplies for */
      /* final add.  This needs N-1 divides and multiplies for */
      /* each item in the accumulator (which will become up to N */
      /* each item in the accumulator (which will become up to N */
      /* units, where 2<=N<=9). */
      /* units, where 2<=N<=9). */
      for (lp=zacc, up=acc; lp<zacc+iacc; lp++) {
      for (lp=zacc, up=acc; lp<zacc+iacc; lp++) {
        uInt item=(uInt)*lp;                 /* decapitate to uInt */
        uInt item=(uInt)*lp;                 /* decapitate to uInt */
        for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) {
        for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) {
          uInt part=item/(DECDPUNMAX+1);
          uInt part=item/(DECDPUNMAX+1);
          *up=(Unit)(item-(part*(DECDPUNMAX+1)));
          *up=(Unit)(item-(part*(DECDPUNMAX+1)));
          item=part;
          item=part;
          } /* p */
          } /* p */
        *up=(Unit)item; up++;                /* [final needs no division] */
        *up=(Unit)item; up++;                /* [final needs no division] */
        } /* lp */
        } /* lp */
      accunits=up-acc;                       /* count of units */
      accunits=up-acc;                       /* count of units */
      }
      }
     else { /* here to use units directly, without chunking ['old code'] */
     else { /* here to use units directly, without chunking ['old code'] */
    #endif
    #endif
 
 
      /* if accumulator will be too long for local storage, then allocate */
      /* if accumulator will be too long for local storage, then allocate */
      acc=accbuff;                 /* -> assume buffer for accumulator */
      acc=accbuff;                 /* -> assume buffer for accumulator */
      needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit);
      needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit);
      if (needbytes>(Int)sizeof(accbuff)) {
      if (needbytes>(Int)sizeof(accbuff)) {
        allocacc=(Unit *)malloc(needbytes);
        allocacc=(Unit *)malloc(needbytes);
        if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;}
        if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;}
        acc=(Unit *)allocacc;                /* use the allocated space */
        acc=(Unit *)allocacc;                /* use the allocated space */
        }
        }
 
 
      /* Now the main long multiplication loop */
      /* Now the main long multiplication loop */
      /* Unlike the equivalent in the IBM Java implementation, there */
      /* Unlike the equivalent in the IBM Java implementation, there */
      /* is no advantage in calculating from msu to lsu.  So, do it */
      /* is no advantage in calculating from msu to lsu.  So, do it */
      /* by the book, as it were. */
      /* by the book, as it were. */
      /* Each iteration calculates ACC=ACC+MULTAND*MULT */
      /* Each iteration calculates ACC=ACC+MULTAND*MULT */
      accunits=1;                  /* accumulator starts at '0' */
      accunits=1;                  /* accumulator starts at '0' */
      *acc=0;                       /* .. (lsu=0) */
      *acc=0;                       /* .. (lsu=0) */
      shift=0;                      /* no multiplicand shift at first */
      shift=0;                      /* no multiplicand shift at first */
      madlength=D2U(lhs->digits);  /* this won't change */
      madlength=D2U(lhs->digits);  /* this won't change */
      mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */
      mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */
 
 
      for (mer=rhs->lsu; mer<mermsup; mer++) {
      for (mer=rhs->lsu; mer<mermsup; mer++) {
        /* Here, *mer is the next Unit in the multiplier to use */
        /* Here, *mer is the next Unit in the multiplier to use */
        /* If non-zero [optimization] add it... */
        /* If non-zero [optimization] add it... */
        if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift,
        if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift,
                                            lhs->lsu, madlength, 0,
                                            lhs->lsu, madlength, 0,
                                            &acc[shift], *mer)
                                            &acc[shift], *mer)
                                            + shift;
                                            + shift;
         else { /* extend acc with a 0; it will be used shortly */
         else { /* extend acc with a 0; it will be used shortly */
          *(acc+accunits)=0;        /* [this avoids length of <=0 later] */
          *(acc+accunits)=0;        /* [this avoids length of <=0 later] */
          accunits++;
          accunits++;
          }
          }
        /* multiply multiplicand by 10**DECDPUN for next Unit to left */
        /* multiply multiplicand by 10**DECDPUN for next Unit to left */
        shift++;                   /* add this for 'logical length' */
        shift++;                   /* add this for 'logical length' */
        } /* n */
        } /* n */
    #if FASTMUL
    #if FASTMUL
      } /* unchunked units */
      } /* unchunked units */
    #endif
    #endif
    /* common end-path */
    /* common end-path */
    #if DECTRACE
    #if DECTRACE
      decDumpAr('*', acc, accunits);         /* Show exact result */
      decDumpAr('*', acc, accunits);         /* Show exact result */
    #endif
    #endif
 
 
    /* acc now contains the exact result of the multiplication, */
    /* acc now contains the exact result of the multiplication, */
    /* possibly with a leading zero unit; build the decNumber from */
    /* possibly with a leading zero unit; build the decNumber from */
    /* it, noting if any residue */
    /* it, noting if any residue */
    res->bits=bits;                          /* set sign */
    res->bits=bits;                          /* set sign */
    res->digits=decGetDigits(acc, accunits); /* count digits exactly */
    res->digits=decGetDigits(acc, accunits); /* count digits exactly */
 
 
    /* There can be a 31-bit wrap in calculating the exponent. */
    /* There can be a 31-bit wrap in calculating the exponent. */
    /* This can only happen if both input exponents are negative and */
    /* This can only happen if both input exponents are negative and */
    /* both their magnitudes are large.  If there was a wrap, set a */
    /* both their magnitudes are large.  If there was a wrap, set a */
    /* safe very negative exponent, from which decFinalize() will */
    /* safe very negative exponent, from which decFinalize() will */
    /* raise a hard underflow shortly. */
    /* raise a hard underflow shortly. */
    exponent=lhs->exponent+rhs->exponent;    /* calculate exponent */
    exponent=lhs->exponent+rhs->exponent;    /* calculate exponent */
    if (lhs->exponent<0 && rhs->exponent<0 && exponent>0)
    if (lhs->exponent<0 && rhs->exponent<0 && exponent>0)
      exponent=-2*DECNUMMAXE;                /* force underflow */
      exponent=-2*DECNUMMAXE;                /* force underflow */
    res->exponent=exponent;                  /* OK to overwrite now */
    res->exponent=exponent;                  /* OK to overwrite now */
 
 
 
 
    /* Set the coefficient.  If any rounding, residue records */
    /* Set the coefficient.  If any rounding, residue records */
    decSetCoeff(res, set, acc, res->digits, &residue, status);
    decSetCoeff(res, set, acc, res->digits, &residue, status);
    decFinish(res, set, &residue, status);   /* final cleanup */
    decFinish(res, set, &residue, status);   /* final cleanup */
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  if (allocacc!=NULL) free(allocacc);   /* drop any storage used */
  if (allocacc!=NULL) free(allocacc);   /* drop any storage used */
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs!=NULL) free(allocrhs);   /* .. */
  if (allocrhs!=NULL) free(allocrhs);   /* .. */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  #endif
  #endif
  #if FASTMUL
  #if FASTMUL
  if (allocrhi!=NULL) free(allocrhi);   /* .. */
  if (allocrhi!=NULL) free(allocrhi);   /* .. */
  if (alloclhi!=NULL) free(alloclhi);   /* .. */
  if (alloclhi!=NULL) free(alloclhi);   /* .. */
  #endif
  #endif
  return res;
  return res;
  } /* decMultiplyOp */
  } /* decMultiplyOp */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decExpOp -- effect exponentiation                                  */
/* decExpOp -- effect exponentiation                                  */
/*                                                                    */
/*                                                                    */
/*   This computes C = exp(A)                                         */
/*   This computes C = exp(A)                                         */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context; note that rounding mode has no effect        */
/*   set is the context; note that rounding mode has no effect        */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits. status is updated but    */
/* C must have space for set->digits digits. status is updated but    */
/* not set.                                                           */
/* not set.                                                           */
/*                                                                    */
/*                                                                    */
/* Restrictions:                                                      */
/* Restrictions:                                                      */
/*                                                                    */
/*                                                                    */
/*   digits, emax, and -emin in the context must be less than         */
/*   digits, emax, and -emin in the context must be less than         */
/*   2*DEC_MAX_MATH (1999998), and the rhs must be within these       */
/*   2*DEC_MAX_MATH (1999998), and the rhs must be within these       */
/*   bounds or a zero.  This is an internal routine, so these         */
/*   bounds or a zero.  This is an internal routine, so these         */
/*   restrictions are contractual and not enforced.                   */
/*   restrictions are contractual and not enforced.                   */
/*                                                                    */
/*                                                                    */
/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will      */
/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* error in rare cases.                                               */
/* error in rare cases.                                               */
/*                                                                    */
/*                                                                    */
/* Finite results will always be full precision and Inexact, except   */
/* Finite results will always be full precision and Inexact, except   */
/* when A is a zero or -Infinity (giving 1 or 0 respectively).        */
/* when A is a zero or -Infinity (giving 1 or 0 respectively).        */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This approach used here is similar to the algorithm described in   */
/* This approach used here is similar to the algorithm described in   */
/*                                                                    */
/*                                                                    */
/*   Variable Precision Exponential Function, T. E. Hull and          */
/*   Variable Precision Exponential Function, T. E. Hull and          */
/*   A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */
/*   A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */
/*   pp79-91, ACM, June 1986.                                         */
/*   pp79-91, ACM, June 1986.                                         */
/*                                                                    */
/*                                                                    */
/* with the main difference being that the iterations in the series   */
/* with the main difference being that the iterations in the series   */
/* evaluation are terminated dynamically (which does not require the  */
/* evaluation are terminated dynamically (which does not require the  */
/* extra variable-precision variables which are expensive in this     */
/* extra variable-precision variables which are expensive in this     */
/* context).                                                          */
/* context).                                                          */
/*                                                                    */
/*                                                                    */
/* The error analysis in Hull & Abrham's paper applies except for the */
/* The error analysis in Hull & Abrham's paper applies except for the */
/* round-off error accumulation during the series evaluation.  This   */
/* round-off error accumulation during the series evaluation.  This   */
/* code does not precalculate the number of iterations and so cannot  */
/* code does not precalculate the number of iterations and so cannot  */
/* use Horner's scheme.  Instead, the accumulation is done at double- */
/* use Horner's scheme.  Instead, the accumulation is done at double- */
/* precision, which ensures that the additions of the terms are exact */
/* precision, which ensures that the additions of the terms are exact */
/* and do not accumulate round-off (and any round-off errors in the   */
/* and do not accumulate round-off (and any round-off errors in the   */
/* terms themselves move 'to the right' faster than they can          */
/* terms themselves move 'to the right' faster than they can          */
/* accumulate).  This code also extends the calculation by allowing,  */
/* accumulate).  This code also extends the calculation by allowing,  */
/* in the spirit of other decNumber operators, the input to be more   */
/* in the spirit of other decNumber operators, the input to be more   */
/* precise than the result (the precision used is based on the more   */
/* precise than the result (the precision used is based on the more   */
/* precise of the input or requested result).                         */
/* precise of the input or requested result).                         */
/*                                                                    */
/*                                                                    */
/* Implementation notes:                                              */
/* Implementation notes:                                              */
/*                                                                    */
/*                                                                    */
/* 1. This is separated out as decExpOp so it can be called from      */
/* 1. This is separated out as decExpOp so it can be called from      */
/*    other Mathematical functions (notably Ln) with a wider range    */
/*    other Mathematical functions (notably Ln) with a wider range    */
/*    than normal.  In particular, it can handle the slightly wider   */
/*    than normal.  In particular, it can handle the slightly wider   */
/*    (double) range needed by Ln (which has to be able to calculate  */
/*    (double) range needed by Ln (which has to be able to calculate  */
/*    exp(-x) where x can be the tiniest number (Ntiny).              */
/*    exp(-x) where x can be the tiniest number (Ntiny).              */
/*                                                                    */
/*                                                                    */
/* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop         */
/* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop         */
/*    iterations by appoximately a third with additional (although    */
/*    iterations by appoximately a third with additional (although    */
/*    diminishing) returns as the range is reduced to even smaller    */
/*    diminishing) returns as the range is reduced to even smaller    */
/*    fractions.  However, h (the power of 10 used to correct the     */
/*    fractions.  However, h (the power of 10 used to correct the     */
/*    result at the end, see below) must be kept <=8 as otherwise     */
/*    result at the end, see below) must be kept <=8 as otherwise     */
/*    the final result cannot be computed.  Hence the leverage is a   */
/*    the final result cannot be computed.  Hence the leverage is a   */
/*    sliding value (8-h), where potentially the range is reduced     */
/*    sliding value (8-h), where potentially the range is reduced     */
/*    more for smaller values.                                        */
/*    more for smaller values.                                        */
/*                                                                    */
/*                                                                    */
/*    The leverage that can be applied in this way is severely        */
/*    The leverage that can be applied in this way is severely        */
/*    limited by the cost of the raise-to-the power at the end,       */
/*    limited by the cost of the raise-to-the power at the end,       */
/*    which dominates when the number of iterations is small (less    */
/*    which dominates when the number of iterations is small (less    */
/*    than ten) or when rhs is short.  As an example, the adjustment  */
/*    than ten) or when rhs is short.  As an example, the adjustment  */
/*    x**10,000,000 needs 31 multiplications, all but one full-width. */
/*    x**10,000,000 needs 31 multiplications, all but one full-width. */
/*                                                                    */
/*                                                                    */
/* 3. The restrictions (especially precision) could be raised with    */
/* 3. The restrictions (especially precision) could be raised with    */
/*    care, but the full decNumber range seems very hard within the   */
/*    care, but the full decNumber range seems very hard within the   */
/*    32-bit limits.                                                  */
/*    32-bit limits.                                                  */
/*                                                                    */
/*                                                                    */
/* 4. The working precisions for the static buffers are twice the     */
/* 4. The working precisions for the static buffers are twice the     */
/*    obvious size to allow for calls from decNumberPower.            */
/*    obvious size to allow for calls from decNumberPower.            */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decExpOp(decNumber *res, const decNumber *rhs,
decNumber * decExpOp(decNumber *res, const decNumber *rhs,
                         decContext *set, uInt *status) {
                         decContext *set, uInt *status) {
  uInt ignore=0;            /* working status */
  uInt ignore=0;            /* working status */
  Int h;                           /* adjusted exponent for 0.xxxx */
  Int h;                           /* adjusted exponent for 0.xxxx */
  Int p;                           /* working precision */
  Int p;                           /* working precision */
  Int residue;                     /* rounding residue */
  Int residue;                     /* rounding residue */
  uInt needbytes;                  /* for space calculations */
  uInt needbytes;                  /* for space calculations */
  const decNumber *x=rhs;          /* (may point to safe copy later) */
  const decNumber *x=rhs;          /* (may point to safe copy later) */
  decContext aset, tset, dset;     /* working contexts */
  decContext aset, tset, dset;     /* working contexts */
  Int comp;                        /* work */
  Int comp;                        /* work */
 
 
  /* the argument is often copied to normalize it, so (unusually) it */
  /* the argument is often copied to normalize it, so (unusually) it */
  /* is treated like other buffers, using DECBUFFER, +1 in case */
  /* is treated like other buffers, using DECBUFFER, +1 in case */
  /* DECBUFFER is 0 */
  /* DECBUFFER is 0 */
  decNumber bufr[D2N(DECBUFFER*2+1)];
  decNumber bufr[D2N(DECBUFFER*2+1)];
  decNumber *allocrhs=NULL;        /* non-NULL if rhs buffer allocated */
  decNumber *allocrhs=NULL;        /* non-NULL if rhs buffer allocated */
 
 
  /* the working precision will be no more than set->digits+8+1 */
  /* the working precision will be no more than set->digits+8+1 */
  /* so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER */
  /* so for on-stack buffers DECBUFFER+9 is used, +1 in case DECBUFFER */
  /* is 0 (and twice that for the accumulator) */
  /* is 0 (and twice that for the accumulator) */
 
 
  /* buffer for t, term (working precision plus) */
  /* buffer for t, term (working precision plus) */
  decNumber buft[D2N(DECBUFFER*2+9+1)];
  decNumber buft[D2N(DECBUFFER*2+9+1)];
  decNumber *allocbuft=NULL;       /* -> allocated buft, iff allocated */
  decNumber *allocbuft=NULL;       /* -> allocated buft, iff allocated */
  decNumber *t=buft;               /* term */
  decNumber *t=buft;               /* term */
  /* buffer for a, accumulator (working precision * 2), at least 9 */
  /* buffer for a, accumulator (working precision * 2), at least 9 */
  decNumber bufa[D2N(DECBUFFER*4+18+1)];
  decNumber bufa[D2N(DECBUFFER*4+18+1)];
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *a=bufa;               /* accumulator */
  decNumber *a=bufa;               /* accumulator */
  /* decNumber for the divisor term; this needs at most 9 digits */
  /* decNumber for the divisor term; this needs at most 9 digits */
  /* and so can be fixed size [16 so can use standard context] */
  /* and so can be fixed size [16 so can use standard context] */
  decNumber bufd[D2N(16)];
  decNumber bufd[D2N(16)];
  decNumber *d=bufd;               /* divisor */
  decNumber *d=bufd;               /* divisor */
  decNumber numone;                /* constant 1 */
  decNumber numone;                /* constant 1 */
 
 
  #if DECCHECK
  #if DECCHECK
  Int iterations=0;                 /* for later sanity check */
  Int iterations=0;                 /* for later sanity check */
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                                  /* protect allocated storage */
  do {                                  /* protect allocated storage */
    if (SPECIALARG) {                   /* handle infinities and NaNs */
    if (SPECIALARG) {                   /* handle infinities and NaNs */
      if (decNumberIsInfinite(rhs)) {   /* an infinity */
      if (decNumberIsInfinite(rhs)) {   /* an infinity */
        if (decNumberIsNegative(rhs))   /* -Infinity -> +0 */
        if (decNumberIsNegative(rhs))   /* -Infinity -> +0 */
          decNumberZero(res);
          decNumberZero(res);
         else decNumberCopy(res, rhs);  /* +Infinity -> self */
         else decNumberCopy(res, rhs);  /* +Infinity -> self */
        }
        }
       else decNaNs(res, rhs, NULL, set, status); /* a NaN */
       else decNaNs(res, rhs, NULL, set, status); /* a NaN */
      break;}
      break;}
 
 
    if (ISZERO(rhs)) {                  /* zeros -> exact 1 */
    if (ISZERO(rhs)) {                  /* zeros -> exact 1 */
      decNumberZero(res);               /* make clean 1 */
      decNumberZero(res);               /* make clean 1 */
      *res->lsu=1;                      /* .. */
      *res->lsu=1;                      /* .. */
      break;}                           /* [no status to set] */
      break;}                           /* [no status to set] */
 
 
    /* e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path */
    /* e**x when 0 < x < 0.66 is < 1+3x/2, hence can fast-path */
    /* positive and negative tiny cases which will result in inexact */
    /* positive and negative tiny cases which will result in inexact */
    /* 1.  This also allows the later add-accumulate to always be */
    /* 1.  This also allows the later add-accumulate to always be */
    /* exact (because its length will never be more than twice the */
    /* exact (because its length will never be more than twice the */
    /* working precision). */
    /* working precision). */
    /* The comparator (tiny) needs just one digit, so use the */
    /* The comparator (tiny) needs just one digit, so use the */
    /* decNumber d for it (reused as the divisor, etc., below); its */
    /* decNumber d for it (reused as the divisor, etc., below); its */
    /* exponent is such that if x is positive it will have */
    /* exponent is such that if x is positive it will have */
    /* set->digits-1 zeros between the decimal point and the digit, */
    /* set->digits-1 zeros between the decimal point and the digit, */
    /* which is 4, and if x is negative one more zero there as the */
    /* which is 4, and if x is negative one more zero there as the */
    /* more precise result will be of the form 0.9999999 rather than */
    /* more precise result will be of the form 0.9999999 rather than */
    /* 1.0000001.  Hence, tiny will be 0.0000004  if digits=7 and x>0 */
    /* 1.0000001.  Hence, tiny will be 0.0000004  if digits=7 and x>0 */
    /* or 0.00000004 if digits=7 and x<0.  If RHS not larger than */
    /* or 0.00000004 if digits=7 and x<0.  If RHS not larger than */
    /* this then the result will be 1.000000 */
    /* this then the result will be 1.000000 */
    decNumberZero(d);                   /* clean */
    decNumberZero(d);                   /* clean */
    *d->lsu=4;                          /* set 4 .. */
    *d->lsu=4;                          /* set 4 .. */
    d->exponent=-set->digits;           /* * 10**(-d) */
    d->exponent=-set->digits;           /* * 10**(-d) */
    if (decNumberIsNegative(rhs)) d->exponent--;  /* negative case */
    if (decNumberIsNegative(rhs)) d->exponent--;  /* negative case */
    comp=decCompare(d, rhs, 1);         /* signless compare */
    comp=decCompare(d, rhs, 1);         /* signless compare */
    if (comp==BADINT) {
    if (comp==BADINT) {
      *status|=DEC_Insufficient_storage;
      *status|=DEC_Insufficient_storage;
      break;}
      break;}
    if (comp>=0) {                       /* rhs < d */
    if (comp>=0) {                       /* rhs < d */
      Int shift=set->digits-1;
      Int shift=set->digits-1;
      decNumberZero(res);               /* set 1 */
      decNumberZero(res);               /* set 1 */
      *res->lsu=1;                      /* .. */
      *res->lsu=1;                      /* .. */
      res->digits=decShiftToMost(res->lsu, 1, shift);
      res->digits=decShiftToMost(res->lsu, 1, shift);
      res->exponent=-shift;                  /* make 1.0000... */
      res->exponent=-shift;                  /* make 1.0000... */
      *status|=DEC_Inexact | DEC_Rounded;    /* .. inexactly */
      *status|=DEC_Inexact | DEC_Rounded;    /* .. inexactly */
      break;} /* tiny */
      break;} /* tiny */
 
 
    /* set up the context to be used for calculating a, as this is */
    /* set up the context to be used for calculating a, as this is */
    /* used on both paths below */
    /* used on both paths below */
    decContextDefault(&aset, DEC_INIT_DECIMAL64);
    decContextDefault(&aset, DEC_INIT_DECIMAL64);
    /* accumulator bounds are as requested (could underflow) */
    /* accumulator bounds are as requested (could underflow) */
    aset.emax=set->emax;                /* usual bounds */
    aset.emax=set->emax;                /* usual bounds */
    aset.emin=set->emin;                /* .. */
    aset.emin=set->emin;                /* .. */
    aset.clamp=0;                        /* and no concrete format */
    aset.clamp=0;                        /* and no concrete format */
 
 
    /* calculate the adjusted (Hull & Abrham) exponent (where the */
    /* calculate the adjusted (Hull & Abrham) exponent (where the */
    /* decimal point is just to the left of the coefficient msd) */
    /* decimal point is just to the left of the coefficient msd) */
    h=rhs->exponent+rhs->digits;
    h=rhs->exponent+rhs->digits;
    /* if h>8 then 10**h cannot be calculated safely; however, when */
    /* if h>8 then 10**h cannot be calculated safely; however, when */
    /* h=8 then exp(|rhs|) will be at least exp(1E+7) which is at */
    /* h=8 then exp(|rhs|) will be at least exp(1E+7) which is at */
    /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */
    /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */
    /* overflow (or underflow to 0) is guaranteed -- so this case can */
    /* overflow (or underflow to 0) is guaranteed -- so this case can */
    /* be handled by simply forcing the appropriate excess */
    /* be handled by simply forcing the appropriate excess */
    if (h>8) {                          /* overflow/underflow */
    if (h>8) {                          /* overflow/underflow */
      /* set up here so Power call below will over or underflow to */
      /* set up here so Power call below will over or underflow to */
      /* zero; set accumulator to either 2 or 0.02 */
      /* zero; set accumulator to either 2 or 0.02 */
      /* [stack buffer for a is always big enough for this] */
      /* [stack buffer for a is always big enough for this] */
      decNumberZero(a);
      decNumberZero(a);
      *a->lsu=2;                        /* not 1 but < exp(1) */
      *a->lsu=2;                        /* not 1 but < exp(1) */
      if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */
      if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */
      h=8;                              /* clamp so 10**h computable */
      h=8;                              /* clamp so 10**h computable */
      p=9;                              /* set a working precision */
      p=9;                              /* set a working precision */
      }
      }
     else {                             /* h<=8 */
     else {                             /* h<=8 */
      Int maxlever=(rhs->digits>8?1:0);
      Int maxlever=(rhs->digits>8?1:0);
      /* [could/should increase this for precisions >40 or so, too] */
      /* [could/should increase this for precisions >40 or so, too] */
 
 
      /* if h is 8, cannot normalize to a lower upper limit because */
      /* if h is 8, cannot normalize to a lower upper limit because */
      /* the final result will not be computable (see notes above), */
      /* the final result will not be computable (see notes above), */
      /* but leverage can be applied whenever h is less than 8. */
      /* but leverage can be applied whenever h is less than 8. */
      /* Apply as much as possible, up to a MAXLEVER digits, which */
      /* Apply as much as possible, up to a MAXLEVER digits, which */
      /* sets the tradeoff against the cost of the later a**(10**h). */
      /* sets the tradeoff against the cost of the later a**(10**h). */
      /* As h is increased, the working precision below also */
      /* As h is increased, the working precision below also */
      /* increases to compensate for the "constant digits at the */
      /* increases to compensate for the "constant digits at the */
      /* front" effect. */
      /* front" effect. */
      Int lever=MINI(8-h, maxlever);    /* leverage attainable */
      Int lever=MINI(8-h, maxlever);    /* leverage attainable */
      Int use=-rhs->digits-lever;       /* exponent to use for RHS */
      Int use=-rhs->digits-lever;       /* exponent to use for RHS */
      h+=lever;                         /* apply leverage selected */
      h+=lever;                         /* apply leverage selected */
      if (h<0) {                 /* clamp */
      if (h<0) {                 /* clamp */
        use+=h;                         /* [may end up subnormal] */
        use+=h;                         /* [may end up subnormal] */
        h=0;
        h=0;
        }
        }
      /* Take a copy of RHS if it needs normalization (true whenever x>=1) */
      /* Take a copy of RHS if it needs normalization (true whenever x>=1) */
      if (rhs->exponent!=use) {
      if (rhs->exponent!=use) {
        decNumber *newrhs=bufr;         /* assume will fit on stack */
        decNumber *newrhs=bufr;         /* assume will fit on stack */
        needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
        needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
        if (needbytes>sizeof(bufr)) {   /* need malloc space */
        if (needbytes>sizeof(bufr)) {   /* need malloc space */
          allocrhs=(decNumber *)malloc(needbytes);
          allocrhs=(decNumber *)malloc(needbytes);
          if (allocrhs==NULL) {         /* hopeless -- abandon */
          if (allocrhs==NULL) {         /* hopeless -- abandon */
            *status|=DEC_Insufficient_storage;
            *status|=DEC_Insufficient_storage;
            break;}
            break;}
          newrhs=allocrhs;              /* use the allocated space */
          newrhs=allocrhs;              /* use the allocated space */
          }
          }
        decNumberCopy(newrhs, rhs);     /* copy to safe space */
        decNumberCopy(newrhs, rhs);     /* copy to safe space */
        newrhs->exponent=use;           /* normalize; now <1 */
        newrhs->exponent=use;           /* normalize; now <1 */
        x=newrhs;                       /* ready for use */
        x=newrhs;                       /* ready for use */
        /* decNumberShow(x); */
        /* decNumberShow(x); */
        }
        }
 
 
      /* Now use the usual power series to evaluate exp(x).  The */
      /* Now use the usual power series to evaluate exp(x).  The */
      /* series starts as 1 + x + x^2/2 ... so prime ready for the */
      /* series starts as 1 + x + x^2/2 ... so prime ready for the */
      /* third term by setting the term variable t=x, the accumulator */
      /* third term by setting the term variable t=x, the accumulator */
      /* a=1, and the divisor d=2. */
      /* a=1, and the divisor d=2. */
 
 
      /* First determine the working precision.  From Hull & Abrham */
      /* First determine the working precision.  From Hull & Abrham */
      /* this is set->digits+h+2.  However, if x is 'over-precise' we */
      /* this is set->digits+h+2.  However, if x is 'over-precise' we */
      /* need to allow for all its digits to potentially participate */
      /* need to allow for all its digits to potentially participate */
      /* (consider an x where all the excess digits are 9s) so in */
      /* (consider an x where all the excess digits are 9s) so in */
      /* this case use x->digits+h+2 */
      /* this case use x->digits+h+2 */
      p=MAXI(x->digits, set->digits)+h+2;    /* [h<=8] */
      p=MAXI(x->digits, set->digits)+h+2;    /* [h<=8] */
 
 
      /* a and t are variable precision, and depend on p, so space */
      /* a and t are variable precision, and depend on p, so space */
      /* must be allocated for them if necessary */
      /* must be allocated for them if necessary */
 
 
      /* the accumulator needs to be able to hold 2p digits so that */
      /* the accumulator needs to be able to hold 2p digits so that */
      /* the additions on the second and subsequent iterations are */
      /* the additions on the second and subsequent iterations are */
      /* sufficiently exact. */
      /* sufficiently exact. */
      needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit);
      needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit);
      if (needbytes>sizeof(bufa)) {     /* need malloc space */
      if (needbytes>sizeof(bufa)) {     /* need malloc space */
        allocbufa=(decNumber *)malloc(needbytes);
        allocbufa=(decNumber *)malloc(needbytes);
        if (allocbufa==NULL) {          /* hopeless -- abandon */
        if (allocbufa==NULL) {          /* hopeless -- abandon */
          *status|=DEC_Insufficient_storage;
          *status|=DEC_Insufficient_storage;
          break;}
          break;}
        a=allocbufa;                    /* use the allocated space */
        a=allocbufa;                    /* use the allocated space */
        }
        }
      /* the term needs to be able to hold p digits (which is */
      /* the term needs to be able to hold p digits (which is */
      /* guaranteed to be larger than x->digits, so the initial copy */
      /* guaranteed to be larger than x->digits, so the initial copy */
      /* is safe); it may also be used for the raise-to-power */
      /* is safe); it may also be used for the raise-to-power */
      /* calculation below, which needs an extra two digits */
      /* calculation below, which needs an extra two digits */
      needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit);
      needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit);
      if (needbytes>sizeof(buft)) {     /* need malloc space */
      if (needbytes>sizeof(buft)) {     /* need malloc space */
        allocbuft=(decNumber *)malloc(needbytes);
        allocbuft=(decNumber *)malloc(needbytes);
        if (allocbuft==NULL) {          /* hopeless -- abandon */
        if (allocbuft==NULL) {          /* hopeless -- abandon */
          *status|=DEC_Insufficient_storage;
          *status|=DEC_Insufficient_storage;
          break;}
          break;}
        t=allocbuft;                    /* use the allocated space */
        t=allocbuft;                    /* use the allocated space */
        }
        }
 
 
      decNumberCopy(t, x);              /* term=x */
      decNumberCopy(t, x);              /* term=x */
      decNumberZero(a); *a->lsu=1;      /* accumulator=1 */
      decNumberZero(a); *a->lsu=1;      /* accumulator=1 */
      decNumberZero(d); *d->lsu=2;      /* divisor=2 */
      decNumberZero(d); *d->lsu=2;      /* divisor=2 */
      decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */
      decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */
 
 
      /* set up the contexts for calculating a, t, and d */
      /* set up the contexts for calculating a, t, and d */
      decContextDefault(&tset, DEC_INIT_DECIMAL64);
      decContextDefault(&tset, DEC_INIT_DECIMAL64);
      dset=tset;
      dset=tset;
      /* accumulator bounds are set above, set precision now */
      /* accumulator bounds are set above, set precision now */
      aset.digits=p*2;                  /* double */
      aset.digits=p*2;                  /* double */
      /* term bounds avoid any underflow or overflow */
      /* term bounds avoid any underflow or overflow */
      tset.digits=p;
      tset.digits=p;
      tset.emin=DEC_MIN_EMIN;           /* [emax is plenty] */
      tset.emin=DEC_MIN_EMIN;           /* [emax is plenty] */
      /* [dset.digits=16, etc., are sufficient] */
      /* [dset.digits=16, etc., are sufficient] */
 
 
      /* finally ready to roll */
      /* finally ready to roll */
      for (;;) {
      for (;;) {
        #if DECCHECK
        #if DECCHECK
        iterations++;
        iterations++;
        #endif
        #endif
        /* only the status from the accumulation is interesting */
        /* only the status from the accumulation is interesting */
        /* [but it should remain unchanged after first add] */
        /* [but it should remain unchanged after first add] */
        decAddOp(a, a, t, &aset, 0, status);            /* a=a+t */
        decAddOp(a, a, t, &aset, 0, status);            /* a=a+t */
        decMultiplyOp(t, t, x, &tset, &ignore);        /* t=t*x */
        decMultiplyOp(t, t, x, &tset, &ignore);        /* t=t*x */
        decDivideOp(t, t, d, &tset, DIVIDE, &ignore);  /* t=t/d */
        decDivideOp(t, t, d, &tset, DIVIDE, &ignore);  /* t=t/d */
        /* the iteration ends when the term cannot affect the result, */
        /* the iteration ends when the term cannot affect the result, */
        /* if rounded to p digits, which is when its value is smaller */
        /* if rounded to p digits, which is when its value is smaller */
        /* than the accumulator by p+1 digits.  There must also be */
        /* than the accumulator by p+1 digits.  There must also be */
        /* full precision in a. */
        /* full precision in a. */
        if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1))
        if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1))
            && (a->digits>=p)) break;
            && (a->digits>=p)) break;
        decAddOp(d, d, &numone, &dset, 0, &ignore);    /* d=d+1 */
        decAddOp(d, d, &numone, &dset, 0, &ignore);    /* d=d+1 */
        } /* iterate */
        } /* iterate */
 
 
      #if DECCHECK
      #if DECCHECK
      /* just a sanity check; comment out test to show always */
      /* just a sanity check; comment out test to show always */
      if (iterations>p+3)
      if (iterations>p+3)
        printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
        printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
               iterations, *status, p, x->digits);
               iterations, *status, p, x->digits);
      #endif
      #endif
      } /* h<=8 */
      } /* h<=8 */
 
 
    /* apply postconditioning: a=a**(10**h) -- this is calculated */
    /* apply postconditioning: a=a**(10**h) -- this is calculated */
    /* at a slightly higher precision than Hull & Abrham suggest */
    /* at a slightly higher precision than Hull & Abrham suggest */
    if (h>0) {
    if (h>0) {
      Int seenbit=0;                /* set once a 1-bit is seen */
      Int seenbit=0;                /* set once a 1-bit is seen */
      Int i;                       /* counter */
      Int i;                       /* counter */
      Int n=powers[h];             /* always positive */
      Int n=powers[h];             /* always positive */
      aset.digits=p+2;             /* sufficient precision */
      aset.digits=p+2;             /* sufficient precision */
      /* avoid the overhead and many extra digits of decNumberPower */
      /* avoid the overhead and many extra digits of decNumberPower */
      /* as all that is needed is the short 'multipliers' loop; here */
      /* as all that is needed is the short 'multipliers' loop; here */
      /* accumulate the answer into t */
      /* accumulate the answer into t */
      decNumberZero(t); *t->lsu=1; /* acc=1 */
      decNumberZero(t); *t->lsu=1; /* acc=1 */
      for (i=1;;i++){              /* for each bit [top bit ignored] */
      for (i=1;;i++){              /* for each bit [top bit ignored] */
        /* abandon if have had overflow or terminal underflow */
        /* abandon if have had overflow or terminal underflow */
        if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
        if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
          if (*status&DEC_Overflow || ISZERO(t)) break;}
          if (*status&DEC_Overflow || ISZERO(t)) break;}
        n=n<<1;                    /* move next bit to testable position */
        n=n<<1;                    /* move next bit to testable position */
        if (n<0) {                  /* top bit is set */
        if (n<0) {                  /* top bit is set */
          seenbit=1;               /* OK, have a significant bit */
          seenbit=1;               /* OK, have a significant bit */
          decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */
          decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */
          }
          }
        if (i==31) break;          /* that was the last bit */
        if (i==31) break;          /* that was the last bit */
        if (!seenbit) continue;    /* no need to square 1 */
        if (!seenbit) continue;    /* no need to square 1 */
        decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */
        decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */
        } /*i*/ /* 32 bits */
        } /*i*/ /* 32 bits */
      /* decNumberShow(t); */
      /* decNumberShow(t); */
      a=t;                         /* and carry on using t instead of a */
      a=t;                         /* and carry on using t instead of a */
      }
      }
 
 
    /* Copy and round the result to res */
    /* Copy and round the result to res */
    residue=1;                          /* indicate dirt to right .. */
    residue=1;                          /* indicate dirt to right .. */
    if (ISZERO(a)) residue=0;            /* .. unless underflowed to 0 */
    if (ISZERO(a)) residue=0;            /* .. unless underflowed to 0 */
    aset.digits=set->digits;            /* [use default rounding] */
    aset.digits=set->digits;            /* [use default rounding] */
    decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
    decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
    decFinish(res, set, &residue, status);       /* cleanup/set flags */
    decFinish(res, set, &residue, status);       /* cleanup/set flags */
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  if (allocrhs !=NULL) free(allocrhs);  /* drop any storage used */
  if (allocrhs !=NULL) free(allocrhs);  /* drop any storage used */
  if (allocbufa!=NULL) free(allocbufa); /* .. */
  if (allocbufa!=NULL) free(allocbufa); /* .. */
  if (allocbuft!=NULL) free(allocbuft); /* .. */
  if (allocbuft!=NULL) free(allocbuft); /* .. */
  /* [status is handled by caller] */
  /* [status is handled by caller] */
  return res;
  return res;
  } /* decExpOp */
  } /* decExpOp */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* Initial-estimate natural logarithm table                           */
/* Initial-estimate natural logarithm table                           */
/*                                                                    */
/*                                                                    */
/*   LNnn -- 90-entry 16-bit table for values from .10 through .99.   */
/*   LNnn -- 90-entry 16-bit table for values from .10 through .99.   */
/*           The result is a 4-digit encode of the coefficient (c=the */
/*           The result is a 4-digit encode of the coefficient (c=the */
/*           top 14 bits encoding 0-9999) and a 2-digit encode of the */
/*           top 14 bits encoding 0-9999) and a 2-digit encode of the */
/*           exponent (e=the bottom 2 bits encoding 0-3)              */
/*           exponent (e=the bottom 2 bits encoding 0-3)              */
/*                                                                    */
/*                                                                    */
/*           The resulting value is given by:                         */
/*           The resulting value is given by:                         */
/*                                                                    */
/*                                                                    */
/*             v = -c * 10**(-e-3)                                    */
/*             v = -c * 10**(-e-3)                                    */
/*                                                                    */
/*                                                                    */
/*           where e and c are extracted from entry k = LNnn[x-10]    */
/*           where e and c are extracted from entry k = LNnn[x-10]    */
/*           where x is truncated (NB) into the range 10 through 99,  */
/*           where x is truncated (NB) into the range 10 through 99,  */
/*           and then c = k>>2 and e = k&3.                           */
/*           and then c = k>>2 and e = k&3.                           */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
const uShort LNnn[90]={9016,  8652,  8316,  8008,  7724,  7456,  7208,
const uShort LNnn[90]={9016,  8652,  8316,  8008,  7724,  7456,  7208,
  6972,  6748,  6540,  6340,  6148,  5968,  5792,  5628,  5464,  5312,
  6972,  6748,  6540,  6340,  6148,  5968,  5792,  5628,  5464,  5312,
  5164,  5020,  4884,  4748,  4620,  4496,  4376,  4256,  4144,  4032,
  5164,  5020,  4884,  4748,  4620,  4496,  4376,  4256,  4144,  4032,
 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629,
 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629,
 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837,
 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837,
 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321,
 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321,
 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717,
 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717,
 10197,  9685,  9177,  8677,  8185,  7697,  7213,  6737,  6269,  5801,
 10197,  9685,  9177,  8677,  8185,  7697,  7213,  6737,  6269,  5801,
  5341,  4889,  4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254,
  5341,  4889,  4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254,
 10130,  6046, 20055};
 10130,  6046, 20055};
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decLnOp -- effect natural logarithm                                */
/* decLnOp -- effect natural logarithm                                */
/*                                                                    */
/*                                                                    */
/*   This computes C = ln(A)                                          */
/*   This computes C = ln(A)                                          */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A                                */
/*   res is C, the result.  C may be A                                */
/*   rhs is A                                                         */
/*   rhs is A                                                         */
/*   set is the context; note that rounding mode has no effect        */
/*   set is the context; note that rounding mode has no effect        */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Notable cases:                                                     */
/* Notable cases:                                                     */
/*   A<0 -> Invalid                                                   */
/*   A<0 -> Invalid                                                   */
/*   A=0 -> -Infinity (Exact)                                         */
/*   A=0 -> -Infinity (Exact)                                         */
/*   A=+Infinity -> +Infinity (Exact)                                 */
/*   A=+Infinity -> +Infinity (Exact)                                 */
/*   A=1 exactly -> 0 (Exact)                                         */
/*   A=1 exactly -> 0 (Exact)                                         */
/*                                                                    */
/*                                                                    */
/* Restrictions (as for Exp):                                         */
/* Restrictions (as for Exp):                                         */
/*                                                                    */
/*                                                                    */
/*   digits, emax, and -emin in the context must be less than         */
/*   digits, emax, and -emin in the context must be less than         */
/*   DEC_MAX_MATH+11 (1000010), and the rhs must be within these      */
/*   DEC_MAX_MATH+11 (1000010), and the rhs must be within these      */
/*   bounds or a zero.  This is an internal routine, so these         */
/*   bounds or a zero.  This is an internal routine, so these         */
/*   restrictions are contractual and not enforced.                   */
/*   restrictions are contractual and not enforced.                   */
/*                                                                    */
/*                                                                    */
/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will      */
/* A finite result is rounded using DEC_ROUND_HALF_EVEN; it will      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* almost always be correctly rounded, but may be up to 1 ulp in      */
/* error in rare cases.                                               */
/* error in rare cases.                                               */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* The result is calculated using Newton's method, with each          */
/* The result is calculated using Newton's method, with each          */
/* iteration calculating a' = a + x * exp(-a) - 1.  See, for example, */
/* iteration calculating a' = a + x * exp(-a) - 1.  See, for example, */
/* Epperson 1989.                                                     */
/* Epperson 1989.                                                     */
/*                                                                    */
/*                                                                    */
/* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */
/* The iteration ends when the adjustment x*exp(-a)-1 is tiny enough. */
/* This has to be calculated at the sum of the precision of x and the */
/* This has to be calculated at the sum of the precision of x and the */
/* working precision.                                                 */
/* working precision.                                                 */
/*                                                                    */
/*                                                                    */
/* Implementation notes:                                              */
/* Implementation notes:                                              */
/*                                                                    */
/*                                                                    */
/* 1. This is separated out as decLnOp so it can be called from       */
/* 1. This is separated out as decLnOp so it can be called from       */
/*    other Mathematical functions (e.g., Log 10) with a wider range  */
/*    other Mathematical functions (e.g., Log 10) with a wider range  */
/*    than normal.  In particular, it can handle the slightly wider   */
/*    than normal.  In particular, it can handle the slightly wider   */
/*    (+9+2) range needed by a power function.                        */
/*    (+9+2) range needed by a power function.                        */
/*                                                                    */
/*                                                                    */
/* 2. The speed of this function is about 10x slower than exp, as     */
/* 2. The speed of this function is about 10x slower than exp, as     */
/*    it typically needs 4-6 iterations for short numbers, and the    */
/*    it typically needs 4-6 iterations for short numbers, and the    */
/*    extra precision needed adds a squaring effect, twice.           */
/*    extra precision needed adds a squaring effect, twice.           */
/*                                                                    */
/*                                                                    */
/* 3. Fastpaths are included for ln(10) and ln(2), up to length 40,   */
/* 3. Fastpaths are included for ln(10) and ln(2), up to length 40,   */
/*    as these are common requests.  ln(10) is used by log10(x).      */
/*    as these are common requests.  ln(10) is used by log10(x).      */
/*                                                                    */
/*                                                                    */
/* 4. An iteration might be saved by widening the LNnn table, and     */
/* 4. An iteration might be saved by widening the LNnn table, and     */
/*    would certainly save at least one if it were made ten times     */
/*    would certainly save at least one if it were made ten times     */
/*    bigger, too (for truncated fractions 0.100 through 0.999).      */
/*    bigger, too (for truncated fractions 0.100 through 0.999).      */
/*    However, for most practical evaluations, at least four or five  */
/*    However, for most practical evaluations, at least four or five  */
/*    iterations will be neede -- so this would only speed up by      */
/*    iterations will be neede -- so this would only speed up by      */
/*    20-25% and that probably does not justify increasing the table  */
/*    20-25% and that probably does not justify increasing the table  */
/*    size.                                                           */
/*    size.                                                           */
/*                                                                    */
/*                                                                    */
/* 5. The static buffers are larger than might be expected to allow   */
/* 5. The static buffers are larger than might be expected to allow   */
/*    for calls from decNumberPower.                                  */
/*    for calls from decNumberPower.                                  */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decLnOp(decNumber *res, const decNumber *rhs,
decNumber * decLnOp(decNumber *res, const decNumber *rhs,
                    decContext *set, uInt *status) {
                    decContext *set, uInt *status) {
  uInt ignore=0;            /* working status accumulator */
  uInt ignore=0;            /* working status accumulator */
  uInt needbytes;                  /* for space calculations */
  uInt needbytes;                  /* for space calculations */
  Int residue;                     /* rounding residue */
  Int residue;                     /* rounding residue */
  Int r;                           /* rhs=f*10**r [see below] */
  Int r;                           /* rhs=f*10**r [see below] */
  Int p;                           /* working precision */
  Int p;                           /* working precision */
  Int pp;                          /* precision for iteration */
  Int pp;                          /* precision for iteration */
  Int t;                           /* work */
  Int t;                           /* work */
 
 
  /* buffers for a (accumulator, typically precision+2) and b */
  /* buffers for a (accumulator, typically precision+2) and b */
  /* (adjustment calculator, same size) */
  /* (adjustment calculator, same size) */
  decNumber bufa[D2N(DECBUFFER+12)];
  decNumber bufa[D2N(DECBUFFER+12)];
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *allocbufa=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *a=bufa;               /* accumulator/work */
  decNumber *a=bufa;               /* accumulator/work */
  decNumber bufb[D2N(DECBUFFER*2+2)];
  decNumber bufb[D2N(DECBUFFER*2+2)];
  decNumber *allocbufb=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *allocbufb=NULL;       /* -> allocated bufa, iff allocated */
  decNumber *b=bufb;               /* adjustment/work */
  decNumber *b=bufb;               /* adjustment/work */
 
 
  decNumber  numone;               /* constant 1 */
  decNumber  numone;               /* constant 1 */
  decNumber  cmp;                  /* work */
  decNumber  cmp;                  /* work */
  decContext aset, bset;           /* working contexts */
  decContext aset, bset;           /* working contexts */
 
 
  #if DECCHECK
  #if DECCHECK
  Int iterations=0;                 /* for later sanity check */
  Int iterations=0;                 /* for later sanity check */
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                                  /* protect allocated storage */
  do {                                  /* protect allocated storage */
    if (SPECIALARG) {                   /* handle infinities and NaNs */
    if (SPECIALARG) {                   /* handle infinities and NaNs */
      if (decNumberIsInfinite(rhs)) {   /* an infinity */
      if (decNumberIsInfinite(rhs)) {   /* an infinity */
        if (decNumberIsNegative(rhs))   /* -Infinity -> error */
        if (decNumberIsNegative(rhs))   /* -Infinity -> error */
          *status|=DEC_Invalid_operation;
          *status|=DEC_Invalid_operation;
         else decNumberCopy(res, rhs);  /* +Infinity -> self */
         else decNumberCopy(res, rhs);  /* +Infinity -> self */
        }
        }
       else decNaNs(res, rhs, NULL, set, status); /* a NaN */
       else decNaNs(res, rhs, NULL, set, status); /* a NaN */
      break;}
      break;}
 
 
    if (ISZERO(rhs)) {                  /* +/- zeros -> -Infinity */
    if (ISZERO(rhs)) {                  /* +/- zeros -> -Infinity */
      decNumberZero(res);               /* make clean */
      decNumberZero(res);               /* make clean */
      res->bits=DECINF|DECNEG;          /* set - infinity */
      res->bits=DECINF|DECNEG;          /* set - infinity */
      break;}                           /* [no status to set] */
      break;}                           /* [no status to set] */
 
 
    /* Non-zero negatives are bad... */
    /* Non-zero negatives are bad... */
    if (decNumberIsNegative(rhs)) {     /* -x -> error */
    if (decNumberIsNegative(rhs)) {     /* -x -> error */
      *status|=DEC_Invalid_operation;
      *status|=DEC_Invalid_operation;
      break;}
      break;}
 
 
    /* Here, rhs is positive, finite, and in range */
    /* Here, rhs is positive, finite, and in range */
 
 
    /* lookaside fastpath code for ln(2) and ln(10) at common lengths */
    /* lookaside fastpath code for ln(2) and ln(10) at common lengths */
    if (rhs->exponent==0 && set->digits<=40) {
    if (rhs->exponent==0 && set->digits<=40) {
      #if DECDPUN==1
      #if DECDPUN==1
      if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */
      if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */
      #else
      #else
      if (rhs->lsu[0]==10 && rhs->digits==2) {                   /* ln(10) */
      if (rhs->lsu[0]==10 && rhs->digits==2) {                   /* ln(10) */
      #endif
      #endif
        aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
        aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
        #define LN10 "2.302585092994045684017991454684364207601"
        #define LN10 "2.302585092994045684017991454684364207601"
        decNumberFromString(res, LN10, &aset);
        decNumberFromString(res, LN10, &aset);
        *status|=(DEC_Inexact | DEC_Rounded); /* is inexact */
        *status|=(DEC_Inexact | DEC_Rounded); /* is inexact */
        break;}
        break;}
      if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */
      if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */
        aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
        aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
        #define LN2 "0.6931471805599453094172321214581765680755"
        #define LN2 "0.6931471805599453094172321214581765680755"
        decNumberFromString(res, LN2, &aset);
        decNumberFromString(res, LN2, &aset);
        *status|=(DEC_Inexact | DEC_Rounded);
        *status|=(DEC_Inexact | DEC_Rounded);
        break;}
        break;}
      } /* integer and short */
      } /* integer and short */
 
 
    /* Determine the working precision.  This is normally the */
    /* Determine the working precision.  This is normally the */
    /* requested precision + 2, with a minimum of 9.  However, if */
    /* requested precision + 2, with a minimum of 9.  However, if */
    /* the rhs is 'over-precise' then allow for all its digits to */
    /* the rhs is 'over-precise' then allow for all its digits to */
    /* potentially participate (consider an rhs where all the excess */
    /* potentially participate (consider an rhs where all the excess */
    /* digits are 9s) so in this case use rhs->digits+2. */
    /* digits are 9s) so in this case use rhs->digits+2. */
    p=MAXI(rhs->digits, MAXI(set->digits, 7))+2;
    p=MAXI(rhs->digits, MAXI(set->digits, 7))+2;
 
 
    /* Allocate space for the accumulator and the high-precision */
    /* Allocate space for the accumulator and the high-precision */
    /* adjustment calculator, if necessary.  The accumulator must */
    /* adjustment calculator, if necessary.  The accumulator must */
    /* be able to hold p digits, and the adjustment up to */
    /* be able to hold p digits, and the adjustment up to */
    /* rhs->digits+p digits.  They are also made big enough for 16 */
    /* rhs->digits+p digits.  They are also made big enough for 16 */
    /* digits so that they can be used for calculating the initial */
    /* digits so that they can be used for calculating the initial */
    /* estimate. */
    /* estimate. */
    needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit);
    needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit);
    if (needbytes>sizeof(bufa)) {     /* need malloc space */
    if (needbytes>sizeof(bufa)) {     /* need malloc space */
      allocbufa=(decNumber *)malloc(needbytes);
      allocbufa=(decNumber *)malloc(needbytes);
      if (allocbufa==NULL) {          /* hopeless -- abandon */
      if (allocbufa==NULL) {          /* hopeless -- abandon */
        *status|=DEC_Insufficient_storage;
        *status|=DEC_Insufficient_storage;
        break;}
        break;}
      a=allocbufa;                    /* use the allocated space */
      a=allocbufa;                    /* use the allocated space */
      }
      }
    pp=p+rhs->digits;
    pp=p+rhs->digits;
    needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit);
    needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit);
    if (needbytes>sizeof(bufb)) {     /* need malloc space */
    if (needbytes>sizeof(bufb)) {     /* need malloc space */
      allocbufb=(decNumber *)malloc(needbytes);
      allocbufb=(decNumber *)malloc(needbytes);
      if (allocbufb==NULL) {          /* hopeless -- abandon */
      if (allocbufb==NULL) {          /* hopeless -- abandon */
        *status|=DEC_Insufficient_storage;
        *status|=DEC_Insufficient_storage;
        break;}
        break;}
      b=allocbufb;                    /* use the allocated space */
      b=allocbufb;                    /* use the allocated space */
      }
      }
 
 
    /* Prepare an initial estimate in acc. Calculate this by */
    /* Prepare an initial estimate in acc. Calculate this by */
    /* considering the coefficient of x to be a normalized fraction, */
    /* considering the coefficient of x to be a normalized fraction, */
    /* f, with the decimal point at far left and multiplied by */
    /* f, with the decimal point at far left and multiplied by */
    /* 10**r.  Then, rhs=f*10**r and 0.1<=f<1, and */
    /* 10**r.  Then, rhs=f*10**r and 0.1<=f<1, and */
    /*   ln(x) = ln(f) + ln(10)*r */
    /*   ln(x) = ln(f) + ln(10)*r */
    /* Get the initial estimate for ln(f) from a small lookup */
    /* Get the initial estimate for ln(f) from a small lookup */
    /* table (see above) indexed by the first two digits of f, */
    /* table (see above) indexed by the first two digits of f, */
    /* truncated. */
    /* truncated. */
 
 
    decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */
    decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */
    r=rhs->exponent+rhs->digits;        /* 'normalised' exponent */
    r=rhs->exponent+rhs->digits;        /* 'normalised' exponent */
    decNumberFromInt32(a, r);           /* a=r */
    decNumberFromInt32(a, r);           /* a=r */
    decNumberFromInt32(b, 2302585);     /* b=ln(10) (2.302585) */
    decNumberFromInt32(b, 2302585);     /* b=ln(10) (2.302585) */
    b->exponent=-6;                     /*  .. */
    b->exponent=-6;                     /*  .. */
    decMultiplyOp(a, a, b, &aset, &ignore);  /* a=a*b */
    decMultiplyOp(a, a, b, &aset, &ignore);  /* a=a*b */
    /* now get top two digits of rhs into b by simple truncate and */
    /* now get top two digits of rhs into b by simple truncate and */
    /* force to integer */
    /* force to integer */
    residue=0;                           /* (no residue) */
    residue=0;                           /* (no residue) */
    aset.digits=2; aset.round=DEC_ROUND_DOWN;
    aset.digits=2; aset.round=DEC_ROUND_DOWN;
    decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */
    decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */
    b->exponent=0;                       /* make integer */
    b->exponent=0;                       /* make integer */
    t=decGetInt(b);                     /* [cannot fail] */
    t=decGetInt(b);                     /* [cannot fail] */
    if (t<10) t=X10(t);                 /* adjust single-digit b */
    if (t<10) t=X10(t);                 /* adjust single-digit b */
    t=LNnn[t-10];                       /* look up ln(b) */
    t=LNnn[t-10];                       /* look up ln(b) */
    decNumberFromInt32(b, t>>2);        /* b=ln(b) coefficient */
    decNumberFromInt32(b, t>>2);        /* b=ln(b) coefficient */
    b->exponent=-(t&3)-3;               /* set exponent */
    b->exponent=-(t&3)-3;               /* set exponent */
    b->bits=DECNEG;                     /* ln(0.10)->ln(0.99) always -ve */
    b->bits=DECNEG;                     /* ln(0.10)->ln(0.99) always -ve */
    aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */
    aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */
    decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */
    decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */
    /* the initial estimate is now in a, with up to 4 digits correct. */
    /* the initial estimate is now in a, with up to 4 digits correct. */
    /* When rhs is at or near Nmax the estimate will be low, so we */
    /* When rhs is at or near Nmax the estimate will be low, so we */
    /* will approach it from below, avoiding overflow when calling exp. */
    /* will approach it from below, avoiding overflow when calling exp. */
 
 
    decNumberZero(&numone); *numone.lsu=1;   /* constant 1 for adjustment */
    decNumberZero(&numone); *numone.lsu=1;   /* constant 1 for adjustment */
 
 
    /* accumulator bounds are as requested (could underflow, but */
    /* accumulator bounds are as requested (could underflow, but */
    /* cannot overflow) */
    /* cannot overflow) */
    aset.emax=set->emax;
    aset.emax=set->emax;
    aset.emin=set->emin;
    aset.emin=set->emin;
    aset.clamp=0;                        /* no concrete format */
    aset.clamp=0;                        /* no concrete format */
    /* set up a context to be used for the multiply and subtract */
    /* set up a context to be used for the multiply and subtract */
    bset=aset;
    bset=aset;
    bset.emax=DEC_MAX_MATH*2;           /* use double bounds for the */
    bset.emax=DEC_MAX_MATH*2;           /* use double bounds for the */
    bset.emin=-DEC_MAX_MATH*2;          /* adjustment calculation */
    bset.emin=-DEC_MAX_MATH*2;          /* adjustment calculation */
                                        /* [see decExpOp call below] */
                                        /* [see decExpOp call below] */
    /* for each iteration double the number of digits to calculate, */
    /* for each iteration double the number of digits to calculate, */
    /* up to a maximum of p */
    /* up to a maximum of p */
    pp=9;                               /* initial precision */
    pp=9;                               /* initial precision */
    /* [initially 9 as then the sequence starts 7+2, 16+2, and */
    /* [initially 9 as then the sequence starts 7+2, 16+2, and */
    /* 34+2, which is ideal for standard-sized numbers] */
    /* 34+2, which is ideal for standard-sized numbers] */
    aset.digits=pp;                     /* working context */
    aset.digits=pp;                     /* working context */
    bset.digits=pp+rhs->digits;         /* wider context */
    bset.digits=pp+rhs->digits;         /* wider context */
    for (;;) {                          /* iterate */
    for (;;) {                          /* iterate */
      #if DECCHECK
      #if DECCHECK
      iterations++;
      iterations++;
      if (iterations>24) break;         /* consider 9 * 2**24 */
      if (iterations>24) break;         /* consider 9 * 2**24 */
      #endif
      #endif
      /* calculate the adjustment (exp(-a)*x-1) into b.  This is a */
      /* calculate the adjustment (exp(-a)*x-1) into b.  This is a */
      /* catastrophic subtraction but it really is the difference */
      /* catastrophic subtraction but it really is the difference */
      /* from 1 that is of interest. */
      /* from 1 that is of interest. */
      /* Use the internal entry point to Exp as it allows the double */
      /* Use the internal entry point to Exp as it allows the double */
      /* range for calculating exp(-a) when a is the tiniest subnormal. */
      /* range for calculating exp(-a) when a is the tiniest subnormal. */
      a->bits^=DECNEG;                  /* make -a */
      a->bits^=DECNEG;                  /* make -a */
      decExpOp(b, a, &bset, &ignore);   /* b=exp(-a) */
      decExpOp(b, a, &bset, &ignore);   /* b=exp(-a) */
      a->bits^=DECNEG;                  /* restore sign of a */
      a->bits^=DECNEG;                  /* restore sign of a */
      /* now multiply by rhs and subtract 1, at the wider precision */
      /* now multiply by rhs and subtract 1, at the wider precision */
      decMultiplyOp(b, b, rhs, &bset, &ignore);        /* b=b*rhs */
      decMultiplyOp(b, b, rhs, &bset, &ignore);        /* b=b*rhs */
      decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */
      decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */
 
 
      /* the iteration ends when the adjustment cannot affect the */
      /* the iteration ends when the adjustment cannot affect the */
      /* result by >=0.5 ulp (at the requested digits), which */
      /* result by >=0.5 ulp (at the requested digits), which */
      /* is when its value is smaller than the accumulator by */
      /* is when its value is smaller than the accumulator by */
      /* set->digits+1 digits (or it is zero) -- this is a looser */
      /* set->digits+1 digits (or it is zero) -- this is a looser */
      /* requirement than for Exp because all that happens to the */
      /* requirement than for Exp because all that happens to the */
      /* accumulator after this is the final rounding (but note that */
      /* accumulator after this is the final rounding (but note that */
      /* there must also be full precision in a, or a=0). */
      /* there must also be full precision in a, or a=0). */
 
 
      if (decNumberIsZero(b) ||
      if (decNumberIsZero(b) ||
          (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) {
          (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) {
        if (a->digits==p) break;
        if (a->digits==p) break;
        if (decNumberIsZero(a)) {
        if (decNumberIsZero(a)) {
          decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */
          decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */
          if (cmp.lsu[0]==0) a->exponent=0;               /* yes, exact 0 */
          if (cmp.lsu[0]==0) a->exponent=0;               /* yes, exact 0 */
           else *status|=(DEC_Inexact | DEC_Rounded);  /* no, inexact */
           else *status|=(DEC_Inexact | DEC_Rounded);  /* no, inexact */
          break;
          break;
          }
          }
        /* force padding if adjustment has gone to 0 before full length */
        /* force padding if adjustment has gone to 0 before full length */
        if (decNumberIsZero(b)) b->exponent=a->exponent-p;
        if (decNumberIsZero(b)) b->exponent=a->exponent-p;
        }
        }
 
 
      /* not done yet ... */
      /* not done yet ... */
      decAddOp(a, a, b, &aset, 0, &ignore);  /* a=a+b for next estimate */
      decAddOp(a, a, b, &aset, 0, &ignore);  /* a=a+b for next estimate */
      if (pp==p) continue;                   /* precision is at maximum */
      if (pp==p) continue;                   /* precision is at maximum */
      /* lengthen the next calculation */
      /* lengthen the next calculation */
      pp=pp*2;                               /* double precision */
      pp=pp*2;                               /* double precision */
      if (pp>p) pp=p;                        /* clamp to maximum */
      if (pp>p) pp=p;                        /* clamp to maximum */
      aset.digits=pp;                        /* working context */
      aset.digits=pp;                        /* working context */
      bset.digits=pp+rhs->digits;            /* wider context */
      bset.digits=pp+rhs->digits;            /* wider context */
      } /* Newton's iteration */
      } /* Newton's iteration */
 
 
    #if DECCHECK
    #if DECCHECK
    /* just a sanity check; remove the test to show always */
    /* just a sanity check; remove the test to show always */
    if (iterations>24)
    if (iterations>24)
      printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
      printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
            iterations, *status, p, rhs->digits);
            iterations, *status, p, rhs->digits);
    #endif
    #endif
 
 
    /* Copy and round the result to res */
    /* Copy and round the result to res */
    residue=1;                          /* indicate dirt to right */
    residue=1;                          /* indicate dirt to right */
    if (ISZERO(a)) residue=0;            /* .. unless underflowed to 0 */
    if (ISZERO(a)) residue=0;            /* .. unless underflowed to 0 */
    aset.digits=set->digits;            /* [use default rounding] */
    aset.digits=set->digits;            /* [use default rounding] */
    decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
    decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
    decFinish(res, set, &residue, status);       /* cleanup/set flags */
    decFinish(res, set, &residue, status);       /* cleanup/set flags */
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
  if (allocbufb!=NULL) free(allocbufb); /* .. */
  if (allocbufb!=NULL) free(allocbufb); /* .. */
  /* [status is handled by caller] */
  /* [status is handled by caller] */
  return res;
  return res;
  } /* decLnOp */
  } /* decLnOp */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decQuantizeOp  -- force exponent to requested value                */
/* decQuantizeOp  -- force exponent to requested value                */
/*                                                                    */
/*                                                                    */
/*   This computes C = op(A, B), where op adjusts the coefficient     */
/*   This computes C = op(A, B), where op adjusts the coefficient     */
/*   of C (by rounding or shifting) such that the exponent (-scale)   */
/*   of C (by rounding or shifting) such that the exponent (-scale)   */
/*   of C has the value B or matches the exponent of B.               */
/*   of C has the value B or matches the exponent of B.               */
/*   The numerical value of C will equal A, except for the effects of */
/*   The numerical value of C will equal A, except for the effects of */
/*   any rounding that occurred.                                      */
/*   any rounding that occurred.                                      */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A or B                           */
/*   res is C, the result.  C may be A or B                           */
/*   lhs is A, the number to adjust                                   */
/*   lhs is A, the number to adjust                                   */
/*   rhs is B, the requested exponent                                 */
/*   rhs is B, the requested exponent                                 */
/*   set is the context                                               */
/*   set is the context                                               */
/*   quant is 1 for quantize or 0 for rescale                         */
/*   quant is 1 for quantize or 0 for rescale                         */
/*   status is the status accumulator (this can be called without     */
/*   status is the status accumulator (this can be called without     */
/*          risk of control loss)                                     */
/*          risk of control loss)                                     */
/*                                                                    */
/*                                                                    */
/* C must have space for set->digits digits.                          */
/* C must have space for set->digits digits.                          */
/*                                                                    */
/*                                                                    */
/* Unless there is an error or the result is infinite, the exponent   */
/* Unless there is an error or the result is infinite, the exponent   */
/* after the operation is guaranteed to be that requested.            */
/* after the operation is guaranteed to be that requested.            */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs,
static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs,
                                 const decNumber *rhs, decContext *set,
                                 const decNumber *rhs, decContext *set,
                                 Flag quant, uInt *status) {
                                 Flag quant, uInt *status) {
  #if DECSUBSET
  #if DECSUBSET
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *allocrhs=NULL;        /* .., rhs */
  decNumber *allocrhs=NULL;        /* .., rhs */
  #endif
  #endif
  const decNumber *inrhs=rhs;      /* save original rhs */
  const decNumber *inrhs=rhs;      /* save original rhs */
  Int   reqdigits=set->digits;     /* requested DIGITS */
  Int   reqdigits=set->digits;     /* requested DIGITS */
  Int   reqexp;                    /* requested exponent [-scale] */
  Int   reqexp;                    /* requested exponent [-scale] */
  Int   residue=0;                  /* rounding residue */
  Int   residue=0;                  /* rounding residue */
  Int   etiny=set->emin-(reqdigits-1);
  Int   etiny=set->emin-(reqdigits-1);
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                             /* protect allocated storage */
  do {                             /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operands and set lostDigits status, as needed */
      /* reduce operands and set lostDigits status, as needed */
      if (lhs->digits>reqdigits) {
      if (lhs->digits>reqdigits) {
        alloclhs=decRoundOperand(lhs, set, status);
        alloclhs=decRoundOperand(lhs, set, status);
        if (alloclhs==NULL) break;
        if (alloclhs==NULL) break;
        lhs=alloclhs;
        lhs=alloclhs;
        }
        }
      if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */
      if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */
        allocrhs=decRoundOperand(rhs, set, status);
        allocrhs=decRoundOperand(rhs, set, status);
        if (allocrhs==NULL) break;
        if (allocrhs==NULL) break;
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    /* [following code does not require input rounding] */
    /* [following code does not require input rounding] */
 
 
    /* Handle special values */
    /* Handle special values */
    if (SPECIALARGS) {
    if (SPECIALARGS) {
      /* NaNs get usual processing */
      /* NaNs get usual processing */
      if (SPECIALARGS & (DECSNAN | DECNAN))
      if (SPECIALARGS & (DECSNAN | DECNAN))
        decNaNs(res, lhs, rhs, set, status);
        decNaNs(res, lhs, rhs, set, status);
      /* one infinity but not both is bad */
      /* one infinity but not both is bad */
      else if ((lhs->bits ^ rhs->bits) & DECINF)
      else if ((lhs->bits ^ rhs->bits) & DECINF)
        *status|=DEC_Invalid_operation;
        *status|=DEC_Invalid_operation;
      /* both infinity: return lhs */
      /* both infinity: return lhs */
      else decNumberCopy(res, lhs);          /* [nop if in place] */
      else decNumberCopy(res, lhs);          /* [nop if in place] */
      break;
      break;
      }
      }
 
 
    /* set requested exponent */
    /* set requested exponent */
    if (quant) reqexp=inrhs->exponent;  /* quantize -- match exponents */
    if (quant) reqexp=inrhs->exponent;  /* quantize -- match exponents */
     else {                             /* rescale -- use value of rhs */
     else {                             /* rescale -- use value of rhs */
      /* Original rhs must be an integer that fits and is in range, */
      /* Original rhs must be an integer that fits and is in range, */
      /* which could be from -1999999997 to +999999999, thanks to */
      /* which could be from -1999999997 to +999999999, thanks to */
      /* subnormals */
      /* subnormals */
      reqexp=decGetInt(inrhs);               /* [cannot fail] */
      reqexp=decGetInt(inrhs);               /* [cannot fail] */
      }
      }
 
 
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) etiny=set->emin;     /* no subnormals */
    if (!set->extended) etiny=set->emin;     /* no subnormals */
    #endif
    #endif
 
 
    if (reqexp==BADINT                       /* bad (rescale only) or .. */
    if (reqexp==BADINT                       /* bad (rescale only) or .. */
     || reqexp==BIGODD || reqexp==BIGEVEN    /* very big (ditto) or .. */
     || reqexp==BIGODD || reqexp==BIGEVEN    /* very big (ditto) or .. */
     || (reqexp<etiny)                       /* < lowest */
     || (reqexp<etiny)                       /* < lowest */
     || (reqexp>set->emax)) {                /* > emax */
     || (reqexp>set->emax)) {                /* > emax */
      *status|=DEC_Invalid_operation;
      *status|=DEC_Invalid_operation;
      break;}
      break;}
 
 
    /* the RHS has been processed, so it can be overwritten now if necessary */
    /* the RHS has been processed, so it can be overwritten now if necessary */
    if (ISZERO(lhs)) {                       /* zero coefficient unchanged */
    if (ISZERO(lhs)) {                       /* zero coefficient unchanged */
      decNumberCopy(res, lhs);               /* [nop if in place] */
      decNumberCopy(res, lhs);               /* [nop if in place] */
      res->exponent=reqexp;                  /* .. just set exponent */
      res->exponent=reqexp;                  /* .. just set exponent */
      #if DECSUBSET
      #if DECSUBSET
      if (!set->extended) res->bits=0;        /* subset specification; no -0 */
      if (!set->extended) res->bits=0;        /* subset specification; no -0 */
      #endif
      #endif
      }
      }
     else {                                  /* non-zero lhs */
     else {                                  /* non-zero lhs */
      Int adjust=reqexp-lhs->exponent;       /* digit adjustment needed */
      Int adjust=reqexp-lhs->exponent;       /* digit adjustment needed */
      /* if adjusted coefficient will definitely not fit, give up now */
      /* if adjusted coefficient will definitely not fit, give up now */
      if ((lhs->digits-adjust)>reqdigits) {
      if ((lhs->digits-adjust)>reqdigits) {
        *status|=DEC_Invalid_operation;
        *status|=DEC_Invalid_operation;
        break;
        break;
        }
        }
 
 
      if (adjust>0) {                         /* increasing exponent */
      if (adjust>0) {                         /* increasing exponent */
        /* this will decrease the length of the coefficient by adjust */
        /* this will decrease the length of the coefficient by adjust */
        /* digits, and must round as it does so */
        /* digits, and must round as it does so */
        decContext workset;                  /* work */
        decContext workset;                  /* work */
        workset=*set;                        /* clone rounding, etc. */
        workset=*set;                        /* clone rounding, etc. */
        workset.digits=lhs->digits-adjust;   /* set requested length */
        workset.digits=lhs->digits-adjust;   /* set requested length */
        /* [note that the latter can be <1, here] */
        /* [note that the latter can be <1, here] */
        decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */
        decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */
        decApplyRound(res, &workset, residue, status);    /* .. and round */
        decApplyRound(res, &workset, residue, status);    /* .. and round */
        residue=0;                                         /* [used] */
        residue=0;                                         /* [used] */
        /* If just rounded a 999s case, exponent will be off by one; */
        /* If just rounded a 999s case, exponent will be off by one; */
        /* adjust back (after checking space), if so. */
        /* adjust back (after checking space), if so. */
        if (res->exponent>reqexp) {
        if (res->exponent>reqexp) {
          /* re-check needed, e.g., for quantize(0.9999, 0.001) under */
          /* re-check needed, e.g., for quantize(0.9999, 0.001) under */
          /* set->digits==3 */
          /* set->digits==3 */
          if (res->digits==reqdigits) {      /* cannot shift by 1 */
          if (res->digits==reqdigits) {      /* cannot shift by 1 */
            *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */
            *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */
            *status|=DEC_Invalid_operation;
            *status|=DEC_Invalid_operation;
            break;
            break;
            }
            }
          res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */
          res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */
          res->exponent--;                   /* (re)adjust the exponent. */
          res->exponent--;                   /* (re)adjust the exponent. */
          }
          }
        #if DECSUBSET
        #if DECSUBSET
        if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */
        if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */
        #endif
        #endif
        } /* increase */
        } /* increase */
       else /* adjust<=0 */ {                /* decreasing or = exponent */
       else /* adjust<=0 */ {                /* decreasing or = exponent */
        /* this will increase the length of the coefficient by -adjust */
        /* this will increase the length of the coefficient by -adjust */
        /* digits, by adding zero or more trailing zeros; this is */
        /* digits, by adding zero or more trailing zeros; this is */
        /* already checked for fit, above */
        /* already checked for fit, above */
        decNumberCopy(res, lhs);             /* [it will fit] */
        decNumberCopy(res, lhs);             /* [it will fit] */
        /* if padding needed (adjust<0), add it now... */
        /* if padding needed (adjust<0), add it now... */
        if (adjust<0) {
        if (adjust<0) {
          res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
          res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
          res->exponent+=adjust;             /* adjust the exponent */
          res->exponent+=adjust;             /* adjust the exponent */
          }
          }
        } /* decrease */
        } /* decrease */
      } /* non-zero */
      } /* non-zero */
 
 
    /* Check for overflow [do not use Finalize in this case, as an */
    /* Check for overflow [do not use Finalize in this case, as an */
    /* overflow here is a "don't fit" situation] */
    /* overflow here is a "don't fit" situation] */
    if (res->exponent>set->emax-res->digits+1) {  /* too big */
    if (res->exponent>set->emax-res->digits+1) {  /* too big */
      *status|=DEC_Invalid_operation;
      *status|=DEC_Invalid_operation;
      break;
      break;
      }
      }
     else {
     else {
      decFinalize(res, set, &residue, status);    /* set subnormal flags */
      decFinalize(res, set, &residue, status);    /* set subnormal flags */
      *status&=~DEC_Underflow;          /* suppress Underflow [754r] */
      *status&=~DEC_Underflow;          /* suppress Underflow [754r] */
      }
      }
    } while(0);                          /* end protected */
    } while(0);                          /* end protected */
 
 
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs!=NULL) free(allocrhs);   /* drop any storage used */
  if (allocrhs!=NULL) free(allocrhs);   /* drop any storage used */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  #endif
  #endif
  return res;
  return res;
  } /* decQuantizeOp */
  } /* decQuantizeOp */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decCompareOp -- compare, min, or max two Numbers                   */
/* decCompareOp -- compare, min, or max two Numbers                   */
/*                                                                    */
/*                                                                    */
/*   This computes C = A ? B and carries out one of four operations:  */
/*   This computes C = A ? B and carries out one of four operations:  */
/*     COMPARE    -- returns the signum (as a number) giving the      */
/*     COMPARE    -- returns the signum (as a number) giving the      */
/*                   result of a comparison unless one or both        */
/*                   result of a comparison unless one or both        */
/*                   operands is a NaN (in which case a NaN results)  */
/*                   operands is a NaN (in which case a NaN results)  */
/*     COMPSIG    -- as COMPARE except that a quiet NaN raises        */
/*     COMPSIG    -- as COMPARE except that a quiet NaN raises        */
/*                   Invalid operation.                               */
/*                   Invalid operation.                               */
/*     COMPMAX    -- returns the larger of the operands, using the    */
/*     COMPMAX    -- returns the larger of the operands, using the    */
/*                   754r maxnum operation                            */
/*                   754r maxnum operation                            */
/*     COMPMAXMAG -- ditto, comparing absolute values                 */
/*     COMPMAXMAG -- ditto, comparing absolute values                 */
/*     COMPMIN    -- the 754r minnum operation                        */
/*     COMPMIN    -- the 754r minnum operation                        */
/*     COMPMINMAG -- ditto, comparing absolute values                 */
/*     COMPMINMAG -- ditto, comparing absolute values                 */
/*     COMTOTAL   -- returns the signum (as a number) giving the      */
/*     COMTOTAL   -- returns the signum (as a number) giving the      */
/*                   result of a comparison using 754r total ordering */
/*                   result of a comparison using 754r total ordering */
/*                                                                    */
/*                                                                    */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
/*   lhs is A                                                         */
/*   lhs is A                                                         */
/*   rhs is B                                                         */
/*   rhs is B                                                         */
/*   set is the context                                               */
/*   set is the context                                               */
/*   op  is the operation flag                                        */
/*   op  is the operation flag                                        */
/*   status is the usual accumulator                                  */
/*   status is the usual accumulator                                  */
/*                                                                    */
/*                                                                    */
/* C must have space for one digit for COMPARE or set->digits for     */
/* C must have space for one digit for COMPARE or set->digits for     */
/* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG.                       */
/* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG.                       */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* The emphasis here is on speed for common cases, and avoiding       */
/* The emphasis here is on speed for common cases, and avoiding       */
/* coefficient comparison if possible.                                */
/* coefficient comparison if possible.                                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
                         const decNumber *rhs, decContext *set,
                         const decNumber *rhs, decContext *set,
                         Flag op, uInt *status) {
                         Flag op, uInt *status) {
  #if DECSUBSET
  #if DECSUBSET
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *alloclhs=NULL;        /* non-NULL if rounded lhs allocated */
  decNumber *allocrhs=NULL;        /* .., rhs */
  decNumber *allocrhs=NULL;        /* .., rhs */
  #endif
  #endif
  Int   result=0;                   /* default result value */
  Int   result=0;                   /* default result value */
  uByte merged;                    /* work */
  uByte merged;                    /* work */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  if (decCheckOperands(res, lhs, rhs, set)) return res;
  #endif
  #endif
 
 
  do {                             /* protect allocated storage */
  do {                             /* protect allocated storage */
    #if DECSUBSET
    #if DECSUBSET
    if (!set->extended) {
    if (!set->extended) {
      /* reduce operands and set lostDigits status, as needed */
      /* reduce operands and set lostDigits status, as needed */
      if (lhs->digits>set->digits) {
      if (lhs->digits>set->digits) {
        alloclhs=decRoundOperand(lhs, set, status);
        alloclhs=decRoundOperand(lhs, set, status);
        if (alloclhs==NULL) {result=BADINT; break;}
        if (alloclhs==NULL) {result=BADINT; break;}
        lhs=alloclhs;
        lhs=alloclhs;
        }
        }
      if (rhs->digits>set->digits) {
      if (rhs->digits>set->digits) {
        allocrhs=decRoundOperand(rhs, set, status);
        allocrhs=decRoundOperand(rhs, set, status);
        if (allocrhs==NULL) {result=BADINT; break;}
        if (allocrhs==NULL) {result=BADINT; break;}
        rhs=allocrhs;
        rhs=allocrhs;
        }
        }
      }
      }
    #endif
    #endif
    /* [following code does not require input rounding] */
    /* [following code does not require input rounding] */
 
 
    /* If total ordering then handle differing signs 'up front' */
    /* If total ordering then handle differing signs 'up front' */
    if (op==COMPTOTAL) {                /* total ordering */
    if (op==COMPTOTAL) {                /* total ordering */
      if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) {
      if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) {
        result=-1;
        result=-1;
        break;
        break;
        }
        }
      if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) {
      if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) {
        result=+1;
        result=+1;
        break;
        break;
        }
        }
      }
      }
 
 
    /* handle NaNs specially; let infinities drop through */
    /* handle NaNs specially; let infinities drop through */
    /* This assumes sNaN (even just one) leads to NaN. */
    /* This assumes sNaN (even just one) leads to NaN. */
    merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN);
    merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN);
    if (merged) {                       /* a NaN bit set */
    if (merged) {                       /* a NaN bit set */
      if (op==COMPARE);                 /* result will be NaN */
      if (op==COMPARE);                 /* result will be NaN */
       else if (op==COMPSIG)            /* treat qNaN as sNaN */
       else if (op==COMPSIG)            /* treat qNaN as sNaN */
        *status|=DEC_Invalid_operation | DEC_sNaN;
        *status|=DEC_Invalid_operation | DEC_sNaN;
       else if (op==COMPTOTAL) {        /* total ordering, always finite */
       else if (op==COMPTOTAL) {        /* total ordering, always finite */
        /* signs are known to be the same; compute the ordering here */
        /* signs are known to be the same; compute the ordering here */
        /* as if the signs are both positive, then invert for negatives */
        /* as if the signs are both positive, then invert for negatives */
        if (!decNumberIsNaN(lhs)) result=-1;
        if (!decNumberIsNaN(lhs)) result=-1;
         else if (!decNumberIsNaN(rhs)) result=+1;
         else if (!decNumberIsNaN(rhs)) result=+1;
         /* here if both NaNs */
         /* here if both NaNs */
         else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1;
         else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1;
         else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1;
         else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1;
         else { /* both NaN or both sNaN */
         else { /* both NaN or both sNaN */
          /* now it just depends on the payload */
          /* now it just depends on the payload */
          result=decUnitCompare(lhs->lsu, D2U(lhs->digits),
          result=decUnitCompare(lhs->lsu, D2U(lhs->digits),
                                rhs->lsu, D2U(rhs->digits), 0);
                                rhs->lsu, D2U(rhs->digits), 0);
          /* [Error not possible, as these are 'aligned'] */
          /* [Error not possible, as these are 'aligned'] */
          } /* both same NaNs */
          } /* both same NaNs */
        if (decNumberIsNegative(lhs)) result=-result;
        if (decNumberIsNegative(lhs)) result=-result;
        break;
        break;
        } /* total order */
        } /* total order */
 
 
       else if (merged & DECSNAN);           /* sNaN -> qNaN */
       else if (merged & DECSNAN);           /* sNaN -> qNaN */
       else { /* here if MIN or MAX and one or two quiet NaNs */
       else { /* here if MIN or MAX and one or two quiet NaNs */
        /* min or max -- 754r rules ignore single NaN */
        /* min or max -- 754r rules ignore single NaN */
        if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) {
        if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) {
          /* just one NaN; force choice to be the non-NaN operand */
          /* just one NaN; force choice to be the non-NaN operand */
          op=COMPMAX;
          op=COMPMAX;
          if (lhs->bits & DECNAN) result=-1; /* pick rhs */
          if (lhs->bits & DECNAN) result=-1; /* pick rhs */
                             else result=+1; /* pick lhs */
                             else result=+1; /* pick lhs */
          break;
          break;
          }
          }
        } /* max or min */
        } /* max or min */
      op=COMPNAN;                            /* use special path */
      op=COMPNAN;                            /* use special path */
      decNaNs(res, lhs, rhs, set, status);   /* propagate NaN */
      decNaNs(res, lhs, rhs, set, status);   /* propagate NaN */
      break;
      break;
      }
      }
    /* have numbers */
    /* have numbers */
    if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1);
    if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1);
     else result=decCompare(lhs, rhs, 0);    /* sign matters */
     else result=decCompare(lhs, rhs, 0);    /* sign matters */
    } while(0);                               /* end protected */
    } while(0);                               /* end protected */
 
 
  if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */
  if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */
   else {
   else {
    if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */
    if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */
      if (op==COMPTOTAL && result==0) {
      if (op==COMPTOTAL && result==0) {
        /* operands are numerically equal or same NaN (and same sign, */
        /* operands are numerically equal or same NaN (and same sign, */
        /* tested first); if identical, leave result 0 */
        /* tested first); if identical, leave result 0 */
        if (lhs->exponent!=rhs->exponent) {
        if (lhs->exponent!=rhs->exponent) {
          if (lhs->exponent<rhs->exponent) result=-1;
          if (lhs->exponent<rhs->exponent) result=-1;
           else result=+1;
           else result=+1;
          if (decNumberIsNegative(lhs)) result=-result;
          if (decNumberIsNegative(lhs)) result=-result;
          } /* lexp!=rexp */
          } /* lexp!=rexp */
        } /* total-order by exponent */
        } /* total-order by exponent */
      decNumberZero(res);               /* [always a valid result] */
      decNumberZero(res);               /* [always a valid result] */
      if (result!=0) {                   /* must be -1 or +1 */
      if (result!=0) {                   /* must be -1 or +1 */
        *res->lsu=1;
        *res->lsu=1;
        if (result<0) res->bits=DECNEG;
        if (result<0) res->bits=DECNEG;
        }
        }
      }
      }
     else if (op==COMPNAN);             /* special, drop through */
     else if (op==COMPNAN);             /* special, drop through */
     else {                             /* MAX or MIN, non-NaN result */
     else {                             /* MAX or MIN, non-NaN result */
      Int residue=0;                     /* rounding accumulator */
      Int residue=0;                     /* rounding accumulator */
      /* choose the operand for the result */
      /* choose the operand for the result */
      const decNumber *choice;
      const decNumber *choice;
      if (result==0) { /* operands are numerically equal */
      if (result==0) { /* operands are numerically equal */
        /* choose according to sign then exponent (see 754r) */
        /* choose according to sign then exponent (see 754r) */
        uByte slhs=(lhs->bits & DECNEG);
        uByte slhs=(lhs->bits & DECNEG);
        uByte srhs=(rhs->bits & DECNEG);
        uByte srhs=(rhs->bits & DECNEG);
        #if DECSUBSET
        #if DECSUBSET
        if (!set->extended) {           /* subset: force left-hand */
        if (!set->extended) {           /* subset: force left-hand */
          op=COMPMAX;
          op=COMPMAX;
          result=+1;
          result=+1;
          }
          }
        else
        else
        #endif
        #endif
        if (slhs!=srhs) {          /* signs differ */
        if (slhs!=srhs) {          /* signs differ */
          if (slhs) result=-1;     /* rhs is max */
          if (slhs) result=-1;     /* rhs is max */
               else result=+1;     /* lhs is max */
               else result=+1;     /* lhs is max */
          }
          }
         else if (slhs && srhs) {  /* both negative */
         else if (slhs && srhs) {  /* both negative */
          if (lhs->exponent<rhs->exponent) result=+1;
          if (lhs->exponent<rhs->exponent) result=+1;
                                      else result=-1;
                                      else result=-1;
          /* [if equal, use lhs, technically identical] */
          /* [if equal, use lhs, technically identical] */
          }
          }
         else {                    /* both positive */
         else {                    /* both positive */
          if (lhs->exponent>rhs->exponent) result=+1;
          if (lhs->exponent>rhs->exponent) result=+1;
                                      else result=-1;
                                      else result=-1;
          /* [ditto] */
          /* [ditto] */
          }
          }
        } /* numerically equal */
        } /* numerically equal */
      /* here result will be non-0; reverse if looking for MIN */
      /* here result will be non-0; reverse if looking for MIN */
      if (op==COMPMIN || op==COMPMINMAG) result=-result;
      if (op==COMPMIN || op==COMPMINMAG) result=-result;
      choice=(result>0 ? lhs : rhs);     /* choose */
      choice=(result>0 ? lhs : rhs);     /* choose */
      /* copy chosen to result, rounding if need be */
      /* copy chosen to result, rounding if need be */
      decCopyFit(res, choice, set, &residue, status);
      decCopyFit(res, choice, set, &residue, status);
      decFinish(res, set, &residue, status);
      decFinish(res, set, &residue, status);
      }
      }
    }
    }
  #if DECSUBSET
  #if DECSUBSET
  if (allocrhs!=NULL) free(allocrhs);   /* free any storage used */
  if (allocrhs!=NULL) free(allocrhs);   /* free any storage used */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  if (alloclhs!=NULL) free(alloclhs);   /* .. */
  #endif
  #endif
  return res;
  return res;
  } /* decCompareOp */
  } /* decCompareOp */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decCompare -- compare two decNumbers by numerical value            */
/* decCompare -- compare two decNumbers by numerical value            */
/*                                                                    */
/*                                                                    */
/*  This routine compares A ? B without altering them.                */
/*  This routine compares A ? B without altering them.                */
/*                                                                    */
/*                                                                    */
/*  Arg1 is A, a decNumber which is not a NaN                         */
/*  Arg1 is A, a decNumber which is not a NaN                         */
/*  Arg2 is B, a decNumber which is not a NaN                         */
/*  Arg2 is B, a decNumber which is not a NaN                         */
/*  Arg3 is 1 for a sign-independent compare, 0 otherwise             */
/*  Arg3 is 1 for a sign-independent compare, 0 otherwise             */
/*                                                                    */
/*                                                                    */
/*  returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure   */
/*  returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure   */
/*  (the only possible failure is an allocation error)                */
/*  (the only possible failure is an allocation error)                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Int decCompare(const decNumber *lhs, const decNumber *rhs,
static Int decCompare(const decNumber *lhs, const decNumber *rhs,
                      Flag abs) {
                      Flag abs) {
  Int   result;                    /* result value */
  Int   result;                    /* result value */
  Int   sigr;                      /* rhs signum */
  Int   sigr;                      /* rhs signum */
  Int   compare;                   /* work */
  Int   compare;                   /* work */
 
 
  result=1;                                  /* assume signum(lhs) */
  result=1;                                  /* assume signum(lhs) */
  if (ISZERO(lhs)) result=0;
  if (ISZERO(lhs)) result=0;
  if (abs) {
  if (abs) {
    if (ISZERO(rhs)) return result;          /* LHS wins or both 0 */
    if (ISZERO(rhs)) return result;          /* LHS wins or both 0 */
    /* RHS is non-zero */
    /* RHS is non-zero */
    if (result==0) return -1;                 /* LHS is 0; RHS wins */
    if (result==0) return -1;                 /* LHS is 0; RHS wins */
    /* [here, both non-zero, result=1] */
    /* [here, both non-zero, result=1] */
    }
    }
   else {                                    /* signs matter */
   else {                                    /* signs matter */
    if (result && decNumberIsNegative(lhs)) result=-1;
    if (result && decNumberIsNegative(lhs)) result=-1;
    sigr=1;                                  /* compute signum(rhs) */
    sigr=1;                                  /* compute signum(rhs) */
    if (ISZERO(rhs)) sigr=0;
    if (ISZERO(rhs)) sigr=0;
     else if (decNumberIsNegative(rhs)) sigr=-1;
     else if (decNumberIsNegative(rhs)) sigr=-1;
    if (result > sigr) return +1;            /* L > R, return 1 */
    if (result > sigr) return +1;            /* L > R, return 1 */
    if (result < sigr) return -1;            /* L < R, return -1 */
    if (result < sigr) return -1;            /* L < R, return -1 */
    if (result==0) return 0;                     /* both 0 */
    if (result==0) return 0;                     /* both 0 */
    }
    }
 
 
  /* signums are the same; both are non-zero */
  /* signums are the same; both are non-zero */
  if ((lhs->bits | rhs->bits) & DECINF) {    /* one or more infinities */
  if ((lhs->bits | rhs->bits) & DECINF) {    /* one or more infinities */
    if (decNumberIsInfinite(rhs)) {
    if (decNumberIsInfinite(rhs)) {
      if (decNumberIsInfinite(lhs)) result=0;/* both infinite */
      if (decNumberIsInfinite(lhs)) result=0;/* both infinite */
       else result=-result;                  /* only rhs infinite */
       else result=-result;                  /* only rhs infinite */
      }
      }
    return result;
    return result;
    }
    }
  /* must compare the coefficients, allowing for exponents */
  /* must compare the coefficients, allowing for exponents */
  if (lhs->exponent>rhs->exponent) {         /* LHS exponent larger */
  if (lhs->exponent>rhs->exponent) {         /* LHS exponent larger */
    /* swap sides, and sign */
    /* swap sides, and sign */
    const decNumber *temp=lhs;
    const decNumber *temp=lhs;
    lhs=rhs;
    lhs=rhs;
    rhs=temp;
    rhs=temp;
    result=-result;
    result=-result;
    }
    }
  compare=decUnitCompare(lhs->lsu, D2U(lhs->digits),
  compare=decUnitCompare(lhs->lsu, D2U(lhs->digits),
                         rhs->lsu, D2U(rhs->digits),
                         rhs->lsu, D2U(rhs->digits),
                         rhs->exponent-lhs->exponent);
                         rhs->exponent-lhs->exponent);
  if (compare!=BADINT) compare*=result;      /* comparison succeeded */
  if (compare!=BADINT) compare*=result;      /* comparison succeeded */
  return compare;
  return compare;
  } /* decCompare */
  } /* decCompare */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decUnitCompare -- compare two >=0 integers in Unit arrays          */
/* decUnitCompare -- compare two >=0 integers in Unit arrays          */
/*                                                                    */
/*                                                                    */
/*  This routine compares A ? B*10**E where A and B are unit arrays   */
/*  This routine compares A ? B*10**E where A and B are unit arrays   */
/*  A is a plain integer                                              */
/*  A is a plain integer                                              */
/*  B has an exponent of E (which must be non-negative)               */
/*  B has an exponent of E (which must be non-negative)               */
/*                                                                    */
/*                                                                    */
/*  Arg1 is A first Unit (lsu)                                        */
/*  Arg1 is A first Unit (lsu)                                        */
/*  Arg2 is A length in Units                                         */
/*  Arg2 is A length in Units                                         */
/*  Arg3 is B first Unit (lsu)                                        */
/*  Arg3 is B first Unit (lsu)                                        */
/*  Arg4 is B length in Units                                         */
/*  Arg4 is B length in Units                                         */
/*  Arg5 is E (0 if the units are aligned)                            */
/*  Arg5 is E (0 if the units are aligned)                            */
/*                                                                    */
/*                                                                    */
/*  returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure   */
/*  returns -1, 0, or 1 for A<B, A==B, or A>B, or BADINT if failure   */
/*  (the only possible failure is an allocation error, which can      */
/*  (the only possible failure is an allocation error, which can      */
/*  only occur if E!=0)                                               */
/*  only occur if E!=0)                                               */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Int decUnitCompare(const Unit *a, Int alength,
static Int decUnitCompare(const Unit *a, Int alength,
                          const Unit *b, Int blength, Int exp) {
                          const Unit *b, Int blength, Int exp) {
  Unit  *acc;                      /* accumulator for result */
  Unit  *acc;                      /* accumulator for result */
  Unit  accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */
  Unit  accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */
  Unit  *allocacc=NULL;            /* -> allocated acc buffer, iff allocated */
  Unit  *allocacc=NULL;            /* -> allocated acc buffer, iff allocated */
  Int   accunits, need;            /* units in use or needed for acc */
  Int   accunits, need;            /* units in use or needed for acc */
  const Unit *l, *r, *u;           /* work */
  const Unit *l, *r, *u;           /* work */
  Int   expunits, exprem, result;  /* .. */
  Int   expunits, exprem, result;  /* .. */
 
 
  if (exp==0) {                     /* aligned; fastpath */
  if (exp==0) {                     /* aligned; fastpath */
    if (alength>blength) return 1;
    if (alength>blength) return 1;
    if (alength<blength) return -1;
    if (alength<blength) return -1;
    /* same number of units in both -- need unit-by-unit compare */
    /* same number of units in both -- need unit-by-unit compare */
    l=a+alength-1;
    l=a+alength-1;
    r=b+alength-1;
    r=b+alength-1;
    for (;l>=a; l--, r--) {
    for (;l>=a; l--, r--) {
      if (*l>*r) return 1;
      if (*l>*r) return 1;
      if (*l<*r) return -1;
      if (*l<*r) return -1;
      }
      }
    return 0;                       /* all units match */
    return 0;                       /* all units match */
    } /* aligned */
    } /* aligned */
 
 
  /* Unaligned.  If one is >1 unit longer than the other, padded */
  /* Unaligned.  If one is >1 unit longer than the other, padded */
  /* approximately, then can return easily */
  /* approximately, then can return easily */
  if (alength>blength+(Int)D2U(exp)) return 1;
  if (alength>blength+(Int)D2U(exp)) return 1;
  if (alength+1<blength+(Int)D2U(exp)) return -1;
  if (alength+1<blength+(Int)D2U(exp)) return -1;
 
 
  /* Need to do a real subtract.  For this, a result buffer is needed */
  /* Need to do a real subtract.  For this, a result buffer is needed */
  /* even though only the sign is of interest.  Its length needs */
  /* even though only the sign is of interest.  Its length needs */
  /* to be the larger of alength and padded blength, +2 */
  /* to be the larger of alength and padded blength, +2 */
  need=blength+D2U(exp);                /* maximum real length of B */
  need=blength+D2U(exp);                /* maximum real length of B */
  if (need<alength) need=alength;
  if (need<alength) need=alength;
  need+=2;
  need+=2;
  acc=accbuff;                          /* assume use local buffer */
  acc=accbuff;                          /* assume use local buffer */
  if (need*sizeof(Unit)>sizeof(accbuff)) {
  if (need*sizeof(Unit)>sizeof(accbuff)) {
    allocacc=(Unit *)malloc(need*sizeof(Unit));
    allocacc=(Unit *)malloc(need*sizeof(Unit));
    if (allocacc==NULL) return BADINT;  /* hopeless -- abandon */
    if (allocacc==NULL) return BADINT;  /* hopeless -- abandon */
    acc=allocacc;
    acc=allocacc;
    }
    }
  /* Calculate units and remainder from exponent. */
  /* Calculate units and remainder from exponent. */
  expunits=exp/DECDPUN;
  expunits=exp/DECDPUN;
  exprem=exp%DECDPUN;
  exprem=exp%DECDPUN;
  /* subtract [A+B*(-m)] */
  /* subtract [A+B*(-m)] */
  accunits=decUnitAddSub(a, alength, b, blength, expunits, acc,
  accunits=decUnitAddSub(a, alength, b, blength, expunits, acc,
                         -(Int)powers[exprem]);
                         -(Int)powers[exprem]);
  /* [UnitAddSub result may have leading zeros, even on zero] */
  /* [UnitAddSub result may have leading zeros, even on zero] */
  if (accunits<0) result=-1;             /* negative result */
  if (accunits<0) result=-1;             /* negative result */
   else {                               /* non-negative result */
   else {                               /* non-negative result */
    /* check units of the result before freeing any storage */
    /* check units of the result before freeing any storage */
    for (u=acc; u<acc+accunits-1 && *u==0;) u++;
    for (u=acc; u<acc+accunits-1 && *u==0;) u++;
    result=(*u==0 ? 0 : +1);
    result=(*u==0 ? 0 : +1);
    }
    }
  /* clean up and return the result */
  /* clean up and return the result */
  if (allocacc!=NULL) free(allocacc);   /* drop any storage used */
  if (allocacc!=NULL) free(allocacc);   /* drop any storage used */
  return result;
  return result;
  } /* decUnitCompare */
  } /* decUnitCompare */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays   */
/* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays   */
/*                                                                    */
/*                                                                    */
/*  This routine performs the calculation:                            */
/*  This routine performs the calculation:                            */
/*                                                                    */
/*                                                                    */
/*  C=A+(B*M)                                                         */
/*  C=A+(B*M)                                                         */
/*                                                                    */
/*                                                                    */
/*  Where M is in the range -DECDPUNMAX through +DECDPUNMAX.          */
/*  Where M is in the range -DECDPUNMAX through +DECDPUNMAX.          */
/*                                                                    */
/*                                                                    */
/*  A may be shorter or longer than B.                                */
/*  A may be shorter or longer than B.                                */
/*                                                                    */
/*                                                                    */
/*  Leading zeros are not removed after a calculation.  The result is */
/*  Leading zeros are not removed after a calculation.  The result is */
/*  either the same length as the longer of A and B (adding any       */
/*  either the same length as the longer of A and B (adding any       */
/*  shift), or one Unit longer than that (if a Unit carry occurred).  */
/*  shift), or one Unit longer than that (if a Unit carry occurred).  */
/*                                                                    */
/*                                                                    */
/*  A and B content are not altered unless C is also A or B.          */
/*  A and B content are not altered unless C is also A or B.          */
/*  C may be the same array as A or B, but only if no zero padding is */
/*  C may be the same array as A or B, but only if no zero padding is */
/*  requested (that is, C may be B only if bshift==0).                */
/*  requested (that is, C may be B only if bshift==0).                */
/*  C is filled from the lsu; only those units necessary to complete  */
/*  C is filled from the lsu; only those units necessary to complete  */
/*  the calculation are referenced.                                   */
/*  the calculation are referenced.                                   */
/*                                                                    */
/*                                                                    */
/*  Arg1 is A first Unit (lsu)                                        */
/*  Arg1 is A first Unit (lsu)                                        */
/*  Arg2 is A length in Units                                         */
/*  Arg2 is A length in Units                                         */
/*  Arg3 is B first Unit (lsu)                                        */
/*  Arg3 is B first Unit (lsu)                                        */
/*  Arg4 is B length in Units                                         */
/*  Arg4 is B length in Units                                         */
/*  Arg5 is B shift in Units  (>=0; pads with 0 units if positive)    */
/*  Arg5 is B shift in Units  (>=0; pads with 0 units if positive)    */
/*  Arg6 is C first Unit (lsu)                                        */
/*  Arg6 is C first Unit (lsu)                                        */
/*  Arg7 is M, the multiplier                                         */
/*  Arg7 is M, the multiplier                                         */
/*                                                                    */
/*                                                                    */
/*  returns the count of Units written to C, which will be non-zero   */
/*  returns the count of Units written to C, which will be non-zero   */
/*  and negated if the result is negative.  That is, the sign of the  */
/*  and negated if the result is negative.  That is, the sign of the  */
/*  returned Int is the sign of the result (positive for zero) and    */
/*  returned Int is the sign of the result (positive for zero) and    */
/*  the absolute value of the Int is the count of Units.              */
/*  the absolute value of the Int is the count of Units.              */
/*                                                                    */
/*                                                                    */
/*  It is the caller's responsibility to make sure that C size is     */
/*  It is the caller's responsibility to make sure that C size is     */
/*  safe, allowing space if necessary for a one-Unit carry.           */
/*  safe, allowing space if necessary for a one-Unit carry.           */
/*                                                                    */
/*                                                                    */
/*  This routine is severely performance-critical; *any* change here  */
/*  This routine is severely performance-critical; *any* change here  */
/*  must be measured (timed) to assure no performance degradation.    */
/*  must be measured (timed) to assure no performance degradation.    */
/*  In particular, trickery here tends to be counter-productive, as   */
/*  In particular, trickery here tends to be counter-productive, as   */
/*  increased complexity of code hurts register optimizations on      */
/*  increased complexity of code hurts register optimizations on      */
/*  register-poor architectures.  Avoiding divisions is nearly        */
/*  register-poor architectures.  Avoiding divisions is nearly        */
/*  always a Good Idea, however.                                      */
/*  always a Good Idea, however.                                      */
/*                                                                    */
/*                                                                    */
/* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark  */
/* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark  */
/* (IBM Warwick, UK) for some of the ideas used in this routine.      */
/* (IBM Warwick, UK) for some of the ideas used in this routine.      */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Int decUnitAddSub(const Unit *a, Int alength,
static Int decUnitAddSub(const Unit *a, Int alength,
                         const Unit *b, Int blength, Int bshift,
                         const Unit *b, Int blength, Int bshift,
                         Unit *c, Int m) {
                         Unit *c, Int m) {
  const Unit *alsu=a;              /* A lsu [need to remember it] */
  const Unit *alsu=a;              /* A lsu [need to remember it] */
  Unit *clsu=c;                    /* C ditto */
  Unit *clsu=c;                    /* C ditto */
  Unit *minC;                      /* low water mark for C */
  Unit *minC;                      /* low water mark for C */
  Unit *maxC;                      /* high water mark for C */
  Unit *maxC;                      /* high water mark for C */
  eInt carry=0;                     /* carry integer (could be Long) */
  eInt carry=0;                     /* carry integer (could be Long) */
  Int  add;                        /* work */
  Int  add;                        /* work */
  #if DECDPUN<=4                   /* myriadal, millenary, etc. */
  #if DECDPUN<=4                   /* myriadal, millenary, etc. */
  Int  est;                        /* estimated quotient */
  Int  est;                        /* estimated quotient */
  #endif
  #endif
 
 
  #if DECTRACE
  #if DECTRACE
  if (alength<1 || blength<1)
  if (alength<1 || blength<1)
    printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m);
    printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m);
  #endif
  #endif
 
 
  maxC=c+alength;                  /* A is usually the longer */
  maxC=c+alength;                  /* A is usually the longer */
  minC=c+blength;                  /* .. and B the shorter */
  minC=c+blength;                  /* .. and B the shorter */
  if (bshift!=0) {                  /* B is shifted; low As copy across */
  if (bshift!=0) {                  /* B is shifted; low As copy across */
    minC+=bshift;
    minC+=bshift;
    /* if in place [common], skip copy unless there's a gap [rare] */
    /* if in place [common], skip copy unless there's a gap [rare] */
    if (a==c && bshift<=alength) {
    if (a==c && bshift<=alength) {
      c+=bshift;
      c+=bshift;
      a+=bshift;
      a+=bshift;
      }
      }
     else for (; c<clsu+bshift; a++, c++) {  /* copy needed */
     else for (; c<clsu+bshift; a++, c++) {  /* copy needed */
      if (a<alsu+alength) *c=*a;
      if (a<alsu+alength) *c=*a;
       else *c=0;
       else *c=0;
      }
      }
    }
    }
  if (minC>maxC) { /* swap */
  if (minC>maxC) { /* swap */
    Unit *hold=minC;
    Unit *hold=minC;
    minC=maxC;
    minC=maxC;
    maxC=hold;
    maxC=hold;
    }
    }
 
 
  /* For speed, do the addition as two loops; the first where both A */
  /* For speed, do the addition as two loops; the first where both A */
  /* and B contribute, and the second (if necessary) where only one or */
  /* and B contribute, and the second (if necessary) where only one or */
  /* other of the numbers contribute. */
  /* other of the numbers contribute. */
  /* Carry handling is the same (i.e., duplicated) in each case. */
  /* Carry handling is the same (i.e., duplicated) in each case. */
  for (; c<minC; c++) {
  for (; c<minC; c++) {
    carry+=*a;
    carry+=*a;
    a++;
    a++;
    carry+=((eInt)*b)*m;                /* [special-casing m=1/-1 */
    carry+=((eInt)*b)*m;                /* [special-casing m=1/-1 */
    b++;                                /* here is not a win] */
    b++;                                /* here is not a win] */
    /* here carry is new Unit of digits; it could be +ve or -ve */
    /* here carry is new Unit of digits; it could be +ve or -ve */
    if ((ueInt)carry<=DECDPUNMAX) {     /* fastpath 0-DECDPUNMAX */
    if ((ueInt)carry<=DECDPUNMAX) {     /* fastpath 0-DECDPUNMAX */
      *c=(Unit)carry;
      *c=(Unit)carry;
      carry=0;
      carry=0;
      continue;
      continue;
      }
      }
    #if DECDPUN==4                           /* use divide-by-multiply */
    #if DECDPUN==4                           /* use divide-by-multiply */
      if (carry>=0) {
      if (carry>=0) {
        est=(((ueInt)carry>>11)*53687)>>18;
        est=(((ueInt)carry>>11)*53687)>>18;
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        carry=est;                           /* likely quotient [89%] */
        carry=est;                           /* likely quotient [89%] */
        if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
        if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
        carry++;
        carry++;
        *c-=DECDPUNMAX+1;
        *c-=DECDPUNMAX+1;
        continue;
        continue;
        }
        }
      /* negative case */
      /* negative case */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      est=(((ueInt)carry>>11)*53687)>>18;
      est=(((ueInt)carry>>11)*53687)>>18;
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      if (*c<DECDPUNMAX+1) continue;         /* was OK */
      if (*c<DECDPUNMAX+1) continue;         /* was OK */
      carry++;
      carry++;
      *c-=DECDPUNMAX+1;
      *c-=DECDPUNMAX+1;
    #elif DECDPUN==3
    #elif DECDPUN==3
      if (carry>=0) {
      if (carry>=0) {
        est=(((ueInt)carry>>3)*16777)>>21;
        est=(((ueInt)carry>>3)*16777)>>21;
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        carry=est;                           /* likely quotient [99%] */
        carry=est;                           /* likely quotient [99%] */
        if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
        if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
        carry++;
        carry++;
        *c-=DECDPUNMAX+1;
        *c-=DECDPUNMAX+1;
        continue;
        continue;
        }
        }
      /* negative case */
      /* negative case */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      est=(((ueInt)carry>>3)*16777)>>21;
      est=(((ueInt)carry>>3)*16777)>>21;
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      if (*c<DECDPUNMAX+1) continue;         /* was OK */
      if (*c<DECDPUNMAX+1) continue;         /* was OK */
      carry++;
      carry++;
      *c-=DECDPUNMAX+1;
      *c-=DECDPUNMAX+1;
    #elif DECDPUN<=2
    #elif DECDPUN<=2
      /* Can use QUOT10 as carry <= 4 digits */
      /* Can use QUOT10 as carry <= 4 digits */
      if (carry>=0) {
      if (carry>=0) {
        est=QUOT10(carry, DECDPUN);
        est=QUOT10(carry, DECDPUN);
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        carry=est;                           /* quotient */
        carry=est;                           /* quotient */
        continue;
        continue;
        }
        }
      /* negative case */
      /* negative case */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      est=QUOT10(carry, DECDPUN);
      est=QUOT10(carry, DECDPUN);
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
    #else
    #else
      /* remainder operator is undefined if negative, so must test */
      /* remainder operator is undefined if negative, so must test */
      if ((ueInt)carry<(DECDPUNMAX+1)*2) {   /* fastpath carry +1 */
      if ((ueInt)carry<(DECDPUNMAX+1)*2) {   /* fastpath carry +1 */
        *c=(Unit)(carry-(DECDPUNMAX+1));     /* [helps additions] */
        *c=(Unit)(carry-(DECDPUNMAX+1));     /* [helps additions] */
        carry=1;
        carry=1;
        continue;
        continue;
        }
        }
      if (carry>=0) {
      if (carry>=0) {
        *c=(Unit)(carry%(DECDPUNMAX+1));
        *c=(Unit)(carry%(DECDPUNMAX+1));
        carry=carry/(DECDPUNMAX+1);
        carry=carry/(DECDPUNMAX+1);
        continue;
        continue;
        }
        }
      /* negative case */
      /* negative case */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      *c=(Unit)(carry%(DECDPUNMAX+1));
      *c=(Unit)(carry%(DECDPUNMAX+1));
      carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
      carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
    #endif
    #endif
    } /* c */
    } /* c */
 
 
  /* now may have one or other to complete */
  /* now may have one or other to complete */
  /* [pretest to avoid loop setup/shutdown] */
  /* [pretest to avoid loop setup/shutdown] */
  if (c<maxC) for (; c<maxC; c++) {
  if (c<maxC) for (; c<maxC; c++) {
    if (a<alsu+alength) {               /* still in A */
    if (a<alsu+alength) {               /* still in A */
      carry+=*a;
      carry+=*a;
      a++;
      a++;
      }
      }
     else {                             /* inside B */
     else {                             /* inside B */
      carry+=((eInt)*b)*m;
      carry+=((eInt)*b)*m;
      b++;
      b++;
      }
      }
    /* here carry is new Unit of digits; it could be +ve or -ve and */
    /* here carry is new Unit of digits; it could be +ve or -ve and */
    /* magnitude up to DECDPUNMAX squared */
    /* magnitude up to DECDPUNMAX squared */
    if ((ueInt)carry<=DECDPUNMAX) {     /* fastpath 0-DECDPUNMAX */
    if ((ueInt)carry<=DECDPUNMAX) {     /* fastpath 0-DECDPUNMAX */
      *c=(Unit)carry;
      *c=(Unit)carry;
      carry=0;
      carry=0;
      continue;
      continue;
      }
      }
    /* result for this unit is negative or >DECDPUNMAX */
    /* result for this unit is negative or >DECDPUNMAX */
    #if DECDPUN==4                           /* use divide-by-multiply */
    #if DECDPUN==4                           /* use divide-by-multiply */
      if (carry>=0) {
      if (carry>=0) {
        est=(((ueInt)carry>>11)*53687)>>18;
        est=(((ueInt)carry>>11)*53687)>>18;
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        carry=est;                           /* likely quotient [79.7%] */
        carry=est;                           /* likely quotient [79.7%] */
        if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
        if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
        carry++;
        carry++;
        *c-=DECDPUNMAX+1;
        *c-=DECDPUNMAX+1;
        continue;
        continue;
        }
        }
      /* negative case */
      /* negative case */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      est=(((ueInt)carry>>11)*53687)>>18;
      est=(((ueInt)carry>>11)*53687)>>18;
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      if (*c<DECDPUNMAX+1) continue;         /* was OK */
      if (*c<DECDPUNMAX+1) continue;         /* was OK */
      carry++;
      carry++;
      *c-=DECDPUNMAX+1;
      *c-=DECDPUNMAX+1;
    #elif DECDPUN==3
    #elif DECDPUN==3
      if (carry>=0) {
      if (carry>=0) {
        est=(((ueInt)carry>>3)*16777)>>21;
        est=(((ueInt)carry>>3)*16777)>>21;
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        carry=est;                           /* likely quotient [99%] */
        carry=est;                           /* likely quotient [99%] */
        if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
        if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
        carry++;
        carry++;
        *c-=DECDPUNMAX+1;
        *c-=DECDPUNMAX+1;
        continue;
        continue;
        }
        }
      /* negative case */
      /* negative case */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      est=(((ueInt)carry>>3)*16777)>>21;
      est=(((ueInt)carry>>3)*16777)>>21;
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      if (*c<DECDPUNMAX+1) continue;         /* was OK */
      if (*c<DECDPUNMAX+1) continue;         /* was OK */
      carry++;
      carry++;
      *c-=DECDPUNMAX+1;
      *c-=DECDPUNMAX+1;
    #elif DECDPUN<=2
    #elif DECDPUN<=2
      if (carry>=0) {
      if (carry>=0) {
        est=QUOT10(carry, DECDPUN);
        est=QUOT10(carry, DECDPUN);
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
        carry=est;                           /* quotient */
        carry=est;                           /* quotient */
        continue;
        continue;
        }
        }
      /* negative case */
      /* negative case */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      est=QUOT10(carry, DECDPUN);
      est=QUOT10(carry, DECDPUN);
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      *c=(Unit)(carry-est*(DECDPUNMAX+1));
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
      carry=est-(DECDPUNMAX+1);              /* correctly negative */
    #else
    #else
      if ((ueInt)carry<(DECDPUNMAX+1)*2){    /* fastpath carry 1 */
      if ((ueInt)carry<(DECDPUNMAX+1)*2){    /* fastpath carry 1 */
        *c=(Unit)(carry-(DECDPUNMAX+1));
        *c=(Unit)(carry-(DECDPUNMAX+1));
        carry=1;
        carry=1;
        continue;
        continue;
        }
        }
      /* remainder operator is undefined if negative, so must test */
      /* remainder operator is undefined if negative, so must test */
      if (carry>=0) {
      if (carry>=0) {
        *c=(Unit)(carry%(DECDPUNMAX+1));
        *c=(Unit)(carry%(DECDPUNMAX+1));
        carry=carry/(DECDPUNMAX+1);
        carry=carry/(DECDPUNMAX+1);
        continue;
        continue;
        }
        }
      /* negative case */
      /* negative case */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
      *c=(Unit)(carry%(DECDPUNMAX+1));
      *c=(Unit)(carry%(DECDPUNMAX+1));
      carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
      carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
    #endif
    #endif
    } /* c */
    } /* c */
 
 
  /* OK, all A and B processed; might still have carry or borrow */
  /* OK, all A and B processed; might still have carry or borrow */
  /* return number of Units in the result, negated if a borrow */
  /* return number of Units in the result, negated if a borrow */
  if (carry==0) return c-clsu;      /* no carry, so no more to do */
  if (carry==0) return c-clsu;      /* no carry, so no more to do */
  if (carry>0) {            /* positive carry */
  if (carry>0) {            /* positive carry */
    *c=(Unit)carry;                /* place as new unit */
    *c=(Unit)carry;                /* place as new unit */
    c++;                           /* .. */
    c++;                           /* .. */
    return c-clsu;
    return c-clsu;
    }
    }
  /* -ve carry: it's a borrow; complement needed */
  /* -ve carry: it's a borrow; complement needed */
  add=1;                           /* temporary carry... */
  add=1;                           /* temporary carry... */
  for (c=clsu; c<maxC; c++) {
  for (c=clsu; c<maxC; c++) {
    add=DECDPUNMAX+add-*c;
    add=DECDPUNMAX+add-*c;
    if (add<=DECDPUNMAX) {
    if (add<=DECDPUNMAX) {
      *c=(Unit)add;
      *c=(Unit)add;
      add=0;
      add=0;
      }
      }
     else {
     else {
      *c=0;
      *c=0;
      add=1;
      add=1;
      }
      }
    }
    }
  /* add an extra unit iff it would be non-zero */
  /* add an extra unit iff it would be non-zero */
  #if DECTRACE
  #if DECTRACE
    printf("UAS borrow: add %ld, carry %ld\n", add, carry);
    printf("UAS borrow: add %ld, carry %ld\n", add, carry);
  #endif
  #endif
  if ((add-carry-1)!=0) {
  if ((add-carry-1)!=0) {
    *c=(Unit)(add-carry-1);
    *c=(Unit)(add-carry-1);
    c++;                      /* interesting, include it */
    c++;                      /* interesting, include it */
    }
    }
  return clsu-c;              /* -ve result indicates borrowed */
  return clsu-c;              /* -ve result indicates borrowed */
  } /* decUnitAddSub */
  } /* decUnitAddSub */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decTrim -- trim trailing zeros or normalize                        */
/* decTrim -- trim trailing zeros or normalize                        */
/*                                                                    */
/*                                                                    */
/*   dn is the number to trim or normalize                            */
/*   dn is the number to trim or normalize                            */
/*   set is the context to use to check for clamp                     */
/*   set is the context to use to check for clamp                     */
/*   all is 1 to remove all trailing zeros, 0 for just fraction ones  */
/*   all is 1 to remove all trailing zeros, 0 for just fraction ones  */
/*   dropped returns the number of discarded trailing zeros           */
/*   dropped returns the number of discarded trailing zeros           */
/*   returns dn                                                       */
/*   returns dn                                                       */
/*                                                                    */
/*                                                                    */
/* If clamp is set in the context then the number of zeros trimmed    */
/* If clamp is set in the context then the number of zeros trimmed    */
/* may be limited if the exponent is high.                            */
/* may be limited if the exponent is high.                            */
/* All fields are updated as required.  This is a utility operation,  */
/* All fields are updated as required.  This is a utility operation,  */
/* so special values are unchanged and no error is possible.          */
/* so special values are unchanged and no error is possible.          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static decNumber * decTrim(decNumber *dn, decContext *set, Flag all,
static decNumber * decTrim(decNumber *dn, decContext *set, Flag all,
                           Int *dropped) {
                           Int *dropped) {
  Int   d, exp;                    /* work */
  Int   d, exp;                    /* work */
  uInt  cut;                       /* .. */
  uInt  cut;                       /* .. */
  Unit  *up;                       /* -> current Unit */
  Unit  *up;                       /* -> current Unit */
 
 
  #if DECCHECK
  #if DECCHECK
  if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
  if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
  #endif
  #endif
 
 
  *dropped=0;                            /* assume no zeros dropped */
  *dropped=0;                            /* assume no zeros dropped */
  if ((dn->bits & DECSPECIAL)           /* fast exit if special .. */
  if ((dn->bits & DECSPECIAL)           /* fast exit if special .. */
    || (*dn->lsu & 0x01)) return dn;    /* .. or odd */
    || (*dn->lsu & 0x01)) return dn;    /* .. or odd */
  if (ISZERO(dn)) {                     /* .. or 0 */
  if (ISZERO(dn)) {                     /* .. or 0 */
    dn->exponent=0;                      /* (sign is preserved) */
    dn->exponent=0;                      /* (sign is preserved) */
    return dn;
    return dn;
    }
    }
 
 
  /* have a finite number which is even */
  /* have a finite number which is even */
  exp=dn->exponent;
  exp=dn->exponent;
  cut=1;                           /* digit (1-DECDPUN) in Unit */
  cut=1;                           /* digit (1-DECDPUN) in Unit */
  up=dn->lsu;                      /* -> current Unit */
  up=dn->lsu;                      /* -> current Unit */
  for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */
  for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */
    /* slice by powers */
    /* slice by powers */
    #if DECDPUN<=4
    #if DECDPUN<=4
      uInt quot=QUOT10(*up, cut);
      uInt quot=QUOT10(*up, cut);
      if ((*up-quot*powers[cut])!=0) break;  /* found non-0 digit */
      if ((*up-quot*powers[cut])!=0) break;  /* found non-0 digit */
    #else
    #else
      if (*up%powers[cut]!=0) break;          /* found non-0 digit */
      if (*up%powers[cut]!=0) break;          /* found non-0 digit */
    #endif
    #endif
    /* have a trailing 0 */
    /* have a trailing 0 */
    if (!all) {                    /* trimming */
    if (!all) {                    /* trimming */
      /* [if exp>0 then all trailing 0s are significant for trim] */
      /* [if exp>0 then all trailing 0s are significant for trim] */
      if (exp<=0) {                 /* if digit might be significant */
      if (exp<=0) {                 /* if digit might be significant */
        if (exp==0) break;          /* then quit */
        if (exp==0) break;          /* then quit */
        exp++;                     /* next digit might be significant */
        exp++;                     /* next digit might be significant */
        }
        }
      }
      }
    cut++;                         /* next power */
    cut++;                         /* next power */
    if (cut>DECDPUN) {             /* need new Unit */
    if (cut>DECDPUN) {             /* need new Unit */
      up++;
      up++;
      cut=1;
      cut=1;
      }
      }
    } /* d */
    } /* d */
  if (d==0) return dn;              /* none to drop */
  if (d==0) return dn;              /* none to drop */
 
 
  /* may need to limit drop if clamping */
  /* may need to limit drop if clamping */
  if (set->clamp) {
  if (set->clamp) {
    Int maxd=set->emax-set->digits+1-dn->exponent;
    Int maxd=set->emax-set->digits+1-dn->exponent;
    if (maxd<=0) return dn;         /* nothing possible */
    if (maxd<=0) return dn;         /* nothing possible */
    if (d>maxd) d=maxd;
    if (d>maxd) d=maxd;
    }
    }
 
 
  /* effect the drop */
  /* effect the drop */
  decShiftToLeast(dn->lsu, D2U(dn->digits), d);
  decShiftToLeast(dn->lsu, D2U(dn->digits), d);
  dn->exponent+=d;                 /* maintain numerical value */
  dn->exponent+=d;                 /* maintain numerical value */
  dn->digits-=d;                   /* new length */
  dn->digits-=d;                   /* new length */
  *dropped=d;                      /* report the count */
  *dropped=d;                      /* report the count */
  return dn;
  return dn;
  } /* decTrim */
  } /* decTrim */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decReverse -- reverse a Unit array in place                        */
/* decReverse -- reverse a Unit array in place                        */
/*                                                                    */
/*                                                                    */
/*   ulo    is the start of the array                                 */
/*   ulo    is the start of the array                                 */
/*   uhi    is the end of the array (highest Unit to include)         */
/*   uhi    is the end of the array (highest Unit to include)         */
/*                                                                    */
/*                                                                    */
/* The units ulo through uhi are reversed in place (if the number     */
/* The units ulo through uhi are reversed in place (if the number     */
/* of units is odd, the middle one is untouched).  Note that the      */
/* of units is odd, the middle one is untouched).  Note that the      */
/* digit(s) in each unit are unaffected.                              */
/* digit(s) in each unit are unaffected.                              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decReverse(Unit *ulo, Unit *uhi) {
static void decReverse(Unit *ulo, Unit *uhi) {
  Unit temp;
  Unit temp;
  for (; ulo<uhi; ulo++, uhi--) {
  for (; ulo<uhi; ulo++, uhi--) {
    temp=*ulo;
    temp=*ulo;
    *ulo=*uhi;
    *ulo=*uhi;
    *uhi=temp;
    *uhi=temp;
    }
    }
  return;
  return;
  } /* decReverse */
  } /* decReverse */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decShiftToMost -- shift digits in array towards most significant   */
/* decShiftToMost -- shift digits in array towards most significant   */
/*                                                                    */
/*                                                                    */
/*   uar    is the array                                              */
/*   uar    is the array                                              */
/*   digits is the count of digits in use in the array                */
/*   digits is the count of digits in use in the array                */
/*   shift  is the number of zeros to pad with (least significant);   */
/*   shift  is the number of zeros to pad with (least significant);   */
/*     it must be zero or positive                                    */
/*     it must be zero or positive                                    */
/*                                                                    */
/*                                                                    */
/*   returns the new length of the integer in the array, in digits    */
/*   returns the new length of the integer in the array, in digits    */
/*                                                                    */
/*                                                                    */
/* No overflow is permitted (that is, the uar array must be known to  */
/* No overflow is permitted (that is, the uar array must be known to  */
/* be large enough to hold the result, after shifting).               */
/* be large enough to hold the result, after shifting).               */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Int decShiftToMost(Unit *uar, Int digits, Int shift) {
static Int decShiftToMost(Unit *uar, Int digits, Int shift) {
  Unit  *target, *source, *first;  /* work */
  Unit  *target, *source, *first;  /* work */
  Int   cut;                       /* odd 0's to add */
  Int   cut;                       /* odd 0's to add */
  uInt  next;                      /* work */
  uInt  next;                      /* work */
 
 
  if (shift==0) return digits;      /* [fastpath] nothing to do */
  if (shift==0) return digits;      /* [fastpath] nothing to do */
  if ((digits+shift)<=DECDPUN) {   /* [fastpath] single-unit case */
  if ((digits+shift)<=DECDPUN) {   /* [fastpath] single-unit case */
    *uar=(Unit)(*uar*powers[shift]);
    *uar=(Unit)(*uar*powers[shift]);
    return digits+shift;
    return digits+shift;
    }
    }
 
 
  next=0;                           /* all paths */
  next=0;                           /* all paths */
  source=uar+D2U(digits)-1;        /* where msu comes from */
  source=uar+D2U(digits)-1;        /* where msu comes from */
  target=source+D2U(shift);        /* where upper part of first cut goes */
  target=source+D2U(shift);        /* where upper part of first cut goes */
  cut=DECDPUN-MSUDIGITS(shift);    /* where to slice */
  cut=DECDPUN-MSUDIGITS(shift);    /* where to slice */
  if (cut==0) {                     /* unit-boundary case */
  if (cut==0) {                     /* unit-boundary case */
    for (; source>=uar; source--, target--) *target=*source;
    for (; source>=uar; source--, target--) *target=*source;
    }
    }
   else {
   else {
    first=uar+D2U(digits+shift)-1; /* where msu of source will end up */
    first=uar+D2U(digits+shift)-1; /* where msu of source will end up */
    for (; source>=uar; source--, target--) {
    for (; source>=uar; source--, target--) {
      /* split the source Unit and accumulate remainder for next */
      /* split the source Unit and accumulate remainder for next */
      #if DECDPUN<=4
      #if DECDPUN<=4
        uInt quot=QUOT10(*source, cut);
        uInt quot=QUOT10(*source, cut);
        uInt rem=*source-quot*powers[cut];
        uInt rem=*source-quot*powers[cut];
        next+=quot;
        next+=quot;
      #else
      #else
        uInt rem=*source%powers[cut];
        uInt rem=*source%powers[cut];
        next+=*source/powers[cut];
        next+=*source/powers[cut];
      #endif
      #endif
      if (target<=first) *target=(Unit)next;   /* write to target iff valid */
      if (target<=first) *target=(Unit)next;   /* write to target iff valid */
      next=rem*powers[DECDPUN-cut];            /* save remainder for next Unit */
      next=rem*powers[DECDPUN-cut];            /* save remainder for next Unit */
      }
      }
    } /* shift-move */
    } /* shift-move */
 
 
  /* propagate any partial unit to one below and clear the rest */
  /* propagate any partial unit to one below and clear the rest */
  for (; target>=uar; target--) {
  for (; target>=uar; target--) {
    *target=(Unit)next;
    *target=(Unit)next;
    next=0;
    next=0;
    }
    }
  return digits+shift;
  return digits+shift;
  } /* decShiftToMost */
  } /* decShiftToMost */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decShiftToLeast -- shift digits in array towards least significant */
/* decShiftToLeast -- shift digits in array towards least significant */
/*                                                                    */
/*                                                                    */
/*   uar   is the array                                               */
/*   uar   is the array                                               */
/*   units is length of the array, in units                           */
/*   units is length of the array, in units                           */
/*   shift is the number of digits to remove from the lsu end; it     */
/*   shift is the number of digits to remove from the lsu end; it     */
/*     must be zero or positive and <= than units*DECDPUN.            */
/*     must be zero or positive and <= than units*DECDPUN.            */
/*                                                                    */
/*                                                                    */
/*   returns the new length of the integer in the array, in units     */
/*   returns the new length of the integer in the array, in units     */
/*                                                                    */
/*                                                                    */
/* Removed digits are discarded (lost).  Units not required to hold   */
/* Removed digits are discarded (lost).  Units not required to hold   */
/* the final result are unchanged.                                    */
/* the final result are unchanged.                                    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Int decShiftToLeast(Unit *uar, Int units, Int shift) {
static Int decShiftToLeast(Unit *uar, Int units, Int shift) {
  Unit  *target, *up;              /* work */
  Unit  *target, *up;              /* work */
  Int   cut, count;                /* work */
  Int   cut, count;                /* work */
  Int   quot, rem;                 /* for division */
  Int   quot, rem;                 /* for division */
 
 
  if (shift==0) return units;       /* [fastpath] nothing to do */
  if (shift==0) return units;       /* [fastpath] nothing to do */
  if (shift==units*DECDPUN) {      /* [fastpath] little to do */
  if (shift==units*DECDPUN) {      /* [fastpath] little to do */
    *uar=0;                         /* all digits cleared gives zero */
    *uar=0;                         /* all digits cleared gives zero */
    return 1;                      /* leaves just the one */
    return 1;                      /* leaves just the one */
    }
    }
 
 
  target=uar;                      /* both paths */
  target=uar;                      /* both paths */
  cut=MSUDIGITS(shift);
  cut=MSUDIGITS(shift);
  if (cut==DECDPUN) {              /* unit-boundary case; easy */
  if (cut==DECDPUN) {              /* unit-boundary case; easy */
    up=uar+D2U(shift);
    up=uar+D2U(shift);
    for (; up<uar+units; target++, up++) *target=*up;
    for (; up<uar+units; target++, up++) *target=*up;
    return target-uar;
    return target-uar;
    }
    }
 
 
  /* messier */
  /* messier */
  up=uar+D2U(shift-cut);           /* source; correct to whole Units */
  up=uar+D2U(shift-cut);           /* source; correct to whole Units */
  count=units*DECDPUN-shift;       /* the maximum new length */
  count=units*DECDPUN-shift;       /* the maximum new length */
  #if DECDPUN<=4
  #if DECDPUN<=4
    quot=QUOT10(*up, cut);
    quot=QUOT10(*up, cut);
  #else
  #else
    quot=*up/powers[cut];
    quot=*up/powers[cut];
  #endif
  #endif
  for (; ; target++) {
  for (; ; target++) {
    *target=(Unit)quot;
    *target=(Unit)quot;
    count-=(DECDPUN-cut);
    count-=(DECDPUN-cut);
    if (count<=0) break;
    if (count<=0) break;
    up++;
    up++;
    quot=*up;
    quot=*up;
    #if DECDPUN<=4
    #if DECDPUN<=4
      quot=QUOT10(quot, cut);
      quot=QUOT10(quot, cut);
      rem=*up-quot*powers[cut];
      rem=*up-quot*powers[cut];
    #else
    #else
      rem=quot%powers[cut];
      rem=quot%powers[cut];
      quot=quot/powers[cut];
      quot=quot/powers[cut];
    #endif
    #endif
    *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
    *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
    count-=cut;
    count-=cut;
    if (count<=0) break;
    if (count<=0) break;
    }
    }
  return target-uar+1;
  return target-uar+1;
  } /* decShiftToLeast */
  } /* decShiftToLeast */
 
 
#if DECSUBSET
#if DECSUBSET
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decRoundOperand -- round an operand  [used for subset only]        */
/* decRoundOperand -- round an operand  [used for subset only]        */
/*                                                                    */
/*                                                                    */
/*   dn is the number to round (dn->digits is > set->digits)          */
/*   dn is the number to round (dn->digits is > set->digits)          */
/*   set is the relevant context                                      */
/*   set is the relevant context                                      */
/*   status is the status accumulator                                 */
/*   status is the status accumulator                                 */
/*                                                                    */
/*                                                                    */
/*   returns an allocated decNumber with the rounded result.          */
/*   returns an allocated decNumber with the rounded result.          */
/*                                                                    */
/*                                                                    */
/* lostDigits and other status may be set by this.                    */
/* lostDigits and other status may be set by this.                    */
/*                                                                    */
/*                                                                    */
/* Since the input is an operand, it must not be modified.            */
/* Since the input is an operand, it must not be modified.            */
/* Instead, return an allocated decNumber, rounded as required.       */
/* Instead, return an allocated decNumber, rounded as required.       */
/* It is the caller's responsibility to free the allocated storage.   */
/* It is the caller's responsibility to free the allocated storage.   */
/*                                                                    */
/*                                                                    */
/* If no storage is available then the result cannot be used, so NULL */
/* If no storage is available then the result cannot be used, so NULL */
/* is returned.                                                       */
/* is returned.                                                       */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static decNumber *decRoundOperand(const decNumber *dn, decContext *set,
static decNumber *decRoundOperand(const decNumber *dn, decContext *set,
                                  uInt *status) {
                                  uInt *status) {
  decNumber *res;                       /* result structure */
  decNumber *res;                       /* result structure */
  uInt newstatus=0;                      /* status from round */
  uInt newstatus=0;                      /* status from round */
  Int  residue=0;                        /* rounding accumulator */
  Int  residue=0;                        /* rounding accumulator */
 
 
  /* Allocate storage for the returned decNumber, big enough for the */
  /* Allocate storage for the returned decNumber, big enough for the */
  /* length specified by the context */
  /* length specified by the context */
  res=(decNumber *)malloc(sizeof(decNumber)
  res=(decNumber *)malloc(sizeof(decNumber)
                          +(D2U(set->digits)-1)*sizeof(Unit));
                          +(D2U(set->digits)-1)*sizeof(Unit));
  if (res==NULL) {
  if (res==NULL) {
    *status|=DEC_Insufficient_storage;
    *status|=DEC_Insufficient_storage;
    return NULL;
    return NULL;
    }
    }
  decCopyFit(res, dn, set, &residue, &newstatus);
  decCopyFit(res, dn, set, &residue, &newstatus);
  decApplyRound(res, set, residue, &newstatus);
  decApplyRound(res, set, residue, &newstatus);
 
 
  /* If that set Inexact then "lost digits" is raised... */
  /* If that set Inexact then "lost digits" is raised... */
  if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits;
  if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits;
  *status|=newstatus;
  *status|=newstatus;
  return res;
  return res;
  } /* decRoundOperand */
  } /* decRoundOperand */
#endif
#endif
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decCopyFit -- copy a number, truncating the coefficient if needed  */
/* decCopyFit -- copy a number, truncating the coefficient if needed  */
/*                                                                    */
/*                                                                    */
/*   dest is the target decNumber                                     */
/*   dest is the target decNumber                                     */
/*   src  is the source decNumber                                     */
/*   src  is the source decNumber                                     */
/*   set is the context [used for length (digits) and rounding mode]  */
/*   set is the context [used for length (digits) and rounding mode]  */
/*   residue is the residue accumulator                               */
/*   residue is the residue accumulator                               */
/*   status contains the current status to be updated                 */
/*   status contains the current status to be updated                 */
/*                                                                    */
/*                                                                    */
/* (dest==src is allowed and will be a no-op if fits)                 */
/* (dest==src is allowed and will be a no-op if fits)                 */
/* All fields are updated as required.                                */
/* All fields are updated as required.                                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decCopyFit(decNumber *dest, const decNumber *src,
static void decCopyFit(decNumber *dest, const decNumber *src,
                       decContext *set, Int *residue, uInt *status) {
                       decContext *set, Int *residue, uInt *status) {
  dest->bits=src->bits;
  dest->bits=src->bits;
  dest->exponent=src->exponent;
  dest->exponent=src->exponent;
  decSetCoeff(dest, set, src->lsu, src->digits, residue, status);
  decSetCoeff(dest, set, src->lsu, src->digits, residue, status);
  } /* decCopyFit */
  } /* decCopyFit */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decSetCoeff -- set the coefficient of a number                     */
/* decSetCoeff -- set the coefficient of a number                     */
/*                                                                    */
/*                                                                    */
/*   dn    is the number whose coefficient array is to be set.        */
/*   dn    is the number whose coefficient array is to be set.        */
/*         It must have space for set->digits digits                  */
/*         It must have space for set->digits digits                  */
/*   set   is the context [for size]                                  */
/*   set   is the context [for size]                                  */
/*   lsu   -> lsu of the source coefficient [may be dn->lsu]          */
/*   lsu   -> lsu of the source coefficient [may be dn->lsu]          */
/*   len   is digits in the source coefficient [may be dn->digits]    */
/*   len   is digits in the source coefficient [may be dn->digits]    */
/*   residue is the residue accumulator.  This has values as in       */
/*   residue is the residue accumulator.  This has values as in       */
/*         decApplyRound, and will be unchanged unless the            */
/*         decApplyRound, and will be unchanged unless the            */
/*         target size is less than len.  In this case, the           */
/*         target size is less than len.  In this case, the           */
/*         coefficient is truncated and the residue is updated to     */
/*         coefficient is truncated and the residue is updated to     */
/*         reflect the previous residue and the dropped digits.       */
/*         reflect the previous residue and the dropped digits.       */
/*   status is the status accumulator, as usual                       */
/*   status is the status accumulator, as usual                       */
/*                                                                    */
/*                                                                    */
/* The coefficient may already be in the number, or it can be an      */
/* The coefficient may already be in the number, or it can be an      */
/* external intermediate array.  If it is in the number, lsu must ==  */
/* external intermediate array.  If it is in the number, lsu must ==  */
/* dn->lsu and len must == dn->digits.                                */
/* dn->lsu and len must == dn->digits.                                */
/*                                                                    */
/*                                                                    */
/* Note that the coefficient length (len) may be < set->digits, and   */
/* Note that the coefficient length (len) may be < set->digits, and   */
/* in this case this merely copies the coefficient (or is a no-op     */
/* in this case this merely copies the coefficient (or is a no-op     */
/* if dn->lsu==lsu).                                                  */
/* if dn->lsu==lsu).                                                  */
/*                                                                    */
/*                                                                    */
/* Note also that (only internally, from decQuantizeOp and            */
/* Note also that (only internally, from decQuantizeOp and            */
/* decSetSubnormal) the value of set->digits may be less than one,    */
/* decSetSubnormal) the value of set->digits may be less than one,    */
/* indicating a round to left.  This routine handles that case        */
/* indicating a round to left.  This routine handles that case        */
/* correctly; caller ensures space.                                   */
/* correctly; caller ensures space.                                   */
/*                                                                    */
/*                                                                    */
/* dn->digits, dn->lsu (and as required), and dn->exponent are        */
/* dn->digits, dn->lsu (and as required), and dn->exponent are        */
/* updated as necessary.   dn->bits (sign) is unchanged.              */
/* updated as necessary.   dn->bits (sign) is unchanged.              */
/*                                                                    */
/*                                                                    */
/* DEC_Rounded status is set if any digits are discarded.             */
/* DEC_Rounded status is set if any digits are discarded.             */
/* DEC_Inexact status is set if any non-zero digits are discarded, or */
/* DEC_Inexact status is set if any non-zero digits are discarded, or */
/*                       incoming residue was non-0 (implies rounded) */
/*                       incoming residue was non-0 (implies rounded) */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* mapping array: maps 0-9 to canonical residues, so that a residue */
/* mapping array: maps 0-9 to canonical residues, so that a residue */
/* can be adjusted in the range [-1, +1] and achieve correct rounding */
/* can be adjusted in the range [-1, +1] and achieve correct rounding */
/*                             0  1  2  3  4  5  6  7  8  9 */
/*                             0  1  2  3  4  5  6  7  8  9 */
static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7};
static const uByte resmap[10]={0, 3, 3, 3, 3, 5, 7, 7, 7, 7};
static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu,
static void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu,
                        Int len, Int *residue, uInt *status) {
                        Int len, Int *residue, uInt *status) {
  Int   discard;              /* number of digits to discard */
  Int   discard;              /* number of digits to discard */
  uInt  cut;                  /* cut point in Unit */
  uInt  cut;                  /* cut point in Unit */
  const Unit *up;             /* work */
  const Unit *up;             /* work */
  Unit  *target;              /* .. */
  Unit  *target;              /* .. */
  Int   count;                /* .. */
  Int   count;                /* .. */
  #if DECDPUN<=4
  #if DECDPUN<=4
  uInt  temp;                 /* .. */
  uInt  temp;                 /* .. */
  #endif
  #endif
 
 
  discard=len-set->digits;    /* digits to discard */
  discard=len-set->digits;    /* digits to discard */
  if (discard<=0) {            /* no digits are being discarded */
  if (discard<=0) {            /* no digits are being discarded */
    if (dn->lsu!=lsu) {       /* copy needed */
    if (dn->lsu!=lsu) {       /* copy needed */
      /* copy the coefficient array to the result number; no shift needed */
      /* copy the coefficient array to the result number; no shift needed */
      count=len;              /* avoids D2U */
      count=len;              /* avoids D2U */
      up=lsu;
      up=lsu;
      for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
      for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
        *target=*up;
        *target=*up;
      dn->digits=len;         /* set the new length */
      dn->digits=len;         /* set the new length */
      }
      }
    /* dn->exponent and residue are unchanged, record any inexactitude */
    /* dn->exponent and residue are unchanged, record any inexactitude */
    if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded);
    if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded);
    return;
    return;
    }
    }
 
 
  /* some digits must be discarded ... */
  /* some digits must be discarded ... */
  dn->exponent+=discard;      /* maintain numerical value */
  dn->exponent+=discard;      /* maintain numerical value */
  *status|=DEC_Rounded;       /* accumulate Rounded status */
  *status|=DEC_Rounded;       /* accumulate Rounded status */
  if (*residue>1) *residue=1; /* previous residue now to right, so reduce */
  if (*residue>1) *residue=1; /* previous residue now to right, so reduce */
 
 
  if (discard>len) {          /* everything, +1, is being discarded */
  if (discard>len) {          /* everything, +1, is being discarded */
    /* guard digit is 0 */
    /* guard digit is 0 */
    /* residue is all the number [NB could be all 0s] */
    /* residue is all the number [NB could be all 0s] */
    if (*residue<=0) {         /* not already positive */
    if (*residue<=0) {         /* not already positive */
      count=len;              /* avoids D2U */
      count=len;              /* avoids D2U */
      for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */
      for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */
        *residue=1;
        *residue=1;
        break;                /* no need to check any others */
        break;                /* no need to check any others */
        }
        }
      }
      }
    if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
    if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
    *dn->lsu=0;                /* coefficient will now be 0 */
    *dn->lsu=0;                /* coefficient will now be 0 */
    dn->digits=1;             /* .. */
    dn->digits=1;             /* .. */
    return;
    return;
    } /* total discard */
    } /* total discard */
 
 
  /* partial discard [most common case] */
  /* partial discard [most common case] */
  /* here, at least the first (most significant) discarded digit exists */
  /* here, at least the first (most significant) discarded digit exists */
 
 
  /* spin up the number, noting residue during the spin, until get to */
  /* spin up the number, noting residue during the spin, until get to */
  /* the Unit with the first discarded digit.  When reach it, extract */
  /* the Unit with the first discarded digit.  When reach it, extract */
  /* it and remember its position */
  /* it and remember its position */
  count=0;
  count=0;
  for (up=lsu;; up++) {
  for (up=lsu;; up++) {
    count+=DECDPUN;
    count+=DECDPUN;
    if (count>=discard) break; /* full ones all checked */
    if (count>=discard) break; /* full ones all checked */
    if (*up!=0) *residue=1;
    if (*up!=0) *residue=1;
    } /* up */
    } /* up */
 
 
  /* here up -> Unit with first discarded digit */
  /* here up -> Unit with first discarded digit */
  cut=discard-(count-DECDPUN)-1;
  cut=discard-(count-DECDPUN)-1;
  if (cut==DECDPUN-1) {       /* unit-boundary case (fast) */
  if (cut==DECDPUN-1) {       /* unit-boundary case (fast) */
    Unit half=(Unit)powers[DECDPUN]>>1;
    Unit half=(Unit)powers[DECDPUN]>>1;
    /* set residue directly */
    /* set residue directly */
    if (*up>=half) {
    if (*up>=half) {
      if (*up>half) *residue=7;
      if (*up>half) *residue=7;
      else *residue+=5;       /* add sticky bit */
      else *residue+=5;       /* add sticky bit */
      }
      }
     else { /* <half */
     else { /* <half */
      if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */
      if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */
      }
      }
    if (set->digits<=0) {     /* special for Quantize/Subnormal :-( */
    if (set->digits<=0) {     /* special for Quantize/Subnormal :-( */
      *dn->lsu=0;              /* .. result is 0 */
      *dn->lsu=0;              /* .. result is 0 */
      dn->digits=1;           /* .. */
      dn->digits=1;           /* .. */
      }
      }
     else {                   /* shift to least */
     else {                   /* shift to least */
      count=set->digits;      /* now digits to end up with */
      count=set->digits;      /* now digits to end up with */
      dn->digits=count;       /* set the new length */
      dn->digits=count;       /* set the new length */
      up++;                   /* move to next */
      up++;                   /* move to next */
      /* on unit boundary, so shift-down copy loop is simple */
      /* on unit boundary, so shift-down copy loop is simple */
      for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
      for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
        *target=*up;
        *target=*up;
      }
      }
    } /* unit-boundary case */
    } /* unit-boundary case */
 
 
   else { /* discard digit is in low digit(s), and not top digit */
   else { /* discard digit is in low digit(s), and not top digit */
    uInt  discard1;                /* first discarded digit */
    uInt  discard1;                /* first discarded digit */
    uInt  quot, rem;               /* for divisions */
    uInt  quot, rem;               /* for divisions */
    if (cut==0) quot=*up;           /* is at bottom of unit */
    if (cut==0) quot=*up;           /* is at bottom of unit */
     else /* cut>0 */ {            /* it's not at bottom of unit */
     else /* cut>0 */ {            /* it's not at bottom of unit */
      #if DECDPUN<=4
      #if DECDPUN<=4
        quot=QUOT10(*up, cut);
        quot=QUOT10(*up, cut);
        rem=*up-quot*powers[cut];
        rem=*up-quot*powers[cut];
      #else
      #else
        rem=*up%powers[cut];
        rem=*up%powers[cut];
        quot=*up/powers[cut];
        quot=*up/powers[cut];
      #endif
      #endif
      if (rem!=0) *residue=1;
      if (rem!=0) *residue=1;
      }
      }
    /* discard digit is now at bottom of quot */
    /* discard digit is now at bottom of quot */
    #if DECDPUN<=4
    #if DECDPUN<=4
      temp=(quot*6554)>>16;        /* fast /10 */
      temp=(quot*6554)>>16;        /* fast /10 */
      /* Vowels algorithm here not a win (9 instructions) */
      /* Vowels algorithm here not a win (9 instructions) */
      discard1=quot-X10(temp);
      discard1=quot-X10(temp);
      quot=temp;
      quot=temp;
    #else
    #else
      discard1=quot%10;
      discard1=quot%10;
      quot=quot/10;
      quot=quot/10;
    #endif
    #endif
    /* here, discard1 is the guard digit, and residue is everything */
    /* here, discard1 is the guard digit, and residue is everything */
    /* else [use mapping array to accumulate residue safely] */
    /* else [use mapping array to accumulate residue safely] */
    *residue+=resmap[discard1];
    *residue+=resmap[discard1];
    cut++;                         /* update cut */
    cut++;                         /* update cut */
    /* here: up -> Unit of the array with bottom digit */
    /* here: up -> Unit of the array with bottom digit */
    /*       cut is the division point for each Unit */
    /*       cut is the division point for each Unit */
    /*       quot holds the uncut high-order digits for the current unit */
    /*       quot holds the uncut high-order digits for the current unit */
    if (set->digits<=0) {           /* special for Quantize/Subnormal :-( */
    if (set->digits<=0) {           /* special for Quantize/Subnormal :-( */
      *dn->lsu=0;                   /* .. result is 0 */
      *dn->lsu=0;                   /* .. result is 0 */
      dn->digits=1;                /* .. */
      dn->digits=1;                /* .. */
      }
      }
     else {                        /* shift to least needed */
     else {                        /* shift to least needed */
      count=set->digits;           /* now digits to end up with */
      count=set->digits;           /* now digits to end up with */
      dn->digits=count;            /* set the new length */
      dn->digits=count;            /* set the new length */
      /* shift-copy the coefficient array to the result number */
      /* shift-copy the coefficient array to the result number */
      for (target=dn->lsu; ; target++) {
      for (target=dn->lsu; ; target++) {
        *target=(Unit)quot;
        *target=(Unit)quot;
        count-=(DECDPUN-cut);
        count-=(DECDPUN-cut);
        if (count<=0) break;
        if (count<=0) break;
        up++;
        up++;
        quot=*up;
        quot=*up;
        #if DECDPUN<=4
        #if DECDPUN<=4
          quot=QUOT10(quot, cut);
          quot=QUOT10(quot, cut);
          rem=*up-quot*powers[cut];
          rem=*up-quot*powers[cut];
        #else
        #else
          rem=quot%powers[cut];
          rem=quot%powers[cut];
          quot=quot/powers[cut];
          quot=quot/powers[cut];
        #endif
        #endif
        *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
        *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
        count-=cut;
        count-=cut;
        if (count<=0) break;
        if (count<=0) break;
        } /* shift-copy loop */
        } /* shift-copy loop */
      } /* shift to least */
      } /* shift to least */
    } /* not unit boundary */
    } /* not unit boundary */
 
 
  if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
  if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
  return;
  return;
  } /* decSetCoeff */
  } /* decSetCoeff */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decApplyRound -- apply pending rounding to a number                */
/* decApplyRound -- apply pending rounding to a number                */
/*                                                                    */
/*                                                                    */
/*   dn    is the number, with space for set->digits digits           */
/*   dn    is the number, with space for set->digits digits           */
/*   set   is the context [for size and rounding mode]                */
/*   set   is the context [for size and rounding mode]                */
/*   residue indicates pending rounding, being any accumulated        */
/*   residue indicates pending rounding, being any accumulated        */
/*         guard and sticky information.  It may be:                  */
/*         guard and sticky information.  It may be:                  */
/*         6-9: rounding digit is >5                                  */
/*         6-9: rounding digit is >5                                  */
/*         5:   rounding digit is exactly half-way                    */
/*         5:   rounding digit is exactly half-way                    */
/*         1-4: rounding digit is <5 and >0                            */
/*         1-4: rounding digit is <5 and >0                            */
/*         0:   the coefficient is exact                              */
/*         0:   the coefficient is exact                              */
/*        -1:   as 1, but the hidden digits are subtractive, that     */
/*        -1:   as 1, but the hidden digits are subtractive, that     */
/*              is, of the opposite sign to dn.  In this case the     */
/*              is, of the opposite sign to dn.  In this case the     */
/*              coefficient must be non-0.  This case occurs when     */
/*              coefficient must be non-0.  This case occurs when     */
/*              subtracting a small number (which can be reduced to   */
/*              subtracting a small number (which can be reduced to   */
/*              a sticky bit); see decAddOp.                          */
/*              a sticky bit); see decAddOp.                          */
/*   status is the status accumulator, as usual                       */
/*   status is the status accumulator, as usual                       */
/*                                                                    */
/*                                                                    */
/* This routine applies rounding while keeping the length of the      */
/* This routine applies rounding while keeping the length of the      */
/* coefficient constant.  The exponent and status are unchanged       */
/* coefficient constant.  The exponent and status are unchanged       */
/* except if:                                                         */
/* except if:                                                         */
/*                                                                    */
/*                                                                    */
/*   -- the coefficient was increased and is all nines (in which      */
/*   -- the coefficient was increased and is all nines (in which      */
/*      case Overflow could occur, and is handled directly here so    */
/*      case Overflow could occur, and is handled directly here so    */
/*      the caller does not need to re-test for overflow)             */
/*      the caller does not need to re-test for overflow)             */
/*                                                                    */
/*                                                                    */
/*   -- the coefficient was decreased and becomes all nines (in which */
/*   -- the coefficient was decreased and becomes all nines (in which */
/*      case Underflow could occur, and is also handled directly).    */
/*      case Underflow could occur, and is also handled directly).    */
/*                                                                    */
/*                                                                    */
/* All fields in dn are updated as required.                          */
/* All fields in dn are updated as required.                          */
/*                                                                    */
/*                                                                    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decApplyRound(decNumber *dn, decContext *set, Int residue,
static void decApplyRound(decNumber *dn, decContext *set, Int residue,
                          uInt *status) {
                          uInt *status) {
  Int  bump;                  /* 1 if coefficient needs to be incremented */
  Int  bump;                  /* 1 if coefficient needs to be incremented */
                              /* -1 if coefficient needs to be decremented */
                              /* -1 if coefficient needs to be decremented */
 
 
  if (residue==0) return;     /* nothing to apply */
  if (residue==0) return;     /* nothing to apply */
 
 
  bump=0;                      /* assume a smooth ride */
  bump=0;                      /* assume a smooth ride */
 
 
  /* now decide whether, and how, to round, depending on mode */
  /* now decide whether, and how, to round, depending on mode */
  switch (set->round) {
  switch (set->round) {
    case DEC_ROUND_05UP: {    /* round zero or five up (for reround) */
    case DEC_ROUND_05UP: {    /* round zero or five up (for reround) */
      /* This is the same as DEC_ROUND_DOWN unless there is a */
      /* This is the same as DEC_ROUND_DOWN unless there is a */
      /* positive residue and the lsd of dn is 0 or 5, in which case */
      /* positive residue and the lsd of dn is 0 or 5, in which case */
      /* it is bumped; when residue is <0, the number is therefore */
      /* it is bumped; when residue is <0, the number is therefore */
      /* bumped down unless the final digit was 1 or 6 (in which */
      /* bumped down unless the final digit was 1 or 6 (in which */
      /* case it is bumped down and then up -- a no-op) */
      /* case it is bumped down and then up -- a no-op) */
      Int lsd5=*dn->lsu%5;     /* get lsd and quintate */
      Int lsd5=*dn->lsu%5;     /* get lsd and quintate */
      if (residue<0 && lsd5!=1) bump=-1;
      if (residue<0 && lsd5!=1) bump=-1;
       else if (residue>0 && lsd5==0) bump=1;
       else if (residue>0 && lsd5==0) bump=1;
      /* [bump==1 could be applied directly; use common path for clarity] */
      /* [bump==1 could be applied directly; use common path for clarity] */
      break;} /* r-05 */
      break;} /* r-05 */
 
 
    case DEC_ROUND_DOWN: {
    case DEC_ROUND_DOWN: {
      /* no change, except if negative residue */
      /* no change, except if negative residue */
      if (residue<0) bump=-1;
      if (residue<0) bump=-1;
      break;} /* r-d */
      break;} /* r-d */
 
 
    case DEC_ROUND_HALF_DOWN: {
    case DEC_ROUND_HALF_DOWN: {
      if (residue>5) bump=1;
      if (residue>5) bump=1;
      break;} /* r-h-d */
      break;} /* r-h-d */
 
 
    case DEC_ROUND_HALF_EVEN: {
    case DEC_ROUND_HALF_EVEN: {
      if (residue>5) bump=1;            /* >0.5 goes up */
      if (residue>5) bump=1;            /* >0.5 goes up */
       else if (residue==5) {           /* exactly 0.5000... */
       else if (residue==5) {           /* exactly 0.5000... */
        /* 0.5 goes up iff [new] lsd is odd */
        /* 0.5 goes up iff [new] lsd is odd */
        if (*dn->lsu & 0x01) bump=1;
        if (*dn->lsu & 0x01) bump=1;
        }
        }
      break;} /* r-h-e */
      break;} /* r-h-e */
 
 
    case DEC_ROUND_HALF_UP: {
    case DEC_ROUND_HALF_UP: {
      if (residue>=5) bump=1;
      if (residue>=5) bump=1;
      break;} /* r-h-u */
      break;} /* r-h-u */
 
 
    case DEC_ROUND_UP: {
    case DEC_ROUND_UP: {
      if (residue>0) bump=1;
      if (residue>0) bump=1;
      break;} /* r-u */
      break;} /* r-u */
 
 
    case DEC_ROUND_CEILING: {
    case DEC_ROUND_CEILING: {
      /* same as _UP for positive numbers, and as _DOWN for negatives */
      /* same as _UP for positive numbers, and as _DOWN for negatives */
      /* [negative residue cannot occur on 0] */
      /* [negative residue cannot occur on 0] */
      if (decNumberIsNegative(dn)) {
      if (decNumberIsNegative(dn)) {
        if (residue<0) bump=-1;
        if (residue<0) bump=-1;
        }
        }
       else {
       else {
        if (residue>0) bump=1;
        if (residue>0) bump=1;
        }
        }
      break;} /* r-c */
      break;} /* r-c */
 
 
    case DEC_ROUND_FLOOR: {
    case DEC_ROUND_FLOOR: {
      /* same as _UP for negative numbers, and as _DOWN for positive */
      /* same as _UP for negative numbers, and as _DOWN for positive */
      /* [negative residue cannot occur on 0] */
      /* [negative residue cannot occur on 0] */
      if (!decNumberIsNegative(dn)) {
      if (!decNumberIsNegative(dn)) {
        if (residue<0) bump=-1;
        if (residue<0) bump=-1;
        }
        }
       else {
       else {
        if (residue>0) bump=1;
        if (residue>0) bump=1;
        }
        }
      break;} /* r-f */
      break;} /* r-f */
 
 
    default: {      /* e.g., DEC_ROUND_MAX */
    default: {      /* e.g., DEC_ROUND_MAX */
      *status|=DEC_Invalid_context;
      *status|=DEC_Invalid_context;
      #if DECTRACE || (DECCHECK && DECVERB)
      #if DECTRACE || (DECCHECK && DECVERB)
      printf("Unknown rounding mode: %d\n", set->round);
      printf("Unknown rounding mode: %d\n", set->round);
      #endif
      #endif
      break;}
      break;}
    } /* switch */
    } /* switch */
 
 
  /* now bump the number, up or down, if need be */
  /* now bump the number, up or down, if need be */
  if (bump==0) return;                        /* no action required */
  if (bump==0) return;                        /* no action required */
 
 
  /* Simply use decUnitAddSub unless bumping up and the number is */
  /* Simply use decUnitAddSub unless bumping up and the number is */
  /* all nines.  In this special case set to 100... explicitly */
  /* all nines.  In this special case set to 100... explicitly */
  /* and adjust the exponent by one (as otherwise could overflow */
  /* and adjust the exponent by one (as otherwise could overflow */
  /* the array) */
  /* the array) */
  /* Similarly handle all-nines result if bumping down. */
  /* Similarly handle all-nines result if bumping down. */
  if (bump>0) {
  if (bump>0) {
    Unit *up;                                /* work */
    Unit *up;                                /* work */
    uInt count=dn->digits;                   /* digits to be checked */
    uInt count=dn->digits;                   /* digits to be checked */
    for (up=dn->lsu; ; up++) {
    for (up=dn->lsu; ; up++) {
      if (count<=DECDPUN) {
      if (count<=DECDPUN) {
        /* this is the last Unit (the msu) */
        /* this is the last Unit (the msu) */
        if (*up!=powers[count]-1) break;     /* not still 9s */
        if (*up!=powers[count]-1) break;     /* not still 9s */
        /* here if it, too, is all nines */
        /* here if it, too, is all nines */
        *up=(Unit)powers[count-1];           /* here 999 -> 100 etc. */
        *up=(Unit)powers[count-1];           /* here 999 -> 100 etc. */
        for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */
        for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */
        dn->exponent++;                      /* and bump exponent */
        dn->exponent++;                      /* and bump exponent */
        /* [which, very rarely, could cause Overflow...] */
        /* [which, very rarely, could cause Overflow...] */
        if ((dn->exponent+dn->digits)>set->emax+1) {
        if ((dn->exponent+dn->digits)>set->emax+1) {
          decSetOverflow(dn, set, status);
          decSetOverflow(dn, set, status);
          }
          }
        return;                              /* done */
        return;                              /* done */
        }
        }
      /* a full unit to check, with more to come */
      /* a full unit to check, with more to come */
      if (*up!=DECDPUNMAX) break;            /* not still 9s */
      if (*up!=DECDPUNMAX) break;            /* not still 9s */
      count-=DECDPUN;
      count-=DECDPUN;
      } /* up */
      } /* up */
    } /* bump>0 */
    } /* bump>0 */
   else {                                    /* -1 */
   else {                                    /* -1 */
    /* here checking for a pre-bump of 1000... (leading 1, all */
    /* here checking for a pre-bump of 1000... (leading 1, all */
    /* other digits zero) */
    /* other digits zero) */
    Unit *up, *sup;                          /* work */
    Unit *up, *sup;                          /* work */
    uInt count=dn->digits;                   /* digits to be checked */
    uInt count=dn->digits;                   /* digits to be checked */
    for (up=dn->lsu; ; up++) {
    for (up=dn->lsu; ; up++) {
      if (count<=DECDPUN) {
      if (count<=DECDPUN) {
        /* this is the last Unit (the msu) */
        /* this is the last Unit (the msu) */
        if (*up!=powers[count-1]) break;     /* not 100.. */
        if (*up!=powers[count-1]) break;     /* not 100.. */
        /* here if have the 1000... case */
        /* here if have the 1000... case */
        sup=up;                              /* save msu pointer */
        sup=up;                              /* save msu pointer */
        *up=(Unit)powers[count]-1;           /* here 100 in msu -> 999 */
        *up=(Unit)powers[count]-1;           /* here 100 in msu -> 999 */
        /* others all to all-nines, too */
        /* others all to all-nines, too */
        for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1;
        for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1;
        dn->exponent--;                      /* and bump exponent */
        dn->exponent--;                      /* and bump exponent */
 
 
        /* iff the number was at the subnormal boundary (exponent=etiny) */
        /* iff the number was at the subnormal boundary (exponent=etiny) */
        /* then the exponent is now out of range, so it will in fact get */
        /* then the exponent is now out of range, so it will in fact get */
        /* clamped to etiny and the final 9 dropped. */
        /* clamped to etiny and the final 9 dropped. */
        /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */
        /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */
        /*        dn->exponent, set->digits); */
        /*        dn->exponent, set->digits); */
        if (dn->exponent+1==set->emin-set->digits+1) {
        if (dn->exponent+1==set->emin-set->digits+1) {
          if (count==1 && dn->digits==1) *sup=0;  /* here 9 -> 0[.9] */
          if (count==1 && dn->digits==1) *sup=0;  /* here 9 -> 0[.9] */
           else {
           else {
            *sup=(Unit)powers[count-1]-1;    /* here 999.. in msu -> 99.. */
            *sup=(Unit)powers[count-1]-1;    /* here 999.. in msu -> 99.. */
            dn->digits--;
            dn->digits--;
            }
            }
          dn->exponent++;
          dn->exponent++;
          *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
          *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
          }
          }
        return;                              /* done */
        return;                              /* done */
        }
        }
 
 
      /* a full unit to check, with more to come */
      /* a full unit to check, with more to come */
      if (*up!=0) break;              /* not still 0s */
      if (*up!=0) break;              /* not still 0s */
      count-=DECDPUN;
      count-=DECDPUN;
      } /* up */
      } /* up */
 
 
    } /* bump<0 */
    } /* bump<0 */
 
 
  /* Actual bump needed.  Do it. */
  /* Actual bump needed.  Do it. */
  decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump);
  decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump);
  } /* decApplyRound */
  } /* decApplyRound */
 
 
#if DECSUBSET
#if DECSUBSET
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decFinish -- finish processing a number                            */
/* decFinish -- finish processing a number                            */
/*                                                                    */
/*                                                                    */
/*   dn is the number                                                 */
/*   dn is the number                                                 */
/*   set is the context                                               */
/*   set is the context                                               */
/*   residue is the rounding accumulator (as in decApplyRound)        */
/*   residue is the rounding accumulator (as in decApplyRound)        */
/*   status is the accumulator                                        */
/*   status is the accumulator                                        */
/*                                                                    */
/*                                                                    */
/* This finishes off the current number by:                           */
/* This finishes off the current number by:                           */
/*    1. If not extended:                                             */
/*    1. If not extended:                                             */
/*       a. Converting a zero result to clean '0'                     */
/*       a. Converting a zero result to clean '0'                     */
/*       b. Reducing positive exponents to 0, if would fit in digits  */
/*       b. Reducing positive exponents to 0, if would fit in digits  */
/*    2. Checking for overflow and subnormals (always)                */
/*    2. Checking for overflow and subnormals (always)                */
/* Note this is just Finalize when no subset arithmetic.              */
/* Note this is just Finalize when no subset arithmetic.              */
/* All fields are updated as required.                                */
/* All fields are updated as required.                                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decFinish(decNumber *dn, decContext *set, Int *residue,
static void decFinish(decNumber *dn, decContext *set, Int *residue,
                      uInt *status) {
                      uInt *status) {
  if (!set->extended) {
  if (!set->extended) {
    if ISZERO(dn) {                /* value is zero */
    if ISZERO(dn) {                /* value is zero */
      dn->exponent=0;               /* clean exponent .. */
      dn->exponent=0;               /* clean exponent .. */
      dn->bits=0;                   /* .. and sign */
      dn->bits=0;                   /* .. and sign */
      return;                      /* no error possible */
      return;                      /* no error possible */
      }
      }
    if (dn->exponent>=0) {          /* non-negative exponent */
    if (dn->exponent>=0) {          /* non-negative exponent */
      /* >0; reduce to integer if possible */
      /* >0; reduce to integer if possible */
      if (set->digits >= (dn->exponent+dn->digits)) {
      if (set->digits >= (dn->exponent+dn->digits)) {
        dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent);
        dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent);
        dn->exponent=0;
        dn->exponent=0;
        }
        }
      }
      }
    } /* !extended */
    } /* !extended */
 
 
  decFinalize(dn, set, residue, status);
  decFinalize(dn, set, residue, status);
  } /* decFinish */
  } /* decFinish */
#endif
#endif
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decFinalize -- final check, clamp, and round of a number           */
/* decFinalize -- final check, clamp, and round of a number           */
/*                                                                    */
/*                                                                    */
/*   dn is the number                                                 */
/*   dn is the number                                                 */
/*   set is the context                                               */
/*   set is the context                                               */
/*   residue is the rounding accumulator (as in decApplyRound)        */
/*   residue is the rounding accumulator (as in decApplyRound)        */
/*   status is the status accumulator                                 */
/*   status is the status accumulator                                 */
/*                                                                    */
/*                                                                    */
/* This finishes off the current number by checking for subnormal     */
/* This finishes off the current number by checking for subnormal     */
/* results, applying any pending rounding, checking for overflow,     */
/* results, applying any pending rounding, checking for overflow,     */
/* and applying any clamping.                                         */
/* and applying any clamping.                                         */
/* Underflow and overflow conditions are raised as appropriate.       */
/* Underflow and overflow conditions are raised as appropriate.       */
/* All fields are updated as required.                                */
/* All fields are updated as required.                                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decFinalize(decNumber *dn, decContext *set, Int *residue,
static void decFinalize(decNumber *dn, decContext *set, Int *residue,
                        uInt *status) {
                        uInt *status) {
  Int shift;                            /* shift needed if clamping */
  Int shift;                            /* shift needed if clamping */
  Int tinyexp=set->emin-dn->digits+1;   /* precalculate subnormal boundary */
  Int tinyexp=set->emin-dn->digits+1;   /* precalculate subnormal boundary */
 
 
  /* Must be careful, here, when checking the exponent as the */
  /* Must be careful, here, when checking the exponent as the */
  /* adjusted exponent could overflow 31 bits [because it may already */
  /* adjusted exponent could overflow 31 bits [because it may already */
  /* be up to twice the expected]. */
  /* be up to twice the expected]. */
 
 
  /* First test for subnormal.  This must be done before any final */
  /* First test for subnormal.  This must be done before any final */
  /* round as the result could be rounded to Nmin or 0. */
  /* round as the result could be rounded to Nmin or 0. */
  if (dn->exponent<=tinyexp) {          /* prefilter */
  if (dn->exponent<=tinyexp) {          /* prefilter */
    Int comp;
    Int comp;
    decNumber nmin;
    decNumber nmin;
    /* A very nasty case here is dn == Nmin and residue<0 */
    /* A very nasty case here is dn == Nmin and residue<0 */
    if (dn->exponent<tinyexp) {
    if (dn->exponent<tinyexp) {
      /* Go handle subnormals; this will apply round if needed. */
      /* Go handle subnormals; this will apply round if needed. */
      decSetSubnormal(dn, set, residue, status);
      decSetSubnormal(dn, set, residue, status);
      return;
      return;
      }
      }
    /* Equals case: only subnormal if dn=Nmin and negative residue */
    /* Equals case: only subnormal if dn=Nmin and negative residue */
    decNumberZero(&nmin);
    decNumberZero(&nmin);
    nmin.lsu[0]=1;
    nmin.lsu[0]=1;
    nmin.exponent=set->emin;
    nmin.exponent=set->emin;
    comp=decCompare(dn, &nmin, 1);                /* (signless compare) */
    comp=decCompare(dn, &nmin, 1);                /* (signless compare) */
    if (comp==BADINT) {                           /* oops */
    if (comp==BADINT) {                           /* oops */
      *status|=DEC_Insufficient_storage;          /* abandon... */
      *status|=DEC_Insufficient_storage;          /* abandon... */
      return;
      return;
      }
      }
    if (*residue<0 && comp==0) {            /* neg residue and dn==Nmin */
    if (*residue<0 && comp==0) {            /* neg residue and dn==Nmin */
      decApplyRound(dn, set, *residue, status);   /* might force down */
      decApplyRound(dn, set, *residue, status);   /* might force down */
      decSetSubnormal(dn, set, residue, status);
      decSetSubnormal(dn, set, residue, status);
      return;
      return;
      }
      }
    }
    }
 
 
  /* now apply any pending round (this could raise overflow). */
  /* now apply any pending round (this could raise overflow). */
  if (*residue!=0) decApplyRound(dn, set, *residue, status);
  if (*residue!=0) decApplyRound(dn, set, *residue, status);
 
 
  /* Check for overflow [redundant in the 'rare' case] or clamp */
  /* Check for overflow [redundant in the 'rare' case] or clamp */
  if (dn->exponent<=set->emax-set->digits+1) return;   /* neither needed */
  if (dn->exponent<=set->emax-set->digits+1) return;   /* neither needed */
 
 
 
 
  /* here when might have an overflow or clamp to do */
  /* here when might have an overflow or clamp to do */
  if (dn->exponent>set->emax-dn->digits+1) {           /* too big */
  if (dn->exponent>set->emax-dn->digits+1) {           /* too big */
    decSetOverflow(dn, set, status);
    decSetOverflow(dn, set, status);
    return;
    return;
    }
    }
  /* here when the result is normal but in clamp range */
  /* here when the result is normal but in clamp range */
  if (!set->clamp) return;
  if (!set->clamp) return;
 
 
  /* here when need to apply the IEEE exponent clamp (fold-down) */
  /* here when need to apply the IEEE exponent clamp (fold-down) */
  shift=dn->exponent-(set->emax-set->digits+1);
  shift=dn->exponent-(set->emax-set->digits+1);
 
 
  /* shift coefficient (if non-zero) */
  /* shift coefficient (if non-zero) */
  if (!ISZERO(dn)) {
  if (!ISZERO(dn)) {
    dn->digits=decShiftToMost(dn->lsu, dn->digits, shift);
    dn->digits=decShiftToMost(dn->lsu, dn->digits, shift);
    }
    }
  dn->exponent-=shift;   /* adjust the exponent to match */
  dn->exponent-=shift;   /* adjust the exponent to match */
  *status|=DEC_Clamped;  /* and record the dirty deed */
  *status|=DEC_Clamped;  /* and record the dirty deed */
  return;
  return;
  } /* decFinalize */
  } /* decFinalize */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decSetOverflow -- set number to proper overflow value              */
/* decSetOverflow -- set number to proper overflow value              */
/*                                                                    */
/*                                                                    */
/*   dn is the number (used for sign [only] and result)               */
/*   dn is the number (used for sign [only] and result)               */
/*   set is the context [used for the rounding mode, etc.]            */
/*   set is the context [used for the rounding mode, etc.]            */
/*   status contains the current status to be updated                 */
/*   status contains the current status to be updated                 */
/*                                                                    */
/*                                                                    */
/* This sets the sign of a number and sets its value to either        */
/* This sets the sign of a number and sets its value to either        */
/* Infinity or the maximum finite value, depending on the sign of     */
/* Infinity or the maximum finite value, depending on the sign of     */
/* dn and the rounding mode, following IEEE 854 rules.                */
/* dn and the rounding mode, following IEEE 854 rules.                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) {
static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) {
  Flag needmax=0;                   /* result is maximum finite value */
  Flag needmax=0;                   /* result is maximum finite value */
  uByte sign=dn->bits&DECNEG;      /* clean and save sign bit */
  uByte sign=dn->bits&DECNEG;      /* clean and save sign bit */
 
 
  if (ISZERO(dn)) {                /* zero does not overflow magnitude */
  if (ISZERO(dn)) {                /* zero does not overflow magnitude */
    Int emax=set->emax;                      /* limit value */
    Int emax=set->emax;                      /* limit value */
    if (set->clamp) emax-=set->digits-1;     /* lower if clamping */
    if (set->clamp) emax-=set->digits-1;     /* lower if clamping */
    if (dn->exponent>emax) {                 /* clamp required */
    if (dn->exponent>emax) {                 /* clamp required */
      dn->exponent=emax;
      dn->exponent=emax;
      *status|=DEC_Clamped;
      *status|=DEC_Clamped;
      }
      }
    return;
    return;
    }
    }
 
 
  decNumberZero(dn);
  decNumberZero(dn);
  switch (set->round) {
  switch (set->round) {
    case DEC_ROUND_DOWN: {
    case DEC_ROUND_DOWN: {
      needmax=1;                   /* never Infinity */
      needmax=1;                   /* never Infinity */
      break;} /* r-d */
      break;} /* r-d */
    case DEC_ROUND_05UP: {
    case DEC_ROUND_05UP: {
      needmax=1;                   /* never Infinity */
      needmax=1;                   /* never Infinity */
      break;} /* r-05 */
      break;} /* r-05 */
    case DEC_ROUND_CEILING: {
    case DEC_ROUND_CEILING: {
      if (sign) needmax=1;         /* Infinity if non-negative */
      if (sign) needmax=1;         /* Infinity if non-negative */
      break;} /* r-c */
      break;} /* r-c */
    case DEC_ROUND_FLOOR: {
    case DEC_ROUND_FLOOR: {
      if (!sign) needmax=1;        /* Infinity if negative */
      if (!sign) needmax=1;        /* Infinity if negative */
      break;} /* r-f */
      break;} /* r-f */
    default: break;                /* Infinity in all other cases */
    default: break;                /* Infinity in all other cases */
    }
    }
  if (needmax) {
  if (needmax) {
    decSetMaxValue(dn, set);
    decSetMaxValue(dn, set);
    dn->bits=sign;                 /* set sign */
    dn->bits=sign;                 /* set sign */
    }
    }
   else dn->bits=sign|DECINF;      /* Value is +/-Infinity */
   else dn->bits=sign|DECINF;      /* Value is +/-Infinity */
  *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded;
  *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded;
  } /* decSetOverflow */
  } /* decSetOverflow */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decSetMaxValue -- set number to +Nmax (maximum normal value)       */
/* decSetMaxValue -- set number to +Nmax (maximum normal value)       */
/*                                                                    */
/*                                                                    */
/*   dn is the number to set                                          */
/*   dn is the number to set                                          */
/*   set is the context [used for digits and emax]                    */
/*   set is the context [used for digits and emax]                    */
/*                                                                    */
/*                                                                    */
/* This sets the number to the maximum positive value.                */
/* This sets the number to the maximum positive value.                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decSetMaxValue(decNumber *dn, decContext *set) {
static void decSetMaxValue(decNumber *dn, decContext *set) {
  Unit *up;                        /* work */
  Unit *up;                        /* work */
  Int count=set->digits;           /* nines to add */
  Int count=set->digits;           /* nines to add */
  dn->digits=count;
  dn->digits=count;
  /* fill in all nines to set maximum value */
  /* fill in all nines to set maximum value */
  for (up=dn->lsu; ; up++) {
  for (up=dn->lsu; ; up++) {
    if (count>DECDPUN) *up=DECDPUNMAX;  /* unit full o'nines */
    if (count>DECDPUN) *up=DECDPUNMAX;  /* unit full o'nines */
     else {                             /* this is the msu */
     else {                             /* this is the msu */
      *up=(Unit)(powers[count]-1);
      *up=(Unit)(powers[count]-1);
      break;
      break;
      }
      }
    count-=DECDPUN;                /* filled those digits */
    count-=DECDPUN;                /* filled those digits */
    } /* up */
    } /* up */
  dn->bits=0;                       /* + sign */
  dn->bits=0;                       /* + sign */
  dn->exponent=set->emax-set->digits+1;
  dn->exponent=set->emax-set->digits+1;
  } /* decSetMaxValue */
  } /* decSetMaxValue */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decSetSubnormal -- process value whose exponent is <Emin           */
/* decSetSubnormal -- process value whose exponent is <Emin           */
/*                                                                    */
/*                                                                    */
/*   dn is the number (used as input as well as output; it may have   */
/*   dn is the number (used as input as well as output; it may have   */
/*         an allowed subnormal value, which may need to be rounded)  */
/*         an allowed subnormal value, which may need to be rounded)  */
/*   set is the context [used for the rounding mode]                  */
/*   set is the context [used for the rounding mode]                  */
/*   residue is any pending residue                                   */
/*   residue is any pending residue                                   */
/*   status contains the current status to be updated                 */
/*   status contains the current status to be updated                 */
/*                                                                    */
/*                                                                    */
/* If subset mode, set result to zero and set Underflow flags.        */
/* If subset mode, set result to zero and set Underflow flags.        */
/*                                                                    */
/*                                                                    */
/* Value may be zero with a low exponent; this does not set Subnormal */
/* Value may be zero with a low exponent; this does not set Subnormal */
/* but the exponent will be clamped to Etiny.                         */
/* but the exponent will be clamped to Etiny.                         */
/*                                                                    */
/*                                                                    */
/* Otherwise ensure exponent is not out of range, and round as        */
/* Otherwise ensure exponent is not out of range, and round as        */
/* necessary.  Underflow is set if the result is Inexact.             */
/* necessary.  Underflow is set if the result is Inexact.             */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
                            uInt *status) {
                            uInt *status) {
  Int        dnexp;           /* saves original exponent */
  Int        dnexp;           /* saves original exponent */
  decContext workset;         /* work */
  decContext workset;         /* work */
  Int        etiny, adjust;   /* .. */
  Int        etiny, adjust;   /* .. */
 
 
  #if DECSUBSET
  #if DECSUBSET
  /* simple set to zero and 'hard underflow' for subset */
  /* simple set to zero and 'hard underflow' for subset */
  if (!set->extended) {
  if (!set->extended) {
    decNumberZero(dn);
    decNumberZero(dn);
    /* always full overflow */
    /* always full overflow */
    *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
    *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
    return;
    return;
    }
    }
  #endif
  #endif
 
 
  /* Full arithmetic -- allow subnormals, rounded to minimum exponent */
  /* Full arithmetic -- allow subnormals, rounded to minimum exponent */
  /* (Etiny) if needed */
  /* (Etiny) if needed */
  etiny=set->emin-(set->digits-1);      /* smallest allowed exponent */
  etiny=set->emin-(set->digits-1);      /* smallest allowed exponent */
 
 
  if ISZERO(dn) {                       /* value is zero */
  if ISZERO(dn) {                       /* value is zero */
    /* residue can never be non-zero here */
    /* residue can never be non-zero here */
    #if DECCHECK
    #if DECCHECK
      if (*residue!=0) {
      if (*residue!=0) {
        printf("++ Subnormal 0 residue %ld\n", (LI)*residue);
        printf("++ Subnormal 0 residue %ld\n", (LI)*residue);
        *status|=DEC_Invalid_operation;
        *status|=DEC_Invalid_operation;
        }
        }
    #endif
    #endif
    if (dn->exponent<etiny) {           /* clamp required */
    if (dn->exponent<etiny) {           /* clamp required */
      dn->exponent=etiny;
      dn->exponent=etiny;
      *status|=DEC_Clamped;
      *status|=DEC_Clamped;
      }
      }
    return;
    return;
    }
    }
 
 
  *status|=DEC_Subnormal;               /* have a non-zero subnormal */
  *status|=DEC_Subnormal;               /* have a non-zero subnormal */
  adjust=etiny-dn->exponent;            /* calculate digits to remove */
  adjust=etiny-dn->exponent;            /* calculate digits to remove */
  if (adjust<=0) {                       /* not out of range; unrounded */
  if (adjust<=0) {                       /* not out of range; unrounded */
    /* residue can never be non-zero here, except in the Nmin-residue */
    /* residue can never be non-zero here, except in the Nmin-residue */
    /* case (which is a subnormal result), so can take fast-path here */
    /* case (which is a subnormal result), so can take fast-path here */
    /* it may already be inexact (from setting the coefficient) */
    /* it may already be inexact (from setting the coefficient) */
    if (*status&DEC_Inexact) *status|=DEC_Underflow;
    if (*status&DEC_Inexact) *status|=DEC_Underflow;
    return;
    return;
    }
    }
 
 
  /* adjust>0, so need to rescale the result so exponent becomes Etiny */
  /* adjust>0, so need to rescale the result so exponent becomes Etiny */
  /* [this code is similar to that in rescale] */
  /* [this code is similar to that in rescale] */
  dnexp=dn->exponent;                   /* save exponent */
  dnexp=dn->exponent;                   /* save exponent */
  workset=*set;                         /* clone rounding, etc. */
  workset=*set;                         /* clone rounding, etc. */
  workset.digits=dn->digits-adjust;     /* set requested length */
  workset.digits=dn->digits-adjust;     /* set requested length */
  workset.emin-=adjust;                 /* and adjust emin to match */
  workset.emin-=adjust;                 /* and adjust emin to match */
  /* [note that the latter can be <1, here, similar to Rescale case] */
  /* [note that the latter can be <1, here, similar to Rescale case] */
  decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status);
  decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status);
  decApplyRound(dn, &workset, *residue, status);
  decApplyRound(dn, &workset, *residue, status);
 
 
  /* Use 754R/854 default rule: Underflow is set iff Inexact */
  /* Use 754R/854 default rule: Underflow is set iff Inexact */
  /* [independent of whether trapped] */
  /* [independent of whether trapped] */
  if (*status&DEC_Inexact) *status|=DEC_Underflow;
  if (*status&DEC_Inexact) *status|=DEC_Underflow;
 
 
  /* if rounded up a 999s case, exponent will be off by one; adjust */
  /* if rounded up a 999s case, exponent will be off by one; adjust */
  /* back if so [it will fit, because it was shortened earlier] */
  /* back if so [it will fit, because it was shortened earlier] */
  if (dn->exponent>etiny) {
  if (dn->exponent>etiny) {
    dn->digits=decShiftToMost(dn->lsu, dn->digits, 1);
    dn->digits=decShiftToMost(dn->lsu, dn->digits, 1);
    dn->exponent--;                     /* (re)adjust the exponent. */
    dn->exponent--;                     /* (re)adjust the exponent. */
    }
    }
 
 
  /* if rounded to zero, it is by definition clamped... */
  /* if rounded to zero, it is by definition clamped... */
  if (ISZERO(dn)) *status|=DEC_Clamped;
  if (ISZERO(dn)) *status|=DEC_Clamped;
  } /* decSetSubnormal */
  } /* decSetSubnormal */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decCheckMath - check entry conditions for a math function          */
/* decCheckMath - check entry conditions for a math function          */
/*                                                                    */
/*                                                                    */
/*   This checks the context and the operand                          */
/*   This checks the context and the operand                          */
/*                                                                    */
/*                                                                    */
/*   rhs is the operand to check                                      */
/*   rhs is the operand to check                                      */
/*   set is the context to check                                      */
/*   set is the context to check                                      */
/*   status is unchanged if both are good                             */
/*   status is unchanged if both are good                             */
/*                                                                    */
/*                                                                    */
/* returns non-zero if status is changed, 0 otherwise                 */
/* returns non-zero if status is changed, 0 otherwise                 */
/*                                                                    */
/*                                                                    */
/* Restrictions enforced:                                             */
/* Restrictions enforced:                                             */
/*                                                                    */
/*                                                                    */
/*   digits, emax, and -emin in the context must be less than         */
/*   digits, emax, and -emin in the context must be less than         */
/*   DEC_MAX_MATH (999999), and A must be within these bounds if      */
/*   DEC_MAX_MATH (999999), and A must be within these bounds if      */
/*   non-zero.  Invalid_operation is set in the status if a           */
/*   non-zero.  Invalid_operation is set in the status if a           */
/*   restriction is violated.                                         */
/*   restriction is violated.                                         */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static uInt decCheckMath(const decNumber *rhs, decContext *set,
static uInt decCheckMath(const decNumber *rhs, decContext *set,
                         uInt *status) {
                         uInt *status) {
  uInt save=*status;                         /* record */
  uInt save=*status;                         /* record */
  if (set->digits>DEC_MAX_MATH
  if (set->digits>DEC_MAX_MATH
   || set->emax>DEC_MAX_MATH
   || set->emax>DEC_MAX_MATH
   || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context;
   || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context;
   else if ((rhs->digits>DEC_MAX_MATH
   else if ((rhs->digits>DEC_MAX_MATH
     || rhs->exponent+rhs->digits>DEC_MAX_MATH+1
     || rhs->exponent+rhs->digits>DEC_MAX_MATH+1
     || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH))
     || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH))
     && !ISZERO(rhs)) *status|=DEC_Invalid_operation;
     && !ISZERO(rhs)) *status|=DEC_Invalid_operation;
  return (*status!=save);
  return (*status!=save);
  } /* decCheckMath */
  } /* decCheckMath */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decGetInt -- get integer from a number                             */
/* decGetInt -- get integer from a number                             */
/*                                                                    */
/*                                                                    */
/*   dn is the number [which will not be altered]                     */
/*   dn is the number [which will not be altered]                     */
/*                                                                    */
/*                                                                    */
/*   returns one of:                                                  */
/*   returns one of:                                                  */
/*     BADINT if there is a non-zero fraction                         */
/*     BADINT if there is a non-zero fraction                         */
/*     the converted integer                                          */
/*     the converted integer                                          */
/*     BIGEVEN if the integer is even and magnitude > 2*10**9         */
/*     BIGEVEN if the integer is even and magnitude > 2*10**9         */
/*     BIGODD  if the integer is odd  and magnitude > 2*10**9         */
/*     BIGODD  if the integer is odd  and magnitude > 2*10**9         */
/*                                                                    */
/*                                                                    */
/* This checks and gets a whole number from the input decNumber.      */
/* This checks and gets a whole number from the input decNumber.      */
/* The sign can be determined from dn by the caller when BIGEVEN or   */
/* The sign can be determined from dn by the caller when BIGEVEN or   */
/* BIGODD is returned.                                                */
/* BIGODD is returned.                                                */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Int decGetInt(const decNumber *dn) {
static Int decGetInt(const decNumber *dn) {
  Int  theInt;                          /* result accumulator */
  Int  theInt;                          /* result accumulator */
  const Unit *up;                       /* work */
  const Unit *up;                       /* work */
  Int  got;                             /* digits (real or not) processed */
  Int  got;                             /* digits (real or not) processed */
  Int  ilength=dn->digits+dn->exponent; /* integral length */
  Int  ilength=dn->digits+dn->exponent; /* integral length */
  Flag neg=decNumberIsNegative(dn);     /* 1 if -ve */
  Flag neg=decNumberIsNegative(dn);     /* 1 if -ve */
 
 
  /* The number must be an integer that fits in 10 digits */
  /* The number must be an integer that fits in 10 digits */
  /* Assert, here, that 10 is enough for any rescale Etiny */
  /* Assert, here, that 10 is enough for any rescale Etiny */
  #if DEC_MAX_EMAX > 999999999
  #if DEC_MAX_EMAX > 999999999
    #error GetInt may need updating [for Emax]
    #error GetInt may need updating [for Emax]
  #endif
  #endif
  #if DEC_MIN_EMIN < -999999999
  #if DEC_MIN_EMIN < -999999999
    #error GetInt may need updating [for Emin]
    #error GetInt may need updating [for Emin]
  #endif
  #endif
  if (ISZERO(dn)) return 0;              /* zeros are OK, with any exponent */
  if (ISZERO(dn)) return 0;              /* zeros are OK, with any exponent */
 
 
  up=dn->lsu;                           /* ready for lsu */
  up=dn->lsu;                           /* ready for lsu */
  theInt=0;                              /* ready to accumulate */
  theInt=0;                              /* ready to accumulate */
  if (dn->exponent>=0) {         /* relatively easy */
  if (dn->exponent>=0) {         /* relatively easy */
    /* no fractional part [usual]; allow for positive exponent */
    /* no fractional part [usual]; allow for positive exponent */
    got=dn->exponent;
    got=dn->exponent;
    }
    }
   else { /* -ve exponent; some fractional part to check and discard */
   else { /* -ve exponent; some fractional part to check and discard */
    Int count=-dn->exponent;            /* digits to discard */
    Int count=-dn->exponent;            /* digits to discard */
    /* spin up whole units until reach the Unit with the unit digit */
    /* spin up whole units until reach the Unit with the unit digit */
    for (; count>=DECDPUN; up++) {
    for (; count>=DECDPUN; up++) {
      if (*up!=0) return BADINT; /* non-zero Unit to discard */
      if (*up!=0) return BADINT; /* non-zero Unit to discard */
      count-=DECDPUN;
      count-=DECDPUN;
      }
      }
    if (count==0) got=0;          /* [a multiple of DECDPUN] */
    if (count==0) got=0;          /* [a multiple of DECDPUN] */
     else {                             /* [not multiple of DECDPUN] */
     else {                             /* [not multiple of DECDPUN] */
      Int rem;                          /* work */
      Int rem;                          /* work */
      /* slice off fraction digits and check for non-zero */
      /* slice off fraction digits and check for non-zero */
      #if DECDPUN<=4
      #if DECDPUN<=4
        theInt=QUOT10(*up, count);
        theInt=QUOT10(*up, count);
        rem=*up-theInt*powers[count];
        rem=*up-theInt*powers[count];
      #else
      #else
        rem=*up%powers[count];          /* slice off discards */
        rem=*up%powers[count];          /* slice off discards */
        theInt=*up/powers[count];
        theInt=*up/powers[count];
      #endif
      #endif
      if (rem!=0) return BADINT; /* non-zero fraction */
      if (rem!=0) return BADINT; /* non-zero fraction */
      /* it looks good */
      /* it looks good */
      got=DECDPUN-count;                /* number of digits so far */
      got=DECDPUN-count;                /* number of digits so far */
      up++;                             /* ready for next */
      up++;                             /* ready for next */
      }
      }
    }
    }
  /* now it's known there's no fractional part */
  /* now it's known there's no fractional part */
 
 
  /* tricky code now, to accumulate up to 9.3 digits */
  /* tricky code now, to accumulate up to 9.3 digits */
  if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */
  if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */
 
 
  if (ilength<11) {
  if (ilength<11) {
    Int save=theInt;
    Int save=theInt;
    /* collect any remaining unit(s) */
    /* collect any remaining unit(s) */
    for (; got<ilength; up++) {
    for (; got<ilength; up++) {
      theInt+=*up*powers[got];
      theInt+=*up*powers[got];
      got+=DECDPUN;
      got+=DECDPUN;
      }
      }
    if (ilength==10) {                  /* need to check for wrap */
    if (ilength==10) {                  /* need to check for wrap */
      if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11;
      if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11;
         /* [that test also disallows the BADINT result case] */
         /* [that test also disallows the BADINT result case] */
       else if (neg && theInt>1999999997) ilength=11;
       else if (neg && theInt>1999999997) ilength=11;
       else if (!neg && theInt>999999999) ilength=11;
       else if (!neg && theInt>999999999) ilength=11;
      if (ilength==11) theInt=save;     /* restore correct low bit */
      if (ilength==11) theInt=save;     /* restore correct low bit */
      }
      }
    }
    }
 
 
  if (ilength>10) {                     /* too big */
  if (ilength>10) {                     /* too big */
    if (theInt&1) return BIGODD;        /* bottom bit 1 */
    if (theInt&1) return BIGODD;        /* bottom bit 1 */
    return BIGEVEN;                     /* bottom bit 0 */
    return BIGEVEN;                     /* bottom bit 0 */
    }
    }
 
 
  if (neg) theInt=-theInt;              /* apply sign */
  if (neg) theInt=-theInt;              /* apply sign */
  return theInt;
  return theInt;
  } /* decGetInt */
  } /* decGetInt */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decDecap -- decapitate the coefficient of a number                 */
/* decDecap -- decapitate the coefficient of a number                 */
/*                                                                    */
/*                                                                    */
/*   dn   is the number to be decapitated                             */
/*   dn   is the number to be decapitated                             */
/*   drop is the number of digits to be removed from the left of dn;  */
/*   drop is the number of digits to be removed from the left of dn;  */
/*     this must be <= dn->digits (if equal, the coefficient is       */
/*     this must be <= dn->digits (if equal, the coefficient is       */
/*     set to 0)                                                      */
/*     set to 0)                                                      */
/*                                                                    */
/*                                                                    */
/* Returns dn; dn->digits will be <= the initial digits less drop     */
/* Returns dn; dn->digits will be <= the initial digits less drop     */
/* (after removing drop digits there may be leading zero digits       */
/* (after removing drop digits there may be leading zero digits       */
/* which will also be removed).  Only dn->lsu and dn->digits change.  */
/* which will also be removed).  Only dn->lsu and dn->digits change.  */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static decNumber *decDecap(decNumber *dn, Int drop) {
static decNumber *decDecap(decNumber *dn, Int drop) {
  Unit *msu;                            /* -> target cut point */
  Unit *msu;                            /* -> target cut point */
  Int cut;                              /* work */
  Int cut;                              /* work */
  if (drop>=dn->digits) {               /* losing the whole thing */
  if (drop>=dn->digits) {               /* losing the whole thing */
    #if DECCHECK
    #if DECCHECK
    if (drop>dn->digits)
    if (drop>dn->digits)
      printf("decDecap called with drop>digits [%ld>%ld]\n",
      printf("decDecap called with drop>digits [%ld>%ld]\n",
             (LI)drop, (LI)dn->digits);
             (LI)drop, (LI)dn->digits);
    #endif
    #endif
    dn->lsu[0]=0;
    dn->lsu[0]=0;
    dn->digits=1;
    dn->digits=1;
    return dn;
    return dn;
    }
    }
  msu=dn->lsu+D2U(dn->digits-drop)-1;   /* -> likely msu */
  msu=dn->lsu+D2U(dn->digits-drop)-1;   /* -> likely msu */
  cut=MSUDIGITS(dn->digits-drop);       /* digits to be in use in msu */
  cut=MSUDIGITS(dn->digits-drop);       /* digits to be in use in msu */
  if (cut!=DECDPUN) *msu%=powers[cut];  /* clear left digits */
  if (cut!=DECDPUN) *msu%=powers[cut];  /* clear left digits */
  /* that may have left leading zero digits, so do a proper count... */
  /* that may have left leading zero digits, so do a proper count... */
  dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1);
  dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1);
  return dn;
  return dn;
  } /* decDecap */
  } /* decDecap */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decBiStr -- compare string with pairwise options                   */
/* decBiStr -- compare string with pairwise options                   */
/*                                                                    */
/*                                                                    */
/*   targ is the string to compare                                    */
/*   targ is the string to compare                                    */
/*   str1 is one of the strings to compare against (length may be 0)  */
/*   str1 is one of the strings to compare against (length may be 0)  */
/*   str2 is the other; it must be the same length as str1            */
/*   str2 is the other; it must be the same length as str1            */
/*                                                                    */
/*                                                                    */
/*   returns 1 if strings compare equal, (that is, it is the same     */
/*   returns 1 if strings compare equal, (that is, it is the same     */
/*   length as str1 and str2, and each character of targ is in either */
/*   length as str1 and str2, and each character of targ is in either */
/*   str1 or str2 in the corresponding position), or 0 otherwise      */
/*   str1 or str2 in the corresponding position), or 0 otherwise      */
/*                                                                    */
/*                                                                    */
/* This is used for generic caseless compare, including the awkward   */
/* This is used for generic caseless compare, including the awkward   */
/* case of the Turkish dotted and dotless Is.  Use as (for example):  */
/* case of the Turkish dotted and dotless Is.  Use as (for example):  */
/*   if (decBiStr(test, "mike", "MIKE")) ...                          */
/*   if (decBiStr(test, "mike", "MIKE")) ...                          */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
  for (;;targ++, str1++, str2++) {
  for (;;targ++, str1++, str2++) {
    if (*targ!=*str1 && *targ!=*str2) return 0;
    if (*targ!=*str1 && *targ!=*str2) return 0;
    /* *targ has a match in one (or both, if terminator) */
    /* *targ has a match in one (or both, if terminator) */
    if (*targ=='\0') break;
    if (*targ=='\0') break;
    } /* forever */
    } /* forever */
  return 1;
  return 1;
  } /* decBiStr */
  } /* decBiStr */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNaNs -- handle NaN operand or operands                          */
/* decNaNs -- handle NaN operand or operands                          */
/*                                                                    */
/*                                                                    */
/*   res     is the result number                                     */
/*   res     is the result number                                     */
/*   lhs     is the first operand                                     */
/*   lhs     is the first operand                                     */
/*   rhs     is the second operand, or NULL if none                   */
/*   rhs     is the second operand, or NULL if none                   */
/*   context is used to limit payload length                          */
/*   context is used to limit payload length                          */
/*   status  contains the current status                              */
/*   status  contains the current status                              */
/*   returns res in case convenient                                   */
/*   returns res in case convenient                                   */
/*                                                                    */
/*                                                                    */
/* Called when one or both operands is a NaN, and propagates the      */
/* Called when one or both operands is a NaN, and propagates the      */
/* appropriate result to res.  When an sNaN is found, it is changed   */
/* appropriate result to res.  When an sNaN is found, it is changed   */
/* to a qNaN and Invalid operation is set.                            */
/* to a qNaN and Invalid operation is set.                            */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static decNumber * decNaNs(decNumber *res, const decNumber *lhs,
static decNumber * decNaNs(decNumber *res, const decNumber *lhs,
                           const decNumber *rhs, decContext *set,
                           const decNumber *rhs, decContext *set,
                           uInt *status) {
                           uInt *status) {
  /* This decision tree ends up with LHS being the source pointer, */
  /* This decision tree ends up with LHS being the source pointer, */
  /* and status updated if need be */
  /* and status updated if need be */
  if (lhs->bits & DECSNAN)
  if (lhs->bits & DECSNAN)
    *status|=DEC_Invalid_operation | DEC_sNaN;
    *status|=DEC_Invalid_operation | DEC_sNaN;
   else if (rhs==NULL);
   else if (rhs==NULL);
   else if (rhs->bits & DECSNAN) {
   else if (rhs->bits & DECSNAN) {
    lhs=rhs;
    lhs=rhs;
    *status|=DEC_Invalid_operation | DEC_sNaN;
    *status|=DEC_Invalid_operation | DEC_sNaN;
    }
    }
   else if (lhs->bits & DECNAN);
   else if (lhs->bits & DECNAN);
   else lhs=rhs;
   else lhs=rhs;
 
 
  /* propagate the payload */
  /* propagate the payload */
  if (lhs->digits<=set->digits) decNumberCopy(res, lhs); /* easy */
  if (lhs->digits<=set->digits) decNumberCopy(res, lhs); /* easy */
   else { /* too long */
   else { /* too long */
    const Unit *ul;
    const Unit *ul;
    Unit *ur, *uresp1;
    Unit *ur, *uresp1;
    /* copy safe number of units, then decapitate */
    /* copy safe number of units, then decapitate */
    res->bits=lhs->bits;                /* need sign etc. */
    res->bits=lhs->bits;                /* need sign etc. */
    uresp1=res->lsu+D2U(set->digits);
    uresp1=res->lsu+D2U(set->digits);
    for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul;
    for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul;
    res->digits=D2U(set->digits)*DECDPUN;
    res->digits=D2U(set->digits)*DECDPUN;
    /* maybe still too long */
    /* maybe still too long */
    if (res->digits>set->digits) decDecap(res, res->digits-set->digits);
    if (res->digits>set->digits) decDecap(res, res->digits-set->digits);
    }
    }
 
 
  res->bits&=~DECSNAN;        /* convert any sNaN to NaN, while */
  res->bits&=~DECSNAN;        /* convert any sNaN to NaN, while */
  res->bits|=DECNAN;          /* .. preserving sign */
  res->bits|=DECNAN;          /* .. preserving sign */
  res->exponent=0;             /* clean exponent */
  res->exponent=0;             /* clean exponent */
                              /* [coefficient was copied/decapitated] */
                              /* [coefficient was copied/decapitated] */
  return res;
  return res;
  } /* decNaNs */
  } /* decNaNs */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decStatus -- apply non-zero status                                 */
/* decStatus -- apply non-zero status                                 */
/*                                                                    */
/*                                                                    */
/*   dn     is the number to set if error                             */
/*   dn     is the number to set if error                             */
/*   status contains the current status (not yet in context)          */
/*   status contains the current status (not yet in context)          */
/*   set    is the context                                            */
/*   set    is the context                                            */
/*                                                                    */
/*                                                                    */
/* If the status is an error status, the number is set to a NaN,      */
/* If the status is an error status, the number is set to a NaN,      */
/* unless the error was an overflow, divide-by-zero, or underflow,    */
/* unless the error was an overflow, divide-by-zero, or underflow,    */
/* in which case the number will have already been set.               */
/* in which case the number will have already been set.               */
/*                                                                    */
/*                                                                    */
/* The context status is then updated with the new status.  Note that */
/* The context status is then updated with the new status.  Note that */
/* this may raise a signal, so control may never return from this     */
/* this may raise a signal, so control may never return from this     */
/* routine (hence resources must be recovered before it is called).   */
/* routine (hence resources must be recovered before it is called).   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decStatus(decNumber *dn, uInt status, decContext *set) {
static void decStatus(decNumber *dn, uInt status, decContext *set) {
  if (status & DEC_NaNs) {              /* error status -> NaN */
  if (status & DEC_NaNs) {              /* error status -> NaN */
    /* if cause was an sNaN, clear and propagate [NaN is already set up] */
    /* if cause was an sNaN, clear and propagate [NaN is already set up] */
    if (status & DEC_sNaN) status&=~DEC_sNaN;
    if (status & DEC_sNaN) status&=~DEC_sNaN;
     else {
     else {
      decNumberZero(dn);                /* other error: clean throughout */
      decNumberZero(dn);                /* other error: clean throughout */
      dn->bits=DECNAN;                  /* and make a quiet NaN */
      dn->bits=DECNAN;                  /* and make a quiet NaN */
      }
      }
    }
    }
  decContextSetStatus(set, status);     /* [may not return] */
  decContextSetStatus(set, status);     /* [may not return] */
  return;
  return;
  } /* decStatus */
  } /* decStatus */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decGetDigits -- count digits in a Units array                      */
/* decGetDigits -- count digits in a Units array                      */
/*                                                                    */
/*                                                                    */
/*   uar is the Unit array holding the number (this is often an       */
/*   uar is the Unit array holding the number (this is often an       */
/*          accumulator of some sort)                                 */
/*          accumulator of some sort)                                 */
/*   len is the length of the array in units [>=1]                    */
/*   len is the length of the array in units [>=1]                    */
/*                                                                    */
/*                                                                    */
/*   returns the number of (significant) digits in the array          */
/*   returns the number of (significant) digits in the array          */
/*                                                                    */
/*                                                                    */
/* All leading zeros are excluded, except the last if the array has   */
/* All leading zeros are excluded, except the last if the array has   */
/* only zero Units.                                                   */
/* only zero Units.                                                   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This may be called twice during some operations. */
/* This may be called twice during some operations. */
static Int decGetDigits(Unit *uar, Int len) {
static Int decGetDigits(Unit *uar, Int len) {
  Unit *up=uar+(len-1);            /* -> msu */
  Unit *up=uar+(len-1);            /* -> msu */
  Int  digits=(len-1)*DECDPUN+1;   /* possible digits excluding msu */
  Int  digits=(len-1)*DECDPUN+1;   /* possible digits excluding msu */
  #if DECDPUN>4
  #if DECDPUN>4
  uInt const *pow;                 /* work */
  uInt const *pow;                 /* work */
  #endif
  #endif
                                   /* (at least 1 in final msu) */
                                   /* (at least 1 in final msu) */
  #if DECCHECK
  #if DECCHECK
  if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len);
  if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len);
  #endif
  #endif
 
 
  for (; up>=uar; up--) {
  for (; up>=uar; up--) {
    if (*up==0) {                   /* unit is all 0s */
    if (*up==0) {                   /* unit is all 0s */
      if (digits==1) break;        /* a zero has one digit */
      if (digits==1) break;        /* a zero has one digit */
      digits-=DECDPUN;             /* adjust for 0 unit */
      digits-=DECDPUN;             /* adjust for 0 unit */
      continue;}
      continue;}
    /* found the first (most significant) non-zero Unit */
    /* found the first (most significant) non-zero Unit */
    #if DECDPUN>1                  /* not done yet */
    #if DECDPUN>1                  /* not done yet */
    if (*up<10) break;             /* is 1-9 */
    if (*up<10) break;             /* is 1-9 */
    digits++;
    digits++;
    #if DECDPUN>2                  /* not done yet */
    #if DECDPUN>2                  /* not done yet */
    if (*up<100) break;            /* is 10-99 */
    if (*up<100) break;            /* is 10-99 */
    digits++;
    digits++;
    #if DECDPUN>3                  /* not done yet */
    #if DECDPUN>3                  /* not done yet */
    if (*up<1000) break;           /* is 100-999 */
    if (*up<1000) break;           /* is 100-999 */
    digits++;
    digits++;
    #if DECDPUN>4                  /* count the rest ... */
    #if DECDPUN>4                  /* count the rest ... */
    for (pow=&powers[4]; *up>=*pow; pow++) digits++;
    for (pow=&powers[4]; *up>=*pow; pow++) digits++;
    #endif
    #endif
    #endif
    #endif
    #endif
    #endif
    #endif
    #endif
    break;
    break;
    } /* up */
    } /* up */
  return digits;
  return digits;
  } /* decGetDigits */
  } /* decGetDigits */
 
 
#if DECTRACE | DECCHECK
#if DECTRACE | DECCHECK
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decNumberShow -- display a number [debug aid]                      */
/* decNumberShow -- display a number [debug aid]                      */
/*   dn is the number to show                                         */
/*   dn is the number to show                                         */
/*                                                                    */
/*                                                                    */
/* Shows: sign, exponent, coefficient (msu first), digits             */
/* Shows: sign, exponent, coefficient (msu first), digits             */
/*    or: sign, special-value                                         */
/*    or: sign, special-value                                         */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* this is public so other modules can use it */
/* this is public so other modules can use it */
void decNumberShow(const decNumber *dn) {
void decNumberShow(const decNumber *dn) {
  const Unit *up;                  /* work */
  const Unit *up;                  /* work */
  uInt u, d;                       /* .. */
  uInt u, d;                       /* .. */
  Int cut;                         /* .. */
  Int cut;                         /* .. */
  char isign='+';                  /* main sign */
  char isign='+';                  /* main sign */
  if (dn==NULL) {
  if (dn==NULL) {
    printf("NULL\n");
    printf("NULL\n");
    return;}
    return;}
  if (decNumberIsNegative(dn)) isign='-';
  if (decNumberIsNegative(dn)) isign='-';
  printf(" >> %c ", isign);
  printf(" >> %c ", isign);
  if (dn->bits&DECSPECIAL) {       /* Is a special value */
  if (dn->bits&DECSPECIAL) {       /* Is a special value */
    if (decNumberIsInfinite(dn)) printf("Infinity");
    if (decNumberIsInfinite(dn)) printf("Infinity");
     else {                                  /* a NaN */
     else {                                  /* a NaN */
      if (dn->bits&DECSNAN) printf("sNaN");  /* signalling NaN */
      if (dn->bits&DECSNAN) printf("sNaN");  /* signalling NaN */
       else printf("NaN");
       else printf("NaN");
      }
      }
    /* if coefficient and exponent are 0, no more to do */
    /* if coefficient and exponent are 0, no more to do */
    if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) {
    if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) {
      printf("\n");
      printf("\n");
      return;}
      return;}
    /* drop through to report other information */
    /* drop through to report other information */
    printf(" ");
    printf(" ");
    }
    }
 
 
  /* now carefully display the coefficient */
  /* now carefully display the coefficient */
  up=dn->lsu+D2U(dn->digits)-1;         /* msu */
  up=dn->lsu+D2U(dn->digits)-1;         /* msu */
  printf("%ld", (LI)*up);
  printf("%ld", (LI)*up);
  for (up=up-1; up>=dn->lsu; up--) {
  for (up=up-1; up>=dn->lsu; up--) {
    u=*up;
    u=*up;
    printf(":");
    printf(":");
    for (cut=DECDPUN-1; cut>=0; cut--) {
    for (cut=DECDPUN-1; cut>=0; cut--) {
      d=u/powers[cut];
      d=u/powers[cut];
      u-=d*powers[cut];
      u-=d*powers[cut];
      printf("%ld", (LI)d);
      printf("%ld", (LI)d);
      } /* cut */
      } /* cut */
    } /* up */
    } /* up */
  if (dn->exponent!=0) {
  if (dn->exponent!=0) {
    char esign='+';
    char esign='+';
    if (dn->exponent<0) esign='-';
    if (dn->exponent<0) esign='-';
    printf(" E%c%ld", esign, (LI)abs(dn->exponent));
    printf(" E%c%ld", esign, (LI)abs(dn->exponent));
    }
    }
  printf(" [%ld]\n", (LI)dn->digits);
  printf(" [%ld]\n", (LI)dn->digits);
  } /* decNumberShow */
  } /* decNumberShow */
#endif
#endif
 
 
#if DECTRACE || DECCHECK
#if DECTRACE || DECCHECK
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decDumpAr -- display a unit array [debug/check aid]                */
/* decDumpAr -- display a unit array [debug/check aid]                */
/*   name is a single-character tag name                              */
/*   name is a single-character tag name                              */
/*   ar   is the array to display                                     */
/*   ar   is the array to display                                     */
/*   len  is the length of the array in Units                         */
/*   len  is the length of the array in Units                         */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decDumpAr(char name, const Unit *ar, Int len) {
static void decDumpAr(char name, const Unit *ar, Int len) {
  Int i;
  Int i;
  const char *spec;
  const char *spec;
  #if DECDPUN==9
  #if DECDPUN==9
    spec="%09d ";
    spec="%09d ";
  #elif DECDPUN==8
  #elif DECDPUN==8
    spec="%08d ";
    spec="%08d ";
  #elif DECDPUN==7
  #elif DECDPUN==7
    spec="%07d ";
    spec="%07d ";
  #elif DECDPUN==6
  #elif DECDPUN==6
    spec="%06d ";
    spec="%06d ";
  #elif DECDPUN==5
  #elif DECDPUN==5
    spec="%05d ";
    spec="%05d ";
  #elif DECDPUN==4
  #elif DECDPUN==4
    spec="%04d ";
    spec="%04d ";
  #elif DECDPUN==3
  #elif DECDPUN==3
    spec="%03d ";
    spec="%03d ";
  #elif DECDPUN==2
  #elif DECDPUN==2
    spec="%02d ";
    spec="%02d ";
  #else
  #else
    spec="%d ";
    spec="%d ";
  #endif
  #endif
  printf("  :%c: ", name);
  printf("  :%c: ", name);
  for (i=len-1; i>=0; i--) {
  for (i=len-1; i>=0; i--) {
    if (i==len-1) printf("%ld ", (LI)ar[i]);
    if (i==len-1) printf("%ld ", (LI)ar[i]);
     else printf(spec, ar[i]);
     else printf(spec, ar[i]);
    }
    }
  printf("\n");
  printf("\n");
  return;}
  return;}
#endif
#endif
 
 
#if DECCHECK
#if DECCHECK
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decCheckOperands -- check operand(s) to a routine                  */
/* decCheckOperands -- check operand(s) to a routine                  */
/*   res is the result structure (not checked; it will be set to      */
/*   res is the result structure (not checked; it will be set to      */
/*          quiet NaN if error found (and it is not NULL))            */
/*          quiet NaN if error found (and it is not NULL))            */
/*   lhs is the first operand (may be DECUNRESU)                      */
/*   lhs is the first operand (may be DECUNRESU)                      */
/*   rhs is the second (may be DECUNUSED)                             */
/*   rhs is the second (may be DECUNUSED)                             */
/*   set is the context (may be DECUNCONT)                            */
/*   set is the context (may be DECUNCONT)                            */
/*   returns 0 if both operands, and the context are clean, or 1      */
/*   returns 0 if both operands, and the context are clean, or 1      */
/*     otherwise (in which case the context will show an error,       */
/*     otherwise (in which case the context will show an error,       */
/*     unless NULL).  Note that res is not cleaned; caller should     */
/*     unless NULL).  Note that res is not cleaned; caller should     */
/*     handle this so res=NULL case is safe.                          */
/*     handle this so res=NULL case is safe.                          */
/* The caller is expected to abandon immediately if 1 is returned.    */
/* The caller is expected to abandon immediately if 1 is returned.    */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Flag decCheckOperands(decNumber *res, const decNumber *lhs,
static Flag decCheckOperands(decNumber *res, const decNumber *lhs,
                             const decNumber *rhs, decContext *set) {
                             const decNumber *rhs, decContext *set) {
  Flag bad=0;
  Flag bad=0;
  if (set==NULL) {                 /* oops; hopeless */
  if (set==NULL) {                 /* oops; hopeless */
    #if DECTRACE || DECVERB
    #if DECTRACE || DECVERB
    printf("Reference to context is NULL.\n");
    printf("Reference to context is NULL.\n");
    #endif
    #endif
    bad=1;
    bad=1;
    return 1;}
    return 1;}
   else if (set!=DECUNCONT
   else if (set!=DECUNCONT
     && (set->digits<1 || set->round>=DEC_ROUND_MAX)) {
     && (set->digits<1 || set->round>=DEC_ROUND_MAX)) {
    bad=1;
    bad=1;
    #if DECTRACE || DECVERB
    #if DECTRACE || DECVERB
    printf("Bad context [digits=%ld round=%ld].\n",
    printf("Bad context [digits=%ld round=%ld].\n",
           (LI)set->digits, (LI)set->round);
           (LI)set->digits, (LI)set->round);
    #endif
    #endif
    }
    }
   else {
   else {
    if (res==NULL) {
    if (res==NULL) {
      bad=1;
      bad=1;
      #if DECTRACE
      #if DECTRACE
      /* this one not DECVERB as standard tests include NULL */
      /* this one not DECVERB as standard tests include NULL */
      printf("Reference to result is NULL.\n");
      printf("Reference to result is NULL.\n");
      #endif
      #endif
      }
      }
    if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs));
    if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs));
    if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs));
    if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs));
    }
    }
  if (bad) {
  if (bad) {
    if (set!=DECUNCONT) decContextSetStatus(set, DEC_Invalid_operation);
    if (set!=DECUNCONT) decContextSetStatus(set, DEC_Invalid_operation);
    if (res!=DECUNRESU && res!=NULL) {
    if (res!=DECUNRESU && res!=NULL) {
      decNumberZero(res);
      decNumberZero(res);
      res->bits=DECNAN;       /* qNaN */
      res->bits=DECNAN;       /* qNaN */
      }
      }
    }
    }
  return bad;
  return bad;
  } /* decCheckOperands */
  } /* decCheckOperands */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decCheckNumber -- check a number                                   */
/* decCheckNumber -- check a number                                   */
/*   dn is the number to check                                        */
/*   dn is the number to check                                        */
/*   returns 0 if the number is clean, or 1 otherwise                 */
/*   returns 0 if the number is clean, or 1 otherwise                 */
/*                                                                    */
/*                                                                    */
/* The number is considered valid if it could be a result from some   */
/* The number is considered valid if it could be a result from some   */
/* operation in some valid context.                                   */
/* operation in some valid context.                                   */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static Flag decCheckNumber(const decNumber *dn) {
static Flag decCheckNumber(const decNumber *dn) {
  const Unit *up;             /* work */
  const Unit *up;             /* work */
  uInt maxuint;               /* .. */
  uInt maxuint;               /* .. */
  Int ae, d, digits;          /* .. */
  Int ae, d, digits;          /* .. */
  Int emin, emax;             /* .. */
  Int emin, emax;             /* .. */
 
 
  if (dn==NULL) {             /* hopeless */
  if (dn==NULL) {             /* hopeless */
    #if DECTRACE
    #if DECTRACE
    /* this one not DECVERB as standard tests include NULL */
    /* this one not DECVERB as standard tests include NULL */
    printf("Reference to decNumber is NULL.\n");
    printf("Reference to decNumber is NULL.\n");
    #endif
    #endif
    return 1;}
    return 1;}
 
 
  /* check special values */
  /* check special values */
  if (dn->bits & DECSPECIAL) {
  if (dn->bits & DECSPECIAL) {
    if (dn->exponent!=0) {
    if (dn->exponent!=0) {
      #if DECTRACE || DECVERB
      #if DECTRACE || DECVERB
      printf("Exponent %ld (not 0) for a special value [%02x].\n",
      printf("Exponent %ld (not 0) for a special value [%02x].\n",
             (LI)dn->exponent, dn->bits);
             (LI)dn->exponent, dn->bits);
      #endif
      #endif
      return 1;}
      return 1;}
 
 
    /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */
    /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */
    if (decNumberIsInfinite(dn)) {
    if (decNumberIsInfinite(dn)) {
      if (dn->digits!=1) {
      if (dn->digits!=1) {
        #if DECTRACE || DECVERB
        #if DECTRACE || DECVERB
        printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits);
        printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits);
        #endif
        #endif
        return 1;}
        return 1;}
      if (*dn->lsu!=0) {
      if (*dn->lsu!=0) {
        #if DECTRACE || DECVERB
        #if DECTRACE || DECVERB
        printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu);
        printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu);
        #endif
        #endif
        decDumpAr('I', dn->lsu, D2U(dn->digits));
        decDumpAr('I', dn->lsu, D2U(dn->digits));
        return 1;}
        return 1;}
      } /* Inf */
      } /* Inf */
    /* 2002.12.26: negative NaNs can now appear through proposed IEEE */
    /* 2002.12.26: negative NaNs can now appear through proposed IEEE */
    /*             concrete formats (decimal64, etc.). */
    /*             concrete formats (decimal64, etc.). */
    return 0;
    return 0;
    }
    }
 
 
  /* check the coefficient */
  /* check the coefficient */
  if (dn->digits<1 || dn->digits>DECNUMMAXP) {
  if (dn->digits<1 || dn->digits>DECNUMMAXP) {
    #if DECTRACE || DECVERB
    #if DECTRACE || DECVERB
    printf("Digits %ld in number.\n", (LI)dn->digits);
    printf("Digits %ld in number.\n", (LI)dn->digits);
    #endif
    #endif
    return 1;}
    return 1;}
 
 
  d=dn->digits;
  d=dn->digits;
 
 
  for (up=dn->lsu; d>0; up++) {
  for (up=dn->lsu; d>0; up++) {
    if (d>DECDPUN) maxuint=DECDPUNMAX;
    if (d>DECDPUN) maxuint=DECDPUNMAX;
     else {                   /* reached the msu */
     else {                   /* reached the msu */
      maxuint=powers[d]-1;
      maxuint=powers[d]-1;
      if (dn->digits>1 && *up<powers[d-1]) {
      if (dn->digits>1 && *up<powers[d-1]) {
        #if DECTRACE || DECVERB
        #if DECTRACE || DECVERB
        printf("Leading 0 in number.\n");
        printf("Leading 0 in number.\n");
        decNumberShow(dn);
        decNumberShow(dn);
        #endif
        #endif
        return 1;}
        return 1;}
      }
      }
    if (*up>maxuint) {
    if (*up>maxuint) {
      #if DECTRACE || DECVERB
      #if DECTRACE || DECVERB
      printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n",
      printf("Bad Unit [%08lx] in %ld-digit number at offset %ld [maxuint %ld].\n",
              (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint);
              (LI)*up, (LI)dn->digits, (LI)(up-dn->lsu), (LI)maxuint);
      #endif
      #endif
      return 1;}
      return 1;}
    d-=DECDPUN;
    d-=DECDPUN;
    }
    }
 
 
  /* check the exponent.  Note that input operands can have exponents */
  /* check the exponent.  Note that input operands can have exponents */
  /* which are out of the set->emin/set->emax and set->digits range */
  /* which are out of the set->emin/set->emax and set->digits range */
  /* (just as they can have more digits than set->digits). */
  /* (just as they can have more digits than set->digits). */
  ae=dn->exponent+dn->digits-1;    /* adjusted exponent */
  ae=dn->exponent+dn->digits-1;    /* adjusted exponent */
  emax=DECNUMMAXE;
  emax=DECNUMMAXE;
  emin=DECNUMMINE;
  emin=DECNUMMINE;
  digits=DECNUMMAXP;
  digits=DECNUMMAXP;
  if (ae<emin-(digits-1)) {
  if (ae<emin-(digits-1)) {
    #if DECTRACE || DECVERB
    #if DECTRACE || DECVERB
    printf("Adjusted exponent underflow [%ld].\n", (LI)ae);
    printf("Adjusted exponent underflow [%ld].\n", (LI)ae);
    decNumberShow(dn);
    decNumberShow(dn);
    #endif
    #endif
    return 1;}
    return 1;}
  if (ae>+emax) {
  if (ae>+emax) {
    #if DECTRACE || DECVERB
    #if DECTRACE || DECVERB
    printf("Adjusted exponent overflow [%ld].\n", (LI)ae);
    printf("Adjusted exponent overflow [%ld].\n", (LI)ae);
    decNumberShow(dn);
    decNumberShow(dn);
    #endif
    #endif
    return 1;}
    return 1;}
 
 
  return 0;               /* it's OK */
  return 0;               /* it's OK */
  } /* decCheckNumber */
  } /* decCheckNumber */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decCheckInexact -- check a normal finite inexact result has digits */
/* decCheckInexact -- check a normal finite inexact result has digits */
/*   dn is the number to check                                        */
/*   dn is the number to check                                        */
/*   set is the context (for status and precision)                    */
/*   set is the context (for status and precision)                    */
/*   sets Invalid operation, etc., if some digits are missing         */
/*   sets Invalid operation, etc., if some digits are missing         */
/* [this check is not made for DECSUBSET compilation or when          */
/* [this check is not made for DECSUBSET compilation or when          */
/* subnormal is not set]                                              */
/* subnormal is not set]                                              */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decCheckInexact(const decNumber *dn, decContext *set) {
static void decCheckInexact(const decNumber *dn, decContext *set) {
  #if !DECSUBSET && DECEXTFLAG
  #if !DECSUBSET && DECEXTFLAG
    if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact
    if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact
     && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) {
     && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) {
      #if DECTRACE || DECVERB
      #if DECTRACE || DECVERB
      printf("Insufficient digits [%ld] on normal Inexact result.\n",
      printf("Insufficient digits [%ld] on normal Inexact result.\n",
             (LI)dn->digits);
             (LI)dn->digits);
      decNumberShow(dn);
      decNumberShow(dn);
      #endif
      #endif
      decContextSetStatus(set, DEC_Invalid_operation);
      decContextSetStatus(set, DEC_Invalid_operation);
      }
      }
  #else
  #else
    /* next is a noop for quiet compiler */
    /* next is a noop for quiet compiler */
    if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation;
    if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation;
  #endif
  #endif
  return;
  return;
  } /* decCheckInexact */
  } /* decCheckInexact */
#endif
#endif
 
 
#if DECALLOC
#if DECALLOC
#undef malloc
#undef malloc
#undef free
#undef free
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decMalloc -- accountable allocation routine                        */
/* decMalloc -- accountable allocation routine                        */
/*   n is the number of bytes to allocate                             */
/*   n is the number of bytes to allocate                             */
/*                                                                    */
/*                                                                    */
/* Semantics is the same as the stdlib malloc routine, but bytes      */
/* Semantics is the same as the stdlib malloc routine, but bytes      */
/* allocated are accounted for globally, and corruption fences are    */
/* allocated are accounted for globally, and corruption fences are    */
/* added before and after the 'actual' storage.                       */
/* added before and after the 'actual' storage.                       */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This routine allocates storage with an extra twelve bytes; 8 are   */
/* This routine allocates storage with an extra twelve bytes; 8 are   */
/* at the start and hold:                                             */
/* at the start and hold:                                             */
/*   0-3 the original length requested                                */
/*   0-3 the original length requested                                */
/*   4-7 buffer corruption detection fence (DECFENCE, x4)             */
/*   4-7 buffer corruption detection fence (DECFENCE, x4)             */
/* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */
/* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void *decMalloc(size_t n) {
static void *decMalloc(size_t n) {
  uInt  size=n+12;                 /* true size */
  uInt  size=n+12;                 /* true size */
  void  *alloc;                    /* -> allocated storage */
  void  *alloc;                    /* -> allocated storage */
  uInt  *j;                        /* work */
  uInt  *j;                        /* work */
  uByte *b, *b0;                   /* .. */
  uByte *b, *b0;                   /* .. */
 
 
  alloc=malloc(size);              /* -> allocated storage */
  alloc=malloc(size);              /* -> allocated storage */
  if (alloc==NULL) return NULL;    /* out of strorage */
  if (alloc==NULL) return NULL;    /* out of strorage */
  b0=(uByte *)alloc;               /* as bytes */
  b0=(uByte *)alloc;               /* as bytes */
  decAllocBytes+=n;                /* account for storage */
  decAllocBytes+=n;                /* account for storage */
  j=(uInt *)alloc;                 /* -> first four bytes */
  j=(uInt *)alloc;                 /* -> first four bytes */
  *j=n;                            /* save n */
  *j=n;                            /* save n */
  /* printf(" alloc ++ dAB: %ld (%d)\n", decAllocBytes, n); */
  /* printf(" alloc ++ dAB: %ld (%d)\n", decAllocBytes, n); */
  for (b=b0+4; b<b0+8; b++) *b=DECFENCE;
  for (b=b0+4; b<b0+8; b++) *b=DECFENCE;
  for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE;
  for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE;
  return b0+8;                     /* -> play area */
  return b0+8;                     /* -> play area */
  } /* decMalloc */
  } /* decMalloc */
 
 
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* decFree -- accountable free routine                                */
/* decFree -- accountable free routine                                */
/*   alloc is the storage to free                                     */
/*   alloc is the storage to free                                     */
/*                                                                    */
/*                                                                    */
/* Semantics is the same as the stdlib malloc routine, except that    */
/* Semantics is the same as the stdlib malloc routine, except that    */
/* the global storage accounting is updated and the fences are        */
/* the global storage accounting is updated and the fences are        */
/* checked to ensure that no routine has written 'out of bounds'.     */
/* checked to ensure that no routine has written 'out of bounds'.     */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
/* This routine first checks that the fences have not been corrupted. */
/* This routine first checks that the fences have not been corrupted. */
/* It then frees the storage using the 'truw' storage address (that   */
/* It then frees the storage using the 'truw' storage address (that   */
/* is, offset by 8).                                                  */
/* is, offset by 8).                                                  */
/* ------------------------------------------------------------------ */
/* ------------------------------------------------------------------ */
static void decFree(void *alloc) {
static void decFree(void *alloc) {
  uInt  *j, n;                     /* pointer, original length */
  uInt  *j, n;                     /* pointer, original length */
  uByte *b, *b0;                   /* work */
  uByte *b, *b0;                   /* work */
 
 
  if (alloc==NULL) return;         /* allowed; it's a nop */
  if (alloc==NULL) return;         /* allowed; it's a nop */
  b0=(uByte *)alloc;               /* as bytes */
  b0=(uByte *)alloc;               /* as bytes */
  b0-=8;                           /* -> true start of storage */
  b0-=8;                           /* -> true start of storage */
  j=(uInt *)b0;                    /* -> first four bytes */
  j=(uInt *)b0;                    /* -> first four bytes */
  n=*j;                            /* lift */
  n=*j;                            /* lift */
  for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE)
  for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE)
    printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b,
    printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b,
           b-b0-8, (Int)b0);
           b-b0-8, (Int)b0);
  for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE)
  for (b=b0+n+8; b<b0+n+12; b++) if (*b!=DECFENCE)
    printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b,
    printf("=== Corrupt byte [%02x] at offset +%d from %ld, n=%ld ===\n", *b,
           b-b0-8, (Int)b0, n);
           b-b0-8, (Int)b0, n);
  free(b0);                        /* drop the storage */
  free(b0);                        /* drop the storage */
  decAllocBytes-=n;                /* account for storage */
  decAllocBytes-=n;                /* account for storage */
  /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */
  /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */
  } /* decFree */
  } /* decFree */
#define malloc(a) decMalloc(a)
#define malloc(a) decMalloc(a)
#define free(a) decFree(a)
#define free(a) decFree(a)
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.