Makefile.in (libdecnumber_a_OBJS): Remove decUtility.o
authorJanis Johnson <janis187@us.ibm.com>
Mon, 10 Sep 2007 20:44:08 +0000 (20:44 +0000)
committerJanis Johnson <janis@gcc.gnu.org>
Mon, 10 Sep 2007 20:44:08 +0000 (20:44 +0000)
2007-09-10  Janis Johnson  <janis187@us.ibm.com>
    Ben Elliston  <bje@au.ibm.com>

libdecnumber/
* Makefile.in (libdecnumber_a_OBJS): Remove decUtility.o
(dependencies): Add Symbols headers.
* decContext.c: Upgrade to decNumber 3.53.
* decContext.h: Ditto.
* decDPD.h: Ditto.
* decNumber.c: Ditto.
* decNumber.h: Ditto.
* decNumberLocal.h: Ditto.
* decBasic.c: New file from decNumber 3.53.
* decCommon.c: Ditto.
* decDouble.c: Ditto.
* decDouble.h: Ditto.
* decQuad.c: Ditto.
* decQuad.h: Ditto.
* decSingle.c: Ditto.
* decSingle.h: Ditto.
* decPacked.c: Ditto.
* decPacked.h: Ditto.
* dpd/decimal128.c: Upgrade to decNumber 3.53.
* dpd/decimal128.h: Ditto.
* dpd/decimal32.c: Ditto.
* dpd/decimal32.h: Ditto.
* dpd/decimal64.c: Ditto.
* dpd/decimal64.h: Ditto.
* decLibrary.c (__dec_byte_swap): Remove.
* decContextSymbols.h: New file.
* decDoubleSymbols.h: New file.
* decNumberSymbols.h: New file.
* decPackedSymbols.h: New file.
* decQuadSymbols.h: New file.
* decSingleSymbols.h: New file.
* decUtility.c: Delete file.
* decUtility.h: Delete file.
* bid/decimal128Symbols.h: New file.
* bid/decimal128Local.h: New file.
* bid/decimal32Symbols.h: New file.
* bid/decimal64Symbols.h: New file.
* bid/host-ieee128.c (__swap128): Remove.
(__host_to_ieee_128, __ieee_to_host_128): Don't handle endianness.
* bid/host-ieee32.c (__dec_type_swap): Remove.
(__host_to_ieee_32, __ieee_to_host_32): Don't handle endianness.
* bid/host-ieee64.c (__swap64): Remove.
(__host_to_ieee_64, __ieee_to_host_64): Don't handle endianness.
* dpd/decimal32Symbols.h: New file.
* dpd/decimal64Symbols.h: New file.
* dpd/decimal128Symbols.h: New file.
* dpd/decimal128Local.h: New file.

libgcc/
* Makefile.in (dfp-filenames): Remove decUtility, add
decDouble, decPacked, decQuad, decSingle.

gcc/
* dfp.c: Include decimal128Local.h;
(dfp_byte_swap): Remove.
(encode_decimal32, decode_decimal32): Don't handle endianness.
(encode_decimal64, decode_decimal64): Ditto.
(encode_decimal128, decode_decimal128): Ditto.
* config/dfp-bit.c (host_to_ieee32, ieee_to_host_32): Ditto.
(__swap64): Remove.
(host_to_ieee_64, ieee_to_host_64): Don't handle endianness.
         (__swap128): Remove
(host_to_ieee_128, ieee_to_host_128): Don't handle endianness.
* Makefile.in (DECNUM_H): Add decimal128Local.h.

Co-Authored-By: Ben Elliston <bje@au.ibm.com>
From-SVN: r128350

50 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/config/dfp-bit.c
gcc/dfp.c
libdecnumber/ChangeLog
libdecnumber/Makefile.in
libdecnumber/bid/decimal128Local.h [new file with mode: 0644]
libdecnumber/bid/decimal128Symbols.h [new file with mode: 0644]
libdecnumber/bid/decimal32Symbols.h [new file with mode: 0644]
libdecnumber/bid/decimal64Symbols.h [new file with mode: 0644]
libdecnumber/bid/host-ieee128.c
libdecnumber/bid/host-ieee32.c
libdecnumber/bid/host-ieee64.c
libdecnumber/decBasic.c [new file with mode: 0644]
libdecnumber/decCommon.c [new file with mode: 0644]
libdecnumber/decContext.c
libdecnumber/decContext.h
libdecnumber/decContextSymbols.h [new file with mode: 0644]
libdecnumber/decDPD.h
libdecnumber/decDouble.c [new file with mode: 0644]
libdecnumber/decDouble.h [new file with mode: 0644]
libdecnumber/decDoubleSymbols.h [new file with mode: 0644]
libdecnumber/decLibrary.c
libdecnumber/decNumber.c
libdecnumber/decNumber.h
libdecnumber/decNumberLocal.h
libdecnumber/decNumberSymbols.h [new file with mode: 0644]
libdecnumber/decPacked.c [new file with mode: 0644]
libdecnumber/decPacked.h [new file with mode: 0644]
libdecnumber/decPackedSymbols.h [new file with mode: 0644]
libdecnumber/decQuad.c [new file with mode: 0644]
libdecnumber/decQuad.h [new file with mode: 0644]
libdecnumber/decQuadSymbols.h [new file with mode: 0644]
libdecnumber/decSingle.c [new file with mode: 0644]
libdecnumber/decSingle.h [new file with mode: 0644]
libdecnumber/decSingleSymbols.h [new file with mode: 0644]
libdecnumber/decUtility.c [deleted file]
libdecnumber/decUtility.h [deleted file]
libdecnumber/dpd/decimal128.c
libdecnumber/dpd/decimal128.h
libdecnumber/dpd/decimal128Local.h [new file with mode: 0644]
libdecnumber/dpd/decimal128Symbols.h [new file with mode: 0644]
libdecnumber/dpd/decimal32.c
libdecnumber/dpd/decimal32.h
libdecnumber/dpd/decimal32Symbols.h [new file with mode: 0644]
libdecnumber/dpd/decimal64.c
libdecnumber/dpd/decimal64.h
libdecnumber/dpd/decimal64Symbols.h [new file with mode: 0644]
libgcc/ChangeLog
libgcc/Makefile.in

index 9360ae05cf121be257962958d017a6be6303dbd0..9bcfca14751ab7038dc004857d82b6fccf817748 100644 (file)
@@ -1,3 +1,18 @@
+2007-09-10  Janis Johnson  <janis187@us.ibm.com>
+           Ben Elliston  <bje@au.ibm.com>
+
+       * dfp.c: Include decimal128Local.h; 
+       (dfp_byte_swap): Remove.
+       (encode_decimal32, decode_decimal32): Don't handle endianness.
+       (encode_decimal64, decode_decimal64): Ditto.
+       (encode_decimal128, decode_decimal128): Ditto.
+       * config/dfp-bit.c (host_to_ieee32, ieee_to_host_32): Ditto.
+       (__swap64): Remove.
+       (host_to_ieee_64, ieee_to_host_64): Don't handle endianness.
+         (__swap128): Remove
+       (host_to_ieee_128, ieee_to_host_128): Don't handle endianness.
+       * Makefile.in (DECNUM_H): Add decimal128Local.h.
+
 2007-09-10  David Daney  <ddaney@avtrex.com>
 
        * config/mips/mips.md (UNSPEC_MEMORY_BARRIER): New entry in
index 273dda52cc59622d18d9bcbae3d5791dc33f9c9a..ef7a949f121c28d109b7614e8c4cac98a0f35ae1 100644 (file)
@@ -815,7 +815,8 @@ PREDICT_H = predict.h predict.def
 CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
        $(srcdir)/../libcpp/include/cpplib.h
 DECNUM_H = $(DECNUM)/decContext.h $(DECNUM)/decDPD.h $(DECNUM)/decNumber.h \
-       $(DECNUMFMT)/decimal32.h $(DECNUMFMT)/decimal64.h $(DECNUMFMT)/decimal128.h
+       $(DECNUMFMT)/decimal32.h $(DECNUMFMT)/decimal64.h \
+       $(DECNUMFMT)/decimal128.h $(DECNUMFMT)/decimal128Local.h
 MKDEPS_H = $(srcdir)/../libcpp/include/mkdeps.h
 SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h
 CPP_ID_DATA_H = $(CPPLIB_H) $(srcdir)/../libcpp/include/cpp-id-data.h
index 325306a5460d88626bd066bf69884d8d552c7915..252abe0224c1ced5ff4fbb3b895e139c5b41b76e 100644 (file)
@@ -70,8 +70,6 @@ typedef decNumber* (*dfp_unary_func)
 /* A pointer to a binary decNumber operation.  */
 typedef decNumber* (*dfp_binary_func)
      (decNumber *, const decNumber *, const decNumber *, decContext *);
-
-extern uint32_t __dec_byte_swap (uint32_t);
 \f
 /* Unary operations.  */
 
@@ -190,101 +188,41 @@ dfp_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
 void
 __host_to_ieee_32 (_Decimal32 in, decimal32 *out)
 {
-  uint32_t t;
-
-  if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
-    {
-      memcpy (&t, &in, 4);
-      t = __dec_byte_swap (t);
-      memcpy (out, &t, 4);
-    }
-  else
-    memcpy (out, &in, 4);
+  memcpy (out, &in, 4);
 }
 
 void
 __ieee_to_host_32 (decimal32 in, _Decimal32 *out)
 {
-  uint32_t t;
-
-  if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
-    {
-      memcpy (&t, &in, 4);
-      t = __dec_byte_swap (t);
-      memcpy (out, &t, 4);
-    }
-  else
-    memcpy (out, &in, 4);
+  memcpy (out, &in, 4);
 }
 #endif /* L_conv_sd */
 
 #if defined(L_conv_dd)
-static void
-__swap64 (char *src, char *dst)
-{
-  uint32_t t1, t2;
-
-  if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN) 
-    {
-      memcpy (&t1, src, 4);
-      memcpy (&t2, src + 4, 4);
-      t1 = __dec_byte_swap (t1);
-      t2 = __dec_byte_swap (t2);
-      memcpy (dst, &t2, 4);
-      memcpy (dst + 4, &t1, 4);
-    }
-  else
-    memcpy (dst, src, 8);
-}
-
 void
 __host_to_ieee_64 (_Decimal64 in, decimal64 *out)
 {
-  __swap64 ((char *) &in, (char *) out);
+  memcpy (out, &in, 8);
 }
 
 void
 __ieee_to_host_64 (decimal64 in, _Decimal64 *out)
 {
-  __swap64 ((char *) &in, (char *) out);
+  memcpy (out, &in, 8);
 }
 #endif /* L_conv_dd */
 
 #if defined(L_conv_td)
-static void
-__swap128 (char *src, char *dst)
-{
-  uint32_t t1, t2, t3, t4;
-
-  if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
-    {
-      memcpy (&t1, src, 4);
-      memcpy (&t2, src + 4, 4);
-      memcpy (&t3, src + 8, 4);
-      memcpy (&t4, src + 12, 4);
-      t1 = __dec_byte_swap (t1);
-      t2 = __dec_byte_swap (t2);
-      t3 = __dec_byte_swap (t3);
-      t4 = __dec_byte_swap (t4);
-      memcpy (dst, &t4, 4);
-      memcpy (dst + 4, &t3, 4);
-      memcpy (dst + 8, &t2, 4);
-      memcpy (dst + 12, &t1, 4);
-    }
-  else
-    memcpy (dst, src, 16);
-}
-
 void
 __host_to_ieee_128 (_Decimal128 in, decimal128 *out)
 {
-  __swap128 ((char *) &in, (char *) out);
+  memcpy (out, &in, 16);
 }
 
 void
 __ieee_to_host_128 (decimal128 in, _Decimal128 *out)
 {
-  __swap128 ((char *) &in, (char *) out);
+  memcpy (out, &in, 16);
 }
 #endif /* L_conv_td */
 
index 23285892d9bc4eb919edd94595d07ba62ef8976f..88ffdedbcfb41baf5272a9a3616801e495ff070f 100644 (file)
--- a/gcc/dfp.c
+++ b/gcc/dfp.c
@@ -31,29 +31,11 @@ along with GCC; see the file COPYING3.  If not see
    decNumber structure is large enough to hold decimal128 digits.  */
 
 #include "decimal128.h"
+#include "decimal128Local.h"
 #include "decimal64.h"
 #include "decimal32.h"
 #include "decNumber.h"
 
-static uint32_t
-dfp_byte_swap (uint32_t in)
-{
-  uint32_t out = 0;
-  unsigned char *p = (unsigned char *) &out;
-  union {
-    uint32_t i;
-    unsigned char b[4];
-  } u;
-
-  u.i = in;
-  p[0] = u.b[3];
-  p[1] = u.b[2];
-  p[2] = u.b[1];
-  p[3] = u.b[0];
-
-  return out;
-}
-
 /* Initialize R (a real with the decimal flag set) from DN.  Can
    utilize status passed in via CONTEXT, if a previous operation had
    interesting status.  */
@@ -155,10 +137,7 @@ encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decimal_to_decnumber (r, &dn); 
   decimal32FromNumber (&d32, &dn, &set);
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    buf[0] = *(uint32_t *) d32.bytes;
-  else
-    buf[0] = dfp_byte_swap (*(uint32_t *) d32.bytes);
+  buf[0] = *(uint32_t *) d32.bytes;
 }
 
 /* Decode an IEEE 754R decimal32 type into a real.  */
@@ -174,10 +153,7 @@ decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    *((uint32_t *) d32.bytes) = (uint32_t) buf[0];
-  else
-    *((uint32_t *) d32.bytes) = dfp_byte_swap ((uint32_t) buf[0]);
+  *((uint32_t *) d32.bytes) = (uint32_t) buf[0];
 
   decimal32ToNumber (&d32, &dn);
   decimal_from_decnumber (r, &dn, &set); 
@@ -199,16 +175,8 @@ encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decimal_to_decnumber (r, &dn);
   decimal64FromNumber (&d64, &dn, &set);
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    {
-      buf[0] = *(uint32_t *) &d64.bytes[0];
-      buf[1] = *(uint32_t *) &d64.bytes[4];
-    }
-  else
-    {
-      buf[1] = dfp_byte_swap (*(uint32_t *) &d64.bytes[0]);
-      buf[0] = dfp_byte_swap (*(uint32_t *) &d64.bytes[4]);
-    }
+  buf[0] = *(uint32_t *) &d64.bytes[0];
+  buf[1] = *(uint32_t *) &d64.bytes[4];
 }
 
 /* Decode an IEEE 754R decimal64 type into a real.  */
@@ -224,16 +192,8 @@ decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    {
-      *((uint32_t *) &d64.bytes[0]) = (uint32_t) buf[0];
-      *((uint32_t *) &d64.bytes[4]) = (uint32_t) buf[1];
-    }
-  else
-    {
-      *((uint32_t *) &d64.bytes[0]) = dfp_byte_swap ((uint32_t) buf[1]);
-      *((uint32_t *) &d64.bytes[4]) = dfp_byte_swap ((uint32_t) buf[0]); 
-    }
+  *((uint32_t *) &d64.bytes[0]) = (uint32_t) buf[0];
+  *((uint32_t *) &d64.bytes[4]) = (uint32_t) buf[1];
 
   decimal64ToNumber (&d64, &dn);
   decimal_from_decnumber (r, &dn, &set); 
@@ -255,20 +215,10 @@ encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decimal_to_decnumber (r, &dn);
   decimal128FromNumber (&d128, &dn, &set);
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    {
-      buf[0] = *(uint32_t *) &d128.bytes[0];
-      buf[1] = *(uint32_t *) &d128.bytes[4];
-      buf[2] = *(uint32_t *) &d128.bytes[8];
-      buf[3] = *(uint32_t *) &d128.bytes[12];
-    }
-  else
-    {
-      buf[0] = dfp_byte_swap (*(uint32_t *) &d128.bytes[12]);
-      buf[1] = dfp_byte_swap (*(uint32_t *) &d128.bytes[8]);
-      buf[2] = dfp_byte_swap (*(uint32_t *) &d128.bytes[4]);
-      buf[3] = dfp_byte_swap (*(uint32_t *) &d128.bytes[0]);
-    }
+  buf[0] = *(uint32_t *) &d128.bytes[0];
+  buf[1] = *(uint32_t *) &d128.bytes[4];
+  buf[2] = *(uint32_t *) &d128.bytes[8];
+  buf[3] = *(uint32_t *) &d128.bytes[12];
 }
 
 /* Decode an IEEE 754R decimal128 type into a real.  */
@@ -284,20 +234,10 @@ decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
   decContextDefault (&set, DEC_INIT_DECIMAL128);
   set.traps = 0;
 
-  if (FLOAT_WORDS_BIG_ENDIAN)
-    {
-      *((uint32_t *) &d128.bytes[0])  = (uint32_t) buf[0];
-      *((uint32_t *) &d128.bytes[4])  = (uint32_t) buf[1];
-      *((uint32_t *) &d128.bytes[8])  = (uint32_t) buf[2];
-      *((uint32_t *) &d128.bytes[12]) = (uint32_t) buf[3];
-    }
-  else
-    {
-      *((uint32_t *) &d128.bytes[0])  = dfp_byte_swap ((uint32_t) buf[3]);
-      *((uint32_t *) &d128.bytes[4])  = dfp_byte_swap ((uint32_t) buf[2]);
-      *((uint32_t *) &d128.bytes[8])  = dfp_byte_swap ((uint32_t) buf[1]);
-      *((uint32_t *) &d128.bytes[12]) = dfp_byte_swap ((uint32_t) buf[0]);
-    }
+  *((uint32_t *) &d128.bytes[0])  = (uint32_t) buf[0];
+  *((uint32_t *) &d128.bytes[4])  = (uint32_t) buf[1];
+  *((uint32_t *) &d128.bytes[8])  = (uint32_t) buf[2];
+  *((uint32_t *) &d128.bytes[12]) = (uint32_t) buf[3];
 
   decimal128ToNumber (&d128, &dn);
   decimal_from_decnumber (r, &dn, &set); 
index dd1804f04370585ae46f76f75c3448b855b81b65..38b4253920545f732c363db0709198283c86e884 100644 (file)
@@ -1,3 +1,54 @@
+2007-09-10  Janis Johnson  <janis187@us.ibm.com>
+           Ben Elliston  <bje@au.ibm.com>
+
+       * Makefile.in (libdecnumber_a_OBJS): Remove decUtility.o
+       (dependencies): Add Symbols headers.
+       * decContext.c: Upgrade to decNumber 3.53.
+       * decContext.h: Ditto.
+       * decDPD.h: Ditto.
+       * decNumber.c: Ditto.
+       * decNumber.h: Ditto.
+       * decNumberLocal.h: Ditto.
+       * decBasic.c: New file from decNumber 3.53.
+       * decCommon.c: Ditto.
+       * decDouble.c: Ditto.
+       * decDouble.h: Ditto.
+       * decQuad.c: Ditto.
+       * decQuad.h: Ditto.
+       * decSingle.c: Ditto.
+       * decSingle.h: Ditto.
+       * decPacked.c: Ditto.
+       * decPacked.h: Ditto.
+       * dpd/decimal128.c: Upgrade to decNumber 3.53.
+       * dpd/decimal128.h: Ditto.
+       * dpd/decimal32.c: Ditto.
+       * dpd/decimal32.h: Ditto.
+       * dpd/decimal64.c: Ditto.
+       * dpd/decimal64.h: Ditto.
+       * decLibrary.c (__dec_byte_swap): Remove.
+       * decContextSymbols.h: New file.
+       * decDoubleSymbols.h: New file.
+       * decNumberSymbols.h: New file.
+       * decPackedSymbols.h: New file.
+       * decQuadSymbols.h: New file.
+       * decSingleSymbols.h: New file.
+       * decUtility.c: Delete file.
+       * decUtility.h: Delete file.
+       * bid/decimal128Symbols.h: New file.
+       * bid/decimal128Local.h: New file.
+       * bid/decimal32Symbols.h: New file.
+       * bid/decimal64Symbols.h: New file.
+       * bid/host-ieee128.c (__swap128): Remove.
+       (__host_to_ieee_128, __ieee_to_host_128): Don't handle endianness.
+       * bid/host-ieee32.c (__dec_type_swap): Remove.
+       (__host_to_ieee_32, __ieee_to_host_32): Don't handle endianness.
+       * bid/host-ieee64.c (__swap64): Remove.
+       (__host_to_ieee_64, __ieee_to_host_64): Don't handle endianness.
+       * dpd/decimal32Symbols.h: New file.
+       * dpd/decimal64Symbols.h: New file.
+       * dpd/decimal128Symbols.h: New file.
+       * dpd/decimal128Local.h: New file.
+
 2007-06-18  Martin Michlmayr  <tbm@cyrius.com>
            H.J. Lu  <hongjiu.lu@intel.com>
 
index 730e1eb43fa5e2dba0137478aaa03f2a45486cb5..98ae9eac78ca9f9c48eebc923f14dcdad71cf97e 100644 (file)
@@ -56,7 +56,7 @@ INCLUDES = -I$(srcdir) -I.
 
 ALL_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(INCLUDES) $(CPPFLAGS)
 
-libdecnumber_a_OBJS = decNumber.o decContext.o decUtility.o \
+libdecnumber_a_OBJS = decNumber.o decContext.o \
        decimal32.o decimal64.o decimal128.o
 
 ifeq ($(enable_decimal_float),bid)
@@ -66,7 +66,6 @@ endif
 
 libdecnumber_a_SOURCES = decContext.c decContext.h decDPD.h \
        decNumber.c decNumber.h decNumberLocal.h \
-       decUtility.c decUtility.h \
        dpd/decimal128.c dpd/decimal128.h \
        dpd/decimal32.c dpd/decimal32.h \
        dpd/decimal64.c dpd/decimal64.h \
@@ -113,19 +112,25 @@ $(srcdir)/config.in: @MAINT@ $(srcdir)/configure
 
 # Dependencies.
 
-decContext.o: decContext.c decContext.h decNumberLocal.h
-decNumber.o:  decNumber.c decNumber.h decContext.h decNumberLocal.h
+decContext.o: decContext.c decContext.h decNumberLocal.h \
+       decContextSymbols.h
+decNumber.o:  decNumber.c decNumber.h decContext.h decNumberLocal.h \
+       decNumberSymbols.h
 decimal32.o:  $(enable_decimal_float)/decimal32.c \
    $(enable_decimal_float)/decimal32.h \
-   decNumber.h decContext.h decNumberLocal.h decUtility.h
+   $(enable_decimal_float)/decimal32Symbols.h \
+   decNumber.h decContext.h decNumberLocal.h
        $(COMPILE) $<
 decimal64.o:  $(enable_decimal_float)/decimal64.c \
    $(enable_decimal_float)/decimal64.h \
-   decNumber.h decContext.h decNumberLocal.h decUtility.h
+   $(enable_decimal_float)/decimal64Symbols.h \
+   decNumber.h decContext.h decNumberLocal.h
        $(COMPILE) $<
 decimal128.o:  $(enable_decimal_float)/decimal128.c \
    $(enable_decimal_float)/decimal128.h \
-   decNumber.h decContext.h decNumberLocal.h decUtility.h
+   $(enable_decimal_float)/decimal128Symbols.h\
+   $(enable_decimal_float)/decimal128Local.h\
+   decNumber.h decContext.h decNumberLocal.h 
        $(COMPILE) $<
 bid2dpd_dpd2bid.o : bid/bid2dpd_dpd2bid.c bid/bid2dpd_dpd2bid.h
        $(COMPILE) $<
diff --git a/libdecnumber/bid/decimal128Local.h b/libdecnumber/bid/decimal128Local.h
new file mode 100644 (file)
index 0000000..e499d73
--- /dev/null
@@ -0,0 +1 @@
+#include "dpd/decimal128Local.h"
diff --git a/libdecnumber/bid/decimal128Symbols.h b/libdecnumber/bid/decimal128Symbols.h
new file mode 100644 (file)
index 0000000..1775711
--- /dev/null
@@ -0,0 +1 @@
+#include "dpd/decimal128Symbols.h"
diff --git a/libdecnumber/bid/decimal32Symbols.h b/libdecnumber/bid/decimal32Symbols.h
new file mode 100644 (file)
index 0000000..a0c4bf8
--- /dev/null
@@ -0,0 +1 @@
+#include "dpd/decimal32Symbols.h"
diff --git a/libdecnumber/bid/decimal64Symbols.h b/libdecnumber/bid/decimal64Symbols.h
new file mode 100644 (file)
index 0000000..5f3069c
--- /dev/null
@@ -0,0 +1 @@
+#include "dpd/decimal64Symbols.h"
index 2c8ea32746aec7dbbb374a85f0025eec48bdf81c..6d493e5c9d8a49bd5c13b9542f3cf930c8f42fc2 100644 (file)
@@ -27,56 +27,22 @@ along with GCC; see the file COPYING.  If not, write to the Free
 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA.  */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <limits.h>
 
-#include "config.h"
-#include "gstdint.h"
 #include "bid-dpd.h"
 #include "decimal128.h"
 
-extern uint32_t __dec_byte_swap (uint32_t);
 void __host_to_ieee_128 (_Decimal128 in, decimal128 *out);
 void __ieee_to_host_128 (decimal128 in, _Decimal128 *out);
 
-#ifndef WORDS_BIGENDIAN
-#define WORDS_BIGENDIAN 0
-#endif
-
-static void
-__swap128 (char *src, char *dst)
-{
-  uint32_t t1, t2, t3, t4;
-
-  if (!WORDS_BIGENDIAN)
-    {
-      memcpy (&t1, src, 4);
-      memcpy (&t2, src + 4, 4);
-      memcpy (&t3, src + 8, 4);
-      memcpy (&t4, src + 12, 4);
-      t1 = __dec_byte_swap (t1);
-      t2 = __dec_byte_swap (t2);
-      t3 = __dec_byte_swap (t3);
-      t4 = __dec_byte_swap (t4);
-      memcpy (dst, &t4, 4);
-      memcpy (dst + 4, &t3, 4);
-      memcpy (dst + 8, &t2, 4);
-      memcpy (dst + 12, &t1, 4);
-    }
-  else
-    memcpy (dst, src, 16);
-}
-
 void
 __host_to_ieee_128 (_Decimal128 in, decimal128 *out)
 {
-  __swap128 ((char *) &in, (char *) out);
+  memcpy ((char *) out, (char *) &in, 16);
 }
 
 void
 __ieee_to_host_128 (decimal128 in, _Decimal128 *out)
 {
-  __swap128 ((char *) &in, (char *) out);
+  memcpy ((char *) out, (char *) &in, 16);
 }
index 639662edfee943b1649ba3d936065b7454ea0161..9a59c938644983628502f07f7b4bc2a8b5c5ea7c 100644 (file)
@@ -37,69 +37,21 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 /* The intended way to use this file is to make two copies, add `#define '
    to one copy, then compile both copies and add them to libgcc.a.  */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <limits.h>
-
-#include "config.h"
-#include "gstdint.h"
 #include "bid-dpd.h"
 #include "decimal32.h"
 
-uint32_t __dec_byte_swap (uint32_t);
 void __host_to_ieee_32 (_Decimal32 in, decimal32 *out);
 void __ieee_to_host_32 (decimal32 in, _Decimal32 *out);
 
-#ifndef WORDS_BIGENDIAN
-#define WORDS_BIGENDIAN 0
-#endif
-
-uint32_t
-__dec_byte_swap (uint32_t in)
-{
-  uint32_t out = 0;
-  unsigned char *p = (unsigned char *) &out;
-  union {
-    uint32_t i;
-    unsigned char b[4];
-  } u;
-
-  u.i = in;
-  p[0] = u.b[3];
-  p[1] = u.b[2];
-  p[2] = u.b[1];
-  p[3] = u.b[0];
-
-  return out;
-}
-
 void
 __host_to_ieee_32 (_Decimal32 in, decimal32 *out)
 {
-  uint32_t t;
-
-  if (!WORDS_BIGENDIAN)
-    {
-      memcpy (&t, &in, 4);
-      t = __dec_byte_swap (t);
-      memcpy (out, &t, 4);
-    }
-  else
-    memcpy (out, &in, 4);
+  memcpy ((char *) out, (char *) &in, 4);
 }
 
 void
 __ieee_to_host_32 (decimal32 in, _Decimal32 *out)
 {
-  uint32_t t;
-
-  if (!WORDS_BIGENDIAN)
-    {
-      memcpy (&t, &in, 4);
-      t = __dec_byte_swap (t);
-      memcpy (out, &t, 4);
-    }
-  else
-    memcpy (out, &in, 4);
+  memcpy ((char *) out, (char *) &in, 4);
 }
index 3c98985244dfbdb797c4cd87d5ac58fd2e971a1f..ac6cd849efecd86f96f1eb7895a0ce80fb92bcaa 100644 (file)
@@ -37,50 +37,21 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 /* The intended way to use this file is to make two copies, add `#define '
    to one copy, then compile both copies and add them to libgcc.a.  */
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <limits.h>
-
-#include "config.h"
-#include "gstdint.h"
 #include "bid-dpd.h"
 #include "decimal64.h"
 
-uint32_t __dec_byte_swap (uint32_t);
 void __host_to_ieee_64 (_Decimal64 in, decimal64 *out);
 void __ieee_to_host_64 (decimal64 in, _Decimal64 *out);
 
-#ifndef WORDS_BIGENDIAN
-#define WORDS_BIGENDIAN 0
-#endif
-
-static void
-__swap64 (char *src, char *dst)
-{
-  uint32_t t1, t2;
-
-  if (!WORDS_BIGENDIAN) 
-    {
-      memcpy (&t1, src, 4);
-      memcpy (&t2, src + 4, 4);
-      t1 = __dec_byte_swap (t1);
-      t2 = __dec_byte_swap (t2);
-      memcpy (dst, &t2, 4);
-      memcpy (dst + 4, &t1, 4);
-    }
-  else
-    memcpy (dst, src, 8);
-}
-
 void
 __host_to_ieee_64 (_Decimal64 in, decimal64 *out)
 {
-  __swap64 ((char *) &in, (char *) out);
+  memcpy ((char *) out, (char *) &in, 8);
 }
 
 void
 __ieee_to_host_64 (decimal64 in, _Decimal64 *out)
 {
-  __swap64 ((char *) &in, (char *) out);
+  memcpy ((char *) out, (char *) &in, 8);
 }
diff --git a/libdecnumber/decBasic.c b/libdecnumber/decBasic.c
new file mode 100644 (file)
index 0000000..9ce277d
--- /dev/null
@@ -0,0 +1,3769 @@
+/* Common base code for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* decBasic.c -- common base code for Basic decimal types            */
+/* ------------------------------------------------------------------ */
+/* This module comprises code that is shared between decDouble and    */
+/* decQuad (but not decSingle).         The main arithmetic operations are   */
+/* here (Add, Subtract, Multiply, FMA, and Division operators).              */
+/*                                                                   */
+/* Unlike decNumber, parameterization takes place at compile time     */
+/* rather than at runtime.  The parameters are set in the decDouble.c */
+/* (etc.) files, which then include this one to produce the compiled  */
+/* code.  The functions here, therefore, are code shared between      */
+/* multiple formats.                                                 */
+/*                                                                   */
+/* This must be included after decCommon.c.                          */
+/* ------------------------------------------------------------------ */
+/* Names here refer to decFloat rather than to decDouble, etc., and */
+/* the functions are in strict alphabetical order. */
+
+/* The compile-time flags SINGLE, DOUBLE, and QUAD are set up in */
+/* decCommon.c */
+#if !defined(QUAD)
+  #error decBasic.c must be included after decCommon.c
+#endif
+#if SINGLE
+  #error Routines in decBasic.c are for decDouble and decQuad only
+#endif
+
+/* Private constants */
+#define DIVIDE     0x80000000     /* Divide operations [as flags] */
+#define REMAINDER   0x40000000    /* .. */
+#define DIVIDEINT   0x20000000    /* .. */
+#define REMNEAR            0x10000000     /* .. */
+
+/* Private functions (local, used only by routines in this module) */
+static decFloat *decDivide(decFloat *, const decFloat *,
+                             const decFloat *, decContext *, uInt);
+static decFloat *decCanonical(decFloat *, const decFloat *);
+static void     decFiniteMultiply(bcdnum *, uByte *, const decFloat *,
+                             const decFloat *);
+static decFloat *decInfinity(decFloat *, const decFloat *);
+static decFloat *decInvalid(decFloat *, decContext *);
+static decFloat *decNaNs(decFloat *, const decFloat *, const decFloat *,
+                             decContext *);
+static Int      decNumCompare(const decFloat *, const decFloat *, Flag);
+static decFloat *decToIntegral(decFloat *, const decFloat *, decContext *,
+                             enum rounding, Flag);
+static uInt     decToInt32(const decFloat *, decContext *, enum rounding,
+                             Flag, Flag);
+
+/* ------------------------------------------------------------------ */
+/* decCanonical -- copy a decFloat, making canonical                 */
+/*                                                                   */
+/*   result gets the canonicalized df                                */
+/*   df            is the decFloat to copy and make canonical                */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is exposed via decFloatCanonical for Double and Quad only.    */
+/* This works on specials, too; no error or exception is possible.    */
+/* ------------------------------------------------------------------ */
+static decFloat * decCanonical(decFloat *result, const decFloat *df) {
+  uInt encode, precode, dpd;      /* work */
+  uInt inword, uoff, canon;       /* .. */
+  Int  n;                         /* counter (down) */
+  if (df!=result) *result=*df;    /* effect copy if needed */
+  if (DFISSPECIAL(result)) {
+    if (DFISINF(result)) return decInfinity(result, df); /* clean Infinity */
+    /* is a NaN */
+    DFWORD(result, 0)&=~ECONNANMASK;   /* clear ECON except selector */
+    if (DFISCCZERO(df)) return result; /* coefficient continuation is 0 */
+    /* drop through to check payload */
+    }
+  /* return quickly if the coefficient continuation is canonical */
+  { /* declare block */
+  #if DOUBLE
+    uInt sourhi=DFWORD(df, 0);
+    uInt sourlo=DFWORD(df, 1);
+    if (CANONDPDOFF(sourhi, 8)
+     && CANONDPDTWO(sourhi, sourlo, 30)
+     && CANONDPDOFF(sourlo, 20)
+     && CANONDPDOFF(sourlo, 10)
+     && CANONDPDOFF(sourlo, 0)) return result;
+  #elif QUAD
+    uInt sourhi=DFWORD(df, 0);
+    uInt sourmh=DFWORD(df, 1);
+    uInt sourml=DFWORD(df, 2);
+    uInt sourlo=DFWORD(df, 3);
+    if (CANONDPDOFF(sourhi, 4)
+     && CANONDPDTWO(sourhi, sourmh, 26)
+     && CANONDPDOFF(sourmh, 16)
+     && CANONDPDOFF(sourmh, 6)
+     && CANONDPDTWO(sourmh, sourml, 28)
+     && CANONDPDOFF(sourml, 18)
+     && CANONDPDOFF(sourml, 8)
+     && CANONDPDTWO(sourml, sourlo, 30)
+     && CANONDPDOFF(sourlo, 20)
+     && CANONDPDOFF(sourlo, 10)
+     && CANONDPDOFF(sourlo, 0)) return result;
+  #endif
+  } /* block */
+
+  /* Loop to repair a non-canonical coefficent, as needed */
+  inword=DECWORDS-1;              /* current input word */
+  uoff=0;                         /* bit offset of declet */
+  encode=DFWORD(result, inword);
+  for (n=DECLETS-1; n>=0; n--) {   /* count down declets of 10 bits */
+    dpd=encode>>uoff;
+    uoff+=10;
+    if (uoff>32) {                /* crossed uInt boundary */
+      inword--;
+      encode=DFWORD(result, inword);
+      uoff-=32;
+      dpd|=encode<<(10-uoff);     /* get pending bits */
+      }
+    dpd&=0x3ff;                           /* clear uninteresting bits */
+    if (dpd<0x16e) continue;      /* must be canonical */
+    canon=BIN2DPD[DPD2BIN[dpd]];   /* determine canonical declet */
+    if (canon==dpd) continue;     /* have canonical declet */
+    /* need to replace declet */
+    if (uoff>=10) {               /* all within current word */
+      encode&=~(0x3ff<<(uoff-10)); /* clear the 10 bits ready for replace */
+      encode|=canon<<(uoff-10);           /* insert the canonical form */
+      DFWORD(result, inword)=encode;   /* .. and save */
+      continue;
+      }
+    /* straddled words */
+    precode=DFWORD(result, inword+1);  /* get previous */
+    precode&=0xffffffff>>(10-uoff);    /* clear top bits */
+    DFWORD(result, inword+1)=precode|(canon<<(32-(10-uoff)));
+    encode&=0xffffffff<<uoff;          /* clear bottom bits */
+    encode|=canon>>(10-uoff);          /* insert canonical */
+    DFWORD(result, inword)=encode;     /* .. and save */
+    } /* n */
+  return result;
+  } /* decCanonical */
+
+/* ------------------------------------------------------------------ */
+/* decDivide -- divide operations                                    */
+/*                                                                   */
+/*   result gets the result of dividing dfl by dfr:                  */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   op            is the operation selector                                 */
+/*   returns result                                                  */
+/*                                                                   */
+/* op is one of DIVIDE, REMAINDER, DIVIDEINT, or REMNEAR.            */
+/* ------------------------------------------------------------------ */
+#define DIVCOUNT  0               /* 1 to instrument subtractions counter */
+#define DIVBASE          BILLION          /* the base used for divide */
+#define DIVOPLEN  DECPMAX9        /* operand length ('digits' base 10**9) */
+#define DIVACCLEN (DIVOPLEN*3)    /* accumulator length (ditto) */
+static decFloat * decDivide(decFloat *result, const decFloat *dfl,
+                           const decFloat *dfr, decContext *set, uInt op) {
+  decFloat quotient;              /* for remainders */
+  bcdnum num;                     /* for final conversion */
+  uInt  acc[DIVACCLEN];           /* coefficent in base-billion .. */
+  uInt  div[DIVOPLEN];            /* divisor in base-billion .. */
+  uInt  quo[DIVOPLEN+1];          /* quotient in base-billion .. */
+  uByte         bcdacc[(DIVOPLEN+1)*9+2]; /* for quotient in BCD, +1, +1 */
+  uInt  *msua, *msud, *msuq;      /* -> msu of acc, div, and quo */
+  Int   divunits, accunits;       /* lengths */
+  Int   quodigits;                /* digits in quotient */
+  uInt  *lsua, *lsuq;             /* -> current acc and quo lsus */
+  Int   length, multiplier;       /* work */
+  uInt  carry, sign;              /* .. */
+  uInt  *ua, *ud, *uq;            /* .. */
+  uByte         *ub;                      /* .. */
+  uInt  divtop;                   /* top unit of div adjusted for estimating */
+  #if DIVCOUNT
+  static uInt maxcount=0;         /* worst-seen subtractions count */
+  uInt  divcount=0;               /* subtractions count [this divide] */
+  #endif
+
+  /* calculate sign */
+  num.sign=(DFWORD(dfl, 0)^DFWORD(dfr, 0)) & DECFLOAT_Sign;
+
+  if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr)) { /* either is special? */
+    /* NaNs are handled as usual */
+    if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+    /* one or two infinities */
+    if (DFISINF(dfl)) {
+      if (DFISINF(dfr)) return decInvalid(result, set); /* Two infinities bad */
+      if (op&(REMAINDER|REMNEAR)) return decInvalid(result, set); /* as is rem */
+      /* Infinity/x is infinite and quiet, even if x=0 */
+      DFWORD(result, 0)=num.sign;
+      return decInfinity(result, result);
+      }
+    /* must be x/Infinity -- remainders are lhs */
+    if (op&(REMAINDER|REMNEAR)) return decCanonical(result, dfl);
+    /* divides: return zero with correct sign and exponent depending */
+    /* on op (Etiny for divide, 0 for divideInt) */
+    decFloatZero(result);
+    if (op==DIVIDEINT) DFWORD(result, 0)|=num.sign; /* add sign */
+     else DFWORD(result, 0)=num.sign;       /* zeros the exponent, too */
+    return result;
+    }
+  /* next, handle zero operands (x/0 and 0/x) */
+  if (DFISZERO(dfr)) {                      /* x/0 */
+    if (DFISZERO(dfl)) {                    /* 0/0 is undefined */
+      decFloatZero(result);
+      DFWORD(result, 0)=DECFLOAT_qNaN;
+      set->status|=DEC_Division_undefined;
+      return result;
+      }
+    if (op&(REMAINDER|REMNEAR)) return decInvalid(result, set); /* bad rem */
+    set->status|=DEC_Division_by_zero;
+    DFWORD(result, 0)=num.sign;
+    return decInfinity(result, result);             /* x/0 -> signed Infinity */
+    }
+  num.exponent=GETEXPUN(dfl)-GETEXPUN(dfr);  /* ideal exponent */
+  if (DFISZERO(dfl)) {                      /* 0/x (x!=0) */
+    /* if divide, result is 0 with ideal exponent; divideInt has */
+    /* exponent=0, remainders give zero with lower exponent */
+    if (op&DIVIDEINT) {
+      decFloatZero(result);
+      DFWORD(result, 0)|=num.sign;          /* add sign */
+      return result;
+      }
+    if (!(op&DIVIDE)) {                             /* a remainder */
+      /* exponent is the minimum of the operands */
+      num.exponent=MINI(GETEXPUN(dfl), GETEXPUN(dfr));
+      /* if the result is zero the sign shall be sign of dfl */
+      num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign;
+      }
+    bcdacc[0]=0;
+    num.msd=bcdacc;                         /* -> 0 */
+    num.lsd=bcdacc;                         /* .. */
+    return decFinalize(result, &num, set);   /* [divide may clamp exponent] */
+    } /* 0/x */
+  /* [here, both operands are known to be finite and non-zero] */
+
+  /* extract the operand coefficents into 'units' which are */
+  /* base-billion; the lhs is high-aligned in acc and the msu of both */
+  /* acc and div is at the right-hand end of array (offset length-1); */
+  /* the quotient can need one more unit than the operands as digits */
+  /* in it are not necessarily aligned neatly; further, the quotient */
+  /* may not start accumulating until after the end of the initial */
+  /* operand in acc if that is small (e.g., 1) so the accumulator */
+  /* must have at least that number of units extra (at the ls end) */
+  GETCOEFFBILL(dfl, acc+DIVACCLEN-DIVOPLEN);
+  GETCOEFFBILL(dfr, div);
+  /* zero the low uInts of acc */
+  acc[0]=0;
+  acc[1]=0;
+  acc[2]=0;
+  acc[3]=0;
+  #if DOUBLE
+    #if DIVOPLEN!=2
+      #error Unexpected Double DIVOPLEN
+    #endif
+  #elif QUAD
+  acc[4]=0;
+  acc[5]=0;
+  acc[6]=0;
+  acc[7]=0;
+    #if DIVOPLEN!=4
+      #error Unexpected Quad DIVOPLEN
+    #endif
+  #endif
+
+  /* set msu and lsu pointers */
+  msua=acc+DIVACCLEN-1;              /* [leading zeros removed below] */
+  msuq=quo+DIVOPLEN;
+  /*[loop for div will terminate because operands are non-zero] */
+  for (msud=div+DIVOPLEN-1; *msud==0;) msud--;
+  /* the initial least-significant unit of acc is set so acc appears */
+  /* to have the same length as div. */
+  /* This moves one position towards the least possible for each */
+  /* iteration */
+  divunits=(Int)(msud-div+1); /* precalculate */
+  lsua=msua-divunits+1;              /* initial working lsu of acc */
+  lsuq=msuq;                 /* and of quo */
+
+  /* set up the estimator for the multiplier; this is the msu of div, */
+  /* plus two bits from the unit below (if any) rounded up by one if */
+  /* there are any non-zero bits or units below that [the extra two */
+  /* bits makes for a much better estimate when the top unit is small] */
+  divtop=*msud<<2;
+  if (divunits>1) {
+    uInt *um=msud-1;
+    uInt d=*um;
+    if (d>=750000000) {divtop+=3; d-=750000000;}
+     else if (d>=500000000) {divtop+=2; d-=500000000;}
+     else if (d>=250000000) {divtop++; d-=250000000;}
+    if (d) divtop++;
+     else for (um--; um>=div; um--) if (*um) {
+      divtop++;
+      break;
+      }
+    } /* >1 unit */
+
+  #if DECTRACE
+  {Int i;
+  printf("----- div=");
+  for (i=divunits-1; i>=0; i--) printf("%09ld ", (LI)div[i]);
+  printf("\n");}
+  #endif
+
+  /* now collect up to DECPMAX+1 digits in the quotient (this may */
+  /* need OPLEN+1 uInts if unaligned) */
+  quodigits=0;               /* no digits yet */
+  for (;; lsua--) {          /* outer loop -- each input position */
+    #if DECCHECK
+    if (lsua<acc) {
+      printf("Acc underrun...\n");
+      break;
+      }
+    #endif
+    #if DECTRACE
+    printf("Outer: quodigits=%ld acc=", (LI)quodigits);
+    for (ua=msua; ua>=lsua; ua--) printf("%09ld ", (LI)*ua);
+    printf("\n");
+    #endif
+    *lsuq=0;                 /* default unit result is 0 */
+    for (;;) {               /* inner loop -- calculate quotient unit */
+      /* strip leading zero units from acc (either there initially or */
+      /* from subtraction below); this may strip all if exactly 0 */
+      for (; *msua==0 && msua>=lsua;) msua--;
+      accunits=(Int)(msua-lsua+1);               /* [maybe 0] */
+      /* subtraction is only necessary and possible if there are as */
+      /* least as many units remaining in acc for this iteration as */
+      /* there are in div */
+      if (accunits<divunits) {
+       if (accunits==0) msua++;                  /* restore */
+       break;
+       }
+
+      /* If acc is longer than div then subtraction is definitely */
+      /* possible (as msu of both is non-zero), but if they are the */
+      /* same length a comparison is needed. */
+      /* If a subtraction is needed then a good estimate of the */
+      /* multiplier for the subtraction is also needed in order to */
+      /* minimise the iterations of this inner loop because the */
+      /* subtractions needed dominate division performance. */
+      if (accunits==divunits) {
+       /* compare the high divunits of acc and div: */
+       /* acc<div:  this quotient unit is unchanged; subtraction */
+       /*           will be possible on the next iteration */
+       /* acc==div: quotient gains 1, set acc=0 */
+       /* acc>div:  subtraction necessary at this position */
+       for (ud=msud, ua=msua; ud>div; ud--, ua--) if (*ud!=*ua) break;
+       /* [now at first mismatch or lsu] */
+       if (*ud>*ua) break;                       /* next time... */
+       if (*ud==*ua) {                           /* all compared equal */
+         *lsuq+=1;                               /* increment result */
+         msua=lsua;                              /* collapse acc units */
+         *msua=0;                                /* .. to a zero */
+         break;
+         }
+
+       /* subtraction necessary; estimate multiplier [see above] */
+       /* if both *msud and *msua are small it is cost-effective to */
+       /* bring in part of the following units (if any) to get a */
+       /* better estimate (assume some other non-zero in div) */
+       #define DIVLO 1000000U
+       #define DIVHI (DIVBASE/DIVLO)
+       #if DECUSE64
+         if (divunits>1) {
+           /* there cannot be a *(msud-2) for DECDOUBLE so next is */
+           /* an exact calculation unless DECQUAD (which needs to */
+           /* assume bits out there if divunits>2) */
+           uLong mul=(uLong)*msua * DIVBASE + *(msua-1);
+           uLong div=(uLong)*msud * DIVBASE + *(msud-1);
+           #if QUAD
+           if (divunits>2) div++;
+           #endif
+           mul/=div;
+           multiplier=(Int)mul;
+           }
+          else multiplier=*msua/(*msud);
+       #else
+         if (divunits>1 && *msua<DIVLO && *msud<DIVLO) {
+           multiplier=(*msua*DIVHI + *(msua-1)/DIVLO)
+                     /(*msud*DIVHI + *(msud-1)/DIVLO +1);
+           }
+          else multiplier=(*msua<<2)/divtop;
+       #endif
+       }
+       else {                                    /* accunits>divunits */
+       /* msud is one unit 'lower' than msua, so estimate differently */
+       #if DECUSE64
+         uLong mul;
+         /* as before, bring in extra digits if possible */
+         if (divunits>1 && *msua<DIVLO && *msud<DIVLO) {
+           mul=((uLong)*msua * DIVHI * DIVBASE) + *(msua-1) * DIVHI
+              + *(msua-2)/DIVLO;
+           mul/=(*msud*DIVHI + *(msud-1)/DIVLO +1);
+           }
+          else if (divunits==1) {
+           mul=(uLong)*msua * DIVBASE + *(msua-1);
+           mul/=*msud;       /* no more to the right */
+           }
+          else {
+           mul=(uLong)(*msua) * (uInt)(DIVBASE<<2) + (*(msua-1)<<2);
+           mul/=divtop;      /* [divtop already allows for sticky bits] */
+           }
+         multiplier=(Int)mul;
+       #else
+         multiplier=*msua * ((DIVBASE<<2)/divtop);
+       #endif
+       }
+      if (multiplier==0) multiplier=1;           /* marginal case */
+      *lsuq+=multiplier;
+
+      #if DIVCOUNT
+      /* printf("Multiplier: %ld\n", (LI)multiplier); */
+      divcount++;
+      #endif
+
+      /* Carry out the subtraction  acc-(div*multiplier); for each */
+      /* unit in div, do the multiply, split to units (see */
+      /* decFloatMultiply for the algorithm), and subtract from acc */
+      #define DIVMAGIC 2305843009U               /* 2**61/10**9 */
+      #define DIVSHIFTA 29
+      #define DIVSHIFTB 32
+      carry=0;
+      for (ud=div, ua=lsua; ud<=msud; ud++, ua++) {
+       uInt lo, hop;
+       #if DECUSE64
+         uLong sub=(uLong)multiplier*(*ud)+carry;
+         if (sub<DIVBASE) {
+           carry=0;
+           lo=(uInt)sub;
+           }
+          else {
+           hop=(uInt)(sub>>DIVSHIFTA);
+           carry=(uInt)(((uLong)hop*DIVMAGIC)>>DIVSHIFTB);
+           /* the estimate is now in hi; now calculate sub-hi*10**9 */
+           /* to get the remainder (which will be <DIVBASE)) */
+           lo=(uInt)sub;
+           lo-=carry*DIVBASE;                    /* low word of result */
+           if (lo>=DIVBASE) {
+             lo-=DIVBASE;                        /* correct by +1 */
+             carry++;
+             }
+           }
+       #else /* 32-bit */
+         uInt hi;
+         /* calculate multiplier*(*ud) into hi and lo */
+         LONGMUL32HI(hi, *ud, multiplier);       /* get the high word */
+         lo=multiplier*(*ud);                    /* .. and the low */
+         lo+=carry;                              /* add the old hi */
+         carry=hi+(lo<carry);                    /* .. with any carry */
+         if (carry || lo>=DIVBASE) {             /* split is needed */
+           hop=(carry<<3)+(lo>>DIVSHIFTA);       /* hi:lo/2**29 */
+           LONGMUL32HI(carry, hop, DIVMAGIC);    /* only need the high word */
+           /* [DIVSHIFTB is 32, so carry can be used directly] */
+           /* the estimate is now in carry; now calculate hi:lo-est*10**9; */
+           /* happily the top word of the result is irrelevant because it */
+           /* will always be zero so this needs only one multiplication */
+           lo-=(carry*DIVBASE);
+           /* the correction here will be at most +1; do it */
+           if (lo>=DIVBASE) {
+             lo-=DIVBASE;
+             carry++;
+             }
+           }
+       #endif
+       if (lo>*ua) {              /* borrow needed */
+         *ua+=DIVBASE;
+         carry++;
+         }
+       *ua-=lo;
+       } /* ud loop */
+      if (carry) *ua-=carry;      /* accdigits>divdigits [cannot borrow] */
+      } /* inner loop */
+
+    /* the outer loop terminates when there is either an exact result */
+    /* or enough digits; first update the quotient digit count and */
+    /* pointer (if any significant digits) */
+    #if DECTRACE
+    if (*lsuq || quodigits) printf("*lsuq=%09ld\n", (LI)*lsuq);
+    #endif
+    if (quodigits) {
+      quodigits+=9;               /* had leading unit earlier */
+      lsuq--;
+      if (quodigits>DECPMAX+1) break;  /* have enough */
+      }
+     else if (*lsuq) {            /* first quotient digits */
+      const uInt *pow;
+      for (pow=DECPOWERS; *lsuq>=*pow; pow++) quodigits++;
+      lsuq--;
+      /* [cannot have >DECPMAX+1 on first unit] */
+      }
+
+    if (*msua!=0) continue;       /* not an exact result */
+    /* acc is zero iff used all of original units and zero down to lsua */
+    /* (must also continue to original lsu for correct quotient length) */
+    if (lsua>acc+DIVACCLEN-DIVOPLEN) continue;
+    for (; msua>lsua && *msua==0;) msua--;
+    if (*msua==0 && msua==lsua) break;
+    } /* outer loop */
+
+  /* all of the original operand in acc has been covered at this point */
+  /* quotient now has at least DECPMAX+2 digits */
+  /* *msua is now non-0 if inexact and sticky bits */
+  /* lsuq is one below the last uint of the quotient */
+  lsuq++;                         /* set -> true lsu of quo */
+  if (*msua) *lsuq|=1;            /* apply sticky bit */
+
+  /* quo now holds the (unrounded) quotient in base-billion; one */
+  /* base-billion 'digit' per uInt. */
+  #if DECTRACE
+  printf("DivQuo:");
+  for (uq=msuq; uq>=lsuq; uq--) printf(" %09ld", (LI)*uq);
+  printf("\n");
+  #endif
+
+  /* Now convert to BCD for rounding and cleanup, starting from the */
+  /* most significant end [offset by one into bcdacc to leave room */
+  /* for a possible carry digit if rounding for REMNEAR is needed] */
+  for (uq=msuq, ub=bcdacc+1; uq>=lsuq; uq--, ub+=9) {
+    uInt top, mid, rem;                        /* work */
+    if (*uq==0) {                      /* no split needed */
+      UINTAT(ub)=0;                    /* clear 9 BCD8s */
+      UINTAT(ub+4)=0;                  /* .. */
+      *(ub+8)=0;                       /* .. */
+      continue;
+      }
+    /* *uq is non-zero -- split the base-billion digit into */
+    /* hi, mid, and low three-digits */
+    #define divsplit9 1000000          /* divisor */
+    #define divsplit6 1000             /* divisor */
+    /* The splitting is done by simple divides and remainders, */
+    /* assuming the compiler will optimize these [GCC does] */
+    top=*uq/divsplit9;
+    rem=*uq%divsplit9;
+    mid=rem/divsplit6;
+    rem=rem%divsplit6;
+    /* lay out the nine BCD digits (plus one unwanted byte) */
+    UINTAT(ub) =UINTAT(&BIN2BCD8[top*4]);
+    UINTAT(ub+3)=UINTAT(&BIN2BCD8[mid*4]);
+    UINTAT(ub+6)=UINTAT(&BIN2BCD8[rem*4]);
+    } /* BCD conversion loop */
+  ub--;                                        /* -> lsu */
+
+  /* complete the bcdnum; quodigits is correct, so the position of */
+  /* the first non-zero is known */
+  num.msd=bcdacc+1+(msuq-lsuq+1)*9-quodigits;
+  num.lsd=ub;
+
+  /* make exponent adjustments, etc */
+  if (lsua<acc+DIVACCLEN-DIVOPLEN) {   /* used extra digits */
+    num.exponent-=(Int)((acc+DIVACCLEN-DIVOPLEN-lsua)*9);
+    /* if the result was exact then there may be up to 8 extra */
+    /* trailing zeros in the overflowed quotient final unit */
+    if (*msua==0) {
+      for (; *ub==0;) ub--;            /* drop zeros */
+      num.exponent+=(Int)(num.lsd-ub); /* and adjust exponent */
+      num.lsd=ub;
+      }
+    } /* adjustment needed */
+
+  #if DIVCOUNT
+  if (divcount>maxcount) {             /* new high-water nark */
+    maxcount=divcount;
+    printf("DivNewMaxCount: %ld\n", (LI)maxcount);
+    }
+  #endif
+
+  if (op&DIVIDE) return decFinalize(result, &num, set); /* all done */
+
+  /* Is DIVIDEINT or a remainder; there is more to do -- first form */
+  /* the integer (this is done 'after the fact', unlike as in */
+  /* decNumber, so as not to tax DIVIDE) */
+
+  /* The first non-zero digit will be in the first 9 digits, known */
+  /* from quodigits and num.msd, so there is always space for DECPMAX */
+  /* digits */
+
+  length=(Int)(num.lsd-num.msd+1);
+  /*printf("Length exp: %ld %ld\n", (LI)length, (LI)num.exponent); */
+
+  if (length+num.exponent>DECPMAX) { /* cannot fit */
+    decFloatZero(result);
+    DFWORD(result, 0)=DECFLOAT_qNaN;
+    set->status|=DEC_Division_impossible;
+    return result;
+    }
+
+  if (num.exponent>=0) {          /* already an int, or need pad zeros */
+    for (ub=num.lsd+1; ub<=num.lsd+num.exponent; ub++) *ub=0;
+    num.lsd+=num.exponent;
+    }
+   else {                         /* too long: round or truncate needed */
+    Int drop=-num.exponent;
+    if (!(op&REMNEAR)) {          /* simple truncate */
+      num.lsd-=drop;
+      if (num.lsd<num.msd) {      /* truncated all */
+       num.lsd=num.msd;           /* make 0 */
+       *num.lsd=0;                /* .. [sign still relevant] */
+       }
+      }
+     else {                       /* round to nearest even [sigh] */
+      /* round-to-nearest, in-place; msd is at or to right of bcdacc+1 */
+      /* (this is a special case of Quantize -- q.v. for commentary) */
+      uByte *roundat;             /* -> re-round digit */
+      uByte reround;              /* reround value */
+      *(num.msd-1)=0;             /* in case of left carry, or make 0 */
+      if (drop<length) roundat=num.lsd-drop+1;
+       else if (drop==length) roundat=num.msd;
+       else roundat=num.msd-1;    /* [-> 0] */
+      reround=*roundat;
+      for (ub=roundat+1; ub<=num.lsd; ub++) {
+       if (*ub!=0) {
+         reround=DECSTICKYTAB[reround];
+         break;
+         }
+       } /* check stickies */
+      if (roundat>num.msd) num.lsd=roundat-1;
+       else {
+       num.msd--;                           /* use the 0 .. */
+       num.lsd=num.msd;                     /* .. at the new MSD place */
+       }
+      if (reround!=0) {                             /* discarding non-zero */
+       uInt bump=0;
+       /* rounding is DEC_ROUND_HALF_EVEN always */
+       if (reround>5) bump=1;               /* >0.5 goes up */
+        else if (reround==5)                /* exactly 0.5000 .. */
+         bump=*(num.lsd) & 0x01;            /* .. up iff [new] lsd is odd */
+       if (bump!=0) {                       /* need increment */
+         /* increment the coefficient; this might end up with 1000... */
+         ub=num.lsd;
+         for (; UINTAT(ub-3)==0x09090909; ub-=4) UINTAT(ub-3)=0;
+         for (; *ub==9; ub--) *ub=0;        /* at most 3 more */
+         *ub+=1;
+         if (ub<num.msd) num.msd--;         /* carried */
+         } /* bump needed */
+       } /* reround!=0 */
+      } /* remnear */
+    } /* round or truncate needed */
+  num.exponent=0;                           /* all paths */
+  /*decShowNum(&num, "int"); */
+
+  if (op&DIVIDEINT) return decFinalize(result, &num, set); /* all done */
+
+  /* Have a remainder to calculate */
+  decFinalize(&quotient, &num, set);        /* lay out the integer so far */
+  DFWORD(&quotient, 0)^=DECFLOAT_Sign;      /* negate it */
+  sign=DFWORD(dfl, 0);                      /* save sign of dfl */
+  decFloatFMA(result, &quotient, dfr, dfl, set);
+  if (!DFISZERO(result)) return result;
+  /* if the result is zero the sign shall be sign of dfl */
+  DFWORD(&quotient, 0)=sign;                /* construct decFloat of sign */
+  return decFloatCopySign(result, result, &quotient);
+  } /* decDivide */
+
+/* ------------------------------------------------------------------ */
+/* decFiniteMultiply -- multiply two finite decFloats                */
+/*                                                                   */
+/*   num    gets the result of multiplying dfl and dfr               */
+/*   bcdacc .. with the coefficient in this array                    */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*                                                                   */
+/* This effects the multiplication of two decFloats, both known to be */
+/* finite, leaving the result in a bcdnum ready for decFinalize (for  */
+/* use in Multiply) or in a following addition (FMA).                */
+/*                                                                   */
+/* bcdacc must have space for at least DECPMAX9*18+1 bytes.          */
+/* No error is possible and no status is set.                        */
+/* ------------------------------------------------------------------ */
+/* This routine has two separate implementations of the core */
+/* multiplication; both using base-billion.  One uses only 32-bit */
+/* variables (Ints and uInts) or smaller; the other uses uLongs (for */
+/* multiplication and addition only).  Both implementations cover */
+/* both arithmetic sizes (DOUBLE and QUAD) in order to allow timing */
+/* comparisons.         In any one compilation only one implementation for */
+/* each size can be used, and if DECUSE64 is 0 then use of the 32-bit */
+/* version is forced. */
+/* */
+/* Historical note: an earlier version of this code also supported the */
+/* 256-bit format and has been preserved.  That is somewhat trickier */
+/* during lazy carry splitting because the initial quotient estimate */
+/* (est) can exceed 32 bits. */
+
+#define MULTBASE  BILLION         /* the base used for multiply */
+#define MULOPLEN  DECPMAX9        /* operand length ('digits' base 10**9) */
+#define MULACCLEN (MULOPLEN*2)             /* accumulator length (ditto) */
+#define LEADZEROS (MULACCLEN*9 - DECPMAX*2) /* leading zeros always */
+
+/* Assertions: exponent not too large and MULACCLEN is a multiple of 4 */
+#if DECEMAXD>9
+  #error Exponent may overflow when doubled for Multiply
+#endif
+#if MULACCLEN!=(MULACCLEN/4)*4
+  /* This assumption is used below only for initialization */
+  #error MULACCLEN is not a multiple of 4
+#endif
+
+static void decFiniteMultiply(bcdnum *num, uByte *bcdacc,
+                             const decFloat *dfl, const decFloat *dfr) {
+  uInt  bufl[MULOPLEN];           /* left  coefficient (base-billion) */
+  uInt  bufr[MULOPLEN];           /* right coefficient (base-billion) */
+  uInt  *ui, *uj;                 /* work */
+  uByte         *ub;                      /* .. */
+
+  #if DECUSE64
+  uLong         accl[MULACCLEN];          /* lazy accumulator (base-billion+) */
+  uLong         *pl;                      /* work -> lazy accumulator */
+  uInt  acc[MULACCLEN];           /* coefficent in base-billion .. */
+  #else
+  uInt  acc[MULACCLEN*2];         /* accumulator in base-billion .. */
+  #endif
+  uInt  *pa;                      /* work -> accumulator */
+  /*printf("Base10**9: OpLen=%d MulAcclen=%d\n", OPLEN, MULACCLEN); */
+
+  /* Calculate sign and exponent */
+  num->sign=(DFWORD(dfl, 0)^DFWORD(dfr, 0)) & DECFLOAT_Sign;
+  num->exponent=GETEXPUN(dfl)+GETEXPUN(dfr); /* [see assertion above] */
+
+  /* Extract the coefficients and prepare the accumulator */
+  /* the coefficients of the operands are decoded into base-billion */
+  /* numbers in uInt arrays (bufl and bufr, LSD at offset 0) of the */
+  /* appropriate size. */
+  GETCOEFFBILL(dfl, bufl);
+  GETCOEFFBILL(dfr, bufr);
+  #if DECTRACE && 0
+    printf("CoeffbL:");
+    for (ui=bufl+MULOPLEN-1; ui>=bufl; ui--) printf(" %08lx", (LI)*ui);
+    printf("\n");
+    printf("CoeffbR:");
+    for (uj=bufr+MULOPLEN-1; uj>=bufr; uj--) printf(" %08lx", (LI)*uj);
+    printf("\n");
+  #endif
+
+  /* start the 64-bit/32-bit differing paths... */
+#if DECUSE64
+
+  /* zero the accumulator */
+  #if MULACCLEN==4
+    accl[0]=0; accl[1]=0; accl[2]=0; accl[3]=0;
+  #else                                             /* use a loop */
+    /* MULACCLEN is a multiple of four, asserted above */
+    for (pl=accl; pl<accl+MULACCLEN; pl+=4) {
+      *pl=0; *(pl+1)=0; *(pl+2)=0; *(pl+3)=0;/* [reduce overhead] */
+      } /* pl */
+  #endif
+
+  /* Effect the multiplication */
+  /* The multiplcation proceeds using MFC's lazy-carry resolution */
+  /* algorithm from decNumber. First, the multiplication is */
+  /* effected, allowing accumulation of the partial products (which */
+  /* are in base-billion at each column position) into 64 bits */
+  /* without resolving back to base=billion after each addition. */
+  /* These 64-bit numbers (which may contain up to 19 decimal digits) */
+  /* are then split using the Clark & Cowlishaw algorithm (see below). */
+  /* [Testing for 0 in the inner loop is not really a 'win'] */
+  for (ui=bufr; ui<bufr+MULOPLEN; ui++) { /* over each item in rhs */
+    if (*ui==0) continue;                /* product cannot affect result */
+    pl=accl+(ui-bufr);                   /* where to add the lhs */
+    for (uj=bufl; uj<bufl+MULOPLEN; uj++, pl++) { /* over each item in lhs */
+      /* if (*uj==0) continue;           // product cannot affect result */
+      *pl+=((uLong)*ui)*(*uj);
+      } /* uj */
+    } /* ui */
+
+  /* The 64-bit carries must now be resolved; this means that a */
+  /* quotient/remainder has to be calculated for base-billion (1E+9). */
+  /* For this, Clark & Cowlishaw's quotient estimation approach (also */
+  /* used in decNumber) is needed, because 64-bit divide is generally */
+  /* extremely slow on 32-bit machines, and may be slower than this */
+  /* approach even on 64-bit machines. This algorithm splits X */
+  /* using: */
+  /* */
+  /*   magic=2**(A+B)/1E+9;   // 'magic number' */
+  /*   hop=X/2**A;           // high order part of X (by shift) */
+  /*   est=magic*hop/2**B     // quotient estimate (may be low by 1) */
+  /* */
+  /* A and B are quite constrained; hop and magic must fit in 32 bits, */
+  /* and 2**(A+B) must be as large as possible (which is 2**61 if */
+  /* magic is to fit). Further, maxX increases with the length of */
+  /* the operands (and hence the number of partial products */
+  /* accumulated); maxX is OPLEN*(10**18), which is up to 19 digits. */
+  /* */
+  /* It can be shown that when OPLEN is 2 then the maximum error in */
+  /* the estimated quotient is <1, but for larger maximum x the */
+  /* maximum error is above 1 so a correction that is >1 may be */
+  /* needed.  Values of A and B are chosen to satisfy the constraints */
+  /* just mentioned while minimizing the maximum error (and hence the */
+  /* maximum correction), as shown in the following table: */
+  /* */
+  /*   Type    OPLEN   A   B    maxX    maxError  maxCorrection */
+  /*   --------------------------------------------------------- */
+  /*   DOUBLE   2    29  32  <2*10**18    0.63       1 */
+  /*   QUAD     4    30  31  <4*10**18    1.17       2 */
+  /* */
+  /* In the OPLEN==2 case there is most choice, but the value for B */
+  /* of 32 has a big advantage as then the calculation of the */
+  /* estimate requires no shifting; the compiler can extract the high */
+  /* word directly after multiplying magic*hop. */
+  #define MULMAGIC 2305843009U         /* 2**61/10**9  [both cases] */
+  #if DOUBLE
+    #define MULSHIFTA 29
+    #define MULSHIFTB 32
+  #elif QUAD
+    #define MULSHIFTA 30
+    #define MULSHIFTB 31
+  #else
+    #error Unexpected type
+  #endif
+
+  #if DECTRACE
+  printf("MulAccl:");
+  for (pl=accl+MULACCLEN-1; pl>=accl; pl--)
+    printf(" %08lx:%08lx", (LI)(*pl>>32), (LI)(*pl&0xffffffff));
+  printf("\n");
+  #endif
+
+  for (pl=accl, pa=acc; pl<accl+MULACCLEN; pl++, pa++) { /* each column position */
+    uInt lo, hop;                      /* work */
+    uInt est;                          /* cannot exceed 4E+9 */
+    if (*pl>MULTBASE) {
+      /* *pl holds a binary number which needs to be split */
+      hop=(uInt)(*pl>>MULSHIFTA);
+      est=(uInt)(((uLong)hop*MULMAGIC)>>MULSHIFTB);
+      /* the estimate is now in est; now calculate hi:lo-est*10**9; */
+      /* happily the top word of the result is irrelevant because it */
+      /* will always be zero so this needs only one multiplication */
+      lo=(uInt)(*pl-((uLong)est*MULTBASE));  /* low word of result */
+      /* If QUAD, the correction here could be +2 */
+      if (lo>=MULTBASE) {
+       lo-=MULTBASE;                   /* correct by +1 */
+       est++;
+       #if QUAD
+       /* may need to correct by +2 */
+       if (lo>=MULTBASE) {
+         lo-=MULTBASE;
+         est++;
+         }
+       #endif
+       }
+      /* finally place lo as the new coefficient 'digit' and add est to */
+      /* the next place up [this is safe because this path is never */
+      /* taken on the final iteration as *pl will fit] */
+      *pa=lo;
+      *(pl+1)+=est;
+      } /* *pl needed split */
+     else {                            /* *pl<MULTBASE */
+      *pa=(uInt)*pl;                   /* just copy across */
+      }
+    } /* pl loop */
+
+#else  /* 32-bit */
+  for (pa=acc;; pa+=4) {                    /* zero the accumulator */
+    *pa=0; *(pa+1)=0; *(pa+2)=0; *(pa+3)=0;  /* [reduce overhead] */
+    if (pa==acc+MULACCLEN*2-4) break;       /* multiple of 4 asserted */
+    } /* pa */
+
+  /* Effect the multiplication */
+  /* uLongs are not available (and in particular, there is no uLong */
+  /* divide) but it is still possible to use MFC's lazy-carry */
+  /* resolution algorithm from decNumber.  First, the multiplication */
+  /* is effected, allowing accumulation of the partial products */
+  /* (which are in base-billion at each column position) into 64 bits */
+  /* [with the high-order 32 bits in each position being held at */
+  /* offset +ACCLEN from the low-order 32 bits in the accumulator]. */
+  /* These 64-bit numbers (which may contain up to 19 decimal digits) */
+  /* are then split using the Clark & Cowlishaw algorithm (see */
+  /* below). */
+  for (ui=bufr;; ui++) {               /* over each item in rhs */
+    uInt hi, lo;                       /* words of exact multiply result */
+    pa=acc+(ui-bufr);                  /* where to add the lhs */
+    for (uj=bufl;; uj++, pa++) {       /* over each item in lhs */
+      LONGMUL32HI(hi, *ui, *uj);       /* calculate product of digits */
+      lo=(*ui)*(*uj);                  /* .. */
+      *pa+=lo;                         /* accumulate low bits and .. */
+      *(pa+MULACCLEN)+=hi+(*pa<lo);    /* .. high bits with any carry */
+      if (uj==bufl+MULOPLEN-1) break;
+      }
+    if (ui==bufr+MULOPLEN-1) break;
+    }
+
+  /* The 64-bit carries must now be resolved; this means that a */
+  /* quotient/remainder has to be calculated for base-billion (1E+9). */
+  /* For this, Clark & Cowlishaw's quotient estimation approach (also */
+  /* used in decNumber) is needed, because 64-bit divide is generally */
+  /* extremely slow on 32-bit machines.         This algorithm splits X */
+  /* using: */
+  /* */
+  /*   magic=2**(A+B)/1E+9;   // 'magic number' */
+  /*   hop=X/2**A;           // high order part of X (by shift) */
+  /*   est=magic*hop/2**B     // quotient estimate (may be low by 1) */
+  /* */
+  /* A and B are quite constrained; hop and magic must fit in 32 bits, */
+  /* and 2**(A+B) must be as large as possible (which is 2**61 if */
+  /* magic is to fit). Further, maxX increases with the length of */
+  /* the operands (and hence the number of partial products */
+  /* accumulated); maxX is OPLEN*(10**18), which is up to 19 digits. */
+  /* */
+  /* It can be shown that when OPLEN is 2 then the maximum error in */
+  /* the estimated quotient is <1, but for larger maximum x the */
+  /* maximum error is above 1 so a correction that is >1 may be */
+  /* needed.  Values of A and B are chosen to satisfy the constraints */
+  /* just mentioned while minimizing the maximum error (and hence the */
+  /* maximum correction), as shown in the following table: */
+  /* */
+  /*   Type    OPLEN   A   B    maxX    maxError  maxCorrection */
+  /*   --------------------------------------------------------- */
+  /*   DOUBLE   2    29  32  <2*10**18    0.63       1 */
+  /*   QUAD     4    30  31  <4*10**18    1.17       2 */
+  /* */
+  /* In the OPLEN==2 case there is most choice, but the value for B */
+  /* of 32 has a big advantage as then the calculation of the */
+  /* estimate requires no shifting; the high word is simply */
+  /* calculated from multiplying magic*hop. */
+  #define MULMAGIC 2305843009U         /* 2**61/10**9  [both cases] */
+  #if DOUBLE
+    #define MULSHIFTA 29
+    #define MULSHIFTB 32
+  #elif QUAD
+    #define MULSHIFTA 30
+    #define MULSHIFTB 31
+  #else
+    #error Unexpected type
+  #endif
+
+  #if DECTRACE
+  printf("MulHiLo:");
+  for (pa=acc+MULACCLEN-1; pa>=acc; pa--)
+    printf(" %08lx:%08lx", (LI)*(pa+MULACCLEN), (LI)*pa);
+  printf("\n");
+  #endif
+
+  for (pa=acc;; pa++) {                        /* each low uInt */
+    uInt hi, lo;                       /* words of exact multiply result */
+    uInt hop, estlo;                   /* work */
+    #if QUAD
+    uInt esthi;                                /* .. */
+    #endif
+
+    lo=*pa;
+    hi=*(pa+MULACCLEN);                        /* top 32 bits */
+    /* hi and lo now hold a binary number which needs to be split */
+
+    #if DOUBLE
+      hop=(hi<<3)+(lo>>MULSHIFTA);     /* hi:lo/2**29 */
+      LONGMUL32HI(estlo, hop, MULMAGIC);/* only need the high word */
+      /* [MULSHIFTB is 32, so estlo can be used directly] */
+      /* the estimate is now in estlo; now calculate hi:lo-est*10**9; */
+      /* happily the top word of the result is irrelevant because it */
+      /* will always be zero so this needs only one multiplication */
+      lo-=(estlo*MULTBASE);
+      /* esthi=0;                      // high word is ignored below */
+      /* the correction here will be at most +1; do it */
+      if (lo>=MULTBASE) {
+       lo-=MULTBASE;
+       estlo++;
+       }
+    #elif QUAD
+      hop=(hi<<2)+(lo>>MULSHIFTA);     /* hi:lo/2**30 */
+      LONGMUL32HI(esthi, hop, MULMAGIC);/* shift will be 31 .. */
+      estlo=hop*MULMAGIC;              /* .. so low word needed */
+      estlo=(esthi<<1)+(estlo>>MULSHIFTB); /* [just the top bit] */
+      /* esthi=0;                      // high word is ignored below */
+      lo-=(estlo*MULTBASE);            /* as above */
+      /* the correction here could be +1 or +2 */
+      if (lo>=MULTBASE) {
+       lo-=MULTBASE;
+       estlo++;
+       }
+      if (lo>=MULTBASE) {
+       lo-=MULTBASE;
+       estlo++;
+       }
+    #else
+      #error Unexpected type
+    #endif
+
+    /* finally place lo as the new accumulator digit and add est to */
+    /* the next place up; this latter add could cause a carry of 1 */
+    /* to the high word of the next place */
+    *pa=lo;
+    *(pa+1)+=estlo;
+    /* esthi is always 0 for DOUBLE and QUAD so this is skipped */
+    /* *(pa+1+MULACCLEN)+=esthi; */
+    if (*(pa+1)<estlo) *(pa+1+MULACCLEN)+=1; /* carry */
+    if (pa==acc+MULACCLEN-2) break;         /* [MULACCLEN-1 will never need split] */
+    } /* pa loop */
+#endif
+
+  /* At this point, whether using the 64-bit or the 32-bit paths, the */
+  /* accumulator now holds the (unrounded) result in base-billion; */
+  /* one base-billion 'digit' per uInt. */
+  #if DECTRACE
+  printf("MultAcc:");
+  for (pa=acc+MULACCLEN-1; pa>=acc; pa--) printf(" %09ld", (LI)*pa);
+  printf("\n");
+  #endif
+
+  /* Now convert to BCD for rounding and cleanup, starting from the */
+  /* most significant end */
+  pa=acc+MULACCLEN-1;
+  if (*pa!=0) num->msd=bcdacc+LEADZEROS;/* drop known lead zeros */
+   else {                              /* >=1 word of leading zeros */
+    num->msd=bcdacc;                   /* known leading zeros are gone */
+    pa--;                              /* skip first word .. */
+    for (; *pa==0; pa--) if (pa==acc) break; /* .. and any more leading 0s */
+    }
+  for (ub=bcdacc;; pa--, ub+=9) {
+    if (*pa!=0) {                      /* split(s) needed */
+      uInt top, mid, rem;              /* work */
+      /* *pa is non-zero -- split the base-billion acc digit into */
+      /* hi, mid, and low three-digits */
+      #define mulsplit9 1000000                /* divisor */
+      #define mulsplit6 1000           /* divisor */
+      /* The splitting is done by simple divides and remainders, */
+      /* assuming the compiler will optimize these where useful */
+      /* [GCC does] */
+      top=*pa/mulsplit9;
+      rem=*pa%mulsplit9;
+      mid=rem/mulsplit6;
+      rem=rem%mulsplit6;
+      /* lay out the nine BCD digits (plus one unwanted byte) */
+      UINTAT(ub)  =UINTAT(&BIN2BCD8[top*4]);
+      UINTAT(ub+3)=UINTAT(&BIN2BCD8[mid*4]);
+      UINTAT(ub+6)=UINTAT(&BIN2BCD8[rem*4]);
+      }
+     else {                            /* *pa==0 */
+      UINTAT(ub)=0;                    /* clear 9 BCD8s */
+      UINTAT(ub+4)=0;                  /* .. */
+      *(ub+8)=0;                       /* .. */
+      }
+    if (pa==acc) break;
+    } /* BCD conversion loop */
+
+  num->lsd=ub+8;                       /* complete the bcdnum .. */
+
+  #if DECTRACE
+  decShowNum(num, "postmult");
+  decFloatShow(dfl, "dfl");
+  decFloatShow(dfr, "dfr");
+  #endif
+  return;
+  } /* decFiniteMultiply */
+
+/* ------------------------------------------------------------------ */
+/* decFloatAbs -- absolute value, heeding NaNs, etc.                 */
+/*                                                                   */
+/*   result gets the canonicalized df with sign 0                    */
+/*   df            is the decFloat to abs                                    */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* This has the same effect as decFloatPlus unless df is negative,    */
+/* in which case it has the same effect as decFloatMinus.  The       */
+/* effect is also the same as decFloatCopyAbs except that NaNs are    */
+/* handled normally (the sign of a NaN is not affected, and an sNaN   */
+/* will signal) and the result will be canonical.                    */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatAbs(decFloat *result, const decFloat *df,
+                      decContext *set) {
+  if (DFISNAN(df)) return decNaNs(result, df, NULL, set);
+  decCanonical(result, df);            /* copy and check */
+  DFBYTE(result, 0)&=~0x80;            /* zero sign bit */
+  return result;
+  } /* decFloatAbs */
+
+/* ------------------------------------------------------------------ */
+/* decFloatAdd -- add two decFloats                                  */
+/*                                                                   */
+/*   result gets the result of adding dfl and dfr:                   */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatAdd(decFloat *result,
+                      const decFloat *dfl, const decFloat *dfr,
+                      decContext *set) {
+  bcdnum num;                     /* for final conversion */
+  Int   expl, expr;               /* left and right exponents */
+  uInt  *ui, *uj;                 /* work */
+  uByte         *ub;                      /* .. */
+
+  uInt sourhil, sourhir;          /* top words from source decFloats */
+                                  /* [valid only until specials */
+                                  /* handled or exponents decoded] */
+  uInt diffsign;                  /* non-zero if signs differ */
+  uInt carry;                     /* carry: 0 or 1 before add loop */
+  Int  overlap;                           /* coefficient overlap (if full) */
+  /* the following buffers hold coefficients with various alignments */
+  /* (see commentary and diagrams below) */
+  uByte acc[4+2+DECPMAX*3+8];
+  uByte buf[4+2+DECPMAX*2];
+  uByte *umsd, *ulsd;             /* local MSD and LSD pointers */
+
+  #if DECLITEND
+    #define CARRYPAT 0x01000000           /* carry=1 pattern */
+  #else
+    #define CARRYPAT 0x00000001           /* carry=1 pattern */
+  #endif
+
+  /* Start decoding the arguments */
+  /* the initial exponents are placed into the opposite Ints to */
+  /* that which might be expected; there are two sets of data to */
+  /* keep track of (each decFloat and the corresponding exponent), */
+  /* and this scheme means that at the swap point (after comparing */
+  /* exponents) only one pair of words needs to be swapped */
+  /* whichever path is taken (thereby minimising worst-case path) */
+  sourhil=DFWORD(dfl, 0);         /* LHS top word */
+  expr=DECCOMBEXP[sourhil>>26];           /* get exponent high bits (in place) */
+  sourhir=DFWORD(dfr, 0);         /* RHS top word */
+  expl=DECCOMBEXP[sourhir>>26];
+
+  diffsign=(sourhil^sourhir)&DECFLOAT_Sign;
+
+  if (EXPISSPECIAL(expl | expr)) { /* either is special? */
+    if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+    /* one or two infinities */
+    /* two infinities with different signs is invalid */
+    if (diffsign && DFISINF(dfl) && DFISINF(dfr))
+      return decInvalid(result, set);
+    if (DFISINF(dfl)) return decInfinity(result, dfl); /* LHS is infinite */
+    return decInfinity(result, dfr);                  /* RHS must be Infinite */
+    }
+
+  /* Here when both arguments are finite */
+
+  /* complete exponent gathering (keeping swapped) */
+  expr+=GETECON(dfl)-DECBIAS;     /* .. + continuation and unbias */
+  expl+=GETECON(dfr)-DECBIAS;
+  /* here expr has exponent from lhs, and vice versa */
+
+  /* now swap either exponents or argument pointers */
+  if (expl<=expr) {
+    /* original left is bigger */
+    Int expswap=expl;
+    expl=expr;
+    expr=expswap;
+    /* printf("left bigger\n"); */
+    }
+   else {
+    const decFloat *dfswap=dfl;
+    dfl=dfr;
+    dfr=dfswap;
+    /* printf("right bigger\n"); */
+    }
+  /* [here dfl and expl refer to the datum with the larger exponent, */
+  /* of if the exponents are equal then the original LHS argument] */
+
+  /* if lhs is zero then result will be the rhs (now known to have */
+  /* the smaller exponent), which also may need to be tested for zero */
+  /* for the weird IEEE 754 sign rules */
+  if (DFISZERO(dfl)) {
+    decCanonical(result, dfr);              /* clean copy */
+    /* "When the sum of two operands with opposite signs is */
+    /* exactly zero, the sign of that sum shall be '+' in all */
+    /* rounding modes except round toward -Infinity, in which */
+    /* mode that sign shall be '-'." */
+    if (diffsign && DFISZERO(result)) {
+      DFWORD(result, 0)&=~DECFLOAT_Sign;     /* assume sign 0 */
+      if (set->round==DEC_ROUND_FLOOR) DFWORD(result, 0)|=DECFLOAT_Sign;
+      }
+    return result;
+    } /* numfl is zero */
+  /* [here, LHS is non-zero; code below assumes that] */
+
+  /* Coefficients layout during the calculations to follow: */
+  /* */
+  /*      Overlap case: */
+  /*      +------------------------------------------------+ */
+  /* acc:  |0000|      coeffa     | tail B |               | */
+  /*      +------------------------------------------------+ */
+  /* buf:  |0000| pad0s |      coeffb      |               | */
+  /*      +------------------------------------------------+ */
+  /* */
+  /*      Touching coefficients or gap: */
+  /*      +------------------------------------------------+ */
+  /* acc:  |0000|      coeffa     | gap |      coeffb      | */
+  /*      +------------------------------------------------+ */
+  /*      [buf not used or needed; gap clamped to Pmax] */
+
+  /* lay out lhs coefficient into accumulator; this starts at acc+4 */
+  /* for decDouble or acc+6 for decQuad so the LSD is word- */
+  /* aligned; the top word gap is there only in case a carry digit */
+  /* is prefixed after the add -- it does not need to be zeroed */
+  #if DOUBLE
+    #define COFF 4                     /* offset into acc */
+  #elif QUAD
+    USHORTAT(acc+4)=0;                 /* prefix 00 */
+    #define COFF 6                     /* offset into acc */
+  #endif
+
+  GETCOEFF(dfl, acc+COFF);             /* decode from decFloat */
+  ulsd=acc+COFF+DECPMAX-1;
+  umsd=acc+4;                          /* [having this here avoids */
+                                       /* weird GCC optimizer failure] */
+  #if DECTRACE
+  {bcdnum tum;
+  tum.msd=umsd;
+  tum.lsd=ulsd;
+  tum.exponent=expl;
+  tum.sign=DFWORD(dfl, 0) & DECFLOAT_Sign;
+  decShowNum(&tum, "dflx");}
+  #endif
+
+  /* if signs differ, take ten's complement of lhs (here the */
+  /* coefficient is subtracted from all-nines; the 1 is added during */
+  /* the later add cycle -- zeros to the right do not matter because */
+  /* the complement of zero is zero); these are fixed-length inverts */
+  /* where the lsd is known to be at a 4-byte boundary (so no borrow */
+  /* possible) */
+  carry=0;                             /* assume no carry */
+  if (diffsign) {
+    carry=CARRYPAT;                    /* for +1 during add */
+    UINTAT(acc+ 4)=0x09090909-UINTAT(acc+ 4);
+    UINTAT(acc+ 8)=0x09090909-UINTAT(acc+ 8);
+    UINTAT(acc+12)=0x09090909-UINTAT(acc+12);
+    UINTAT(acc+16)=0x09090909-UINTAT(acc+16);
+    #if QUAD
+    UINTAT(acc+20)=0x09090909-UINTAT(acc+20);
+    UINTAT(acc+24)=0x09090909-UINTAT(acc+24);
+    UINTAT(acc+28)=0x09090909-UINTAT(acc+28);
+    UINTAT(acc+32)=0x09090909-UINTAT(acc+32);
+    UINTAT(acc+36)=0x09090909-UINTAT(acc+36);
+    #endif
+    } /* diffsign */
+
+  /* now process the rhs coefficient; if it cannot overlap lhs then */
+  /* it can be put straight into acc (with an appropriate gap, if */
+  /* needed) because no actual addition will be needed (except */
+  /* possibly to complete ten's complement) */
+  overlap=DECPMAX-(expl-expr);
+  #if DECTRACE
+  printf("exps: %ld %ld\n", (LI)expl, (LI)expr);
+  printf("Overlap=%ld carry=%08lx\n", (LI)overlap, (LI)carry);
+  #endif
+
+  if (overlap<=0) {                    /* no overlap possible */
+    uInt gap;                          /* local work */
+    /* since a full addition is not needed, a ten's complement */
+    /* calculation started above may need to be completed */
+    if (carry) {
+      for (ub=ulsd; *ub==9; ub--) *ub=0;
+      *ub+=1;
+      carry=0;                         /* taken care of */
+      }
+    /* up to DECPMAX-1 digits of the final result can extend down */
+    /* below the LSD of the lhs, so if the gap is >DECPMAX then the */
+    /* rhs will be simply sticky bits. In this case the gap is */
+    /* clamped to DECPMAX and the exponent adjusted to suit [this is */
+    /* safe because the lhs is non-zero]. */
+    gap=-overlap;
+    if (gap>DECPMAX) {
+      expr+=gap-1;
+      gap=DECPMAX;
+      }
+    ub=ulsd+gap+1;                     /* where MSD will go */
+    /* Fill the gap with 0s; note that there is no addition to do */
+    ui=&UINTAT(acc+COFF+DECPMAX);      /* start of gap */
+    for (; ui<&UINTAT(ub); ui++) *ui=0; /* mind the gap */
+    if (overlap<-DECPMAX) {            /* gap was > DECPMAX */
+      *ub=(uByte)(!DFISZERO(dfr));     /* make sticky digit */
+      }
+     else {                            /* need full coefficient */
+      GETCOEFF(dfr, ub);               /* decode from decFloat */
+      ub+=DECPMAX-1;                   /* new LSD... */
+      }
+    ulsd=ub;                           /* save new LSD */
+    } /* no overlap possible */
+
+   else {                              /* overlap>0 */
+    /* coefficients overlap (perhaps completely, although also */
+    /* perhaps only where zeros) */
+    ub=buf+COFF+DECPMAX-overlap;       /* where MSD will go */
+    /* Fill the prefix gap with 0s; 8 will cover most common */
+    /* unalignments, so start with direct assignments (a loop is */
+    /* then used for any remaining -- the loop (and the one in a */
+    /* moment) is not then on the critical path because the number */
+    /* of additions is reduced by (at least) two in this case) */
+    UINTAT(buf+4)=0;                   /* [clears decQuad 00 too] */
+    UINTAT(buf+8)=0;
+    if (ub>buf+12) {
+      ui=&UINTAT(buf+12);              /* start of any remaining */
+      for (; ui<&UINTAT(ub); ui++) *ui=0; /* fill them */
+      }
+    GETCOEFF(dfr, ub);                 /* decode from decFloat */
+
+    /* now move tail of rhs across to main acc; again use direct */
+    /* assignment for 8 digits-worth */
+    UINTAT(acc+COFF+DECPMAX)=UINTAT(buf+COFF+DECPMAX);
+    UINTAT(acc+COFF+DECPMAX+4)=UINTAT(buf+COFF+DECPMAX+4);
+    if (buf+COFF+DECPMAX+8<ub+DECPMAX) {
+      uj=&UINTAT(buf+COFF+DECPMAX+8);  /* source */
+      ui=&UINTAT(acc+COFF+DECPMAX+8);  /* target */
+      for (; uj<&UINTAT(ub+DECPMAX); ui++, uj++) *ui=*uj;
+      }
+
+    ulsd=acc+(ub-buf+DECPMAX-1);       /* update LSD pointer */
+
+    /* now do the add of the non-tail; this is all nicely aligned, */
+    /* and is over a multiple of four digits (because for Quad two */
+    /* two 0 digits were added on the left); words in both acc and */
+    /* buf (buf especially) will often be zero */
+    /* [byte-by-byte add, here, is about 15% slower than the by-fours] */
+
+    /* Now effect the add; this is harder on a little-endian */
+    /* machine as the inter-digit carry cannot use the usual BCD */
+    /* addition trick because the bytes are loaded in the wrong order */
+    /* [this loop could be unrolled, but probably scarcely worth it] */
+
+    ui=&UINTAT(acc+COFF+DECPMAX-4);    /* target LSW (acc) */
+    uj=&UINTAT(buf+COFF+DECPMAX-4);    /* source LSW (buf, to add to acc) */
+
+    #if !DECLITEND
+    for (; ui>=&UINTAT(acc+4); ui--, uj--) {
+      /* bcd8 add */
+      carry+=*uj;                      /* rhs + carry */
+      if (carry==0) continue;          /* no-op */
+      carry+=*ui;                      /* lhs */
+      /* Big-endian BCD adjust (uses internal carry) */
+      carry+=0x76f6f6f6;               /* note top nibble not all bits */
+      *ui=(carry & 0x0f0f0f0f) - ((carry & 0x60606060)>>4); /* BCD adjust */
+      carry>>=31;                      /* true carry was at far left */
+      } /* add loop */
+    #else
+    for (; ui>=&UINTAT(acc+4); ui--, uj--) {
+      /* bcd8 add */
+      carry+=*uj;                      /* rhs + carry */
+      if (carry==0) continue;          /* no-op [common if unaligned] */
+      carry+=*ui;                      /* lhs */
+      /* Little-endian BCD adjust; inter-digit carry must be manual */
+      /* because the lsb from the array will be in the most-significant */
+      /* byte of carry */
+      carry+=0x76767676;               /* note no inter-byte carries */
+      carry+=(carry & 0x80000000)>>15;
+      carry+=(carry & 0x00800000)>>15;
+      carry+=(carry & 0x00008000)>>15;
+      carry-=(carry & 0x60606060)>>4;  /* BCD adjust back */
+      *ui=carry & 0x0f0f0f0f;          /* clear debris and save */
+      /* here, final carry-out bit is at 0x00000080; move it ready */
+      /* for next word-add (i.e., to 0x01000000) */
+      carry=(carry & 0x00000080)<<17;
+      } /* add loop */
+    #endif
+    #if DECTRACE
+    {bcdnum tum;
+    printf("Add done, carry=%08lx, diffsign=%ld\n", (LI)carry, (LI)diffsign);
+    tum.msd=umsd;  /* acc+4; */
+    tum.lsd=ulsd;
+    tum.exponent=0;
+    tum.sign=0;
+    decShowNum(&tum, "dfadd");}
+    #endif
+    } /* overlap possible */
+
+  /* ordering here is a little strange in order to have slowest path */
+  /* first in GCC asm listing */
+  if (diffsign) {                 /* subtraction */
+    if (!carry) {                 /* no carry out means RHS<LHS */
+      /* borrowed -- take ten's complement */
+      /* sign is lhs sign */
+      num.sign=DFWORD(dfl, 0) & DECFLOAT_Sign;
+
+      /* invert the coefficient first by fours, then add one; space */
+      /* at the end of the buffer ensures the by-fours is always */
+      /* safe, but lsd+1 must be cleared to prevent a borrow */
+      /* if big-endian */
+      #if !DECLITEND
+      *(ulsd+1)=0;
+      #endif
+      /* there are always at least four coefficient words */
+      UINTAT(umsd)   =0x09090909-UINTAT(umsd);
+      UINTAT(umsd+4) =0x09090909-UINTAT(umsd+4);
+      UINTAT(umsd+8) =0x09090909-UINTAT(umsd+8);
+      UINTAT(umsd+12)=0x09090909-UINTAT(umsd+12);
+      #if DOUBLE
+       #define BNEXT 16
+      #elif QUAD
+       UINTAT(umsd+16)=0x09090909-UINTAT(umsd+16);
+       UINTAT(umsd+20)=0x09090909-UINTAT(umsd+20);
+       UINTAT(umsd+24)=0x09090909-UINTAT(umsd+24);
+       UINTAT(umsd+28)=0x09090909-UINTAT(umsd+28);
+       UINTAT(umsd+32)=0x09090909-UINTAT(umsd+32);
+       #define BNEXT 36
+      #endif
+      if (ulsd>=umsd+BNEXT) {          /* unaligned */
+       /* eight will handle most unaligments for Double; 16 for Quad */
+       UINTAT(umsd+BNEXT)=0x09090909-UINTAT(umsd+BNEXT);
+       UINTAT(umsd+BNEXT+4)=0x09090909-UINTAT(umsd+BNEXT+4);
+       #if DOUBLE
+       #define BNEXTY (BNEXT+8)
+       #elif QUAD
+       UINTAT(umsd+BNEXT+8)=0x09090909-UINTAT(umsd+BNEXT+8);
+       UINTAT(umsd+BNEXT+12)=0x09090909-UINTAT(umsd+BNEXT+12);
+       #define BNEXTY (BNEXT+16)
+       #endif
+       if (ulsd>=umsd+BNEXTY) {        /* very unaligned */
+         ui=&UINTAT(umsd+BNEXTY);      /* -> continue */
+         for (;;ui++) {
+           *ui=0x09090909-*ui;         /* invert four digits */
+           if (ui>=&UINTAT(ulsd-3)) break; /* all done */
+           }
+         }
+       }
+      /* complete the ten's complement by adding 1 */
+      for (ub=ulsd; *ub==9; ub--) *ub=0;
+      *ub+=1;
+      } /* borrowed */
+
+     else {                       /* carry out means RHS>=LHS */
+      num.sign=DFWORD(dfr, 0) & DECFLOAT_Sign;
+      /* all done except for the special IEEE 754 exact-zero-result */
+      /* rule (see above); while testing for zero, strip leading */
+      /* zeros (which will save decFinalize doing it) (this is in */
+      /* diffsign path, so carry impossible and true umsd is */
+      /* acc+COFF) */
+
+      /* Check the initial coefficient area using the fast macro; */
+      /* this will often be all that needs to be done (as on the */
+      /* worst-case path when the subtraction was aligned and */
+      /* full-length) */
+      if (ISCOEFFZERO(acc+COFF)) {
+       umsd=acc+COFF+DECPMAX-1;   /* so far, so zero */
+       if (ulsd>umsd) {           /* more to check */
+         umsd++;                  /* to align after checked area */
+         for (; UINTAT(umsd)==0 && umsd+3<ulsd;) umsd+=4;
+         for (; *umsd==0 && umsd<ulsd;) umsd++;
+         }
+       if (*umsd==0) {            /* must be true zero (and diffsign) */
+         num.sign=0;              /* assume + */
+         if (set->round==DEC_ROUND_FLOOR) num.sign=DECFLOAT_Sign;
+         }
+       }
+      /* [else was not zero, might still have leading zeros] */
+      } /* subtraction gave positive result */
+    } /* diffsign */
+
+   else { /* same-sign addition */
+    num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign;
+    #if DOUBLE
+    if (carry) {                  /* only possible with decDouble */
+      *(acc+3)=1;                 /* [Quad has leading 00] */
+      umsd=acc+3;
+      }
+    #endif
+    } /* same sign */
+
+  num.msd=umsd;                           /* set MSD .. */
+  num.lsd=ulsd;                           /* .. and LSD */
+  num.exponent=expr;              /* set exponent to smaller */
+
+  #if DECTRACE
+  decFloatShow(dfl, "dfl");
+  decFloatShow(dfr, "dfr");
+  decShowNum(&num, "postadd");
+  #endif
+  return decFinalize(result, &num, set); /* round, check, and lay out */
+  } /* decFloatAdd */
+
+/* ------------------------------------------------------------------ */
+/* decFloatAnd -- logical digitwise AND of two decFloats             */
+/*                                                                   */
+/*   result gets the result of ANDing dfl and dfr                    */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result, which will be canonical with sign=0             */
+/*                                                                   */
+/* The operands must be positive, finite with exponent q=0, and              */
+/* comprise just zeros and ones; if not, Invalid operation results.   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatAnd(decFloat *result,
+                      const decFloat *dfl, const decFloat *dfr,
+                      decContext *set) {
+  if (!DFISUINT01(dfl) || !DFISUINT01(dfr)
+   || !DFISCC01(dfl)   || !DFISCC01(dfr)) return decInvalid(result, set);
+  /* the operands are positive finite integers (q=0) with just 0s and 1s */
+  #if DOUBLE
+   DFWORD(result, 0)=ZEROWORD
+                  |((DFWORD(dfl, 0) & DFWORD(dfr, 0))&0x04009124);
+   DFWORD(result, 1)=(DFWORD(dfl, 1) & DFWORD(dfr, 1))&0x49124491;
+  #elif QUAD
+   DFWORD(result, 0)=ZEROWORD
+                  |((DFWORD(dfl, 0) & DFWORD(dfr, 0))&0x04000912);
+   DFWORD(result, 1)=(DFWORD(dfl, 1) & DFWORD(dfr, 1))&0x44912449;
+   DFWORD(result, 2)=(DFWORD(dfl, 2) & DFWORD(dfr, 2))&0x12449124;
+   DFWORD(result, 3)=(DFWORD(dfl, 3) & DFWORD(dfr, 3))&0x49124491;
+  #endif
+  return result;
+  } /* decFloatAnd */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCanonical -- copy a decFloat, making canonical            */
+/*                                                                   */
+/*   result gets the canonicalized df                                */
+/*   df            is the decFloat to copy and make canonical                */
+/*   returns result                                                  */
+/*                                                                   */
+/* This works on specials, too; no error or exception is possible.    */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCanonical(decFloat *result, const decFloat *df) {
+  return decCanonical(result, df);
+  } /* decFloatCanonical */
+
+/* ------------------------------------------------------------------ */
+/* decFloatClass -- return the class of a decFloat                   */
+/*                                                                   */
+/*   df is the decFloat to test                                              */
+/*   returns the decClass that df falls into                         */
+/* ------------------------------------------------------------------ */
+enum decClass decFloatClass(const decFloat *df) {
+  Int exp;                        /* exponent */
+  if (DFISSPECIAL(df)) {
+    if (DFISQNAN(df)) return DEC_CLASS_QNAN;
+    if (DFISSNAN(df)) return DEC_CLASS_SNAN;
+    /* must be an infinity */
+    if (DFISSIGNED(df)) return DEC_CLASS_NEG_INF;
+    return DEC_CLASS_POS_INF;
+    }
+  if (DFISZERO(df)) {             /* quite common */
+    if (DFISSIGNED(df)) return DEC_CLASS_NEG_ZERO;
+    return DEC_CLASS_POS_ZERO;
+    }
+  /* is finite and non-zero; similar code to decFloatIsNormal, here */
+  /* [this could be speeded up slightly by in-lining decFloatDigits] */
+  exp=GETEXPUN(df)                /* get unbiased exponent .. */
+     +decFloatDigits(df)-1;       /* .. and make adjusted exponent */
+  if (exp>=DECEMIN) {             /* is normal */
+    if (DFISSIGNED(df)) return DEC_CLASS_NEG_NORMAL;
+    return DEC_CLASS_POS_NORMAL;
+    }
+  /* is subnormal */
+  if (DFISSIGNED(df)) return DEC_CLASS_NEG_SUBNORMAL;
+  return DEC_CLASS_POS_SUBNORMAL;
+  } /* decFloatClass */
+
+/* ------------------------------------------------------------------ */
+/* decFloatClassString -- return the class of a decFloat as a string  */
+/*                                                                   */
+/*   df is the decFloat to test                                              */
+/*   returns a constant string describing the class df falls into     */
+/* ------------------------------------------------------------------ */
+const char *decFloatClassString(const decFloat *df) {
+  enum decClass eclass=decFloatClass(df);
+  if (eclass==DEC_CLASS_POS_NORMAL)    return DEC_ClassString_PN;
+  if (eclass==DEC_CLASS_NEG_NORMAL)    return DEC_ClassString_NN;
+  if (eclass==DEC_CLASS_POS_ZERO)      return DEC_ClassString_PZ;
+  if (eclass==DEC_CLASS_NEG_ZERO)      return DEC_ClassString_NZ;
+  if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS;
+  if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS;
+  if (eclass==DEC_CLASS_POS_INF)       return DEC_ClassString_PI;
+  if (eclass==DEC_CLASS_NEG_INF)       return DEC_ClassString_NI;
+  if (eclass==DEC_CLASS_QNAN)         return DEC_ClassString_QN;
+  if (eclass==DEC_CLASS_SNAN)         return DEC_ClassString_SN;
+  return DEC_ClassString_UN;          /* Unknown */
+  } /* decFloatClassString */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCompare -- compare two decFloats; quiet NaNs allowed              */
+/*                                                                   */
+/*   result gets the result of comparing dfl and dfr                 */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result, which may be -1, 0, 1, or NaN (Unordered)       */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCompare(decFloat *result,
+                          const decFloat *dfl, const decFloat *dfr,
+                          decContext *set) {
+  Int comp;                                 /* work */
+  /* NaNs are handled as usual */
+  if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+  /* numeric comparison needed */
+  comp=decNumCompare(dfl, dfr, 0);
+  decFloatZero(result);
+  if (comp==0) return result;
+  DFBYTE(result, DECBYTES-1)=0x01;     /* LSD=1 */
+  if (comp<0) DFBYTE(result, 0)|=0x80; /* set sign bit */
+  return result;
+  } /* decFloatCompare */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCompareSignal -- compare two decFloats; all NaNs signal    */
+/*                                                                   */
+/*   result gets the result of comparing dfl and dfr                 */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result, which may be -1, 0, 1, or NaN (Unordered)       */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCompareSignal(decFloat *result,
+                                const decFloat *dfl, const decFloat *dfr,
+                                decContext *set) {
+  Int comp;                                 /* work */
+  /* NaNs are handled as usual, except that all NaNs signal */
+  if (DFISNAN(dfl) || DFISNAN(dfr)) {
+    set->status|=DEC_Invalid_operation;
+    return decNaNs(result, dfl, dfr, set);
+    }
+  /* numeric comparison needed */
+  comp=decNumCompare(dfl, dfr, 0);
+  decFloatZero(result);
+  if (comp==0) return result;
+  DFBYTE(result, DECBYTES-1)=0x01;     /* LSD=1 */
+  if (comp<0) DFBYTE(result, 0)|=0x80; /* set sign bit */
+  return result;
+  } /* decFloatCompareSignal */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCompareTotal -- compare two decFloats with total ordering  */
+/*                                                                   */
+/*   result gets the result of comparing dfl and dfr                 */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   returns result, which may be -1, 0, or 1                        */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCompareTotal(decFloat *result,
+                               const decFloat *dfl, const decFloat *dfr) {
+  Int comp;                                 /* work */
+  if (DFISNAN(dfl) || DFISNAN(dfr)) {
+    Int nanl, nanr;                         /* work */
+    /* morph NaNs to +/- 1 or 2, leave numbers as 0 */
+    nanl=DFISSNAN(dfl)+DFISQNAN(dfl)*2;             /* quiet > signalling */
+    if (DFISSIGNED(dfl)) nanl=-nanl;
+    nanr=DFISSNAN(dfr)+DFISQNAN(dfr)*2;
+    if (DFISSIGNED(dfr)) nanr=-nanr;
+    if (nanl>nanr) comp=+1;
+     else if (nanl<nanr) comp=-1;
+     else { /* NaNs are the same type and sign .. must compare payload */
+      /* buffers need +2 for QUAD */
+      uByte bufl[DECPMAX+4];                /* for LHS coefficient + foot */
+      uByte bufr[DECPMAX+4];                /* for RHS coefficient + foot */
+      uByte *ub, *uc;                       /* work */
+      Int sigl;                                     /* signum of LHS */
+      sigl=(DFISSIGNED(dfl) ? -1 : +1);
+
+      /* decode the coefficients */
+      /* (shift both right two if Quad to make a multiple of four) */
+      #if QUAD
+       USHORTAT(bufl)=0;
+       USHORTAT(bufr)=0;
+      #endif
+      GETCOEFF(dfl, bufl+QUAD*2);           /* decode from decFloat */
+      GETCOEFF(dfr, bufr+QUAD*2);           /* .. */
+      /* all multiples of four, here */
+      comp=0;                               /* assume equal */
+      for (ub=bufl, uc=bufr; ub<bufl+DECPMAX+QUAD*2; ub+=4, uc+=4) {
+       if (UINTAT(ub)==UINTAT(uc)) continue; /* so far so same */
+       /* about to find a winner; go by bytes in case little-endian */
+       for (;; ub++, uc++) {
+         if (*ub==*uc) continue;
+         if (*ub>*uc) comp=sigl;            /* difference found */
+          else comp=-sigl;                  /* .. */
+          break;
+         }
+       }
+      } /* same NaN type and sign */
+    }
+   else {
+    /* numeric comparison needed */
+    comp=decNumCompare(dfl, dfr, 1);   /* total ordering */
+    }
+  decFloatZero(result);
+  if (comp==0) return result;
+  DFBYTE(result, DECBYTES-1)=0x01;     /* LSD=1 */
+  if (comp<0) DFBYTE(result, 0)|=0x80; /* set sign bit */
+  return result;
+  } /* decFloatCompareTotal */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCompareTotalMag -- compare magnitudes with total ordering  */
+/*                                                                   */
+/*   result gets the result of comparing abs(dfl) and abs(dfr)       */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   returns result, which may be -1, 0, or 1                        */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCompareTotalMag(decFloat *result,
+                               const decFloat *dfl, const decFloat *dfr) {
+  decFloat a, b;                       /* for copy if needed */
+  /* copy and redirect signed operand(s) */
+  if (DFISSIGNED(dfl)) {
+    decFloatCopyAbs(&a, dfl);
+    dfl=&a;
+    }
+  if (DFISSIGNED(dfr)) {
+    decFloatCopyAbs(&b, dfr);
+    dfr=&b;
+    }
+  return decFloatCompareTotal(result, dfl, dfr);
+  } /* decFloatCompareTotalMag */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCopy -- copy a decFloat as-is                             */
+/*                                                                   */
+/*   result gets the copy of dfl                                     */
+/*   dfl    is the decFloat to copy                                  */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is a bitwise operation; no errors or exceptions are possible. */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCopy(decFloat *result, const decFloat *dfl) {
+  if (dfl!=result) *result=*dfl;            /* copy needed */
+  return result;
+  } /* decFloatCopy */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCopyAbs -- copy a decFloat as-is and set sign bit to 0     */
+/*                                                                   */
+/*   result gets the copy of dfl with sign bit 0                     */
+/*   dfl    is the decFloat to copy                                  */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is a bitwise operation; no errors or exceptions are possible. */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCopyAbs(decFloat *result, const decFloat *dfl) {
+  if (dfl!=result) *result=*dfl;       /* copy needed */
+  DFBYTE(result, 0)&=~0x80;            /* zero sign bit */
+  return result;
+  } /* decFloatCopyAbs */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCopyNegate -- copy a decFloat as-is with inverted sign bit */
+/*                                                                   */
+/*   result gets the copy of dfl with sign bit inverted                      */
+/*   dfl    is the decFloat to copy                                  */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is a bitwise operation; no errors or exceptions are possible. */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCopyNegate(decFloat *result, const decFloat *dfl) {
+  if (dfl!=result) *result=*dfl;       /* copy needed */
+  DFBYTE(result, 0)^=0x80;             /* invert sign bit */
+  return result;
+  } /* decFloatCopyNegate */
+
+/* ------------------------------------------------------------------ */
+/* decFloatCopySign -- copy a decFloat with the sign of another              */
+/*                                                                   */
+/*   result gets the result of copying dfl with the sign of dfr              */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is a bitwise operation; no errors or exceptions are possible. */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatCopySign(decFloat *result,
+                           const decFloat *dfl, const decFloat *dfr) {
+  uByte sign=(uByte)(DFBYTE(dfr, 0)&0x80);   /* save sign bit */
+  if (dfl!=result) *result=*dfl;            /* copy needed */
+  DFBYTE(result, 0)&=~0x80;                 /* clear sign .. */
+  DFBYTE(result, 0)=(uByte)(DFBYTE(result, 0)|sign); /* .. and set saved */
+  return result;
+  } /* decFloatCopySign */
+
+/* ------------------------------------------------------------------ */
+/* decFloatDigits -- return the number of digits in a decFloat       */
+/*                                                                   */
+/*   df is the decFloat to investigate                               */
+/*   returns the number of significant digits in the decFloat; a      */
+/*     zero coefficient returns 1 as does an infinity (a NaN returns  */
+/*     the number of digits in the payload)                          */
+/* ------------------------------------------------------------------ */
+/* private macro to extract a declet according to provided formula */
+/* (form), and if it is non-zero then return the calculated digits */
+/* depending on the declet number (n), where n=0 for the most */
+/* significant declet; uses uInt dpd for work */
+#define dpdlenchk(n, form) {dpd=(form)&0x3ff;    \
+  if (dpd) return (DECPMAX-1-3*(n))-(3-DPD2BCD8[dpd*4+3]);}
+/* next one is used when it is known that the declet must be */
+/* non-zero, or is the final zero declet */
+#define dpdlendun(n, form) {dpd=(form)&0x3ff;    \
+  if (dpd==0) return 1;                                  \
+  return (DECPMAX-1-3*(n))-(3-DPD2BCD8[dpd*4+3]);}
+
+uInt decFloatDigits(const decFloat *df) {
+  uInt dpd;                       /* work */
+  uInt sourhi=DFWORD(df, 0);      /* top word from source decFloat */
+  #if QUAD
+  uInt sourmh, sourml;
+  #endif
+  uInt sourlo;
+
+  if (DFISINF(df)) return 1;
+  /* A NaN effectively has an MSD of 0; otherwise if non-zero MSD */
+  /* then the coefficient is full-length */
+  if (!DFISNAN(df) && DECCOMBMSD[sourhi>>26]) return DECPMAX;
+
+  #if DOUBLE
+    if (sourhi&0x0003ffff) {    /* ends in first */
+      dpdlenchk(0, sourhi>>8);
+      sourlo=DFWORD(df, 1);
+      dpdlendun(1, (sourhi<<2) | (sourlo>>30));
+      } /* [cannot drop through] */
+    sourlo=DFWORD(df, 1);  /* sourhi not involved now */
+    if (sourlo&0xfff00000) {    /* in one of first two */
+      dpdlenchk(1, sourlo>>30);         /* very rare */
+      dpdlendun(2, sourlo>>20);
+      } /* [cannot drop through] */
+    dpdlenchk(3, sourlo>>10);
+    dpdlendun(4, sourlo);
+    /* [cannot drop through] */
+
+  #elif QUAD
+    if (sourhi&0x00003fff) {    /* ends in first */
+      dpdlenchk(0, sourhi>>4);
+      sourmh=DFWORD(df, 1);
+      dpdlendun(1, ((sourhi)<<6) | (sourmh>>26));
+      } /* [cannot drop through] */
+    sourmh=DFWORD(df, 1);
+    if (sourmh) {
+      dpdlenchk(1, sourmh>>26);
+      dpdlenchk(2, sourmh>>16);
+      dpdlenchk(3, sourmh>>6);
+      sourml=DFWORD(df, 2);
+      dpdlendun(4, ((sourmh)<<4) | (sourml>>28));
+      } /* [cannot drop through] */
+    sourml=DFWORD(df, 2);
+    if (sourml) {
+      dpdlenchk(4, sourml>>28);
+      dpdlenchk(5, sourml>>18);
+      dpdlenchk(6, sourml>>8);
+      sourlo=DFWORD(df, 3);
+      dpdlendun(7, ((sourml)<<2) | (sourlo>>30));
+      } /* [cannot drop through] */
+    sourlo=DFWORD(df, 3);
+    if (sourlo&0xfff00000) {    /* in one of first two */
+      dpdlenchk(7, sourlo>>30);         /* very rare */
+      dpdlendun(8, sourlo>>20);
+      } /* [cannot drop through] */
+    dpdlenchk(9, sourlo>>10);
+    dpdlendun(10, sourlo);
+    /* [cannot drop through] */
+  #endif
+  } /* decFloatDigits */
+
+/* ------------------------------------------------------------------ */
+/* decFloatDivide -- divide a decFloat by another                    */
+/*                                                                   */
+/*   result gets the result of dividing dfl by dfr:                  */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+/* This is just a wrapper. */
+decFloat * decFloatDivide(decFloat *result,
+                         const decFloat *dfl, const decFloat *dfr,
+                         decContext *set) {
+  return decDivide(result, dfl, dfr, set, DIVIDE);
+  } /* decFloatDivide */
+
+/* ------------------------------------------------------------------ */
+/* decFloatDivideInteger -- integer divide a decFloat by another      */
+/*                                                                   */
+/*   result gets the result of dividing dfl by dfr:                  */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatDivideInteger(decFloat *result,
+                            const decFloat *dfl, const decFloat *dfr,
+                            decContext *set) {
+  return decDivide(result, dfl, dfr, set, DIVIDEINT);
+  } /* decFloatDivideInteger */
+
+/* ------------------------------------------------------------------ */
+/* decFloatFMA -- multiply and add three decFloats, fused            */
+/*                                                                   */
+/*   result gets the result of (dfl*dfr)+dff with a single rounding   */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   dff    is the final decFloat (fhs)                                      */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatFMA(decFloat *result, const decFloat *dfl,
+                      const decFloat *dfr, const decFloat *dff,
+                      decContext *set) {
+  /* The accumulator has the bytes needed for FiniteMultiply, plus */
+  /* one byte to the left in case of carry, plus DECPMAX+2 to the */
+  /* right for the final addition (up to full fhs + round & sticky) */
+  #define FMALEN (1+ (DECPMAX9*18) +DECPMAX+2)
+  uByte         acc[FMALEN];              /* for multiplied coefficient in BCD */
+                                  /* .. and for final result */
+  bcdnum mul;                     /* for multiplication result */
+  bcdnum fin;                     /* for final operand, expanded */
+  uByte         coe[DECPMAX];             /* dff coefficient in BCD */
+  bcdnum *hi, *lo;                /* bcdnum with higher/lower exponent */
+  uInt  diffsign;                 /* non-zero if signs differ */
+  uInt  hipad;                    /* pad digit for hi if needed */
+  Int   padding;                  /* excess exponent */
+  uInt  carry;                    /* +1 for ten's complement and during add */
+  uByte         *ub, *uh, *ul;            /* work */
+
+  /* handle all the special values [any special operand leads to a */
+  /* special result] */
+  if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr) || DFISSPECIAL(dff)) {
+    decFloat proxy;               /* multiplication result proxy */
+    /* NaNs are handled as usual, giving priority to sNaNs */
+    if (DFISSNAN(dfl) || DFISSNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+    if (DFISSNAN(dff)) return decNaNs(result, dff, NULL, set);
+    if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+    if (DFISNAN(dff)) return decNaNs(result, dff, NULL, set);
+    /* One or more of the three is infinite */
+    /* infinity times zero is bad */
+    decFloatZero(&proxy);
+    if (DFISINF(dfl)) {
+      if (DFISZERO(dfr)) return decInvalid(result, set);
+      decInfinity(&proxy, &proxy);
+      }
+     else if (DFISINF(dfr)) {
+      if (DFISZERO(dfl)) return decInvalid(result, set);
+      decInfinity(&proxy, &proxy);
+      }
+    /* compute sign of multiplication and place in proxy */
+    DFWORD(&proxy, 0)|=(DFWORD(dfl, 0)^DFWORD(dfr, 0))&DECFLOAT_Sign;
+    if (!DFISINF(dff)) return decFloatCopy(result, &proxy);
+    /* dff is Infinite */
+    if (!DFISINF(&proxy)) return decInfinity(result, dff);
+    /* both sides of addition are infinite; different sign is bad */
+    if ((DFWORD(dff, 0)&DECFLOAT_Sign)!=(DFWORD(&proxy, 0)&DECFLOAT_Sign))
+      return decInvalid(result, set);
+    return decFloatCopy(result, &proxy);
+    }
+
+  /* Here when all operands are finite */
+
+  /* First multiply dfl*dfr */
+  decFiniteMultiply(&mul, acc+1, dfl, dfr);
+  /* The multiply is complete, exact and unbounded, and described in */
+  /* mul with the coefficient held in acc[1...] */
+
+  /* now add in dff; the algorithm is essentially the same as */
+  /* decFloatAdd, but the code is different because the code there */
+  /* is highly optimized for adding two numbers of the same size */
+  fin.exponent=GETEXPUN(dff);          /* get dff exponent and sign */
+  fin.sign=DFWORD(dff, 0)&DECFLOAT_Sign;
+  diffsign=mul.sign^fin.sign;          /* note if signs differ */
+  fin.msd=coe;
+  fin.lsd=coe+DECPMAX-1;
+  GETCOEFF(dff, coe);                  /* extract the coefficient */
+
+  /* now set hi and lo so that hi points to whichever of mul and fin */
+  /* has the higher exponent and lo point to the other [don't care if */
+  /* the same] */
+  if (mul.exponent>=fin.exponent) {
+    hi=&mul;
+    lo=&fin;
+    }
+   else {
+    hi=&fin;
+    lo=&mul;
+    }
+
+  /* remove leading zeros on both operands; this will save time later */
+  /* and make testing for zero trivial */
+  for (; UINTAT(hi->msd)==0 && hi->msd+3<hi->lsd;) hi->msd+=4;
+  for (; *hi->msd==0 && hi->msd<hi->lsd;) hi->msd++;
+  for (; UINTAT(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4;
+  for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++;
+
+  /* if hi is zero then result will be lo (which has the smaller */
+  /* exponent), which also may need to be tested for zero for the */
+  /* weird IEEE 754 sign rules */
+  if (*hi->msd==0 && hi->msd==hi->lsd) {     /* hi is zero */
+    /* "When the sum of two operands with opposite signs is */
+    /* exactly zero, the sign of that sum shall be '+' in all */
+    /* rounding modes except round toward -Infinity, in which */
+    /* mode that sign shall be '-'." */
+    if (diffsign) {
+      if (*lo->msd==0 && lo->msd==lo->lsd) { /* lo is zero */
+       lo->sign=0;
+       if (set->round==DEC_ROUND_FLOOR) lo->sign=DECFLOAT_Sign;
+       } /* diffsign && lo=0 */
+      } /* diffsign */
+    return decFinalize(result, lo, set);     /* may need clamping */
+    } /* numfl is zero */
+  /* [here, both are minimal length and hi is non-zero] */
+
+  /* if signs differ, take the ten's complement of hi (zeros to the */
+  /* right do not matter because the complement of zero is zero); */
+  /* the +1 is done later, as part of the addition, inserted at the */
+  /* correct digit */
+  hipad=0;
+  carry=0;
+  if (diffsign) {
+    hipad=9;
+    carry=1;
+    /* exactly the correct number of digits must be inverted */
+    for (uh=hi->msd; uh<hi->lsd-3; uh+=4) UINTAT(uh)=0x09090909-UINTAT(uh);
+    for (; uh<=hi->lsd; uh++) *uh=(uByte)(0x09-*uh);
+    }
+
+  /* ready to add; note that hi has no leading zeros so gap */
+  /* calculation does not have to be as pessimistic as in decFloatAdd */
+  /* (this is much more like the arbitrary-precision algorithm in */
+  /* Rexx and decNumber) */
+
+  /* padding is the number of zeros that would need to be added to hi */
+  /* for its lsd to be aligned with the lsd of lo */
+  padding=hi->exponent-lo->exponent;
+  /* printf("FMA pad %ld\n", (LI)padding); */
+
+  /* the result of the addition will be built into the accumulator, */
+  /* starting from the far right; this could be either hi or lo */
+  ub=acc+FMALEN-1;                /* where lsd of result will go */
+  ul=lo->lsd;                     /* lsd of rhs */
+
+  if (padding!=0) {               /* unaligned */
+    /* if the msd of lo is more than DECPMAX+2 digits to the right of */
+    /* the original msd of hi then it can be reduced to a single */
+    /* digit at the right place, as it stays clear of hi digits */
+    /* [it must be DECPMAX+2 because during a subtraction the msd */
+    /* could become 0 after a borrow from 1.000 to 0.9999...] */
+    Int hilen=(Int)(hi->lsd-hi->msd+1); /* lengths */
+    Int lolen=(Int)(lo->lsd-lo->msd+1); /* .. */
+    Int newexp=MINI(hi->exponent, hi->exponent+hilen-DECPMAX)-3;
+    Int reduce=newexp-lo->exponent;
+    if (reduce>0) {                    /* [= case gives reduce=0 nop] */
+      /* printf("FMA reduce: %ld\n", (LI)reduce); */
+      if (reduce>=lolen) {             /* eating all */
+       lo->lsd=lo->msd;                /* reduce to single digit */
+       lo->exponent=newexp;            /* [known to be non-zero] */
+       }
+       else { /* < */
+       uByte *up=lo->lsd;
+       lo->lsd=lo->lsd-reduce;
+       if (*lo->lsd==0)                /* could need sticky bit */
+        for (; up>lo->lsd; up--) {     /* search discarded digits */
+         if (*up!=0) {                 /* found one... */
+           *lo->lsd=1;                 /* set sticky bit */
+           break;
+           }
+         }
+       lo->exponent+=reduce;
+       }
+      padding=hi->exponent-lo->exponent; /* recalculate */
+      ul=lo->lsd;                       /* .. */
+      } /* maybe reduce */
+    /* padding is now <= DECPMAX+2 but still > 0; tricky DOUBLE case */
+    /* is when hi is a 1 that will become a 0.9999... by subtraction: */
+    /*  hi:   1                                   E+16 */
+    /*  lo:    .................1000000000000000  E-16 */
+    /* which for the addition pads and reduces to: */
+    /*  hi:   1000000000000000000                 E-2 */
+    /*  lo:    .................1                 E-2 */
+    #if DECCHECK
+      if (padding>DECPMAX+2) printf("FMA excess padding: %ld\n", (LI)padding);
+      if (padding<=0) printf("FMA low padding: %ld\n", (LI)padding);
+      /* printf("FMA padding: %ld\n", (LI)padding); */
+    #endif
+    /* padding digits can now be set in the result; one or more of */
+    /* these will come from lo; others will be zeros in the gap */
+    for (; ul>=lo->msd && padding>0; padding--, ul--, ub--) *ub=*ul;
+    for (;padding>0; padding--, ub--) *ub=0; /* mind the gap */
+    }
+
+  /* addition now complete to the right of the rightmost digit of hi */
+  uh=hi->lsd;
+
+  /* carry was set up depending on ten's complement above; do the add... */
+  for (;; ub--) {
+    uInt hid, lod;
+    if (uh<hi->msd) {
+      if (ul<lo->msd) break;
+      hid=hipad;
+      }
+     else hid=*uh--;
+    if (ul<lo->msd) lod=0;
+     else lod=*ul--;
+    *ub=(uByte)(carry+hid+lod);
+    if (*ub<10) carry=0;
+     else {
+      *ub-=10;
+      carry=1;
+      }
+    } /* addition loop */
+
+  /* addition complete -- now handle carry, borrow, etc. */
+  /* use lo to set up the num (its exponent is already correct, and */
+  /* sign usually is) */
+  lo->msd=ub+1;
+  lo->lsd=acc+FMALEN-1;
+  /* decShowNum(lo, "lo"); */
+  if (!diffsign) {                /* same-sign addition */
+    if (carry) {                  /* carry out */
+      *ub=1;                      /* place the 1 .. */
+      lo->msd--;                  /* .. and update */
+      }
+    } /* same sign */
+   else {                         /* signs differed (subtraction) */
+    if (!carry) {                 /* no carry out means hi<lo */
+      /* borrowed -- take ten's complement of the right digits */
+      lo->sign=hi->sign;          /* sign is lhs sign */
+      for (ul=lo->msd; ul<lo->lsd-3; ul+=4) UINTAT(ul)=0x09090909-UINTAT(ul);
+      for (; ul<=lo->lsd; ul++) *ul=(uByte)(0x09-*ul); /* [leaves ul at lsd+1] */
+      /* complete the ten's complement by adding 1 [cannot overrun] */
+      for (ul--; *ul==9; ul--) *ul=0;
+      *ul+=1;
+      } /* borrowed */
+     else {                       /* carry out means hi>=lo */
+      /* sign to use is lo->sign */
+      /* all done except for the special IEEE 754 exact-zero-result */
+      /* rule (see above); while testing for zero, strip leading */
+      /* zeros (which will save decFinalize doing it) */
+      for (; UINTAT(lo->msd)==0 && lo->msd+3<lo->lsd;) lo->msd+=4;
+      for (; *lo->msd==0 && lo->msd<lo->lsd;) lo->msd++;
+      if (*lo->msd==0) {          /* must be true zero (and diffsign) */
+       lo->sign=0;                /* assume + */
+       if (set->round==DEC_ROUND_FLOOR) lo->sign=DECFLOAT_Sign;
+       }
+      /* [else was not zero, might still have leading zeros] */
+      } /* subtraction gave positive result */
+    } /* diffsign */
+
+  return decFinalize(result, lo, set); /* round, check, and lay out */
+  } /* decFloatFMA */
+
+/* ------------------------------------------------------------------ */
+/* decFloatFromInt -- initialise a decFloat from an Int                      */
+/*                                                                   */
+/*   result gets the converted Int                                   */
+/*   n     is the Int to convert                                     */
+/*   returns result                                                  */
+/*                                                                   */
+/* The result is Exact; no errors or exceptions are possible.        */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatFromInt32(decFloat *result, Int n) {
+  uInt u=(uInt)n;                      /* copy as bits */
+  uInt encode;                         /* work */
+  DFWORD(result, 0)=ZEROWORD;          /* always */
+  #if QUAD
+    DFWORD(result, 1)=0;
+    DFWORD(result, 2)=0;
+  #endif
+  if (n<0) {                           /* handle -n with care */
+    /* [This can be done without the test, but is then slightly slower] */
+    u=(~u)+1;
+    DFWORD(result, 0)|=DECFLOAT_Sign;
+    }
+  /* Since the maximum value of u now is 2**31, only the low word of */
+  /* result is affected */
+  encode=BIN2DPD[u%1000];
+  u/=1000;
+  encode|=BIN2DPD[u%1000]<<10;
+  u/=1000;
+  encode|=BIN2DPD[u%1000]<<20;
+  u/=1000;                             /* now 0, 1, or 2 */
+  encode|=u<<30;
+  DFWORD(result, DECWORDS-1)=encode;
+  return result;
+  } /* decFloatFromInt32 */
+
+/* ------------------------------------------------------------------ */
+/* decFloatFromUInt -- initialise a decFloat from a uInt             */
+/*                                                                   */
+/*   result gets the converted uInt                                  */
+/*   n     is the uInt to convert                                    */
+/*   returns result                                                  */
+/*                                                                   */
+/* The result is Exact; no errors or exceptions are possible.        */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatFromUInt32(decFloat *result, uInt u) {
+  uInt encode;                         /* work */
+  DFWORD(result, 0)=ZEROWORD;          /* always */
+  #if QUAD
+    DFWORD(result, 1)=0;
+    DFWORD(result, 2)=0;
+  #endif
+  encode=BIN2DPD[u%1000];
+  u/=1000;
+  encode|=BIN2DPD[u%1000]<<10;
+  u/=1000;
+  encode|=BIN2DPD[u%1000]<<20;
+  u/=1000;                             /* now 0 -> 4 */
+  encode|=u<<30;
+  DFWORD(result, DECWORDS-1)=encode;
+  DFWORD(result, DECWORDS-2)|=u>>2;    /* rarely non-zero */
+  return result;
+  } /* decFloatFromUInt32 */
+
+/* ------------------------------------------------------------------ */
+/* decFloatInvert -- logical digitwise INVERT of a decFloat          */
+/*                                                                   */
+/*   result gets the result of INVERTing df                          */
+/*   df            is the decFloat to invert                                 */
+/*   set    is the context                                           */
+/*   returns result, which will be canonical with sign=0             */
+/*                                                                   */
+/* The operand must be positive, finite with exponent q=0, and       */
+/* comprise just zeros and ones; if not, Invalid operation results.   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatInvert(decFloat *result, const decFloat *df,
+                         decContext *set) {
+  uInt sourhi=DFWORD(df, 0);           /* top word of dfs */
+
+  if (!DFISUINT01(df) || !DFISCC01(df)) return decInvalid(result, set);
+  /* the operand is a finite integer (q=0) */
+  #if DOUBLE
+   DFWORD(result, 0)=ZEROWORD|((~sourhi)&0x04009124);
+   DFWORD(result, 1)=(~DFWORD(df, 1))  &0x49124491;
+  #elif QUAD
+   DFWORD(result, 0)=ZEROWORD|((~sourhi)&0x04000912);
+   DFWORD(result, 1)=(~DFWORD(df, 1))  &0x44912449;
+   DFWORD(result, 2)=(~DFWORD(df, 2))  &0x12449124;
+   DFWORD(result, 3)=(~DFWORD(df, 3))  &0x49124491;
+  #endif
+  return result;
+  } /* decFloatInvert */
+
+/* ------------------------------------------------------------------ */
+/* decFloatIs -- decFloat tests (IsSigned, etc.)                     */
+/*                                                                   */
+/*   df is the decFloat to test                                              */
+/*   returns 0 or 1 in an int32_t                                    */
+/*                                                                   */
+/* Many of these could be macros, but having them as real functions   */
+/* is a bit cleaner (and they can be referred to here by the generic  */
+/* names)                                                            */
+/* ------------------------------------------------------------------ */
+uInt decFloatIsCanonical(const decFloat *df) {
+  if (DFISSPECIAL(df)) {
+    if (DFISINF(df)) {
+      if (DFWORD(df, 0)&ECONMASK) return 0;  /* exponent continuation */
+      if (!DFISCCZERO(df)) return 0;        /* coefficient continuation */
+      return 1;
+      }
+    /* is a NaN */
+    if (DFWORD(df, 0)&ECONNANMASK) return 0; /* exponent continuation */
+    if (DFISCCZERO(df)) return 1;           /* coefficient continuation */
+    /* drop through to check payload */
+    }
+  { /* declare block */
+  #if DOUBLE
+    uInt sourhi=DFWORD(df, 0);
+    uInt sourlo=DFWORD(df, 1);
+    if (CANONDPDOFF(sourhi, 8)
+     && CANONDPDTWO(sourhi, sourlo, 30)
+     && CANONDPDOFF(sourlo, 20)
+     && CANONDPDOFF(sourlo, 10)
+     && CANONDPDOFF(sourlo, 0)) return 1;
+  #elif QUAD
+    uInt sourhi=DFWORD(df, 0);
+    uInt sourmh=DFWORD(df, 1);
+    uInt sourml=DFWORD(df, 2);
+    uInt sourlo=DFWORD(df, 3);
+    if (CANONDPDOFF(sourhi, 4)
+     && CANONDPDTWO(sourhi, sourmh, 26)
+     && CANONDPDOFF(sourmh, 16)
+     && CANONDPDOFF(sourmh, 6)
+     && CANONDPDTWO(sourmh, sourml, 28)
+     && CANONDPDOFF(sourml, 18)
+     && CANONDPDOFF(sourml, 8)
+     && CANONDPDTWO(sourml, sourlo, 30)
+     && CANONDPDOFF(sourlo, 20)
+     && CANONDPDOFF(sourlo, 10)
+     && CANONDPDOFF(sourlo, 0)) return 1;
+  #endif
+  } /* block */
+  return 0;    /* a declet is non-canonical */
+  }
+
+uInt decFloatIsFinite(const decFloat *df) {
+  return !DFISSPECIAL(df);
+  }
+uInt decFloatIsInfinite(const decFloat *df) {
+  return DFISINF(df);
+  }
+uInt decFloatIsInteger(const decFloat *df) {
+  return DFISINT(df);
+  }
+uInt decFloatIsNaN(const decFloat *df) {
+  return DFISNAN(df);
+  }
+uInt decFloatIsNormal(const decFloat *df) {
+  Int exp;                        /* exponent */
+  if (DFISSPECIAL(df)) return 0;
+  if (DFISZERO(df)) return 0;
+  /* is finite and non-zero */
+  exp=GETEXPUN(df)                /* get unbiased exponent .. */
+     +decFloatDigits(df)-1;       /* .. and make adjusted exponent */
+  return (exp>=DECEMIN);          /* < DECEMIN is subnormal */
+  }
+uInt decFloatIsSignaling(const decFloat *df) {
+  return DFISSNAN(df);
+  }
+uInt decFloatIsSignalling(const decFloat *df) {
+  return DFISSNAN(df);
+  }
+uInt decFloatIsSigned(const decFloat *df) {
+  return DFISSIGNED(df);
+  }
+uInt decFloatIsSubnormal(const decFloat *df) {
+  if (DFISSPECIAL(df)) return 0;
+  /* is finite */
+  if (decFloatIsNormal(df)) return 0;
+  /* it is <Nmin, but could be zero */
+  if (DFISZERO(df)) return 0;
+  return 1;                                 /* is subnormal */
+  }
+uInt decFloatIsZero(const decFloat *df) {
+  return DFISZERO(df);
+  } /* decFloatIs... */
+
+/* ------------------------------------------------------------------ */
+/* decFloatLogB -- return adjusted exponent, by 754r rules           */
+/*                                                                   */
+/*   result gets the adjusted exponent as an integer, or a NaN etc.   */
+/*   df            is the decFloat to be examined                            */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* Notable cases:                                                    */
+/*   A<0 -> Use |A|                                                  */
+/*   A=0 -> -Infinity (Division by zero)                             */
+/*   A=Infinite -> +Infinity (Exact)                                 */
+/*   A=1 exactly -> 0 (Exact)                                        */
+/*   NaNs are propagated as usual                                    */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatLogB(decFloat *result, const decFloat *df,
+                       decContext *set) {
+  Int ae;                                   /* adjusted exponent */
+  if (DFISNAN(df)) return decNaNs(result, df, NULL, set);
+  if (DFISINF(df)) {
+    DFWORD(result, 0)=0;                    /* need +ve */
+    return decInfinity(result, result);             /* canonical +Infinity */
+    }
+  if (DFISZERO(df)) {
+    set->status|=DEC_Division_by_zero;      /* as per 754r */
+    DFWORD(result, 0)=DECFLOAT_Sign;        /* make negative */
+    return decInfinity(result, result);             /* canonical -Infinity */
+    }
+  ae=GETEXPUN(df)                      /* get unbiased exponent .. */
+    +decFloatDigits(df)-1;             /* .. and make adjusted exponent */
+  /* ae has limited range (3 digits for DOUBLE and 4 for QUAD), so */
+  /* it is worth using a special case of decFloatFromInt32 */
+  DFWORD(result, 0)=ZEROWORD;          /* always */
+  if (ae<0) {
+    DFWORD(result, 0)|=DECFLOAT_Sign;  /* -0 so far */
+    ae=-ae;
+    }
+  #if DOUBLE
+    DFWORD(result, 1)=BIN2DPD[ae];     /* a single declet */
+  #elif QUAD
+    DFWORD(result, 1)=0;
+    DFWORD(result, 2)=0;
+    DFWORD(result, 3)=(ae/1000)<<10;   /* is <10, so need no DPD encode */
+    DFWORD(result, 3)|=BIN2DPD[ae%1000];
+  #endif
+  return result;
+  } /* decFloatLogB */
+
+/* ------------------------------------------------------------------ */
+/* decFloatMax -- return maxnum of two operands                              */
+/*                                                                   */
+/*   result gets the chosen decFloat                                 */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* If just one operand is a quiet NaN it is ignored.                 */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatMax(decFloat *result,
+                      const decFloat *dfl, const decFloat *dfr,
+                      decContext *set) {
+  Int comp;
+  if (DFISNAN(dfl)) {
+    /* sNaN or both NaNs leads to normal NaN processing */
+    if (DFISNAN(dfr) || DFISSNAN(dfl)) return decNaNs(result, dfl, dfr, set);
+    return decCanonical(result, dfr);       /* RHS is numeric */
+    }
+  if (DFISNAN(dfr)) {
+    /* sNaN leads to normal NaN processing (both NaN handled above) */
+    if (DFISSNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+    return decCanonical(result, dfl);       /* LHS is numeric */
+    }
+  /* Both operands are numeric; numeric comparison needed -- use */
+  /* total order for a well-defined choice (and +0 > -0) */
+  comp=decNumCompare(dfl, dfr, 1);
+  if (comp>=0) return decCanonical(result, dfl);
+  return decCanonical(result, dfr);
+  } /* decFloatMax */
+
+/* ------------------------------------------------------------------ */
+/* decFloatMaxMag -- return maxnummag of two operands                */
+/*                                                                   */
+/*   result gets the chosen decFloat                                 */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* Returns according to the magnitude comparisons if both numeric and */
+/* unequal, otherwise returns maxnum                                 */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatMaxMag(decFloat *result,
+                      const decFloat *dfl, const decFloat *dfr,
+                      decContext *set) {
+  Int comp;
+  decFloat absl, absr;
+  if (DFISNAN(dfl) || DFISNAN(dfr)) return decFloatMax(result, dfl, dfr, set);
+
+  decFloatCopyAbs(&absl, dfl);
+  decFloatCopyAbs(&absr, dfr);
+  comp=decNumCompare(&absl, &absr, 0);
+  if (comp>0) return decCanonical(result, dfl);
+  if (comp<0) return decCanonical(result, dfr);
+  return decFloatMax(result, dfl, dfr, set);
+  } /* decFloatMaxMag */
+
+/* ------------------------------------------------------------------ */
+/* decFloatMin -- return minnum of two operands                              */
+/*                                                                   */
+/*   result gets the chosen decFloat                                 */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* If just one operand is a quiet NaN it is ignored.                 */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatMin(decFloat *result,
+                      const decFloat *dfl, const decFloat *dfr,
+                      decContext *set) {
+  Int comp;
+  if (DFISNAN(dfl)) {
+    /* sNaN or both NaNs leads to normal NaN processing */
+    if (DFISNAN(dfr) || DFISSNAN(dfl)) return decNaNs(result, dfl, dfr, set);
+    return decCanonical(result, dfr);       /* RHS is numeric */
+    }
+  if (DFISNAN(dfr)) {
+    /* sNaN leads to normal NaN processing (both NaN handled above) */
+    if (DFISSNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+    return decCanonical(result, dfl);       /* LHS is numeric */
+    }
+  /* Both operands are numeric; numeric comparison needed -- use */
+  /* total order for a well-defined choice (and +0 > -0) */
+  comp=decNumCompare(dfl, dfr, 1);
+  if (comp<=0) return decCanonical(result, dfl);
+  return decCanonical(result, dfr);
+  } /* decFloatMin */
+
+/* ------------------------------------------------------------------ */
+/* decFloatMinMag -- return minnummag of two operands                */
+/*                                                                   */
+/*   result gets the chosen decFloat                                 */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* Returns according to the magnitude comparisons if both numeric and */
+/* unequal, otherwise returns minnum                                 */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatMinMag(decFloat *result,
+                      const decFloat *dfl, const decFloat *dfr,
+                      decContext *set) {
+  Int comp;
+  decFloat absl, absr;
+  if (DFISNAN(dfl) || DFISNAN(dfr)) return decFloatMin(result, dfl, dfr, set);
+
+  decFloatCopyAbs(&absl, dfl);
+  decFloatCopyAbs(&absr, dfr);
+  comp=decNumCompare(&absl, &absr, 0);
+  if (comp<0) return decCanonical(result, dfl);
+  if (comp>0) return decCanonical(result, dfr);
+  return decFloatMin(result, dfl, dfr, set);
+  } /* decFloatMinMag */
+
+/* ------------------------------------------------------------------ */
+/* decFloatMinus -- negate value, heeding NaNs, etc.                 */
+/*                                                                   */
+/*   result gets the canonicalized 0-df                                      */
+/*   df            is the decFloat to minus                                  */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* This has the same effect as 0-df where the exponent of the zero is */
+/* the same as that of df (if df is finite).                         */
+/* The effect is also the same as decFloatCopyNegate except that NaNs */
+/* are handled normally (the sign of a NaN is not affected, and an    */
+/* sNaN will signal), the result is canonical, and zero gets sign 0.  */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatMinus(decFloat *result, const decFloat *df,
+                        decContext *set) {
+  if (DFISNAN(df)) return decNaNs(result, df, NULL, set);
+  decCanonical(result, df);                      /* copy and check */
+  if (DFISZERO(df)) DFBYTE(result, 0)&=~0x80;    /* turn off sign bit */
+   else DFBYTE(result, 0)^=0x80;                 /* flip sign bit */
+  return result;
+  } /* decFloatMinus */
+
+/* ------------------------------------------------------------------ */
+/* decFloatMultiply -- multiply two decFloats                        */
+/*                                                                   */
+/*   result gets the result of multiplying dfl and dfr:                      */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatMultiply(decFloat *result,
+                           const decFloat *dfl, const decFloat *dfr,
+                           decContext *set) {
+  bcdnum num;                     /* for final conversion */
+  uByte         bcdacc[DECPMAX9*18+1];    /* for coefficent in BCD */
+
+  if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr)) { /* either is special? */
+    /* NaNs are handled as usual */
+    if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+    /* infinity times zero is bad */
+    if (DFISINF(dfl) && DFISZERO(dfr)) return decInvalid(result, set);
+    if (DFISINF(dfr) && DFISZERO(dfl)) return decInvalid(result, set);
+    /* both infinite; return canonical infinity with computed sign */
+    DFWORD(result, 0)=DFWORD(dfl, 0)^DFWORD(dfr, 0); /* compute sign */
+    return decInfinity(result, result);
+    }
+
+  /* Here when both operands are finite */
+  decFiniteMultiply(&num, bcdacc, dfl, dfr);
+  return decFinalize(result, &num, set); /* round, check, and lay out */
+  } /* decFloatMultiply */
+
+/* ------------------------------------------------------------------ */
+/* decFloatNextMinus -- next towards -Infinity                       */
+/*                                                                   */
+/*   result gets the next lesser decFloat                            */
+/*   dfl    is the decFloat to start with                            */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is 754r nextdown; Invalid is the only status possible (from   */
+/* an sNaN).                                                         */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatNextMinus(decFloat *result, const decFloat *dfl,
+                            decContext *set) {
+  decFloat delta;                      /* tiny increment */
+  uInt savestat;                       /* saves status */
+  enum rounding saveround;             /* .. and mode */
+
+  /* +Infinity is the special case */
+  if (DFISINF(dfl) && !DFISSIGNED(dfl)) {
+    DFSETNMAX(result);
+    return result;                     /* [no status to set] */
+    }
+  /* other cases are effected by sutracting a tiny delta -- this */
+  /* should be done in a wider format as the delta is unrepresentable */
+  /* here (but can be done with normal add if the sign of zero is */
+  /* treated carefully, because no Inexactitude is interesting); */
+  /* rounding to -Infinity then pushes the result to next below */
+  decFloatZero(&delta);                        /* set up tiny delta */
+  DFWORD(&delta, DECWORDS-1)=1;                /* coefficient=1 */
+  DFWORD(&delta, 0)=DECFLOAT_Sign;     /* Sign=1 + biased exponent=0 */
+  /* set up for the directional round */
+  saveround=set->round;                        /* save mode */
+  set->round=DEC_ROUND_FLOOR;          /* .. round towards -Infinity */
+  savestat=set->status;                        /* save status */
+  decFloatAdd(result, dfl, &delta, set);
+  /* Add rules mess up the sign when going from +Ntiny to 0 */
+  if (DFISZERO(result)) DFWORD(result, 0)^=DECFLOAT_Sign; /* correct */
+  set->status&=DEC_Invalid_operation;  /* preserve only sNaN status */
+  set->status|=savestat;               /* restore pending flags */
+  set->round=saveround;                        /* .. and mode */
+  return result;
+  } /* decFloatNextMinus */
+
+/* ------------------------------------------------------------------ */
+/* decFloatNextPlus -- next towards +Infinity                        */
+/*                                                                   */
+/*   result gets the next larger decFloat                            */
+/*   dfl    is the decFloat to start with                            */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is 754r nextup; Invalid is the only status possible (from     */
+/* an sNaN).                                                         */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatNextPlus(decFloat *result, const decFloat *dfl,
+                           decContext *set) {
+  uInt savestat;                       /* saves status */
+  enum rounding saveround;             /* .. and mode */
+  decFloat delta;                      /* tiny increment */
+
+  /* -Infinity is the special case */
+  if (DFISINF(dfl) && DFISSIGNED(dfl)) {
+    DFSETNMAX(result);
+    DFWORD(result, 0)|=DECFLOAT_Sign;  /* make negative */
+    return result;                     /* [no status to set] */
+    }
+  /* other cases are effected by sutracting a tiny delta -- this */
+  /* should be done in a wider format as the delta is unrepresentable */
+  /* here (but can be done with normal add if the sign of zero is */
+  /* treated carefully, because no Inexactitude is interesting); */
+  /* rounding to +Infinity then pushes the result to next above */
+  decFloatZero(&delta);                        /* set up tiny delta */
+  DFWORD(&delta, DECWORDS-1)=1;                /* coefficient=1 */
+  DFWORD(&delta, 0)=0;                 /* Sign=0 + biased exponent=0 */
+  /* set up for the directional round */
+  saveround=set->round;                        /* save mode */
+  set->round=DEC_ROUND_CEILING;                /* .. round towards +Infinity */
+  savestat=set->status;                        /* save status */
+  decFloatAdd(result, dfl, &delta, set);
+  /* Add rules mess up the sign when going from -Ntiny to -0 */
+  if (DFISZERO(result)) DFWORD(result, 0)^=DECFLOAT_Sign; /* correct */
+  set->status&=DEC_Invalid_operation;  /* preserve only sNaN status */
+  set->status|=savestat;               /* restore pending flags */
+  set->round=saveround;                        /* .. and mode */
+  return result;
+  } /* decFloatNextPlus */
+
+/* ------------------------------------------------------------------ */
+/* decFloatNextToward -- next towards a decFloat                     */
+/*                                                                   */
+/*   result gets the next decFloat                                   */
+/*   dfl    is the decFloat to start with                            */
+/*   dfr    is the decFloat to move toward                           */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is 754r nextafter; status may be set unless the result is a   */
+/* normal number.                                                    */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatNextToward(decFloat *result,
+                             const decFloat *dfl, const decFloat *dfr,
+                             decContext *set) {
+  decFloat delta;                      /* tiny increment or decrement */
+  decFloat pointone;                   /* 1e-1 */
+  uInt savestat;                       /* saves status */
+  enum rounding saveround;             /* .. and mode */
+  uInt deltatop;                       /* top word for delta */
+  Int  comp;                           /* work */
+
+  if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+  /* Both are numeric, so Invalid no longer a possibility */
+  comp=decNumCompare(dfl, dfr, 0);
+  if (comp==0) return decFloatCopySign(result, dfl, dfr); /* equal */
+  /* unequal; do NextPlus or NextMinus but with different status rules */
+
+  if (comp<0) { /* lhs<rhs, do NextPlus, see above for commentary */
+    if (DFISINF(dfl) && DFISSIGNED(dfl)) {   /* -Infinity special case */
+      DFSETNMAX(result);
+      DFWORD(result, 0)|=DECFLOAT_Sign;
+      return result;
+      }
+    saveround=set->round;                   /* save mode */
+    set->round=DEC_ROUND_CEILING;           /* .. round towards +Infinity */
+    deltatop=0;                                     /* positive delta */
+    }
+   else { /* lhs>rhs, do NextMinus, see above for commentary */
+    if (DFISINF(dfl) && !DFISSIGNED(dfl)) {  /* +Infinity special case */
+      DFSETNMAX(result);
+      return result;
+      }
+    saveround=set->round;                   /* save mode */
+    set->round=DEC_ROUND_FLOOR;                     /* .. round towards -Infinity */
+    deltatop=DECFLOAT_Sign;                 /* negative delta */
+    }
+  savestat=set->status;                             /* save status */
+  /* Here, Inexact is needed where appropriate (and hence Underflow, */
+  /* etc.).  Therefore the tiny delta which is otherwise */
+  /* unrepresentable (see NextPlus and NextMinus) is constructed */
+  /* using the multiplication of FMA. */
+  decFloatZero(&delta);                        /* set up tiny delta */
+  DFWORD(&delta, DECWORDS-1)=1;                /* coefficient=1 */
+  DFWORD(&delta, 0)=deltatop;          /* Sign + biased exponent=0 */
+  decFloatFromString(&pointone, "1E-1", set); /* set up multiplier */
+  decFloatFMA(result, &delta, &pointone, dfl, set);
+  /* [Delta is truly tiny, so no need to correct sign of zero] */
+  /* use new status unless the result is normal */
+  if (decFloatIsNormal(result)) set->status=savestat; /* else goes forward */
+  set->round=saveround;                        /* restore mode */
+  return result;
+  } /* decFloatNextToward */
+
+/* ------------------------------------------------------------------ */
+/* decFloatOr -- logical digitwise OR of two decFloats               */
+/*                                                                   */
+/*   result gets the result of ORing dfl and dfr                     */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result, which will be canonical with sign=0             */
+/*                                                                   */
+/* The operands must be positive, finite with exponent q=0, and              */
+/* comprise just zeros and ones; if not, Invalid operation results.   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatOr(decFloat *result,
+                      const decFloat *dfl, const decFloat *dfr,
+                      decContext *set) {
+  if (!DFISUINT01(dfl) || !DFISUINT01(dfr)
+   || !DFISCC01(dfl)   || !DFISCC01(dfr)) return decInvalid(result, set);
+  /* the operands are positive finite integers (q=0) with just 0s and 1s */
+  #if DOUBLE
+   DFWORD(result, 0)=ZEROWORD
+                  |((DFWORD(dfl, 0) | DFWORD(dfr, 0))&0x04009124);
+   DFWORD(result, 1)=(DFWORD(dfl, 1) | DFWORD(dfr, 1))&0x49124491;
+  #elif QUAD
+   DFWORD(result, 0)=ZEROWORD
+                  |((DFWORD(dfl, 0) | DFWORD(dfr, 0))&0x04000912);
+   DFWORD(result, 1)=(DFWORD(dfl, 1) | DFWORD(dfr, 1))&0x44912449;
+   DFWORD(result, 2)=(DFWORD(dfl, 2) | DFWORD(dfr, 2))&0x12449124;
+   DFWORD(result, 3)=(DFWORD(dfl, 3) | DFWORD(dfr, 3))&0x49124491;
+  #endif
+  return result;
+  } /* decFloatOr */
+
+/* ------------------------------------------------------------------ */
+/* decFloatPlus -- add value to 0, heeding NaNs, etc.                */
+/*                                                                   */
+/*   result gets the canonicalized 0+df                                      */
+/*   df            is the decFloat to plus                                   */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* This has the same effect as 0+df where the exponent of the zero is */
+/* the same as that of df (if df is finite).                         */
+/* The effect is also the same as decFloatCopy except that NaNs              */
+/* are handled normally (the sign of a NaN is not affected, and an    */
+/* sNaN will signal), the result is canonical, and zero gets sign 0.  */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatPlus(decFloat *result, const decFloat *df,
+                       decContext *set) {
+  if (DFISNAN(df)) return decNaNs(result, df, NULL, set);
+  decCanonical(result, df);                      /* copy and check */
+  if (DFISZERO(df)) DFBYTE(result, 0)&=~0x80;    /* turn off sign bit */
+  return result;
+  } /* decFloatPlus */
+
+/* ------------------------------------------------------------------ */
+/* decFloatQuantize -- quantize a decFloat                           */
+/*                                                                   */
+/*   result gets the result of quantizing dfl to match dfr           */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs), which sets the exponent     */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* Unless there is an error or the result is infinite, the exponent   */
+/* of result is guaranteed to be the same as that of dfr.            */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatQuantize(decFloat *result,
+                           const decFloat *dfl, const decFloat *dfr,
+                           decContext *set) {
+  Int  explb, exprb;         /* left and right biased exponents */
+  uByte *ulsd;               /* local LSD pointer */
+  uInt *ui;                  /* work */
+  uByte *ub;                 /* .. */
+  Int  drop;                 /* .. */
+  uInt dpd;                  /* .. */
+  uInt encode;               /* encoding accumulator */
+  uInt sourhil, sourhir;     /* top words from source decFloats */
+  /* the following buffer holds the coefficient for manipulation */
+  uByte buf[4+DECPMAX*3];     /* + space for zeros to left or right */
+  #if DECTRACE
+  bcdnum num;                /* for trace displays */
+  #endif
+
+  /* Start decoding the arguments */
+  sourhil=DFWORD(dfl, 0);         /* LHS top word */
+  explb=DECCOMBEXP[sourhil>>26];   /* get exponent high bits (in place) */
+  sourhir=DFWORD(dfr, 0);         /* RHS top word */
+  exprb=DECCOMBEXP[sourhir>>26];
+
+  if (EXPISSPECIAL(explb | exprb)) { /* either is special? */
+    /* NaNs are handled as usual */
+    if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+    /* one infinity but not both is bad */
+    if (DFISINF(dfl)!=DFISINF(dfr)) return decInvalid(result, set);
+    /* both infinite; return canonical infinity with sign of LHS */
+    return decInfinity(result, dfl);
+    }
+
+  /* Here when both arguments are finite */
+  /* complete extraction of the exponents [no need to unbias] */
+  explb+=GETECON(dfl);            /* + continuation */
+  exprb+=GETECON(dfr);            /* .. */
+
+  /* calculate the number of digits to drop from the coefficient */
+  drop=exprb-explb;               /* 0 if nothing to do */
+  if (drop==0) return decCanonical(result, dfl); /* return canonical */
+
+  /* the coefficient is needed; lay it out into buf, offset so zeros */
+  /* can be added before or after as needed -- an extra heading is */
+  /* added so can safely pad Quad DECPMAX-1 zeros to the left by */
+  /* fours */
+  #define BUFOFF (buf+4+DECPMAX)
+  GETCOEFF(dfl, BUFOFF);          /* decode from decFloat */
+  /* [now the msd is at BUFOFF and the lsd is at BUFOFF+DECPMAX-1] */
+
+  #if DECTRACE
+  num.msd=BUFOFF;
+  num.lsd=BUFOFF+DECPMAX-1;
+  num.exponent=explb-DECBIAS;
+  num.sign=sourhil & DECFLOAT_Sign;
+  decShowNum(&num, "dfl");
+  #endif
+
+  if (drop>0) {                                /* [most common case] */
+    /* (this code is very similar to that in decFloatFinalize, but */
+    /* has many differences so is duplicated here -- so any changes */
+    /* may need to be made there, too) */
+    uByte *roundat;                         /* -> re-round digit */
+    uByte reround;                          /* reround value */
+    /* printf("Rounding; drop=%ld\n", (LI)drop); */
+
+    /* there is at least one zero needed to the left, in all but one */
+    /* exceptional (all-nines) case, so place four zeros now; this is */
+    /* needed almost always and makes rounding all-nines by fours safe */
+    UINTAT(BUFOFF-4)=0;
+
+    /* Three cases here: */
+    /*  1. new LSD is in coefficient (almost always) */
+    /*  2. new LSD is digit to left of coefficient (so MSD is */
+    /*     round-for-reround digit) */
+    /*  3. new LSD is to left of case 2 (whole coefficient is sticky) */
+    /* Note that leading zeros can safely be treated as useful digits */
+
+    /* [duplicate check-stickies code to save a test] */
+    /* [by-digit check for stickies as runs of zeros are rare] */
+    if (drop<DECPMAX) {                             /* NB lengths not addresses */
+      roundat=BUFOFF+DECPMAX-drop;
+      reround=*roundat;
+      for (ub=roundat+1; ub<BUFOFF+DECPMAX; ub++) {
+       if (*ub!=0) {                        /* non-zero to be discarded */
+         reround=DECSTICKYTAB[reround];     /* apply sticky bit */
+         break;                             /* [remainder don't-care] */
+         }
+       } /* check stickies */
+      ulsd=roundat-1;                       /* set LSD */
+      }
+     else {                                 /* edge case */
+      if (drop==DECPMAX) {
+       roundat=BUFOFF;
+       reround=*roundat;
+       }
+       else {
+       roundat=BUFOFF-1;
+       reround=0;
+       }
+      for (ub=roundat+1; ub<BUFOFF+DECPMAX; ub++) {
+       if (*ub!=0) {                        /* non-zero to be discarded */
+         reround=DECSTICKYTAB[reround];     /* apply sticky bit */
+         break;                             /* [remainder don't-care] */
+         }
+       } /* check stickies */
+      *BUFOFF=0;                            /* make a coefficient of 0 */
+      ulsd=BUFOFF;                          /* .. at the MSD place */
+      }
+
+    if (reround!=0) {                       /* discarding non-zero */
+      uInt bump=0;
+      set->status|=DEC_Inexact;
+
+      /* next decide whether to increment the coefficient */
+      if (set->round==DEC_ROUND_HALF_EVEN) { /* fastpath slowest case */
+       if (reround>5) bump=1;               /* >0.5 goes up */
+        else if (reround==5)                /* exactly 0.5000 .. */
+         bump=*ulsd & 0x01;                 /* .. up iff [new] lsd is odd */
+       } /* r-h-e */
+       else switch (set->round) {
+       case DEC_ROUND_DOWN: {
+         /* no change */
+         break;} /* r-d */
+       case DEC_ROUND_HALF_DOWN: {
+         if (reround>5) bump=1;
+         break;} /* r-h-d */
+       case DEC_ROUND_HALF_UP: {
+         if (reround>=5) bump=1;
+         break;} /* r-h-u */
+       case DEC_ROUND_UP: {
+         if (reround>0) bump=1;
+         break;} /* r-u */
+       case DEC_ROUND_CEILING: {
+         /* same as _UP for positive numbers, and as _DOWN for negatives */
+         if (!(sourhil&DECFLOAT_Sign) && reround>0) bump=1;
+         break;} /* r-c */
+       case DEC_ROUND_FLOOR: {
+         /* same as _UP for negative numbers, and as _DOWN for positive */
+         /* [negative reround cannot occur on 0] */
+         if (sourhil&DECFLOAT_Sign && reround>0) bump=1;
+         break;} /* r-f */
+       case DEC_ROUND_05UP: {
+         if (reround>0) { /* anything out there is 'sticky' */
+           /* bump iff lsd=0 or 5; this cannot carry so it could be */
+           /* effected immediately with no bump -- but the code */
+           /* is clearer if this is done the same way as the others */
+           if (*ulsd==0 || *ulsd==5) bump=1;
+           }
+         break;} /* r-r */
+       default: {      /* e.g., DEC_ROUND_MAX */
+         set->status|=DEC_Invalid_context;
+         #if DECCHECK
+         printf("Unknown rounding mode: %ld\n", (LI)set->round);
+         #endif
+         break;}
+       } /* switch (not r-h-e) */
+      /* printf("ReRound: %ld  bump: %ld\n", (LI)reround, (LI)bump); */
+
+      if (bump!=0) {                        /* need increment */
+       /* increment the coefficient; this could give 1000... (after */
+       /* the all nines case) */
+       ub=ulsd;
+       for (; UINTAT(ub-3)==0x09090909; ub-=4) UINTAT(ub-3)=0;
+       /* now at most 3 digits left to non-9 (usually just the one) */
+       for (; *ub==9; ub--) *ub=0;
+       *ub+=1;
+       /* [the all-nines case will have carried one digit to the */
+       /* left of the original MSD -- just where it is needed] */
+       } /* bump needed */
+      } /* inexact rounding */
+
+    /* now clear zeros to the left so exactly DECPMAX digits will be */
+    /* available in the coefficent -- the first word to the left was */
+    /* cleared earlier for safe carry; now add any more needed */
+    if (drop>4) {
+      UINTAT(BUFOFF-8)=0;                   /* must be at least 5 */
+      for (ui=&UINTAT(BUFOFF-12); ui>&UINTAT(ulsd-DECPMAX-3); ui--) *ui=0;
+      }
+    } /* need round (drop>0) */
+
+   else { /* drop<0; padding with -drop digits is needed */
+    /* This is the case where an error can occur if the padded */
+    /* coefficient will not fit; checking for this can be done in the */
+    /* same loop as padding for zeros if the no-hope and zero cases */
+    /* are checked first */
+    if (-drop>DECPMAX-1) {                  /* cannot fit unless 0 */
+      if (!ISCOEFFZERO(BUFOFF)) return decInvalid(result, set);
+      /* a zero can have any exponent; just drop through and use it */
+      ulsd=BUFOFF+DECPMAX-1;
+      }
+     else { /* padding will fit (but may still be too long) */
+      /* final-word mask depends on endianess */
+      #if DECLITEND
+      static const uInt dmask[]={0, 0x000000ff, 0x0000ffff, 0x00ffffff};
+      #else
+      static const uInt dmask[]={0, 0xff000000, 0xffff0000, 0xffffff00};
+      #endif
+      for (ui=&UINTAT(BUFOFF+DECPMAX);; ui++) {
+       *ui=0;
+       if (UINTAT(&UBYTEAT(ui)-DECPMAX)!=0) { /* could be bad */
+         /* if all four digits should be zero, definitely bad */
+         if (ui<=&UINTAT(BUFOFF+DECPMAX+(-drop)-4))
+           return decInvalid(result, set);
+         /* must be a 1- to 3-digit sequence; check more carefully */
+         if ((UINTAT(&UBYTEAT(ui)-DECPMAX)&dmask[(-drop)%4])!=0)
+           return decInvalid(result, set);
+         break;    /* no need for loop end test */
+         }
+       if (ui>=&UINTAT(BUFOFF+DECPMAX+(-drop)-4)) break; /* done */
+       }
+      ulsd=BUFOFF+DECPMAX+(-drop)-1;
+      } /* pad and check leading zeros */
+    } /* drop<0 */
+
+  #if DECTRACE
+  num.msd=ulsd-DECPMAX+1;
+  num.lsd=ulsd;
+  num.exponent=explb-DECBIAS;
+  num.sign=sourhil & DECFLOAT_Sign;
+  decShowNum(&num, "res");
+  #endif
+
+  /*------------------------------------------------------------------*/
+  /* At this point the result is DECPMAX digits, ending at ulsd, so   */
+  /* fits the encoding exactly; there is no possibility of error      */
+  /*------------------------------------------------------------------*/
+  encode=((exprb>>DECECONL)<<4) + *(ulsd-DECPMAX+1); /* make index */
+  encode=DECCOMBFROM[encode];               /* indexed by (0-2)*16+msd */
+  /* the exponent continuation can be extracted from the original RHS */
+  encode|=sourhir & ECONMASK;
+  encode|=sourhil&DECFLOAT_Sign;            /* add the sign from LHS */
+
+  /* finally encode the coefficient */
+  /* private macro to encode a declet; this version can be used */
+  /* because all coefficient digits exist */
+  #define getDPD3q(dpd, n) ub=ulsd-(3*(n))-2;                  \
+    dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)];
+
+  #if DOUBLE
+    getDPD3q(dpd, 4); encode|=dpd<<8;
+    getDPD3q(dpd, 3); encode|=dpd>>2;
+    DFWORD(result, 0)=encode;
+    encode=dpd<<30;
+    getDPD3q(dpd, 2); encode|=dpd<<20;
+    getDPD3q(dpd, 1); encode|=dpd<<10;
+    getDPD3q(dpd, 0); encode|=dpd;
+    DFWORD(result, 1)=encode;
+
+  #elif QUAD
+    getDPD3q(dpd,10); encode|=dpd<<4;
+    getDPD3q(dpd, 9); encode|=dpd>>6;
+    DFWORD(result, 0)=encode;
+    encode=dpd<<26;
+    getDPD3q(dpd, 8); encode|=dpd<<16;
+    getDPD3q(dpd, 7); encode|=dpd<<6;
+    getDPD3q(dpd, 6); encode|=dpd>>4;
+    DFWORD(result, 1)=encode;
+    encode=dpd<<28;
+    getDPD3q(dpd, 5); encode|=dpd<<18;
+    getDPD3q(dpd, 4); encode|=dpd<<8;
+    getDPD3q(dpd, 3); encode|=dpd>>2;
+    DFWORD(result, 2)=encode;
+    encode=dpd<<30;
+    getDPD3q(dpd, 2); encode|=dpd<<20;
+    getDPD3q(dpd, 1); encode|=dpd<<10;
+    getDPD3q(dpd, 0); encode|=dpd;
+    DFWORD(result, 3)=encode;
+  #endif
+  return result;
+  } /* decFloatQuantize */
+
+/* ------------------------------------------------------------------ */
+/* decFloatReduce -- reduce finite coefficient to minimum length      */
+/*                                                                   */
+/*   result gets the reduced decFloat                                */
+/*   df            is the source decFloat                                    */
+/*   set    is the context                                           */
+/*   returns result, which will be canonical                         */
+/*                                                                   */
+/* This removes all possible trailing zeros from the coefficient;     */
+/* some may remain when the number is very close to Nmax.            */
+/* Special values are unchanged and no status is set unless df=sNaN.  */
+/* Reduced zero has an exponent q=0.                                 */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatReduce(decFloat *result, const decFloat *df,
+                         decContext *set) {
+  bcdnum num;                          /* work */
+  uByte buf[DECPMAX], *ub;             /* coefficient and pointer */
+  if (df!=result) *result=*df;         /* copy, if needed */
+  if (DFISNAN(df)) return decNaNs(result, df, NULL, set);   /* sNaN */
+  /* zeros and infinites propagate too */
+  if (DFISINF(df)) return decInfinity(result, df);     /* canonical */
+  if (DFISZERO(df)) {
+    uInt sign=DFWORD(df, 0)&DECFLOAT_Sign;
+    decFloatZero(result);
+    DFWORD(result, 0)|=sign;
+    return result;                     /* exponent dropped, sign OK */
+    }
+  /* non-zero finite */
+  GETCOEFF(df, buf);
+  ub=buf+DECPMAX-1;                    /* -> lsd */
+  if (*ub) return result;              /* no trailing zeros */
+  for (ub--; *ub==0;) ub--;            /* terminates because non-zero */
+  /* *ub is the first non-zero from the right */
+  num.sign=DFWORD(df, 0)&DECFLOAT_Sign; /* set up number... */
+  num.exponent=GETEXPUN(df)+(Int)(buf+DECPMAX-1-ub); /* adjusted exponent */
+  num.msd=buf;
+  num.lsd=ub;
+  return decFinalize(result, &num, set);
+  } /* decFloatReduce */
+
+/* ------------------------------------------------------------------ */
+/* decFloatRemainder -- integer divide and return remainder          */
+/*                                                                   */
+/*   result gets the remainder of dividing dfl by dfr:               */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatRemainder(decFloat *result,
+                            const decFloat *dfl, const decFloat *dfr,
+                            decContext *set) {
+  return decDivide(result, dfl, dfr, set, REMAINDER);
+  } /* decFloatRemainder */
+
+/* ------------------------------------------------------------------ */
+/* decFloatRemainderNear -- integer divide to nearest and remainder   */
+/*                                                                   */
+/*   result gets the remainder of dividing dfl by dfr:               */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* This is the IEEE remainder, where the nearest integer is used.     */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatRemainderNear(decFloat *result,
+                            const decFloat *dfl, const decFloat *dfr,
+                            decContext *set) {
+  return decDivide(result, dfl, dfr, set, REMNEAR);
+  } /* decFloatRemainderNear */
+
+/* ------------------------------------------------------------------ */
+/* decFloatRotate -- rotate the coefficient of a decFloat left/right  */
+/*                                                                   */
+/*   result gets the result of rotating dfl                          */
+/*   dfl    is the source decFloat to rotate                         */
+/*   dfr    is the count of digits to rotate, an integer (with q=0)   */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* The digits of the coefficient of dfl are rotated to the left (if   */
+/* dfr is positive) or to the right (if dfr is negative) without      */
+/* adjusting the exponent or the sign of dfl.                        */
+/*                                                                   */
+/* dfr must be in the range -DECPMAX through +DECPMAX.               */
+/* NaNs are propagated as usual.  An infinite dfl is unaffected (but  */
+/* dfr must be valid). No status is set unless dfr is invalid or an  */
+/* operand is an sNaN. The result is canonical.                      */
+/* ------------------------------------------------------------------ */
+#define PHALF (ROUNDUP(DECPMAX/2, 4))  /* half length, rounded up */
+decFloat * decFloatRotate(decFloat *result,
+                        const decFloat *dfl, const decFloat *dfr,
+                        decContext *set) {
+  Int rotate;                          /* dfr as an Int */
+  uByte buf[DECPMAX+PHALF];            /* coefficient + half */
+  uInt digits, savestat;               /* work */
+  bcdnum num;                          /* .. */
+  uByte *ub;                           /* .. */
+
+  if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+  if (!DFISINT(dfr)) return decInvalid(result, set);
+  digits=decFloatDigits(dfr);                   /* calculate digits */
+  if (digits>2) return decInvalid(result, set);         /* definitely out of range */
+  rotate=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff]; /* is in bottom declet */
+  if (rotate>DECPMAX) return decInvalid(result, set); /* too big */
+  /* [from here on no error or status change is possible] */
+  if (DFISINF(dfl)) return decInfinity(result, dfl);  /* canonical */
+  /* handle no-rotate cases */
+  if (rotate==0 || rotate==DECPMAX) return decCanonical(result, dfl);
+  /* a real rotate is needed: 0 < rotate < DECPMAX */
+  /* reduce the rotation to no more than half to reduce copying later */
+  /* (for QUAD in fact half + 2 digits) */
+  if (DFISSIGNED(dfr)) rotate=-rotate;
+  if (abs(rotate)>PHALF) {
+    if (rotate<0) rotate=DECPMAX+rotate;
+     else rotate=rotate-DECPMAX;
+    }
+  /* now lay out the coefficient, leaving room to the right or the */
+  /* left depending on the direction of rotation */
+  ub=buf;
+  if (rotate<0) ub+=PHALF;    /* rotate right, so space to left */
+  GETCOEFF(dfl, ub);
+  /* copy half the digits to left or right, and set num.msd */
+  if (rotate<0) {
+    memcpy(buf, buf+DECPMAX, PHALF);
+    num.msd=buf+PHALF+rotate;
+    }
+   else {
+    memcpy(buf+DECPMAX, buf, PHALF);
+    num.msd=buf+rotate;
+    }
+  /* fill in rest of num */
+  num.lsd=num.msd+DECPMAX-1;
+  num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign;
+  num.exponent=GETEXPUN(dfl);
+  savestat=set->status;                        /* record */
+  decFinalize(result, &num, set);
+  set->status=savestat;                        /* restore */
+  return result;
+  } /* decFloatRotate */
+
+/* ------------------------------------------------------------------ */
+/* decFloatSameQuantum -- test decFloats for same quantum            */
+/*                                                                   */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   returns 1 if the operands have the same quantum, 0 otherwise     */
+/*                                                                   */
+/* No error is possible and no status results.                       */
+/* ------------------------------------------------------------------ */
+uInt decFloatSameQuantum(const decFloat *dfl, const decFloat *dfr) {
+  if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr)) {
+    if (DFISNAN(dfl) && DFISNAN(dfr)) return 1;
+    if (DFISINF(dfl) && DFISINF(dfr)) return 1;
+    return 0;  /* any other special mixture gives false */
+    }
+  if (GETEXP(dfl)==GETEXP(dfr)) return 1; /* biased exponents match */
+  return 0;
+  } /* decFloatSameQuantum */
+
+/* ------------------------------------------------------------------ */
+/* decFloatScaleB -- multiply by a power of 10, as per 754r          */
+/*                                                                   */
+/*   result gets the result of the operation                         */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs), am integer (with q=0)              */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* This computes result=dfl x 10**dfr where dfr is an integer in the  */
+/* range +/-2*(emax+pmax), typically resulting from LogB.            */
+/* Underflow and Overflow (with Inexact) may occur.  NaNs propagate   */
+/* as usual.                                                         */
+/* ------------------------------------------------------------------ */
+#define SCALEBMAX 2*(DECEMAX+DECPMAX)  /* D=800, Q=12356 */
+decFloat * decFloatScaleB(decFloat *result,
+                         const decFloat *dfl, const decFloat *dfr,
+                         decContext *set) {
+  uInt digits;                         /* work */
+  Int  expr;                           /* dfr as an Int */
+
+  if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+  if (!DFISINT(dfr)) return decInvalid(result, set);
+  digits=decFloatDigits(dfr);               /* calculate digits */
+
+  #if DOUBLE
+  if (digits>3) return decInvalid(result, set);          /* definitely out of range */
+  expr=DPD2BIN[DFWORD(dfr, 1)&0x3ff];            /* must be in bottom declet */
+  #elif QUAD
+  if (digits>5) return decInvalid(result, set);          /* definitely out of range */
+  expr=DPD2BIN[DFWORD(dfr, 3)&0x3ff]             /* in bottom 2 declets .. */
+      +DPD2BIN[(DFWORD(dfr, 3)>>10)&0x3ff]*1000;  /* .. */
+  #endif
+  if (expr>SCALEBMAX) return decInvalid(result, set);  /* oops */
+  /* [from now on no error possible] */
+  if (DFISINF(dfl)) return decInfinity(result, dfl);   /* canonical */
+  if (DFISSIGNED(dfr)) expr=-expr;
+  /* dfl is finite and expr is valid */
+  *result=*dfl;                                     /* copy to target */
+  return decFloatSetExponent(result, set, GETEXPUN(result)+expr);
+  } /* decFloatScaleB */
+
+/* ------------------------------------------------------------------ */
+/* decFloatShift -- shift the coefficient of a decFloat left or right */
+/*                                                                   */
+/*   result gets the result of shifting dfl                          */
+/*   dfl    is the source decFloat to shift                          */
+/*   dfr    is the count of digits to shift, an integer (with q=0)    */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* The digits of the coefficient of dfl are shifted to the left (if   */
+/* dfr is positive) or to the right (if dfr is negative) without      */
+/* adjusting the exponent or the sign of dfl.                        */
+/*                                                                   */
+/* dfr must be in the range -DECPMAX through +DECPMAX.               */
+/* NaNs are propagated as usual.  An infinite dfl is unaffected (but  */
+/* dfr must be valid). No status is set unless dfr is invalid or an  */
+/* operand is an sNaN. The result is canonical.                      */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatShift(decFloat *result,
+                        const decFloat *dfl, const decFloat *dfr,
+                        decContext *set) {
+  Int shift;                           /* dfr as an Int */
+  uByte buf[DECPMAX*2];                        /* coefficient + padding */
+  uInt digits, savestat;               /* work */
+  bcdnum num;                          /* .. */
+
+  if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set);
+  if (!DFISINT(dfr)) return decInvalid(result, set);
+  digits=decFloatDigits(dfr);                    /* calculate digits */
+  if (digits>2) return decInvalid(result, set);          /* definitely out of range */
+  shift=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff];          /* is in bottom declet */
+  if (shift>DECPMAX) return decInvalid(result, set);   /* too big */
+  /* [from here on no error or status change is possible] */
+
+  if (DFISINF(dfl)) return decInfinity(result, dfl); /* canonical */
+  /* handle no-shift and all-shift (clear to zero) cases */
+  if (shift==0) return decCanonical(result, dfl);
+  if (shift==DECPMAX) {                             /* zero with sign */
+    uByte sign=(uByte)(DFBYTE(dfl, 0)&0x80); /* save sign bit */
+    decFloatZero(result);                   /* make +0 */
+    DFBYTE(result, 0)=(uByte)(DFBYTE(result, 0)|sign); /* and set sign */
+    /* [cannot safely use CopySign] */
+    return result;
+    }
+  /* a real shift is needed: 0 < shift < DECPMAX */
+  num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign;
+  num.exponent=GETEXPUN(dfl);
+  num.msd=buf;
+  GETCOEFF(dfl, buf);
+  if (DFISSIGNED(dfr)) { /* shift right */
+    /* edge cases are taken care of, so this is easy */
+    num.lsd=buf+DECPMAX-shift-1;
+    }
+   else { /* shift left -- zero padding needed to right */
+    UINTAT(buf+DECPMAX)=0;             /* 8 will handle most cases */
+    UINTAT(buf+DECPMAX+4)=0;           /* .. */
+    if (shift>8) memset(buf+DECPMAX+8, 0, 8+QUAD*18); /* all other cases */
+    num.msd+=shift;
+    num.lsd=num.msd+DECPMAX-1;
+    }
+  savestat=set->status;                        /* record */
+  decFinalize(result, &num, set);
+  set->status=savestat;                        /* restore */
+  return result;
+  } /* decFloatShift */
+
+/* ------------------------------------------------------------------ */
+/* decFloatSubtract -- subtract a decFloat from another                      */
+/*                                                                   */
+/*   result gets the result of subtracting dfr from dfl:             */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatSubtract(decFloat *result,
+                           const decFloat *dfl, const decFloat *dfr,
+                           decContext *set) {
+  decFloat temp;
+  /* NaNs must propagate without sign change */
+  if (DFISNAN(dfr)) return decFloatAdd(result, dfl, dfr, set);
+  temp=*dfr;                                  /* make a copy */
+  DFBYTE(&temp, 0)^=0x80;                     /* flip sign */
+  return decFloatAdd(result, dfl, &temp, set); /* and add to the lhs */
+  } /* decFloatSubtract */
+
+/* ------------------------------------------------------------------ */
+/* decFloatToInt -- round to 32-bit binary integer (4 flavours)              */
+/*                                                                   */
+/*   df           is the decFloat to round                                   */
+/*   set   is the context                                            */
+/*   round is the rounding mode to use                               */
+/*   returns a uInt or an Int, rounded according to the name         */
+/*                                                                   */
+/* Invalid will always be signaled if df is a NaN, is Infinite, or is */
+/* outside the range of the target; Inexact will not be signaled for  */
+/* simple rounding unless 'Exact' appears in the name.               */
+/* ------------------------------------------------------------------ */
+uInt decFloatToUInt32(const decFloat *df, decContext *set,
+                     enum rounding round) {
+  return decToInt32(df, set, round, 0, 1);}
+
+uInt decFloatToUInt32Exact(const decFloat *df, decContext *set,
+                          enum rounding round) {
+  return decToInt32(df, set, round, 1, 1);}
+
+Int decFloatToInt32(const decFloat *df, decContext *set,
+                   enum rounding round) {
+  return (Int)decToInt32(df, set, round, 0, 0);}
+
+Int decFloatToInt32Exact(const decFloat *df, decContext *set,
+                        enum rounding round) {
+  return (Int)decToInt32(df, set, round, 1, 0);}
+
+/* ------------------------------------------------------------------ */
+/* decFloatToIntegral -- round to integral value (two flavours)              */
+/*                                                                   */
+/*   result gets the result                                          */
+/*   df            is the decFloat to round                                  */
+/*   set    is the context                                           */
+/*   round  is the rounding mode to use                                      */
+/*   returns result                                                  */
+/*                                                                   */
+/* No exceptions, even Inexact, are raised except for sNaN input, or  */
+/* if 'Exact' appears in the name.                                   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatToIntegralValue(decFloat *result, const decFloat *df,
+                                  decContext *set, enum rounding round) {
+  return decToIntegral(result, df, set, round, 0);}
+
+decFloat * decFloatToIntegralExact(decFloat *result, const decFloat *df,
+                                  decContext *set) {
+  return decToIntegral(result, df, set, set->round, 1);}
+
+/* ------------------------------------------------------------------ */
+/* decFloatXor -- logical digitwise XOR of two decFloats             */
+/*                                                                   */
+/*   result gets the result of XORing dfl and dfr                    */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs)                             */
+/*   set    is the context                                           */
+/*   returns result, which will be canonical with sign=0             */
+/*                                                                   */
+/* The operands must be positive, finite with exponent q=0, and              */
+/* comprise just zeros and ones; if not, Invalid operation results.   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatXor(decFloat *result,
+                      const decFloat *dfl, const decFloat *dfr,
+                      decContext *set) {
+  if (!DFISUINT01(dfl) || !DFISUINT01(dfr)
+   || !DFISCC01(dfl)   || !DFISCC01(dfr)) return decInvalid(result, set);
+  /* the operands are positive finite integers (q=0) with just 0s and 1s */
+  #if DOUBLE
+   DFWORD(result, 0)=ZEROWORD
+                  |((DFWORD(dfl, 0) ^ DFWORD(dfr, 0))&0x04009124);
+   DFWORD(result, 1)=(DFWORD(dfl, 1) ^ DFWORD(dfr, 1))&0x49124491;
+  #elif QUAD
+   DFWORD(result, 0)=ZEROWORD
+                  |((DFWORD(dfl, 0) ^ DFWORD(dfr, 0))&0x04000912);
+   DFWORD(result, 1)=(DFWORD(dfl, 1) ^ DFWORD(dfr, 1))&0x44912449;
+   DFWORD(result, 2)=(DFWORD(dfl, 2) ^ DFWORD(dfr, 2))&0x12449124;
+   DFWORD(result, 3)=(DFWORD(dfl, 3) ^ DFWORD(dfr, 3))&0x49124491;
+  #endif
+  return result;
+  } /* decFloatXor */
+
+/* ------------------------------------------------------------------ */
+/* decInvalid -- set Invalid_operation result                        */
+/*                                                                   */
+/*   result gets a canonical NaN                                     */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* status has Invalid_operation added                                */
+/* ------------------------------------------------------------------ */
+static decFloat *decInvalid(decFloat *result, decContext *set) {
+  decFloatZero(result);
+  DFWORD(result, 0)=DECFLOAT_qNaN;
+  set->status|=DEC_Invalid_operation;
+  return result;
+  } /* decInvalid */
+
+/* ------------------------------------------------------------------ */
+/* decInfinity -- set canonical Infinity with sign from a decFloat    */
+/*                                                                   */
+/*   result gets a canonical Infinity                                */
+/*   df            is source decFloat (only the sign is used)                */
+/*   returns result                                                  */
+/*                                                                   */
+/* df may be the same as result                                              */
+/* ------------------------------------------------------------------ */
+static decFloat *decInfinity(decFloat *result, const decFloat *df) {
+  uInt sign=DFWORD(df, 0);        /* save source signword */
+  decFloatZero(result);                   /* clear everything */
+  DFWORD(result, 0)=DECFLOAT_Inf | (sign & DECFLOAT_Sign);
+  return result;
+  } /* decInfinity */
+
+/* ------------------------------------------------------------------ */
+/* decNaNs -- handle NaN argument(s)                                 */
+/*                                                                   */
+/*   result gets the result of handling dfl and dfr, one or both of   */
+/*         which is a NaN                                            */
+/*   dfl    is the first decFloat (lhs)                                      */
+/*   dfr    is the second decFloat (rhs) -- may be NULL for a single- */
+/*         operand operation                                         */
+/*   set    is the context                                           */
+/*   returns result                                                  */
+/*                                                                   */
+/* Called when one or both operands is a NaN, and propagates the      */
+/* appropriate result to res.  When an sNaN is found, it is changed   */
+/* to a qNaN and Invalid operation is set.                           */
+/* ------------------------------------------------------------------ */
+static decFloat *decNaNs(decFloat *result,
+                        const decFloat *dfl, const decFloat *dfr,
+                        decContext *set) {
+  /* handle sNaNs first */
+  if (dfr!=NULL && DFISSNAN(dfr) && !DFISSNAN(dfl)) dfl=dfr; /* use RHS */
+  if (DFISSNAN(dfl)) {
+    decCanonical(result, dfl);         /* propagate canonical sNaN */
+    DFWORD(result, 0)&=~(DECFLOAT_qNaN ^ DECFLOAT_sNaN); /* quiet */
+    set->status|=DEC_Invalid_operation;
+    return result;
+    }
+  /* one or both is a quiet NaN */
+  if (!DFISNAN(dfl)) dfl=dfr;          /* RHS must be NaN, use it */
+  return decCanonical(result, dfl);    /* propagate canonical qNaN */
+  } /* decNaNs */
+
+/* ------------------------------------------------------------------ */
+/* decNumCompare -- numeric comparison of two decFloats                      */
+/*                                                                   */
+/*   dfl    is the left-hand decFloat, which is not a NaN            */
+/*   dfr    is the right-hand decFloat, which is not a NaN           */
+/*   tot    is 1 for total order compare, 0 for simple numeric       */
+/*   returns -1, 0, or +1 for dfl<dfr, dfl=dfr, dfl>dfr                      */
+/*                                                                   */
+/* No error is possible; status and mode are unchanged.                      */
+/* ------------------------------------------------------------------ */
+static Int decNumCompare(const decFloat *dfl, const decFloat *dfr, Flag tot) {
+  Int  sigl, sigr;                     /* LHS and RHS non-0 signums */
+  Int  shift;                          /* shift needed to align operands */
+  uByte *ub, *uc;                      /* work */
+  /* buffers +2 if Quad (36 digits), need double plus 4 for safe padding */
+  uByte bufl[DECPMAX*2+QUAD*2+4];      /* for LHS coefficient + padding */
+  uByte bufr[DECPMAX*2+QUAD*2+4];      /* for RHS coefficient + padding */
+
+  sigl=1;
+  if (DFISSIGNED(dfl)) {
+    if (!DFISSIGNED(dfr)) {            /* -LHS +RHS */
+      if (DFISZERO(dfl) && DFISZERO(dfr) && !tot) return 0;
+      return -1;                       /* RHS wins */
+      }
+    sigl=-1;
+    }
+  if (DFISSIGNED(dfr)) {
+    if (!DFISSIGNED(dfl)) {            /* +LHS -RHS */
+      if (DFISZERO(dfl) && DFISZERO(dfr) && !tot) return 0;
+      return +1;                       /* LHS wins */
+      }
+    }
+
+  /* signs are the same; operand(s) could be zero */
+  sigr=-sigl;                          /* sign to return if abs(RHS) wins */
+
+  if (DFISINF(dfl)) {
+    if (DFISINF(dfr)) return 0;                /* both infinite & same sign */
+    return sigl;                       /* inf > n */
+    }
+  if (DFISINF(dfr)) return sigr;       /* n < inf [dfl is finite] */
+
+  /* here, both are same sign and finite; calculate their offset */
+  shift=GETEXP(dfl)-GETEXP(dfr);       /* [0 means aligned] */
+  /* [bias can be ignored -- the absolute exponent is not relevant] */
+
+  if (DFISZERO(dfl)) {
+    if (!DFISZERO(dfr)) return sigr;   /* LHS=0, RHS!=0 */
+    /* both are zero, return 0 if both same exponent or numeric compare */
+    if (shift==0 || !tot) return 0;
+    if (shift>0) return sigl;
+    return sigr;                       /* [shift<0] */
+    }
+   else {                              /* LHS!=0 */
+    if (DFISZERO(dfr)) return sigl;    /* LHS!=0, RHS=0 */
+    }
+  /* both are known to be non-zero at this point */
+
+  /* if the exponents are so different that the coefficients do not */
+  /* overlap (by even one digit) then a full comparison is not needed */
+  if (abs(shift)>=DECPMAX) {           /* no overlap */
+    /* coefficients are known to be non-zero */
+    if (shift>0) return sigl;
+    return sigr;                       /* [shift<0] */
+    }
+
+  /* decode the coefficients */
+  /* (shift both right two if Quad to make a multiple of four) */
+  #if QUAD
+    UINTAT(bufl)=0;
+    UINTAT(bufr)=0;
+  #endif
+  GETCOEFF(dfl, bufl+QUAD*2);          /* decode from decFloat */
+  GETCOEFF(dfr, bufr+QUAD*2);          /* .. */
+  if (shift==0) {                      /* aligned; common and easy */
+    /* all multiples of four, here */
+    for (ub=bufl, uc=bufr; ub<bufl+DECPMAX+QUAD*2; ub+=4, uc+=4) {
+      if (UINTAT(ub)==UINTAT(uc)) continue; /* so far so same */
+      /* about to find a winner; go by bytes in case little-endian */
+      for (;; ub++, uc++) {
+       if (*ub>*uc) return sigl;       /* difference found */
+       if (*ub<*uc) return sigr;       /* .. */
+       }
+      }
+    } /* aligned */
+   else if (shift>0) {                 /* lhs to left */
+    ub=bufl;                           /* RHS pointer */
+    /* pad bufl so right-aligned; most shifts will fit in 8 */
+    UINTAT(bufl+DECPMAX+QUAD*2)=0;     /* add eight zeros */
+    UINTAT(bufl+DECPMAX+QUAD*2+4)=0;   /* .. */
+    if (shift>8) {
+      /* more than eight; fill the rest, and also worth doing the */
+      /* lead-in by fours */
+      uByte *up;                        /* work */
+      uByte *upend=bufl+DECPMAX+QUAD*2+shift;
+      for (up=bufl+DECPMAX+QUAD*2+8; up<upend; up+=4) UINTAT(up)=0;
+      /* [pads up to 36 in all for Quad] */
+      for (;; ub+=4) {
+       if (UINTAT(ub)!=0) return sigl;
+       if (ub+4>bufl+shift-4) break;
+       }
+      }
+    /* check remaining leading digits */
+    for (; ub<bufl+shift; ub++) if (*ub!=0) return sigl;
+    /* now start the overlapped part; bufl has been padded, so the */
+    /* comparison can go for the full length of bufr, which is a */
+    /* multiple of 4 bytes */
+    for (uc=bufr; ; uc+=4, ub+=4) {
+      if (UINTAT(uc)!=UINTAT(ub)) {    /* mismatch found */
+       for (;; uc++, ub++) {           /* check from left [little-endian?] */
+         if (*ub>*uc) return sigl;     /* difference found */
+         if (*ub<*uc) return sigr;     /* .. */
+         }
+       } /* mismatch */
+      if (uc==bufr+QUAD*2+DECPMAX-4) break; /* all checked */
+      }
+    } /* shift>0 */
+
+   else { /* shift<0) .. RHS is to left of LHS; mirror shift>0 */
+    uc=bufr;                           /* RHS pointer */
+    /* pad bufr so right-aligned; most shifts will fit in 8 */
+    UINTAT(bufr+DECPMAX+QUAD*2)=0;     /* add eight zeros */
+    UINTAT(bufr+DECPMAX+QUAD*2+4)=0;   /* .. */
+    if (shift<-8) {
+      /* more than eight; fill the rest, and also worth doing the */
+      /* lead-in by fours */
+      uByte *up;                        /* work */
+      uByte *upend=bufr+DECPMAX+QUAD*2-shift;
+      for (up=bufr+DECPMAX+QUAD*2+8; up<upend; up+=4) UINTAT(up)=0;
+      /* [pads up to 36 in all for Quad] */
+      for (;; uc+=4) {
+       if (UINTAT(uc)!=0) return sigr;
+       if (uc+4>bufr-shift-4) break;
+       }
+      }
+    /* check remaining leading digits */
+    for (; uc<bufr-shift; uc++) if (*uc!=0) return sigr;
+    /* now start the overlapped part; bufr has been padded, so the */
+    /* comparison can go for the full length of bufl, which is a */
+    /* multiple of 4 bytes */
+    for (ub=bufl; ; ub+=4, uc+=4) {
+      if (UINTAT(ub)!=UINTAT(uc)) {    /* mismatch found */
+       for (;; ub++, uc++) {           /* check from left [little-endian?] */
+         if (*ub>*uc) return sigl;     /* difference found */
+         if (*ub<*uc) return sigr;     /* .. */
+         }
+       } /* mismatch */
+      if (ub==bufl+QUAD*2+DECPMAX-4) break; /* all checked */
+      }
+    } /* shift<0 */
+
+  /* Here when compare equal */
+  if (!tot) return 0;                  /* numerically equal */
+  /* total ordering .. exponent matters */
+  if (shift>0) return sigl;            /* total order by exponent */
+  if (shift<0) return sigr;            /* .. */
+  return 0;
+  } /* decNumCompare */
+
+/* ------------------------------------------------------------------ */
+/* decToInt32 -- local routine to effect ToInteger conversions       */
+/*                                                                   */
+/*   df            is the decFloat to convert                                */
+/*   set    is the context                                           */
+/*   rmode  is the rounding mode to use                                      */
+/*   exact  is 1 if Inexact should be signalled                              */
+/*   unsign is 1 if the result a uInt, 0 if an Int (cast to uInt)     */
+/*   returns 32-bit result as a uInt                                 */
+/*                                                                   */
+/* Invalid is set is df is a NaN, is infinite, or is out-of-range; in */
+/* these cases 0 is returned.                                        */
+/* ------------------------------------------------------------------ */
+static uInt decToInt32(const decFloat *df, decContext *set,
+                      enum rounding rmode, Flag exact, Flag unsign) {
+  Int  exp;                       /* exponent */
+  uInt sourhi, sourpen, sourlo;           /* top word from source decFloat .. */
+  uInt hi, lo;                    /* .. penultimate, least, etc. */
+  decFloat zero, result;          /* work */
+  Int  i;                         /* .. */
+
+  /* Start decoding the argument */
+  sourhi=DFWORD(df, 0);                        /* top word */
+  exp=DECCOMBEXP[sourhi>>26];          /* get exponent high bits (in place) */
+  if (EXPISSPECIAL(exp)) {             /* is special? */
+    set->status|=DEC_Invalid_operation; /* signal */
+    return 0;
+    }
+
+  /* Here when the argument is finite */
+  if (GETEXPUN(df)==0) result=*df;     /* already a true integer */
+   else {                              /* need to round to integer */
+    enum rounding saveround;           /* saver */
+    uInt savestatus;                   /* .. */
+    saveround=set->round;              /* save rounding mode .. */
+    savestatus=set->status;            /* .. and status */
+    set->round=rmode;                  /* set mode */
+    decFloatZero(&zero);               /* make 0E+0 */
+    set->status=0;                     /* clear */
+    decFloatQuantize(&result, df, &zero, set); /* [this may fail] */
+    set->round=saveround;              /* restore rounding mode .. */
+    if (exact) set->status|=savestatus; /* include Inexact */
+     else set->status=savestatus;      /* .. or just original status */
+    }
+
+  /* only the last four declets of the coefficient can contain */
+  /* non-zero; check for others (and also NaN or Infinity from the */
+  /* Quantize) first (see DFISZERO for explanation): */
+  /* decFloatShow(&result, "sofar"); */
+  #if DOUBLE
+  if ((DFWORD(&result, 0)&0x1c03ff00)!=0
+   || (DFWORD(&result, 0)&0x60000000)==0x60000000) {
+  #elif QUAD
+  if ((DFWORD(&result, 2)&0xffffff00)!=0
+   ||  DFWORD(&result, 1)!=0
+   || (DFWORD(&result, 0)&0x1c003fff)!=0
+   || (DFWORD(&result, 0)&0x60000000)==0x60000000) {
+  #endif
+    set->status|=DEC_Invalid_operation; /* Invalid or out of range */
+    return 0;
+    }
+  /* get last twelve digits of the coefficent into hi & ho, base */
+  /* 10**9 (see GETCOEFFBILL): */
+  sourlo=DFWORD(&result, DECWORDS-1);
+  lo=DPD2BIN0[sourlo&0x3ff]
+    +DPD2BINK[(sourlo>>10)&0x3ff]
+    +DPD2BINM[(sourlo>>20)&0x3ff];
+  sourpen=DFWORD(&result, DECWORDS-2);
+  hi=DPD2BIN0[((sourpen<<2) | (sourlo>>30))&0x3ff];
+
+  /* according to request, check range carefully */
+  if (unsign) {
+    if (hi>4 || (hi==4 && lo>294967295) || (hi+lo!=0 && DFISSIGNED(&result))) {
+      set->status|=DEC_Invalid_operation; /* out of range */
+      return 0;
+      }
+    return hi*BILLION+lo;
+    }
+  /* signed */
+  if (hi>2 || (hi==2 && lo>147483647)) {
+    /* handle the usual edge case */
+    if (lo==147483648 && hi==2 && DFISSIGNED(&result)) return 0x80000000;
+    set->status|=DEC_Invalid_operation; /* truly out of range */
+    return 0;
+    }
+  i=hi*BILLION+lo;
+  if (DFISSIGNED(&result)) i=-i;
+  return (uInt)i;
+  } /* decToInt32 */
+
+/* ------------------------------------------------------------------ */
+/* decToIntegral -- local routine to effect ToIntegral value         */
+/*                                                                   */
+/*   result gets the result                                          */
+/*   df            is the decFloat to round                                  */
+/*   set    is the context                                           */
+/*   rmode  is the rounding mode to use                                      */
+/*   exact  is 1 if Inexact should be signalled                              */
+/*   returns result                                                  */
+/* ------------------------------------------------------------------ */
+static decFloat * decToIntegral(decFloat *result, const decFloat *df,
+                               decContext *set, enum rounding rmode,
+                               Flag exact) {
+  Int  exp;                       /* exponent */
+  uInt sourhi;                    /* top word from source decFloat */
+  enum rounding saveround;        /* saver */
+  uInt savestatus;                /* .. */
+  decFloat zero;                  /* work */
+
+  /* Start decoding the argument */
+  sourhi=DFWORD(df, 0);                   /* top word */
+  exp=DECCOMBEXP[sourhi>>26];     /* get exponent high bits (in place) */
+
+  if (EXPISSPECIAL(exp)) {        /* is special? */
+    /* NaNs are handled as usual */
+    if (DFISNAN(df)) return decNaNs(result, df, NULL, set);
+    /* must be infinite; return canonical infinity with sign of df */
+    return decInfinity(result, df);
+    }
+
+  /* Here when the argument is finite */
+  /* complete extraction of the exponent */
+  exp+=GETECON(df)-DECBIAS;            /* .. + continuation and unbias */
+
+  if (exp>=0) return decCanonical(result, df); /* already integral */
+
+  saveround=set->round;                        /* save rounding mode .. */
+  savestatus=set->status;              /* .. and status */
+  set->round=rmode;                    /* set mode */
+  decFloatZero(&zero);                 /* make 0E+0 */
+  decFloatQuantize(result, df, &zero, set); /* 'integrate'; cannot fail */
+  set->round=saveround;                        /* restore rounding mode .. */
+  if (!exact) set->status=savestatus;  /* .. and status, unless exact */
+  return result;
+  } /* decToIntegral */
diff --git a/libdecnumber/decCommon.c b/libdecnumber/decCommon.c
new file mode 100644 (file)
index 0000000..84e1b2a
--- /dev/null
@@ -0,0 +1,1771 @@
+/* Common code for fixed-size types in the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* decCommon.c -- common code for all three fixed-size types         */
+/* ------------------------------------------------------------------ */
+/* This module comprises code that is shared between all the formats  */
+/* (decSingle, decDouble, and decQuad); it includes set and extract   */
+/* of format components, widening, narrowing, and string conversions. */
+/*                                                                   */
+/* Unlike decNumber, parameterization takes place at compile time     */
+/* rather than at runtime.  The parameters are set in the decDouble.c */
+/* (etc.) files, which then include this one to produce the compiled  */
+/* code.  The functions here, therefore, are code shared between      */
+/* multiple formats.                                                 */
+/* ------------------------------------------------------------------ */
+/* Names here refer to decFloat rather than to decDouble, etc., and */
+/* the functions are in strict alphabetical order. */
+/* Constants, tables, and debug function(s) are included only for QUAD */
+/* (which will always be compiled if DOUBLE or SINGLE are used). */
+/* */
+/* Whenever a decContext is used, only the status may be set (using */
+/* OR) or the rounding mode read; all other fields are ignored and */
+/* untouched. */
+
+/* names for simpler testing and default context */
+#if DECPMAX==7
+  #define SINGLE     1
+  #define DOUBLE     0
+  #define QUAD      0
+  #define DEFCONTEXT DEC_INIT_DECIMAL32
+#elif DECPMAX==16
+  #define SINGLE     0
+  #define DOUBLE     1
+  #define QUAD      0
+  #define DEFCONTEXT DEC_INIT_DECIMAL64
+#elif DECPMAX==34
+  #define SINGLE     0
+  #define DOUBLE     0
+  #define QUAD      1
+  #define DEFCONTEXT DEC_INIT_DECIMAL128
+#else
+  #error Unexpected DECPMAX value
+#endif
+
+/* Assertions */
+
+#if DECPMAX!=7 && DECPMAX!=16 && DECPMAX!=34
+  #error Unexpected Pmax (DECPMAX) value for this module
+#endif
+
+/* Assert facts about digit characters, etc. */
+#if ('9'&0x0f)!=9
+  #error This module assumes characters are of the form 0b....nnnn
+  /* where .... are don't care 4 bits and nnnn is 0000 through 1001 */
+#endif
+#if ('9'&0xf0)==('.'&0xf0)
+  #error This module assumes '.' has a different mask than a digit
+#endif
+
+/* Assert ToString lay-out conditions */
+#if DECSTRING<DECPMAX+9
+  #error ToString needs at least 8 characters for lead-in and dot
+#endif
+#if DECPMAX+DECEMAXD+5 > DECSTRING
+  #error Exponent form can be too long for ToString to lay out safely
+#endif
+#if DECEMAXD > 4
+  #error Exponent form is too long for ToString to lay out
+  /* Note: code for up to 9 digits exists in archives [decOct] */
+#endif
+
+/* Private functions used here and possibly in decBasic.c, etc. */
+static decFloat * decFinalize(decFloat *, bcdnum *, decContext *);
+static Flag decBiStr(const char *, const char *, const char *);
+
+/* Macros and private tables; those which are not format-dependent    */
+/* are only included if decQuad is being built.                              */
+
+/* ------------------------------------------------------------------ */
+/* Combination field lookup tables (uInts to save measurable work)    */
+/*                                                                   */
+/*   DECCOMBEXP         - 2 most-significant-bits of exponent (00, 01, or    */
+/*                10), shifted left for format, or DECFLOAT_Inf/NaN  */
+/*   DECCOMBWEXP - The same, for the next-wider format (unless QUAD)  */
+/*   DECCOMBMSD         - 4-bit most-significant-digit                       */
+/*                [0 if the index is a special (Infinity or NaN)]    */
+/*   DECCOMBFROM - 5-bit combination field from EXP top bits and MSD  */
+/*                (placed in uInt so no shift is needed)             */
+/*                                                                   */
+/* DECCOMBEXP, DECCOMBWEXP, and DECCOMBMSD are indexed by the sign    */
+/*   and 5-bit combination field (0-63, the second half of the table  */
+/*   identical to the first half)                                    */
+/* DECCOMBFROM is indexed by expTopTwoBits*16 + msd                  */
+/*                                                                   */
+/* DECCOMBMSD and DECCOMBFROM are not format-dependent and so are     */
+/* only included once, when QUAD is being built                              */
+/* ------------------------------------------------------------------ */
+static const uInt DECCOMBEXP[64]={
+  0, 0, 0, 0, 0, 0, 0, 0,
+  1<<DECECONL, 1<<DECECONL, 1<<DECECONL, 1<<DECECONL,
+  1<<DECECONL, 1<<DECECONL, 1<<DECECONL, 1<<DECECONL,
+  2<<DECECONL, 2<<DECECONL, 2<<DECECONL, 2<<DECECONL,
+  2<<DECECONL, 2<<DECECONL, 2<<DECECONL, 2<<DECECONL,
+  0,          0,           1<<DECECONL, 1<<DECECONL,
+  2<<DECECONL, 2<<DECECONL, DECFLOAT_Inf, DECFLOAT_NaN,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  1<<DECECONL, 1<<DECECONL, 1<<DECECONL, 1<<DECECONL,
+  1<<DECECONL, 1<<DECECONL, 1<<DECECONL, 1<<DECECONL,
+  2<<DECECONL, 2<<DECECONL, 2<<DECECONL, 2<<DECECONL,
+  2<<DECECONL, 2<<DECECONL, 2<<DECECONL, 2<<DECECONL,
+  0,          0,           1<<DECECONL, 1<<DECECONL,
+  2<<DECECONL, 2<<DECECONL, DECFLOAT_Inf, DECFLOAT_NaN};
+#if !QUAD
+static const uInt DECCOMBWEXP[64]={
+  0, 0, 0, 0, 0, 0, 0, 0,
+  1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL,
+  1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL,
+  2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL,
+  2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL,
+  0,           0,            1<<DECWECONL, 1<<DECWECONL,
+  2<<DECWECONL, 2<<DECWECONL, DECFLOAT_Inf, DECFLOAT_NaN,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL,
+  1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL,
+  2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL,
+  2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL,
+  0,           0,            1<<DECWECONL, 1<<DECWECONL,
+  2<<DECWECONL, 2<<DECWECONL, DECFLOAT_Inf, DECFLOAT_NaN};
+#endif
+
+#if QUAD
+const uInt DECCOMBMSD[64]={
+  0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 1,
+  0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 0};
+
+const uInt DECCOMBFROM[48]={
+  0x00000000, 0x04000000, 0x08000000, 0x0C000000, 0x10000000, 0x14000000,
+  0x18000000, 0x1C000000, 0x60000000, 0x64000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x20000000, 0x24000000,
+  0x28000000, 0x2C000000, 0x30000000, 0x34000000, 0x38000000, 0x3C000000,
+  0x68000000, 0x6C000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+  0x00000000, 0x00000000, 0x40000000, 0x44000000, 0x48000000, 0x4C000000,
+  0x50000000, 0x54000000, 0x58000000, 0x5C000000, 0x70000000, 0x74000000,
+  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
+
+/* ------------------------------------------------------------------ */
+/* Request and include the tables to use for conversions             */
+/* ------------------------------------------------------------------ */
+#define DEC_BCD2DPD  1       /* 0-0x999 -> DPD */
+#define DEC_BIN2DPD  1       /* 0-999 -> DPD */
+#define DEC_BIN2BCD8 1       /* 0-999 -> ddd, len */
+#define DEC_DPD2BCD8 1       /* DPD -> ddd, len */
+#define DEC_DPD2BIN  1       /* DPD -> 0-999 */
+#define DEC_DPD2BINK 1       /* DPD -> 0-999000 */
+#define DEC_DPD2BINM 1       /* DPD -> 0-999000000 */
+#include "decDPD.h"          /* source of the lookup tables */
+
+#endif
+
+/* ----------------------------------------------------------------- */
+/* decBiStr -- compare string with pairwise options                 */
+/*                                                                  */
+/*   targ is the string to compare                                  */
+/*   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          */
+/*                                                                  */
+/*   returns 1 if strings compare equal, (that is, targ is the same  */
+/*   length as str1 and str2, and each character of targ is in one   */
+/*   of str1 or str2 in the corresponding position), or 0 otherwise  */
+/*                                                                  */
+/* This is used for generic caseless compare, including the awkward  */
+/* case of the Turkish dotted and dotless Is.  Use as (for example): */
+/*   if (decBiStr(test, "mike", "MIKE")) ...                        */
+/* ----------------------------------------------------------------- */
+static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
+  for (;;targ++, str1++, str2++) {
+    if (*targ!=*str1 && *targ!=*str2) return 0;
+    /* *targ has a match in one (or both, if terminator) */
+    if (*targ=='\0') break;
+    } /* forever */
+  return 1;
+  } /* decBiStr */
+
+/* ------------------------------------------------------------------ */
+/* decFinalize -- adjust and store a final result                    */
+/*                                                                   */
+/*  df is the decFloat format number which gets the final result     */
+/*  num is the descriptor of the number to be checked and encoded     */
+/*        [its values, including the coefficient, may be modified]   */
+/*  set is the context to use                                        */
+/*  returns df                                                       */
+/*                                                                   */
+/* The num descriptor may point to a bcd8 string of any length; this  */
+/* string may have leading insignificant zeros.         If it has more than  */
+/* DECPMAX digits then the final digit can be a round-for-reround     */
+/* digit (i.e., it may include a sticky bit residue).                */
+/*                                                                   */
+/* The exponent (q) may be one of the codes for a special value and   */
+/* can be up to 999999999 for conversion from string.                */
+/*                                                                   */
+/* No error is possible, but Inexact, Underflow, and/or Overflow may  */
+/* be set.                                                           */
+/* ------------------------------------------------------------------ */
+/* Constant whose size varies with format; also the check for surprises */
+static uByte allnines[DECPMAX]=
+#if SINGLE
+  {9, 9, 9, 9, 9, 9, 9};
+#elif DOUBLE
+  {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
+#elif QUAD
+  {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+   9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
+#endif
+
+static decFloat * decFinalize(decFloat *df, bcdnum *num,
+                             decContext *set) {
+  uByte *ub;                 /* work */
+  uInt  dpd;                 /* .. */
+  uByte *umsd=num->msd;              /* local copy */
+  uByte *ulsd=num->lsd;              /* .. */
+  uInt  encode;              /* encoding accumulator */
+  Int   length;              /* coefficient length */
+
+  #if DECCHECK
+  Int clen=ulsd-umsd+1;
+  #if QUAD
+    #define COEXTRA 2                       /* extra-long coefficent */
+  #else
+    #define COEXTRA 0
+  #endif
+  if (clen<1 || clen>DECPMAX*3+2+COEXTRA)
+    printf("decFinalize: suspect coefficient [length=%ld]\n", (LI)clen);
+  if (num->sign!=0 && num->sign!=DECFLOAT_Sign)
+    printf("decFinalize: bad sign [%08lx]\n", (LI)num->sign);
+  if (!EXPISSPECIAL(num->exponent)
+      && (num->exponent>1999999999 || num->exponent<-1999999999))
+    printf("decFinalize: improbable exponent [%ld]\n", (LI)num->exponent);
+  /* decShowNum(num, "final"); */
+  #endif
+
+  /* A special will have an 'exponent' which is very positive and a */
+  /* coefficient < DECPMAX */
+  length=(uInt)(ulsd-umsd+1);               /* coefficient length */
+
+  if (!NUMISSPECIAL(num)) {
+    Int          drop;                              /* digits to be dropped */
+    /* skip leading insignificant zeros to calculate an exact length */
+    /* [this is quite expensive] */
+    if (*umsd==0) {
+      for (; UINTAT(umsd)==0 && umsd+3<ulsd;) umsd+=4;
+      for (; *umsd==0 && umsd<ulsd;) umsd++;
+      length=ulsd-umsd+1;                   /* recalculate */
+      }
+    drop=MAXI(length-DECPMAX, DECQTINY-num->exponent);
+    /* drop can now be > digits for bottom-clamp (subnormal) cases */
+    if (drop>0) {                           /* rounding needed */
+      /* (decFloatQuantize has very similar code to this, so any */
+      /* changes may need to be made there, too) */
+      uByte *roundat;                       /* -> re-round digit */
+      uByte reround;                        /* reround value */
+      /* printf("Rounding; drop=%ld\n", (LI)drop); */
+
+      num->exponent+=drop;                  /* always update exponent */
+
+      /* Three cases here: */
+      /*   1. new LSD is in coefficient (almost always) */
+      /*   2. new LSD is digit to left of coefficient (so MSD is */
+      /*      round-for-reround digit) */
+      /*   3. new LSD is to left of case 2 (whole coefficient is sticky) */
+      /* [duplicate check-stickies code to save a test] */
+      /* [by-digit check for stickies as runs of zeros are rare] */
+      if (drop<length) {                    /* NB lengths not addresses */
+       roundat=umsd+length-drop;
+       reround=*roundat;
+       for (ub=roundat+1; ub<=ulsd; ub++) {
+         if (*ub!=0) {                      /* non-zero to be discarded */
+           reround=DECSTICKYTAB[reround];   /* apply sticky bit */
+           break;                           /* [remainder don't-care] */
+           }
+         } /* check stickies */
+       ulsd=roundat-1;                      /* new LSD */
+       }
+       else {                               /* edge case */
+       if (drop==length) {
+         roundat=umsd;
+         reround=*roundat;
+         }
+        else {
+         roundat=umsd-1;
+         reround=0;
+         }
+       for (ub=roundat+1; ub<=ulsd; ub++) {
+         if (*ub!=0) {                      /* non-zero to be discarded */
+           reround=DECSTICKYTAB[reround];   /* apply sticky bit */
+           break;                           /* [remainder don't-care] */
+           }
+         } /* check stickies */
+       *umsd=0;                             /* coefficient is a 0 */
+       ulsd=umsd;                           /* .. */
+       }
+
+      if (reround!=0) {                             /* discarding non-zero */
+       uInt bump=0;
+       set->status|=DEC_Inexact;
+       /* if adjusted exponent [exp+digits-1] is < EMIN then num is */
+       /* subnormal -- so raise Underflow */
+       if (num->exponent<DECEMIN && (num->exponent+(ulsd-umsd+1)-1)<DECEMIN)
+         set->status|=DEC_Underflow;
+
+       /* next decide whether increment of the coefficient is needed */
+       if (set->round==DEC_ROUND_HALF_EVEN) {    /* fastpath slowest case */
+         if (reround>5) bump=1;                  /* >0.5 goes up */
+          else if (reround==5)                   /* exactly 0.5000 .. */
+           bump=*ulsd & 0x01;                    /* .. up iff [new] lsd is odd */
+         } /* r-h-e */
+        else switch (set->round) {
+         case DEC_ROUND_DOWN: {
+           /* no change */
+           break;} /* r-d */
+         case DEC_ROUND_HALF_DOWN: {
+           if (reround>5) bump=1;
+           break;} /* r-h-d */
+         case DEC_ROUND_HALF_UP: {
+           if (reround>=5) bump=1;
+           break;} /* r-h-u */
+         case DEC_ROUND_UP: {
+           if (reround>0) bump=1;
+           break;} /* r-u */
+         case DEC_ROUND_CEILING: {
+           /* same as _UP for positive numbers, and as _DOWN for negatives */
+           if (!num->sign && reround>0) bump=1;
+           break;} /* r-c */
+         case DEC_ROUND_FLOOR: {
+           /* same as _UP for negative numbers, and as _DOWN for positive */
+           /* [negative reround cannot occur on 0] */
+           if (num->sign && reround>0) bump=1;
+           break;} /* r-f */
+         case DEC_ROUND_05UP: {
+           if (reround>0) { /* anything out there is 'sticky' */
+             /* bump iff lsd=0 or 5; this cannot carry so it could be */
+             /* effected immediately with no bump -- but the code */
+             /* is clearer if this is done the same way as the others */
+             if (*ulsd==0 || *ulsd==5) bump=1;
+             }
+           break;} /* r-r */
+         default: {      /* e.g., DEC_ROUND_MAX */
+           set->status|=DEC_Invalid_context;
+           #if DECCHECK
+           printf("Unknown rounding mode: %ld\n", (LI)set->round);
+           #endif
+           break;}
+         } /* switch (not r-h-e) */
+       /* printf("ReRound: %ld  bump: %ld\n", (LI)reround, (LI)bump); */
+
+       if (bump!=0) {                       /* need increment */
+         /* increment the coefficient; this might end up with 1000... */
+         /* (after the all nines case) */
+         ub=ulsd;
+         for(; ub-3>=umsd && UINTAT(ub-3)==0x09090909; ub-=4) UINTAT(ub-3)=0;
+         /* [note ub could now be to left of msd, and it is not safe */
+         /* to write to the the left of the msd] */
+         /* now at most 3 digits left to non-9 (usually just the one) */
+         for (; ub>=umsd; *ub=0, ub--) {
+           if (*ub==9) continue;            /* carry */
+           *ub+=1;
+           break;
+           }
+         if (ub<umsd) {                     /* had all-nines */
+           *umsd=1;                         /* coefficient to 1000... */
+           /* usually the 1000... coefficient can be used as-is */
+           if ((ulsd-umsd+1)==DECPMAX) {
+             num->exponent++;
+             }
+            else {
+             /* if coefficient is shorter than Pmax then num is */
+             /* subnormal, so extend it; this is safe as drop>0 */
+             /* (or, if the coefficient was supplied above, it could */
+             /* not be 9); this may make the result normal. */
+             ulsd++;
+             *ulsd=0;
+             /* [exponent unchanged] */
+             #if DECCHECK
+             if (num->exponent!=DECQTINY) /* sanity check */
+               printf("decFinalize: bad all-nines extend [^%ld, %ld]\n",
+                      (LI)num->exponent, (LI)(ulsd-umsd+1));
+             #endif
+             } /* subnormal extend */
+           } /* had all-nines */
+         } /* bump needed */
+       } /* inexact rounding */
+
+      length=ulsd-umsd+1;              /* recalculate (may be <DECPMAX) */
+      } /* need round (drop>0) */
+
+    /* The coefficient will now fit and has final length unless overflow */
+    /* decShowNum(num, "rounded"); */
+
+    /* if exponent is >=emax may have to clamp, overflow, or fold-down */
+    if (num->exponent>DECEMAX-(DECPMAX-1)) { /* is edge case */
+      /* printf("overflow checks...\n"); */
+      if (*ulsd==0 && ulsd==umsd) {    /* have zero */
+       num->exponent=DECEMAX-(DECPMAX-1); /* clamp to max */
+       }
+       else if ((num->exponent+length-1)>DECEMAX) { /* > Nmax */
+       /* Overflow -- these could go straight to encoding, here, but */
+       /* instead num is adjusted to keep the code cleaner */
+       Flag needmax=0;                 /* 1 for finite result */
+       set->status|=(DEC_Overflow | DEC_Inexact);
+       switch (set->round) {
+         case DEC_ROUND_DOWN: {
+           needmax=1;                  /* never Infinity */
+           break;} /* r-d */
+         case DEC_ROUND_05UP: {
+           needmax=1;                  /* never Infinity */
+           break;} /* r-05 */
+         case DEC_ROUND_CEILING: {
+           if (num->sign) needmax=1;   /* Infinity iff non-negative */
+           break;} /* r-c */
+         case DEC_ROUND_FLOOR: {
+           if (!num->sign) needmax=1;  /* Infinity iff negative */
+           break;} /* r-f */
+         default: break;               /* Infinity in all other cases */
+         }
+       if (!needmax) {                 /* easy .. set Infinity */
+         num->exponent=DECFLOAT_Inf;
+         *umsd=0;                      /* be clean: coefficient to 0 */
+         ulsd=umsd;                    /* .. */
+         }
+        else {                         /* return Nmax */
+         umsd=allnines;                /* use constant array */
+         ulsd=allnines+DECPMAX-1;
+         num->exponent=DECEMAX-(DECPMAX-1);
+         }
+       }
+       else { /* no overflow but non-zero and may have to fold-down */
+       Int shift=num->exponent-(DECEMAX-(DECPMAX-1));
+       if (shift>0) {                  /* fold-down needed */
+         /* fold down needed; must copy to buffer in order to pad */
+         /* with zeros safely; fortunately this is not the worst case */
+         /* path because cannot have had a round */
+         uByte buffer[ROUNDUP(DECPMAX+3, 4)]; /* [+3 allows uInt padding] */
+         uByte *s=umsd;                /* source */
+         uByte *t=buffer;              /* safe target */
+         uByte *tlsd=buffer+(ulsd-umsd)+shift; /* target LSD */
+         /* printf("folddown shift=%ld\n", (LI)shift); */
+         for (; s<=ulsd; s+=4, t+=4) UINTAT(t)=UINTAT(s);
+         for (t=tlsd-shift+1; t<=tlsd; t+=4) UINTAT(t)=0;  /* pad */
+         num->exponent-=shift;
+         umsd=buffer;
+         ulsd=tlsd;
+         }
+       } /* fold-down? */
+      length=ulsd-umsd+1;              /* recalculate length */
+      } /* high-end edge case */
+    } /* finite number */
+
+  /*------------------------------------------------------------------*/
+  /* At this point the result will properly fit the decFloat         */
+  /* encoding, and it can be encoded with no possibility of error     */
+  /*------------------------------------------------------------------*/
+  /* Following code does not alter coefficient (could be allnines array) */
+
+  if (length==DECPMAX) {
+    return decFloatFromBCD(df, num->exponent, umsd, num->sign);
+    }
+
+  /* Here when length is short */
+  if (!NUMISSPECIAL(num)) {            /* is still finite */
+    /* encode the combination field and exponent continuation */
+    uInt uexp=(uInt)(num->exponent+DECBIAS); /* biased exponent */
+    uInt code=(uexp>>DECECONL)<<4;     /* top two bits of exp */
+    /* [msd=0] */
+    /* look up the combination field and make high word */
+    encode=DECCOMBFROM[code];          /* indexed by (0-2)*16+msd */
+    encode|=(uexp<<(32-6-DECECONL)) & 0x03ffffff; /* exponent continuation */
+    }
+   else encode=num->exponent;          /* special [already in word] */
+  /* [coefficient length here will be < DECPMAX] */
+
+  encode|=num->sign;                   /* add sign */
+
+  /* private macro to extract a declet, n (where 0<=n<DECLETS and 0 */
+  /* refers to the declet from the least significant three digits) */
+  /* and put the corresponding DPD code into dpd.  Access to umsd and */
+  /* ulsd (pointers to the most and least significant digit of the */
+  /* variable-length coefficient) is assumed, along with use of a */
+  /* working pointer, uInt *ub. */
+  /* As not full-length then chances are there are many leading zeros */
+  /* [and there may be a partial triad] */
+  #define getDPD(dpd, n) ub=ulsd-(3*(n))-2;                          \
+    if (ub<umsd-2) dpd=0;                                            \
+     else if (ub>=umsd) dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)];  \
+     else {dpd=*(ub+2); if (ub+1==umsd) dpd+=*(ub+1)*16; dpd=BCD2DPD[dpd];}
+
+  /* place the declets in the encoding words and copy to result (df), */
+  /* according to endianness; in all cases complete the sign word */
+  /* first */
+  #if DECPMAX==7
+    getDPD(dpd, 1);
+    encode|=dpd<<10;
+    getDPD(dpd, 0);
+    encode|=dpd;
+    DFWORD(df, 0)=encode;     /* just the one word */
+
+  #elif DECPMAX==16
+    getDPD(dpd, 4); encode|=dpd<<8;
+    getDPD(dpd, 3); encode|=dpd>>2;
+    DFWORD(df, 0)=encode;
+    encode=dpd<<30;
+    getDPD(dpd, 2); encode|=dpd<<20;
+    getDPD(dpd, 1); encode|=dpd<<10;
+    getDPD(dpd, 0); encode|=dpd;
+    DFWORD(df, 1)=encode;
+
+  #elif DECPMAX==34
+    getDPD(dpd,10); encode|=dpd<<4;
+    getDPD(dpd, 9); encode|=dpd>>6;
+    DFWORD(df, 0)=encode;
+
+    encode=dpd<<26;
+    getDPD(dpd, 8); encode|=dpd<<16;
+    getDPD(dpd, 7); encode|=dpd<<6;
+    getDPD(dpd, 6); encode|=dpd>>4;
+    DFWORD(df, 1)=encode;
+
+    encode=dpd<<28;
+    getDPD(dpd, 5); encode|=dpd<<18;
+    getDPD(dpd, 4); encode|=dpd<<8;
+    getDPD(dpd, 3); encode|=dpd>>2;
+    DFWORD(df, 2)=encode;
+
+    encode=dpd<<30;
+    getDPD(dpd, 2); encode|=dpd<<20;
+    getDPD(dpd, 1); encode|=dpd<<10;
+    getDPD(dpd, 0); encode|=dpd;
+    DFWORD(df, 3)=encode;
+  #endif
+
+  /* printf("Status: %08lx\n", (LI)set->status); */
+  /* decFloatShow(df, "final"); */
+  return df;
+  } /* decFinalize */
+
+/* ------------------------------------------------------------------ */
+/* decFloatFromBCD -- set decFloat from exponent, BCD8, and sign      */
+/*                                                                   */
+/*  df is the target decFloat                                        */
+/*  exp is the in-range unbiased exponent, q, or a special value in   */
+/*    the form returned by decFloatGetExponent                       */
+/*  bcdar holds DECPMAX digits to set the coefficient from, one              */
+/*    digit in each byte (BCD8 encoding); the first (MSD) is ignored  */
+/*    if df is a NaN; all are ignored if df is infinite.             */
+/*    All bytes must be in 0-9; results undefined otherwise.         */
+/*  sig is DECFLOAT_Sign to set the sign bit, 0 otherwise            */
+/*  returns df, which will be canonical                                      */
+/*                                                                   */
+/* No error is possible, and no status will be set.                  */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatFromBCD(decFloat *df, Int exp, const uByte *bcdar,
+                          Int sig) {
+  uInt encode, dpd;                    /* work */
+  const uByte *ub;                     /* .. */
+
+  if (EXPISSPECIAL(exp)) encode=exp|sig;/* specials already encoded */
+   else {                              /* is finite */
+    /* encode the combination field and exponent continuation */
+    uInt uexp=(uInt)(exp+DECBIAS);     /* biased exponent */
+    uInt code=(uexp>>DECECONL)<<4;     /* top two bits of exp */
+    code+=bcdar[0];                    /* add msd */
+    /* look up the combination field and make high word */
+    encode=DECCOMBFROM[code]|sig;      /* indexed by (0-2)*16+msd */
+    encode|=(uexp<<(32-6-DECECONL)) & 0x03ffffff; /* exponent continuation */
+    }
+
+  /* private macro to extract a declet, n (where 0<=n<DECLETS and 0 */
+  /* refers to the declet from the least significant three digits) */
+  /* and put the corresponding DPD code into dpd. */
+  /* Use of a working pointer, uInt *ub, is assumed. */
+
+  #define getDPDf(dpd, n) ub=bcdar+DECPMAX-1-(3*(n))-2;            \
+    dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)];
+
+  /* place the declets in the encoding words and copy to result (df), */
+  /* according to endianness; in all cases complete the sign word */
+  /* first */
+  #if DECPMAX==7
+    getDPDf(dpd, 1);
+    encode|=dpd<<10;
+    getDPDf(dpd, 0);
+    encode|=dpd;
+    DFWORD(df, 0)=encode;     /* just the one word */
+
+  #elif DECPMAX==16
+    getDPDf(dpd, 4); encode|=dpd<<8;
+    getDPDf(dpd, 3); encode|=dpd>>2;
+    DFWORD(df, 0)=encode;
+    encode=dpd<<30;
+    getDPDf(dpd, 2); encode|=dpd<<20;
+    getDPDf(dpd, 1); encode|=dpd<<10;
+    getDPDf(dpd, 0); encode|=dpd;
+    DFWORD(df, 1)=encode;
+
+  #elif DECPMAX==34
+    getDPDf(dpd,10); encode|=dpd<<4;
+    getDPDf(dpd, 9); encode|=dpd>>6;
+    DFWORD(df, 0)=encode;
+
+    encode=dpd<<26;
+    getDPDf(dpd, 8); encode|=dpd<<16;
+    getDPDf(dpd, 7); encode|=dpd<<6;
+    getDPDf(dpd, 6); encode|=dpd>>4;
+    DFWORD(df, 1)=encode;
+
+    encode=dpd<<28;
+    getDPDf(dpd, 5); encode|=dpd<<18;
+    getDPDf(dpd, 4); encode|=dpd<<8;
+    getDPDf(dpd, 3); encode|=dpd>>2;
+    DFWORD(df, 2)=encode;
+
+    encode=dpd<<30;
+    getDPDf(dpd, 2); encode|=dpd<<20;
+    getDPDf(dpd, 1); encode|=dpd<<10;
+    getDPDf(dpd, 0); encode|=dpd;
+    DFWORD(df, 3)=encode;
+  #endif
+  /* decFloatShow(df, "final"); */
+  return df;
+  } /* decFloatFromBCD */
+
+/* ------------------------------------------------------------------ */
+/* decFloatFromPacked -- set decFloat from exponent and packed BCD    */
+/*                                                                   */
+/*  df is the target decFloat                                        */
+/*  exp is the in-range unbiased exponent, q, or a special value in   */
+/*    the form returned by decFloatGetExponent                       */
+/*  packed holds DECPMAX packed decimal digits plus a sign nibble     */
+/*    (all 6 codes are OK); the first (MSD) is ignored if df is a NaN */
+/*    and all except sign are ignored if df is infinite.  For DOUBLE  */
+/*    and QUAD the first (pad) nibble is also ignored in all cases.   */
+/*    All coefficient nibbles must be in 0-9 and sign in A-F; results */
+/*    are undefined otherwise.                                       */
+/*  returns df, which will be canonical                                      */
+/*                                                                   */
+/* No error is possible, and no status will be set.                  */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) {
+  uByte bcdar[DECPMAX+2];              /* work [+1 for pad, +1 for sign] */
+  const uByte *ip;                     /* .. */
+  uByte *op;                           /* .. */
+  Int  sig=0;                          /* sign */
+
+  /* expand coefficient and sign to BCDAR */
+  #if SINGLE
+  op=bcdar+1;                          /* no pad digit */
+  #else
+  op=bcdar;                            /* first (pad) digit ignored */
+  #endif
+  for (ip=packed; ip<packed+((DECPMAX+2)/2); ip++) {
+    *op++=*ip>>4;
+    *op++=(uByte)(*ip&0x0f);           /* [final nibble is sign] */
+    }
+  op--;                                        /* -> sign byte */
+  if (*op==DECPMINUS || *op==DECPMINUSALT) sig=DECFLOAT_Sign;
+
+  if (EXPISSPECIAL(exp)) {             /* Infinity or NaN */
+    if (!EXPISINF(exp)) bcdar[1]=0;    /* a NaN: ignore MSD */
+     else memset(bcdar+1, 0, DECPMAX); /* Infinite: coefficient to 0 */
+    }
+  return decFloatFromBCD(df, exp, bcdar+1, sig);
+  } /* decFloatFromPacked */
+
+/* ------------------------------------------------------------------ */
+/* decFloatFromString -- conversion from numeric string                      */
+/*                                                                   */
+/*  result  is the decFloat format number which gets the result of    */
+/*         the conversion                                            */
+/*  *string is the character string which should contain a valid      */
+/*         number (which may be a special value), \0-terminated      */
+/*         If there are too many significant digits in the           */
+/*         coefficient it will be rounded.                           */
+/*  set            is the context                                            */
+/*  returns result                                                   */
+/*                                                                   */
+/* The length of the coefficient and the size of the exponent are     */
+/* checked by this routine, so the correct error (Underflow or       */
+/* Overflow) can be reported or rounding applied, as necessary.              */
+/*                                                                   */
+/* There is no limit to the coefficient length for finite inputs;     */
+/* NaN payloads must be integers with no more than DECPMAX-1 digits.  */
+/* Exponents may have up to nine significant digits.                 */
+/*                                                                   */
+/* If bad syntax is detected, the result will be a quiet NaN.        */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatFromString(decFloat *result, const char *string,
+                             decContext *set) {
+  Int   digits;                   /* count of digits in coefficient */
+  const         char *dotchar=NULL;       /* where dot was found [NULL if none] */
+  const         char *cfirst=string;      /* -> first character of decimal part */
+  const         char *c;                  /* work */
+  uByte *ub;                      /* .. */
+  bcdnum num;                     /* collects data for finishing */
+  uInt  error=DEC_Conversion_syntax;   /* assume the worst */
+  uByte         buffer[ROUNDUP(DECSTRING+11, 8)]; /* room for most coefficents, */
+                                  /* some common rounding, +3, & pad */
+  #if DECTRACE
+  /* printf("FromString %s ...\n", string); */
+  #endif
+
+  for(;;) {                            /* once-only 'loop' */
+    num.sign=0;                                /* assume non-negative */
+    num.msd=buffer;                    /* MSD is here always */
+
+    /* detect and validate the coefficient, including any leading, */
+    /* trailing, or embedded '.' */
+    /* [could test four-at-a-time here (saving 10% for decQuads), */
+    /* but that risks storage violation because the position of the */
+    /* terminator is unknown] */
+    for (c=string;; c++) {             /* -> input character */
+      if (((unsigned)(*c-'0'))<=9) continue; /* '0' through '9' is good */
+      if (*c=='\0') break;             /* most common non-digit */
+      if (*c=='.') {
+       if (dotchar!=NULL) break;       /* not first '.' */
+       dotchar=c;                      /* record offset into decimal part */
+       continue;}
+      if (c==string) {                 /* first in string... */
+       if (*c=='-') {                  /* valid - sign */
+         cfirst++;
+         num.sign=DECFLOAT_Sign;
+         continue;}
+       if (*c=='+') {                  /* valid + sign */
+         cfirst++;
+         continue;}
+       }
+      /* *c is not a digit, terminator, or a valid +, -, or '.' */
+      break;
+      } /* c loop */
+
+    digits=(uInt)(c-cfirst);           /* digits (+1 if a dot) */
+
+    if (digits>0) {                    /* had digits and/or dot */
+      const char *clast=c-1;           /* note last coefficient char position */
+      Int exp=0;                       /* exponent accumulator */
+      if (*c!='\0') {                  /* something follows the coefficient */
+       uInt edig;                      /* unsigned work */
+       /* had some digits and more to come; expect E[+|-]nnn now */
+       const char *firstexp;           /* exponent first non-zero */
+       if (*c!='E' && *c!='e') break;
+       c++;                            /* to (optional) sign */
+       if (*c=='-' || *c=='+') c++;    /* step over sign (c=clast+2) */
+       if (*c=='\0') break;            /* no digits!  (e.g., '1.2E') */
+       for (; *c=='0';) c++;           /* skip leading zeros [even last] */
+       firstexp=c;                     /* remember start [maybe '\0'] */
+       /* gather exponent digits */
+       edig=(uInt)*c-(uInt)'0';
+       if (edig<=9) {                  /* [check not bad or terminator] */
+         exp+=edig;                    /* avoid initial X10 */
+         c++;
+         for (;; c++) {
+           edig=(uInt)*c-(uInt)'0';
+           if (edig>9) break;
+           exp=exp*10+edig;
+           }
+         }
+       /* if not now on the '\0', *c must not be a digit */
+       if (*c!='\0') break;
+
+       /* (this next test must be after the syntax checks) */
+       /* if definitely more than the possible digits for format then */
+       /* the exponent may have wrapped, so simply set it to a certain */
+       /* over/underflow value */
+       if (c>firstexp+DECEMAXD) exp=DECEMAX*2;
+       if (*(clast+2)=='-') exp=-exp;  /* was negative */
+       } /* digits>0 */
+
+      if (dotchar!=NULL) {             /* had a '.' */
+       digits--;                       /* remove from digits count */
+       if (digits==0) break;           /* was dot alone: bad syntax */
+       exp-=(Int)(clast-dotchar);      /* adjust exponent */
+       /* [the '.' can now be ignored] */
+       }
+      num.exponent=exp;                        /* exponent is good; store it */
+
+      /* Here when whole string has been inspected and syntax is good */
+      /* cfirst->first digit or dot, clast->last digit or dot */
+      error=0;                         /* no error possible now */
+
+      /* if the number of digits in the coefficient will fit in buffer */
+      /* then it can simply be converted to bcd8 and copied -- decFinalize */
+      /* will take care of leading zeros and rounding; the buffer is big */
+      /* enough for all canonical coefficients, including 0.00000nn... */
+      ub=buffer;
+      if (digits<=(Int)(sizeof(buffer)-3)) { /* [-3 allows by-4s copy] */
+       c=cfirst;
+       if (dotchar!=NULL) {                 /* a dot to worry about */
+         if (*(c+1)=='.') {                 /* common canonical case */
+           *ub++=(uByte)(*c-'0');           /* copy leading digit */
+           c+=2;                            /* prepare to handle rest */
+           }
+          else for (; c<=clast;) {          /* '.' could be anywhere */
+           /* as usual, go by fours when safe; NB it has been asserted */
+           /* that a '.' does not have the same mask as a digit */
+           if (c<=clast-3                             /* safe for four */
+            && (UINTAT(c)&0xf0f0f0f0)==CHARMASK) {    /* test four */
+             UINTAT(ub)=UINTAT(c)&0x0f0f0f0f;         /* to BCD8 */
+             ub+=4;
+             c+=4;
+             continue;
+             }
+           if (*c=='.') {                   /* found the dot */
+             c++;                           /* step over it .. */
+             break;                         /* .. and handle the rest */
+             }
+           *ub++=(uByte)(*c++-'0');
+           }
+         } /* had dot */
+       /* Now no dot; do this by fours (where safe) */
+       for (; c<=clast-3; c+=4, ub+=4) UINTAT(ub)=UINTAT(c)&0x0f0f0f0f;
+       for (; c<=clast; c++, ub++) *ub=(uByte)(*c-'0');
+       num.lsd=buffer+digits-1;             /* record new LSD */
+       } /* fits */
+
+       else {                               /* too long for buffer */
+       /* [This is a rare and unusual case; arbitrary-length input] */
+       /* strip leading zeros [but leave final 0 if all 0's] */
+       if (*cfirst=='.') cfirst++;          /* step past dot at start */
+       if (*cfirst=='0') {                  /* [cfirst always -> digit] */
+         for (; cfirst<clast; cfirst++) {
+           if (*cfirst!='0') {              /* non-zero found */
+             if (*cfirst=='.') continue;    /* [ignore] */
+             break;                         /* done */
+             }
+           digits--;                        /* 0 stripped */
+           } /* cfirst */
+         } /* at least one leading 0 */
+
+       /* the coefficient is now as short as possible, but may still */
+       /* be too long; copy up to Pmax+1 digits to the buffer, then */
+       /* just record any non-zeros (set round-for-reround digit) */
+       for (c=cfirst; c<=clast && ub<=buffer+DECPMAX; c++) {
+         /* (see commentary just above) */
+         if (c<=clast-3                          /* safe for four */
+          && (UINTAT(c)&0xf0f0f0f0)==CHARMASK) { /* four digits */
+           UINTAT(ub)=UINTAT(c)&0x0f0f0f0f;      /* to BCD8 */
+           ub+=4;
+           c+=3;                            /* [will become 4] */
+           continue;
+           }
+         if (*c=='.') continue;             /* [ignore] */
+         *ub++=(uByte)(*c-'0');
+         }
+       ub--;                                /* -> LSD */
+       for (; c<=clast; c++) {              /* inspect remaining chars */
+         if (*c!='0') {                     /* sticky bit needed */
+           if (*c=='.') continue;           /* [ignore] */
+           *ub=DECSTICKYTAB[*ub];           /* update round-for-reround */
+           break;                           /* no need to look at more */
+           }
+         }
+       num.lsd=ub;                          /* record LSD */
+       /* adjust exponent for dropped digits */
+       num.exponent+=digits-(Int)(ub-buffer+1);
+       } /* too long for buffer */
+      } /* digits or dot */
+
+     else {                            /* no digits or dot were found */
+      if (*c=='\0') break;             /* nothing to come is bad */
+      /* only Infinities and NaNs are allowed, here */
+      buffer[0]=0;                     /* default a coefficient of 0 */
+      num.lsd=buffer;                  /* .. */
+      if (decBiStr(c, "infinity", "INFINITY")
+       || decBiStr(c, "inf", "INF")) num.exponent=DECFLOAT_Inf;
+       else {                          /* should be a NaN */
+       num.exponent=DECFLOAT_qNaN;     /* assume quiet NaN */
+       if (*c=='s' || *c=='S') {       /* probably an sNaN */
+         c++;
+         num.exponent=DECFLOAT_sNaN;   /* assume is in fact sNaN */
+         }
+       if (*c!='N' && *c!='n') break;  /* check caseless "NaN" */
+       c++;
+       if (*c!='a' && *c!='A') break;  /* .. */
+       c++;
+       if (*c!='N' && *c!='n') break;  /* .. */
+       c++;
+       /* now either nothing, or nnnn payload (no dots), expected */
+       /* -> start of integer, and skip leading 0s [including plain 0] */
+       for (cfirst=c; *cfirst=='0';) cfirst++;
+       if (*cfirst!='\0') {            /* not empty or all-0, payload */
+         /* payload found; check all valid digits and copy to buffer as bcd8 */
+         ub=buffer;
+         for (c=cfirst;; c++, ub++) {
+           if ((unsigned)(*c-'0')>9) break; /* quit if not 0-9 */
+           if (c-cfirst==DECPMAX-1) break;  /* too many digits */
+           *ub=(uByte)(*c-'0');        /* good bcd8 */
+           }
+         if (*c!='\0') break;          /* not all digits, or too many */
+         num.lsd=ub-1;                 /* record new LSD */
+         }
+       } /* NaN or sNaN */
+      error=0;                         /* syntax is OK */
+      break;                           /* done with specials */
+      } /* digits=0 (special expected) */
+    break;
+    }                                  /* [for(;;) break] */
+
+  /* decShowNum(&num, "fromStr"); */
+
+  if (error!=0) {
+    set->status|=error;
+    num.exponent=DECFLOAT_qNaN;                /* set up quiet NaN */
+    num.sign=0;                                /* .. with 0 sign */
+    buffer[0]=0;                       /* .. and coefficient */
+    num.lsd=buffer;                    /* .. */
+    /* decShowNum(&num, "oops"); */
+    }
+
+  /* decShowNum(&num, "dffs"); */
+  decFinalize(result, &num, set);      /* round, check, and lay out */
+  /* decFloatShow(result, "fromString"); */
+  return result;
+  } /* decFloatFromString */
+
+/* ------------------------------------------------------------------ */
+/* decFloatFromWider -- conversion from next-wider format            */
+/*                                                                   */
+/*  result  is the decFloat format number which gets the result of    */
+/*         the conversion                                            */
+/*  wider   is the decFloatWider format number which will be narrowed */
+/*  set            is the context                                            */
+/*  returns result                                                   */
+/*                                                                   */
+/* Narrowing can cause rounding, overflow, etc., but not Invalid      */
+/* operation (sNaNs are copied and do not signal).                   */
+/* ------------------------------------------------------------------ */
+/* narrow-to is not possible for decQuad format numbers; simply omit */
+#if !QUAD
+decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider,
+                            decContext *set) {
+  bcdnum num;                          /* collects data for finishing */
+  uByte         bcdar[DECWPMAX];               /* room for wider coefficient */
+  uInt  widerhi=DFWWORD(wider, 0);     /* top word */
+  Int   exp;
+
+  GETWCOEFF(wider, bcdar);
+
+  num.msd=bcdar;                       /* MSD is here always */
+  num.lsd=bcdar+DECWPMAX-1;            /* LSD is here always */
+  num.sign=widerhi&0x80000000;         /* extract sign [DECFLOAT_Sign=Neg] */
+
+  /* decode the wider combination field to exponent */
+  exp=DECCOMBWEXP[widerhi>>26];                /* decode from wider combination field */
+  /* if it is a special there's nothing to do unless sNaN; if it's */
+  /* finite then add the (wider) exponent continuation and unbias */
+  if (EXPISSPECIAL(exp)) exp=widerhi&0x7e000000; /* include sNaN selector */
+   else exp+=GETWECON(wider)-DECWBIAS;
+  num.exponent=exp;
+
+  /* decShowNum(&num, "dffw"); */
+  return decFinalize(result, &num, set);/* round, check, and lay out */
+  } /* decFloatFromWider */
+#endif
+
+/* ------------------------------------------------------------------ */
+/* decFloatGetCoefficient -- get coefficient as BCD8                 */
+/*                                                                   */
+/*  df is the decFloat from which to extract the coefficient         */
+/*  bcdar is where DECPMAX bytes will be written, one BCD digit in    */
+/*    each byte (BCD8 encoding); if df is a NaN the first byte will   */
+/*    be zero, and if it is infinite they will all be zero           */
+/*  returns the sign of the coefficient (DECFLOAT_Sign if negative,   */
+/*    0 otherwise)                                                   */
+/*                                                                   */
+/* No error is possible, and no status will be set.  If df is a              */
+/* special value the array is set to zeros (for Infinity) or to the   */
+/* payload of a qNaN or sNaN.                                        */
+/* ------------------------------------------------------------------ */
+Int decFloatGetCoefficient(const decFloat *df, uByte *bcdar) {
+  if (DFISINF(df)) memset(bcdar, 0, DECPMAX);
+   else {
+    GETCOEFF(df, bcdar);          /* use macro */
+    if (DFISNAN(df)) bcdar[0]=0;   /* MSD needs correcting */
+    }
+  return DFISSIGNED(df);
+  } /* decFloatGetCoefficient */
+
+/* ------------------------------------------------------------------ */
+/* decFloatGetExponent -- get unbiased exponent                              */
+/*                                                                   */
+/*  df is the decFloat from which to extract the exponent            */
+/*  returns the exponent, q.                                         */
+/*                                                                   */
+/* No error is possible, and no status will be set.  If df is a              */
+/* special value the first seven bits of the decFloat are returned,   */
+/* left adjusted and with the first (sign) bit set to 0 (followed by  */
+/* 25 0 bits). e.g., -sNaN would return 0x7e000000 (DECFLOAT_sNaN).  */
+/* ------------------------------------------------------------------ */
+Int decFloatGetExponent(const decFloat *df) {
+  if (DFISSPECIAL(df)) return DFWORD(df, 0)&0x7e000000;
+  return GETEXPUN(df);
+  } /* decFloatGetExponent */
+
+/* ------------------------------------------------------------------ */
+/* decFloatSetCoefficient -- set coefficient from BCD8               */
+/*                                                                   */
+/*  df is the target decFloat (and source of exponent/special value)  */
+/*  bcdar holds DECPMAX digits to set the coefficient from, one              */
+/*    digit in each byte (BCD8 encoding); the first (MSD) is ignored  */
+/*    if df is a NaN; all are ignored if df is infinite.             */
+/*  sig is DECFLOAT_Sign to set the sign bit, 0 otherwise            */
+/*  returns df, which will be canonical                                      */
+/*                                                                   */
+/* No error is possible, and no status will be set.                  */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatSetCoefficient(decFloat *df, const uByte *bcdar,
+                                 Int sig) {
+  uInt exp;                       /* for exponent */
+  uByte bcdzero[DECPMAX];         /* for infinities */
+
+  /* Exponent/special code is extracted from df */
+  if (DFISSPECIAL(df)) {
+    exp=DFWORD(df, 0)&0x7e000000;
+    if (DFISINF(df)) {
+      memset(bcdzero, 0, DECPMAX);
+      return decFloatFromBCD(df, exp, bcdzero, sig);
+      }
+    }
+   else exp=GETEXPUN(df);
+  return decFloatFromBCD(df, exp, bcdar, sig);
+  } /* decFloatSetCoefficient */
+
+/* ------------------------------------------------------------------ */
+/* decFloatSetExponent -- set exponent or special value                      */
+/*                                                                   */
+/*  df is the target decFloat (and source of coefficient/payload)    */
+/*  set is the context for reporting status                          */
+/*  exp is the unbiased exponent, q, or a special value in the form   */
+/*    returned by decFloatGetExponent                                */
+/*  returns df, which will be canonical                                      */
+/*                                                                   */
+/* No error is possible, but Overflow or Underflow might occur.              */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatSetExponent(decFloat *df, decContext *set, Int exp) {
+  uByte         bcdcopy[DECPMAX];         /* for coefficient */
+  bcdnum num;                     /* work */
+  num.exponent=exp;
+  num.sign=decFloatGetCoefficient(df, bcdcopy); /* extract coefficient */
+  if (DFISSPECIAL(df)) {          /* MSD or more needs correcting */
+    if (DFISINF(df)) memset(bcdcopy, 0, DECPMAX);
+    bcdcopy[0]=0;
+    }
+  num.msd=bcdcopy;
+  num.lsd=bcdcopy+DECPMAX-1;
+  return decFinalize(df, &num, set);
+  } /* decFloatSetExponent */
+
+/* ------------------------------------------------------------------ */
+/* decFloatRadix -- returns the base (10)                            */
+/*                                                                   */
+/*   df is any decFloat of this format                               */
+/* ------------------------------------------------------------------ */
+uInt decFloatRadix(const decFloat *df) {
+  if (df) return 10;                        /* to placate compiler */
+  return 10;
+  } /* decFloatRadix */
+
+/* ------------------------------------------------------------------ */
+/* decFloatShow -- printf a decFloat in hexadecimal and decimal              */
+/*   df         is the decFloat to show                                      */
+/*   tag is a tag string displayed with the number                   */
+/*                                                                   */
+/* This is a debug aid; the precise format of the string may change.  */
+/* ------------------------------------------------------------------ */
+void decFloatShow(const decFloat *df, const char *tag) {
+  char hexbuf[DECBYTES*2+DECBYTES/4+1]; /* NB blank after every fourth */
+  char buff[DECSTRING];                        /* for value in decimal */
+  Int i, j=0;
+
+  for (i=0; i<DECBYTES; i++) {
+    #if DECLITEND
+      sprintf(&hexbuf[j], "%02x", df->bytes[DECBYTES-1-i]);
+    #else
+      sprintf(&hexbuf[j], "%02x", df->bytes[i]);
+    #endif
+    j+=2;
+    /* the next line adds blank (and terminator) after final pair, too */
+    if ((i+1)%4==0) {strcpy(&hexbuf[j], " "); j++;}
+    }
+  decFloatToString(df, buff);
+  printf(">%s> %s [big-endian] %s\n", tag, hexbuf, buff);
+  return;
+  } /* decFloatShow */
+
+/* ------------------------------------------------------------------ */
+/* decFloatToBCD -- get sign, exponent, and BCD8 from a decFloat      */
+/*                                                                   */
+/*  df is the source decFloat                                        */
+/*  exp will be set to the unbiased exponent, q, or to a special      */
+/*    value in the form returned by decFloatGetExponent                      */
+/*  bcdar is where DECPMAX bytes will be written, one BCD digit in    */
+/*    each byte (BCD8 encoding); if df is a NaN the first byte will   */
+/*    be zero, and if it is infinite they will all be zero           */
+/*  returns the sign of the coefficient (DECFLOAT_Sign if negative,   */
+/*    0 otherwise)                                                   */
+/*                                                                   */
+/* No error is possible, and no status will be set.                  */
+/* ------------------------------------------------------------------ */
+Int decFloatToBCD(const decFloat *df, Int *exp, uByte *bcdar) {
+  if (DFISINF(df)) {
+    memset(bcdar, 0, DECPMAX);
+    *exp=DFWORD(df, 0)&0x7e000000;
+    }
+   else {
+    GETCOEFF(df, bcdar);          /* use macro */
+    if (DFISNAN(df)) {
+      bcdar[0]=0;                 /* MSD needs correcting */
+      *exp=DFWORD(df, 0)&0x7e000000;
+      }
+     else {                       /* finite */
+      *exp=GETEXPUN(df);
+      }
+    }
+  return DFISSIGNED(df);
+  } /* decFloatToBCD */
+
+/* ------------------------------------------------------------------ */
+/* decFloatToEngString -- conversion to numeric string, engineering   */
+/*                                                                   */
+/*  df is the decFloat format number to convert                              */
+/*  string is the string where the result will be laid out           */
+/*                                                                   */
+/* string must be at least DECPMAX+9 characters (the worst case is    */
+/* "-0.00000nnn...nnn\0", which is as long as the exponent form when  */
+/* DECEMAXD<=4); this condition is asserted above                    */
+/*                                                                   */
+/* No error is possible, and no status will be set                   */
+/* ------------------------------------------------------------------ */
+char * decFloatToEngString(const decFloat *df, char *string){
+  uInt msd;                       /* coefficient MSD */
+  Int  exp;                       /* exponent top two bits or full */
+  uInt comb;                      /* combination field */
+  char *cstart;                           /* coefficient start */
+  char *c;                        /* output pointer in string */
+  char *s, *t;                    /* .. (source, target) */
+  Int  pre, e;                    /* work */
+  const uByte *u;                 /* .. */
+
+  /* Source words; macro handles endianness */
+  uInt sourhi=DFWORD(df, 0);      /* word with sign */
+  #if DECPMAX==16
+  uInt sourlo=DFWORD(df, 1);
+  #elif DECPMAX==34
+  uInt sourmh=DFWORD(df, 1);
+  uInt sourml=DFWORD(df, 2);
+  uInt sourlo=DFWORD(df, 3);
+  #endif
+
+  c=string;                       /* where result will go */
+  if (((Int)sourhi)<0) *c++='-';   /* handle sign */
+  comb=sourhi>>26;                /* sign+combination field */
+  msd=DECCOMBMSD[comb];                   /* decode the combination field */
+  exp=DECCOMBEXP[comb];                   /* .. */
+
+  if (EXPISSPECIAL(exp)) {        /* special */
+    if (exp==DECFLOAT_Inf) {      /* infinity */
+      strcpy(c,          "Inf");
+      strcpy(c+3, "inity");
+      return string;              /* easy */
+      }
+    if (sourhi&0x02000000) *c++='s'; /* sNaN */
+    strcpy(c, "NaN");             /* complete word */
+    c+=3;                         /* step past */
+    /* quick exit if the payload is zero */
+    #if DECPMAX==7
+    if ((sourhi&0x000fffff)==0) return string;
+    #elif DECPMAX==16
+    if (sourlo==0 && (sourhi&0x0003ffff)==0) return string;
+    #elif DECPMAX==34
+    if (sourlo==0 && sourml==0 && sourmh==0
+     && (sourhi&0x00003fff)==0) return string;
+    #endif
+    /* otherwise drop through to add integer; set correct exp etc. */
+    exp=0; msd=0;                 /* setup for following code */
+    }
+   else { /* complete exponent; top two bits are in place */
+    exp+=GETECON(df)-DECBIAS;     /* .. + continuation and unbias */
+    }
+
+  /* convert the digits of the significand to characters */
+  cstart=c;                       /* save start of coefficient */
+  if (msd) *c++=(char)('0'+(char)msd); /* non-zero most significant digit */
+
+  /* Decode the declets.  After extracting each declet, it is */
+  /* decoded to a 4-uByte sequence by table lookup; the four uBytes */
+  /* are the three encoded BCD8 digits followed by a 1-byte length */
+  /* (significant digits, except that 000 has length 0).  This allows */
+  /* us to left-align the first declet with non-zero content, then */
+  /* the remaining ones are full 3-char length.         Fixed-length copies */
+  /* are used because variable-length memcpy causes a subroutine call */
+  /* in at least two compilers.         (The copies are length 4 for speed */
+  /* and are safe because the last item in the array is of length */
+  /* three and has the length byte following.) */
+  #define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4];       \
+        if (c!=cstart) {UINTAT(c)=UINTAT(u)|CHARMASK; c+=3;}    \
+         else if (*(u+3)) {                                     \
+          UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; c+=*(u+3);}
+
+  #if DECPMAX==7
+  dpd2char(sourhi>>10);                        /* declet 1 */
+  dpd2char(sourhi);                    /* declet 2 */
+
+  #elif DECPMAX==16
+  dpd2char(sourhi>>8);                 /* declet 1 */
+  dpd2char((sourhi<<2) | (sourlo>>30)); /* declet 2 */
+  dpd2char(sourlo>>20);                        /* declet 3 */
+  dpd2char(sourlo>>10);                        /* declet 4 */
+  dpd2char(sourlo);                    /* declet 5 */
+
+  #elif DECPMAX==34
+  dpd2char(sourhi>>4);                 /* declet 1 */
+  dpd2char((sourhi<<6) | (sourmh>>26)); /* declet 2 */
+  dpd2char(sourmh>>16);                        /* declet 3 */
+  dpd2char(sourmh>>6);                 /* declet 4 */
+  dpd2char((sourmh<<4) | (sourml>>28)); /* declet 5 */
+  dpd2char(sourml>>18);                        /* declet 6 */
+  dpd2char(sourml>>8);                 /* declet 7 */
+  dpd2char((sourml<<2) | (sourlo>>30)); /* declet 8 */
+  dpd2char(sourlo>>20);                        /* declet 9 */
+  dpd2char(sourlo>>10);                        /* declet 10 */
+  dpd2char(sourlo);                    /* declet 11 */
+  #endif
+
+  if (c==cstart) *c++='0';        /* all zeros, empty -- make "0" */
+
+  if (exp==0) {                           /* integer or NaN case -- easy */
+    *c='\0';                      /* terminate */
+    return string;
+    }
+  /* non-0 exponent */
+
+  e=0;                            /* assume no E */
+  pre=(Int)(c-cstart)+exp;        /* length+exp  [c->LSD+1] */
+  /* [here, pre-exp is the digits count (==1 for zero)] */
+
+  if (exp>0 || pre<-5) {          /* need exponential form */
+    e=pre-1;                      /* calculate E value */
+    pre=1;                        /* assume one digit before '.' */
+    if (e!=0) {                           /* engineering: may need to adjust */
+      Int adj;                    /* adjustment */
+      /* The C remainder operator is undefined for negative numbers, so */
+      /* a positive remainder calculation must be used here */
+      if (e<0) {
+       adj=(-e)%3;
+       if (adj!=0) adj=3-adj;
+       }
+       else { /* e>0 */
+       adj=e%3;
+       }
+      e=e-adj;
+      /* if dealing with zero still produce an exponent which is a */
+      /* multiple of three, as expected, but there will only be the */
+      /* one zero before the E, still. Otherwise note the padding. */
+      if (!DFISZERO(df)) pre+=adj;
+       else {  /* is zero */
+       if (adj!=0) {              /* 0.00Esnn needed */
+         e=e+3;
+         pre=-(2-adj);
+         }
+       } /* zero */
+      } /* engineering adjustment */
+    } /* exponential form */
+  /* printf("e=%ld pre=%ld exp=%ld\n", (LI)e, (LI)pre, (LI)exp); */
+
+  /* modify the coefficient, adding 0s, '.', and E+nn as needed */
+  if (pre>0) {                    /* ddd.ddd (plain), perhaps with E */
+                                  /* or dd00 padding for engineering */
+    char *dotat=cstart+pre;
+    if (dotat<c) {                     /* if embedded dot needed... */
+      /* move by fours; there must be space for junk at the end */
+      /* because there is still space for exponent */
+      s=dotat+ROUNDDOWN4(c-dotat);     /* source */
+      t=s+1;                           /* target */
+      /* open the gap */
+      for (; s>=dotat; s-=4, t-=4) UINTAT(t)=UINTAT(s);
+      *dotat='.';
+      c++;                             /* length increased by one */
+      } /* need dot? */
+     else for (; c<dotat; c++) *c='0'; /* pad for engineering */
+    } /* pre>0 */
+   else {
+    /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (may have
+       E, but only for 0.00E+3 kind of case -- with plenty of spare
+       space in this case */
+    pre=-pre+2;                                /* gap width, including "0." */
+    t=cstart+ROUNDDOWN4(c-cstart)+pre; /* preferred first target point */
+    /* backoff if too far to the right */
+    if (t>string+DECSTRING-5) t=string+DECSTRING-5; /* adjust to fit */
+    /* now shift the entire coefficient to the right, being careful not */
+    /* to access to the left of string */
+    for (s=t-pre; s>=string; s-=4, t-=4) UINTAT(t)=UINTAT(s);
+    /* for Quads and Singles there may be a character or two left... */
+    s+=3;                              /* where next would come from */
+    for(; s>=cstart; s--, t--) *(t+3)=*(s);
+    /* now have fill 0. through 0.00000; use overlaps to avoid tests */
+    if (pre>=4) {
+      UINTAT(cstart+pre-4)=UINTAT("0000");
+      UINTAT(cstart)=UINTAT("0.00");
+      }
+     else { /* 2 or 3 */
+      *(cstart+pre-1)='0';
+      USHORTAT(cstart)=USHORTAT("0.");
+      }
+    c+=pre;                            /* to end */
+    }
+
+  /* finally add the E-part, if needed; it will never be 0, and has */
+  /* a maximum length of 3 or 4 digits (asserted above) */
+  if (e!=0) {
+    USHORTAT(c)=USHORTAT("E+");                /* starts with E, assume + */
+    c++;
+    if (e<0) {
+      *c='-';                          /* oops, need '-' */
+      e=-e;                            /* uInt, please */
+      }
+    c++;
+    /* Three-character exponents are easy; 4-character a little trickier */
+    #if DECEMAXD<=3
+      u=&BIN2BCD8[e*4];                        /* -> 3 digits + length byte */
+      /* copy fixed 4 characters [is safe], starting at non-zero */
+      /* and with character mask to convert BCD to char */
+      UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK;
+      c+=*(u+3);                       /* bump pointer appropriately */
+    #elif DECEMAXD==4
+      if (e<1000) {                    /* 3 (or fewer) digits case */
+       u=&BIN2BCD8[e*4];               /* -> 3 digits + length byte */
+       UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; /* [as above] */
+       c+=*(u+3);                      /* bump pointer appropriately */
+       }
+       else {                          /* 4-digits */
+       Int thou=((e>>3)*1049)>>17;     /* e/1000 */
+       Int rem=e-(1000*thou);          /* e%1000 */
+       *c++=(char)('0'+(char)thou);    /* the thousands digit */
+       u=&BIN2BCD8[rem*4];             /* -> 3 digits + length byte */
+       UINTAT(c)=UINTAT(u)|CHARMASK;   /* copy fixed 3+1 characters [is safe] */
+       c+=3;                           /* bump pointer, always 3 digits */
+       }
+    #endif
+    }
+  *c='\0';                             /* terminate */
+  /*printf("res %s\n", string); */
+  return string;
+  } /* decFloatToEngString */
+
+/* ------------------------------------------------------------------ */
+/* decFloatToPacked -- convert decFloat to Packed decimal + exponent  */
+/*                                                                   */
+/*  df is the source decFloat                                        */
+/*  exp will be set to the unbiased exponent, q, or to a special      */
+/*    value in the form returned by decFloatGetExponent                      */
+/*  packed is where DECPMAX nibbles will be written with the sign as  */
+/*    final nibble (0x0c for +, 0x0d for -); a NaN has a first nibble */
+/*    of zero, and an infinity is all zeros. decDouble and decQuad    */
+/*    have a additional leading zero nibble, leading to result       */
+/*    lengths of 4, 9, and 18 bytes.                                 */
+/*  returns the sign of the coefficient (DECFLOAT_Sign if negative,   */
+/*    0 otherwise)                                                   */
+/*                                                                   */
+/* No error is possible, and no status will be set.                  */
+/* ------------------------------------------------------------------ */
+Int decFloatToPacked(const decFloat *df, Int *exp, uByte *packed) {
+  uByte bcdar[DECPMAX+2];         /* work buffer */
+  uByte *ip=bcdar, *op=packed;    /* work pointers */
+  if (DFISINF(df)) {
+    memset(bcdar, 0, DECPMAX+2);
+    *exp=DECFLOAT_Inf;
+    }
+   else {
+    GETCOEFF(df, bcdar+1);        /* use macro */
+    if (DFISNAN(df)) {
+      bcdar[1]=0;                 /* MSD needs clearing */
+      *exp=DFWORD(df, 0)&0x7e000000;
+      }
+     else {                       /* finite */
+      *exp=GETEXPUN(df);
+      }
+    }
+  /* now pack; coefficient currently at bcdar+1 */
+  #if SINGLE
+    ip++;                         /* ignore first byte */
+  #else
+    *ip=0;                        /* need leading zero */
+  #endif
+  /* set final byte to Packed BCD sign value */
+  bcdar[DECPMAX+1]=(DFISSIGNED(df) ? DECPMINUS : DECPPLUS);
+  /* pack an even number of bytes... */
+  for (; op<packed+((DECPMAX+2)/2); op++, ip+=2) {
+    *op=(uByte)((*ip<<4)+*(ip+1));
+    }
+  return (bcdar[DECPMAX+1]==DECPMINUS ? DECFLOAT_Sign : 0);
+  } /* decFloatToPacked */
+
+/* ------------------------------------------------------------------ */
+/* decFloatToString -- conversion to numeric string                  */
+/*                                                                   */
+/*  df is the decFloat format number to convert                              */
+/*  string is the string where the result will be laid out           */
+/*                                                                   */
+/* string must be at least DECPMAX+9 characters (the worst case is    */
+/* "-0.00000nnn...nnn\0", which is as long as the exponent form when  */
+/* DECEMAXD<=4); this condition is asserted above                    */
+/*                                                                   */
+/* No error is possible, and no status will be set                   */
+/* ------------------------------------------------------------------ */
+char * decFloatToString(const decFloat *df, char *string){
+  uInt msd;                       /* coefficient MSD */
+  Int  exp;                       /* exponent top two bits or full */
+  uInt comb;                      /* combination field */
+  char *cstart;                           /* coefficient start */
+  char *c;                        /* output pointer in string */
+  char *s, *t;                    /* .. (source, target) */
+  Int  pre, e;                    /* work */
+  const uByte *u;                 /* .. */
+
+  /* Source words; macro handles endianness */
+  uInt sourhi=DFWORD(df, 0);      /* word with sign */
+  #if DECPMAX==16
+  uInt sourlo=DFWORD(df, 1);
+  #elif DECPMAX==34
+  uInt sourmh=DFWORD(df, 1);
+  uInt sourml=DFWORD(df, 2);
+  uInt sourlo=DFWORD(df, 3);
+  #endif
+
+  c=string;                       /* where result will go */
+  if (((Int)sourhi)<0) *c++='-';   /* handle sign */
+  comb=sourhi>>26;                /* sign+combination field */
+  msd=DECCOMBMSD[comb];                   /* decode the combination field */
+  exp=DECCOMBEXP[comb];                   /* .. */
+
+  if (EXPISSPECIAL(exp)) {        /* special */
+    if (exp==DECFLOAT_Inf) {      /* infinity */
+      strcpy(c, "Infinity");
+      return string;              /* easy */
+      }
+    if (sourhi&0x02000000) *c++='s'; /* sNaN */
+    strcpy(c, "NaN");             /* complete word */
+    c+=3;                         /* step past */
+    /* quick exit if the payload is zero */
+    #if DECPMAX==7
+    if ((sourhi&0x000fffff)==0) return string;
+    #elif DECPMAX==16
+    if (sourlo==0 && (sourhi&0x0003ffff)==0) return string;
+    #elif DECPMAX==34
+    if (sourlo==0 && sourml==0 && sourmh==0
+     && (sourhi&0x00003fff)==0) return string;
+    #endif
+    /* otherwise drop through to add integer; set correct exp etc. */
+    exp=0; msd=0;                 /* setup for following code */
+    }
+   else { /* complete exponent; top two bits are in place */
+    exp+=GETECON(df)-DECBIAS;     /* .. + continuation and unbias */
+    }
+
+  /* convert the digits of the significand to characters */
+  cstart=c;                       /* save start of coefficient */
+  if (msd) *c++=(char)('0'+(char)msd); /* non-zero most significant digit */
+
+  /* Decode the declets.  After extracting each declet, it is */
+  /* decoded to a 4-uByte sequence by table lookup; the four uBytes */
+  /* are the three encoded BCD8 digits followed by a 1-byte length */
+  /* (significant digits, except that 000 has length 0).  This allows */
+  /* us to left-align the first declet with non-zero content, then */
+  /* the remaining ones are full 3-char length.         Fixed-length copies */
+  /* are used because variable-length memcpy causes a subroutine call */
+  /* in at least two compilers.         (The copies are length 4 for speed */
+  /* and are safe because the last item in the array is of length */
+  /* three and has the length byte following.) */
+  #define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4];       \
+        if (c!=cstart) {UINTAT(c)=UINTAT(u)|CHARMASK; c+=3;}    \
+         else if (*(u+3)) {                                     \
+          UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; c+=*(u+3);}
+
+  #if DECPMAX==7
+  dpd2char(sourhi>>10);                        /* declet 1 */
+  dpd2char(sourhi);                    /* declet 2 */
+
+  #elif DECPMAX==16
+  dpd2char(sourhi>>8);                 /* declet 1 */
+  dpd2char((sourhi<<2) | (sourlo>>30)); /* declet 2 */
+  dpd2char(sourlo>>20);                        /* declet 3 */
+  dpd2char(sourlo>>10);                        /* declet 4 */
+  dpd2char(sourlo);                    /* declet 5 */
+
+  #elif DECPMAX==34
+  dpd2char(sourhi>>4);                 /* declet 1 */
+  dpd2char((sourhi<<6) | (sourmh>>26)); /* declet 2 */
+  dpd2char(sourmh>>16);                        /* declet 3 */
+  dpd2char(sourmh>>6);                 /* declet 4 */
+  dpd2char((sourmh<<4) | (sourml>>28)); /* declet 5 */
+  dpd2char(sourml>>18);                        /* declet 6 */
+  dpd2char(sourml>>8);                 /* declet 7 */
+  dpd2char((sourml<<2) | (sourlo>>30)); /* declet 8 */
+  dpd2char(sourlo>>20);                        /* declet 9 */
+  dpd2char(sourlo>>10);                        /* declet 10 */
+  dpd2char(sourlo);                    /* declet 11 */
+  #endif
+
+  if (c==cstart) *c++='0';        /* all zeros, empty -- make "0" */
+
+  /*[This fast path is valid but adds 3-5 cycles to worst case length] */
+  /*if (exp==0) {                 // integer or NaN case -- easy */
+  /*  *c='\0';                    // terminate */
+  /*  return string; */
+  /*  } */
+
+  e=0;                            /* assume no E */
+  pre=(Int)(c-cstart)+exp;        /* length+exp  [c->LSD+1] */
+  /* [here, pre-exp is the digits count (==1 for zero)] */
+
+  if (exp>0 || pre<-5) {          /* need exponential form */
+    e=pre-1;                      /* calculate E value */
+    pre=1;                        /* assume one digit before '.' */
+    } /* exponential form */
+
+  /* modify the coefficient, adding 0s, '.', and E+nn as needed */
+  if (pre>0) {                    /* ddd.ddd (plain), perhaps with E */
+    char *dotat=cstart+pre;
+    if (dotat<c) {                     /* if embedded dot needed... */
+      /* move by fours; there must be space for junk at the end */
+      /* because there is still space for exponent */
+      s=dotat+ROUNDDOWN4(c-dotat);     /* source */
+      t=s+1;                           /* target */
+      /* open the gap */
+      for (; s>=dotat; s-=4, t-=4) UINTAT(t)=UINTAT(s);
+      *dotat='.';
+      c++;                             /* length increased by one */
+      } /* need dot? */
+
+    /* finally add the E-part, if needed; it will never be 0, and has */
+    /* a maximum length of 3 or 4 digits (asserted above) */
+    if (e!=0) {
+      USHORTAT(c)=USHORTAT("E+");      /* starts with E, assume + */
+      c++;
+      if (e<0) {
+       *c='-';                         /* oops, need '-' */
+       e=-e;                           /* uInt, please */
+       }
+      c++;
+      /* Three-character exponents are easy; 4-character a little trickier */
+      #if DECEMAXD<=3
+       u=&BIN2BCD8[e*4];               /* -> 3 digits + length byte */
+       /* copy fixed 4 characters [is safe], starting at non-zero */
+       /* and with character mask to convert BCD to char */
+       UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK;
+       c+=*(u+3);                      /* bump pointer appropriately */
+      #elif DECEMAXD==4
+       if (e<1000) {                   /* 3 (or fewer) digits case */
+         u=&BIN2BCD8[e*4];             /* -> 3 digits + length byte */
+         UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; /* [as above] */
+         c+=*(u+3);                    /* bump pointer appropriately */
+         }
+        else {                         /* 4-digits */
+         Int thou=((e>>3)*1049)>>17;   /* e/1000 */
+         Int rem=e-(1000*thou);        /* e%1000 */
+         *c++=(char)('0'+(char)thou);  /* the thousands digit */
+         u=&BIN2BCD8[rem*4];           /* -> 3 digits + length byte */
+         UINTAT(c)=UINTAT(u)|CHARMASK; /* copy fixed 3+1 characters [is safe] */
+         c+=3;                         /* bump pointer, always 3 digits */
+         }
+      #endif
+      }
+    *c='\0';                           /* add terminator */
+    /*printf("res %s\n", string); */
+    return string;
+    } /* pre>0 */
+
+  /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
+  /* Surprisingly, this is close to being the worst-case path, so the */
+  /* shift is done by fours; this is a little tricky because the */
+  /* rightmost character to be written must not be beyond where the */
+  /* rightmost terminator could be -- so backoff to not touch */
+  /* terminator position if need be (this can make exact alignments */
+  /* for full Doubles, but in some cases needs care not to access too */
+  /* far to the left) */
+
+  pre=-pre+2;                          /* gap width, including "0." */
+  t=cstart+ROUNDDOWN4(c-cstart)+pre;   /* preferred first target point */
+  /* backoff if too far to the right */
+  if (t>string+DECSTRING-5) t=string+DECSTRING-5; /* adjust to fit */
+  /* now shift the entire coefficient to the right, being careful not */
+  /* to access to the left of string */
+  for (s=t-pre; s>=string; s-=4, t-=4) UINTAT(t)=UINTAT(s);
+  /* for Quads and Singles there may be a character or two left... */
+  s+=3;                                        /* where next would come from */
+  for(; s>=cstart; s--, t--) *(t+3)=*(s);
+  /* now have fill 0. through 0.00000; use overlaps to avoid tests */
+  if (pre>=4) {
+    UINTAT(cstart+pre-4)=UINTAT("0000");
+    UINTAT(cstart)=UINTAT("0.00");
+    }
+   else { /* 2 or 3 */
+    *(cstart+pre-1)='0';
+    USHORTAT(cstart)=USHORTAT("0.");
+    }
+  *(c+pre)='\0';                       /* terminate */
+  return string;
+  } /* decFloatToString */
+
+/* ------------------------------------------------------------------ */
+/* decFloatToWider -- conversion to next-wider format                */
+/*                                                                   */
+/*  source  is the decFloat format number which gets the result of    */
+/*         the conversion                                            */
+/*  wider   is the decFloatWider format number which will be narrowed */
+/*  returns wider                                                    */
+/*                                                                   */
+/* Widening is always exact; no status is set (sNaNs are copied and   */
+/* do not signal).  The result will be canonical if the source is,    */
+/* and may or may not be if the source is not.                       */
+/* ------------------------------------------------------------------ */
+/* widening is not possible for decQuad format numbers; simply omit */
+#if !QUAD
+decFloatWider * decFloatToWider(const decFloat *source, decFloatWider *wider) {
+  uInt msd;
+
+  /* Construct and copy the sign word */
+  if (DFISSPECIAL(source)) {
+    /* copy sign, combination, and first bit of exponent (sNaN selector) */
+    DFWWORD(wider, 0)=DFWORD(source, 0)&0xfe000000;
+    msd=0;
+    }
+   else { /* is finite number */
+    uInt exp=GETEXPUN(source)+DECWBIAS; /* get unbiased exponent and rebias */
+    uInt code=(exp>>DECWECONL)<<29;    /* set two bits of exp [msd=0] */
+    code|=(exp<<(32-6-DECWECONL)) & 0x03ffffff; /* add exponent continuation */
+    code|=DFWORD(source, 0)&0x80000000; /* add sign */
+    DFWWORD(wider, 0)=code;            /* .. and place top word in wider */
+    msd=GETMSD(source);                        /* get source coefficient MSD [0-9] */
+    }
+  /* Copy the coefficient and clear any 'unused' words to left */
+  #if SINGLE
+    DFWWORD(wider, 1)=(DFWORD(source, 0)&0x000fffff)|(msd<<20);
+  #elif DOUBLE
+    DFWWORD(wider, 2)=(DFWORD(source, 0)&0x0003ffff)|(msd<<18);
+    DFWWORD(wider, 3)=DFWORD(source, 1);
+    DFWWORD(wider, 1)=0;
+  #endif
+  return wider;
+  } /* decFloatToWider */
+#endif
+
+/* ------------------------------------------------------------------ */
+/* decFloatVersion -- return package version string                  */
+/*                                                                   */
+/*  returns a constant string describing this package                */
+/* ------------------------------------------------------------------ */
+const char *decFloatVersion(void) {
+  return DECVERSION;
+  } /* decFloatVersion */
+
+/* ------------------------------------------------------------------ */
+/* decFloatZero -- set to canonical (integer) zero                   */
+/*                                                                   */
+/*  df is the decFloat format number to integer +0 (q=0, c=+0)       */
+/*  returns df                                                       */
+/*                                                                   */
+/* No error is possible, and no status can be set.                   */
+/* ------------------------------------------------------------------ */
+decFloat * decFloatZero(decFloat *df){
+  DFWORD(df, 0)=ZEROWORD;     /* set appropriate top word */
+  #if DOUBLE || QUAD
+    DFWORD(df, 1)=0;
+    #if QUAD
+      DFWORD(df, 2)=0;
+      DFWORD(df, 3)=0;
+    #endif
+  #endif
+  /* decFloatShow(df, "zero"); */
+  return df;
+  } /* decFloatZero */
+
+/* ------------------------------------------------------------------ */
+/* Private generic function (not format-specific) for development use */
+/* ------------------------------------------------------------------ */
+/* This is included once only, for all to use */
+#if QUAD && (DECCHECK || DECTRACE)
+  /* ---------------------------------------------------------------- */
+  /* decShowNum -- display bcd8 number in debug form                 */
+  /*                                                                 */
+  /*   num is the bcdnum to display                                  */
+  /*   tag is a string to label the display                          */
+  /* ---------------------------------------------------------------- */
+  void decShowNum(const bcdnum *num, const char *tag) {
+    const char *csign="+";             /* sign character */
+    uByte *ub;                         /* work */
+    if (num->sign==DECFLOAT_Sign) csign="-";
+
+    printf(">%s> ", tag);
+    if (num->exponent==DECFLOAT_Inf) printf("%sInfinity", csign);
+    else if (num->exponent==DECFLOAT_qNaN) printf("%sqNaN", csign);
+    else if (num->exponent==DECFLOAT_sNaN) printf("%ssNaN", csign);
+    else {                             /* finite */
+     char qbuf[10];                    /* for right-aligned q */
+     char *c;                          /* work */
+     const uByte *u;                   /* .. */
+     Int e=num->exponent;              /* .. exponent */
+     strcpy(qbuf, "q=");
+     c=&qbuf[2];                       /* where exponent will go */
+     /* lay out the exponent */
+     if (e<0) {
+       *c++='-';                       /* add '-' */
+       e=-e;                           /* uInt, please */
+       }
+     #if DECEMAXD>4
+       #error Exponent form is too long for ShowNum to lay out
+     #endif
+     if (e==0) *c++='0';               /* 0-length case */
+      else if (e<1000) {               /* 3 (or fewer) digits case */
+       u=&BIN2BCD8[e*4];               /* -> 3 digits + length byte */
+       UINTAT(c)=UINTAT(u+3-*(u+3))|CHARMASK; /* [as above] */
+       c+=*(u+3);                      /* bump pointer appropriately */
+       }
+      else {                           /* 4-digits */
+       Int thou=((e>>3)*1049)>>17;     /* e/1000 */
+       Int rem=e-(1000*thou);          /* e%1000 */
+       *c++=(char)('0'+(char)thou);    /* the thousands digit */
+       u=&BIN2BCD8[rem*4];             /* -> 3 digits + length byte */
+       UINTAT(c)=UINTAT(u)|CHARMASK;   /* copy fixed 3+1 characters [is safe] */
+       c+=3;                           /* bump pointer, always 3 digits */
+       }
+     *c='\0';                          /* add terminator */
+     printf("%7s c=%s", qbuf, csign);
+     }
+
+    if (!EXPISSPECIAL(num->exponent) || num->msd!=num->lsd || *num->lsd!=0) {
+      for (ub=num->msd; ub<=num->lsd; ub++) { /* coefficient... */
+       printf("%1x", *ub);
+       if ((num->lsd-ub)%3==0 && ub!=num->lsd) printf(" "); /* 4-space */
+       }
+      }
+    printf("\n");
+    } /* decShowNum */
+#endif
index 66da2ae7956565438c8d312f2a36552b648bf91f..077419318194df44cc1d53f0a82580c90276816e 100644 (file)
@@ -1,5 +1,5 @@
 /* Decimal context module for the decNumber C Library.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-/*  This module compirises the routines for handling the arithmetic
-    context structures. */
-
-#include <string.h>            /* for strcmp */
-#include "config.h"
-#include "decContext.h"                /* context and base types */
-#include "decNumberLocal.h"    /* decNumber local types, etc. */
-
-/* ------------------------------------------------------------------ */
-/* decContextDefault -- initialize a context structure                */
-/*                                                                    */
-/*  context is the structure to be initialized                        */
-/*  kind selects the required set of default values, one of:          */
-/*      DEC_INIT_BASE       -- select ANSI X3-274 defaults            */
-/*      DEC_INIT_DECIMAL32  -- select IEEE 754r defaults, 32-bit      */
-/*      DEC_INIT_DECIMAL64  -- select IEEE 754r defaults, 64-bit      */
-/*      DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit     */
-/*      For any other value a valid context is returned, but with     */
-/*      Invalid_operation set in the status field.                    */
+/* ------------------------------------------------------------------ */
+/* Decimal Context module                                            */
+/* ------------------------------------------------------------------ */
+/* This module comprises the routines for handling arithmetic        */
+/* context structures.                                               */
+/* ------------------------------------------------------------------ */
+
+#include <string.h>          /* for strcmp */
+#include <stdio.h>           /* for printf if DECCHECK */
+#include "config.h"          /* for GCC definitions */
+#include "decContext.h"              /* context and base types */
+#include "decNumberLocal.h"   /* decNumber local types, etc. */
+
+#if DECCHECK
+/* compile-time endian tester [assumes sizeof(Int)>1] */
+static const  Int mfcone=1;                 /* constant 1 */
+static const  Flag *mfctop=(Flag *)&mfcone; /* -> top byte */
+#define LITEND *mfctop            /* named flag; 1=little-endian */
+#endif
+
+/* ------------------------------------------------------------------ */
+/* round-for-reround digits                                          */
+/* ------------------------------------------------------------------ */
+const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */
+
+/* ------------------------------------------------------------------ */
+/* Powers of ten (powers[n]==10**n, 0<=n<=9)                         */
+/* ------------------------------------------------------------------ */
+const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
+                         10000000, 100000000, 1000000000};
+
+/* ------------------------------------------------------------------ */
+/* decContextClearStatus -- clear bits in current status             */
+/*                                                                   */
+/*  context is the context structure to be queried                   */
+/*  mask indicates the bits to be cleared (the status bit that       */
+/*    corresponds to each 1 bit in the mask is cleared)                      */
+/*  returns context                                                  */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decContext *decContextClearStatus(decContext *context, uInt mask) {
+  context->status&=~mask;
+  return context;
+  } /* decContextClearStatus */
+
+/* ------------------------------------------------------------------ */
+/* decContextDefault -- initialize a context structure               */
+/*                                                                   */
+/*  context is the structure to be initialized                       */
+/*  kind selects the required set of default values, one of:         */
+/*     DEC_INIT_BASE       -- select ANSI X3-274 defaults            */
+/*     DEC_INIT_DECIMAL32  -- select IEEE 754r defaults, 32-bit      */
+/*     DEC_INIT_DECIMAL64  -- select IEEE 754r defaults, 64-bit      */
+/*     DEC_INIT_DECIMAL128 -- select IEEE 754r defaults, 128-bit     */
+/*     For any other value a valid context is returned, but with     */
+/*     Invalid_operation set in the status field.                    */
 /*  returns a context structure with the appropriate initial values.  */
 /* ------------------------------------------------------------------ */
-decContext *
-decContextDefault (decContext * context, Int kind)
-{
+decContext * decContextDefault(decContext *context, Int kind) {
   /* set defaults... */
-  context->digits = 9;         /* 9 digits */
-  context->emax = DEC_MAX_EMAX;        /* 9-digit exponents */
-  context->emin = DEC_MIN_EMIN;        /* .. balanced */
-  context->round = DEC_ROUND_HALF_UP;  /* 0.5 rises */
-  context->traps = DEC_Errors; /* all but informational */
-  context->status = 0;         /* cleared */
-  context->clamp = 0;          /* no clamping */
-#if DECSUBSET
-  context->extended = 0;       /* cleared */
-#endif
-  switch (kind)
-    {
+  context->digits=9;                        /* 9 digits */
+  context->emax=DEC_MAX_EMAX;               /* 9-digit exponents */
+  context->emin=DEC_MIN_EMIN;               /* .. balanced */
+  context->round=DEC_ROUND_HALF_UP;         /* 0.5 rises */
+  context->traps=DEC_Errors;                /* all but informational */
+  context->status=0;                        /* cleared */
+  context->clamp=0;                         /* no clamping */
+  #if DECSUBSET
+  context->extended=0;                      /* cleared */
+  #endif
+  switch (kind) {
     case DEC_INIT_BASE:
       /* [use defaults] */
       break;
     case DEC_INIT_DECIMAL32:
-      context->digits = 7;     /* digits */
-      context->emax = 96;      /* Emax */
-      context->emin = -95;     /* Emin */
-      context->round = DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even */
-      context->traps = 0;      /* no traps set */
-      context->clamp = 1;      /* clamp exponents */
-#if DECSUBSET
-      context->extended = 1;   /* set */
-#endif
+      context->digits=7;                    /* digits */
+      context->emax=96;                             /* Emax */
+      context->emin=-95;                    /* Emin */
+      context->round=DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even */
+      context->traps=0;                             /* no traps set */
+      context->clamp=1;                             /* clamp exponents */
+      #if DECSUBSET
+      context->extended=1;                  /* set */
+      #endif
       break;
     case DEC_INIT_DECIMAL64:
-      context->digits = 16;    /* digits */
-      context->emax = 384;     /* Emax */
-      context->emin = -383;    /* Emin */
-      context->round = DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even */
-      context->traps = 0;      /* no traps set */
-      context->clamp = 1;      /* clamp exponents */
-#if DECSUBSET
-      context->extended = 1;   /* set */
-#endif
+      context->digits=16;                   /* digits */
+      context->emax=384;                    /* Emax */
+      context->emin=-383;                   /* Emin */
+      context->round=DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even */
+      context->traps=0;                             /* no traps set */
+      context->clamp=1;                             /* clamp exponents */
+      #if DECSUBSET
+      context->extended=1;                  /* set */
+      #endif
       break;
     case DEC_INIT_DECIMAL128:
-      context->digits = 34;    /* digits */
-      context->emax = 6144;    /* Emax */
-      context->emin = -6143;   /* Emin */
-      context->round = DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even */
-      context->traps = 0;      /* no traps set */
-      context->clamp = 1;      /* clamp exponents */
-#if DECSUBSET
-      context->extended = 1;   /* set */
-#endif
+      context->digits=34;                   /* digits */
+      context->emax=6144;                   /* Emax */
+      context->emin=-6143;                  /* Emin */
+      context->round=DEC_ROUND_HALF_EVEN;    /* 0.5 to nearest even */
+      context->traps=0;                             /* no traps set */
+      context->clamp=1;                             /* clamp exponents */
+      #if DECSUBSET
+      context->extended=1;                  /* set */
+      #endif
       break;
 
-    default:                   /* invalid Kind */
+    default:                                /* invalid Kind */
       /* use defaults, and .. */
-      decContextSetStatus (context, DEC_Invalid_operation);    /* trap */
+      decContextSetStatus(context, DEC_Invalid_operation); /* trap */
+    }
+
+  #if DECCHECK
+  if (LITEND!=DECLITEND) {
+    const char *adj;
+    if (LITEND) adj="little";
+          else adj="big";
+    printf("Warning: DECLITEND is set to %d, but this computer appears to be %s-endian\n",
+          DECLITEND, adj);
     }
+  #endif
+  return context;} /* decContextDefault */
+
+/* ------------------------------------------------------------------ */
+/* decContextGetRounding -- return current rounding mode             */
+/*                                                                   */
+/*  context is the context structure to be queried                   */
+/*  returns the rounding mode                                        */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+enum rounding decContextGetRounding(decContext *context) {
+  return context->round;
+  } /* decContextGetRounding */
+
+/* ------------------------------------------------------------------ */
+/* decContextGetStatus -- return current status                              */
+/*                                                                   */
+/*  context is the context structure to be queried                   */
+/*  returns status                                                   */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+uInt decContextGetStatus(decContext *context) {
+  return context->status;
+  } /* decContextGetStatus */
+
+/* ------------------------------------------------------------------ */
+/* decContextRestoreStatus -- restore bits in current status         */
+/*                                                                   */
+/*  context is the context structure to be updated                   */
+/*  newstatus is the source for the bits to be restored                      */
+/*  mask indicates the bits to be restored (the status bit that              */
+/*    corresponds to each 1 bit in the mask is set to the value of    */
+/*    the correspnding bit in newstatus)                             */
+/*  returns context                                                  */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decContext *decContextRestoreStatus(decContext *context,
+                                   uInt newstatus, uInt mask) {
+  context->status&=~mask;              /* clear the selected bits */
+  context->status|=(mask&newstatus);   /* or in the new bits */
   return context;
-}                              /* decContextDefault */
+  } /* decContextRestoreStatus */
 
 /* ------------------------------------------------------------------ */
-/* decContextStatusToString -- convert status flags to a string       */
-/*                                                                    */
-/*  context is a context with valid status field                      */
-/*                                                                    */
-/*  returns a constant string describing the condition.  If multiple  */
-/*    (or no) flags are set, a generic constant message is returned.  */
+/* decContextSaveStatus -- save bits in current status               */
+/*                                                                   */
+/*  context is the context structure to be queried                   */
+/*  mask indicates the bits to be saved (the status bits that        */
+/*    correspond to each 1 bit in the mask are saved)                */
+/*  returns the AND of the mask and the current status               */
+/*                                                                   */
+/* No error is possible.                                             */
 /* ------------------------------------------------------------------ */
-const char *
-decContextStatusToString (const decContext * context)
-{
-  Int status = context->status;
-  if (status == DEC_Conversion_syntax)
-    return DEC_Condition_CS;
-  if (status == DEC_Division_by_zero)
-    return DEC_Condition_DZ;
-  if (status == DEC_Division_impossible)
-    return DEC_Condition_DI;
-  if (status == DEC_Division_undefined)
-    return DEC_Condition_DU;
-  if (status == DEC_Inexact)
-    return DEC_Condition_IE;
-  if (status == DEC_Insufficient_storage)
-    return DEC_Condition_IS;
-  if (status == DEC_Invalid_context)
-    return DEC_Condition_IC;
-  if (status == DEC_Invalid_operation)
-    return DEC_Condition_IO;
-#if DECSUBSET
-  if (status == DEC_Lost_digits)
-    return DEC_Condition_LD;
-#endif
-  if (status == DEC_Overflow)
-    return DEC_Condition_OV;
-  if (status == DEC_Clamped)
-    return DEC_Condition_PA;
-  if (status == DEC_Rounded)
-    return DEC_Condition_RO;
-  if (status == DEC_Subnormal)
-    return DEC_Condition_SU;
-  if (status == DEC_Underflow)
-    return DEC_Condition_UN;
-  if (status == 0)
-    return DEC_Condition_ZE;
-  return DEC_Condition_MU;     /* Multiple errors */
-}                              /* decContextStatusToString */
-
-/* ------------------------------------------------------------------ */
-/* decContextSetStatusFromString -- set status from a string          */
-/*                                                                    */
-/*  context is the controlling context                                */
+uInt decContextSaveStatus(decContext *context, uInt mask) {
+  return context->status&mask;
+  } /* decContextSaveStatus */
+
+/* ------------------------------------------------------------------ */
+/* decContextSetRounding -- set current rounding mode                */
+/*                                                                   */
+/*  context is the context structure to be updated                   */
+/*  newround is the value which will replace the current mode        */
+/*  returns context                                                  */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decContext *decContextSetRounding(decContext *context,
+                                 enum rounding newround) {
+  context->round=newround;
+  return context;
+  } /* decContextSetRounding */
+
+/* ------------------------------------------------------------------ */
+/* decContextSetStatus -- set status and raise trap if appropriate    */
+/*                                                                   */
+/*  context is the context structure to be updated                   */
+/*  status  is the DEC_ exception code                               */
+/*  returns the context structure                                    */
+/*                                                                   */
+/* Control may never return from this routine, if there is a signal   */
+/* handler and it takes a long jump.                                 */
+/* ------------------------------------------------------------------ */
+decContext * decContextSetStatus(decContext *context, uInt status) {
+  context->status|=status;
+  if (status & context->traps) raise(SIGFPE);
+  return context;} /* decContextSetStatus */
+
+/* ------------------------------------------------------------------ */
+/* decContextSetStatusFromString -- set status from a string + trap   */
+/*                                                                   */
+/*  context is the context structure to be updated                   */
 /*  string is a string exactly equal to one that might be returned    */
-/*            by decContextStatusToString                             */
-/*                                                                    */
+/*           by decContextStatusToString                             */
+/*                                                                   */
 /*  The status bit corresponding to the string is set, and a trap     */
-/*  is raised if appropriate.                                         */
-/*                                                                    */
+/*  is raised if appropriate.                                        */
+/*                                                                   */
 /*  returns the context structure, unless the string is equal to      */
 /*    DEC_Condition_MU or is not recognized.  In these cases NULL is  */
-/*    returned.                                                       */
-/* ------------------------------------------------------------------ */
-decContext *
-decContextSetStatusFromString (decContext * context, const char *string)
-{
-  if (strcmp (string, DEC_Condition_CS) == 0)
-    return decContextSetStatus (context, DEC_Conversion_syntax);
-  if (strcmp (string, DEC_Condition_DZ) == 0)
-    return decContextSetStatus (context, DEC_Division_by_zero);
-  if (strcmp (string, DEC_Condition_DI) == 0)
-    return decContextSetStatus (context, DEC_Division_impossible);
-  if (strcmp (string, DEC_Condition_DU) == 0)
-    return decContextSetStatus (context, DEC_Division_undefined);
-  if (strcmp (string, DEC_Condition_IE) == 0)
-    return decContextSetStatus (context, DEC_Inexact);
-  if (strcmp (string, DEC_Condition_IS) == 0)
-    return decContextSetStatus (context, DEC_Insufficient_storage);
-  if (strcmp (string, DEC_Condition_IC) == 0)
-    return decContextSetStatus (context, DEC_Invalid_context);
-  if (strcmp (string, DEC_Condition_IO) == 0)
-    return decContextSetStatus (context, DEC_Invalid_operation);
-#if DECSUBSET
-  if (strcmp (string, DEC_Condition_LD) == 0)
-    return decContextSetStatus (context, DEC_Lost_digits);
-#endif
-  if (strcmp (string, DEC_Condition_OV) == 0)
-    return decContextSetStatus (context, DEC_Overflow);
-  if (strcmp (string, DEC_Condition_PA) == 0)
-    return decContextSetStatus (context, DEC_Clamped);
-  if (strcmp (string, DEC_Condition_RO) == 0)
-    return decContextSetStatus (context, DEC_Rounded);
-  if (strcmp (string, DEC_Condition_SU) == 0)
-    return decContextSetStatus (context, DEC_Subnormal);
-  if (strcmp (string, DEC_Condition_UN) == 0)
-    return decContextSetStatus (context, DEC_Underflow);
-  if (strcmp (string, DEC_Condition_ZE) == 0)
+/*    returned.                                                              */
+/* ------------------------------------------------------------------ */
+decContext * decContextSetStatusFromString(decContext *context,
+                                          const char *string) {
+  if (strcmp(string, DEC_Condition_CS)==0)
+    return decContextSetStatus(context, DEC_Conversion_syntax);
+  if (strcmp(string, DEC_Condition_DZ)==0)
+    return decContextSetStatus(context, DEC_Division_by_zero);
+  if (strcmp(string, DEC_Condition_DI)==0)
+    return decContextSetStatus(context, DEC_Division_impossible);
+  if (strcmp(string, DEC_Condition_DU)==0)
+    return decContextSetStatus(context, DEC_Division_undefined);
+  if (strcmp(string, DEC_Condition_IE)==0)
+    return decContextSetStatus(context, DEC_Inexact);
+  if (strcmp(string, DEC_Condition_IS)==0)
+    return decContextSetStatus(context, DEC_Insufficient_storage);
+  if (strcmp(string, DEC_Condition_IC)==0)
+    return decContextSetStatus(context, DEC_Invalid_context);
+  if (strcmp(string, DEC_Condition_IO)==0)
+    return decContextSetStatus(context, DEC_Invalid_operation);
+  #if DECSUBSET
+  if (strcmp(string, DEC_Condition_LD)==0)
+    return decContextSetStatus(context, DEC_Lost_digits);
+  #endif
+  if (strcmp(string, DEC_Condition_OV)==0)
+    return decContextSetStatus(context, DEC_Overflow);
+  if (strcmp(string, DEC_Condition_PA)==0)
+    return decContextSetStatus(context, DEC_Clamped);
+  if (strcmp(string, DEC_Condition_RO)==0)
+    return decContextSetStatus(context, DEC_Rounded);
+  if (strcmp(string, DEC_Condition_SU)==0)
+    return decContextSetStatus(context, DEC_Subnormal);
+  if (strcmp(string, DEC_Condition_UN)==0)
+    return decContextSetStatus(context, DEC_Underflow);
+  if (strcmp(string, DEC_Condition_ZE)==0)
     return context;
-  return NULL;                 /* Multiple status, or unknown */
-}                              /* decContextSetStatusFromString */
+  return NULL; /* Multiple status, or unknown */
+  } /* decContextSetStatusFromString */
 
 /* ------------------------------------------------------------------ */
-/* decContextSetStatus -- set status and raise trap if appropriate    */
-/*                                                                    */
-/*  context is the controlling context                                */
-/*  status  is the DEC_ exception code                                */
-/*  returns the context structure                                     */
-/*                                                                    */
-/* Control may never return from this routine, if there is a signal   */
-/* handler and it takes a long jump.                                  */
-/* ------------------------------------------------------------------ */
-decContext *
-decContextSetStatus (decContext * context, uInt status)
-{
-  context->status |= status;
-  if (status & context->traps)
-    raise (SIGFPE);
+/* decContextSetStatusFromStringQuiet -- set status from a string     */
+/*                                                                   */
+/*  context is the context structure to be updated                   */
+/*  string is a string exactly equal to one that might be returned    */
+/*           by decContextStatusToString                             */
+/*                                                                   */
+/*  The status bit corresponding to the string is set; no trap is     */
+/*  raised.                                                          */
+/*                                                                   */
+/*  returns the context structure, unless the string is equal to      */
+/*    DEC_Condition_MU or is not recognized.  In these cases NULL is  */
+/*    returned.                                                              */
+/* ------------------------------------------------------------------ */
+decContext * decContextSetStatusFromStringQuiet(decContext *context,
+                                               const char *string) {
+  if (strcmp(string, DEC_Condition_CS)==0)
+    return decContextSetStatusQuiet(context, DEC_Conversion_syntax);
+  if (strcmp(string, DEC_Condition_DZ)==0)
+    return decContextSetStatusQuiet(context, DEC_Division_by_zero);
+  if (strcmp(string, DEC_Condition_DI)==0)
+    return decContextSetStatusQuiet(context, DEC_Division_impossible);
+  if (strcmp(string, DEC_Condition_DU)==0)
+    return decContextSetStatusQuiet(context, DEC_Division_undefined);
+  if (strcmp(string, DEC_Condition_IE)==0)
+    return decContextSetStatusQuiet(context, DEC_Inexact);
+  if (strcmp(string, DEC_Condition_IS)==0)
+    return decContextSetStatusQuiet(context, DEC_Insufficient_storage);
+  if (strcmp(string, DEC_Condition_IC)==0)
+    return decContextSetStatusQuiet(context, DEC_Invalid_context);
+  if (strcmp(string, DEC_Condition_IO)==0)
+    return decContextSetStatusQuiet(context, DEC_Invalid_operation);
+  #if DECSUBSET
+  if (strcmp(string, DEC_Condition_LD)==0)
+    return decContextSetStatusQuiet(context, DEC_Lost_digits);
+  #endif
+  if (strcmp(string, DEC_Condition_OV)==0)
+    return decContextSetStatusQuiet(context, DEC_Overflow);
+  if (strcmp(string, DEC_Condition_PA)==0)
+    return decContextSetStatusQuiet(context, DEC_Clamped);
+  if (strcmp(string, DEC_Condition_RO)==0)
+    return decContextSetStatusQuiet(context, DEC_Rounded);
+  if (strcmp(string, DEC_Condition_SU)==0)
+    return decContextSetStatusQuiet(context, DEC_Subnormal);
+  if (strcmp(string, DEC_Condition_UN)==0)
+    return decContextSetStatusQuiet(context, DEC_Underflow);
+  if (strcmp(string, DEC_Condition_ZE)==0)
+    return context;
+  return NULL; /* Multiple status, or unknown */
+  } /* decContextSetStatusFromStringQuiet */
+
+/* ------------------------------------------------------------------ */
+/* decContextSetStatusQuiet -- set status without trap               */
+/*                                                                   */
+/*  context is the context structure to be updated                   */
+/*  status  is the DEC_ exception code                               */
+/*  returns the context structure                                    */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decContext * decContextSetStatusQuiet(decContext *context, uInt status) {
+  context->status|=status;
+  return context;} /* decContextSetStatusQuiet */
+
+/* ------------------------------------------------------------------ */
+/* decContextStatusToString -- convert status flags to a string              */
+/*                                                                   */
+/*  context is a context with valid status field                     */
+/*                                                                   */
+/*  returns a constant string describing the condition.         If multiple  */
+/*    (or no) flags are set, a generic constant message is returned.  */
+/* ------------------------------------------------------------------ */
+const char *decContextStatusToString(const decContext *context) {
+  Int status=context->status;
+
+  /* test the five IEEE first, as some of the others are ambiguous when */
+  /* DECEXTFLAG=0 */
+  if (status==DEC_Invalid_operation    ) return DEC_Condition_IO;
+  if (status==DEC_Division_by_zero     ) return DEC_Condition_DZ;
+  if (status==DEC_Overflow            ) return DEC_Condition_OV;
+  if (status==DEC_Underflow           ) return DEC_Condition_UN;
+  if (status==DEC_Inexact             ) return DEC_Condition_IE;
+
+  if (status==DEC_Division_impossible  ) return DEC_Condition_DI;
+  if (status==DEC_Division_undefined   ) return DEC_Condition_DU;
+  if (status==DEC_Rounded             ) return DEC_Condition_RO;
+  if (status==DEC_Clamped             ) return DEC_Condition_PA;
+  if (status==DEC_Subnormal           ) return DEC_Condition_SU;
+  if (status==DEC_Conversion_syntax    ) return DEC_Condition_CS;
+  if (status==DEC_Insufficient_storage ) return DEC_Condition_IS;
+  if (status==DEC_Invalid_context      ) return DEC_Condition_IC;
+  #if DECSUBSET
+  if (status==DEC_Lost_digits         ) return DEC_Condition_LD;
+  #endif
+  if (status==0                               ) return DEC_Condition_ZE;
+  return DEC_Condition_MU;  /* Multiple errors */
+  } /* decContextStatusToString */
+
+/* ------------------------------------------------------------------ */
+/* decContextTestSavedStatus -- test bits in saved status            */
+/*                                                                   */
+/*  oldstatus is the status word to be tested                        */
+/*  mask indicates the bits to be tested (the oldstatus bits that     */
+/*    correspond to each 1 bit in the mask are tested)               */
+/*  returns 1 if any of the tested bits are 1, or 0 otherwise        */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+uInt decContextTestSavedStatus(uInt oldstatus, uInt mask) {
+  return (oldstatus&mask)!=0;
+  } /* decContextTestSavedStatus */
+
+/* ------------------------------------------------------------------ */
+/* decContextTestStatus -- test bits in current status               */
+/*                                                                   */
+/*  context is the context structure to be updated                   */
+/*  mask indicates the bits to be tested (the status bits that       */
+/*    correspond to each 1 bit in the mask are tested)               */
+/*  returns 1 if any of the tested bits are 1, or 0 otherwise        */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+uInt decContextTestStatus(decContext *context, uInt mask) {
+  return (context->status&mask)!=0;
+  } /* decContextTestStatus */
+
+/* ------------------------------------------------------------------ */
+/* decContextZeroStatus -- clear all status bits                     */
+/*                                                                   */
+/*  context is the context structure to be updated                   */
+/*  returns context                                                  */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decContext *decContextZeroStatus(decContext *context) {
+  context->status=0;
   return context;
-}                              /* decContextSetStatus */
+  } /* decContextZeroStatus */
+
index 5252b33d52936e06797eecbace33db942bf4512f..f80d03c50cf5710a4c3b2a6994d087794fc4c237 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal Context module header for the decNumber C Library
-   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+/* Decimal context header module for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    02110-1301, USA.  */
 
 /* ------------------------------------------------------------------ */
-/*                                                                    */
-/* Context must always be set correctly:                              */
-/*                                                                    */
-/*  digits   -- must be in the range 1 through 999999999              */
-/*  emax     -- must be in the range 0 through 999999999              */
-/*  emin     -- must be in the range 0 through -999999999             */
-/*  round    -- must be one of the enumerated rounding modes          */
-/*  traps    -- only defined bits may be set                          */
-/*  status   -- [any bits may be cleared, but not set, by user]       */
-/*  clamp    -- must be either 0 or 1                                 */
+/* Decimal Context module header                                     */
+/* ------------------------------------------------------------------ */
+/*                                                                   */
+/* Context variables must always have valid values:                  */
+/*                                                                   */
+/*  status   -- [any bits may be cleared, but not set, by user]              */
+/*  round    -- must be one of the enumerated rounding modes         */
+/*                                                                   */
+/* The following variables are implied for fixed size formats (i.e.,  */
+/* they are ignored) but should still be set correctly in case used   */
+/* with decNumber functions:                                         */
+/*                                                                   */
+/*  clamp    -- must be either 0 or 1                                */
+/*  digits   -- must be in the range 1 through 999999999             */
+/*  emax     -- must be in the range 0 through 999999999             */
+/*  emin     -- must be in the range 0 through -999999999            */
 /*  extended -- must be either 0 or 1 [present only if DECSUBSET]     */
-/*                                                                    */
+/*  traps    -- only defined bits may be set                         */
+/*                                                                   */
 /* ------------------------------------------------------------------ */
 
 #if !defined(DECCONTEXT)
-#define DECCONTEXT
-#define DECCNAME     "decContext"      /* Short name */
-#define DECCFULLNAME "Decimal Context Descriptor"      /* Verbose name */
-#define DECCAUTHOR   "Mike Cowlishaw"  /* Who to blame */
-
-#include "gstdint.h"           /* C99 standard integers */
-#include <signal.h>            /* for traps */
-
-
-  /* Conditional code flag -- set this to 0 for best performance */
-#define DECSUBSET 0            /* 1 to enable subset arithmetic */
-
-  /* Context for operations, with associated constants */
-enum rounding
-{
-  DEC_ROUND_CEILING,           /* round towards +infinity */
-  DEC_ROUND_UP,                        /* round away from 0 */
-  DEC_ROUND_HALF_UP,           /* 0.5 rounds up */
-  DEC_ROUND_HALF_EVEN,         /* 0.5 rounds to nearest even */
-  DEC_ROUND_HALF_DOWN,         /* 0.5 rounds down */
-  DEC_ROUND_DOWN,              /* round towards 0 (truncate) */
-  DEC_ROUND_FLOOR,             /* round towards -infinity */
-  DEC_ROUND_MAX                        /* enum must be less than this */
-};
-
-typedef struct
-{
-  int32_t digits;              /* working precision */
-  int32_t emax;                        /* maximum positive exponent */
-  int32_t emin;                        /* minimum negative exponent */
-  enum rounding round;         /* rounding mode */
-  uint32_t traps;              /* trap-enabler flags */
-  uint32_t status;             /* status flags */
-  uint8_t clamp;               /* flag: apply IEEE exponent clamp */
-#if DECSUBSET
-  uint8_t extended;            /* flag: special-values allowed */
-#endif
-} decContext;
-
-  /* Maxima and Minima */
-#define DEC_MAX_DIGITS 999999999
-#define DEC_MIN_DIGITS         1
-#define DEC_MAX_EMAX   999999999
-#define DEC_MIN_EMAX           0
-#define DEC_MAX_EMIN           0
-#define DEC_MIN_EMIN  -999999999
-
-  /* Trap-enabler and Status flags (exceptional conditions), and their names */
-  /* Top byte is reserved for internal use */
-#define DEC_Conversion_syntax    0x00000001
-#define DEC_Division_by_zero     0x00000002
-#define DEC_Division_impossible  0x00000004
-#define DEC_Division_undefined   0x00000008
-#define DEC_Insufficient_storage 0x00000010    /* [used if malloc fails] */
-#define DEC_Inexact              0x00000020
-#define DEC_Invalid_context      0x00000040
-#define DEC_Invalid_operation    0x00000080
-#if DECSUBSET
-#define DEC_Lost_digits          0x00000100
-#endif
-#define DEC_Overflow             0x00000200
-#define DEC_Clamped              0x00000400
-#define DEC_Rounded              0x00000800
-#define DEC_Subnormal            0x00001000
-#define DEC_Underflow            0x00002000
-
-  /* IEEE 854 groupings for the flags */
-  /* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal are */
-  /* not in IEEE 854] */
-#define DEC_IEEE_854_Division_by_zero  (DEC_Division_by_zero)
-#if DECSUBSET
-#define DEC_IEEE_854_Inexact           (DEC_Inexact | DEC_Lost_digits)
-#else
-#define DEC_IEEE_854_Inexact           (DEC_Inexact)
-#endif
-#define DEC_IEEE_854_Invalid_operation (DEC_Conversion_syntax |     \
-                                          DEC_Division_impossible |   \
-                                          DEC_Division_undefined |    \
-                                          DEC_Insufficient_storage |  \
-                                          DEC_Invalid_context |       \
-                                          DEC_Invalid_operation)
-#define DEC_IEEE_854_Overflow          (DEC_Overflow)
-#define DEC_IEEE_854_Underflow         (DEC_Underflow)
-
-  /* flags which are normally errors (results are qNaN, infinite, or 0) */
-#define DEC_Errors (DEC_IEEE_854_Division_by_zero |                 \
-                      DEC_IEEE_854_Invalid_operation |                \
-                      DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow)
-  /* flags which cause a result to become qNaN */
-#define DEC_NaNs    DEC_IEEE_854_Invalid_operation
-
-  /* flags which are normally for information only (have finite results) */
-#if DECSUBSET
-#define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact     \
-                          | DEC_Lost_digits)
-#else
-#define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact)
-#endif
+  #define DECCONTEXT
+  #define DECCNAME     "decContext"                    /* Short name */
+  #define DECCFULLNAME "Decimal Context Descriptor"   /* Verbose name */
+  #define DECCAUTHOR   "Mike Cowlishaw"                      /* Who to blame */
 
-  /* name strings for the exceptional conditions */
-
-#define DEC_Condition_CS "Conversion syntax"
-#define DEC_Condition_DZ "Division by zero"
-#define DEC_Condition_DI "Division impossible"
-#define DEC_Condition_DU "Division undefined"
-#define DEC_Condition_IE "Inexact"
-#define DEC_Condition_IS "Insufficient storage"
-#define DEC_Condition_IC "Invalid context"
-#define DEC_Condition_IO "Invalid operation"
-#if DECSUBSET
-#define DEC_Condition_LD "Lost digits"
-#endif
-#define DEC_Condition_OV "Overflow"
-#define DEC_Condition_PA "Clamped"
-#define DEC_Condition_RO "Rounded"
-#define DEC_Condition_SU "Subnormal"
-#define DEC_Condition_UN "Underflow"
-#define DEC_Condition_ZE "No status"
-#define DEC_Condition_MU "Multiple status"
-#define DEC_Condition_Length 21        /* length of the longest string, */
-                                  /* including terminator */
-
-  /* Initialization descriptors, used by decContextDefault */
-#define DEC_INIT_BASE         0
-#define DEC_INIT_DECIMAL32   32
-#define DEC_INIT_DECIMAL64   64
-#define DEC_INIT_DECIMAL128 128
-
-  /* decContext routines */
-#ifdef IN_LIBGCC2
-#define decContextDefault __decContextDefault
-#define decContextSetStatus __decContextSetStatus
-#define decContextStatusToString __decContextStatusToString
-#define decContextSetStatusFromString __decContextSetStatusFromString
-#endif
-decContext *decContextDefault (decContext *, int32_t);
-decContext *decContextSetStatus (decContext *, uint32_t);
-const char *decContextStatusToString (const decContext *);
-decContext *decContextSetStatusFromString (decContext *, const char *);
+  #include "gstdint.h"            /* C99 standard integers           */
+  #include <stdio.h>              /* for printf, etc.                */
+  #include <signal.h>             /* for traps                       */
+
+  /* Extended flags setting -- set this to 0 to use only IEEE flags   */
+  #define DECEXTFLAG 1            /* 1=enable extended flags         */
+
+  /* Conditional code flag -- set this to 0 for best performance      */
+  #define DECSUBSET  0            /* 1=enable subset arithmetic      */
+
+  /* Context for operations, with associated constants               */
+  enum rounding {
+    DEC_ROUND_CEILING,            /* round towards +infinity         */
+    DEC_ROUND_UP,                 /* round away from 0               */
+    DEC_ROUND_HALF_UP,            /* 0.5 rounds up                   */
+    DEC_ROUND_HALF_EVEN,          /* 0.5 rounds to nearest even      */
+    DEC_ROUND_HALF_DOWN,          /* 0.5 rounds down                 */
+    DEC_ROUND_DOWN,               /* round towards 0 (truncate)      */
+    DEC_ROUND_FLOOR,              /* round towards -infinity         */
+    DEC_ROUND_05UP,               /* round for reround               */
+    DEC_ROUND_MAX                 /* enum must be less than this     */
+    };
+  #define DEC_ROUND_DEFAULT DEC_ROUND_HALF_EVEN;
+
+  typedef struct {
+    int32_t  digits;              /* working precision               */
+    int32_t  emax;                /* maximum positive exponent       */
+    int32_t  emin;                /* minimum negative exponent       */
+    enum     rounding round;      /* rounding mode                   */
+    uint32_t traps;               /* trap-enabler flags              */
+    uint32_t status;              /* status flags                    */
+    uint8_t  clamp;               /* flag: apply IEEE exponent clamp */
+    #if DECSUBSET
+    uint8_t  extended;            /* flag: special-values allowed    */
+    #endif
+    } decContext;
+
+  /* Maxima and Minima for context settings                          */
+  #define DEC_MAX_DIGITS 999999999
+  #define DEC_MIN_DIGITS        1
+  #define DEC_MAX_EMAX  999999999
+  #define DEC_MIN_EMAX          0
+  #define DEC_MAX_EMIN          0
+  #define DEC_MIN_EMIN -999999999
+  #define DEC_MAX_MATH     999999 /* max emax, etc., for math funcs. */
+
+  /* Classifications for decimal numbers, aligned with 754r (note     */
+  /* that 'normal' and 'subnormal' are meaningful only with a        */
+  /* decContext or a fixed size format).                             */
+  enum decClass {
+    DEC_CLASS_SNAN,
+    DEC_CLASS_QNAN,
+    DEC_CLASS_NEG_INF,
+    DEC_CLASS_NEG_NORMAL,
+    DEC_CLASS_NEG_SUBNORMAL,
+    DEC_CLASS_NEG_ZERO,
+    DEC_CLASS_POS_ZERO,
+    DEC_CLASS_POS_SUBNORMAL,
+    DEC_CLASS_POS_NORMAL,
+    DEC_CLASS_POS_INF
+    };
+  /* Strings for the decClasses */
+  #define DEC_ClassString_SN  "sNaN"
+  #define DEC_ClassString_QN  "NaN"
+  #define DEC_ClassString_NI  "-Infinity"
+  #define DEC_ClassString_NN  "-Normal"
+  #define DEC_ClassString_NS  "-Subnormal"
+  #define DEC_ClassString_NZ  "-Zero"
+  #define DEC_ClassString_PZ  "+Zero"
+  #define DEC_ClassString_PS  "+Subnormal"
+  #define DEC_ClassString_PN  "+Normal"
+  #define DEC_ClassString_PI  "+Infinity"
+  #define DEC_ClassString_UN  "Invalid"
+
+  /* Trap-enabler and Status flags (exceptional conditions), and      */
+  /* their names.  The top byte is reserved for internal use         */
+  #if DECEXTFLAG
+    /* Extended flags */
+    #define DEC_Conversion_syntax    0x00000001
+    #define DEC_Division_by_zero     0x00000002
+    #define DEC_Division_impossible  0x00000004
+    #define DEC_Division_undefined   0x00000008
+    #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */
+    #define DEC_Inexact                     0x00000020
+    #define DEC_Invalid_context             0x00000040
+    #define DEC_Invalid_operation    0x00000080
+    #if DECSUBSET
+    #define DEC_Lost_digits         0x00000100
+    #endif
+    #define DEC_Overflow            0x00000200
+    #define DEC_Clamped                     0x00000400
+    #define DEC_Rounded                     0x00000800
+    #define DEC_Subnormal           0x00001000
+    #define DEC_Underflow           0x00002000
+  #else
+    /* IEEE flags only */
+    #define DEC_Conversion_syntax    0x00000010
+    #define DEC_Division_by_zero     0x00000002
+    #define DEC_Division_impossible  0x00000010
+    #define DEC_Division_undefined   0x00000010
+    #define DEC_Insufficient_storage 0x00000010 /* [when malloc fails] */
+    #define DEC_Inexact                     0x00000001
+    #define DEC_Invalid_context             0x00000010
+    #define DEC_Invalid_operation    0x00000010
+    #if DECSUBSET
+    #define DEC_Lost_digits         0x00000000
+    #endif
+    #define DEC_Overflow            0x00000008
+    #define DEC_Clamped                     0x00000000
+    #define DEC_Rounded                     0x00000000
+    #define DEC_Subnormal           0x00000000
+    #define DEC_Underflow           0x00000004
+  #endif
+
+  /* IEEE 854 groupings for the flags                                */
+  /* [DEC_Clamped, DEC_Lost_digits, DEC_Rounded, and DEC_Subnormal    */
+  /* are not in IEEE 854]                                            */
+  #define DEC_IEEE_854_Division_by_zero         (DEC_Division_by_zero)
+  #if DECSUBSET
+  #define DEC_IEEE_854_Inexact          (DEC_Inexact | DEC_Lost_digits)
+  #else
+  #define DEC_IEEE_854_Inexact          (DEC_Inexact)
+  #endif
+  #define DEC_IEEE_854_Invalid_operation (DEC_Conversion_syntax |     \
+                                         DEC_Division_impossible |   \
+                                         DEC_Division_undefined |    \
+                                         DEC_Insufficient_storage |  \
+                                         DEC_Invalid_context |       \
+                                         DEC_Invalid_operation)
+  #define DEC_IEEE_854_Overflow                 (DEC_Overflow)
+  #define DEC_IEEE_854_Underflow        (DEC_Underflow)
+
+  /* flags which are normally errors (result is qNaN, infinite, or 0) */
+  #define DEC_Errors (DEC_IEEE_854_Division_by_zero |                \
+                     DEC_IEEE_854_Invalid_operation |                \
+                     DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow)
+  /* flags which cause a result to become qNaN                       */
+  #define DEC_NaNs    DEC_IEEE_854_Invalid_operation
+
+  /* flags which are normally for information only (finite results)   */
+  #if DECSUBSET
+  #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact    \
+                         | DEC_Lost_digits)
+  #else
+  #define DEC_Information (DEC_Clamped | DEC_Rounded | DEC_Inexact)
+  #endif
+
+  /* Name strings for the exceptional conditions                     */
+  #define DEC_Condition_CS "Conversion syntax"
+  #define DEC_Condition_DZ "Division by zero"
+  #define DEC_Condition_DI "Division impossible"
+  #define DEC_Condition_DU "Division undefined"
+  #define DEC_Condition_IE "Inexact"
+  #define DEC_Condition_IS "Insufficient storage"
+  #define DEC_Condition_IC "Invalid context"
+  #define DEC_Condition_IO "Invalid operation"
+  #if DECSUBSET
+  #define DEC_Condition_LD "Lost digits"
+  #endif
+  #define DEC_Condition_OV "Overflow"
+  #define DEC_Condition_PA "Clamped"
+  #define DEC_Condition_RO "Rounded"
+  #define DEC_Condition_SU "Subnormal"
+  #define DEC_Condition_UN "Underflow"
+  #define DEC_Condition_ZE "No status"
+  #define DEC_Condition_MU "Multiple status"
+  #define DEC_Condition_Length 21  /* length of the longest string,   */
+                                  /* including terminator            */
+
+  /* Initialization descriptors, used by decContextDefault           */
+  #define DEC_INIT_BASE                0
+  #define DEC_INIT_DECIMAL32   32
+  #define DEC_INIT_DECIMAL64   64
+  #define DEC_INIT_DECIMAL128 128
+  /* Synonyms */
+  #define DEC_INIT_DECSINGLE  DEC_INIT_DECIMAL32
+  #define DEC_INIT_DECDOUBLE  DEC_INIT_DECIMAL64
+  #define DEC_INIT_DECQUAD    DEC_INIT_DECIMAL128
+
+  /* decContext routines                                             */
+
+  #include "decContextSymbols.h"
+
+  extern decContext  * decContextClearStatus(decContext *, uint32_t);
+  extern decContext  * decContextDefault(decContext *, int32_t);
+  extern enum rounding decContextGetRounding(decContext *);
+  extern uint32_t      decContextGetStatus(decContext *);
+  extern decContext  * decContextRestoreStatus(decContext *, uint32_t, uint32_t);
+  extern uint32_t      decContextSaveStatus(decContext *, uint32_t);
+  extern decContext  * decContextSetRounding(decContext *, enum rounding);
+  extern decContext  * decContextSetStatus(decContext *, uint32_t);
+  extern decContext  * decContextSetStatusFromString(decContext *, const char *);
+  extern decContext  * decContextSetStatusFromStringQuiet(decContext *, const char *);
+  extern decContext  * decContextSetStatusQuiet(decContext *, uint32_t);
+  extern const char  * decContextStatusToString(const decContext *);
+  extern uint32_t      decContextTestSavedStatus(uint32_t, uint32_t);
+  extern uint32_t      decContextTestStatus(decContext *, uint32_t);
+  extern decContext  * decContextZeroStatus(decContext *);
 
 #endif
diff --git a/libdecnumber/decContextSymbols.h b/libdecnumber/decContextSymbols.h
new file mode 100644 (file)
index 0000000..38830a9
--- /dev/null
@@ -0,0 +1,22 @@
+#if !defined(DECCONTEXTSYMBOLS)
+#define DECCONTEXTSYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decContextClearStatus __decContextClearStatus
+#define decContextDefault __decContextDefault
+#define decContextGetRounding __decContextGetRounding
+#define decContextGetStatus __decContextGetStatus
+#define decContextRestoreStatus __decContextRestoreStatus
+#define decContextSaveStatus __decContextSaveStatus
+#define decContextSetRounding __decContextSetRounding
+#define decContextSetStatus __decContextSetStatus
+#define decContextSetStatusFromString __decContextSetStatusFromString
+#define decContextSetStatusFromStringQuiet __decContextSetStatusFromStringQuiet
+#define decContextSetStatusQuiet __decContextSetStatusQuiet
+#define decContextStatusToString __decContextStatusToString
+#define decContextTestSavedStatus __decContextTestSavedStatus
+#define decContextTestStatus __decContextTestStatus
+#define decContextZeroStatus __decContextZeroStatus
+#endif
+
+#endif
index 159683bb9604a4810115a88815d55e7dcd521c1e..8e0347c6aa85f6413e9a0b05c65339389a67e01f 100644 (file)
@@ -1,5 +1,5 @@
-/* Binary Coded Decimal <--> Densely Packed Decimal lookup tables.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Conversion lookup tables for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    02110-1301, USA.  */
 
 /* ------------------------------------------------------------------------ */
-/* For details, see: http://www2.hursley.ibm.com/decimal/DPDecimal.html     */
-/*                                                                          */
-/* This include file defines conversion tables for DPD, as follows.         */
-/*                                                                          */
-/*   uint16_t BCD2DPD[2458];     // BCD -> DPD (0x999 => 2457)              */
-/*   uint16_t DPD2BCD[1024];     // DPD -> BCD (0x3FF => 0x999)             */
-/*   uint16_t BIN2DPD[1000];     // BIN -> DPD (999 => 2457)                */
-/*   uint16_t DPD2BIN[1024];     // DPD -> BIN (0x3FF => 999)               */
-/*                                                                          */
+/* Binary Coded Decimal and Densely Packed Decimal conversion lookup tables */
+/* [Automatically generated -- do not edit.  2007.05.05]                   */
+/* ------------------------------------------------------------------------ */
+/* ------------------------------------------------------------------------ */
+/* For details, see: http://www2.hursley.ibm.com/decimal/DPDecimal.html            */
+/*                                                                         */
+/* This include file defines several DPD and BCD conversion tables:        */
+/*                                                                         */
+/*   uint16_t BCD2DPD[2458];    -- BCD -> DPD (0x999 => 2457)              */
+/*   uint16_t BIN2DPD[1000];    -- Bin -> DPD (999 => 2457)                */
+/*   uint8_t  BIN2CHAR[4001];   -- Bin -> CHAR (999 => '\3' '9' '9' '9')   */
+/*   uint8_t  BIN2BCD8[4000];   -- Bin -> bytes (999 => 9 9 9 3)           */
+/*   uint16_t DPD2BCD[1024];    -- DPD -> BCD (0x3FF => 0x999)             */
+/*   uint16_t DPD2BIN[1024];    -- DPD -> BIN (0x3FF => 999)               */
+/*   uint32_t DPD2BINK[1024];   -- DPD -> BIN * 1000 (0x3FF => 999000)     */
+/*   uint32_t DPD2BINM[1024];   -- DPD -> BIN * 1E+6 (0x3FF => 999000000)  */
+/*   uint8_t  DPD2BCD8[4096];   -- DPD -> bytes (x3FF => 9 9 9 3)          */
+/*                                                                         */
 /* In all cases the result (10 bits or 12 bits, or binary) is right-aligned */
-/* in the table entry.                                                      */
-/*                                                                          */
-/* To use a table, its name, prefixed with DEC_, must be defined with a     */
-/* value of 1 before this header file is included.  For example:            */
-/*    #define DEC_BCD2DPD 1                                                 */
+/* in the table entry. BIN2CHAR entries are a single byte length (0 for    */
+/* value 0) followed by three digit characters; a trailing terminator is    */
+/* included to allow 4-char moves always.  BIN2BCD8 and DPD2BCD8 entries    */
+/* are similar with the three BCD8 digits followed by a one-byte length            */
+/* (again, length=0 for value 0).                                          */
+/*                                                                         */
+/* To use a table, its name, prefixed with DEC_, must be defined with a            */
+/* value of 1 before this header file is included.  For example:           */
+/*    #define DEC_BCD2DPD 1                                                */
+/* This mechanism allows software to only include tables that are needed.   */
 /* ------------------------------------------------------------------------ */
 
-#if DEC_BCD2DPD==1
+#if defined(DEC_BCD2DPD) && DEC_BCD2DPD==1 && !defined(DECBCD2DPD)
+#define DECBCD2DPD
+
+const uint16_t BCD2DPD[2458]={   0,    1,    2,    3,    4,    5,    6,    7,
+    8,   9,    0,    0,    0,    0,    0,    0,   16,   17,   18,   19,   20,
+   21,  22,   23,   24,   25,    0,    0,    0,    0,    0,    0,   32,   33,
+   34,  35,   36,   37,   38,   39,   40,   41,    0,    0,    0,    0,    0,
+    0,  48,   49,   50,   51,   52,   53,   54,   55,   56,   57,    0,    0,
+    0,   0,    0,    0,   64,   65,   66,   67,   68,   69,   70,   71,   72,
+   73,   0,    0,    0,    0,    0,    0,   80,   81,   82,   83,   84,   85,
+   86,  87,   88,   89,    0,    0,    0,    0,    0,    0,   96,   97,   98,
+   99, 100,  101,  102,  103,  104,  105,    0,    0,    0,    0,    0,    0,
+  112, 113,  114,  115,  116,  117,  118,  119,  120,  121,    0,    0,    0,
+    0,   0,    0,   10,   11,   42,   43,   74,   75,  106,  107,   78,   79,
+    0,   0,    0,    0,    0,    0,   26,   27,   58,   59,   90,   91,  122,
+  123,  94,   95,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0, 128,  129,  130,  131,  132,  133,  134,  135,  136,  137,    0,    0,
+    0,   0,    0,    0,  144,  145,  146,  147,  148,  149,  150,  151,  152,
+  153,   0,    0,    0,    0,    0,    0,  160,  161,  162,  163,  164,  165,
+  166, 167,  168,  169,    0,    0,    0,    0,    0,    0,  176,  177,  178,
+  179, 180,  181,  182,  183,  184,  185,    0,    0,    0,    0,    0,    0,
+  192, 193,  194,  195,  196,  197,  198,  199,  200,  201,    0,    0,    0,
+    0,   0,    0,  208,  209,  210,  211,  212,  213,  214,  215,  216,  217,
+    0,   0,    0,    0,    0,    0,  224,  225,  226,  227,  228,  229,  230,
+  231, 232,  233,    0,    0,    0,    0,    0,    0,  240,  241,  242,  243,
+  244, 245,  246,  247,  248,  249,    0,    0,    0,    0,    0,    0,  138,
+  139, 170,  171,  202,  203,  234,  235,  206,  207,    0,    0,    0,    0,
+    0,   0,  154,  155,  186,  187,  218,  219,  250,  251,  222,  223,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,  256,  257,  258,
+  259, 260,  261,  262,  263,  264,  265,    0,    0,    0,    0,    0,    0,
+  272, 273,  274,  275,  276,  277,  278,  279,  280,  281,    0,    0,    0,
+    0,   0,    0,  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,
+    0,   0,    0,    0,    0,    0,  304,  305,  306,  307,  308,  309,  310,
+  311, 312,  313,    0,    0,    0,    0,    0,    0,  320,  321,  322,  323,
+  324, 325,  326,  327,  328,  329,    0,    0,    0,    0,    0,    0,  336,
+  337, 338,  339,  340,  341,  342,  343,  344,  345,    0,    0,    0,    0,
+    0,   0,  352,  353,  354,  355,  356,  357,  358,  359,  360,  361,    0,
+    0,   0,    0,    0,    0,  368,  369,  370,  371,  372,  373,  374,  375,
+  376, 377,    0,    0,    0,    0,    0,    0,  266,  267,  298,  299,  330,
+  331, 362,  363,  334,  335,    0,    0,    0,    0,    0,    0,  282,  283,
+  314, 315,  346,  347,  378,  379,  350,  351,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,  384,  385,  386,  387,  388,  389,  390,
+  391, 392,  393,    0,    0,    0,    0,    0,    0,  400,  401,  402,  403,
+  404, 405,  406,  407,  408,  409,    0,    0,    0,    0,    0,    0,  416,
+  417, 418,  419,  420,  421,  422,  423,  424,  425,    0,    0,    0,    0,
+    0,   0,  432,  433,  434,  435,  436,  437,  438,  439,  440,  441,    0,
+    0,   0,    0,    0,    0,  448,  449,  450,  451,  452,  453,  454,  455,
+  456, 457,    0,    0,    0,    0,    0,    0,  464,  465,  466,  467,  468,
+  469, 470,  471,  472,  473,    0,    0,    0,    0,    0,    0,  480,  481,
+  482, 483,  484,  485,  486,  487,  488,  489,    0,    0,    0,    0,    0,
+    0, 496,  497,  498,  499,  500,  501,  502,  503,  504,  505,    0,    0,
+    0,   0,    0,    0,  394,  395,  426,  427,  458,  459,  490,  491,  462,
+  463,   0,    0,    0,    0,    0,    0,  410,  411,  442,  443,  474,  475,
+  506, 507,  478,  479,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,  512,  513,  514,  515,  516,  517,  518,  519,  520,  521,    0,
+    0,   0,    0,    0,    0,  528,  529,  530,  531,  532,  533,  534,  535,
+  536, 537,    0,    0,    0,    0,    0,    0,  544,  545,  546,  547,  548,
+  549, 550,  551,  552,  553,    0,    0,    0,    0,    0,    0,  560,  561,
+  562, 563,  564,  565,  566,  567,  568,  569,    0,    0,    0,    0,    0,
+    0, 576,  577,  578,  579,  580,  581,  582,  583,  584,  585,    0,    0,
+    0,   0,    0,    0,  592,  593,  594,  595,  596,  597,  598,  599,  600,
+  601,   0,    0,    0,    0,    0,    0,  608,  609,  610,  611,  612,  613,
+  614, 615,  616,  617,    0,    0,    0,    0,    0,    0,  624,  625,  626,
+  627, 628,  629,  630,  631,  632,  633,    0,    0,    0,    0,    0,    0,
+  522, 523,  554,  555,  586,  587,  618,  619,  590,  591,    0,    0,    0,
+    0,   0,    0,  538,  539,  570,  571,  602,  603,  634,  635,  606,  607,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  640,  641,
+  642, 643,  644,  645,  646,  647,  648,  649,    0,    0,    0,    0,    0,
+    0, 656,  657,  658,  659,  660,  661,  662,  663,  664,  665,    0,    0,
+    0,   0,    0,    0,  672,  673,  674,  675,  676,  677,  678,  679,  680,
+  681,   0,    0,    0,    0,    0,    0,  688,  689,  690,  691,  692,  693,
+  694, 695,  696,  697,    0,    0,    0,    0,    0,    0,  704,  705,  706,
+  707, 708,  709,  710,  711,  712,  713,    0,    0,    0,    0,    0,    0,
+  720, 721,  722,  723,  724,  725,  726,  727,  728,  729,    0,    0,    0,
+    0,   0,    0,  736,  737,  738,  739,  740,  741,  742,  743,  744,  745,
+    0,   0,    0,    0,    0,    0,  752,  753,  754,  755,  756,  757,  758,
+  759, 760,  761,    0,    0,    0,    0,    0,    0,  650,  651,  682,  683,
+  714, 715,  746,  747,  718,  719,    0,    0,    0,    0,    0,    0,  666,
+  667, 698,  699,  730,  731,  762,  763,  734,  735,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,  768,  769,  770,  771,  772,  773,
+  774, 775,  776,  777,    0,    0,    0,    0,    0,    0,  784,  785,  786,
+  787, 788,  789,  790,  791,  792,  793,    0,    0,    0,    0,    0,    0,
+  800, 801,  802,  803,  804,  805,  806,  807,  808,  809,    0,    0,    0,
+    0,   0,    0,  816,  817,  818,  819,  820,  821,  822,  823,  824,  825,
+    0,   0,    0,    0,    0,    0,  832,  833,  834,  835,  836,  837,  838,
+  839, 840,  841,    0,    0,    0,    0,    0,    0,  848,  849,  850,  851,
+  852, 853,  854,  855,  856,  857,    0,    0,    0,    0,    0,    0,  864,
+  865, 866,  867,  868,  869,  870,  871,  872,  873,    0,    0,    0,    0,
+    0,   0,  880,  881,  882,  883,  884,  885,  886,  887,  888,  889,    0,
+    0,   0,    0,    0,    0,  778,  779,  810,  811,  842,  843,  874,  875,
+  846, 847,    0,    0,    0,    0,    0,    0,  794,  795,  826,  827,  858,
+  859, 890,  891,  862,  863,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,  896,  897,  898,  899,  900,  901,  902,  903,  904,  905,
+    0,   0,    0,    0,    0,    0,  912,  913,  914,  915,  916,  917,  918,
+  919, 920,  921,    0,    0,    0,    0,    0,    0,  928,  929,  930,  931,
+  932, 933,  934,  935,  936,  937,    0,    0,    0,    0,    0,    0,  944,
+  945, 946,  947,  948,  949,  950,  951,  952,  953,    0,    0,    0,    0,
+    0,   0,  960,  961,  962,  963,  964,  965,  966,  967,  968,  969,    0,
+    0,   0,    0,    0,    0,  976,  977,  978,  979,  980,  981,  982,  983,
+  984, 985,    0,    0,    0,    0,    0,    0,  992,  993,  994,  995,  996,
+  997, 998,  999, 1000, 1001,    0,    0,    0,    0,    0,    0, 1008, 1009,
+ 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017,    0,   0,    0,    0,    0,
+    0, 906,  907,  938,  939,  970,  971, 1002, 1003,  974,  975,    0,    0,
+    0,   0,    0,    0,  922,  923,  954,  955,  986,  987, 1018, 1019,  990,
+  991,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   12,
+   13, 268,  269,  524,  525,  780,  781,   46,   47,    0,    0,    0,    0,
+    0,   0,   28,   29,  284,  285,  540,  541,  796,  797,   62,   63,    0,
+    0,   0,    0,    0,    0,   44,   45,  300,  301,  556,  557,  812,  813,
+  302, 303,    0,    0,    0,    0,    0,    0,   60,   61,  316,  317,  572,
+  573, 828,  829,  318,  319,    0,    0,    0,    0,    0,    0,   76,   77,
+  332, 333,  588,  589,  844,  845,  558,  559,    0,    0,    0,    0,    0,
+    0,  92,   93,  348,  349,  604,  605,  860,  861,  574,  575,    0,    0,
+    0,   0,    0,    0,  108,  109,  364,  365,  620,  621,  876,  877,  814,
+  815,   0,    0,    0,    0,    0,    0,  124,  125,  380,  381,  636,  637,
+  892, 893,  830,  831,    0,    0,    0,    0,    0,    0,   14,   15,  270,
+  271, 526,  527,  782,  783,  110,  111,    0,    0,    0,    0,    0,    0,
+   30,  31,  286,  287,  542,  543,  798,  799,  126,  127,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   0,    0,    0,    0,    0,    0,    0,  140,  141,  396,  397,  652,
+  653, 908,  909,  174,  175,    0,    0,    0,    0,    0,    0,  156,  157,
+  412, 413,  668,  669,  924,  925,  190,  191,    0,    0,    0,    0,    0,
+    0, 172,  173,  428,  429,  684,  685,  940,  941,  430,  431,    0,    0,
+    0,   0,    0,    0,  188,  189,  444,  445,  700,  701,  956,  957,  446,
+  447,   0,    0,    0,    0,    0,    0,  204,  205,  460,  461,  716,  717,
+  972, 973,  686,  687,    0,    0,    0,    0,    0,    0,  220,  221,  476,
+  477, 732,  733,  988,  989,  702,  703,    0,    0,    0,    0,    0,    0,
+  236, 237,  492,  493,  748,  749, 1004, 1005,  942,  943,    0,    0,    0,
+    0,   0,    0,  252,  253,  508,  509,  764,  765, 1020, 1021,  958,  959,
+    0,   0,    0,    0,    0,    0,  142,  143,  398,  399,  654,  655,  910,
+  911, 238,  239,    0,    0,    0,    0,    0,    0,  158,  159,  414,  415,
+  670, 671,  926,  927,  254,  255};
+#endif
+
+#if defined(DEC_DPD2BCD) && DEC_DPD2BCD==1 && !defined(DECDPD2BCD)
+#define DECDPD2BCD
+
+const uint16_t DPD2BCD[1024]={   0,    1,    2,    3,    4,    5,    6,    7,
+    8,   9,  128,  129, 2048, 2049, 2176, 2177,   16,   17,   18,   19,   20,
+   21,  22,   23,   24,   25,  144,  145, 2064, 2065, 2192, 2193,   32,   33,
+   34,  35,   36,   37,   38,   39,   40,   41,  130,  131, 2080, 2081, 2056,
+ 2057,  48,   49,   50,   51,   52,   53,   54,   55,   56,   57,  146,  147,
+ 2096, 2097, 2072, 2073,   64,  65,   66,   67,   68,   69,   70,   71,   72,
+   73, 132,  133, 2112, 2113,  136,  137,   80,   81,   82,   83,   84,   85,
+   86,  87,   88,   89,  148,  149, 2128, 2129,  152,  153,   96,   97,   98,
+   99, 100,  101,  102,  103,  104,  105,  134,  135, 2144, 2145, 2184, 2185,
+  112, 113,  114,  115,  116,  117,  118,  119,  120,  121,  150,  151, 2160,
+ 2161, 2200, 2201,  256,  257, 258,  259,  260,  261,  262,  263,  264,  265,
+  384, 385, 2304, 2305, 2432, 2433,  272,  273,  274,  275,  276,  277,  278,
+  279, 280,  281,  400,  401, 2320, 2321, 2448, 2449,  288,  289,  290,  291,
+  292, 293,  294,  295,  296,  297,  386,  387, 2336, 2337, 2312, 2313,  304,
+  305, 306,  307,  308,  309,  310,  311,  312,  313,  402,  403, 2352, 2353,
+ 2328, 2329,  320,  321,  322, 323,  324,  325,  326,  327,  328,  329,  388,
+  389, 2368, 2369,  392,  393, 336,  337,  338,  339,  340,  341,  342,  343,
+  344, 345,  404,  405, 2384, 2385,  408,  409,  352,  353,  354,  355,  356,
+  357, 358,  359,  360,  361,  390,  391, 2400, 2401, 2440, 2441,  368,  369,
+  370, 371,  372,  373,  374,  375,  376,  377,  406,  407, 2416, 2417, 2456,
+ 2457, 512,  513,  514,  515,  516,  517,  518,  519,  520,  521,  640,  641,
+ 2050, 2051, 2178, 2179,  528, 529,  530,  531,  532,  533,  534,  535,  536,
+  537, 656,  657, 2066, 2067, 2194, 2195,  544,  545,  546,  547,  548,  549,
+  550, 551,  552,  553,  642,  643, 2082, 2083, 2088, 2089,  560,  561,  562,
+  563, 564,  565,  566,  567,  568,  569,  658,  659, 2098, 2099, 2104, 2105,
+  576, 577,  578,  579,  580,  581,  582,  583,  584,  585,  644,  645, 2114,
+ 2115, 648,  649,  592,  593,  594,  595,  596,  597,  598,  599,  600,  601,
+  660, 661, 2130, 2131,  664,  665,  608,  609,  610,  611,  612,  613,  614,
+  615, 616,  617,  646,  647, 2146, 2147, 2184, 2185,  624,  625,  626,  627,
+  628, 629,  630,  631,  632,  633,  662,  663, 2162, 2163, 2200, 2201,  768,
+  769, 770,  771,  772,  773,  774,  775,  776,  777,  896,  897, 2306, 2307,
+ 2434, 2435,  784,  785,  786, 787,  788,  789,  790,  791,  792,  793,  912,
+  913, 2322, 2323, 2450, 2451, 800,  801,  802,  803,  804,  805,  806,  807,
+  808, 809,  898,  899, 2338, 2339, 2344, 2345,  816,  817,  818,  819,  820,
+  821, 822,  823,  824,  825,  914,  915, 2354, 2355, 2360, 2361,  832,  833,
+  834, 835,  836,  837,  838,  839,  840,  841,  900,  901, 2370, 2371,  904,
+  905, 848,  849,  850,  851,  852,  853,  854,  855,  856,  857,  916,  917,
+ 2386, 2387,  920,  921,  864, 865,  866,  867,  868,  869,  870,  871,  872,
+  873, 902,  903, 2402, 2403, 2440, 2441,  880,  881,  882,  883,  884,  885,
+  886, 887,  888,  889,  918,  919, 2418, 2419, 2456, 2457, 1024, 1025, 1026,
+ 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1152, 1153, 2052, 2053, 2180, 2181,
+ 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1168, 1169, 2068,
+ 2069, 2196, 2197, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065,
+ 1154, 1155, 2084, 2085, 2120, 2121, 1072, 1073, 1074, 1075, 1076, 1077, 1078,
+ 1079, 1080, 1081, 1170, 1171, 2100, 2101, 2136, 2137, 1088, 1089, 1090, 1091,
+ 1092, 1093, 1094, 1095, 1096, 1097, 1156, 1157, 2116, 2117, 1160, 1161, 1104,
+ 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1172, 1173, 2132, 2133,
+ 1176, 1177, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1158,
+ 1159, 2148, 2149, 2184, 2185, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143,
+ 1144, 1145, 1174, 1175, 2164, 2165, 2200, 2201, 1280, 1281, 1282, 1283, 1284,
+ 1285, 1286, 1287, 1288, 1289, 1408, 1409, 2308, 2309, 2436, 2437, 1296, 1297,
+ 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1424, 1425, 2324, 2325, 2452,
+ 2453, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1410, 1411,
+ 2340, 2341, 2376, 2377, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336,
+ 1337, 1426, 1427, 2356, 2357, 2392, 2393, 1344, 1345, 1346, 1347, 1348, 1349,
+ 1350, 1351, 1352, 1353, 1412, 1413, 2372, 2373, 1416, 1417, 1360, 1361, 1362,
+ 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1428, 1429, 2388, 2389, 1432, 1433,
+ 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1414, 1415, 2404,
+ 2405, 2440, 2441, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401,
+ 1430, 1431, 2420, 2421, 2456, 2457, 1536, 1537, 1538, 1539, 1540, 1541, 1542,
+ 1543, 1544, 1545, 1664, 1665, 2054, 2055, 2182, 2183, 1552, 1553, 1554, 1555,
+ 1556, 1557, 1558, 1559, 1560, 1561, 1680, 1681, 2070, 2071, 2198, 2199, 1568,
+ 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1666, 1667, 2086, 2087,
+ 2152, 2153, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1682,
+ 1683, 2102, 2103, 2168, 2169, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607,
+ 1608, 1609, 1668, 1669, 2118, 2119, 1672, 1673, 1616, 1617, 1618, 1619, 1620,
+ 1621, 1622, 1623, 1624, 1625, 1684, 1685, 2134, 2135, 1688, 1689, 1632, 1633,
+ 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1670, 1671, 2150, 2151, 2184,
+ 2185, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1686, 1687,
+ 2166, 2167, 2200, 2201, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800,
+ 1801, 1920, 1921, 2310, 2311, 2438, 2439, 1808, 1809, 1810, 1811, 1812, 1813,
+ 1814, 1815, 1816, 1817, 1936, 1937, 2326, 2327, 2454, 2455, 1824, 1825, 1826,
+ 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1922, 1923, 2342, 2343, 2408, 2409,
+ 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1938, 1939, 2358,
+ 2359, 2424, 2425, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865,
+ 1924, 1925, 2374, 2375, 1928, 1929, 1872, 1873, 1874, 1875, 1876, 1877, 1878,
+ 1879, 1880, 1881, 1940, 1941, 2390, 2391, 1944, 1945, 1888, 1889, 1890, 1891,
+ 1892, 1893, 1894, 1895, 1896, 1897, 1926, 1927, 2406, 2407, 2440, 2441, 1904,
+ 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1942, 1943, 2422, 2423,
+ 2456, 2457};
+#endif
+
+#if defined(DEC_BIN2DPD) && DEC_BIN2DPD==1 && !defined(DECBIN2DPD)
+#define DECBIN2DPD
+
+const uint16_t BIN2DPD[1000]={   0,    1,    2,    3,    4,    5,    6,    7,
+    8,   9,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,   32,
+   33,  34,   35,   36,   37,   38,   39,   40,   41,   48,   49,   50,   51,
+   52,  53,   54,   55,   56,   57,   64,   65,   66,   67,   68,   69,   70,
+   71,  72,   73,   80,   81,   82,   83,   84,   85,   86,   87,   88,   89,
+   96,  97,   98,   99,  100,  101,  102,  103,  104,  105,  112,  113,  114,
+  115, 116,  117,  118,  119,  120,  121,   10,   11,   42,   43,   74,   75,
+  106, 107,   78,   79,   26,   27,   58,   59,   90,   91,  122,  123,   94,
+   95, 128,  129,  130,  131,  132,  133,  134,  135,  136,  137,  144,  145,
+  146, 147,  148,  149,  150,  151,  152,  153,  160,  161,  162,  163,  164,
+  165, 166,  167,  168,  169,  176,  177,  178,  179,  180,  181,  182,  183,
+  184, 185,  192,  193,  194,  195,  196,  197,  198,  199,  200,  201,  208,
+  209, 210,  211,  212,  213,  214,  215,  216,  217,  224,  225,  226,  227,
+  228, 229,  230,  231,  232,  233,  240,  241,  242,  243,  244,  245,  246,
+  247, 248,  249,  138,  139,  170,  171,  202,  203,  234,  235,  206,  207,
+  154, 155,  186,  187,  218,  219,  250,  251,  222,  223,  256,  257,  258,
+  259, 260,  261,  262,  263,  264,  265,  272,  273,  274,  275,  276,  277,
+  278, 279,  280,  281,  288,  289,  290,  291,  292,  293,  294,  295,  296,
+  297, 304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  320,  321,
+  322, 323,  324,  325,  326,  327,  328,  329,  336,  337,  338,  339,  340,
+  341, 342,  343,  344,  345,  352,  353,  354,  355,  356,  357,  358,  359,
+  360, 361,  368,  369,  370,  371,  372,  373,  374,  375,  376,  377,  266,
+  267, 298,  299,  330,  331,  362,  363,  334,  335,  282,  283,  314,  315,
+  346, 347,  378,  379,  350,  351,  384,  385,  386,  387,  388,  389,  390,
+  391, 392,  393,  400,  401,  402,  403,  404,  405,  406,  407,  408,  409,
+  416, 417,  418,  419,  420,  421,  422,  423,  424,  425,  432,  433,  434,
+  435, 436,  437,  438,  439,  440,  441,  448,  449,  450,  451,  452,  453,
+  454, 455,  456,  457,  464,  465,  466,  467,  468,  469,  470,  471,  472,
+  473, 480,  481,  482,  483,  484,  485,  486,  487,  488,  489,  496,  497,
+  498, 499,  500,  501,  502,  503,  504,  505,  394,  395,  426,  427,  458,
+  459, 490,  491,  462,  463,  410,  411,  442,  443,  474,  475,  506,  507,
+  478, 479,  512,  513,  514,  515,  516,  517,  518,  519,  520,  521,  528,
+  529, 530,  531,  532,  533,  534,  535,  536,  537,  544,  545,  546,  547,
+  548, 549,  550,  551,  552,  553,  560,  561,  562,  563,  564,  565,  566,
+  567, 568,  569,  576,  577,  578,  579,  580,  581,  582,  583,  584,  585,
+  592, 593,  594,  595,  596,  597,  598,  599,  600,  601,  608,  609,  610,
+  611, 612,  613,  614,  615,  616,  617,  624,  625,  626,  627,  628,  629,
+  630, 631,  632,  633,  522,  523,  554,  555,  586,  587,  618,  619,  590,
+  591, 538,  539,  570,  571,  602,  603,  634,  635,  606,  607,  640,  641,
+  642, 643,  644,  645,  646,  647,  648,  649,  656,  657,  658,  659,  660,
+  661, 662,  663,  664,  665,  672,  673,  674,  675,  676,  677,  678,  679,
+  680, 681,  688,  689,  690,  691,  692,  693,  694,  695,  696,  697,  704,
+  705, 706,  707,  708,  709,  710,  711,  712,  713,  720,  721,  722,  723,
+  724, 725,  726,  727,  728,  729,  736,  737,  738,  739,  740,  741,  742,
+  743, 744,  745,  752,  753,  754,  755,  756,  757,  758,  759,  760,  761,
+  650, 651,  682,  683,  714,  715,  746,  747,  718,  719,  666,  667,  698,
+  699, 730,  731,  762,  763,  734,  735,  768,  769,  770,  771,  772,  773,
+  774, 775,  776,  777,  784,  785,  786,  787,  788,  789,  790,  791,  792,
+  793, 800,  801,  802,  803,  804,  805,  806,  807,  808,  809,  816,  817,
+  818, 819,  820,  821,  822,  823,  824,  825,  832,  833,  834,  835,  836,
+  837, 838,  839,  840,  841,  848,  849,  850,  851,  852,  853,  854,  855,
+  856, 857,  864,  865,  866,  867,  868,  869,  870,  871,  872,  873,  880,
+  881, 882,  883,  884,  885,  886,  887,  888,  889,  778,  779,  810,  811,
+  842, 843,  874,  875,  846,  847,  794,  795,  826,  827,  858,  859,  890,
+  891, 862,  863,  896,  897,  898,  899,  900,  901,  902,  903,  904,  905,
+  912, 913,  914,  915,  916,  917,  918,  919,  920,  921,  928,  929,  930,
+  931, 932,  933,  934,  935,  936,  937,  944,  945,  946,  947,  948,  949,
+  950, 951,  952,  953,  960,  961,  962,  963,  964,  965,  966,  967,  968,
+  969, 976,  977,  978,  979,  980,  981,  982,  983,  984,  985,  992,  993,
+  994, 995,  996,  997,  998,  999, 1000, 1001, 1008, 1009, 1010, 1011, 1012,
+ 1013, 1014, 1015, 1016, 1017, 906,  907,  938,  939,  970,  971, 1002, 1003,
+  974, 975,  922,  923,  954,  955,  986,  987, 1018, 1019,  990,  991,   12,
+   13, 268,  269,  524,  525,  780,  781,   46,   47,   28,   29,  284,  285,
+  540, 541,  796,  797,   62,   63,   44,   45,  300,  301,  556,  557,  812,
+  813, 302,  303,   60,   61,  316,  317,  572,  573,  828,  829,  318,  319,
+   76,  77,  332,  333,  588,  589,  844,  845,  558,  559,   92,   93,  348,
+  349, 604,  605,  860,  861,  574,  575,  108,  109,  364,  365,  620,  621,
+  876, 877,  814,  815,  124,  125,  380,  381,  636,  637,  892,  893,  830,
+  831,  14,   15,  270,  271,  526,  527,  782,  783,  110,  111,   30,   31,
+  286, 287,  542,  543,  798,  799,  126,  127,  140,  141,  396,  397,  652,
+  653, 908,  909,  174,  175,  156,  157,  412,  413,  668,  669,  924,  925,
+  190, 191,  172,  173,  428,  429,  684,  685,  940,  941,  430,  431,  188,
+  189, 444,  445,  700,  701,  956,  957,  446,  447,  204,  205,  460,  461,
+  716, 717,  972,  973,  686,  687,  220,  221,  476,  477,  732,  733,  988,
+  989, 702,  703,  236,  237,  492,  493,  748,  749, 1004, 1005,  942,  943,
+  252, 253,  508,  509,  764,  765, 1020, 1021,  958,  959,  142,  143,  398,
+  399, 654,  655,  910,  911,  238,  239,  158,  159,  414,  415,  670,  671,
+  926, 927,  254,  255};
+#endif
+
+#if defined(DEC_DPD2BIN) && DEC_DPD2BIN==1 && !defined(DECDPD2BIN)
+#define DECDPD2BIN
+
+const uint16_t DPD2BIN[1024]={   0,    1,    2,    3,    4,    5,    6,    7,
+    8,   9,   80,   81,  800,  801,  880,  881,   10,   11,   12,   13,   14,
+   15,  16,   17,   18,   19,   90,   91,  810,  811,  890,  891,   20,   21,
+   22,  23,   24,   25,   26,   27,   28,   29,   82,   83,  820,  821,  808,
+  809,  30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   92,   93,
+  830, 831,  818,  819,   40,   41,   42,   43,   44,   45,   46,   47,   48,
+   49,  84,   85,  840,  841,   88,   89,   50,   51,   52,   53,   54,   55,
+   56,  57,   58,   59,   94,   95,  850,  851,   98,   99,   60,   61,   62,
+   63,  64,   65,   66,   67,   68,   69,   86,   87,  860,  861,  888,  889,
+   70,  71,   72,   73,   74,   75,   76,   77,   78,   79,   96,   97,  870,
+  871, 898,  899,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,
+  180, 181,  900,  901,  980,  981,  110,  111,  112,  113,  114,  115,  116,
+  117, 118,  119,  190,  191,  910,  911,  990,  991,  120,  121,  122,  123,
+  124, 125,  126,  127,  128,  129,  182,  183,  920,  921,  908,  909,  130,
+  131, 132,  133,  134,  135,  136,  137,  138,  139,  192,  193,  930,  931,
+  918, 919,  140,  141,  142,  143,  144,  145,  146,  147,  148,  149,  184,
+  185, 940,  941,  188,  189,  150,  151,  152,  153,  154,  155,  156,  157,
+  158, 159,  194,  195,  950,  951,  198,  199,  160,  161,  162,  163,  164,
+  165, 166,  167,  168,  169,  186,  187,  960,  961,  988,  989,  170,  171,
+  172, 173,  174,  175,  176,  177,  178,  179,  196,  197,  970,  971,  998,
+  999, 200,  201,  202,  203,  204,  205,  206,  207,  208,  209,  280,  281,
+  802, 803,  882,  883,  210,  211,  212,  213,  214,  215,  216,  217,  218,
+  219, 290,  291,  812,  813,  892,  893,  220,  221,  222,  223,  224,  225,
+  226, 227,  228,  229,  282,  283,  822,  823,  828,  829,  230,  231,  232,
+  233, 234,  235,  236,  237,  238,  239,  292,  293,  832,  833,  838,  839,
+  240, 241,  242,  243,  244,  245,  246,  247,  248,  249,  284,  285,  842,
+  843, 288,  289,  250,  251,  252,  253,  254,  255,  256,  257,  258,  259,
+  294, 295,  852,  853,  298,  299,  260,  261,  262,  263,  264,  265,  266,
+  267, 268,  269,  286,  287,  862,  863,  888,  889,  270,  271,  272,  273,
+  274, 275,  276,  277,  278,  279,  296,  297,  872,  873,  898,  899,  300,
+  301, 302,  303,  304,  305,  306,  307,  308,  309,  380,  381,  902,  903,
+  982, 983,  310,  311,  312,  313,  314,  315,  316,  317,  318,  319,  390,
+  391, 912,  913,  992,  993,  320,  321,  322,  323,  324,  325,  326,  327,
+  328, 329,  382,  383,  922,  923,  928,  929,  330,  331,  332,  333,  334,
+  335, 336,  337,  338,  339,  392,  393,  932,  933,  938,  939,  340,  341,
+  342, 343,  344,  345,  346,  347,  348,  349,  384,  385,  942,  943,  388,
+  389, 350,  351,  352,  353,  354,  355,  356,  357,  358,  359,  394,  395,
+  952, 953,  398,  399,  360,  361,  362,  363,  364,  365,  366,  367,  368,
+  369, 386,  387,  962,  963,  988,  989,  370,  371,  372,  373,  374,  375,
+  376, 377,  378,  379,  396,  397,  972,  973,  998,  999,  400,  401,  402,
+  403, 404,  405,  406,  407,  408,  409,  480,  481,  804,  805,  884,  885,
+  410, 411,  412,  413,  414,  415,  416,  417,  418,  419,  490,  491,  814,
+  815, 894,  895,  420,  421,  422,  423,  424,  425,  426,  427,  428,  429,
+  482, 483,  824,  825,  848,  849,  430,  431,  432,  433,  434,  435,  436,
+  437, 438,  439,  492,  493,  834,  835,  858,  859,  440,  441,  442,  443,
+  444, 445,  446,  447,  448,  449,  484,  485,  844,  845,  488,  489,  450,
+  451, 452,  453,  454,  455,  456,  457,  458,  459,  494,  495,  854,  855,
+  498, 499,  460,  461,  462,  463,  464,  465,  466,  467,  468,  469,  486,
+  487, 864,  865,  888,  889,  470,  471,  472,  473,  474,  475,  476,  477,
+  478, 479,  496,  497,  874,  875,  898,  899,  500,  501,  502,  503,  504,
+  505, 506,  507,  508,  509,  580,  581,  904,  905,  984,  985,  510,  511,
+  512, 513,  514,  515,  516,  517,  518,  519,  590,  591,  914,  915,  994,
+  995, 520,  521,  522,  523,  524,  525,  526,  527,  528,  529,  582,  583,
+  924, 925,  948,  949,  530,  531,  532,  533,  534,  535,  536,  537,  538,
+  539, 592,  593,  934,  935,  958,  959,  540,  541,  542,  543,  544,  545,
+  546, 547,  548,  549,  584,  585,  944,  945,  588,  589,  550,  551,  552,
+  553, 554,  555,  556,  557,  558,  559,  594,  595,  954,  955,  598,  599,
+  560, 561,  562,  563,  564,  565,  566,  567,  568,  569,  586,  587,  964,
+  965, 988,  989,  570,  571,  572,  573,  574,  575,  576,  577,  578,  579,
+  596, 597,  974,  975,  998,  999,  600,  601,  602,  603,  604,  605,  606,
+  607, 608,  609,  680,  681,  806,  807,  886,  887,  610,  611,  612,  613,
+  614, 615,  616,  617,  618,  619,  690,  691,  816,  817,  896,  897,  620,
+  621, 622,  623,  624,  625,  626,  627,  628,  629,  682,  683,  826,  827,
+  868, 869,  630,  631,  632,  633,  634,  635,  636,  637,  638,  639,  692,
+  693, 836,  837,  878,  879,  640,  641,  642,  643,  644,  645,  646,  647,
+  648, 649,  684,  685,  846,  847,  688,  689,  650,  651,  652,  653,  654,
+  655, 656,  657,  658,  659,  694,  695,  856,  857,  698,  699,  660,  661,
+  662, 663,  664,  665,  666,  667,  668,  669,  686,  687,  866,  867,  888,
+  889, 670,  671,  672,  673,  674,  675,  676,  677,  678,  679,  696,  697,
+  876, 877,  898,  899,  700,  701,  702,  703,  704,  705,  706,  707,  708,
+  709, 780,  781,  906,  907,  986,  987,  710,  711,  712,  713,  714,  715,
+  716, 717,  718,  719,  790,  791,  916,  917,  996,  997,  720,  721,  722,
+  723, 724,  725,  726,  727,  728,  729,  782,  783,  926,  927,  968,  969,
+  730, 731,  732,  733,  734,  735,  736,  737,  738,  739,  792,  793,  936,
+  937, 978,  979,  740,  741,  742,  743,  744,  745,  746,  747,  748,  749,
+  784, 785,  946,  947,  788,  789,  750,  751,  752,  753,  754,  755,  756,
+  757, 758,  759,  794,  795,  956,  957,  798,  799,  760,  761,  762,  763,
+  764, 765,  766,  767,  768,  769,  786,  787,  966,  967,  988,  989,  770,
+  771, 772,  773,  774,  775,  776,  777,  778,  779,  796,  797,  976,  977,
+  998, 999};
+#endif
+
+#if defined(DEC_DPD2BINK) && DEC_DPD2BINK==1 && !defined(DECDPD2BINK)
+#define DECDPD2BINK
 
-const uint16_t BCD2DPD[2458] = { 0, 1, 2, 3, 4, 5, 6, 7,
-  8, 9, 0, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20,
-  21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 32, 33,
-  34, 35, 36, 37, 38, 39, 40, 41, 0, 0, 0, 0, 0,
-  0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 0,
-  0, 0, 0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72,
-  73, 0, 0, 0, 0, 0, 0, 80, 81, 82, 83, 84, 85,
-  86, 87, 88, 89, 0, 0, 0, 0, 0, 0, 96, 97, 98,
-  99, 100, 101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 0,
-  112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 0, 0, 0,
-  0, 0, 0, 10, 11, 42, 43, 74, 75, 106, 107, 78, 79,
-  0, 0, 0, 0, 0, 0, 26, 27, 58, 59, 90, 91, 122,
-  123, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 42, 43, 74,
-  75, 106, 107, 78, 79, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 0, 0,
-  0, 0, 0, 0, 144, 145, 146, 147, 148, 149, 150, 151, 152,
-  153, 0, 0, 0, 0, 0, 0, 160, 161, 162, 163, 164, 165,
-  166, 167, 168, 169, 0, 0, 0, 0, 0, 0, 176, 177, 178,
-  179, 180, 181, 182, 183, 184, 185, 0, 0, 0, 0, 0, 0,
-  192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 0, 0, 0,
-  0, 0, 0, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
-  0, 0, 0, 0, 0, 0, 224, 225, 226, 227, 228, 229, 230,
-  231, 232, 233, 0, 0, 0, 0, 0, 0, 240, 241, 242, 243,
-  244, 245, 246, 247, 248, 249, 0, 0, 0, 0, 0, 0, 138,
-  139, 170, 171, 202, 203, 234, 235, 206, 207, 0, 0, 0, 0,
-  0, 0, 154, 155, 186, 187, 218, 219, 250, 251, 222, 223, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 138, 139, 170, 171, 202, 203, 234, 235, 206,
-  207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 257, 258,
-  259, 260, 261, 262, 263, 264, 265, 0, 0, 0, 0, 0, 0,
-  272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 0, 0, 0,
-  0, 0, 0, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
-  0, 0, 0, 0, 0, 0, 304, 305, 306, 307, 308, 309, 310,
-  311, 312, 313, 0, 0, 0, 0, 0, 0, 320, 321, 322, 323,
-  324, 325, 326, 327, 328, 329, 0, 0, 0, 0, 0, 0, 336,
-  337, 338, 339, 340, 341, 342, 343, 344, 345, 0, 0, 0, 0,
-  0, 0, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 0,
-  0, 0, 0, 0, 0, 368, 369, 370, 371, 372, 373, 374, 375,
-  376, 377, 0, 0, 0, 0, 0, 0, 266, 267, 298, 299, 330,
-  331, 362, 363, 334, 335, 0, 0, 0, 0, 0, 0, 282, 283,
-  314, 315, 346, 347, 378, 379, 350, 351, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  266, 267, 298, 299, 330, 331, 362, 363, 334, 335, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 384, 385, 386, 387, 388, 389, 390,
-  391, 392, 393, 0, 0, 0, 0, 0, 0, 400, 401, 402, 403,
-  404, 405, 406, 407, 408, 409, 0, 0, 0, 0, 0, 0, 416,
-  417, 418, 419, 420, 421, 422, 423, 424, 425, 0, 0, 0, 0,
-  0, 0, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 0,
-  0, 0, 0, 0, 0, 448, 449, 450, 451, 452, 453, 454, 455,
-  456, 457, 0, 0, 0, 0, 0, 0, 464, 465, 466, 467, 468,
-  469, 470, 471, 472, 473, 0, 0, 0, 0, 0, 0, 480, 481,
-  482, 483, 484, 485, 486, 487, 488, 489, 0, 0, 0, 0, 0,
-  0, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 0, 0,
-  0, 0, 0, 0, 394, 395, 426, 427, 458, 459, 490, 491, 462,
-  463, 0, 0, 0, 0, 0, 0, 410, 411, 442, 443, 474, 475,
-  506, 507, 478, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 394, 395, 426, 427,
-  458, 459, 490, 491, 462, 463, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 0,
-  0, 0, 0, 0, 0, 528, 529, 530, 531, 532, 533, 534, 535,
-  536, 537, 0, 0, 0, 0, 0, 0, 544, 545, 546, 547, 548,
-  549, 550, 551, 552, 553, 0, 0, 0, 0, 0, 0, 560, 561,
-  562, 563, 564, 565, 566, 567, 568, 569, 0, 0, 0, 0, 0,
-  0, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 0, 0,
-  0, 0, 0, 0, 592, 593, 594, 595, 596, 597, 598, 599, 600,
-  601, 0, 0, 0, 0, 0, 0, 608, 609, 610, 611, 612, 613,
-  614, 615, 616, 617, 0, 0, 0, 0, 0, 0, 624, 625, 626,
-  627, 628, 629, 630, 631, 632, 633, 0, 0, 0, 0, 0, 0,
-  522, 523, 554, 555, 586, 587, 618, 619, 590, 591, 0, 0, 0,
-  0, 0, 0, 538, 539, 570, 571, 602, 603, 634, 635, 606, 607,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 522, 523, 554, 555, 586, 587, 618, 619,
-  590, 591, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 640, 641,
-  642, 643, 644, 645, 646, 647, 648, 649, 0, 0, 0, 0, 0,
-  0, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 0, 0,
-  0, 0, 0, 0, 672, 673, 674, 675, 676, 677, 678, 679, 680,
-  681, 0, 0, 0, 0, 0, 0, 688, 689, 690, 691, 692, 693,
-  694, 695, 696, 697, 0, 0, 0, 0, 0, 0, 704, 705, 706,
-  707, 708, 709, 710, 711, 712, 713, 0, 0, 0, 0, 0, 0,
-  720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 0, 0, 0,
-  0, 0, 0, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745,
-  0, 0, 0, 0, 0, 0, 752, 753, 754, 755, 756, 757, 758,
-  759, 760, 761, 0, 0, 0, 0, 0, 0, 650, 651, 682, 683,
-  714, 715, 746, 747, 718, 719, 0, 0, 0, 0, 0, 0, 666,
-  667, 698, 699, 730, 731, 762, 763, 734, 735, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 650, 651, 682, 683, 714, 715, 746, 747, 718, 719, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 768, 769, 770, 771, 772, 773,
-  774, 775, 776, 777, 0, 0, 0, 0, 0, 0, 784, 785, 786,
-  787, 788, 789, 790, 791, 792, 793, 0, 0, 0, 0, 0, 0,
-  800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 0, 0, 0,
-  0, 0, 0, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825,
-  0, 0, 0, 0, 0, 0, 832, 833, 834, 835, 836, 837, 838,
-  839, 840, 841, 0, 0, 0, 0, 0, 0, 848, 849, 850, 851,
-  852, 853, 854, 855, 856, 857, 0, 0, 0, 0, 0, 0, 864,
-  865, 866, 867, 868, 869, 870, 871, 872, 873, 0, 0, 0, 0,
-  0, 0, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 0,
-  0, 0, 0, 0, 0, 778, 779, 810, 811, 842, 843, 874, 875,
-  846, 847, 0, 0, 0, 0, 0, 0, 794, 795, 826, 827, 858,
-  859, 890, 891, 862, 863, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 778, 779, 810,
-  811, 842, 843, 874, 875, 846, 847, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905,
-  0, 0, 0, 0, 0, 0, 912, 913, 914, 915, 916, 917, 918,
-  919, 920, 921, 0, 0, 0, 0, 0, 0, 928, 929, 930, 931,
-  932, 933, 934, 935, 936, 937, 0, 0, 0, 0, 0, 0, 944,
-  945, 946, 947, 948, 949, 950, 951, 952, 953, 0, 0, 0, 0,
-  0, 0, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 0,
-  0, 0, 0, 0, 0, 976, 977, 978, 979, 980, 981, 982, 983,
-  984, 985, 0, 0, 0, 0, 0, 0, 992, 993, 994, 995, 996,
-  997, 998, 999, 1000, 1001, 0, 0, 0, 0, 0, 0, 1008, 1009,
-  1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 0, 0, 0, 0, 0,
-  0, 906, 907, 938, 939, 970, 971, 1002, 1003, 974, 975, 0, 0,
-  0, 0, 0, 0, 922, 923, 954, 955, 986, 987, 1018, 1019, 990,
-  991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 906, 907, 938, 939, 970, 971, 1002,
-  1003, 974, 975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,
-  13, 268, 269, 524, 525, 780, 781, 46, 47, 0, 0, 0, 0,
-  0, 0, 28, 29, 284, 285, 540, 541, 796, 797, 62, 63, 0,
-  0, 0, 0, 0, 0, 44, 45, 300, 301, 556, 557, 812, 813,
-  302, 303, 0, 0, 0, 0, 0, 0, 60, 61, 316, 317, 572,
-  573, 828, 829, 318, 319, 0, 0, 0, 0, 0, 0, 76, 77,
-  332, 333, 588, 589, 844, 845, 558, 559, 0, 0, 0, 0, 0,
-  0, 92, 93, 348, 349, 604, 605, 860, 861, 574, 575, 0, 0,
-  0, 0, 0, 0, 108, 109, 364, 365, 620, 621, 876, 877, 814,
-  815, 0, 0, 0, 0, 0, 0, 124, 125, 380, 381, 636, 637,
-  892, 893, 830, 831, 0, 0, 0, 0, 0, 0, 14, 15, 270,
-  271, 526, 527, 782, 783, 110, 111, 0, 0, 0, 0, 0, 0,
-  30, 31, 286, 287, 542, 543, 798, 799, 126, 127, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 14, 15, 270, 271, 526, 527, 782, 783, 110, 111, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 140, 141, 396, 397, 652,
-  653, 908, 909, 174, 175, 0, 0, 0, 0, 0, 0, 156, 157,
-  412, 413, 668, 669, 924, 925, 190, 191, 0, 0, 0, 0, 0,
-  0, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 0, 0,
-  0, 0, 0, 0, 188, 189, 444, 445, 700, 701, 956, 957, 446,
-  447, 0, 0, 0, 0, 0, 0, 204, 205, 460, 461, 716, 717,
-  972, 973, 686, 687, 0, 0, 0, 0, 0, 0, 220, 221, 476,
-  477, 732, 733, 988, 989, 702, 703, 0, 0, 0, 0, 0, 0,
-  236, 237, 492, 493, 748, 749, 1004, 1005, 942, 943, 0, 0, 0,
-  0, 0, 0, 252, 253, 508, 509, 764, 765, 1020, 1021, 958, 959,
-  0, 0, 0, 0, 0, 0, 142, 143, 398, 399, 654, 655, 910,
-  911, 238, 239, 0, 0, 0, 0, 0, 0, 158, 159, 414, 415,
-  670, 671, 926, 927, 254, 255
-};
+const uint32_t DPD2BINK[1024]={              0,   1000,   2000,   3000,   4000,   5000,
+   6000,   7000,   8000,   9000,  80000,  81000, 800000, 801000, 880000, 881000,
+  10000,  11000,  12000,  13000,  14000,  15000,  16000,  17000,  18000,  19000,
+  90000,  91000, 810000, 811000, 890000, 891000,  20000,  21000,  22000,  23000,
+  24000,  25000,  26000,  27000,  28000,  29000,  82000,  83000, 820000, 821000,
+ 808000, 809000,  30000,  31000,  32000,  33000,  34000,  35000,  36000,  37000,
+  38000,  39000,  92000,  93000, 830000, 831000, 818000, 819000,  40000,  41000,
+  42000,  43000,  44000,  45000,  46000,  47000,  48000,  49000,  84000,  85000,
+ 840000, 841000,  88000,  89000,  50000,  51000,  52000,  53000,  54000,  55000,
+  56000,  57000,  58000,  59000,  94000,  95000, 850000, 851000,  98000,  99000,
+  60000,  61000,  62000,  63000,  64000,  65000,  66000,  67000,  68000,  69000,
+  86000,  87000, 860000, 861000, 888000, 889000,  70000,  71000,  72000,  73000,
+  74000,  75000,  76000,  77000,  78000,  79000,  96000,  97000, 870000, 871000,
+ 898000, 899000, 100000, 101000, 102000, 103000, 104000, 105000, 106000, 107000,
+ 108000, 109000, 180000, 181000, 900000, 901000, 980000, 981000, 110000, 111000,
+ 112000, 113000, 114000, 115000, 116000, 117000, 118000, 119000, 190000, 191000,
+ 910000, 911000, 990000, 991000, 120000, 121000, 122000, 123000, 124000, 125000,
+ 126000, 127000, 128000, 129000, 182000, 183000, 920000, 921000, 908000, 909000,
+ 130000, 131000, 132000, 133000, 134000, 135000, 136000, 137000, 138000, 139000,
+ 192000, 193000, 930000, 931000, 918000, 919000, 140000, 141000, 142000, 143000,
+ 144000, 145000, 146000, 147000, 148000, 149000, 184000, 185000, 940000, 941000,
+ 188000, 189000, 150000, 151000, 152000, 153000, 154000, 155000, 156000, 157000,
+ 158000, 159000, 194000, 195000, 950000, 951000, 198000, 199000, 160000, 161000,
+ 162000, 163000, 164000, 165000, 166000, 167000, 168000, 169000, 186000, 187000,
+ 960000, 961000, 988000, 989000, 170000, 171000, 172000, 173000, 174000, 175000,
+ 176000, 177000, 178000, 179000, 196000, 197000, 970000, 971000, 998000, 999000,
+ 200000, 201000, 202000, 203000, 204000, 205000, 206000, 207000, 208000, 209000,
+ 280000, 281000, 802000, 803000, 882000, 883000, 210000, 211000, 212000, 213000,
+ 214000, 215000, 216000, 217000, 218000, 219000, 290000, 291000, 812000, 813000,
+ 892000, 893000, 220000, 221000, 222000, 223000, 224000, 225000, 226000, 227000,
+ 228000, 229000, 282000, 283000, 822000, 823000, 828000, 829000, 230000, 231000,
+ 232000, 233000, 234000, 235000, 236000, 237000, 238000, 239000, 292000, 293000,
+ 832000, 833000, 838000, 839000, 240000, 241000, 242000, 243000, 244000, 245000,
+ 246000, 247000, 248000, 249000, 284000, 285000, 842000, 843000, 288000, 289000,
+ 250000, 251000, 252000, 253000, 254000, 255000, 256000, 257000, 258000, 259000,
+ 294000, 295000, 852000, 853000, 298000, 299000, 260000, 261000, 262000, 263000,
+ 264000, 265000, 266000, 267000, 268000, 269000, 286000, 287000, 862000, 863000,
+ 888000, 889000, 270000, 271000, 272000, 273000, 274000, 275000, 276000, 277000,
+ 278000, 279000, 296000, 297000, 872000, 873000, 898000, 899000, 300000, 301000,
+ 302000, 303000, 304000, 305000, 306000, 307000, 308000, 309000, 380000, 381000,
+ 902000, 903000, 982000, 983000, 310000, 311000, 312000, 313000, 314000, 315000,
+ 316000, 317000, 318000, 319000, 390000, 391000, 912000, 913000, 992000, 993000,
+ 320000, 321000, 322000, 323000, 324000, 325000, 326000, 327000, 328000, 329000,
+ 382000, 383000, 922000, 923000, 928000, 929000, 330000, 331000, 332000, 333000,
+ 334000, 335000, 336000, 337000, 338000, 339000, 392000, 393000, 932000, 933000,
+ 938000, 939000, 340000, 341000, 342000, 343000, 344000, 345000, 346000, 347000,
+ 348000, 349000, 384000, 385000, 942000, 943000, 388000, 389000, 350000, 351000,
+ 352000, 353000, 354000, 355000, 356000, 357000, 358000, 359000, 394000, 395000,
+ 952000, 953000, 398000, 399000, 360000, 361000, 362000, 363000, 364000, 365000,
+ 366000, 367000, 368000, 369000, 386000, 387000, 962000, 963000, 988000, 989000,
+ 370000, 371000, 372000, 373000, 374000, 375000, 376000, 377000, 378000, 379000,
+ 396000, 397000, 972000, 973000, 998000, 999000, 400000, 401000, 402000, 403000,
+ 404000, 405000, 406000, 407000, 408000, 409000, 480000, 481000, 804000, 805000,
+ 884000, 885000, 410000, 411000, 412000, 413000, 414000, 415000, 416000, 417000,
+ 418000, 419000, 490000, 491000, 814000, 815000, 894000, 895000, 420000, 421000,
+ 422000, 423000, 424000, 425000, 426000, 427000, 428000, 429000, 482000, 483000,
+ 824000, 825000, 848000, 849000, 430000, 431000, 432000, 433000, 434000, 435000,
+ 436000, 437000, 438000, 439000, 492000, 493000, 834000, 835000, 858000, 859000,
+ 440000, 441000, 442000, 443000, 444000, 445000, 446000, 447000, 448000, 449000,
+ 484000, 485000, 844000, 845000, 488000, 489000, 450000, 451000, 452000, 453000,
+ 454000, 455000, 456000, 457000, 458000, 459000, 494000, 495000, 854000, 855000,
+ 498000, 499000, 460000, 461000, 462000, 463000, 464000, 465000, 466000, 467000,
+ 468000, 469000, 486000, 487000, 864000, 865000, 888000, 889000, 470000, 471000,
+ 472000, 473000, 474000, 475000, 476000, 477000, 478000, 479000, 496000, 497000,
+ 874000, 875000, 898000, 899000, 500000, 501000, 502000, 503000, 504000, 505000,
+ 506000, 507000, 508000, 509000, 580000, 581000, 904000, 905000, 984000, 985000,
+ 510000, 511000, 512000, 513000, 514000, 515000, 516000, 517000, 518000, 519000,
+ 590000, 591000, 914000, 915000, 994000, 995000, 520000, 521000, 522000, 523000,
+ 524000, 525000, 526000, 527000, 528000, 529000, 582000, 583000, 924000, 925000,
+ 948000, 949000, 530000, 531000, 532000, 533000, 534000, 535000, 536000, 537000,
+ 538000, 539000, 592000, 593000, 934000, 935000, 958000, 959000, 540000, 541000,
+ 542000, 543000, 544000, 545000, 546000, 547000, 548000, 549000, 584000, 585000,
+ 944000, 945000, 588000, 589000, 550000, 551000, 552000, 553000, 554000, 555000,
+ 556000, 557000, 558000, 559000, 594000, 595000, 954000, 955000, 598000, 599000,
+ 560000, 561000, 562000, 563000, 564000, 565000, 566000, 567000, 568000, 569000,
+ 586000, 587000, 964000, 965000, 988000, 989000, 570000, 571000, 572000, 573000,
+ 574000, 575000, 576000, 577000, 578000, 579000, 596000, 597000, 974000, 975000,
+ 998000, 999000, 600000, 601000, 602000, 603000, 604000, 605000, 606000, 607000,
+ 608000, 609000, 680000, 681000, 806000, 807000, 886000, 887000, 610000, 611000,
+ 612000, 613000, 614000, 615000, 616000, 617000, 618000, 619000, 690000, 691000,
+ 816000, 817000, 896000, 897000, 620000, 621000, 622000, 623000, 624000, 625000,
+ 626000, 627000, 628000, 629000, 682000, 683000, 826000, 827000, 868000, 869000,
+ 630000, 631000, 632000, 633000, 634000, 635000, 636000, 637000, 638000, 639000,
+ 692000, 693000, 836000, 837000, 878000, 879000, 640000, 641000, 642000, 643000,
+ 644000, 645000, 646000, 647000, 648000, 649000, 684000, 685000, 846000, 847000,
+ 688000, 689000, 650000, 651000, 652000, 653000, 654000, 655000, 656000, 657000,
+ 658000, 659000, 694000, 695000, 856000, 857000, 698000, 699000, 660000, 661000,
+ 662000, 663000, 664000, 665000, 666000, 667000, 668000, 669000, 686000, 687000,
+ 866000, 867000, 888000, 889000, 670000, 671000, 672000, 673000, 674000, 675000,
+ 676000, 677000, 678000, 679000, 696000, 697000, 876000, 877000, 898000, 899000,
+ 700000, 701000, 702000, 703000, 704000, 705000, 706000, 707000, 708000, 709000,
+ 780000, 781000, 906000, 907000, 986000, 987000, 710000, 711000, 712000, 713000,
+ 714000, 715000, 716000, 717000, 718000, 719000, 790000, 791000, 916000, 917000,
+ 996000, 997000, 720000, 721000, 722000, 723000, 724000, 725000, 726000, 727000,
+ 728000, 729000, 782000, 783000, 926000, 927000, 968000, 969000, 730000, 731000,
+ 732000, 733000, 734000, 735000, 736000, 737000, 738000, 739000, 792000, 793000,
+ 936000, 937000, 978000, 979000, 740000, 741000, 742000, 743000, 744000, 745000,
+ 746000, 747000, 748000, 749000, 784000, 785000, 946000, 947000, 788000, 789000,
+ 750000, 751000, 752000, 753000, 754000, 755000, 756000, 757000, 758000, 759000,
+ 794000, 795000, 956000, 957000, 798000, 799000, 760000, 761000, 762000, 763000,
+ 764000, 765000, 766000, 767000, 768000, 769000, 786000, 787000, 966000, 967000,
+ 988000, 989000, 770000, 771000, 772000, 773000, 774000, 775000, 776000, 777000,
+ 778000, 779000, 796000, 797000, 976000, 977000, 998000, 999000};
 #endif
 
-#if DEC_DPD2BCD==1
+#if defined(DEC_DPD2BINM) && DEC_DPD2BINM==1 && !defined(DECDPD2BINM)
+#define DECDPD2BINM
 
-const uint16_t DPD2BCD[1024] = { 0, 1, 2, 3, 4, 5, 6, 7,
-  8, 9, 128, 129, 2048, 2049, 2176, 2177, 16, 17, 18, 19, 20,
-  21, 22, 23, 24, 25, 144, 145, 2064, 2065, 2192, 2193, 32, 33,
-  34, 35, 36, 37, 38, 39, 40, 41, 130, 131, 2080, 2081, 2056,
-  2057, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 146, 147,
-  2096, 2097, 2072, 2073, 64, 65, 66, 67, 68, 69, 70, 71, 72,
-  73, 132, 133, 2112, 2113, 136, 137, 80, 81, 82, 83, 84, 85,
-  86, 87, 88, 89, 148, 149, 2128, 2129, 152, 153, 96, 97, 98,
-  99, 100, 101, 102, 103, 104, 105, 134, 135, 2144, 2145, 2184, 2185,
-  112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 150, 151, 2160,
-  2161, 2200, 2201, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
-  384, 385, 2304, 2305, 2432, 2433, 272, 273, 274, 275, 276, 277, 278,
-  279, 280, 281, 400, 401, 2320, 2321, 2448, 2449, 288, 289, 290, 291,
-  292, 293, 294, 295, 296, 297, 386, 387, 2336, 2337, 2312, 2313, 304,
-  305, 306, 307, 308, 309, 310, 311, 312, 313, 402, 403, 2352, 2353,
-  2328, 2329, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 388,
-  389, 2368, 2369, 392, 393, 336, 337, 338, 339, 340, 341, 342, 343,
-  344, 345, 404, 405, 2384, 2385, 408, 409, 352, 353, 354, 355, 356,
-  357, 358, 359, 360, 361, 390, 391, 2400, 2401, 2440, 2441, 368, 369,
-  370, 371, 372, 373, 374, 375, 376, 377, 406, 407, 2416, 2417, 2456,
-  2457, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 640, 641,
-  2050, 2051, 2178, 2179, 528, 529, 530, 531, 532, 533, 534, 535, 536,
-  537, 656, 657, 2066, 2067, 2194, 2195, 544, 545, 546, 547, 548, 549,
-  550, 551, 552, 553, 642, 643, 2082, 2083, 2088, 2089, 560, 561, 562,
-  563, 564, 565, 566, 567, 568, 569, 658, 659, 2098, 2099, 2104, 2105,
-  576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 644, 645, 2114,
-  2115, 648, 649, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601,
-  660, 661, 2130, 2131, 664, 665, 608, 609, 610, 611, 612, 613, 614,
-  615, 616, 617, 646, 647, 2146, 2147, 2184, 2185, 624, 625, 626, 627,
-  628, 629, 630, 631, 632, 633, 662, 663, 2162, 2163, 2200, 2201, 768,
-  769, 770, 771, 772, 773, 774, 775, 776, 777, 896, 897, 2306, 2307,
-  2434, 2435, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 912,
-  913, 2322, 2323, 2450, 2451, 800, 801, 802, 803, 804, 805, 806, 807,
-  808, 809, 898, 899, 2338, 2339, 2344, 2345, 816, 817, 818, 819, 820,
-  821, 822, 823, 824, 825, 914, 915, 2354, 2355, 2360, 2361, 832, 833,
-  834, 835, 836, 837, 838, 839, 840, 841, 900, 901, 2370, 2371, 904,
-  905, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 916, 917,
-  2386, 2387, 920, 921, 864, 865, 866, 867, 868, 869, 870, 871, 872,
-  873, 902, 903, 2402, 2403, 2440, 2441, 880, 881, 882, 883, 884, 885,
-  886, 887, 888, 889, 918, 919, 2418, 2419, 2456, 2457, 1024, 1025, 1026,
-  1027, 1028, 1029, 1030, 1031, 1032, 1033, 1152, 1153, 2052, 2053, 2180,
-    2181,
-  1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1168, 1169,
-    2068,
-  2069, 2196, 2197, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064,
-    1065,
-  1154, 1155, 2084, 2085, 2120, 2121, 1072, 1073, 1074, 1075, 1076, 1077,
-    1078,
-  1079, 1080, 1081, 1170, 1171, 2100, 2101, 2136, 2137, 1088, 1089, 1090,
-    1091,
-  1092, 1093, 1094, 1095, 1096, 1097, 1156, 1157, 2116, 2117, 1160, 1161,
-    1104,
-  1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1172, 1173, 2132,
-    2133,
-  1176, 1177, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129,
-    1158,
-  1159, 2148, 2149, 2184, 2185, 1136, 1137, 1138, 1139, 1140, 1141, 1142,
-    1143,
-  1144, 1145, 1174, 1175, 2164, 2165, 2200, 2201, 1280, 1281, 1282, 1283,
-    1284,
-  1285, 1286, 1287, 1288, 1289, 1408, 1409, 2308, 2309, 2436, 2437, 1296,
-    1297,
-  1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1424, 1425, 2324, 2325,
-    2452,
-  2453, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1410,
-    1411,
-  2340, 2341, 2376, 2377, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335,
-    1336,
-  1337, 1426, 1427, 2356, 2357, 2392, 2393, 1344, 1345, 1346, 1347, 1348,
-    1349,
-  1350, 1351, 1352, 1353, 1412, 1413, 2372, 2373, 1416, 1417, 1360, 1361,
-    1362,
-  1363, 1364, 1365, 1366, 1367, 1368, 1369, 1428, 1429, 2388, 2389, 1432,
-    1433,
-  1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1414, 1415,
-    2404,
-  2405, 2440, 2441, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400,
-    1401,
-  1430, 1431, 2420, 2421, 2456, 2457, 1536, 1537, 1538, 1539, 1540, 1541,
-    1542,
-  1543, 1544, 1545, 1664, 1665, 2054, 2055, 2182, 2183, 1552, 1553, 1554,
-    1555,
-  1556, 1557, 1558, 1559, 1560, 1561, 1680, 1681, 2070, 2071, 2198, 2199,
-    1568,
-  1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1666, 1667, 2086,
-    2087,
-  2152, 2153, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593,
-    1682,
-  1683, 2102, 2103, 2168, 2169, 1600, 1601, 1602, 1603, 1604, 1605, 1606,
-    1607,
-  1608, 1609, 1668, 1669, 2118, 2119, 1672, 1673, 1616, 1617, 1618, 1619,
-    1620,
-  1621, 1622, 1623, 1624, 1625, 1684, 1685, 2134, 2135, 1688, 1689, 1632,
-    1633,
-  1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1670, 1671, 2150, 2151,
-    2184,
-  2185, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1686,
-    1687,
-  2166, 2167, 2200, 2201, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799,
-    1800,
-  1801, 1920, 1921, 2310, 2311, 2438, 2439, 1808, 1809, 1810, 1811, 1812,
-    1813,
-  1814, 1815, 1816, 1817, 1936, 1937, 2326, 2327, 2454, 2455, 1824, 1825,
-    1826,
-  1827, 1828, 1829, 1830, 1831, 1832, 1833, 1922, 1923, 2342, 2343, 2408,
-    2409,
-  1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1938, 1939,
-    2358,
-  2359, 2424, 2425, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864,
-    1865,
-  1924, 1925, 2374, 2375, 1928, 1929, 1872, 1873, 1874, 1875, 1876, 1877,
-    1878,
-  1879, 1880, 1881, 1940, 1941, 2390, 2391, 1944, 1945, 1888, 1889, 1890,
-    1891,
-  1892, 1893, 1894, 1895, 1896, 1897, 1926, 1927, 2406, 2407, 2440, 2441,
-    1904,
-  1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1942, 1943, 2422,
-    2423,
-  2456, 2457
-};
+const uint32_t DPD2BINM[1024]={0,   1000000,   2000000,          3000000,   4000000,
+   5000000,   6000000,  7000000,   8000000,   9000000,  80000000,  81000000,
+ 800000000, 801000000, 880000000, 881000000,  10000000,         11000000,  12000000,
+  13000000,  14000000, 15000000,  16000000,  17000000,  18000000,  19000000,
+  90000000,  91000000, 810000000, 811000000, 890000000, 891000000,  20000000,
+  21000000,  22000000, 23000000,  24000000,  25000000,  26000000,  27000000,
+  28000000,  29000000, 82000000,  83000000, 820000000, 821000000, 808000000,
+ 809000000,  30000000, 31000000,  32000000,  33000000,  34000000,  35000000,
+  36000000,  37000000, 38000000,  39000000,  92000000,  93000000, 830000000,
+ 831000000, 818000000, 819000000,  40000000,  41000000,         42000000,  43000000,
+  44000000,  45000000, 46000000,  47000000,  48000000,  49000000,  84000000,
+  85000000, 840000000, 841000000,  88000000,  89000000,         50000000,  51000000,
+  52000000,  53000000, 54000000,  55000000,  56000000,  57000000,  58000000,
+  59000000,  94000000, 95000000, 850000000, 851000000,  98000000,  99000000,
+  60000000,  61000000, 62000000,  63000000,  64000000,  65000000,  66000000,
+  67000000,  68000000, 69000000,  86000000,  87000000, 860000000, 861000000,
+ 888000000, 889000000, 70000000,  71000000,  72000000,  73000000,  74000000,
+  75000000,  76000000, 77000000,  78000000,  79000000,  96000000,  97000000,
+ 870000000, 871000000, 898000000, 899000000, 100000000, 101000000, 102000000,
+ 103000000, 104000000, 105000000, 106000000, 107000000, 108000000, 109000000,
+ 180000000, 181000000, 900000000, 901000000, 980000000, 981000000, 110000000,
+ 111000000, 112000000, 113000000, 114000000, 115000000, 116000000, 117000000,
+ 118000000, 119000000, 190000000, 191000000, 910000000, 911000000, 990000000,
+ 991000000, 120000000, 121000000, 122000000, 123000000, 124000000, 125000000,
+ 126000000, 127000000, 128000000, 129000000, 182000000, 183000000, 920000000,
+ 921000000, 908000000, 909000000, 130000000, 131000000, 132000000, 133000000,
+ 134000000, 135000000, 136000000, 137000000, 138000000, 139000000, 192000000,
+ 193000000, 930000000, 931000000, 918000000, 919000000, 140000000, 141000000,
+ 142000000, 143000000, 144000000, 145000000, 146000000, 147000000, 148000000,
+ 149000000, 184000000, 185000000, 940000000, 941000000, 188000000, 189000000,
+ 150000000, 151000000, 152000000, 153000000, 154000000, 155000000, 156000000,
+ 157000000, 158000000, 159000000, 194000000, 195000000, 950000000, 951000000,
+ 198000000, 199000000, 160000000, 161000000, 162000000, 163000000, 164000000,
+ 165000000, 166000000, 167000000, 168000000, 169000000, 186000000, 187000000,
+ 960000000, 961000000, 988000000, 989000000, 170000000, 171000000, 172000000,
+ 173000000, 174000000, 175000000, 176000000, 177000000, 178000000, 179000000,
+ 196000000, 197000000, 970000000, 971000000, 998000000, 999000000, 200000000,
+ 201000000, 202000000, 203000000, 204000000, 205000000, 206000000, 207000000,
+ 208000000, 209000000, 280000000, 281000000, 802000000, 803000000, 882000000,
+ 883000000, 210000000, 211000000, 212000000, 213000000, 214000000, 215000000,
+ 216000000, 217000000, 218000000, 219000000, 290000000, 291000000, 812000000,
+ 813000000, 892000000, 893000000, 220000000, 221000000, 222000000, 223000000,
+ 224000000, 225000000, 226000000, 227000000, 228000000, 229000000, 282000000,
+ 283000000, 822000000, 823000000, 828000000, 829000000, 230000000, 231000000,
+ 232000000, 233000000, 234000000, 235000000, 236000000, 237000000, 238000000,
+ 239000000, 292000000, 293000000, 832000000, 833000000, 838000000, 839000000,
+ 240000000, 241000000, 242000000, 243000000, 244000000, 245000000, 246000000,
+ 247000000, 248000000, 249000000, 284000000, 285000000, 842000000, 843000000,
+ 288000000, 289000000, 250000000, 251000000, 252000000, 253000000, 254000000,
+ 255000000, 256000000, 257000000, 258000000, 259000000, 294000000, 295000000,
+ 852000000, 853000000, 298000000, 299000000, 260000000, 261000000, 262000000,
+ 263000000, 264000000, 265000000, 266000000, 267000000, 268000000, 269000000,
+ 286000000, 287000000, 862000000, 863000000, 888000000, 889000000, 270000000,
+ 271000000, 272000000, 273000000, 274000000, 275000000, 276000000, 277000000,
+ 278000000, 279000000, 296000000, 297000000, 872000000, 873000000, 898000000,
+ 899000000, 300000000, 301000000, 302000000, 303000000, 304000000, 305000000,
+ 306000000, 307000000, 308000000, 309000000, 380000000, 381000000, 902000000,
+ 903000000, 982000000, 983000000, 310000000, 311000000, 312000000, 313000000,
+ 314000000, 315000000, 316000000, 317000000, 318000000, 319000000, 390000000,
+ 391000000, 912000000, 913000000, 992000000, 993000000, 320000000, 321000000,
+ 322000000, 323000000, 324000000, 325000000, 326000000, 327000000, 328000000,
+ 329000000, 382000000, 383000000, 922000000, 923000000, 928000000, 929000000,
+ 330000000, 331000000, 332000000, 333000000, 334000000, 335000000, 336000000,
+ 337000000, 338000000, 339000000, 392000000, 393000000, 932000000, 933000000,
+ 938000000, 939000000, 340000000, 341000000, 342000000, 343000000, 344000000,
+ 345000000, 346000000, 347000000, 348000000, 349000000, 384000000, 385000000,
+ 942000000, 943000000, 388000000, 389000000, 350000000, 351000000, 352000000,
+ 353000000, 354000000, 355000000, 356000000, 357000000, 358000000, 359000000,
+ 394000000, 395000000, 952000000, 953000000, 398000000, 399000000, 360000000,
+ 361000000, 362000000, 363000000, 364000000, 365000000, 366000000, 367000000,
+ 368000000, 369000000, 386000000, 387000000, 962000000, 963000000, 988000000,
+ 989000000, 370000000, 371000000, 372000000, 373000000, 374000000, 375000000,
+ 376000000, 377000000, 378000000, 379000000, 396000000, 397000000, 972000000,
+ 973000000, 998000000, 999000000, 400000000, 401000000, 402000000, 403000000,
+ 404000000, 405000000, 406000000, 407000000, 408000000, 409000000, 480000000,
+ 481000000, 804000000, 805000000, 884000000, 885000000, 410000000, 411000000,
+ 412000000, 413000000, 414000000, 415000000, 416000000, 417000000, 418000000,
+ 419000000, 490000000, 491000000, 814000000, 815000000, 894000000, 895000000,
+ 420000000, 421000000, 422000000, 423000000, 424000000, 425000000, 426000000,
+ 427000000, 428000000, 429000000, 482000000, 483000000, 824000000, 825000000,
+ 848000000, 849000000, 430000000, 431000000, 432000000, 433000000, 434000000,
+ 435000000, 436000000, 437000000, 438000000, 439000000, 492000000, 493000000,
+ 834000000, 835000000, 858000000, 859000000, 440000000, 441000000, 442000000,
+ 443000000, 444000000, 445000000, 446000000, 447000000, 448000000, 449000000,
+ 484000000, 485000000, 844000000, 845000000, 488000000, 489000000, 450000000,
+ 451000000, 452000000, 453000000, 454000000, 455000000, 456000000, 457000000,
+ 458000000, 459000000, 494000000, 495000000, 854000000, 855000000, 498000000,
+ 499000000, 460000000, 461000000, 462000000, 463000000, 464000000, 465000000,
+ 466000000, 467000000, 468000000, 469000000, 486000000, 487000000, 864000000,
+ 865000000, 888000000, 889000000, 470000000, 471000000, 472000000, 473000000,
+ 474000000, 475000000, 476000000, 477000000, 478000000, 479000000, 496000000,
+ 497000000, 874000000, 875000000, 898000000, 899000000, 500000000, 501000000,
+ 502000000, 503000000, 504000000, 505000000, 506000000, 507000000, 508000000,
+ 509000000, 580000000, 581000000, 904000000, 905000000, 984000000, 985000000,
+ 510000000, 511000000, 512000000, 513000000, 514000000, 515000000, 516000000,
+ 517000000, 518000000, 519000000, 590000000, 591000000, 914000000, 915000000,
+ 994000000, 995000000, 520000000, 521000000, 522000000, 523000000, 524000000,
+ 525000000, 526000000, 527000000, 528000000, 529000000, 582000000, 583000000,
+ 924000000, 925000000, 948000000, 949000000, 530000000, 531000000, 532000000,
+ 533000000, 534000000, 535000000, 536000000, 537000000, 538000000, 539000000,
+ 592000000, 593000000, 934000000, 935000000, 958000000, 959000000, 540000000,
+ 541000000, 542000000, 543000000, 544000000, 545000000, 546000000, 547000000,
+ 548000000, 549000000, 584000000, 585000000, 944000000, 945000000, 588000000,
+ 589000000, 550000000, 551000000, 552000000, 553000000, 554000000, 555000000,
+ 556000000, 557000000, 558000000, 559000000, 594000000, 595000000, 954000000,
+ 955000000, 598000000, 599000000, 560000000, 561000000, 562000000, 563000000,
+ 564000000, 565000000, 566000000, 567000000, 568000000, 569000000, 586000000,
+ 587000000, 964000000, 965000000, 988000000, 989000000, 570000000, 571000000,
+ 572000000, 573000000, 574000000, 575000000, 576000000, 577000000, 578000000,
+ 579000000, 596000000, 597000000, 974000000, 975000000, 998000000, 999000000,
+ 600000000, 601000000, 602000000, 603000000, 604000000, 605000000, 606000000,
+ 607000000, 608000000, 609000000, 680000000, 681000000, 806000000, 807000000,
+ 886000000, 887000000, 610000000, 611000000, 612000000, 613000000, 614000000,
+ 615000000, 616000000, 617000000, 618000000, 619000000, 690000000, 691000000,
+ 816000000, 817000000, 896000000, 897000000, 620000000, 621000000, 622000000,
+ 623000000, 624000000, 625000000, 626000000, 627000000, 628000000, 629000000,
+ 682000000, 683000000, 826000000, 827000000, 868000000, 869000000, 630000000,
+ 631000000, 632000000, 633000000, 634000000, 635000000, 636000000, 637000000,
+ 638000000, 639000000, 692000000, 693000000, 836000000, 837000000, 878000000,
+ 879000000, 640000000, 641000000, 642000000, 643000000, 644000000, 645000000,
+ 646000000, 647000000, 648000000, 649000000, 684000000, 685000000, 846000000,
+ 847000000, 688000000, 689000000, 650000000, 651000000, 652000000, 653000000,
+ 654000000, 655000000, 656000000, 657000000, 658000000, 659000000, 694000000,
+ 695000000, 856000000, 857000000, 698000000, 699000000, 660000000, 661000000,
+ 662000000, 663000000, 664000000, 665000000, 666000000, 667000000, 668000000,
+ 669000000, 686000000, 687000000, 866000000, 867000000, 888000000, 889000000,
+ 670000000, 671000000, 672000000, 673000000, 674000000, 675000000, 676000000,
+ 677000000, 678000000, 679000000, 696000000, 697000000, 876000000, 877000000,
+ 898000000, 899000000, 700000000, 701000000, 702000000, 703000000, 704000000,
+ 705000000, 706000000, 707000000, 708000000, 709000000, 780000000, 781000000,
+ 906000000, 907000000, 986000000, 987000000, 710000000, 711000000, 712000000,
+ 713000000, 714000000, 715000000, 716000000, 717000000, 718000000, 719000000,
+ 790000000, 791000000, 916000000, 917000000, 996000000, 997000000, 720000000,
+ 721000000, 722000000, 723000000, 724000000, 725000000, 726000000, 727000000,
+ 728000000, 729000000, 782000000, 783000000, 926000000, 927000000, 968000000,
+ 969000000, 730000000, 731000000, 732000000, 733000000, 734000000, 735000000,
+ 736000000, 737000000, 738000000, 739000000, 792000000, 793000000, 936000000,
+ 937000000, 978000000, 979000000, 740000000, 741000000, 742000000, 743000000,
+ 744000000, 745000000, 746000000, 747000000, 748000000, 749000000, 784000000,
+ 785000000, 946000000, 947000000, 788000000, 789000000, 750000000, 751000000,
+ 752000000, 753000000, 754000000, 755000000, 756000000, 757000000, 758000000,
+ 759000000, 794000000, 795000000, 956000000, 957000000, 798000000, 799000000,
+ 760000000, 761000000, 762000000, 763000000, 764000000, 765000000, 766000000,
+ 767000000, 768000000, 769000000, 786000000, 787000000, 966000000, 967000000,
+ 988000000, 989000000, 770000000, 771000000, 772000000, 773000000, 774000000,
+ 775000000, 776000000, 777000000, 778000000, 779000000, 796000000, 797000000,
+ 976000000, 977000000, 998000000, 999000000};
 #endif
 
-#if DEC_BIN2DPD==1
+#if defined(DEC_BIN2CHAR) && DEC_BIN2CHAR==1 && !defined(DECBIN2CHAR)
+#define DECBIN2CHAR
 
-const uint16_t BIN2DPD[1000] = { 0, 1, 2, 3, 4, 5, 6, 7,
-  8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32,
-  33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51,
-  52, 53, 54, 55, 56, 57, 64, 65, 66, 67, 68, 69, 70,
-  71, 72, 73, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
-  96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 112, 113, 114,
-  115, 116, 117, 118, 119, 120, 121, 10, 11, 42, 43, 74, 75,
-  106, 107, 78, 79, 26, 27, 58, 59, 90, 91, 122, 123, 94,
-  95, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 144, 145,
-  146, 147, 148, 149, 150, 151, 152, 153, 160, 161, 162, 163, 164,
-  165, 166, 167, 168, 169, 176, 177, 178, 179, 180, 181, 182, 183,
-  184, 185, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 208,
-  209, 210, 211, 212, 213, 214, 215, 216, 217, 224, 225, 226, 227,
-  228, 229, 230, 231, 232, 233, 240, 241, 242, 243, 244, 245, 246,
-  247, 248, 249, 138, 139, 170, 171, 202, 203, 234, 235, 206, 207,
-  154, 155, 186, 187, 218, 219, 250, 251, 222, 223, 256, 257, 258,
-  259, 260, 261, 262, 263, 264, 265, 272, 273, 274, 275, 276, 277,
-  278, 279, 280, 281, 288, 289, 290, 291, 292, 293, 294, 295, 296,
-  297, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 320, 321,
-  322, 323, 324, 325, 326, 327, 328, 329, 336, 337, 338, 339, 340,
-  341, 342, 343, 344, 345, 352, 353, 354, 355, 356, 357, 358, 359,
-  360, 361, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 266,
-  267, 298, 299, 330, 331, 362, 363, 334, 335, 282, 283, 314, 315,
-  346, 347, 378, 379, 350, 351, 384, 385, 386, 387, 388, 389, 390,
-  391, 392, 393, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409,
-  416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 432, 433, 434,
-  435, 436, 437, 438, 439, 440, 441, 448, 449, 450, 451, 452, 453,
-  454, 455, 456, 457, 464, 465, 466, 467, 468, 469, 470, 471, 472,
-  473, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 496, 497,
-  498, 499, 500, 501, 502, 503, 504, 505, 394, 395, 426, 427, 458,
-  459, 490, 491, 462, 463, 410, 411, 442, 443, 474, 475, 506, 507,
-  478, 479, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 528,
-  529, 530, 531, 532, 533, 534, 535, 536, 537, 544, 545, 546, 547,
-  548, 549, 550, 551, 552, 553, 560, 561, 562, 563, 564, 565, 566,
-  567, 568, 569, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585,
-  592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 608, 609, 610,
-  611, 612, 613, 614, 615, 616, 617, 624, 625, 626, 627, 628, 629,
-  630, 631, 632, 633, 522, 523, 554, 555, 586, 587, 618, 619, 590,
-  591, 538, 539, 570, 571, 602, 603, 634, 635, 606, 607, 640, 641,
-  642, 643, 644, 645, 646, 647, 648, 649, 656, 657, 658, 659, 660,
-  661, 662, 663, 664, 665, 672, 673, 674, 675, 676, 677, 678, 679,
-  680, 681, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 704,
-  705, 706, 707, 708, 709, 710, 711, 712, 713, 720, 721, 722, 723,
-  724, 725, 726, 727, 728, 729, 736, 737, 738, 739, 740, 741, 742,
-  743, 744, 745, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761,
-  650, 651, 682, 683, 714, 715, 746, 747, 718, 719, 666, 667, 698,
-  699, 730, 731, 762, 763, 734, 735, 768, 769, 770, 771, 772, 773,
-  774, 775, 776, 777, 784, 785, 786, 787, 788, 789, 790, 791, 792,
-  793, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 816, 817,
-  818, 819, 820, 821, 822, 823, 824, 825, 832, 833, 834, 835, 836,
-  837, 838, 839, 840, 841, 848, 849, 850, 851, 852, 853, 854, 855,
-  856, 857, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 880,
-  881, 882, 883, 884, 885, 886, 887, 888, 889, 778, 779, 810, 811,
-  842, 843, 874, 875, 846, 847, 794, 795, 826, 827, 858, 859, 890,
-  891, 862, 863, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905,
-  912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 928, 929, 930,
-  931, 932, 933, 934, 935, 936, 937, 944, 945, 946, 947, 948, 949,
-  950, 951, 952, 953, 960, 961, 962, 963, 964, 965, 966, 967, 968,
-  969, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 992, 993,
-  994, 995, 996, 997, 998, 999, 1000, 1001, 1008, 1009, 1010, 1011, 1012,
-  1013, 1014, 1015, 1016, 1017, 906, 907, 938, 939, 970, 971, 1002, 1003,
-  974, 975, 922, 923, 954, 955, 986, 987, 1018, 1019, 990, 991, 12,
-  13, 268, 269, 524, 525, 780, 781, 46, 47, 28, 29, 284, 285,
-  540, 541, 796, 797, 62, 63, 44, 45, 300, 301, 556, 557, 812,
-  813, 302, 303, 60, 61, 316, 317, 572, 573, 828, 829, 318, 319,
-  76, 77, 332, 333, 588, 589, 844, 845, 558, 559, 92, 93, 348,
-  349, 604, 605, 860, 861, 574, 575, 108, 109, 364, 365, 620, 621,
-  876, 877, 814, 815, 124, 125, 380, 381, 636, 637, 892, 893, 830,
-  831, 14, 15, 270, 271, 526, 527, 782, 783, 110, 111, 30, 31,
-  286, 287, 542, 543, 798, 799, 126, 127, 140, 141, 396, 397, 652,
-  653, 908, 909, 174, 175, 156, 157, 412, 413, 668, 669, 924, 925,
-  190, 191, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 188,
-  189, 444, 445, 700, 701, 956, 957, 446, 447, 204, 205, 460, 461,
-  716, 717, 972, 973, 686, 687, 220, 221, 476, 477, 732, 733, 988,
-  989, 702, 703, 236, 237, 492, 493, 748, 749, 1004, 1005, 942, 943,
-  252, 253, 508, 509, 764, 765, 1020, 1021, 958, 959, 142, 143, 398,
-  399, 654, 655, 910, 911, 238, 239, 158, 159, 414, 415, 670, 671,
-  926, 927, 254, 255
-};
+const uint8_t BIN2CHAR[4001]={
+ '\0','0','0','0', '\1','0','0','1', '\1','0','0','2', '\1','0','0','3', '\1','0','0','4',
+ '\1','0','0','5', '\1','0','0','6', '\1','0','0','7', '\1','0','0','8', '\1','0','0','9',
+ '\2','0','1','0', '\2','0','1','1', '\2','0','1','2', '\2','0','1','3', '\2','0','1','4',
+ '\2','0','1','5', '\2','0','1','6', '\2','0','1','7', '\2','0','1','8', '\2','0','1','9',
+ '\2','0','2','0', '\2','0','2','1', '\2','0','2','2', '\2','0','2','3', '\2','0','2','4',
+ '\2','0','2','5', '\2','0','2','6', '\2','0','2','7', '\2','0','2','8', '\2','0','2','9',
+ '\2','0','3','0', '\2','0','3','1', '\2','0','3','2', '\2','0','3','3', '\2','0','3','4',
+ '\2','0','3','5', '\2','0','3','6', '\2','0','3','7', '\2','0','3','8', '\2','0','3','9',
+ '\2','0','4','0', '\2','0','4','1', '\2','0','4','2', '\2','0','4','3', '\2','0','4','4',
+ '\2','0','4','5', '\2','0','4','6', '\2','0','4','7', '\2','0','4','8', '\2','0','4','9',
+ '\2','0','5','0', '\2','0','5','1', '\2','0','5','2', '\2','0','5','3', '\2','0','5','4',
+ '\2','0','5','5', '\2','0','5','6', '\2','0','5','7', '\2','0','5','8', '\2','0','5','9',
+ '\2','0','6','0', '\2','0','6','1', '\2','0','6','2', '\2','0','6','3', '\2','0','6','4',
+ '\2','0','6','5', '\2','0','6','6', '\2','0','6','7', '\2','0','6','8', '\2','0','6','9',
+ '\2','0','7','0', '\2','0','7','1', '\2','0','7','2', '\2','0','7','3', '\2','0','7','4',
+ '\2','0','7','5', '\2','0','7','6', '\2','0','7','7', '\2','0','7','8', '\2','0','7','9',
+ '\2','0','8','0', '\2','0','8','1', '\2','0','8','2', '\2','0','8','3', '\2','0','8','4',
+ '\2','0','8','5', '\2','0','8','6', '\2','0','8','7', '\2','0','8','8', '\2','0','8','9',
+ '\2','0','9','0', '\2','0','9','1', '\2','0','9','2', '\2','0','9','3', '\2','0','9','4',
+ '\2','0','9','5', '\2','0','9','6', '\2','0','9','7', '\2','0','9','8', '\2','0','9','9',
+ '\3','1','0','0', '\3','1','0','1', '\3','1','0','2', '\3','1','0','3', '\3','1','0','4',
+ '\3','1','0','5', '\3','1','0','6', '\3','1','0','7', '\3','1','0','8', '\3','1','0','9',
+ '\3','1','1','0', '\3','1','1','1', '\3','1','1','2', '\3','1','1','3', '\3','1','1','4',
+ '\3','1','1','5', '\3','1','1','6', '\3','1','1','7', '\3','1','1','8', '\3','1','1','9',
+ '\3','1','2','0', '\3','1','2','1', '\3','1','2','2', '\3','1','2','3', '\3','1','2','4',
+ '\3','1','2','5', '\3','1','2','6', '\3','1','2','7', '\3','1','2','8', '\3','1','2','9',
+ '\3','1','3','0', '\3','1','3','1', '\3','1','3','2', '\3','1','3','3', '\3','1','3','4',
+ '\3','1','3','5', '\3','1','3','6', '\3','1','3','7', '\3','1','3','8', '\3','1','3','9',
+ '\3','1','4','0', '\3','1','4','1', '\3','1','4','2', '\3','1','4','3', '\3','1','4','4',
+ '\3','1','4','5', '\3','1','4','6', '\3','1','4','7', '\3','1','4','8', '\3','1','4','9',
+ '\3','1','5','0', '\3','1','5','1', '\3','1','5','2', '\3','1','5','3', '\3','1','5','4',
+ '\3','1','5','5', '\3','1','5','6', '\3','1','5','7', '\3','1','5','8', '\3','1','5','9',
+ '\3','1','6','0', '\3','1','6','1', '\3','1','6','2', '\3','1','6','3', '\3','1','6','4',
+ '\3','1','6','5', '\3','1','6','6', '\3','1','6','7', '\3','1','6','8', '\3','1','6','9',
+ '\3','1','7','0', '\3','1','7','1', '\3','1','7','2', '\3','1','7','3', '\3','1','7','4',
+ '\3','1','7','5', '\3','1','7','6', '\3','1','7','7', '\3','1','7','8', '\3','1','7','9',
+ '\3','1','8','0', '\3','1','8','1', '\3','1','8','2', '\3','1','8','3', '\3','1','8','4',
+ '\3','1','8','5', '\3','1','8','6', '\3','1','8','7', '\3','1','8','8', '\3','1','8','9',
+ '\3','1','9','0', '\3','1','9','1', '\3','1','9','2', '\3','1','9','3', '\3','1','9','4',
+ '\3','1','9','5', '\3','1','9','6', '\3','1','9','7', '\3','1','9','8', '\3','1','9','9',
+ '\3','2','0','0', '\3','2','0','1', '\3','2','0','2', '\3','2','0','3', '\3','2','0','4',
+ '\3','2','0','5', '\3','2','0','6', '\3','2','0','7', '\3','2','0','8', '\3','2','0','9',
+ '\3','2','1','0', '\3','2','1','1', '\3','2','1','2', '\3','2','1','3', '\3','2','1','4',
+ '\3','2','1','5', '\3','2','1','6', '\3','2','1','7', '\3','2','1','8', '\3','2','1','9',
+ '\3','2','2','0', '\3','2','2','1', '\3','2','2','2', '\3','2','2','3', '\3','2','2','4',
+ '\3','2','2','5', '\3','2','2','6', '\3','2','2','7', '\3','2','2','8', '\3','2','2','9',
+ '\3','2','3','0', '\3','2','3','1', '\3','2','3','2', '\3','2','3','3', '\3','2','3','4',
+ '\3','2','3','5', '\3','2','3','6', '\3','2','3','7', '\3','2','3','8', '\3','2','3','9',
+ '\3','2','4','0', '\3','2','4','1', '\3','2','4','2', '\3','2','4','3', '\3','2','4','4',
+ '\3','2','4','5', '\3','2','4','6', '\3','2','4','7', '\3','2','4','8', '\3','2','4','9',
+ '\3','2','5','0', '\3','2','5','1', '\3','2','5','2', '\3','2','5','3', '\3','2','5','4',
+ '\3','2','5','5', '\3','2','5','6', '\3','2','5','7', '\3','2','5','8', '\3','2','5','9',
+ '\3','2','6','0', '\3','2','6','1', '\3','2','6','2', '\3','2','6','3', '\3','2','6','4',
+ '\3','2','6','5', '\3','2','6','6', '\3','2','6','7', '\3','2','6','8', '\3','2','6','9',
+ '\3','2','7','0', '\3','2','7','1', '\3','2','7','2', '\3','2','7','3', '\3','2','7','4',
+ '\3','2','7','5', '\3','2','7','6', '\3','2','7','7', '\3','2','7','8', '\3','2','7','9',
+ '\3','2','8','0', '\3','2','8','1', '\3','2','8','2', '\3','2','8','3', '\3','2','8','4',
+ '\3','2','8','5', '\3','2','8','6', '\3','2','8','7', '\3','2','8','8', '\3','2','8','9',
+ '\3','2','9','0', '\3','2','9','1', '\3','2','9','2', '\3','2','9','3', '\3','2','9','4',
+ '\3','2','9','5', '\3','2','9','6', '\3','2','9','7', '\3','2','9','8', '\3','2','9','9',
+ '\3','3','0','0', '\3','3','0','1', '\3','3','0','2', '\3','3','0','3', '\3','3','0','4',
+ '\3','3','0','5', '\3','3','0','6', '\3','3','0','7', '\3','3','0','8', '\3','3','0','9',
+ '\3','3','1','0', '\3','3','1','1', '\3','3','1','2', '\3','3','1','3', '\3','3','1','4',
+ '\3','3','1','5', '\3','3','1','6', '\3','3','1','7', '\3','3','1','8', '\3','3','1','9',
+ '\3','3','2','0', '\3','3','2','1', '\3','3','2','2', '\3','3','2','3', '\3','3','2','4',
+ '\3','3','2','5', '\3','3','2','6', '\3','3','2','7', '\3','3','2','8', '\3','3','2','9',
+ '\3','3','3','0', '\3','3','3','1', '\3','3','3','2', '\3','3','3','3', '\3','3','3','4',
+ '\3','3','3','5', '\3','3','3','6', '\3','3','3','7', '\3','3','3','8', '\3','3','3','9',
+ '\3','3','4','0', '\3','3','4','1', '\3','3','4','2', '\3','3','4','3', '\3','3','4','4',
+ '\3','3','4','5', '\3','3','4','6', '\3','3','4','7', '\3','3','4','8', '\3','3','4','9',
+ '\3','3','5','0', '\3','3','5','1', '\3','3','5','2', '\3','3','5','3', '\3','3','5','4',
+ '\3','3','5','5', '\3','3','5','6', '\3','3','5','7', '\3','3','5','8', '\3','3','5','9',
+ '\3','3','6','0', '\3','3','6','1', '\3','3','6','2', '\3','3','6','3', '\3','3','6','4',
+ '\3','3','6','5', '\3','3','6','6', '\3','3','6','7', '\3','3','6','8', '\3','3','6','9',
+ '\3','3','7','0', '\3','3','7','1', '\3','3','7','2', '\3','3','7','3', '\3','3','7','4',
+ '\3','3','7','5', '\3','3','7','6', '\3','3','7','7', '\3','3','7','8', '\3','3','7','9',
+ '\3','3','8','0', '\3','3','8','1', '\3','3','8','2', '\3','3','8','3', '\3','3','8','4',
+ '\3','3','8','5', '\3','3','8','6', '\3','3','8','7', '\3','3','8','8', '\3','3','8','9',
+ '\3','3','9','0', '\3','3','9','1', '\3','3','9','2', '\3','3','9','3', '\3','3','9','4',
+ '\3','3','9','5', '\3','3','9','6', '\3','3','9','7', '\3','3','9','8', '\3','3','9','9',
+ '\3','4','0','0', '\3','4','0','1', '\3','4','0','2', '\3','4','0','3', '\3','4','0','4',
+ '\3','4','0','5', '\3','4','0','6', '\3','4','0','7', '\3','4','0','8', '\3','4','0','9',
+ '\3','4','1','0', '\3','4','1','1', '\3','4','1','2', '\3','4','1','3', '\3','4','1','4',
+ '\3','4','1','5', '\3','4','1','6', '\3','4','1','7', '\3','4','1','8', '\3','4','1','9',
+ '\3','4','2','0', '\3','4','2','1', '\3','4','2','2', '\3','4','2','3', '\3','4','2','4',
+ '\3','4','2','5', '\3','4','2','6', '\3','4','2','7', '\3','4','2','8', '\3','4','2','9',
+ '\3','4','3','0', '\3','4','3','1', '\3','4','3','2', '\3','4','3','3', '\3','4','3','4',
+ '\3','4','3','5', '\3','4','3','6', '\3','4','3','7', '\3','4','3','8', '\3','4','3','9',
+ '\3','4','4','0', '\3','4','4','1', '\3','4','4','2', '\3','4','4','3', '\3','4','4','4',
+ '\3','4','4','5', '\3','4','4','6', '\3','4','4','7', '\3','4','4','8', '\3','4','4','9',
+ '\3','4','5','0', '\3','4','5','1', '\3','4','5','2', '\3','4','5','3', '\3','4','5','4',
+ '\3','4','5','5', '\3','4','5','6', '\3','4','5','7', '\3','4','5','8', '\3','4','5','9',
+ '\3','4','6','0', '\3','4','6','1', '\3','4','6','2', '\3','4','6','3', '\3','4','6','4',
+ '\3','4','6','5', '\3','4','6','6', '\3','4','6','7', '\3','4','6','8', '\3','4','6','9',
+ '\3','4','7','0', '\3','4','7','1', '\3','4','7','2', '\3','4','7','3', '\3','4','7','4',
+ '\3','4','7','5', '\3','4','7','6', '\3','4','7','7', '\3','4','7','8', '\3','4','7','9',
+ '\3','4','8','0', '\3','4','8','1', '\3','4','8','2', '\3','4','8','3', '\3','4','8','4',
+ '\3','4','8','5', '\3','4','8','6', '\3','4','8','7', '\3','4','8','8', '\3','4','8','9',
+ '\3','4','9','0', '\3','4','9','1', '\3','4','9','2', '\3','4','9','3', '\3','4','9','4',
+ '\3','4','9','5', '\3','4','9','6', '\3','4','9','7', '\3','4','9','8', '\3','4','9','9',
+ '\3','5','0','0', '\3','5','0','1', '\3','5','0','2', '\3','5','0','3', '\3','5','0','4',
+ '\3','5','0','5', '\3','5','0','6', '\3','5','0','7', '\3','5','0','8', '\3','5','0','9',
+ '\3','5','1','0', '\3','5','1','1', '\3','5','1','2', '\3','5','1','3', '\3','5','1','4',
+ '\3','5','1','5', '\3','5','1','6', '\3','5','1','7', '\3','5','1','8', '\3','5','1','9',
+ '\3','5','2','0', '\3','5','2','1', '\3','5','2','2', '\3','5','2','3', '\3','5','2','4',
+ '\3','5','2','5', '\3','5','2','6', '\3','5','2','7', '\3','5','2','8', '\3','5','2','9',
+ '\3','5','3','0', '\3','5','3','1', '\3','5','3','2', '\3','5','3','3', '\3','5','3','4',
+ '\3','5','3','5', '\3','5','3','6', '\3','5','3','7', '\3','5','3','8', '\3','5','3','9',
+ '\3','5','4','0', '\3','5','4','1', '\3','5','4','2', '\3','5','4','3', '\3','5','4','4',
+ '\3','5','4','5', '\3','5','4','6', '\3','5','4','7', '\3','5','4','8', '\3','5','4','9',
+ '\3','5','5','0', '\3','5','5','1', '\3','5','5','2', '\3','5','5','3', '\3','5','5','4',
+ '\3','5','5','5', '\3','5','5','6', '\3','5','5','7', '\3','5','5','8', '\3','5','5','9',
+ '\3','5','6','0', '\3','5','6','1', '\3','5','6','2', '\3','5','6','3', '\3','5','6','4',
+ '\3','5','6','5', '\3','5','6','6', '\3','5','6','7', '\3','5','6','8', '\3','5','6','9',
+ '\3','5','7','0', '\3','5','7','1', '\3','5','7','2', '\3','5','7','3', '\3','5','7','4',
+ '\3','5','7','5', '\3','5','7','6', '\3','5','7','7', '\3','5','7','8', '\3','5','7','9',
+ '\3','5','8','0', '\3','5','8','1', '\3','5','8','2', '\3','5','8','3', '\3','5','8','4',
+ '\3','5','8','5', '\3','5','8','6', '\3','5','8','7', '\3','5','8','8', '\3','5','8','9',
+ '\3','5','9','0', '\3','5','9','1', '\3','5','9','2', '\3','5','9','3', '\3','5','9','4',
+ '\3','5','9','5', '\3','5','9','6', '\3','5','9','7', '\3','5','9','8', '\3','5','9','9',
+ '\3','6','0','0', '\3','6','0','1', '\3','6','0','2', '\3','6','0','3', '\3','6','0','4',
+ '\3','6','0','5', '\3','6','0','6', '\3','6','0','7', '\3','6','0','8', '\3','6','0','9',
+ '\3','6','1','0', '\3','6','1','1', '\3','6','1','2', '\3','6','1','3', '\3','6','1','4',
+ '\3','6','1','5', '\3','6','1','6', '\3','6','1','7', '\3','6','1','8', '\3','6','1','9',
+ '\3','6','2','0', '\3','6','2','1', '\3','6','2','2', '\3','6','2','3', '\3','6','2','4',
+ '\3','6','2','5', '\3','6','2','6', '\3','6','2','7', '\3','6','2','8', '\3','6','2','9',
+ '\3','6','3','0', '\3','6','3','1', '\3','6','3','2', '\3','6','3','3', '\3','6','3','4',
+ '\3','6','3','5', '\3','6','3','6', '\3','6','3','7', '\3','6','3','8', '\3','6','3','9',
+ '\3','6','4','0', '\3','6','4','1', '\3','6','4','2', '\3','6','4','3', '\3','6','4','4',
+ '\3','6','4','5', '\3','6','4','6', '\3','6','4','7', '\3','6','4','8', '\3','6','4','9',
+ '\3','6','5','0', '\3','6','5','1', '\3','6','5','2', '\3','6','5','3', '\3','6','5','4',
+ '\3','6','5','5', '\3','6','5','6', '\3','6','5','7', '\3','6','5','8', '\3','6','5','9',
+ '\3','6','6','0', '\3','6','6','1', '\3','6','6','2', '\3','6','6','3', '\3','6','6','4',
+ '\3','6','6','5', '\3','6','6','6', '\3','6','6','7', '\3','6','6','8', '\3','6','6','9',
+ '\3','6','7','0', '\3','6','7','1', '\3','6','7','2', '\3','6','7','3', '\3','6','7','4',
+ '\3','6','7','5', '\3','6','7','6', '\3','6','7','7', '\3','6','7','8', '\3','6','7','9',
+ '\3','6','8','0', '\3','6','8','1', '\3','6','8','2', '\3','6','8','3', '\3','6','8','4',
+ '\3','6','8','5', '\3','6','8','6', '\3','6','8','7', '\3','6','8','8', '\3','6','8','9',
+ '\3','6','9','0', '\3','6','9','1', '\3','6','9','2', '\3','6','9','3', '\3','6','9','4',
+ '\3','6','9','5', '\3','6','9','6', '\3','6','9','7', '\3','6','9','8', '\3','6','9','9',
+ '\3','7','0','0', '\3','7','0','1', '\3','7','0','2', '\3','7','0','3', '\3','7','0','4',
+ '\3','7','0','5', '\3','7','0','6', '\3','7','0','7', '\3','7','0','8', '\3','7','0','9',
+ '\3','7','1','0', '\3','7','1','1', '\3','7','1','2', '\3','7','1','3', '\3','7','1','4',
+ '\3','7','1','5', '\3','7','1','6', '\3','7','1','7', '\3','7','1','8', '\3','7','1','9',
+ '\3','7','2','0', '\3','7','2','1', '\3','7','2','2', '\3','7','2','3', '\3','7','2','4',
+ '\3','7','2','5', '\3','7','2','6', '\3','7','2','7', '\3','7','2','8', '\3','7','2','9',
+ '\3','7','3','0', '\3','7','3','1', '\3','7','3','2', '\3','7','3','3', '\3','7','3','4',
+ '\3','7','3','5', '\3','7','3','6', '\3','7','3','7', '\3','7','3','8', '\3','7','3','9',
+ '\3','7','4','0', '\3','7','4','1', '\3','7','4','2', '\3','7','4','3', '\3','7','4','4',
+ '\3','7','4','5', '\3','7','4','6', '\3','7','4','7', '\3','7','4','8', '\3','7','4','9',
+ '\3','7','5','0', '\3','7','5','1', '\3','7','5','2', '\3','7','5','3', '\3','7','5','4',
+ '\3','7','5','5', '\3','7','5','6', '\3','7','5','7', '\3','7','5','8', '\3','7','5','9',
+ '\3','7','6','0', '\3','7','6','1', '\3','7','6','2', '\3','7','6','3', '\3','7','6','4',
+ '\3','7','6','5', '\3','7','6','6', '\3','7','6','7', '\3','7','6','8', '\3','7','6','9',
+ '\3','7','7','0', '\3','7','7','1', '\3','7','7','2', '\3','7','7','3', '\3','7','7','4',
+ '\3','7','7','5', '\3','7','7','6', '\3','7','7','7', '\3','7','7','8', '\3','7','7','9',
+ '\3','7','8','0', '\3','7','8','1', '\3','7','8','2', '\3','7','8','3', '\3','7','8','4',
+ '\3','7','8','5', '\3','7','8','6', '\3','7','8','7', '\3','7','8','8', '\3','7','8','9',
+ '\3','7','9','0', '\3','7','9','1', '\3','7','9','2', '\3','7','9','3', '\3','7','9','4',
+ '\3','7','9','5', '\3','7','9','6', '\3','7','9','7', '\3','7','9','8', '\3','7','9','9',
+ '\3','8','0','0', '\3','8','0','1', '\3','8','0','2', '\3','8','0','3', '\3','8','0','4',
+ '\3','8','0','5', '\3','8','0','6', '\3','8','0','7', '\3','8','0','8', '\3','8','0','9',
+ '\3','8','1','0', '\3','8','1','1', '\3','8','1','2', '\3','8','1','3', '\3','8','1','4',
+ '\3','8','1','5', '\3','8','1','6', '\3','8','1','7', '\3','8','1','8', '\3','8','1','9',
+ '\3','8','2','0', '\3','8','2','1', '\3','8','2','2', '\3','8','2','3', '\3','8','2','4',
+ '\3','8','2','5', '\3','8','2','6', '\3','8','2','7', '\3','8','2','8', '\3','8','2','9',
+ '\3','8','3','0', '\3','8','3','1', '\3','8','3','2', '\3','8','3','3', '\3','8','3','4',
+ '\3','8','3','5', '\3','8','3','6', '\3','8','3','7', '\3','8','3','8', '\3','8','3','9',
+ '\3','8','4','0', '\3','8','4','1', '\3','8','4','2', '\3','8','4','3', '\3','8','4','4',
+ '\3','8','4','5', '\3','8','4','6', '\3','8','4','7', '\3','8','4','8', '\3','8','4','9',
+ '\3','8','5','0', '\3','8','5','1', '\3','8','5','2', '\3','8','5','3', '\3','8','5','4',
+ '\3','8','5','5', '\3','8','5','6', '\3','8','5','7', '\3','8','5','8', '\3','8','5','9',
+ '\3','8','6','0', '\3','8','6','1', '\3','8','6','2', '\3','8','6','3', '\3','8','6','4',
+ '\3','8','6','5', '\3','8','6','6', '\3','8','6','7', '\3','8','6','8', '\3','8','6','9',
+ '\3','8','7','0', '\3','8','7','1', '\3','8','7','2', '\3','8','7','3', '\3','8','7','4',
+ '\3','8','7','5', '\3','8','7','6', '\3','8','7','7', '\3','8','7','8', '\3','8','7','9',
+ '\3','8','8','0', '\3','8','8','1', '\3','8','8','2', '\3','8','8','3', '\3','8','8','4',
+ '\3','8','8','5', '\3','8','8','6', '\3','8','8','7', '\3','8','8','8', '\3','8','8','9',
+ '\3','8','9','0', '\3','8','9','1', '\3','8','9','2', '\3','8','9','3', '\3','8','9','4',
+ '\3','8','9','5', '\3','8','9','6', '\3','8','9','7', '\3','8','9','8', '\3','8','9','9',
+ '\3','9','0','0', '\3','9','0','1', '\3','9','0','2', '\3','9','0','3', '\3','9','0','4',
+ '\3','9','0','5', '\3','9','0','6', '\3','9','0','7', '\3','9','0','8', '\3','9','0','9',
+ '\3','9','1','0', '\3','9','1','1', '\3','9','1','2', '\3','9','1','3', '\3','9','1','4',
+ '\3','9','1','5', '\3','9','1','6', '\3','9','1','7', '\3','9','1','8', '\3','9','1','9',
+ '\3','9','2','0', '\3','9','2','1', '\3','9','2','2', '\3','9','2','3', '\3','9','2','4',
+ '\3','9','2','5', '\3','9','2','6', '\3','9','2','7', '\3','9','2','8', '\3','9','2','9',
+ '\3','9','3','0', '\3','9','3','1', '\3','9','3','2', '\3','9','3','3', '\3','9','3','4',
+ '\3','9','3','5', '\3','9','3','6', '\3','9','3','7', '\3','9','3','8', '\3','9','3','9',
+ '\3','9','4','0', '\3','9','4','1', '\3','9','4','2', '\3','9','4','3', '\3','9','4','4',
+ '\3','9','4','5', '\3','9','4','6', '\3','9','4','7', '\3','9','4','8', '\3','9','4','9',
+ '\3','9','5','0', '\3','9','5','1', '\3','9','5','2', '\3','9','5','3', '\3','9','5','4',
+ '\3','9','5','5', '\3','9','5','6', '\3','9','5','7', '\3','9','5','8', '\3','9','5','9',
+ '\3','9','6','0', '\3','9','6','1', '\3','9','6','2', '\3','9','6','3', '\3','9','6','4',
+ '\3','9','6','5', '\3','9','6','6', '\3','9','6','7', '\3','9','6','8', '\3','9','6','9',
+ '\3','9','7','0', '\3','9','7','1', '\3','9','7','2', '\3','9','7','3', '\3','9','7','4',
+ '\3','9','7','5', '\3','9','7','6', '\3','9','7','7', '\3','9','7','8', '\3','9','7','9',
+ '\3','9','8','0', '\3','9','8','1', '\3','9','8','2', '\3','9','8','3', '\3','9','8','4',
+ '\3','9','8','5', '\3','9','8','6', '\3','9','8','7', '\3','9','8','8', '\3','9','8','9',
+ '\3','9','9','0', '\3','9','9','1', '\3','9','9','2', '\3','9','9','3', '\3','9','9','4',
+ '\3','9','9','5', '\3','9','9','6', '\3','9','9','7', '\3','9','9','8', '\3','9','9','9', '\0'};
 #endif
 
-#if DEC_DPD2BIN==1
+#if defined(DEC_DPD2BCD8) && DEC_DPD2BCD8==1 && !defined(DECDPD2BCD8)
+#define DECDPD2BCD8
 
-const uint16_t DPD2BIN[1024] = { 0, 1, 2, 3, 4, 5, 6, 7,
-  8, 9, 80, 81, 800, 801, 880, 881, 10, 11, 12, 13, 14,
-  15, 16, 17, 18, 19, 90, 91, 810, 811, 890, 891, 20, 21,
-  22, 23, 24, 25, 26, 27, 28, 29, 82, 83, 820, 821, 808,
-  809, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 92, 93,
-  830, 831, 818, 819, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-  49, 84, 85, 840, 841, 88, 89, 50, 51, 52, 53, 54, 55,
-  56, 57, 58, 59, 94, 95, 850, 851, 98, 99, 60, 61, 62,
-  63, 64, 65, 66, 67, 68, 69, 86, 87, 860, 861, 888, 889,
-  70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 96, 97, 870,
-  871, 898, 899, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-  180, 181, 900, 901, 980, 981, 110, 111, 112, 113, 114, 115, 116,
-  117, 118, 119, 190, 191, 910, 911, 990, 991, 120, 121, 122, 123,
-  124, 125, 126, 127, 128, 129, 182, 183, 920, 921, 908, 909, 130,
-  131, 132, 133, 134, 135, 136, 137, 138, 139, 192, 193, 930, 931,
-  918, 919, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 184,
-  185, 940, 941, 188, 189, 150, 151, 152, 153, 154, 155, 156, 157,
-  158, 159, 194, 195, 950, 951, 198, 199, 160, 161, 162, 163, 164,
-  165, 166, 167, 168, 169, 186, 187, 960, 961, 988, 989, 170, 171,
-  172, 173, 174, 175, 176, 177, 178, 179, 196, 197, 970, 971, 998,
-  999, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 280, 281,
-  802, 803, 882, 883, 210, 211, 212, 213, 214, 215, 216, 217, 218,
-  219, 290, 291, 812, 813, 892, 893, 220, 221, 222, 223, 224, 225,
-  226, 227, 228, 229, 282, 283, 822, 823, 828, 829, 230, 231, 232,
-  233, 234, 235, 236, 237, 238, 239, 292, 293, 832, 833, 838, 839,
-  240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 284, 285, 842,
-  843, 288, 289, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
-  294, 295, 852, 853, 298, 299, 260, 261, 262, 263, 264, 265, 266,
-  267, 268, 269, 286, 287, 862, 863, 888, 889, 270, 271, 272, 273,
-  274, 275, 276, 277, 278, 279, 296, 297, 872, 873, 898, 899, 300,
-  301, 302, 303, 304, 305, 306, 307, 308, 309, 380, 381, 902, 903,
-  982, 983, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 390,
-  391, 912, 913, 992, 993, 320, 321, 322, 323, 324, 325, 326, 327,
-  328, 329, 382, 383, 922, 923, 928, 929, 330, 331, 332, 333, 334,
-  335, 336, 337, 338, 339, 392, 393, 932, 933, 938, 939, 340, 341,
-  342, 343, 344, 345, 346, 347, 348, 349, 384, 385, 942, 943, 388,
-  389, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 394, 395,
-  952, 953, 398, 399, 360, 361, 362, 363, 364, 365, 366, 367, 368,
-  369, 386, 387, 962, 963, 988, 989, 370, 371, 372, 373, 374, 375,
-  376, 377, 378, 379, 396, 397, 972, 973, 998, 999, 400, 401, 402,
-  403, 404, 405, 406, 407, 408, 409, 480, 481, 804, 805, 884, 885,
-  410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 490, 491, 814,
-  815, 894, 895, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429,
-  482, 483, 824, 825, 848, 849, 430, 431, 432, 433, 434, 435, 436,
-  437, 438, 439, 492, 493, 834, 835, 858, 859, 440, 441, 442, 443,
-  444, 445, 446, 447, 448, 449, 484, 485, 844, 845, 488, 489, 450,
-  451, 452, 453, 454, 455, 456, 457, 458, 459, 494, 495, 854, 855,
-  498, 499, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 486,
-  487, 864, 865, 888, 889, 470, 471, 472, 473, 474, 475, 476, 477,
-  478, 479, 496, 497, 874, 875, 898, 899, 500, 501, 502, 503, 504,
-  505, 506, 507, 508, 509, 580, 581, 904, 905, 984, 985, 510, 511,
-  512, 513, 514, 515, 516, 517, 518, 519, 590, 591, 914, 915, 994,
-  995, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 582, 583,
-  924, 925, 948, 949, 530, 531, 532, 533, 534, 535, 536, 537, 538,
-  539, 592, 593, 934, 935, 958, 959, 540, 541, 542, 543, 544, 545,
-  546, 547, 548, 549, 584, 585, 944, 945, 588, 589, 550, 551, 552,
-  553, 554, 555, 556, 557, 558, 559, 594, 595, 954, 955, 598, 599,
-  560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 586, 587, 964,
-  965, 988, 989, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579,
-  596, 597, 974, 975, 998, 999, 600, 601, 602, 603, 604, 605, 606,
-  607, 608, 609, 680, 681, 806, 807, 886, 887, 610, 611, 612, 613,
-  614, 615, 616, 617, 618, 619, 690, 691, 816, 817, 896, 897, 620,
-  621, 622, 623, 624, 625, 626, 627, 628, 629, 682, 683, 826, 827,
-  868, 869, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 692,
-  693, 836, 837, 878, 879, 640, 641, 642, 643, 644, 645, 646, 647,
-  648, 649, 684, 685, 846, 847, 688, 689, 650, 651, 652, 653, 654,
-  655, 656, 657, 658, 659, 694, 695, 856, 857, 698, 699, 660, 661,
-  662, 663, 664, 665, 666, 667, 668, 669, 686, 687, 866, 867, 888,
-  889, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 696, 697,
-  876, 877, 898, 899, 700, 701, 702, 703, 704, 705, 706, 707, 708,
-  709, 780, 781, 906, 907, 986, 987, 710, 711, 712, 713, 714, 715,
-  716, 717, 718, 719, 790, 791, 916, 917, 996, 997, 720, 721, 722,
-  723, 724, 725, 726, 727, 728, 729, 782, 783, 926, 927, 968, 969,
-  730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 792, 793, 936,
-  937, 978, 979, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749,
-  784, 785, 946, 947, 788, 789, 750, 751, 752, 753, 754, 755, 756,
-  757, 758, 759, 794, 795, 956, 957, 798, 799, 760, 761, 762, 763,
-  764, 765, 766, 767, 768, 769, 786, 787, 966, 967, 988, 989, 770,
-  771, 772, 773, 774, 775, 776, 777, 778, 779, 796, 797, 976, 977,
-  998, 999
-};
+const uint8_t DPD2BCD8[4096]={
+ 0,0,0,0, 0,0,1,1, 0,0,2,1, 0,0,3,1, 0,0,4,1, 0,0,5,1, 0,0,6,1, 0,0,7,1, 0,0,8,1,
+ 0,0,9,1, 0,8,0,2, 0,8,1,2, 8,0,0,3, 8,0,1,3, 8,8,0,3, 8,8,1,3, 0,1,0,2, 0,1,1,2,
+ 0,1,2,2, 0,1,3,2, 0,1,4,2, 0,1,5,2, 0,1,6,2, 0,1,7,2, 0,1,8,2, 0,1,9,2, 0,9,0,2,
+ 0,9,1,2, 8,1,0,3, 8,1,1,3, 8,9,0,3, 8,9,1,3, 0,2,0,2, 0,2,1,2, 0,2,2,2, 0,2,3,2,
+ 0,2,4,2, 0,2,5,2, 0,2,6,2, 0,2,7,2, 0,2,8,2, 0,2,9,2, 0,8,2,2, 0,8,3,2, 8,2,0,3,
+ 8,2,1,3, 8,0,8,3, 8,0,9,3, 0,3,0,2, 0,3,1,2, 0,3,2,2, 0,3,3,2, 0,3,4,2, 0,3,5,2,
+ 0,3,6,2, 0,3,7,2, 0,3,8,2, 0,3,9,2, 0,9,2,2, 0,9,3,2, 8,3,0,3, 8,3,1,3, 8,1,8,3,
+ 8,1,9,3, 0,4,0,2, 0,4,1,2, 0,4,2,2, 0,4,3,2, 0,4,4,2, 0,4,5,2, 0,4,6,2, 0,4,7,2,
+ 0,4,8,2, 0,4,9,2, 0,8,4,2, 0,8,5,2, 8,4,0,3, 8,4,1,3, 0,8,8,2, 0,8,9,2, 0,5,0,2,
+ 0,5,1,2, 0,5,2,2, 0,5,3,2, 0,5,4,2, 0,5,5,2, 0,5,6,2, 0,5,7,2, 0,5,8,2, 0,5,9,2,
+ 0,9,4,2, 0,9,5,2, 8,5,0,3, 8,5,1,3, 0,9,8,2, 0,9,9,2, 0,6,0,2, 0,6,1,2, 0,6,2,2,
+ 0,6,3,2, 0,6,4,2, 0,6,5,2, 0,6,6,2, 0,6,7,2, 0,6,8,2, 0,6,9,2, 0,8,6,2, 0,8,7,2,
+ 8,6,0,3, 8,6,1,3, 8,8,8,3, 8,8,9,3, 0,7,0,2, 0,7,1,2, 0,7,2,2, 0,7,3,2, 0,7,4,2,
+ 0,7,5,2, 0,7,6,2, 0,7,7,2, 0,7,8,2, 0,7,9,2, 0,9,6,2, 0,9,7,2, 8,7,0,3, 8,7,1,3,
+ 8,9,8,3, 8,9,9,3, 1,0,0,3, 1,0,1,3, 1,0,2,3, 1,0,3,3, 1,0,4,3, 1,0,5,3, 1,0,6,3,
+ 1,0,7,3, 1,0,8,3, 1,0,9,3, 1,8,0,3, 1,8,1,3, 9,0,0,3, 9,0,1,3, 9,8,0,3, 9,8,1,3,
+ 1,1,0,3, 1,1,1,3, 1,1,2,3, 1,1,3,3, 1,1,4,3, 1,1,5,3, 1,1,6,3, 1,1,7,3, 1,1,8,3,
+ 1,1,9,3, 1,9,0,3, 1,9,1,3, 9,1,0,3, 9,1,1,3, 9,9,0,3, 9,9,1,3, 1,2,0,3, 1,2,1,3,
+ 1,2,2,3, 1,2,3,3, 1,2,4,3, 1,2,5,3, 1,2,6,3, 1,2,7,3, 1,2,8,3, 1,2,9,3, 1,8,2,3,
+ 1,8,3,3, 9,2,0,3, 9,2,1,3, 9,0,8,3, 9,0,9,3, 1,3,0,3, 1,3,1,3, 1,3,2,3, 1,3,3,3,
+ 1,3,4,3, 1,3,5,3, 1,3,6,3, 1,3,7,3, 1,3,8,3, 1,3,9,3, 1,9,2,3, 1,9,3,3, 9,3,0,3,
+ 9,3,1,3, 9,1,8,3, 9,1,9,3, 1,4,0,3, 1,4,1,3, 1,4,2,3, 1,4,3,3, 1,4,4,3, 1,4,5,3,
+ 1,4,6,3, 1,4,7,3, 1,4,8,3, 1,4,9,3, 1,8,4,3, 1,8,5,3, 9,4,0,3, 9,4,1,3, 1,8,8,3,
+ 1,8,9,3, 1,5,0,3, 1,5,1,3, 1,5,2,3, 1,5,3,3, 1,5,4,3, 1,5,5,3, 1,5,6,3, 1,5,7,3,
+ 1,5,8,3, 1,5,9,3, 1,9,4,3, 1,9,5,3, 9,5,0,3, 9,5,1,3, 1,9,8,3, 1,9,9,3, 1,6,0,3,
+ 1,6,1,3, 1,6,2,3, 1,6,3,3, 1,6,4,3, 1,6,5,3, 1,6,6,3, 1,6,7,3, 1,6,8,3, 1,6,9,3,
+ 1,8,6,3, 1,8,7,3, 9,6,0,3, 9,6,1,3, 9,8,8,3, 9,8,9,3, 1,7,0,3, 1,7,1,3, 1,7,2,3,
+ 1,7,3,3, 1,7,4,3, 1,7,5,3, 1,7,6,3, 1,7,7,3, 1,7,8,3, 1,7,9,3, 1,9,6,3, 1,9,7,3,
+ 9,7,0,3, 9,7,1,3, 9,9,8,3, 9,9,9,3, 2,0,0,3, 2,0,1,3, 2,0,2,3, 2,0,3,3, 2,0,4,3,
+ 2,0,5,3, 2,0,6,3, 2,0,7,3, 2,0,8,3, 2,0,9,3, 2,8,0,3, 2,8,1,3, 8,0,2,3, 8,0,3,3,
+ 8,8,2,3, 8,8,3,3, 2,1,0,3, 2,1,1,3, 2,1,2,3, 2,1,3,3, 2,1,4,3, 2,1,5,3, 2,1,6,3,
+ 2,1,7,3, 2,1,8,3, 2,1,9,3, 2,9,0,3, 2,9,1,3, 8,1,2,3, 8,1,3,3, 8,9,2,3, 8,9,3,3,
+ 2,2,0,3, 2,2,1,3, 2,2,2,3, 2,2,3,3, 2,2,4,3, 2,2,5,3, 2,2,6,3, 2,2,7,3, 2,2,8,3,
+ 2,2,9,3, 2,8,2,3, 2,8,3,3, 8,2,2,3, 8,2,3,3, 8,2,8,3, 8,2,9,3, 2,3,0,3, 2,3,1,3,
+ 2,3,2,3, 2,3,3,3, 2,3,4,3, 2,3,5,3, 2,3,6,3, 2,3,7,3, 2,3,8,3, 2,3,9,3, 2,9,2,3,
+ 2,9,3,3, 8,3,2,3, 8,3,3,3, 8,3,8,3, 8,3,9,3, 2,4,0,3, 2,4,1,3, 2,4,2,3, 2,4,3,3,
+ 2,4,4,3, 2,4,5,3, 2,4,6,3, 2,4,7,3, 2,4,8,3, 2,4,9,3, 2,8,4,3, 2,8,5,3, 8,4,2,3,
+ 8,4,3,3, 2,8,8,3, 2,8,9,3, 2,5,0,3, 2,5,1,3, 2,5,2,3, 2,5,3,3, 2,5,4,3, 2,5,5,3,
+ 2,5,6,3, 2,5,7,3, 2,5,8,3, 2,5,9,3, 2,9,4,3, 2,9,5,3, 8,5,2,3, 8,5,3,3, 2,9,8,3,
+ 2,9,9,3, 2,6,0,3, 2,6,1,3, 2,6,2,3, 2,6,3,3, 2,6,4,3, 2,6,5,3, 2,6,6,3, 2,6,7,3,
+ 2,6,8,3, 2,6,9,3, 2,8,6,3, 2,8,7,3, 8,6,2,3, 8,6,3,3, 8,8,8,3, 8,8,9,3, 2,7,0,3,
+ 2,7,1,3, 2,7,2,3, 2,7,3,3, 2,7,4,3, 2,7,5,3, 2,7,6,3, 2,7,7,3, 2,7,8,3, 2,7,9,3,
+ 2,9,6,3, 2,9,7,3, 8,7,2,3, 8,7,3,3, 8,9,8,3, 8,9,9,3, 3,0,0,3, 3,0,1,3, 3,0,2,3,
+ 3,0,3,3, 3,0,4,3, 3,0,5,3, 3,0,6,3, 3,0,7,3, 3,0,8,3, 3,0,9,3, 3,8,0,3, 3,8,1,3,
+ 9,0,2,3, 9,0,3,3, 9,8,2,3, 9,8,3,3, 3,1,0,3, 3,1,1,3, 3,1,2,3, 3,1,3,3, 3,1,4,3,
+ 3,1,5,3, 3,1,6,3, 3,1,7,3, 3,1,8,3, 3,1,9,3, 3,9,0,3, 3,9,1,3, 9,1,2,3, 9,1,3,3,
+ 9,9,2,3, 9,9,3,3, 3,2,0,3, 3,2,1,3, 3,2,2,3, 3,2,3,3, 3,2,4,3, 3,2,5,3, 3,2,6,3,
+ 3,2,7,3, 3,2,8,3, 3,2,9,3, 3,8,2,3, 3,8,3,3, 9,2,2,3, 9,2,3,3, 9,2,8,3, 9,2,9,3,
+ 3,3,0,3, 3,3,1,3, 3,3,2,3, 3,3,3,3, 3,3,4,3, 3,3,5,3, 3,3,6,3, 3,3,7,3, 3,3,8,3,
+ 3,3,9,3, 3,9,2,3, 3,9,3,3, 9,3,2,3, 9,3,3,3, 9,3,8,3, 9,3,9,3, 3,4,0,3, 3,4,1,3,
+ 3,4,2,3, 3,4,3,3, 3,4,4,3, 3,4,5,3, 3,4,6,3, 3,4,7,3, 3,4,8,3, 3,4,9,3, 3,8,4,3,
+ 3,8,5,3, 9,4,2,3, 9,4,3,3, 3,8,8,3, 3,8,9,3, 3,5,0,3, 3,5,1,3, 3,5,2,3, 3,5,3,3,
+ 3,5,4,3, 3,5,5,3, 3,5,6,3, 3,5,7,3, 3,5,8,3, 3,5,9,3, 3,9,4,3, 3,9,5,3, 9,5,2,3,
+ 9,5,3,3, 3,9,8,3, 3,9,9,3, 3,6,0,3, 3,6,1,3, 3,6,2,3, 3,6,3,3, 3,6,4,3, 3,6,5,3,
+ 3,6,6,3, 3,6,7,3, 3,6,8,3, 3,6,9,3, 3,8,6,3, 3,8,7,3, 9,6,2,3, 9,6,3,3, 9,8,8,3,
+ 9,8,9,3, 3,7,0,3, 3,7,1,3, 3,7,2,3, 3,7,3,3, 3,7,4,3, 3,7,5,3, 3,7,6,3, 3,7,7,3,
+ 3,7,8,3, 3,7,9,3, 3,9,6,3, 3,9,7,3, 9,7,2,3, 9,7,3,3, 9,9,8,3, 9,9,9,3, 4,0,0,3,
+ 4,0,1,3, 4,0,2,3, 4,0,3,3, 4,0,4,3, 4,0,5,3, 4,0,6,3, 4,0,7,3, 4,0,8,3, 4,0,9,3,
+ 4,8,0,3, 4,8,1,3, 8,0,4,3, 8,0,5,3, 8,8,4,3, 8,8,5,3, 4,1,0,3, 4,1,1,3, 4,1,2,3,
+ 4,1,3,3, 4,1,4,3, 4,1,5,3, 4,1,6,3, 4,1,7,3, 4,1,8,3, 4,1,9,3, 4,9,0,3, 4,9,1,3,
+ 8,1,4,3, 8,1,5,3, 8,9,4,3, 8,9,5,3, 4,2,0,3, 4,2,1,3, 4,2,2,3, 4,2,3,3, 4,2,4,3,
+ 4,2,5,3, 4,2,6,3, 4,2,7,3, 4,2,8,3, 4,2,9,3, 4,8,2,3, 4,8,3,3, 8,2,4,3, 8,2,5,3,
+ 8,4,8,3, 8,4,9,3, 4,3,0,3, 4,3,1,3, 4,3,2,3, 4,3,3,3, 4,3,4,3, 4,3,5,3, 4,3,6,3,
+ 4,3,7,3, 4,3,8,3, 4,3,9,3, 4,9,2,3, 4,9,3,3, 8,3,4,3, 8,3,5,3, 8,5,8,3, 8,5,9,3,
+ 4,4,0,3, 4,4,1,3, 4,4,2,3, 4,4,3,3, 4,4,4,3, 4,4,5,3, 4,4,6,3, 4,4,7,3, 4,4,8,3,
+ 4,4,9,3, 4,8,4,3, 4,8,5,3, 8,4,4,3, 8,4,5,3, 4,8,8,3, 4,8,9,3, 4,5,0,3, 4,5,1,3,
+ 4,5,2,3, 4,5,3,3, 4,5,4,3, 4,5,5,3, 4,5,6,3, 4,5,7,3, 4,5,8,3, 4,5,9,3, 4,9,4,3,
+ 4,9,5,3, 8,5,4,3, 8,5,5,3, 4,9,8,3, 4,9,9,3, 4,6,0,3, 4,6,1,3, 4,6,2,3, 4,6,3,3,
+ 4,6,4,3, 4,6,5,3, 4,6,6,3, 4,6,7,3, 4,6,8,3, 4,6,9,3, 4,8,6,3, 4,8,7,3, 8,6,4,3,
+ 8,6,5,3, 8,8,8,3, 8,8,9,3, 4,7,0,3, 4,7,1,3, 4,7,2,3, 4,7,3,3, 4,7,4,3, 4,7,5,3,
+ 4,7,6,3, 4,7,7,3, 4,7,8,3, 4,7,9,3, 4,9,6,3, 4,9,7,3, 8,7,4,3, 8,7,5,3, 8,9,8,3,
+ 8,9,9,3, 5,0,0,3, 5,0,1,3, 5,0,2,3, 5,0,3,3, 5,0,4,3, 5,0,5,3, 5,0,6,3, 5,0,7,3,
+ 5,0,8,3, 5,0,9,3, 5,8,0,3, 5,8,1,3, 9,0,4,3, 9,0,5,3, 9,8,4,3, 9,8,5,3, 5,1,0,3,
+ 5,1,1,3, 5,1,2,3, 5,1,3,3, 5,1,4,3, 5,1,5,3, 5,1,6,3, 5,1,7,3, 5,1,8,3, 5,1,9,3,
+ 5,9,0,3, 5,9,1,3, 9,1,4,3, 9,1,5,3, 9,9,4,3, 9,9,5,3, 5,2,0,3, 5,2,1,3, 5,2,2,3,
+ 5,2,3,3, 5,2,4,3, 5,2,5,3, 5,2,6,3, 5,2,7,3, 5,2,8,3, 5,2,9,3, 5,8,2,3, 5,8,3,3,
+ 9,2,4,3, 9,2,5,3, 9,4,8,3, 9,4,9,3, 5,3,0,3, 5,3,1,3, 5,3,2,3, 5,3,3,3, 5,3,4,3,
+ 5,3,5,3, 5,3,6,3, 5,3,7,3, 5,3,8,3, 5,3,9,3, 5,9,2,3, 5,9,3,3, 9,3,4,3, 9,3,5,3,
+ 9,5,8,3, 9,5,9,3, 5,4,0,3, 5,4,1,3, 5,4,2,3, 5,4,3,3, 5,4,4,3, 5,4,5,3, 5,4,6,3,
+ 5,4,7,3, 5,4,8,3, 5,4,9,3, 5,8,4,3, 5,8,5,3, 9,4,4,3, 9,4,5,3, 5,8,8,3, 5,8,9,3,
+ 5,5,0,3, 5,5,1,3, 5,5,2,3, 5,5,3,3, 5,5,4,3, 5,5,5,3, 5,5,6,3, 5,5,7,3, 5,5,8,3,
+ 5,5,9,3, 5,9,4,3, 5,9,5,3, 9,5,4,3, 9,5,5,3, 5,9,8,3, 5,9,9,3, 5,6,0,3, 5,6,1,3,
+ 5,6,2,3, 5,6,3,3, 5,6,4,3, 5,6,5,3, 5,6,6,3, 5,6,7,3, 5,6,8,3, 5,6,9,3, 5,8,6,3,
+ 5,8,7,3, 9,6,4,3, 9,6,5,3, 9,8,8,3, 9,8,9,3, 5,7,0,3, 5,7,1,3, 5,7,2,3, 5,7,3,3,
+ 5,7,4,3, 5,7,5,3, 5,7,6,3, 5,7,7,3, 5,7,8,3, 5,7,9,3, 5,9,6,3, 5,9,7,3, 9,7,4,3,
+ 9,7,5,3, 9,9,8,3, 9,9,9,3, 6,0,0,3, 6,0,1,3, 6,0,2,3, 6,0,3,3, 6,0,4,3, 6,0,5,3,
+ 6,0,6,3, 6,0,7,3, 6,0,8,3, 6,0,9,3, 6,8,0,3, 6,8,1,3, 8,0,6,3, 8,0,7,3, 8,8,6,3,
+ 8,8,7,3, 6,1,0,3, 6,1,1,3, 6,1,2,3, 6,1,3,3, 6,1,4,3, 6,1,5,3, 6,1,6,3, 6,1,7,3,
+ 6,1,8,3, 6,1,9,3, 6,9,0,3, 6,9,1,3, 8,1,6,3, 8,1,7,3, 8,9,6,3, 8,9,7,3, 6,2,0,3,
+ 6,2,1,3, 6,2,2,3, 6,2,3,3, 6,2,4,3, 6,2,5,3, 6,2,6,3, 6,2,7,3, 6,2,8,3, 6,2,9,3,
+ 6,8,2,3, 6,8,3,3, 8,2,6,3, 8,2,7,3, 8,6,8,3, 8,6,9,3, 6,3,0,3, 6,3,1,3, 6,3,2,3,
+ 6,3,3,3, 6,3,4,3, 6,3,5,3, 6,3,6,3, 6,3,7,3, 6,3,8,3, 6,3,9,3, 6,9,2,3, 6,9,3,3,
+ 8,3,6,3, 8,3,7,3, 8,7,8,3, 8,7,9,3, 6,4,0,3, 6,4,1,3, 6,4,2,3, 6,4,3,3, 6,4,4,3,
+ 6,4,5,3, 6,4,6,3, 6,4,7,3, 6,4,8,3, 6,4,9,3, 6,8,4,3, 6,8,5,3, 8,4,6,3, 8,4,7,3,
+ 6,8,8,3, 6,8,9,3, 6,5,0,3, 6,5,1,3, 6,5,2,3, 6,5,3,3, 6,5,4,3, 6,5,5,3, 6,5,6,3,
+ 6,5,7,3, 6,5,8,3, 6,5,9,3, 6,9,4,3, 6,9,5,3, 8,5,6,3, 8,5,7,3, 6,9,8,3, 6,9,9,3,
+ 6,6,0,3, 6,6,1,3, 6,6,2,3, 6,6,3,3, 6,6,4,3, 6,6,5,3, 6,6,6,3, 6,6,7,3, 6,6,8,3,
+ 6,6,9,3, 6,8,6,3, 6,8,7,3, 8,6,6,3, 8,6,7,3, 8,8,8,3, 8,8,9,3, 6,7,0,3, 6,7,1,3,
+ 6,7,2,3, 6,7,3,3, 6,7,4,3, 6,7,5,3, 6,7,6,3, 6,7,7,3, 6,7,8,3, 6,7,9,3, 6,9,6,3,
+ 6,9,7,3, 8,7,6,3, 8,7,7,3, 8,9,8,3, 8,9,9,3, 7,0,0,3, 7,0,1,3, 7,0,2,3, 7,0,3,3,
+ 7,0,4,3, 7,0,5,3, 7,0,6,3, 7,0,7,3, 7,0,8,3, 7,0,9,3, 7,8,0,3, 7,8,1,3, 9,0,6,3,
+ 9,0,7,3, 9,8,6,3, 9,8,7,3, 7,1,0,3, 7,1,1,3, 7,1,2,3, 7,1,3,3, 7,1,4,3, 7,1,5,3,
+ 7,1,6,3, 7,1,7,3, 7,1,8,3, 7,1,9,3, 7,9,0,3, 7,9,1,3, 9,1,6,3, 9,1,7,3, 9,9,6,3,
+ 9,9,7,3, 7,2,0,3, 7,2,1,3, 7,2,2,3, 7,2,3,3, 7,2,4,3, 7,2,5,3, 7,2,6,3, 7,2,7,3,
+ 7,2,8,3, 7,2,9,3, 7,8,2,3, 7,8,3,3, 9,2,6,3, 9,2,7,3, 9,6,8,3, 9,6,9,3, 7,3,0,3,
+ 7,3,1,3, 7,3,2,3, 7,3,3,3, 7,3,4,3, 7,3,5,3, 7,3,6,3, 7,3,7,3, 7,3,8,3, 7,3,9,3,
+ 7,9,2,3, 7,9,3,3, 9,3,6,3, 9,3,7,3, 9,7,8,3, 9,7,9,3, 7,4,0,3, 7,4,1,3, 7,4,2,3,
+ 7,4,3,3, 7,4,4,3, 7,4,5,3, 7,4,6,3, 7,4,7,3, 7,4,8,3, 7,4,9,3, 7,8,4,3, 7,8,5,3,
+ 9,4,6,3, 9,4,7,3, 7,8,8,3, 7,8,9,3, 7,5,0,3, 7,5,1,3, 7,5,2,3, 7,5,3,3, 7,5,4,3,
+ 7,5,5,3, 7,5,6,3, 7,5,7,3, 7,5,8,3, 7,5,9,3, 7,9,4,3, 7,9,5,3, 9,5,6,3, 9,5,7,3,
+ 7,9,8,3, 7,9,9,3, 7,6,0,3, 7,6,1,3, 7,6,2,3, 7,6,3,3, 7,6,4,3, 7,6,5,3, 7,6,6,3,
+ 7,6,7,3, 7,6,8,3, 7,6,9,3, 7,8,6,3, 7,8,7,3, 9,6,6,3, 9,6,7,3, 9,8,8,3, 9,8,9,3,
+ 7,7,0,3, 7,7,1,3, 7,7,2,3, 7,7,3,3, 7,7,4,3, 7,7,5,3, 7,7,6,3, 7,7,7,3, 7,7,8,3,
+ 7,7,9,3, 7,9,6,3, 7,9,7,3, 9,7,6,3, 9,7,7,3, 9,9,8,3, 9,9,9,3};
 #endif
+
+#if defined(DEC_BIN2BCD8) && DEC_BIN2BCD8==1 && !defined(DECBIN2BCD8)
+#define DECBIN2BCD8
+
+const uint8_t BIN2BCD8[4000]={
+ 0,0,0,0, 0,0,1,1, 0,0,2,1, 0,0,3,1, 0,0,4,1, 0,0,5,1, 0,0,6,1, 0,0,7,1, 0,0,8,1,
+ 0,0,9,1, 0,1,0,2, 0,1,1,2, 0,1,2,2, 0,1,3,2, 0,1,4,2, 0,1,5,2, 0,1,6,2, 0,1,7,2,
+ 0,1,8,2, 0,1,9,2, 0,2,0,2, 0,2,1,2, 0,2,2,2, 0,2,3,2, 0,2,4,2, 0,2,5,2, 0,2,6,2,
+ 0,2,7,2, 0,2,8,2, 0,2,9,2, 0,3,0,2, 0,3,1,2, 0,3,2,2, 0,3,3,2, 0,3,4,2, 0,3,5,2,
+ 0,3,6,2, 0,3,7,2, 0,3,8,2, 0,3,9,2, 0,4,0,2, 0,4,1,2, 0,4,2,2, 0,4,3,2, 0,4,4,2,
+ 0,4,5,2, 0,4,6,2, 0,4,7,2, 0,4,8,2, 0,4,9,2, 0,5,0,2, 0,5,1,2, 0,5,2,2, 0,5,3,2,
+ 0,5,4,2, 0,5,5,2, 0,5,6,2, 0,5,7,2, 0,5,8,2, 0,5,9,2, 0,6,0,2, 0,6,1,2, 0,6,2,2,
+ 0,6,3,2, 0,6,4,2, 0,6,5,2, 0,6,6,2, 0,6,7,2, 0,6,8,2, 0,6,9,2, 0,7,0,2, 0,7,1,2,
+ 0,7,2,2, 0,7,3,2, 0,7,4,2, 0,7,5,2, 0,7,6,2, 0,7,7,2, 0,7,8,2, 0,7,9,2, 0,8,0,2,
+ 0,8,1,2, 0,8,2,2, 0,8,3,2, 0,8,4,2, 0,8,5,2, 0,8,6,2, 0,8,7,2, 0,8,8,2, 0,8,9,2,
+ 0,9,0,2, 0,9,1,2, 0,9,2,2, 0,9,3,2, 0,9,4,2, 0,9,5,2, 0,9,6,2, 0,9,7,2, 0,9,8,2,
+ 0,9,9,2, 1,0,0,3, 1,0,1,3, 1,0,2,3, 1,0,3,3, 1,0,4,3, 1,0,5,3, 1,0,6,3, 1,0,7,3,
+ 1,0,8,3, 1,0,9,3, 1,1,0,3, 1,1,1,3, 1,1,2,3, 1,1,3,3, 1,1,4,3, 1,1,5,3, 1,1,6,3,
+ 1,1,7,3, 1,1,8,3, 1,1,9,3, 1,2,0,3, 1,2,1,3, 1,2,2,3, 1,2,3,3, 1,2,4,3, 1,2,5,3,
+ 1,2,6,3, 1,2,7,3, 1,2,8,3, 1,2,9,3, 1,3,0,3, 1,3,1,3, 1,3,2,3, 1,3,3,3, 1,3,4,3,
+ 1,3,5,3, 1,3,6,3, 1,3,7,3, 1,3,8,3, 1,3,9,3, 1,4,0,3, 1,4,1,3, 1,4,2,3, 1,4,3,3,
+ 1,4,4,3, 1,4,5,3, 1,4,6,3, 1,4,7,3, 1,4,8,3, 1,4,9,3, 1,5,0,3, 1,5,1,3, 1,5,2,3,
+ 1,5,3,3, 1,5,4,3, 1,5,5,3, 1,5,6,3, 1,5,7,3, 1,5,8,3, 1,5,9,3, 1,6,0,3, 1,6,1,3,
+ 1,6,2,3, 1,6,3,3, 1,6,4,3, 1,6,5,3, 1,6,6,3, 1,6,7,3, 1,6,8,3, 1,6,9,3, 1,7,0,3,
+ 1,7,1,3, 1,7,2,3, 1,7,3,3, 1,7,4,3, 1,7,5,3, 1,7,6,3, 1,7,7,3, 1,7,8,3, 1,7,9,3,
+ 1,8,0,3, 1,8,1,3, 1,8,2,3, 1,8,3,3, 1,8,4,3, 1,8,5,3, 1,8,6,3, 1,8,7,3, 1,8,8,3,
+ 1,8,9,3, 1,9,0,3, 1,9,1,3, 1,9,2,3, 1,9,3,3, 1,9,4,3, 1,9,5,3, 1,9,6,3, 1,9,7,3,
+ 1,9,8,3, 1,9,9,3, 2,0,0,3, 2,0,1,3, 2,0,2,3, 2,0,3,3, 2,0,4,3, 2,0,5,3, 2,0,6,3,
+ 2,0,7,3, 2,0,8,3, 2,0,9,3, 2,1,0,3, 2,1,1,3, 2,1,2,3, 2,1,3,3, 2,1,4,3, 2,1,5,3,
+ 2,1,6,3, 2,1,7,3, 2,1,8,3, 2,1,9,3, 2,2,0,3, 2,2,1,3, 2,2,2,3, 2,2,3,3, 2,2,4,3,
+ 2,2,5,3, 2,2,6,3, 2,2,7,3, 2,2,8,3, 2,2,9,3, 2,3,0,3, 2,3,1,3, 2,3,2,3, 2,3,3,3,
+ 2,3,4,3, 2,3,5,3, 2,3,6,3, 2,3,7,3, 2,3,8,3, 2,3,9,3, 2,4,0,3, 2,4,1,3, 2,4,2,3,
+ 2,4,3,3, 2,4,4,3, 2,4,5,3, 2,4,6,3, 2,4,7,3, 2,4,8,3, 2,4,9,3, 2,5,0,3, 2,5,1,3,
+ 2,5,2,3, 2,5,3,3, 2,5,4,3, 2,5,5,3, 2,5,6,3, 2,5,7,3, 2,5,8,3, 2,5,9,3, 2,6,0,3,
+ 2,6,1,3, 2,6,2,3, 2,6,3,3, 2,6,4,3, 2,6,5,3, 2,6,6,3, 2,6,7,3, 2,6,8,3, 2,6,9,3,
+ 2,7,0,3, 2,7,1,3, 2,7,2,3, 2,7,3,3, 2,7,4,3, 2,7,5,3, 2,7,6,3, 2,7,7,3, 2,7,8,3,
+ 2,7,9,3, 2,8,0,3, 2,8,1,3, 2,8,2,3, 2,8,3,3, 2,8,4,3, 2,8,5,3, 2,8,6,3, 2,8,7,3,
+ 2,8,8,3, 2,8,9,3, 2,9,0,3, 2,9,1,3, 2,9,2,3, 2,9,3,3, 2,9,4,3, 2,9,5,3, 2,9,6,3,
+ 2,9,7,3, 2,9,8,3, 2,9,9,3, 3,0,0,3, 3,0,1,3, 3,0,2,3, 3,0,3,3, 3,0,4,3, 3,0,5,3,
+ 3,0,6,3, 3,0,7,3, 3,0,8,3, 3,0,9,3, 3,1,0,3, 3,1,1,3, 3,1,2,3, 3,1,3,3, 3,1,4,3,
+ 3,1,5,3, 3,1,6,3, 3,1,7,3, 3,1,8,3, 3,1,9,3, 3,2,0,3, 3,2,1,3, 3,2,2,3, 3,2,3,3,
+ 3,2,4,3, 3,2,5,3, 3,2,6,3, 3,2,7,3, 3,2,8,3, 3,2,9,3, 3,3,0,3, 3,3,1,3, 3,3,2,3,
+ 3,3,3,3, 3,3,4,3, 3,3,5,3, 3,3,6,3, 3,3,7,3, 3,3,8,3, 3,3,9,3, 3,4,0,3, 3,4,1,3,
+ 3,4,2,3, 3,4,3,3, 3,4,4,3, 3,4,5,3, 3,4,6,3, 3,4,7,3, 3,4,8,3, 3,4,9,3, 3,5,0,3,
+ 3,5,1,3, 3,5,2,3, 3,5,3,3, 3,5,4,3, 3,5,5,3, 3,5,6,3, 3,5,7,3, 3,5,8,3, 3,5,9,3,
+ 3,6,0,3, 3,6,1,3, 3,6,2,3, 3,6,3,3, 3,6,4,3, 3,6,5,3, 3,6,6,3, 3,6,7,3, 3,6,8,3,
+ 3,6,9,3, 3,7,0,3, 3,7,1,3, 3,7,2,3, 3,7,3,3, 3,7,4,3, 3,7,5,3, 3,7,6,3, 3,7,7,3,
+ 3,7,8,3, 3,7,9,3, 3,8,0,3, 3,8,1,3, 3,8,2,3, 3,8,3,3, 3,8,4,3, 3,8,5,3, 3,8,6,3,
+ 3,8,7,3, 3,8,8,3, 3,8,9,3, 3,9,0,3, 3,9,1,3, 3,9,2,3, 3,9,3,3, 3,9,4,3, 3,9,5,3,
+ 3,9,6,3, 3,9,7,3, 3,9,8,3, 3,9,9,3, 4,0,0,3, 4,0,1,3, 4,0,2,3, 4,0,3,3, 4,0,4,3,
+ 4,0,5,3, 4,0,6,3, 4,0,7,3, 4,0,8,3, 4,0,9,3, 4,1,0,3, 4,1,1,3, 4,1,2,3, 4,1,3,3,
+ 4,1,4,3, 4,1,5,3, 4,1,6,3, 4,1,7,3, 4,1,8,3, 4,1,9,3, 4,2,0,3, 4,2,1,3, 4,2,2,3,
+ 4,2,3,3, 4,2,4,3, 4,2,5,3, 4,2,6,3, 4,2,7,3, 4,2,8,3, 4,2,9,3, 4,3,0,3, 4,3,1,3,
+ 4,3,2,3, 4,3,3,3, 4,3,4,3, 4,3,5,3, 4,3,6,3, 4,3,7,3, 4,3,8,3, 4,3,9,3, 4,4,0,3,
+ 4,4,1,3, 4,4,2,3, 4,4,3,3, 4,4,4,3, 4,4,5,3, 4,4,6,3, 4,4,7,3, 4,4,8,3, 4,4,9,3,
+ 4,5,0,3, 4,5,1,3, 4,5,2,3, 4,5,3,3, 4,5,4,3, 4,5,5,3, 4,5,6,3, 4,5,7,3, 4,5,8,3,
+ 4,5,9,3, 4,6,0,3, 4,6,1,3, 4,6,2,3, 4,6,3,3, 4,6,4,3, 4,6,5,3, 4,6,6,3, 4,6,7,3,
+ 4,6,8,3, 4,6,9,3, 4,7,0,3, 4,7,1,3, 4,7,2,3, 4,7,3,3, 4,7,4,3, 4,7,5,3, 4,7,6,3,
+ 4,7,7,3, 4,7,8,3, 4,7,9,3, 4,8,0,3, 4,8,1,3, 4,8,2,3, 4,8,3,3, 4,8,4,3, 4,8,5,3,
+ 4,8,6,3, 4,8,7,3, 4,8,8,3, 4,8,9,3, 4,9,0,3, 4,9,1,3, 4,9,2,3, 4,9,3,3, 4,9,4,3,
+ 4,9,5,3, 4,9,6,3, 4,9,7,3, 4,9,8,3, 4,9,9,3, 5,0,0,3, 5,0,1,3, 5,0,2,3, 5,0,3,3,
+ 5,0,4,3, 5,0,5,3, 5,0,6,3, 5,0,7,3, 5,0,8,3, 5,0,9,3, 5,1,0,3, 5,1,1,3, 5,1,2,3,
+ 5,1,3,3, 5,1,4,3, 5,1,5,3, 5,1,6,3, 5,1,7,3, 5,1,8,3, 5,1,9,3, 5,2,0,3, 5,2,1,3,
+ 5,2,2,3, 5,2,3,3, 5,2,4,3, 5,2,5,3, 5,2,6,3, 5,2,7,3, 5,2,8,3, 5,2,9,3, 5,3,0,3,
+ 5,3,1,3, 5,3,2,3, 5,3,3,3, 5,3,4,3, 5,3,5,3, 5,3,6,3, 5,3,7,3, 5,3,8,3, 5,3,9,3,
+ 5,4,0,3, 5,4,1,3, 5,4,2,3, 5,4,3,3, 5,4,4,3, 5,4,5,3, 5,4,6,3, 5,4,7,3, 5,4,8,3,
+ 5,4,9,3, 5,5,0,3, 5,5,1,3, 5,5,2,3, 5,5,3,3, 5,5,4,3, 5,5,5,3, 5,5,6,3, 5,5,7,3,
+ 5,5,8,3, 5,5,9,3, 5,6,0,3, 5,6,1,3, 5,6,2,3, 5,6,3,3, 5,6,4,3, 5,6,5,3, 5,6,6,3,
+ 5,6,7,3, 5,6,8,3, 5,6,9,3, 5,7,0,3, 5,7,1,3, 5,7,2,3, 5,7,3,3, 5,7,4,3, 5,7,5,3,
+ 5,7,6,3, 5,7,7,3, 5,7,8,3, 5,7,9,3, 5,8,0,3, 5,8,1,3, 5,8,2,3, 5,8,3,3, 5,8,4,3,
+ 5,8,5,3, 5,8,6,3, 5,8,7,3, 5,8,8,3, 5,8,9,3, 5,9,0,3, 5,9,1,3, 5,9,2,3, 5,9,3,3,
+ 5,9,4,3, 5,9,5,3, 5,9,6,3, 5,9,7,3, 5,9,8,3, 5,9,9,3, 6,0,0,3, 6,0,1,3, 6,0,2,3,
+ 6,0,3,3, 6,0,4,3, 6,0,5,3, 6,0,6,3, 6,0,7,3, 6,0,8,3, 6,0,9,3, 6,1,0,3, 6,1,1,3,
+ 6,1,2,3, 6,1,3,3, 6,1,4,3, 6,1,5,3, 6,1,6,3, 6,1,7,3, 6,1,8,3, 6,1,9,3, 6,2,0,3,
+ 6,2,1,3, 6,2,2,3, 6,2,3,3, 6,2,4,3, 6,2,5,3, 6,2,6,3, 6,2,7,3, 6,2,8,3, 6,2,9,3,
+ 6,3,0,3, 6,3,1,3, 6,3,2,3, 6,3,3,3, 6,3,4,3, 6,3,5,3, 6,3,6,3, 6,3,7,3, 6,3,8,3,
+ 6,3,9,3, 6,4,0,3, 6,4,1,3, 6,4,2,3, 6,4,3,3, 6,4,4,3, 6,4,5,3, 6,4,6,3, 6,4,7,3,
+ 6,4,8,3, 6,4,9,3, 6,5,0,3, 6,5,1,3, 6,5,2,3, 6,5,3,3, 6,5,4,3, 6,5,5,3, 6,5,6,3,
+ 6,5,7,3, 6,5,8,3, 6,5,9,3, 6,6,0,3, 6,6,1,3, 6,6,2,3, 6,6,3,3, 6,6,4,3, 6,6,5,3,
+ 6,6,6,3, 6,6,7,3, 6,6,8,3, 6,6,9,3, 6,7,0,3, 6,7,1,3, 6,7,2,3, 6,7,3,3, 6,7,4,3,
+ 6,7,5,3, 6,7,6,3, 6,7,7,3, 6,7,8,3, 6,7,9,3, 6,8,0,3, 6,8,1,3, 6,8,2,3, 6,8,3,3,
+ 6,8,4,3, 6,8,5,3, 6,8,6,3, 6,8,7,3, 6,8,8,3, 6,8,9,3, 6,9,0,3, 6,9,1,3, 6,9,2,3,
+ 6,9,3,3, 6,9,4,3, 6,9,5,3, 6,9,6,3, 6,9,7,3, 6,9,8,3, 6,9,9,3, 7,0,0,3, 7,0,1,3,
+ 7,0,2,3, 7,0,3,3, 7,0,4,3, 7,0,5,3, 7,0,6,3, 7,0,7,3, 7,0,8,3, 7,0,9,3, 7,1,0,3,
+ 7,1,1,3, 7,1,2,3, 7,1,3,3, 7,1,4,3, 7,1,5,3, 7,1,6,3, 7,1,7,3, 7,1,8,3, 7,1,9,3,
+ 7,2,0,3, 7,2,1,3, 7,2,2,3, 7,2,3,3, 7,2,4,3, 7,2,5,3, 7,2,6,3, 7,2,7,3, 7,2,8,3,
+ 7,2,9,3, 7,3,0,3, 7,3,1,3, 7,3,2,3, 7,3,3,3, 7,3,4,3, 7,3,5,3, 7,3,6,3, 7,3,7,3,
+ 7,3,8,3, 7,3,9,3, 7,4,0,3, 7,4,1,3, 7,4,2,3, 7,4,3,3, 7,4,4,3, 7,4,5,3, 7,4,6,3,
+ 7,4,7,3, 7,4,8,3, 7,4,9,3, 7,5,0,3, 7,5,1,3, 7,5,2,3, 7,5,3,3, 7,5,4,3, 7,5,5,3,
+ 7,5,6,3, 7,5,7,3, 7,5,8,3, 7,5,9,3, 7,6,0,3, 7,6,1,3, 7,6,2,3, 7,6,3,3, 7,6,4,3,
+ 7,6,5,3, 7,6,6,3, 7,6,7,3, 7,6,8,3, 7,6,9,3, 7,7,0,3, 7,7,1,3, 7,7,2,3, 7,7,3,3,
+ 7,7,4,3, 7,7,5,3, 7,7,6,3, 7,7,7,3, 7,7,8,3, 7,7,9,3, 7,8,0,3, 7,8,1,3, 7,8,2,3,
+ 7,8,3,3, 7,8,4,3, 7,8,5,3, 7,8,6,3, 7,8,7,3, 7,8,8,3, 7,8,9,3, 7,9,0,3, 7,9,1,3,
+ 7,9,2,3, 7,9,3,3, 7,9,4,3, 7,9,5,3, 7,9,6,3, 7,9,7,3, 7,9,8,3, 7,9,9,3, 8,0,0,3,
+ 8,0,1,3, 8,0,2,3, 8,0,3,3, 8,0,4,3, 8,0,5,3, 8,0,6,3, 8,0,7,3, 8,0,8,3, 8,0,9,3,
+ 8,1,0,3, 8,1,1,3, 8,1,2,3, 8,1,3,3, 8,1,4,3, 8,1,5,3, 8,1,6,3, 8,1,7,3, 8,1,8,3,
+ 8,1,9,3, 8,2,0,3, 8,2,1,3, 8,2,2,3, 8,2,3,3, 8,2,4,3, 8,2,5,3, 8,2,6,3, 8,2,7,3,
+ 8,2,8,3, 8,2,9,3, 8,3,0,3, 8,3,1,3, 8,3,2,3, 8,3,3,3, 8,3,4,3, 8,3,5,3, 8,3,6,3,
+ 8,3,7,3, 8,3,8,3, 8,3,9,3, 8,4,0,3, 8,4,1,3, 8,4,2,3, 8,4,3,3, 8,4,4,3, 8,4,5,3,
+ 8,4,6,3, 8,4,7,3, 8,4,8,3, 8,4,9,3, 8,5,0,3, 8,5,1,3, 8,5,2,3, 8,5,3,3, 8,5,4,3,
+ 8,5,5,3, 8,5,6,3, 8,5,7,3, 8,5,8,3, 8,5,9,3, 8,6,0,3, 8,6,1,3, 8,6,2,3, 8,6,3,3,
+ 8,6,4,3, 8,6,5,3, 8,6,6,3, 8,6,7,3, 8,6,8,3, 8,6,9,3, 8,7,0,3, 8,7,1,3, 8,7,2,3,
+ 8,7,3,3, 8,7,4,3, 8,7,5,3, 8,7,6,3, 8,7,7,3, 8,7,8,3, 8,7,9,3, 8,8,0,3, 8,8,1,3,
+ 8,8,2,3, 8,8,3,3, 8,8,4,3, 8,8,5,3, 8,8,6,3, 8,8,7,3, 8,8,8,3, 8,8,9,3, 8,9,0,3,
+ 8,9,1,3, 8,9,2,3, 8,9,3,3, 8,9,4,3, 8,9,5,3, 8,9,6,3, 8,9,7,3, 8,9,8,3, 8,9,9,3,
+ 9,0,0,3, 9,0,1,3, 9,0,2,3, 9,0,3,3, 9,0,4,3, 9,0,5,3, 9,0,6,3, 9,0,7,3, 9,0,8,3,
+ 9,0,9,3, 9,1,0,3, 9,1,1,3, 9,1,2,3, 9,1,3,3, 9,1,4,3, 9,1,5,3, 9,1,6,3, 9,1,7,3,
+ 9,1,8,3, 9,1,9,3, 9,2,0,3, 9,2,1,3, 9,2,2,3, 9,2,3,3, 9,2,4,3, 9,2,5,3, 9,2,6,3,
+ 9,2,7,3, 9,2,8,3, 9,2,9,3, 9,3,0,3, 9,3,1,3, 9,3,2,3, 9,3,3,3, 9,3,4,3, 9,3,5,3,
+ 9,3,6,3, 9,3,7,3, 9,3,8,3, 9,3,9,3, 9,4,0,3, 9,4,1,3, 9,4,2,3, 9,4,3,3, 9,4,4,3,
+ 9,4,5,3, 9,4,6,3, 9,4,7,3, 9,4,8,3, 9,4,9,3, 9,5,0,3, 9,5,1,3, 9,5,2,3, 9,5,3,3,
+ 9,5,4,3, 9,5,5,3, 9,5,6,3, 9,5,7,3, 9,5,8,3, 9,5,9,3, 9,6,0,3, 9,6,1,3, 9,6,2,3,
+ 9,6,3,3, 9,6,4,3, 9,6,5,3, 9,6,6,3, 9,6,7,3, 9,6,8,3, 9,6,9,3, 9,7,0,3, 9,7,1,3,
+ 9,7,2,3, 9,7,3,3, 9,7,4,3, 9,7,5,3, 9,7,6,3, 9,7,7,3, 9,7,8,3, 9,7,9,3, 9,8,0,3,
+ 9,8,1,3, 9,8,2,3, 9,8,3,3, 9,8,4,3, 9,8,5,3, 9,8,6,3, 9,8,7,3, 9,8,8,3, 9,8,9,3,
+ 9,9,0,3, 9,9,1,3, 9,9,2,3, 9,9,3,3, 9,9,4,3, 9,9,5,3, 9,9,6,3, 9,9,7,3, 9,9,8,3,
+ 9,9,9,3};
+#endif
+
diff --git a/libdecnumber/decDouble.c b/libdecnumber/decDouble.c
new file mode 100644 (file)
index 0000000..ba6a0af
--- /dev/null
@@ -0,0 +1,154 @@
+/* decDouble module for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* decDouble.c -- decDouble operations module                        */
+/* ------------------------------------------------------------------ */
+/* This module comprises decDouble operations (including conversions) */
+/* ------------------------------------------------------------------ */
+
+#include "decContext.h"              /* public includes */
+#include "decDouble.h"       /* .. */
+
+/* Constant mappings for shared code */
+#define DECPMAX            DECDOUBLE_Pmax
+#define DECEMIN            DECDOUBLE_Emin
+#define DECEMAX            DECDOUBLE_Emax
+#define DECEMAXD    DECDOUBLE_EmaxD
+#define DECBYTES    DECDOUBLE_Bytes
+#define DECSTRING   DECDOUBLE_String
+#define DECECONL    DECDOUBLE_EconL
+#define DECBIAS            DECDOUBLE_Bias
+#define DECLETS            DECDOUBLE_Declets
+#define DECQTINY    (-DECDOUBLE_Bias)
+/* parameters of next-wider format */
+#define DECWBYTES   DECQUAD_Bytes
+#define DECWPMAX    DECQUAD_Pmax
+#define DECWECONL   DECQUAD_EconL
+#define DECWBIAS    DECQUAD_Bias
+
+/* Type and function mappings for shared code */
+#define decFloat              decDouble          /* Type name */
+#define decFloatWider         decQuad            /* Type name */
+
+/* Utilities and conversions (binary results, extractors, etc.) */
+#define decFloatFromBCD                decDoubleFromBCD
+#define decFloatFromInt32      decDoubleFromInt32
+#define decFloatFromPacked     decDoubleFromPacked
+#define decFloatFromString     decDoubleFromString
+#define decFloatFromUInt32     decDoubleFromUInt32
+#define decFloatFromWider      decDoubleFromWider
+#define decFloatGetCoefficient decDoubleGetCoefficient
+#define decFloatGetExponent    decDoubleGetExponent
+#define decFloatSetCoefficient decDoubleSetCoefficient
+#define decFloatSetExponent    decDoubleSetExponent
+#define decFloatShow           decDoubleShow
+#define decFloatToBCD          decDoubleToBCD
+#define decFloatToEngString    decDoubleToEngString
+#define decFloatToInt32                decDoubleToInt32
+#define decFloatToInt32Exact   decDoubleToInt32Exact
+#define decFloatToPacked       decDoubleToPacked
+#define decFloatToString       decDoubleToString
+#define decFloatToUInt32       decDoubleToUInt32
+#define decFloatToUInt32Exact  decDoubleToUInt32Exact
+#define decFloatToWider                decDoubleToWider
+#define decFloatZero           decDoubleZero
+
+/* Computational (result is a decFloat) */
+#define decFloatAbs            decDoubleAbs
+#define decFloatAdd            decDoubleAdd
+#define decFloatAnd            decDoubleAnd
+#define decFloatDivide         decDoubleDivide
+#define decFloatDivideInteger  decDoubleDivideInteger
+#define decFloatFMA            decDoubleFMA
+#define decFloatInvert         decDoubleInvert
+#define decFloatLogB           decDoubleLogB
+#define decFloatMax            decDoubleMax
+#define decFloatMaxMag         decDoubleMaxMag
+#define decFloatMin            decDoubleMin
+#define decFloatMinMag         decDoubleMinMag
+#define decFloatMinus          decDoubleMinus
+#define decFloatMultiply       decDoubleMultiply
+#define decFloatNextMinus      decDoubleNextMinus
+#define decFloatNextPlus       decDoubleNextPlus
+#define decFloatNextToward     decDoubleNextToward
+#define decFloatOr             decDoubleOr
+#define decFloatPlus           decDoublePlus
+#define decFloatQuantize       decDoubleQuantize
+#define decFloatReduce         decDoubleReduce
+#define decFloatRemainder      decDoubleRemainder
+#define decFloatRemainderNear  decDoubleRemainderNear
+#define decFloatRotate         decDoubleRotate
+#define decFloatScaleB         decDoubleScaleB
+#define decFloatShift          decDoubleShift
+#define decFloatSubtract       decDoubleSubtract
+#define decFloatToIntegralValue decDoubleToIntegralValue
+#define decFloatToIntegralExact decDoubleToIntegralExact
+#define decFloatXor            decDoubleXor
+
+/* Comparisons */
+#define decFloatCompare                decDoubleCompare
+#define decFloatCompareSignal  decDoubleCompareSignal
+#define decFloatCompareTotal   decDoubleCompareTotal
+#define decFloatCompareTotalMag decDoubleCompareTotalMag
+
+/* Copies */
+#define decFloatCanonical      decDoubleCanonical
+#define decFloatCopy           decDoubleCopy
+#define decFloatCopyAbs                decDoubleCopyAbs
+#define decFloatCopyNegate     decDoubleCopyNegate
+#define decFloatCopySign       decDoubleCopySign
+
+/* Non-computational */
+#define decFloatClass          decDoubleClass
+#define decFloatClassString    decDoubleClassString
+#define decFloatDigits         decDoubleDigits
+#define decFloatIsCanonical    decDoubleIsCanonical
+#define decFloatIsFinite       decDoubleIsFinite
+#define decFloatIsInfinite     decDoubleIsInfinite
+#define decFloatIsInteger      decDoubleIsInteger
+#define decFloatIsNaN          decDoubleIsNaN
+#define decFloatIsNormal       decDoubleIsNormal
+#define decFloatIsSignaling    decDoubleIsSignaling
+#define decFloatIsSignalling   decDoubleIsSignalling
+#define decFloatIsSigned       decDoubleIsSigned
+#define decFloatIsSubnormal    decDoubleIsSubnormal
+#define decFloatIsZero         decDoubleIsZero
+#define decFloatRadix          decDoubleRadix
+#define decFloatSameQuantum    decDoubleSameQuantum
+#define decFloatVersion                decDoubleVersion
+
+
+#include "decNumberLocal.h"   /* local includes (need DECPMAX) */
+#include "decCommon.c"       /* non-arithmetic decFloat routines */
+#include "decBasic.c"        /* basic formats routines */
+
+/* Below here will move to shared file as completed */
+
diff --git a/libdecnumber/decDouble.h b/libdecnumber/decDouble.h
new file mode 100644 (file)
index 0000000..32eba39
--- /dev/null
@@ -0,0 +1,164 @@
+/* decDouble module header for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* decDouble.h -- Decimal 64-bit format module header                */
+/* ------------------------------------------------------------------ */
+/* Please see decFloats.h for an overview and documentation details.  */
+/* ------------------------------------------------------------------ */
+
+#if !defined(DECDOUBLE)
+  #define DECDOUBLE
+
+  #define DECDOUBLENAME              "decimalDouble"         /* Short name   */
+  #define DECDOUBLETITLE      "Decimal 64-bit datum"  /* Verbose name */
+  #define DECDOUBLEAUTHOR     "Mike Cowlishaw"       /* Who to blame */
+
+  /* parameters for decDoubles */
+  #define DECDOUBLE_Bytes   8     /* length                          */
+  #define DECDOUBLE_Pmax    16    /* maximum precision (digits)      */
+  #define DECDOUBLE_Emin   -383           /* minimum adjusted exponent       */
+  #define DECDOUBLE_Emax    384           /* maximum adjusted exponent       */
+  #define DECDOUBLE_EmaxD   3     /* maximum exponent digits         */
+  #define DECDOUBLE_Bias    398           /* bias for the exponent           */
+  #define DECDOUBLE_String  25    /* maximum string length, +1       */
+  #define DECDOUBLE_EconL   8     /* exponent continuation length    */
+  #define DECDOUBLE_Declets 5     /* count of declets                */
+  /* highest biased exponent (Elimit-1) */
+  #define DECDOUBLE_Ehigh (DECDOUBLE_Emax + DECDOUBLE_Bias - (DECDOUBLE_Pmax-1))
+
+  /* Required includes                                               */
+  #include "decContext.h"
+  #include "decQuad.h"
+
+  /* The decDouble decimal 64-bit type, accessible by bytes */
+  typedef struct {
+    uint8_t bytes[DECDOUBLE_Bytes]; /* fields: 1, 5, 8, 50 bits          */
+    } decDouble;
+
+  /* ---------------------------------------------------------------- */
+  /* Routines -- implemented as decFloat routines in common files     */
+  /* ---------------------------------------------------------------- */
+
+  #include "decDoubleSymbols.h"
+
+  /* Utilities and conversions, extractors, etc.) */
+  extern decDouble * decDoubleFromBCD(decDouble *, int32_t, const uint8_t *, int32_t);
+  extern decDouble * decDoubleFromInt32(decDouble *, int32_t);
+  extern decDouble * decDoubleFromPacked(decDouble *, int32_t, const uint8_t *);
+  extern decDouble * decDoubleFromString(decDouble *, const char *, decContext *);
+  extern decDouble * decDoubleFromUInt32(decDouble *, uint32_t);
+  extern decDouble * decDoubleFromWider(decDouble *, const decQuad *, decContext *);
+  extern int32_t     decDoubleGetCoefficient(const decDouble *, uint8_t *);
+  extern int32_t     decDoubleGetExponent(const decDouble *);
+  extern decDouble * decDoubleSetCoefficient(decDouble *, const uint8_t *, int32_t);
+  extern decDouble * decDoubleSetExponent(decDouble *, decContext *, int32_t);
+  extern void       decDoubleShow(const decDouble *, const char *);
+  extern int32_t     decDoubleToBCD(const decDouble *, int32_t *, uint8_t *);
+  extern char     * decDoubleToEngString(const decDouble *, char *);
+  extern int32_t     decDoubleToInt32(const decDouble *, decContext *, enum rounding);
+  extern int32_t     decDoubleToInt32Exact(const decDouble *, decContext *, enum rounding);
+  extern int32_t     decDoubleToPacked(const decDouble *, int32_t *, uint8_t *);
+  extern char     * decDoubleToString(const decDouble *, char *);
+  extern uint32_t    decDoubleToUInt32(const decDouble *, decContext *, enum rounding);
+  extern uint32_t    decDoubleToUInt32Exact(const decDouble *, decContext *, enum rounding);
+  extern decQuad   * decDoubleToWider(const decDouble *, decQuad *);
+  extern decDouble * decDoubleZero(decDouble *);
+
+  /* Computational (result is a decDouble) */
+  extern decDouble * decDoubleAbs(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleAdd(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleAnd(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleDivide(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleDivideInteger(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleFMA(decDouble *, const decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleInvert(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleLogB(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleMax(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleMaxMag(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleMin(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleMinMag(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleMinus(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleMultiply(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleNextMinus(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleNextPlus(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleNextToward(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleOr(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoublePlus(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleQuantize(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleReduce(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleRemainder(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleRemainderNear(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleRotate(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleScaleB(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleShift(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleSubtract(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleToIntegralValue(decDouble *, const decDouble *, decContext *, enum rounding);
+  extern decDouble * decDoubleToIntegralExact(decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleXor(decDouble *, const decDouble *, const decDouble *, decContext *);
+
+  /* Comparisons */
+  extern decDouble * decDoubleCompare(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleCompareSignal(decDouble *, const decDouble *, const decDouble *, decContext *);
+  extern decDouble * decDoubleCompareTotal(decDouble *, const decDouble *, const decDouble *);
+  extern decDouble * decDoubleCompareTotalMag(decDouble *, const decDouble *, const decDouble *);
+
+  /* Copies */
+  extern decDouble * decDoubleCanonical(decDouble *, const decDouble *);
+  extern decDouble * decDoubleCopy(decDouble *, const decDouble *);
+  extern decDouble * decDoubleCopyAbs(decDouble *, const decDouble *);
+  extern decDouble * decDoubleCopyNegate(decDouble *, const decDouble *);
+  extern decDouble * decDoubleCopySign(decDouble *, const decDouble *, const decDouble *);
+
+  /* Non-computational */
+  extern enum decClass decDoubleClass(const decDouble *);
+  extern const char *  decDoubleClassString(const decDouble *);
+  extern uint32_t      decDoubleDigits(const decDouble *);
+  extern uint32_t      decDoubleIsCanonical(const decDouble *);
+  extern uint32_t      decDoubleIsFinite(const decDouble *);
+  extern uint32_t      decDoubleIsInfinite(const decDouble *);
+  extern uint32_t      decDoubleIsInteger(const decDouble *);
+  extern uint32_t      decDoubleIsNaN(const decDouble *);
+  extern uint32_t      decDoubleIsNormal(const decDouble *);
+  extern uint32_t      decDoubleIsSignaling(const decDouble *);
+  extern uint32_t      decDoubleIsSignalling(const decDouble *);
+  extern uint32_t      decDoubleIsSigned(const decDouble *);
+  extern uint32_t      decDoubleIsSubnormal(const decDouble *);
+  extern uint32_t      decDoubleIsZero(const decDouble *);
+  extern uint32_t      decDoubleRadix(const decDouble *);
+  extern uint32_t      decDoubleSameQuantum(const decDouble *, const decDouble *);
+  extern const char *  decDoubleVersion(void);
+
+  /* decNumber conversions; these are implemented as macros so as not  */
+  /* to force a dependency on decimal64 and decNumber in decDouble.    */
+  #define decDoubleToNumber(dq, dn) decimal64ToNumber((decimal64 *)(dq), dn)
+  #define decDoubleFromNumber(dq, dn, set) (decDouble *)decimal64FromNumber((decimal64 *)(dq), dn, set)
+
+#endif
diff --git a/libdecnumber/decDoubleSymbols.h b/libdecnumber/decDoubleSymbols.h
new file mode 100644 (file)
index 0000000..add1248
--- /dev/null
@@ -0,0 +1,84 @@
+#if !defined(DECDOUBLESYMBOLS)
+#define DECDOUBLESYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decDoubleAbs __decDoubleAbs
+#define decDoubleAdd __decDoubleAdd
+#define decDoubleAnd __decDoubleAnd
+#define decDoubleCanonical __decDoubleCanonical
+#define decDoubleClass __decDoubleClass
+#define decDoubleClassString __decDoubleClassString
+#define decDoubleCompare __decDoubleCompare
+#define decDoubleCompareSignal __decDoubleCompareSignal
+#define decDoubleCompareTotal __decDoubleCompareTotal
+#define decDoubleCompareTotalMag __decDoubleCompareTotalMag
+#define decDoubleCopy __decDoubleCopy
+#define decDoubleCopyAbs __decDoubleCopyAbs
+#define decDoubleCopyNegate __decDoubleCopyNegate
+#define decDoubleCopySign __decDoubleCopySign
+#define decDoubleDigits __decDoubleDigits
+#define decDoubleDivide __decDoubleDivide
+#define decDoubleDivideInteger __decDoubleDivideInteger
+#define decDoubleFMA __decDoubleFMA
+#define decDoubleFromBCD __decDoubleFromBCD
+#define decDoubleFromInt32 __decDoubleFromInt32
+#define decDoubleFromPacked __decDoubleFromPacked
+#define decDoubleFromString __decDoubleFromString
+#define decDoubleFromUInt32 __decDoubleFromUInt32
+#define decDoubleFromWider __decDoubleFromWider
+#define decDoubleGetCoefficient __decDoubleGetCoefficient
+#define decDoubleGetExponent __decDoubleGetExponent
+#define decDoubleInvert __decDoubleInvert
+#define decDoubleIsCanonical __decDoubleIsCanonical
+#define decDoubleIsFinite __decDoubleIsFinite
+#define decDoubleIsInfinite __decDoubleIsInfinite
+#define decDoubleIsInteger __decDoubleIsInteger
+#define decDoubleIsNaN __decDoubleIsNaN
+#define decDoubleIsNormal __decDoubleIsNormal
+#define decDoubleIsSignaling __decDoubleIsSignaling
+#define decDoubleIsSignalling __decDoubleIsSignalling
+#define decDoubleIsSigned __decDoubleIsSigned
+#define decDoubleIsSubnormal __decDoubleIsSubnormal
+#define decDoubleIsZero __decDoubleIsZero
+#define decDoubleLogB __decDoubleLogB
+#define decDoubleMax __decDoubleMax
+#define decDoubleMaxMag __decDoubleMaxMag
+#define decDoubleMin __decDoubleMin
+#define decDoubleMinMag __decDoubleMinMag
+#define decDoubleMinus __decDoubleMinus
+#define decDoubleMultiply __decDoubleMultiply
+#define decDoubleNextMinus __decDoubleNextMinus
+#define decDoubleNextPlus __decDoubleNextPlus
+#define decDoubleNextToward __decDoubleNextToward
+#define decDoubleOr __decDoubleOr
+#define decDoublePlus __decDoublePlus
+#define decDoubleQuantize __decDoubleQuantize
+#define decDoubleRadix __decDoubleRadix
+#define decDoubleReduce __decDoubleReduce
+#define decDoubleRemainder __decDoubleRemainder
+#define decDoubleRemainderNear __decDoubleRemainderNear
+#define decDoubleRotate __decDoubleRotate
+#define decDoubleSameQuantum __decDoubleSameQuantum
+#define decDoubleScaleB __decDoubleScaleB
+#define decDoubleSetCoefficient __decDoubleSetCoefficient
+#define decDoubleSetExponent __decDoubleSetExponent
+#define decDoubleShift __decDoubleShift
+#define decDoubleShow __decDoubleShow
+#define decDoubleSubtract __decDoubleSubtract
+#define decDoubleToBCD __decDoubleToBCD
+#define decDoubleToEngString __decDoubleToEngString
+#define decDoubleToInt32 __decDoubleToInt32
+#define decDoubleToInt32Exact __decDoubleToInt32Exact
+#define decDoubleToIntegralExact __decDoubleToIntegralExact
+#define decDoubleToIntegralValue __decDoubleToIntegralValue
+#define decDoubleToPacked __decDoubleToPacked
+#define decDoubleToString __decDoubleToString
+#define decDoubleToUInt32 __decDoubleToUInt32
+#define decDoubleToUInt32Exact __decDoubleToUInt32Exact
+#define decDoubleToWider __decDoubleToWider
+#define decDoubleVersion __decDoubleVersion
+#define decDoubleXor __decDoubleXor
+#define decDoubleZero __decDoubleZero
+#endif
+
+#endif
index 5a172502ef04ffdfa419f65545479a3877166a89..7e5e928edc27977db4969403b271f89a1417db9d 100644 (file)
@@ -74,22 +74,3 @@ isinfd128 (_Decimal128 arg)
   decimal128ToNumber (&d128, &dn);
   return (decNumberIsInfinite (&dn));
 }
-
-uint32_t
-__dec_byte_swap (uint32_t in)
-{
-  uint32_t out = 0;
-  unsigned char *p = (unsigned char *) &out;
-  union {
-    uint32_t i;
-    unsigned char b[4];
-  } u;
-
-  u.i = in;
-  p[0] = u.b[3];
-  p[1] = u.b[2];
-  p[2] = u.b[1];
-  p[3] = u.b[0];
-
-  return out;
-}
index dbc42148985caa12e185526d1c12813956156d27..c5e223c812fea3e755700734025db06168cb7aa1 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal Number module for the decNumber C Library
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Decimal number arithmetic module for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    02110-1301, USA.  */
 
 /* ------------------------------------------------------------------ */
-/* This module comprises the routines for Standard Decimal Arithmetic */
-/* as defined in the specification which may be found on the          */
+/* Decimal Number arithmetic module                                  */
+/* ------------------------------------------------------------------ */
+/* This module comprises the routines for General Decimal Arithmetic  */
+/* as defined in the specification which may be found on the         */
 /* http://www2.hursley.ibm.com/decimal web pages.  It implements both */
-/* the full ('extended') arithmetic and the simpler ('subset')        */
-/* arithmetic.                                                        */
-/*                                                                    */
-/* Usage notes:                                                       */
-/*                                                                    */
-/* 1. This code is ANSI C89 except:                                   */
-/*                                                                    */
-/*    a) Line comments (double forward slash) are used.  (Most C      */
-/*       compilers accept these.  If yours does not, a simple script  */
-/*       can be used to convert them to ANSI C comments.)             */
-/*                                                                    */
-/*    b) Types from C99 stdint.h are used.  If you do not have this   */
-/*       header file, see the User's Guide section of the decNumber   */
-/*       documentation; this lists the necessary definitions.         */
-/*                                                                    */
-/*    c) If DECDPUN>4, non-ANSI 64-bit 'long long' types are used.    */
-/*       To avoid these, set DECDPUN <= 4 (see documentation).        */
-/*                                                                    */
+/* the full ('extended') arithmetic and the simpler ('subset')       */
+/* arithmetic.                                                       */
+/*                                                                   */
+/* Usage notes:                                                              */
+/*                                                                   */
+/* 1. This code is ANSI C89 except:                                  */
+/*                                                                   */
+/*       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  */
+/*      and DECDPUN<=4 (see documentation).                          */
+/*                                                                   */
 /* 2. The decNumber format which this library uses is optimized for   */
 /*    efficient processing of relatively short numbers; in particular */
 /*    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     */
 /*    range (Emax in the range 0 through 999,999,999 and Emin in the  */
-/*    range -999,999,999 through 0).                                  */
-/*                                                                    */
-/* 3. Operands to operator functions are never modified unless they   */
+/*    range -999,999,999 through 0).  Mathematical functions (for     */
+/*    example decNumberExp) as identified below are restricted more   */
+/*    tightly: digits, emax, and -emin in the context must be <=      */
+/*    DEC_MAX_MATH (999999), and their operand(s) must be within      */
+/*    these bounds.                                                  */
+/*                                                                   */
+/* 3. Logical functions are further restricted; their operands must   */
+/*    be finite, positive, have an exponent of zero, and all 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).    */
+/*                                                                   */
+/* 4. Operands to operator functions are never modified unless they   */
 /*    are also specified to be the result number (which is always     */
-/*    permitted).  Other than that case, operands may not overlap.    */
-/*                                                                    */
-/* 4. Error handling: the type of the error is ORed into the status   */
-/*    flags in the current context (decContext structure).  The       */
+/*    permitted).  Other than that case, operands must not overlap.   */
+/*                                                                   */
+/* 5. Error handling: the type of the error is ORed into the status   */
+/*    flags in the current context (decContext structure).  The              */
 /*    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      */
-/*    flags as required.                                              */
-/*                                                                    */
+/*    flags as required.                                             */
+/*                                                                   */
 /*    The result of any routine which returns a number will always    */
 /*    be a valid number (which may be a special value, such as an     */
-/*    Infinity or NaN).                                               */
-/*                                                                    */
-/* 5. The decNumber format is not an exchangeable concrete            */
+/*    Infinity or NaN).                                                      */
+/*                                                                   */
+/* 6. The decNumber format is not an exchangeable concrete           */
 /*    representation as it comprises fields which may be machine-     */
-/*    dependent (big-endian or little-endian, for example).           */
+/*    dependent (packed or unpacked, or special length, for example). */
 /*    Canonical conversions to and from strings are provided; other   */
-/*    conversions are available in separate modules.                  */
-/*                                                                    */
-/* 6. Normally, input operands are assumed to be valid.  Set DECCHECK */
+/*    conversions are available in separate modules.                 */
+/*                                                                   */
+/* 7. Normally, input operands are assumed to be valid.         Set DECCHECK */
 /*    to 1 for extended operand checking (including NULL operands).   */
 /*    Results are undefined if a badly-formed structure (or a NULL    */
-/*    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. */
 /*    (Except if the result pointer is NULL, which is unrecoverable.) */
-/*                                                                    */
+/*                                                                   */
 /*    However, the routines will never cause exceptions if they are   */
 /*    given well-formed operands, even if the value of the operands   */
 /*    is inappropriate for the operation and DECCHECK is not set.     */
-/*                                                                    */
-/* 7. Subset arithmetic is available only if DECSUBSET is set to 1.   */
+/*    (Except for SIGFPE, as and where documented.)                  */
+/*                                                                   */
+/* 8. Subset arithmetic is available only if DECSUBSET is set to 1.   */
 /* ------------------------------------------------------------------ */
-/* Implementation notes for maintenance of this module:               */
-/*                                                                    */
-/* 1. Storage leak protection:  Routines which use malloc are not     */
+/* Implementation notes for maintenance of this module:                      */
+/*                                                                   */
+/* 1. Storage leak protection: Routines which use malloc are not     */
 /*    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     */
-/*    code which is protected -- break may be used from this.         */
-/*    Other routines are allowed to use the return statement inline.  */
-/*                                                                    */
-/*    Storage leak accounting can be enabled using DECALLOC.          */
-/*                                                                    */
-/* 2. All loops use the for(;;) construct.  Any do construct is for   */
-/*    protection as just described.                                   */
-/*                                                                    */
+/*    code which is protected -- break may be used to exit this.      */
+/*    Other routines can safely use the return statement inline.      */
+/*                                                                   */
+/*    Storage leak accounting can be enabled using DECALLOC.         */
+/*                                                                   */
+/* 2. All loops use the for(;;) construct.  Any do construct does     */
+/*    not loop; it is for allocation protection as just described.    */
+/*                                                                   */
 /* 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 */
 /*    the call to set status may not return (if the handler uses long */
-/*    jump).  Therefore all cleanup must be done first.  In general,  */
-/*    to achieve this we accumulate status and only finally apply it  */
-/*    by calling decContextSetStatus (via decStatus).                 */
-/*                                                                    */
-/*    Routines which allocate storage cannot, therefore, use the      */
-/*    'top level' routines which could cause a non-returning          */
+/*    jump).  Therefore all cleanup must be done first.         In general,  */
+/*    to achieve this status is accumulated and is only applied just  */
+/*    before return by calling decContextSetStatus (via decStatus).   */
+/*                                                                   */
+/*    Routines which allocate storage cannot, in general, use the     */
+/*    'top level' routines which could cause a non-returning         */
 /*    transfer of control.  The decXxxxOp routines are safe (do not   */
 /*    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      */
 /*    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,      */
-/*    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  */
 /*    a 999999999-digit number with adjusted exponent of -999999999). */
-/*                                                                    */
+/*                                                                   */
 /* 5. Rounding is deferred until finalization of results, with any    */
 /*    'off to the right' data being represented as a single digit     */
 /*    residue (in the range -1 through 9).  This avoids any double-   */
-/*    rounding when more than one shortening takes place (for         */
-/*    example, when a result is subnormal).                           */
-/*                                                                    */
+/*    rounding when more than one shortening takes place (for        */
+/*    example, when a result is subnormal).                          */
+/*                                                                   */
 /* 6. The digits count is allowed to rise to a multiple of DECDPUN    */
 /*    during many operations, so whole Units are handled and exact    */
 /*    accounting of digits is not needed.  The correct digits value   */
 /*    is found by decGetDigits, which accounts for leading zeros.     */
 /*    This must be called before any rounding if the number of digits */
-/*    is not known exactly.                                           */
-/*                                                                    */
-/* 7. We use the multiply-by-reciprocal 'trick' for partitioning      */
+/*    is not known exactly.                                          */
+/*                                                                   */
+/* 7. The multiply-by-reciprocal 'trick' is used for partitioning     */
 /*    numbers up to four digits, using appropriate constants.  This   */
 /*    is not useful for longer numbers because overflow of 32 bits    */
 /*    would lead to 4 multiplies, which is almost as expensive as     */
-/*    a divide (unless we assumed floating-point multiply available). */
-/*                                                                    */
-/* 8. Unusual abbreviations possibly used in the commentary:          */
-/*      lhs -- left hand side (operand, of an operation)              */
-/*      lsd -- least significant digit (of coefficient)               */
-/*      lsu -- least significant Unit (of coefficient)                */
-/*      msd -- most significant digit (of coefficient)                */
-/*      msu -- most significant Unit (of coefficient)                 */
-/*      rhs -- right hand side (operand, of an operation)             */
-/*      +ve -- positive                                               */
-/*      -ve -- negative                                               */
-/* ------------------------------------------------------------------ */
-
-/* Some of glibc's string inlines cause warnings.  Plus we'd rather
-   rely on (and therefore test) GCC's string builtins.  */
-#define __NO_STRING_INLINES
-
-#include <stdlib.h>            /* for malloc, free, etc. */
-#include <stdio.h>             /* for printf [if needed] */
-#include <string.h>            /* for strcpy */
-#include <ctype.h>             /* for lower */
-#include "config.h"
-#include "decNumber.h"         /* base number library */
-#include "decNumberLocal.h"    /* decNumber local types, etc. */
+/*    a divide (unless a floating-point or 64-bit multiply is        */
+/*    assumed to be available).                                              */
+/*                                                                   */
+/* 8. Unusual abbreviations that may be used in the commentary:              */
+/*     lhs -- left hand side (operand, of an operation)              */
+/*     lsd -- least significant digit (of coefficient)               */
+/*     lsu -- least significant Unit (of coefficient)                */
+/*     msd -- most significant digit (of coefficient)                */
+/*     msi -- most significant item (in an array)                    */
+/*     msu -- most significant Unit (of coefficient)                 */
+/*     rhs -- right hand side (operand, of an operation)             */
+/*     +ve -- positive                                               */
+/*     -ve -- negative                                               */
+/*     **  -- raise to the power                                     */
+/* ------------------------------------------------------------------ */
+
+#include <stdlib.h>               /* for malloc, free, etc. */
+#include <stdio.h>                /* for printf [if needed] */
+#include <string.h>               /* for strcpy */
+#include <ctype.h>                /* for lower */
+#include "config.h"               /* for GCC definitions */
+#include "decNumber.h"            /* base number library */
+#include "decNumberLocal.h"       /* decNumber local types, etc. */
 
 /* Constants */
-/* Public constant array: powers of ten (powers[n]==10**n) */
-const uInt powers[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
-  10000000, 100000000, 1000000000
-};
-
-/* Local constants */
-#define DIVIDE    0x80         /* Divide operators */
-#define REMAINDER 0x40         /* .. */
-#define DIVIDEINT 0x20         /* .. */
-#define REMNEAR   0x10         /* .. */
-#define COMPARE   0x01         /* Compare operators */
-#define COMPMAX   0x02         /* .. */
-#define COMPMIN   0x03         /* .. */
-#define COMPNAN   0x04         /* .. [NaN processing] */
+/* Public lookup table used by the D2U macro */
+const uByte d2utable[DECMAXD2U+1]=D2UTABLE;
 
-#define DEC_sNaN 0x40000000    /* local status: sNaN signal */
-#define BADINT (Int)0x80000000 /* most-negative Int; error indicator */
+#define DECVERB            1              /* set to 1 for verbose DECCHECK */
+#define powers     DECPOWERS      /* old internal name */
 
-static Unit one[] = { 1 };     /* Unit array of 1, used for incrementing */
+/* Local constants */
+#define DIVIDE     0x80           /* Divide operators */
+#define REMAINDER   0x40          /* .. */
+#define DIVIDEINT   0x20          /* .. */
+#define REMNEAR            0x10           /* .. */
+#define COMPARE            0x01           /* Compare operators */
+#define COMPMAX            0x02           /* .. */
+#define COMPMIN            0x03           /* .. */
+#define COMPTOTAL   0x04          /* .. */
+#define COMPNAN            0x05           /* .. [NaN processing] */
+#define COMPSIG            0x06           /* .. [signaling COMPARE] */
+#define COMPMAXMAG  0x07          /* .. */
+#define COMPMINMAG  0x08          /* .. */
+
+#define DEC_sNaN     0x40000000           /* local status: sNaN signal */
+#define BADINT (Int)0x80000000    /* most-negative Int; error indicator */
+/* Next two indicate an integer >= 10**6, and its parity (bottom bit) */
+#define BIGEVEN (Int)0x80000002
+#define BIGODD (Int)0x80000003
+
+static Unit uarrone[1]={1};   /* Unit array of 1, used for incrementing */
 
 /* Granularity-dependent code */
 #if DECDPUN<=4
-#define eInt  Int              /* extended integer */
-#define ueInt uInt             /* unsigned extended integer */
+  #define eInt Int           /* extended integer */
+  #define ueInt uInt         /* unsigned extended integer */
   /* Constant multipliers for divide-by-power-of five using reciprocal */
   /* multiply, after removing powers of 2 by shifting, and final shift */
   /* 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 */
-#define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
+  #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
 #else
-  /* For DECDPUN>4 we currently use non-ANSI 64-bit types.  These could */
-  /* be replaced by subroutine calls later. */
-#ifdef long
-#undef long
-#endif
-typedef signed long long Long;
-typedef unsigned long long uLong;
-#define eInt  Long             /* extended integer */
-#define ueInt uLong            /* unsigned extended integer */
+  /* For DECDPUN>4 non-ANSI-89 64-bit types are needed. */
+  #if !DECUSE64
+    #error decNumber.c: DECUSE64 must be 1 when DECDPUN>4
+  #endif
+  #define eInt Long          /* extended integer */
+  #define ueInt uLong        /* unsigned extended integer */
 #endif
 
 /* Local routines */
-static decNumber *decAddOp (decNumber *, const decNumber *,
-                           const decNumber *, decContext *,
-                           uByte, uInt *);
-static void decApplyRound (decNumber *, decContext *, Int, uInt *);
-static Int decCompare (const decNumber * lhs, const decNumber * rhs);
-static decNumber *decCompareOp (decNumber *, const decNumber *, const decNumber *,
-                               decContext *, Flag, uInt *);
-static void decCopyFit (decNumber *, const decNumber *, decContext *,
-                       Int *, uInt *);
-static decNumber *decDivideOp (decNumber *, const decNumber *, const decNumber *,
-                              decContext *, Flag, uInt *);
-static void decFinalize (decNumber *, decContext *, Int *, uInt *);
-static Int decGetDigits (const Unit *, Int);
-#if DECSUBSET
-static Int decGetInt (const decNumber *, decContext *);
-#else
-static Int decGetInt (const decNumber *);
-#endif
-static decNumber *decMultiplyOp (decNumber *, const decNumber *,
-                                const decNumber *, decContext *, uInt *);
-static decNumber *decNaNs (decNumber *, const decNumber *, const decNumber *, uInt *);
-static decNumber *decQuantizeOp (decNumber *, const decNumber *,
-                                const decNumber *, decContext *, Flag, uInt *);
-static void decSetCoeff (decNumber *, decContext *, const Unit *,
-                        Int, Int *, uInt *);
-static void decSetOverflow (decNumber *, decContext *, uInt *);
-static void decSetSubnormal (decNumber *, decContext *, Int *, uInt *);
-static Int decShiftToLeast (Unit *, Int, Int);
-static Int decShiftToMost (Unit *, Int, Int);
-static void decStatus (decNumber *, uInt, decContext *);
-static Flag decStrEq (const char *, const char *);
-static void decToString (const decNumber *, char[], Flag);
-static decNumber *decTrim (decNumber *, Flag, Int *);
-static Int decUnitAddSub (const Unit *, Int, const Unit *, Int, Int, Unit *, Int);
-static Int decUnitCompare (const Unit *, Int, const Unit *, Int, Int);
+static decNumber * decAddOp(decNumber *, const decNumber *, const decNumber *,
+                             decContext *, uByte, uInt *);
+static Flag       decBiStr(const char *, const char *, const char *);
+static uInt       decCheckMath(const decNumber *, decContext *, uInt *);
+static void       decApplyRound(decNumber *, decContext *, Int, uInt *);
+static Int        decCompare(const decNumber *lhs, const decNumber *rhs, Flag);
+static decNumber * decCompareOp(decNumber *, const decNumber *,
+                             const decNumber *, decContext *,
+                             Flag, uInt *);
+static void       decCopyFit(decNumber *, const decNumber *, decContext *,
+                             Int *, uInt *);
+static decNumber * decDecap(decNumber *, Int);
+static decNumber * decDivideOp(decNumber *, const decNumber *,
+                             const decNumber *, decContext *, Flag, uInt *);
+static decNumber * decExpOp(decNumber *, const decNumber *,
+                             decContext *, uInt *);
+static void       decFinalize(decNumber *, decContext *, Int *, uInt *);
+static Int        decGetDigits(Unit *, Int);
+static Int        decGetInt(const decNumber *);
+static decNumber * decLnOp(decNumber *, const decNumber *,
+                             decContext *, uInt *);
+static decNumber * decMultiplyOp(decNumber *, const decNumber *,
+                             const decNumber *, decContext *,
+                             uInt *);
+static decNumber * decNaNs(decNumber *, const decNumber *,
+                             const decNumber *, decContext *, uInt *);
+static decNumber * decQuantizeOp(decNumber *, const decNumber *,
+                             const decNumber *, decContext *, Flag,
+                             uInt *);
+static void       decReverse(Unit *, Unit *);
+static void       decSetCoeff(decNumber *, decContext *, const Unit *,
+                             Int, Int *, uInt *);
+static void       decSetMaxValue(decNumber *, decContext *);
+static void       decSetOverflow(decNumber *, decContext *, uInt *);
+static void       decSetSubnormal(decNumber *, decContext *, Int *, uInt *);
+static Int        decShiftToLeast(Unit *, Int, Int);
+static Int        decShiftToMost(Unit *, Int, Int);
+static void       decStatus(decNumber *, uInt, decContext *);
+static void       decToString(const decNumber *, char[], Flag);
+static decNumber * decTrim(decNumber *, decContext *, Flag, Int *);
+static Int        decUnitAddSub(const Unit *, Int, const Unit *, Int, Int,
+                             Unit *, Int);
+static Int        decUnitCompare(const Unit *, Int, const Unit *, Int, Int);
 
 #if !DECSUBSET
 /* decFinish == decFinalize when no subset arithmetic needed */
 #define decFinish(a,b,c,d) decFinalize(a,b,c,d)
 #else
-static void decFinish (decNumber *, decContext *, Int *, uInt *);
-static decNumber *decRoundOperand (const decNumber *, decContext *, uInt *);
+static void       decFinish(decNumber *, decContext *, Int *, uInt *);
+static decNumber * decRoundOperand(const decNumber *, decContext *, uInt *);
 #endif
 
+/* Local macros */
+/* masked special-values bits */
+#define SPECIALARG  (rhs->bits & DECSPECIAL)
+#define SPECIALARGS ((lhs->bits | rhs->bits) & DECSPECIAL)
+
 /* Diagnostic macros, etc. */
 #if DECALLOC
 /* Handle malloc/free accounting.  If enabled, our accountable routines */
@@ -266,5698 +287,7836 @@ static decNumber *decRoundOperand (const decNumber *, decContext *, uInt *);
 /* and free routines. */
 #define malloc(a) decMalloc(a)
 #define free(a) decFree(a)
-#define DECFENCE 0x5a          /* corruption detector */
+#define DECFENCE 0x5a             /* corruption detector */
 /* 'Our' malloc and free: */
-static void *decMalloc (size_t);
-static void decFree (void *);
-uInt decAllocBytes = 0;                /* count of bytes allocated */
+static void *decMalloc(size_t);
+static void  decFree(void *);
+uInt decAllocBytes=0;             /* count of bytes allocated */
 /* Note that DECALLOC code only checks for storage buffer overflow. */
-/* To check for memory leaks, the decAllocBytes variable should be */
+/* To check for memory leaks, the decAllocBytes variable must be */
 /* checked to be 0 at appropriate times (e.g., after the test */
 /* harness completes a set of tests).  This checking may be unreliable */
 /* if the testing is done in a multi-thread environment. */
 #endif
 
 #if DECCHECK
-/* Optional operand checking routines.  Enabling these means that */
-/* decNumber and decContext operands to operator routines are checked */
-/* for correctness.  This roughly doubles the execution time of the */
+/* Optional checking routines. Enabling these means that decNumber */
+/* and decContext operands to operator routines are checked for */
+/* correctness.         This roughly doubles the execution time of the */
 /* fastest routines (and adds 600+ bytes), so should not normally be */
 /* used in 'production'. */
-#define DECUNUSED (void *)(0xffffffff)
-static Flag decCheckOperands (decNumber *, const decNumber *,
-                             const decNumber *, decContext *);
-static Flag decCheckNumber (const decNumber *, decContext *);
+/* decCheckInexact is used to check that inexact results have a full */
+/* complement of digits (where appropriate -- this is not the case */
+/* for Quantize, for example) */
+#define DECUNRESU ((decNumber *)(void *)0xffffffff)
+#define DECUNUSED ((const decNumber *)(void *)0xffffffff)
+#define DECUNCONT ((decContext *)(void *)(0xffffffff))
+static Flag decCheckOperands(decNumber *, const decNumber *,
+                            const decNumber *, decContext *);
+static Flag decCheckNumber(const decNumber *);
+static void decCheckInexact(const decNumber *, decContext *);
 #endif
 
 #if DECTRACE || DECCHECK
-/* Optional trace/debugging routines. */
-void decNumberShow (const decNumber *);        /* displays the components of a number */
-static void decDumpAr (char, const Unit *, Int);
+/* Optional trace/debugging routines (may or may not be used) */
+void decNumberShow(const decNumber *); /* displays the components of a number */
+static void decDumpAr(char, const Unit *, Int);
 #endif
 
 /* ================================================================== */
-/* Conversions                                                        */
+/* Conversions                                                       */
 /* ================================================================== */
 
 /* ------------------------------------------------------------------ */
-/* to-scientific-string -- conversion to numeric string               */
-/* to-engineering-string -- conversion to numeric string              */
-/*                                                                    */
-/*   decNumberToString(dn, string);                                   */
-/*   decNumberToEngString(dn, string);                                */
-/*                                                                    */
-/*  dn is the decNumber to convert                                    */
-/*  string is the string where the result will be laid out            */
-/*                                                                    */
-/*  string must be at least dn->digits+14 characters long             */
-/*                                                                    */
-/*  No error is possible, and no status can be set.                   */
-/* ------------------------------------------------------------------ */
-char *
-decNumberToString (const decNumber * dn, char *string)
-{
-  decToString (dn, string, 0);
+/* from-int32 -- conversion from Int or uInt                         */
+/*                                                                   */
+/*  dn is the decNumber to receive the integer                       */
+/*  in or uin is the integer to be converted                         */
+/*  returns dn                                                       */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberFromInt32(decNumber *dn, Int in) {
+  uInt unsig;
+  if (in>=0) unsig=in;
+   else {                              /* negative (possibly BADINT) */
+    if (in==BADINT) unsig=(uInt)1073741824*2; /* special case */
+     else unsig=-in;                   /* invert */
+    }
+  /* in is now positive */
+  decNumberFromUInt32(dn, unsig);
+  if (in<0) dn->bits=DECNEG;           /* sign needed */
+  return dn;
+  } /* decNumberFromInt32 */
+
+decNumber * decNumberFromUInt32(decNumber *dn, uInt uin) {
+  Unit *up;                            /* work pointer */
+  decNumberZero(dn);                   /* clean */
+  if (uin==0) return dn;               /* [or decGetDigits bad call] */
+  for (up=dn->lsu; uin>0; up++) {
+    *up=(Unit)(uin%(DECDPUNMAX+1));
+    uin=uin/(DECDPUNMAX+1);
+    }
+  dn->digits=decGetDigits(dn->lsu, up-dn->lsu);
+  return dn;
+  } /* decNumberFromUInt32 */
+
+/* ------------------------------------------------------------------ */
+/* to-int32 -- conversion to Int or uInt                             */
+/*                                                                   */
+/*  dn is the decNumber to convert                                   */
+/*  set is the context for reporting errors                          */
+/*  returns the converted decNumber, or 0 if Invalid is set          */
+/*                                                                   */
+/* Invalid is set if the decNumber does not have exponent==0 or if    */
+/* it is a NaN, Infinite, or out-of-range.                           */
+/* ------------------------------------------------------------------ */
+Int decNumberToInt32(const decNumber *dn, decContext *set) {
+  #if DECCHECK
+  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
+  #endif
+
+  /* special or too many digits, or bad exponent */
+  if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0) ; /* bad */
+   else { /* is a finite integer with 10 or fewer digits */
+    Int d;                        /* work */
+    const Unit *up;               /* .. */
+    uInt hi=0, lo;                /* .. */
+    up=dn->lsu;                           /* -> lsu */
+    lo=*up;                       /* get 1 to 9 digits */
+    #if DECDPUN>1                 /* split to higher */
+      hi=lo/10;
+      lo=lo%10;
+    #endif
+    up++;
+    /* collect remaining Units, if any, into hi */
+    for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
+    /* now low has the lsd, hi the remainder */
+    if (hi>214748364 || (hi==214748364 && lo>7)) { /* out of range? */
+      /* most-negative is a reprieve */
+      if (dn->bits&DECNEG && hi==214748364 && lo==8) return 0x80000000;
+      /* bad -- drop through */
+      }
+     else { /* in-range always */
+      Int i=X10(hi)+lo;
+      if (dn->bits&DECNEG) return -i;
+      return i;
+      }
+    } /* integer */
+  decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
+  return 0;
+  } /* decNumberToInt32 */
+
+uInt decNumberToUInt32(const decNumber *dn, decContext *set) {
+  #if DECCHECK
+  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
+  #endif
+  /* special or too many digits, or bad exponent, or negative (<0) */
+  if (dn->bits&DECSPECIAL || dn->digits>10 || dn->exponent!=0
+    || (dn->bits&DECNEG && !ISZERO(dn)));                  /* bad */
+   else { /* is a finite integer with 10 or fewer digits */
+    Int d;                        /* work */
+    const Unit *up;               /* .. */
+    uInt hi=0, lo;                /* .. */
+    up=dn->lsu;                           /* -> lsu */
+    lo=*up;                       /* get 1 to 9 digits */
+    #if DECDPUN>1                 /* split to higher */
+      hi=lo/10;
+      lo=lo%10;
+    #endif
+    up++;
+    /* collect remaining Units, if any, into hi */
+    for (d=DECDPUN; d<dn->digits; up++, d+=DECDPUN) hi+=*up*powers[d-1];
+
+    /* now low has the lsd, hi the remainder */
+    if (hi>429496729 || (hi==429496729 && lo>5)) ; /* no reprieve possible */
+     else return X10(hi)+lo;
+    } /* integer */
+  decContextSetStatus(set, DEC_Invalid_operation); /* [may not return] */
+  return 0;
+  } /* decNumberToUInt32 */
+
+/* ------------------------------------------------------------------ */
+/* to-scientific-string -- conversion to numeric string                      */
+/* to-engineering-string -- conversion to numeric string             */
+/*                                                                   */
+/*   decNumberToString(dn, string);                                  */
+/*   decNumberToEngString(dn, string);                               */
+/*                                                                   */
+/*  dn is the decNumber to convert                                   */
+/*  string is the string where the result will be laid out           */
+/*                                                                   */
+/*  string must be at least dn->digits+14 characters long            */
+/*                                                                   */
+/*  No error is possible, and no status can be set.                  */
+/* ------------------------------------------------------------------ */
+char * decNumberToString(const decNumber *dn, char *string){
+  decToString(dn, string, 0);
   return string;
-}
+  } /* DecNumberToString */
 
-char *
-decNumberToEngString (const decNumber * dn, char *string)
-{
-  decToString (dn, string, 1);
+char * decNumberToEngString(const decNumber *dn, char *string){
+  decToString(dn, string, 1);
   return string;
-}
-
-/* ------------------------------------------------------------------ */
-/* to-number -- conversion from numeric string                        */
-/*                                                                    */
-/* decNumberFromString -- convert string to decNumber                 */
-/*   dn        -- the number structure to fill                        */
-/*   chars[]   -- the string to convert ('\0' terminated)             */
-/*   set       -- the context used for processing any error,          */
-/*                determining the maximum precision available         */
-/*                (set.digits), determining the maximum and minimum   */
-/*                exponent (set.emax and set.emin), determining if    */
-/*                extended values are allowed, and checking the       */
-/*                rounding mode if overflow occurs or rounding is     */
-/*                needed.                                             */
-/*                                                                    */
+  } /* DecNumberToEngString */
+
+/* ------------------------------------------------------------------ */
+/* to-number -- conversion from numeric string                       */
+/*                                                                   */
+/* decNumberFromString -- convert string to decNumber                */
+/*   dn               -- the number structure to fill                        */
+/*   chars[]   -- the string to convert ('\0' terminated)            */
+/*   set       -- the context used for processing any error,         */
+/*               determining the maximum precision available         */
+/*               (set.digits), determining the maximum and minimum   */
+/*               exponent (set.emax and set.emin), determining if    */
+/*               extended values are allowed, and checking the       */
+/*               rounding mode if overflow occurs or rounding is     */
+/*               needed.                                             */
+/*                                                                   */
 /* The length of the coefficient and the size of the exponent are     */
-/* checked by this routine, so the correct error (Underflow or        */
-/* Overflow) can be reported or rounding applied, as necessary.       */
-/*                                                                    */
-/* If bad syntax is detected, the result will be a quiet NaN.         */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberFromString (decNumber * dn, const char chars[], decContext * set)
-{
-  Int exponent = 0;            /* working exponent [assume 0] */
-  uByte bits = 0;              /* working flags [assume +ve] */
-  Unit *res;                   /* where result will be built */
-  Unit resbuff[D2U (DECBUFFER + 1)];   /* local buffer in case need temporary */
-  Unit *allocres = NULL;       /* -> allocated result, iff allocated */
-  Int need;                    /* units needed for result */
-  Int d = 0;                   /* count of digits found in decimal part */
-  const char *dotchar = NULL;  /* where dot was found */
-  const char *cfirst;          /* -> first character of decimal part */
-  const char *last = NULL;     /* -> last digit of decimal part */
-  const char *firstexp;                /* -> first significant exponent digit */
-  const char *c;               /* work */
-  Unit *up;                    /* .. */
-#if DECDPUN>1
-  Int i;                       /* .. */
-#endif
-  Int residue = 0;             /* rounding residue */
-  uInt status = 0;             /* error code */
-
-#if DECCHECK
-  if (decCheckOperands (DECUNUSED, DECUNUSED, DECUNUSED, set))
-    return decNumberZero (dn);
-#endif
-
-  do
-    {                          /* status & malloc protection */
-      c = chars;               /* -> input character */
-      if (*c == '-')
-       {                       /* handle leading '-' */
-         bits = DECNEG;
-         c++;
+/* checked by this routine, so the correct error (Underflow or       */
+/* Overflow) can be reported or rounding applied, as necessary.              */
+/*                                                                   */
+/* If bad syntax is detected, the result will be a quiet NaN.        */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberFromString(decNumber *dn, const char chars[],
+                               decContext *set) {
+  Int  exponent=0;                /* working exponent [assume 0] */
+  uByte bits=0;                           /* working flags [assume +ve] */
+  Unit *res;                      /* where result will be built */
+  Unit resbuff[SD2U(DECBUFFER+9)];/* local buffer in case need temporary */
+                                  /* [+9 allows for ln() constants] */
+  Unit *allocres=NULL;            /* -> allocated result, iff allocated */
+  Int  d=0;                       /* count of digits found in decimal part */
+  const char *dotchar=NULL;       /* where dot was found */
+  const char *cfirst=chars;       /* -> first character of decimal part */
+  const char *last=NULL;          /* -> last digit of decimal part */
+  const char *c;                  /* work */
+  Unit *up;                       /* .. */
+  #if DECDPUN>1
+  Int  cut, out;                  /* .. */
+  #endif
+  Int  residue;                   /* rounding residue */
+  uInt status=0;                  /* error code */
+
+  #if DECCHECK
+  if (decCheckOperands(DECUNRESU, DECUNUSED, DECUNUSED, set))
+    return decNumberZero(dn);
+  #endif
+
+  do {                            /* status & malloc protection */
+    for (c=chars;; c++) {         /* -> input character */
+      if (*c>='0' && *c<='9') {           /* test for Arabic digit */
+       last=c;
+       d++;                       /* count of real digits */
+       continue;                  /* still in decimal part */
        }
-      else if (*c == '+')
-       c++;                    /* step over leading '+' */
-      /* We're at the start of the number [we think] */
-      cfirst = c;              /* save */
-      for (;; c++)
-       {
-         if (*c >= '0' && *c <= '9')
-           {                   /* test for Arabic digit */
-             last = c;
-             d++;              /* count of real digits */
-             continue;         /* still in decimal part */
-           }
-         if (*c != '.')
-           break;              /* done with decimal part */
-         /* dot: record, check, and ignore */
-         if (dotchar != NULL)
-           {                   /* two dots */
-             last = NULL;      /* indicate bad */
-             break;
-           }                   /* .. and go report */
-         dotchar = c;          /* offset into decimal part */
-       }                       /* c */
-
-      if (last == NULL)
-       {                       /* no decimal digits, or >1 . */
-#if DECSUBSET
-         /* If subset then infinities and NaNs are not allowed */
-         if (!set->extended)
-           {
-             status = DEC_Conversion_syntax;
-             break;            /* all done */
-           }
-         else
-           {
-#endif
-             /* Infinities and NaNs are possible, here */
-             decNumberZero (dn);       /* be optimistic */
-             if (decStrEq (c, "Infinity") || decStrEq (c, "Inf"))
-               {
-                 dn->bits = bits | DECINF;
-                 break;        /* all done */
-               }
-             else
-               {               /* a NaN expected */
-                 /* 2003.09.10 NaNs are now permitted to have a sign */
-                 status = DEC_Conversion_syntax;       /* assume the worst */
-                 dn->bits = bits | DECNAN;     /* assume simple NaN */
-                 if (*c == 's' || *c == 'S')
-                   {           /* looks like an` sNaN */
-                     c++;
-                     dn->bits = bits | DECSNAN;
-                   }
-                 if (*c != 'n' && *c != 'N')
-                   break;      /* check caseless "NaN" */
-                 c++;
-                 if (*c != 'a' && *c != 'A')
-                   break;      /* .. */
-                 c++;
-                 if (*c != 'n' && *c != 'N')
-                   break;      /* .. */
-                 c++;
-                 /* now nothing, or nnnn, expected */
-                 /* -> start of integer and skip leading 0s [including plain 0] */
-                 for (cfirst = c; *cfirst == '0';)
-                   cfirst++;
-                 if (*cfirst == '\0')
-                   {           /* "NaN" or "sNaN", maybe with all 0s */
-                     status = 0;       /* it's good */
-                     break;    /* .. */
-                   }
-                 /* something other than 0s; setup last and d as usual [no dots] */
-                 for (c = cfirst;; c++, d++)
-                   {
-                     if (*c < '0' || *c > '9')
-                       break;  /* test for Arabic digit */
-                     last = c;
-                   }
-                 if (*c != '\0')
-                   break;      /* not all digits */
-                 if (d > set->digits)
-                   break;      /* too many digits */
-                 /* good; drop through and convert the integer */
-                 status = 0;
-                 bits = dn->bits;      /* for copy-back */
-               }               /* NaN expected */
-#if DECSUBSET
-           }
-#endif
-       }                       /* last==NULL */
-
-      if (*c != '\0')
-       {                       /* more there; exponent expected... */
-         Flag nege = 0;        /* 1=negative exponent */
-         if (*c != 'e' && *c != 'E')
-           {
-             status = DEC_Conversion_syntax;
-             break;
-           }
-
-         /* Found 'e' or 'E' -- now process explicit exponent */
-         /* 1998.07.11: sign no longer required */
-         c++;                  /* to (expected) sign */
-         if (*c == '-')
-           {
-             nege = 1;
-             c++;
-           }
-         else if (*c == '+')
-           c++;
-         if (*c == '\0')
-           {
-             status = DEC_Conversion_syntax;
-             break;
-           }
-
-         for (; *c == '0' && *(c + 1) != '\0';)
-           c++;                /* strip insignificant zeros */
-         firstexp = c;         /* save exponent digit place */
-         for (;; c++)
-           {
-             if (*c < '0' || *c > '9')
-               break;          /* not a digit */
-             exponent = X10 (exponent) + (Int) * c - (Int) '0';
-           }                   /* c */
-         /* if we didn't end on '\0' must not be a digit */
-         if (*c != '\0')
-           {
-             status = DEC_Conversion_syntax;
-             break;
-           }
-
-         /* (this next test must be after the syntax check) */
-         /* if it was too long the exponent may have wrapped, so check */
-         /* carefully and set it to a certain overflow if wrap possible */
-         if (c >= firstexp + 9 + 1)
-           {
-             if (c > firstexp + 9 + 1 || *firstexp > '1')
-               exponent = DECNUMMAXE * 2;
-             /* [up to 1999999999 is OK, for example 1E-1000000998] */
-           }
-         if (nege)
-           exponent = -exponent;       /* was negative */
-       }                       /* had exponent */
-      /* Here when all inspected; syntax is good */
-
-      /* Handle decimal point... */
-      if (dotchar != NULL && dotchar < last)   /* embedded . found, so */
-       exponent = exponent - (last - dotchar); /* .. adjust exponent */
-      /* [we can now ignore the .] */
-
-      /* strip leading zeros/dot (leave final if all 0's) */
-      for (c = cfirst; c < last; c++)
-       {
-         if (*c == '0')
-           d--;                /* 0 stripped */
-         else if (*c != '.')
-           break;
-         cfirst++;             /* step past leader */
-       }                       /* c */
-
-#if DECSUBSET
-      /* We can now make a rapid exit for zeros if !extended */
-      if (*cfirst == '0' && !set->extended)
-       {
-         decNumberZero (dn);   /* clean result */
-         break;                /* [could be return] */
+      if (*c=='.' && dotchar==NULL) { /* first '.' */
+       dotchar=c;                 /* record offset into decimal part */
+       if (c==cfirst) cfirst++;   /* first digit must follow */
+       continue;}
+      if (c==chars) {             /* first in string... */
+       if (*c=='-') {             /* valid - sign */
+         cfirst++;
+         bits=DECNEG;
+         continue;}
+       if (*c=='+') {             /* valid + sign */
+         cfirst++;
+         continue;}
        }
-#endif
-
-      /* OK, the digits string is good.  Copy to the decNumber, or to
-         a temporary decNumber if rounding is needed */
-      if (d <= set->digits)
-       res = dn->lsu;          /* fits into given decNumber */
-      else
-       {                       /* rounding needed */
-         need = D2U (d);       /* units needed */
-         res = resbuff;        /* assume use local buffer */
-         if (need * sizeof (Unit) > sizeof (resbuff))
-           {                   /* too big for local */
-             allocres = (Unit *) malloc (need * sizeof (Unit));
-             if (allocres == NULL)
-               {
-                 status |= DEC_Insufficient_storage;
-                 break;
-               }
-             res = allocres;
-           }
+      /* *c is not a digit, or a valid +, -, or '.' */
+      break;
+      } /* c */
+
+    if (last==NULL) {             /* no digits yet */
+      status=DEC_Conversion_syntax;/* assume the worst */
+      if (*c=='\0') break;        /* and no more to come... */
+      #if DECSUBSET
+      /* if subset then infinities and NaNs are not allowed */
+      if (!set->extended) break;   /* hopeless */
+      #endif
+      /* Infinities and NaNs are possible, here */
+      if (dotchar!=NULL) break;           /* .. unless had a dot */
+      decNumberZero(dn);          /* be optimistic */
+      if (decBiStr(c, "infinity", "INFINITY")
+       || decBiStr(c, "inf", "INF")) {
+       dn->bits=bits | DECINF;
+       status=0;                  /* is OK */
+       break; /* all done */
        }
-      /* res now -> number lsu, buffer, or allocated storage for Unit array */
-
-      /* Place the coefficient into the selected Unit array */
-#if DECDPUN>1
-      i = d % DECDPUN;         /* digits in top unit */
-      if (i == 0)
-       i = DECDPUN;
-      up = res + D2U (d) - 1;  /* -> msu */
-      *up = 0;
-      for (c = cfirst;; c++)
-       {                       /* along the digits */
-         if (*c == '.')
-           {                   /* ignore . [don't decrement i] */
-             if (c != last)
-               continue;
-             break;
-           }
-         *up = (Unit) (X10 (*up) + (Int) * c - (Int) '0');
-         i--;
-         if (i > 0)
-           continue;           /* more for this unit */
-         if (up == res)
-           break;              /* just filled the last unit */
-         i = DECDPUN;
-         up--;
-         *up = 0;
-       }                       /* c */
-#else
-      /* DECDPUN==1 */
-      up = res;                        /* -> lsu */
-      for (c = last; c >= cfirst; c--)
-       {                       /* over each character, from least */
-         if (*c == '.')
-           continue;           /* ignore . [don't step b] */
-         *up = (Unit) ((Int) * c - (Int) '0');
-         up++;
-       }                       /* c */
-#endif
-
-      dn->bits = bits;
-      dn->exponent = exponent;
-      dn->digits = d;
-
-      /* if not in number (too long) shorten into the number */
-      if (d > set->digits)
-       decSetCoeff (dn, set, res, d, &residue, &status);
-
-      /* Finally check for overflow or subnormal and round as needed */
-      decFinalize (dn, set, &residue, &status);
-      /* decNumberShow(dn); */
-    }
-  while (0);                   /* [for break] */
+      /* a NaN expected */
+      /* 2003.09.10 NaNs are now permitted to have a sign */
+      dn->bits=bits | DECNAN;     /* assume simple NaN */
+      if (*c=='s' || *c=='S') {           /* looks like an sNaN */
+       c++;
+       dn->bits=bits | DECSNAN;
+       }
+      if (*c!='n' && *c!='N') break;   /* check caseless "NaN" */
+      c++;
+      if (*c!='a' && *c!='A') break;   /* .. */
+      c++;
+      if (*c!='n' && *c!='N') break;   /* .. */
+      c++;
+      /* now either nothing, or nnnn payload, expected */
+      /* -> start of integer and skip leading 0s [including plain 0] */
+      for (cfirst=c; *cfirst=='0';) cfirst++;
+      if (*cfirst=='\0') {        /* "NaN" or "sNaN", maybe with all 0s */
+       status=0;                  /* it's good */
+       break;                     /* .. */
+       }
+      /* something other than 0s; setup last and d as usual [no dots] */
+      for (c=cfirst;; c++, d++) {
+       if (*c<'0' || *c>'9') break; /* test for Arabic digit */
+       last=c;
+       }
+      if (*c!='\0') break;        /* not all digits */
+      if (d>set->digits-1) {
+       /* [NB: payload in a decNumber can be full length unless */
+       /* clamped, in which case can only be digits-1] */
+       if (set->clamp) break;
+       if (d>set->digits) break;
+       } /* too many digits? */
+      /* good; drop through to convert the integer to coefficient */
+      status=0;                           /* syntax is OK */
+      bits=dn->bits;              /* for copy-back */
+      } /* last==NULL */
+
+     else if (*c!='\0') {         /* more to process... */
+      /* had some digits; exponent is only valid sequence now */
+      Flag nege;                  /* 1=negative exponent */
+      const char *firstexp;       /* -> first significant exponent digit */
+      status=DEC_Conversion_syntax;/* assume the worst */
+      if (*c!='e' && *c!='E') break;
+      /* Found 'e' or 'E' -- now process explicit exponent */
+      /* 1998.07.11: sign no longer required */
+      nege=0;
+      c++;                        /* to (possible) sign */
+      if (*c=='-') {nege=1; c++;}
+       else if (*c=='+') c++;
+      if (*c=='\0') break;
+
+      for (; *c=='0' && *(c+1)!='\0';) c++;  /* strip insignificant zeros */
+      firstexp=c;                           /* save exponent digit place */
+      for (; ;c++) {
+       if (*c<'0' || *c>'9') break;         /* not a digit */
+       exponent=X10(exponent)+(Int)*c-(Int)'0';
+       } /* c */
+      /* if not now on a '\0', *c must not be a digit */
+      if (*c!='\0') break;
+
+      /* (this next test must be after the syntax checks) */
+      /* if it was too long the exponent may have wrapped, so check */
+      /* carefully and set it to a certain overflow if wrap possible */
+      if (c>=firstexp+9+1) {
+       if (c>firstexp+9+1 || *firstexp>'1') exponent=DECNUMMAXE*2;
+       /* [up to 1999999999 is OK, for example 1E-1000000998] */
+       }
+      if (nege) exponent=-exponent;    /* was negative */
+      status=0;                                /* is OK */
+      } /* stuff after digits */
+
+    /* Here when whole string has been inspected; syntax is good */
+    /* cfirst->first digit (never dot), last->last digit (ditto) */
+
+    /* strip leading zeros/dot [leave final 0 if all 0's] */
+    if (*cfirst=='0') {                        /* [cfirst has stepped over .] */
+      for (c=cfirst; c<last; c++, cfirst++) {
+       if (*c=='.') continue;          /* ignore dots */
+       if (*c!='0') break;             /* non-zero found */
+       d--;                            /* 0 stripped */
+       } /* c */
+      #if DECSUBSET
+      /* make a rapid exit for easy zeros if !extended */
+      if (*cfirst=='0' && !set->extended) {
+       decNumberZero(dn);              /* clean result */
+       break;                          /* [could be return] */
+       }
+      #endif
+      } /* at least one leading 0 */
+
+    /* Handle decimal point... */
+    if (dotchar!=NULL && dotchar<last) /* non-trailing '.' found? */
+      exponent-=(last-dotchar);                /* adjust exponent */
+    /* [we can now ignore the .] */
+
+    /* OK, the digits string is good.  Assemble in the decNumber, or in */
+    /* a temporary units array if rounding is needed */
+    if (d<=set->digits) res=dn->lsu;   /* fits into supplied decNumber */
+     else {                            /* rounding needed */
+      Int needbytes=D2U(d)*sizeof(Unit);/* bytes needed */
+      res=resbuff;                     /* assume use local buffer */
+      if (needbytes>(Int)sizeof(resbuff)) { /* too big for local */
+       allocres=(Unit *)malloc(needbytes);
+       if (allocres==NULL) {status|=DEC_Insufficient_storage; break;}
+       res=allocres;
+       }
+      }
+    /* res now -> number lsu, buffer, or allocated storage for Unit array */
+
+    /* Place the coefficient into the selected Unit array */
+    /* [this is often 70% of the cost of this function when DECDPUN>1] */
+    #if DECDPUN>1
+    out=0;                        /* accumulator */
+    up=res+D2U(d)-1;              /* -> msu */
+    cut=d-(up-res)*DECDPUN;       /* digits in top unit */
+    for (c=cfirst;; c++) {        /* along the digits */
+      if (*c=='.') continue;      /* ignore '.' [don't decrement cut] */
+      out=X10(out)+(Int)*c-(Int)'0';
+      if (c==last) break;         /* done [never get to trailing '.'] */
+      cut--;
+      if (cut>0) continue;        /* more for this unit */
+      *up=(Unit)out;              /* write unit */
+      up--;                       /* prepare for unit below.. */
+      cut=DECDPUN;                /* .. */
+      out=0;                      /* .. */
+      } /* c */
+    *up=(Unit)out;                /* write lsu */
+
+    #else
+    /* DECDPUN==1 */
+    up=res;                       /* -> lsu */
+    for (c=last; c>=cfirst; c--) { /* over each character, from least */
+      if (*c=='.') continue;      /* ignore . [don't step up] */
+      *up=(Unit)((Int)*c-(Int)'0');
+      up++;
+      } /* c */
+    #endif
+
+    dn->bits=bits;
+    dn->exponent=exponent;
+    dn->digits=d;
+
+    /* if not in number (too long) shorten into the number */
+    if (d>set->digits) {
+      residue=0;
+      decSetCoeff(dn, set, res, d, &residue, &status);
+      /* always check for overflow or subnormal and round as needed */
+      decFinalize(dn, set, &residue, &status);
+      }
+     else { /* no rounding, but may still have overflow or subnormal */
+      /* [these tests are just for performance; finalize repeats them] */
+      if ((dn->exponent-1<set->emin-dn->digits)
+       || (dn->exponent-1>set->emax-set->digits)) {
+       residue=0;
+       decFinalize(dn, set, &residue, &status);
+       }
+      }
+    /* decNumberShow(dn); */
+    } while(0);                                /* [for break] */
 
-  if (allocres != NULL)
-    free (allocres);           /* drop any storage we used */
-  if (status != 0)
-    decStatus (dn, status, set);
+  if (allocres!=NULL) free(allocres);  /* drop any storage used */
+  if (status!=0) decStatus(dn, status, set);
   return dn;
-}
+  } /* decNumberFromString */
 
 /* ================================================================== */
-/* Operators                                                          */
+/* Operators                                                         */
 /* ================================================================== */
 
 /* ------------------------------------------------------------------ */
-/* decNumberAbs -- absolute value operator                            */
-/*                                                                    */
-/*   This computes C = abs(A)                                         */
-/*                                                                    */
-/*   res is C, the result.  C may be A                                */
-/*   rhs is A                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
+/* decNumberAbs -- absolute value operator                           */
+/*                                                                   */
+/*   This computes C = abs(A)                                        */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* See also decNumberCopyAbs for a quiet bitwise version of this.     */
+/* C must have space for set->digits digits.                         */
 /* ------------------------------------------------------------------ */
 /* This has the same effect as decNumberPlus unless A is negative,    */
-/* in which case it has the same effect as decNumberMinus.            */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberAbs (decNumber * res, const decNumber * rhs, decContext * set)
-{
-  decNumber dzero;             /* for 0 */
-  uInt status = 0;             /* accumulator */
-
-#if DECCHECK
-  if (decCheckOperands (res, DECUNUSED, rhs, set))
+/* in which case it has the same effect as decNumberMinus.           */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberAbs(decNumber *res, const decNumber *rhs,
+                        decContext *set) {
+  decNumber dzero;                     /* for 0 */
+  uInt status=0;                       /* accumulator */
+
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  decNumberZero(&dzero);               /* set 0 */
+  dzero.exponent=rhs->exponent;                /* [no coefficient expansion] */
+  decAddOp(res, &dzero, rhs, set, (uByte)(rhs->bits & DECNEG), &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberAbs */
+
+/* ------------------------------------------------------------------ */
+/* decNumberAdd -- add two Numbers                                   */
+/*                                                                   */
+/*   This computes C = A + B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+/* This just calls the routine shared with Subtract                  */
+decNumber * decNumberAdd(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decAddOp(res, lhs, rhs, set, 0, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberAdd */
+
+/* ------------------------------------------------------------------ */
+/* decNumberAnd -- AND two Numbers, digitwise                        */
+/*                                                                   */
+/*   This computes C = A & B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X&X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context (used for result length and error report)     */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Logical function restrictions apply (see above); a NaN is         */
+/* returned with Invalid_operation if a restriction is violated.      */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberAnd(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, decContext *set) {
+  const Unit *ua, *ub;                 /* -> operands */
+  const Unit *msua, *msub;             /* -> operand msus */
+  Unit *uc,  *msuc;                    /* -> result and its msu */
+  Int  msudigs;                        /* digits in res msu */
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
+   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
+    decStatus(res, DEC_Invalid_operation, set);
     return res;
-#endif
+    }
 
-  decNumberZero (&dzero);      /* set 0 */
-  dzero.exponent = rhs->exponent;      /* [no coefficient expansion] */
-  decAddOp (res, &dzero, rhs, set, (uByte) (rhs->bits & DECNEG), &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  /* operands are valid */
+  ua=lhs->lsu;                         /* bottom-up */
+  ub=rhs->lsu;                         /* .. */
+  uc=res->lsu;                         /* .. */
+  msua=ua+D2U(lhs->digits)-1;          /* -> msu of lhs */
+  msub=ub+D2U(rhs->digits)-1;          /* -> msu of rhs */
+  msuc=uc+D2U(set->digits)-1;          /* -> msu of result */
+  msudigs=MSUDIGITS(set->digits);      /* [faster than remainder] */
+  for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
+    Unit a, b;                         /* extract units */
+    if (ua>msua) a=0;
+     else a=*ua;
+    if (ub>msub) b=0;
+     else b=*ub;
+    *uc=0;                             /* can now write back */
+    if (a|b) {                         /* maybe 1 bits to examine */
+      Int i, j;
+      *uc=0;                           /* can now write back */
+      /* This loop could be unrolled and/or use BIN2BCD tables */
+      for (i=0; i<DECDPUN; i++) {
+       if (a&b&1) *uc=*uc+(Unit)powers[i];  /* effect AND */
+       j=a%10;
+       a=a/10;
+       j|=b%10;
+       b=b/10;
+       if (j>1) {
+         decStatus(res, DEC_Invalid_operation, set);
+         return res;
+         }
+       if (uc==msuc && i==msudigs-1) break; /* just did final digit */
+       } /* each digit */
+      } /* both OK */
+    } /* each unit */
+  /* [here uc-1 is the msu of the result] */
+  res->digits=decGetDigits(res->lsu, uc-res->lsu);
+  res->exponent=0;                     /* integer */
+  res->bits=0;                         /* sign=0 */
+  return res;  /* [no status to set] */
+  } /* decNumberAnd */
+
+/* ------------------------------------------------------------------ */
+/* decNumberCompare -- compare two Numbers                           */
+/*                                                                   */
+/*   This computes C = A ? B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for one digit (or NaN).                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberCompare(decNumber *res, const decNumber *lhs,
+                            const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decCompareOp(res, lhs, rhs, set, COMPARE, &status);
+  if (status!=0) decStatus(res, status, set);
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberAdd -- add two Numbers                                    */
-/*                                                                    */
-/*   This computes C = A + B                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-/* This just calls the routine shared with Subtract                   */
-decNumber *
-decNumberAdd (decNumber * res, const decNumber * lhs,
-             const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decAddOp (res, lhs, rhs, set, 0, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  } /* decNumberCompare */
+
+/* ------------------------------------------------------------------ */
+/* decNumberCompareSignal -- compare, signalling on all NaNs         */
+/*                                                                   */
+/*   This computes C = A ? B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for one digit (or NaN).                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberCompareSignal(decNumber *res, const decNumber *lhs,
+                                  const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decCompareOp(res, lhs, rhs, set, COMPSIG, &status);
+  if (status!=0) decStatus(res, status, set);
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberCompare -- compare two Numbers                            */
-/*                                                                    */
-/*   This computes C = A ? B                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for one digit.                                   */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberCompare (decNumber * res, const decNumber * lhs,
-                 const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decCompareOp (res, lhs, rhs, set, COMPARE, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  } /* decNumberCompareSignal */
+
+/* ------------------------------------------------------------------ */
+/* decNumberCompareTotal -- compare two Numbers, using 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)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for one digit; the result will always be one of  */
+/* -1, 0, or 1.                                                              */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberCompareTotal(decNumber *res, const decNumber *lhs,
+                                 const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
+  if (status!=0) decStatus(res, status, set);
+  return res;
+  } /* decNumberCompareTotal */
+
+/* ------------------------------------------------------------------ */
+/* decNumberCompareTotalMag -- compare, total ordering of magnitudes  */
+/*                                                                   */
+/*   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)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for one digit; the result will always be one of  */
+/* -1, 0, or 1.                                                              */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberCompareTotalMag(decNumber *res, const decNumber *lhs,
+                                    const decNumber *rhs, decContext *set) {
+  uInt status=0;                  /* accumulator */
+  uInt needbytes;                 /* for space calculations */
+  decNumber bufa[D2N(DECBUFFER+1)];/* +1 in case DECBUFFER=0 */
+  decNumber *allocbufa=NULL;      /* -> allocated bufa, iff allocated */
+  decNumber bufb[D2N(DECBUFFER+1)];
+  decNumber *allocbufb=NULL;      /* -> allocated bufb, iff allocated */
+  decNumber *a, *b;               /* temporary pointers */
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  do {                                 /* protect allocated storage */
+    /* if either is negative, take a copy and absolute */
+    if (decNumberIsNegative(lhs)) {    /* lhs<0 */
+      a=bufa;
+      needbytes=sizeof(decNumber)+(D2U(lhs->digits)-1)*sizeof(Unit);
+      if (needbytes>sizeof(bufa)) {    /* need malloc space */
+       allocbufa=(decNumber *)malloc(needbytes);
+       if (allocbufa==NULL) {          /* hopeless -- abandon */
+         status|=DEC_Insufficient_storage;
+         break;}
+       a=allocbufa;                    /* use the allocated space */
+       }
+      decNumberCopy(a, lhs);           /* copy content */
+      a->bits&=~DECNEG;                        /* .. and clear the sign */
+      lhs=a;                           /* use copy from here on */
+      }
+    if (decNumberIsNegative(rhs)) {    /* rhs<0 */
+      b=bufb;
+      needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
+      if (needbytes>sizeof(bufb)) {    /* need malloc space */
+       allocbufb=(decNumber *)malloc(needbytes);
+       if (allocbufb==NULL) {          /* hopeless -- abandon */
+         status|=DEC_Insufficient_storage;
+         break;}
+       b=allocbufb;                    /* use the allocated space */
+       }
+      decNumberCopy(b, rhs);           /* copy content */
+      b->bits&=~DECNEG;                        /* .. and clear the sign */
+      rhs=b;                           /* use copy from here on */
+      }
+    decCompareOp(res, lhs, rhs, set, COMPTOTAL, &status);
+    } while(0);                                /* end protected */
+
+  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
+  if (allocbufb!=NULL) free(allocbufb); /* .. */
+  if (status!=0) decStatus(res, status, set);
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberDivide -- divide one number by another                    */
-/*                                                                    */
-/*   This computes C = A / B                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X/X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberDivide (decNumber * res, const decNumber * lhs,
-                const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decDivideOp (res, lhs, rhs, set, DIVIDE, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  } /* decNumberCompareTotalMag */
+
+/* ------------------------------------------------------------------ */
+/* decNumberDivide -- divide one number by another                   */
+/*                                                                   */
+/*   This computes C = A / B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X/X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberDivide(decNumber *res, const decNumber *lhs,
+                           const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decDivideOp(res, lhs, rhs, set, DIVIDE, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
+  } /* decNumberDivide */
 
 /* ------------------------------------------------------------------ */
-/* decNumberDivideInteger -- divide and return integer quotient       */
-/*                                                                    */
+/* decNumberDivideInteger -- divide and return integer quotient              */
+/*                                                                   */
 /*   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)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberDivideInteger (decNumber * res, const decNumber * lhs,
-                       const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decDivideOp (res, lhs, rhs, set, DIVIDEINT, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X#X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberDivideInteger(decNumber *res, const decNumber *lhs,
+                                  const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decDivideOp(res, lhs, rhs, set, DIVIDEINT, &status);
+  if (status!=0) decStatus(res, status, set);
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberMax -- compare two Numbers and return the maximum         */
-/*                                                                    */
-/*   This computes C = A ? B, returning the maximum or A if equal     */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberMax (decNumber * res, const decNumber * lhs,
-             const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decCompareOp (res, lhs, rhs, set, COMPMAX, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  } /* decNumberDivideInteger */
+
+/* ------------------------------------------------------------------ */
+/* decNumberExp -- exponentiation                                    */
+/*                                                                   */
+/*   This computes C = exp(A)                                        */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context; note that rounding mode has no effect       */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Mathematical function restrictions apply (see above); a NaN is     */
+/* returned with Invalid_operation if a restriction is violated.      */
+/*                                                                   */
+/* Finite results will always be full precision and Inexact, except   */
+/* when A is a zero or -Infinity (giving 1 or 0 respectively).       */
+/*                                                                   */
+/* 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      */
+/* error in rare cases.                                                      */
+/* ------------------------------------------------------------------ */
+/* This is a wrapper for decExpOp which can handle the slightly wider */
+/* (double) range needed by Ln (which has to be able to calculate     */
+/* exp(-a) where a can be the tiniest number (Ntiny).                */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberExp(decNumber *res, const decNumber *rhs,
+                        decContext *set) {
+  uInt status=0;                       /* accumulator */
+  #if DECSUBSET
+  decNumber *allocrhs=NULL;       /* non-NULL if rounded rhs allocated */
+  #endif
+
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  /* Check restrictions; these restrictions ensure that if h=8 (see */
+  /* decExpOp) then the result will either overflow or underflow to 0. */
+  /* Other math functions restrict the input range, too, for inverses. */
+  /* If not violated then carry out the operation. */
+  if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operand and set lostDigits status, as needed */
+      if (rhs->digits>set->digits) {
+       allocrhs=decRoundOperand(rhs, set, &status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
+       }
+      }
+    #endif
+    decExpOp(res, rhs, set, &status);
+    } while(0);                                /* end protected */
+
+  #if DECSUBSET
+  if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */
+  #endif
+  /* apply significant status */
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberMin -- compare two Numbers and return the minimum         */
-/*                                                                    */
-/*   This computes C = A ? B, returning the minimum or A if equal     */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberMin (decNumber * res, const decNumber * lhs,
-             const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decCompareOp (res, lhs, rhs, set, COMPMIN, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  } /* decNumberExp */
+
+/* ------------------------------------------------------------------ */
+/* decNumberFMA -- fused multiply add                                */
+/*                                                                   */
+/*   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)) */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   fhs is C [far hand side]                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* Mathematical function restrictions apply (see above); a NaN is     */
+/* returned with Invalid_operation if a restriction is violated.      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberFMA(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, const decNumber *fhs,
+                        decContext *set) {
+  uInt status=0;                  /* accumulator */
+  decContext dcmul;               /* context for the multiplication */
+  uInt needbytes;                 /* for space calculations */
+  decNumber bufa[D2N(DECBUFFER*2+1)];
+  decNumber *allocbufa=NULL;      /* -> allocated bufa, iff allocated */
+  decNumber *acc;                 /* accumulator pointer */
+  decNumber dzero;                /* work */
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  if (decCheckOperands(res, fhs, DECUNUSED, set)) return res;
+  #endif
+
+  do {                                 /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) {              /* [undefined if subset] */
+      status|=DEC_Invalid_operation;
+      break;}
+    #endif
+    /* Check math restrictions [these ensure no overflow or underflow] */
+    if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status))
+     || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status))
+     || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break;
+    /* set up context for multiply */
+    dcmul=*set;
+    dcmul.digits=lhs->digits+rhs->digits; /* just enough */
+    /* [The above may be an over-estimate for subset arithmetic, but that's OK] */
+    dcmul.emax=DEC_MAX_EMAX;           /* effectively unbounded .. */
+    dcmul.emin=DEC_MIN_EMIN;           /* [thanks to Math restrictions] */
+    /* set up decNumber space to receive the result of the multiply */
+    acc=bufa;                          /* may fit */
+    needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit);
+    if (needbytes>sizeof(bufa)) {      /* need malloc space */
+      allocbufa=(decNumber *)malloc(needbytes);
+      if (allocbufa==NULL) {           /* hopeless -- abandon */
+       status|=DEC_Insufficient_storage;
+       break;}
+      acc=allocbufa;                   /* use the allocated space */
+      }
+    /* multiply with extended range and necessary precision */
+    /*printf("emin=%ld\n", dcmul.emin); */
+    decMultiplyOp(acc, lhs, rhs, &dcmul, &status);
+    /* Only Invalid operation (from sNaN or Inf * 0) is possible in */
+    /* status; if either is seen than ignore fhs (in case it is */
+    /* another sNaN) and set acc to NaN unless we had an sNaN */
+    /* [decMultiplyOp leaves that to caller] */
+    /* Note sNaN has to go through addOp to shorten payload if */
+    /* necessary */
+    if ((status&DEC_Invalid_operation)!=0) {
+      if (!(status&DEC_sNaN)) {                /* but be true invalid */
+       decNumberZero(res);             /* acc not yet set */
+       res->bits=DECNAN;
+       break;
+       }
+      decNumberZero(&dzero);           /* make 0 (any non-NaN would do) */
+      fhs=&dzero;                      /* use that */
+      }
+    #if DECCHECK
+     else { /* multiply was OK */
+      if (status!=0) printf("Status=%08lx after FMA multiply\n", status);
+      }
+    #endif
+    /* add the third operand and result -> res, and all is done */
+    decAddOp(res, acc, fhs, set, 0, &status);
+    } while(0);                                /* end protected */
+
+  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberMinus -- prefix minus operator                            */
-/*                                                                    */
-/*   This computes C = 0 - A                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A                                */
-/*   rhs is A                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-/* We simply use AddOp for the subtract, which will do the necessary. */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberMinus (decNumber * res, const decNumber * rhs, decContext * set)
-{
-  decNumber dzero;
-  uInt status = 0;             /* accumulator */
-
-#if DECCHECK
-  if (decCheckOperands (res, DECUNUSED, rhs, set))
+  } /* decNumberFMA */
+
+/* ------------------------------------------------------------------ */
+/* decNumberInvert -- invert a Number, digitwise                     */
+/*                                                                   */
+/*   This computes C = ~A                                            */
+/*                                                                   */
+/*   res is C, the result.  C may be A (e.g., X=~X)                  */
+/*   rhs is A                                                        */
+/*   set is the context (used for result length and error report)     */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Logical function restrictions apply (see above); a NaN is         */
+/* returned with Invalid_operation if a restriction is violated.      */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberInvert(decNumber *res, const decNumber *rhs,
+                           decContext *set) {
+  const Unit *ua, *msua;               /* -> operand and its msu */
+  Unit *uc, *msuc;                     /* -> result and its msu */
+  Int  msudigs;                        /* digits in res msu */
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  if (rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
+    decStatus(res, DEC_Invalid_operation, set);
     return res;
-#endif
+    }
+  /* operand is valid */
+  ua=rhs->lsu;                         /* bottom-up */
+  uc=res->lsu;                         /* .. */
+  msua=ua+D2U(rhs->digits)-1;          /* -> msu of rhs */
+  msuc=uc+D2U(set->digits)-1;          /* -> msu of result */
+  msudigs=MSUDIGITS(set->digits);      /* [faster than remainder] */
+  for (; uc<=msuc; ua++, uc++) {       /* Unit loop */
+    Unit a;                            /* extract unit */
+    Int         i, j;                          /* work */
+    if (ua>msua) a=0;
+     else a=*ua;
+    *uc=0;                             /* can now write back */
+    /* always need to examine all bits in rhs */
+    /* This loop could be unrolled and/or use BIN2BCD tables */
+    for (i=0; i<DECDPUN; i++) {
+      if ((~a)&1) *uc=*uc+(Unit)powers[i];   /* effect INVERT */
+      j=a%10;
+      a=a/10;
+      if (j>1) {
+       decStatus(res, DEC_Invalid_operation, set);
+       return res;
+       }
+      if (uc==msuc && i==msudigs-1) break;   /* just did final digit */
+      } /* each digit */
+    } /* each unit */
+  /* [here uc-1 is the msu of the result] */
+  res->digits=decGetDigits(res->lsu, uc-res->lsu);
+  res->exponent=0;                     /* integer */
+  res->bits=0;                         /* sign=0 */
+  return res;  /* [no status to set] */
+  } /* decNumberInvert */
+
+/* ------------------------------------------------------------------ */
+/* decNumberLn -- natural logarithm                                  */
+/*                                                                   */
+/*   This computes C = ln(A)                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context; note that rounding mode has no effect       */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Notable cases:                                                    */
+/*   A<0 -> Invalid                                                  */
+/*   A=0 -> -Infinity (Exact)                                        */
+/*   A=+Infinity -> +Infinity (Exact)                                */
+/*   A=1 exactly -> 0 (Exact)                                        */
+/*                                                                   */
+/* Mathematical function restrictions apply (see above); a NaN is     */
+/* returned with Invalid_operation if a restriction is violated.      */
+/*                                                                   */
+/* 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      */
+/* error in rare cases.                                                      */
+/* ------------------------------------------------------------------ */
+/* 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   */
+/* to calculate at p+e+2).                                           */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberLn(decNumber *res, const decNumber *rhs,
+                       decContext *set) {
+  uInt status=0;                  /* accumulator */
+  #if DECSUBSET
+  decNumber *allocrhs=NULL;       /* non-NULL if rounded rhs allocated */
+  #endif
+
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  /* Check restrictions; this is a math function; if not violated */
+  /* then carry out the operation. */
+  if (!decCheckMath(rhs, set, &status)) do { /* protect allocation */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operand and set lostDigits status, as needed */
+      if (rhs->digits>set->digits) {
+       allocrhs=decRoundOperand(rhs, set, &status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
+       }
+      /* special check in subset for rhs=0 */
+      if (ISZERO(rhs)) {               /* +/- zeros -> error */
+       status|=DEC_Invalid_operation;
+       break;}
+      } /* extended=0 */
+    #endif
+    decLnOp(res, rhs, set, &status);
+    } while(0);                                /* end protected */
+
+  #if DECSUBSET
+  if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */
+  #endif
+  /* apply significant status */
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberLn */
+
+/* ------------------------------------------------------------------ */
+/* decNumberLogB - get adjusted exponent, by 754r rules                      */
+/*                                                                   */
+/*   This computes C = adjustedexponent(A)                           */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context, used only for digits and status             */
+/*                                                                   */
+/* 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        */
+/* -1999999999).                                                     */
+/*                                                                   */
+/* This returns the adjusted exponent of A after (in theory) padding  */
+/* with zeros on the right to set->digits digits while keeping the    */
+/* same value. The exponent is not limited by emin/emax.             */
+/*                                                                   */
+/* Notable cases:                                                    */
+/*   A<0 -> Use |A|                                                  */
+/*   A=0 -> -Infinity (Division by zero)                             */
+/*   A=Infinite -> +Infinity (Exact)                                 */
+/*   A=1 exactly -> 0 (Exact)                                        */
+/*   NaNs are propagated as usual                                    */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberLogB(decNumber *res, const decNumber *rhs,
+                         decContext *set) {
+  uInt status=0;                  /* accumulator */
+
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  /* NaNs as usual; Infinities return +Infinity; 0->oops */
+  if (decNumberIsNaN(rhs)) decNaNs(res, rhs, NULL, set, &status);
+   else if (decNumberIsInfinite(rhs)) decNumberCopyAbs(res, rhs);
+   else if (decNumberIsZero(rhs)) {
+    decNumberZero(res);                        /* prepare for Infinity */
+    res->bits=DECNEG|DECINF;           /* -Infinity */
+    status|=DEC_Division_by_zero;      /* as per 754r */
+    }
+   else { /* finite non-zero */
+    Int ae=rhs->exponent+rhs->digits-1; /* adjusted exponent */
+    decNumberFromInt32(res, ae);       /* lay it out */
+    }
 
-  decNumberZero (&dzero);      /* make 0 */
-  dzero.exponent = rhs->exponent;      /* [no coefficient expansion] */
-  decAddOp (res, &dzero, rhs, set, DECNEG, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  if (status!=0) decStatus(res, status, set);
+  return res;
+  } /* decNumberLogB */
+
+/* ------------------------------------------------------------------ */
+/* decNumberLog10 -- logarithm in base 10                            */
+/*                                                                   */
+/*   This computes C = log10(A)                                              */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context; note that rounding mode has no effect       */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Notable cases:                                                    */
+/*   A<0 -> Invalid                                                  */
+/*   A=0 -> -Infinity (Exact)                                        */
+/*   A=+Infinity -> +Infinity (Exact)                                */
+/*   A=10**n (if n is an integer) -> n (Exact)                       */
+/*                                                                   */
+/* Mathematical function restrictions apply (see above); a NaN is     */
+/* returned with Invalid_operation if a restriction is violated.      */
+/*                                                                   */
+/* 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      */
+/* error in rare cases.                                                      */
+/* ------------------------------------------------------------------ */
+/* 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      */
+/* 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 */
+/* fastpath in decLnOp.         The final division is done to the requested  */
+/* precision.                                                        */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberLog10(decNumber *res, const decNumber *rhs,
+                         decContext *set) {
+  uInt status=0, ignore=0;        /* status accumulators */
+  uInt needbytes;                 /* for space calculations */
+  Int p;                          /* working precision */
+  Int t;                          /* digits in exponent of A */
+
+  /* buffers for a and b working decimals */
+  /* (adjustment calculator, same size) */
+  decNumber bufa[D2N(DECBUFFER+2)];
+  decNumber *allocbufa=NULL;      /* -> allocated bufa, iff allocated */
+  decNumber *a=bufa;              /* temporary a */
+  decNumber bufb[D2N(DECBUFFER+2)];
+  decNumber *allocbufb=NULL;      /* -> allocated bufb, iff allocated */
+  decNumber *b=bufb;              /* temporary b */
+  decNumber bufw[D2N(10)];        /* working 2-10 digit number */
+  decNumber *w=bufw;              /* .. */
+  #if DECSUBSET
+  decNumber *allocrhs=NULL;       /* non-NULL if rounded rhs allocated */
+  #endif
+
+  decContext aset;                /* working context */
+
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  /* Check restrictions; this is a math function; if not violated */
+  /* then carry out the operation. */
+  if (!decCheckMath(rhs, set, &status)) do { /* protect malloc */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operand and set lostDigits status, as needed */
+      if (rhs->digits>set->digits) {
+       allocrhs=decRoundOperand(rhs, set, &status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
+       }
+      /* special check in subset for rhs=0 */
+      if (ISZERO(rhs)) {               /* +/- zeros -> error */
+       status|=DEC_Invalid_operation;
+       break;}
+      } /* extended=0 */
+    #endif
+
+    decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
+
+    /* handle exact powers of 10; only check if +ve finite */
+    if (!(rhs->bits&(DECNEG|DECSPECIAL)) && !ISZERO(rhs)) {
+      Int residue=0;              /* (no residue) */
+      uInt copystat=0;            /* clean status */
+
+      /* round to a single digit... */
+      aset.digits=1;
+      decCopyFit(w, rhs, &aset, &residue, &copystat); /* copy & shorten */
+      /* if exact and the digit is 1, rhs is a power of 10 */
+      if (!(copystat&DEC_Inexact) && w->lsu[0]==1) {
+       /* the exponent, conveniently, is the power of 10; making */
+       /* this the result needs a little care as it might not fit, */
+       /* so first convert it into the working number, and then move */
+       /* to res */
+       decNumberFromInt32(w, w->exponent);
+       residue=0;
+       decCopyFit(res, w, set, &residue, &status); /* copy & round */
+       decFinish(res, set, &residue, &status);     /* cleanup/set flags */
+       break;
+       } /* not a power of 10 */
+      } /* not a candidate for exact */
+
+    /* simplify the information-content calculation to use 'total */
+    /* number of digits in a, including exponent' as compared to the */
+    /* requested digits, as increasing this will only rarely cost an */
+    /* iteration in ln(a) anyway */
+    t=6;                               /* it can never be >6 */
+
+    /* allocate space when needed... */
+    p=(rhs->digits+t>set->digits?rhs->digits+t:set->digits)+3;
+    needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
+    if (needbytes>sizeof(bufa)) {      /* need malloc space */
+      allocbufa=(decNumber *)malloc(needbytes);
+      if (allocbufa==NULL) {           /* hopeless -- abandon */
+       status|=DEC_Insufficient_storage;
+       break;}
+      a=allocbufa;                     /* use the allocated space */
+      }
+    aset.digits=p;                     /* as calculated */
+    aset.emax=DEC_MAX_MATH;            /* usual bounds */
+    aset.emin=-DEC_MAX_MATH;           /* .. */
+    aset.clamp=0;                      /* and no concrete format */
+    decLnOp(a, rhs, &aset, &status);   /* a=ln(rhs) */
+
+    /* skip the division if the result so far is infinite, NaN, or */
+    /* zero, or there was an error; note NaN from sNaN needs copy */
+    if (status&DEC_NaNs && !(status&DEC_sNaN)) break;
+    if (a->bits&DECSPECIAL || ISZERO(a)) {
+      decNumberCopy(res, a);           /* [will fit] */
+      break;}
+
+    /* for ln(10) an extra 3 digits of precision are needed */
+    p=set->digits+3;
+    needbytes=sizeof(decNumber)+(D2U(p)-1)*sizeof(Unit);
+    if (needbytes>sizeof(bufb)) {      /* need malloc space */
+      allocbufb=(decNumber *)malloc(needbytes);
+      if (allocbufb==NULL) {           /* hopeless -- abandon */
+       status|=DEC_Insufficient_storage;
+       break;}
+      b=allocbufb;                     /* use the allocated space */
+      }
+    decNumberZero(w);                  /* set up 10... */
+    #if DECDPUN==1
+    w->lsu[1]=1; w->lsu[0]=0;          /* .. */
+    #else
+    w->lsu[0]=10;                      /* .. */
+    #endif
+    w->digits=2;                       /* .. */
+
+    aset.digits=p;
+    decLnOp(b, w, &aset, &ignore);     /* b=ln(10) */
+
+    aset.digits=set->digits;           /* for final divide */
+    decDivideOp(res, a, b, &aset, DIVIDE, &status); /* into result */
+    } while(0);                                /* [for break] */
+
+  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
+  if (allocbufb!=NULL) free(allocbufb); /* .. */
+  #if DECSUBSET
+  if (allocrhs !=NULL) free(allocrhs); /* .. */
+  #endif
+  /* apply significant status */
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberLog10 */
+
+/* ------------------------------------------------------------------ */
+/* decNumberMax -- compare two Numbers and return the maximum        */
+/*                                                                   */
+/*   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)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberMax(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decCompareOp(res, lhs, rhs, set, COMPMAX, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberMax */
+
+/* ------------------------------------------------------------------ */
+/* decNumberMaxMag -- compare and return the maximum by magnitude     */
+/*                                                                   */
+/*   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)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberMaxMag(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decCompareOp(res, lhs, rhs, set, COMPMAXMAG, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
+  } /* decNumberMaxMag */
+
+/* ------------------------------------------------------------------ */
+/* decNumberMin -- compare two Numbers and return the minimum        */
+/*                                                                   */
+/*   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)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberMin(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decCompareOp(res, lhs, rhs, set, COMPMIN, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberMin */
+
+/* ------------------------------------------------------------------ */
+/* decNumberMinMag -- compare and return the minimum by magnitude     */
+/*                                                                   */
+/*   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)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberMinMag(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decCompareOp(res, lhs, rhs, set, COMPMINMAG, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberMinMag */
 
 /* ------------------------------------------------------------------ */
-/* decNumberPlus -- prefix plus operator                              */
-/*                                                                    */
-/*   This computes C = 0 + A                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A                                */
-/*   rhs is A                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
+/* decNumberMinus -- prefix minus operator                           */
+/*                                                                   */
+/*   This computes C = 0 - A                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* See also decNumberCopyNegate for a quiet bitwise version of this.  */
+/* C must have space for set->digits digits.                         */
 /* ------------------------------------------------------------------ */
-/* We simply use AddOp; Add will take fast path after preparing A.    */
-/* Performance is a concern here, as this routine is often used to    */
-/* check operands and apply rounding and overflow/underflow testing.  */
+/* Simply use AddOp for the subtract, which will do the necessary.    */
 /* ------------------------------------------------------------------ */
-decNumber *
-decNumberPlus (decNumber * res, const decNumber * rhs, decContext * set)
-{
+decNumber * decNumberMinus(decNumber *res, const decNumber *rhs,
+                          decContext *set) {
   decNumber dzero;
-  uInt status = 0;             /* accumulator */
-
-#if DECCHECK
-  if (decCheckOperands (res, DECUNUSED, rhs, set))
-    return res;
-#endif
-
-  decNumberZero (&dzero);      /* make 0 */
-  dzero.exponent = rhs->exponent;      /* [no coefficient expansion] */
-  decAddOp (res, &dzero, rhs, set, 0, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  uInt status=0;                       /* accumulator */
+
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  decNumberZero(&dzero);               /* make 0 */
+  dzero.exponent=rhs->exponent;                /* [no coefficient expansion] */
+  decAddOp(res, &dzero, rhs, set, DECNEG, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberMultiply -- multiply two Numbers                          */
-/*                                                                    */
-/*   This computes C = A x B                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberMultiply (decNumber * res, const decNumber * lhs,
-                  const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decMultiplyOp (res, lhs, rhs, set, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  } /* decNumberMinus */
+
+/* ------------------------------------------------------------------ */
+/* decNumberNextMinus -- next towards -Infinity                              */
+/*                                                                   */
+/*   This computes C = A - infinitesimal, rounded towards -Infinity   */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* This is a generalization of 754r NextDown.                        */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberNextMinus(decNumber *res, const decNumber *rhs,
+                              decContext *set) {
+  decNumber dtiny;                          /* constant */
+  decContext workset=*set;                  /* work */
+  uInt status=0;                            /* accumulator */
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  /* +Infinity is the special case */
+  if ((rhs->bits&(DECINF|DECNEG))==DECINF) {
+    decSetMaxValue(res, set);               /* is +ve */
+    /* there is no status to set */
+    return res;
+    }
+  decNumberZero(&dtiny);                    /* start with 0 */
+  dtiny.lsu[0]=1;                           /* make number that is .. */
+  dtiny.exponent=DEC_MIN_EMIN-1;            /* .. smaller than tiniest */
+  workset.round=DEC_ROUND_FLOOR;
+  decAddOp(res, rhs, &dtiny, &workset, DECNEG, &status);
+  status&=DEC_Invalid_operation|DEC_sNaN;    /* only sNaN Invalid please */
+  if (status!=0) decStatus(res, status, set);
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberNormalize -- remove trailing zeros                        */
-/*                                                                    */
-/*   This computes C = 0 + A, and normalizes the result               */
-/*                                                                    */
-/*   res is C, the result.  C may be A                                */
-/*   rhs is A                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberNormalize (decNumber * res, const decNumber * rhs, decContext * set)
-{
-  decNumber *allocrhs = NULL;  /* non-NULL if rounded rhs allocated */
-  uInt status = 0;             /* as usual */
-  Int residue = 0;             /* as usual */
-  Int dropped;                 /* work */
-
-#if DECCHECK
-  if (decCheckOperands (res, DECUNUSED, rhs, set))
+  } /* decNumberNextMinus */
+
+/* ------------------------------------------------------------------ */
+/* decNumberNextPlus -- next towards +Infinity                       */
+/*                                                                   */
+/*   This computes C = A + infinitesimal, rounded towards +Infinity   */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* This is a generalization of 754r NextUp.                          */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberNextPlus(decNumber *res, const decNumber *rhs,
+                             decContext *set) {
+  decNumber dtiny;                          /* constant */
+  decContext workset=*set;                  /* work */
+  uInt status=0;                            /* accumulator */
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  /* -Infinity is the special case */
+  if ((rhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
+    decSetMaxValue(res, set);
+    res->bits=DECNEG;                       /* negative */
+    /* there is no status to set */
     return res;
-#endif
-
-  do
-    {                          /* protect allocated storage */
-#if DECSUBSET
-      if (!set->extended)
-       {
-         /* reduce operand and set lostDigits status, as needed */
-         if (rhs->digits > set->digits)
-           {
-             allocrhs = decRoundOperand (rhs, set, &status);
-             if (allocrhs == NULL)
-               break;
-             rhs = allocrhs;
+    }
+  decNumberZero(&dtiny);                    /* start with 0 */
+  dtiny.lsu[0]=1;                           /* make number that is .. */
+  dtiny.exponent=DEC_MIN_EMIN-1;            /* .. smaller than tiniest */
+  workset.round=DEC_ROUND_CEILING;
+  decAddOp(res, rhs, &dtiny, &workset, 0, &status);
+  status&=DEC_Invalid_operation|DEC_sNaN;    /* only sNaN Invalid please */
+  if (status!=0) decStatus(res, status, set);
+  return res;
+  } /* decNumberNextPlus */
+
+/* ------------------------------------------------------------------ */
+/* decNumberNextToward -- next towards rhs                           */
+/*                                                                   */
+/*   This computes C = A +/- infinitesimal, rounded towards          */
+/*   +/-Infinity in the direction of B, as per 754r nextafter rules   */
+/*                                                                   */
+/*   res is C, the result.  C may be A or B.                         */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* This is a generalization of 754r NextAfter.                       */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberNextToward(decNumber *res, const decNumber *lhs,
+                               const decNumber *rhs, decContext *set) {
+  decNumber dtiny;                          /* constant */
+  decContext workset=*set;                  /* work */
+  Int result;                               /* .. */
+  uInt status=0;                            /* accumulator */
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) {
+    decNaNs(res, lhs, rhs, set, &status);
+    }
+   else { /* Is numeric, so no chance of sNaN Invalid, etc. */
+    result=decCompare(lhs, rhs, 0);    /* sign matters */
+    if (result==BADINT) status|=DEC_Insufficient_storage; /* rare */
+     else { /* valid compare */
+      if (result==0) decNumberCopySign(res, lhs, rhs); /* easy */
+       else { /* differ: need NextPlus or NextMinus */
+       uByte sub;                      /* add or subtract */
+       if (result<0) {                 /* lhs<rhs, do nextplus */
+         /* -Infinity is the special case */
+         if ((lhs->bits&(DECINF|DECNEG))==(DECINF|DECNEG)) {
+           decSetMaxValue(res, set);
+           res->bits=DECNEG;           /* negative */
+           return res;                 /* there is no status to set */
            }
-       }
-#endif
-      /* [following code does not require input rounding] */
-
-      /* specials copy through, except NaNs need care */
-      if (decNumberIsNaN (rhs))
-       {
-         decNaNs (res, rhs, NULL, &status);
-         break;
-       }
-
-      /* reduce result to the requested length and copy to result */
-      decCopyFit (res, rhs, set, &residue, &status);   /* copy & round */
-      decFinish (res, set, &residue, &status); /* cleanup/set flags */
-      decTrim (res, 1, &dropped);      /* normalize in place */
+         workset.round=DEC_ROUND_CEILING;
+         sub=0;                        /* add, please */
+         } /* plus */
+        else {                         /* lhs>rhs, do nextminus */
+         /* +Infinity is the special case */
+         if ((lhs->bits&(DECINF|DECNEG))==DECINF) {
+           decSetMaxValue(res, set);
+           return res;                 /* there is no status to set */
+           }
+         workset.round=DEC_ROUND_FLOOR;
+         sub=DECNEG;                   /* subtract, please */
+         } /* minus */
+       decNumberZero(&dtiny);          /* start with 0 */
+       dtiny.lsu[0]=1;                 /* make number that is .. */
+       dtiny.exponent=DEC_MIN_EMIN-1;  /* .. smaller than tiniest */
+       decAddOp(res, lhs, &dtiny, &workset, sub, &status); /* + or - */
+       /* turn off exceptions if the result is a normal number */
+       /* (including Nmin), otherwise let all status through */
+       if (decNumberIsNormal(res, set)) status=0;
+       } /* unequal */
+      } /* compare OK */
+    } /* numeric */
+  if (status!=0) decStatus(res, status, set);
+  return res;
+  } /* decNumberNextToward */
+
+/* ------------------------------------------------------------------ */
+/* decNumberOr -- OR two Numbers, digitwise                          */
+/*                                                                   */
+/*   This computes C = A | B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X|X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context (used for result length and error report)     */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Logical function restrictions apply (see above); a NaN is         */
+/* returned with Invalid_operation if a restriction is violated.      */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberOr(decNumber *res, const decNumber *lhs,
+                       const decNumber *rhs, decContext *set) {
+  const Unit *ua, *ub;                 /* -> operands */
+  const Unit *msua, *msub;             /* -> operand msus */
+  Unit *uc, *msuc;                     /* -> result and its msu */
+  Int  msudigs;                        /* digits in res msu */
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
+   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
+    decStatus(res, DEC_Invalid_operation, set);
+    return res;
     }
-  while (0);                   /* end protected */
-
-  if (allocrhs != NULL)
-    free (allocrhs);           /* .. */
-  if (status != 0)
-    decStatus (res, status, set);      /* then report status */
+  /* operands are valid */
+  ua=lhs->lsu;                         /* bottom-up */
+  ub=rhs->lsu;                         /* .. */
+  uc=res->lsu;                         /* .. */
+  msua=ua+D2U(lhs->digits)-1;          /* -> msu of lhs */
+  msub=ub+D2U(rhs->digits)-1;          /* -> msu of rhs */
+  msuc=uc+D2U(set->digits)-1;          /* -> msu of result */
+  msudigs=MSUDIGITS(set->digits);      /* [faster than remainder] */
+  for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
+    Unit a, b;                         /* extract units */
+    if (ua>msua) a=0;
+     else a=*ua;
+    if (ub>msub) b=0;
+     else b=*ub;
+    *uc=0;                             /* can now write back */
+    if (a|b) {                         /* maybe 1 bits to examine */
+      Int i, j;
+      /* This loop could be unrolled and/or use BIN2BCD tables */
+      for (i=0; i<DECDPUN; i++) {
+       if ((a|b)&1) *uc=*uc+(Unit)powers[i];     /* effect OR */
+       j=a%10;
+       a=a/10;
+       j|=b%10;
+       b=b/10;
+       if (j>1) {
+         decStatus(res, DEC_Invalid_operation, set);
+         return res;
+         }
+       if (uc==msuc && i==msudigs-1) break;      /* just did final digit */
+       } /* each digit */
+      } /* non-zero */
+    } /* each unit */
+  /* [here uc-1 is the msu of the result] */
+  res->digits=decGetDigits(res->lsu, uc-res->lsu);
+  res->exponent=0;                     /* integer */
+  res->bits=0;                         /* sign=0 */
+  return res;  /* [no status to set] */
+  } /* decNumberOr */
+
+/* ------------------------------------------------------------------ */
+/* decNumberPlus -- prefix plus operator                             */
+/*                                                                   */
+/*   This computes C = 0 + A                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* See also decNumberCopy for a quiet bitwise version of this.       */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+/* This simply uses AddOp; Add will take fast path after preparing A. */
+/* Performance is a concern here, as this routine is often used to    */
+/* check operands and apply rounding and overflow/underflow testing.  */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberPlus(decNumber *res, const decNumber *rhs,
+                         decContext *set) {
+  decNumber dzero;
+  uInt status=0;                       /* accumulator */
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  decNumberZero(&dzero);               /* make 0 */
+  dzero.exponent=rhs->exponent;                /* [no coefficient expansion] */
+  decAddOp(res, &dzero, rhs, set, 0, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberPower -- raise a number to an integer power               */
-/*                                                                    */
-/*   This computes C = A ** B                                         */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X**X)        */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/*                                                                    */
-/* Specification restriction: abs(n) must be <=999999999              */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberPower (decNumber * res, const decNumber * lhs,
-               const decNumber * rhs, decContext * set)
-{
-  decNumber *alloclhs = NULL;  /* non-NULL if rounded lhs allocated */
-  decNumber *allocrhs = NULL;  /* .., rhs */
-  decNumber *allocdac = NULL;  /* -> allocated acc buffer, iff used */
-  const decNumber *inrhs = rhs;        /* save original rhs */
-  Int reqdigits = set->digits; /* requested DIGITS */
-  Int n;                       /* RHS in binary */
-  Int i;                       /* work */
-#if DECSUBSET
-  Int dropped;                 /* .. */
-#endif
-  uInt needbytes;              /* buffer size needed */
-  Flag seenbit;                        /* seen a bit while powering */
-  Int residue = 0;             /* rounding residue */
-  uInt status = 0;             /* accumulator */
-  uByte bits = 0;              /* result sign if errors */
-  decContext workset;          /* working context */
-  decNumber dnOne;             /* work value 1... */
+  } /* decNumberPlus */
+
+/* ------------------------------------------------------------------ */
+/* decNumberMultiply -- multiply two Numbers                         */
+/*                                                                   */
+/*   This computes C = A x B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberMultiply(decNumber *res, const decNumber *lhs,
+                             const decNumber *rhs, decContext *set) {
+  uInt status=0;                  /* accumulator */
+  decMultiplyOp(res, lhs, rhs, set, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberMultiply */
+
+/* ------------------------------------------------------------------ */
+/* decNumberPower -- raise a number to a power                       */
+/*                                                                   */
+/*   This computes C = A ** B                                        */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X**X)       */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Mathematical function restrictions apply (see above); a NaN is     */
+/* returned with Invalid_operation if a restriction is violated.      */
+/*                                                                   */
+/* However, if 1999999997<=B<=999999999 and B is an integer then the  */
+/* restrictions on A and the context are relaxed to the usual bounds, */
+/* for compatibility with the earlier (integer power only) version    */
+/* of this function.                                                 */
+/*                                                                   */
+/* When B is an integer, the result may be exact, even if rounded.    */
+/*                                                                   */
+/* The final result is rounded according to the context; it will      */
+/* almost always be correctly rounded, but may be up to 1 ulp in      */
+/* error in rare cases.                                                      */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberPower(decNumber *res, const decNumber *lhs,
+                          const decNumber *rhs, decContext *set) {
+  #if DECSUBSET
+  decNumber *alloclhs=NULL;       /* non-NULL if rounded lhs allocated */
+  decNumber *allocrhs=NULL;       /* .., rhs */
+  #endif
+  decNumber *allocdac=NULL;       /* -> allocated acc buffer, iff used */
+  decNumber *allocinv=NULL;       /* -> allocated 1/x buffer, iff used */
+  Int  reqdigits=set->digits;     /* requested DIGITS */
+  Int  n;                         /* rhs in binary */
+  Flag rhsint=0;                  /* 1 if rhs is an integer */
+  Flag useint=0;                  /* 1 if can use integer calculation */
+  Flag isoddint=0;                /* 1 if rhs is an integer and odd */
+  Int  i;                         /* work */
+  #if DECSUBSET
+  Int  dropped;                   /* .. */
+  #endif
+  uInt needbytes;                 /* buffer size needed */
+  Flag seenbit;                   /* seen a bit while powering */
+  Int  residue=0;                 /* rounding residue */
+  uInt status=0;                  /* accumulators */
+  uByte bits=0;                           /* result sign if errors */
+  decContext aset;                /* working context */
+  decNumber dnOne;                /* work value 1... */
   /* local accumulator buffer [a decNumber, with digits+elength+1 digits] */
-  uByte dacbuff[sizeof (decNumber) + D2U (DECBUFFER + 9) * sizeof (Unit)];
+  decNumber dacbuff[D2N(DECBUFFER+9)];
+  decNumber *dac=dacbuff;         /* -> result accumulator */
   /* same again for possible 1/lhs calculation */
-  uByte lhsbuff[sizeof (decNumber) + D2U (DECBUFFER + 9) * sizeof (Unit)];
-  decNumber *dac = (decNumber *) dacbuff;      /* -> result accumulator */
-
-#if DECCHECK
-  if (decCheckOperands (res, lhs, rhs, set))
-    return res;
-#endif
-
-  do
-    {                          /* protect allocated storage */
-#if DECSUBSET
-      if (!set->extended)
-       {
-         /* reduce operands and set lostDigits status, as needed */
-         if (lhs->digits > reqdigits)
-           {
-             alloclhs = decRoundOperand (lhs, set, &status);
-             if (alloclhs == NULL)
-               break;
-             lhs = alloclhs;
-           }
-         /* rounding won't affect the result, but we might signal lostDigits */
-         /* as well as the error for non-integer [x**y would need this too] */
-         if (rhs->digits > reqdigits)
-           {
-             allocrhs = decRoundOperand (rhs, set, &status);
-             if (allocrhs == NULL)
-               break;
-             rhs = allocrhs;
-           }
-       }
-#endif
-      /* [following code does not require input rounding] */
-
-      /* handle rhs Infinity */
-      if (decNumberIsInfinite (rhs))
-       {
-         status |= DEC_Invalid_operation;      /* bad */
-         break;
+  decNumber invbuff[D2N(DECBUFFER+9)];
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  do {                            /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) { /* reduce operands and set status, as needed */
+      if (lhs->digits>reqdigits) {
+       alloclhs=decRoundOperand(lhs, set, &status);
+       if (alloclhs==NULL) break;
+       lhs=alloclhs;
        }
-      /* handle NaNs */
-      if ((lhs->bits | rhs->bits) & (DECNAN | DECSNAN))
-       {
-         decNaNs (res, lhs, rhs, &status);
-         break;
+      if (rhs->digits>reqdigits) {
+       allocrhs=decRoundOperand(rhs, set, &status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
        }
+      }
+    #endif
+    /* [following code does not require input rounding] */
+
+    /* handle NaNs and rhs Infinity (lhs infinity is harder) */
+    if (SPECIALARGS) {
+      if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs)) { /* NaNs */
+       decNaNs(res, lhs, rhs, set, &status);
+       break;}
+      if (decNumberIsInfinite(rhs)) {  /* rhs Infinity */
+       Flag rhsneg=rhs->bits&DECNEG;   /* save rhs sign */
+       if (decNumberIsNegative(lhs)    /* lhs<0 */
+        && !decNumberIsZero(lhs))      /* .. */
+         status|=DEC_Invalid_operation;
+        else {                         /* lhs >=0 */
+         decNumberZero(&dnOne);        /* set up 1 */
+         dnOne.lsu[0]=1;
+         decNumberCompare(dac, lhs, &dnOne, set); /* lhs ? 1 */
+         decNumberZero(res);           /* prepare for 0/1/Infinity */
+         if (decNumberIsNegative(dac)) {    /* lhs<1 */
+           if (rhsneg) res->bits|=DECINF;   /* +Infinity [else is +0] */
+           }
+          else if (dac->lsu[0]==0) {        /* lhs=1 */
+           /* 1**Infinity is inexact, so return fully-padded 1.0000 */
+           Int shift=set->digits-1;
+           *res->lsu=1;                     /* was 0, make int 1 */
+           res->digits=decShiftToMost(res->lsu, 1, shift);
+           res->exponent=-shift;            /* make 1.0000... */
+           status|=DEC_Inexact|DEC_Rounded; /* deemed inexact */
+           }
+          else {                            /* lhs>1 */
+           if (!rhsneg) res->bits|=DECINF;  /* +Infinity [else is +0] */
+           }
+         } /* lhs>=0 */
+       break;}
+      /* [lhs infinity drops through] */
+      } /* specials */
+
+    /* Original rhs may be an integer that fits and is in range */
+    n=decGetInt(rhs);
+    if (n!=BADINT) {                   /* it is an integer */
+      rhsint=1;                                /* record the fact for 1**n */
+      isoddint=(Flag)n&1;              /* [works even if big] */
+      if (n!=BIGEVEN && n!=BIGODD)     /* can use integer path? */
+       useint=1;                       /* looks good */
+      }
 
-      /* Original rhs must be an integer that fits and is in range */
-#if DECSUBSET
-      n = decGetInt (inrhs, set);
-#else
-      n = decGetInt (inrhs);
-#endif
-      if (n == BADINT || n > 999999999 || n < -999999999)
-       {
-         status |= DEC_Invalid_operation;
-         break;
+    if (decNumberIsNegative(lhs)       /* -x .. */
+      && isoddint) bits=DECNEG;                /* .. to an odd power */
+
+    /* handle LHS infinity */
+    if (decNumberIsInfinite(lhs)) {    /* [NaNs already handled] */
+      uByte rbits=rhs->bits;           /* save */
+      decNumberZero(res);              /* prepare */
+      if (n==0) *res->lsu=1;           /* [-]Inf**0 => 1 */
+       else {
+       /* -Inf**nonint -> error */
+       if (!rhsint && decNumberIsNegative(lhs)) {
+         status|=DEC_Invalid_operation;     /* -Inf**nonint is error */
+         break;}
+       if (!(rbits & DECNEG)) bits|=DECINF; /* was not a **-n */
+       /* [otherwise will be 0 or -0] */
+       res->bits=bits;
        }
-      if (n < 0)
-       {                       /* negative */
-         n = -n;               /* use the absolute value */
+      break;}
+
+    /* similarly handle LHS zero */
+    if (decNumberIsZero(lhs)) {
+      if (n==0) {                           /* 0**0 => Error */
+       #if DECSUBSET
+       if (!set->extended) {                /* [unless subset] */
+         decNumberZero(res);
+         *res->lsu=1;                       /* return 1 */
+         break;}
+       #endif
+       status|=DEC_Invalid_operation;
        }
-      if (decNumberIsNegative (lhs)    /* -x .. */
-         && (n & 0x00000001))
-       bits = DECNEG;          /* .. to an odd power */
-
-      /* handle LHS infinity */
-      if (decNumberIsInfinite (lhs))
-       {                       /* [NaNs already handled] */
-         uByte rbits = rhs->bits;      /* save */
-         decNumberZero (res);
-         if (n == 0)
-           *res->lsu = 1;      /* [-]Inf**0 => 1 */
-         else
-           {
-             if (!(rbits & DECNEG))
-               bits |= DECINF; /* was not a **-n */
-             /* [otherwise will be 0 or -0] */
-             res->bits = bits;
-           }
-         break;
+       else {                               /* 0**x */
+       uByte rbits=rhs->bits;               /* save */
+       if (rbits & DECNEG) {                /* was a 0**(-n) */
+         #if DECSUBSET
+         if (!set->extended) {              /* [bad if subset] */
+           status|=DEC_Invalid_operation;
+           break;}
+         #endif
+         bits|=DECINF;
+         }
+       decNumberZero(res);                  /* prepare */
+       /* [otherwise will be 0 or -0] */
+       res->bits=bits;
        }
-
-      /* clone the context */
-      workset = *set;          /* copy all fields */
+      break;}
+
+    /* here both lhs and rhs are finite; rhs==0 is handled in the */
+    /* integer path.  Next handle the non-integer cases */
+    if (!useint) {                     /* non-integral rhs */
+      /* any -ve lhs is bad, as is either operand or context out of */
+      /* bounds */
+      if (decNumberIsNegative(lhs)) {
+       status|=DEC_Invalid_operation;
+       break;}
+      if (decCheckMath(lhs, set, &status)
+       || decCheckMath(rhs, set, &status)) break; /* variable status */
+
+      decContextDefault(&aset, DEC_INIT_DECIMAL64); /* clean context */
+      aset.emax=DEC_MAX_MATH;          /* usual bounds */
+      aset.emin=-DEC_MAX_MATH;         /* .. */
+      aset.clamp=0;                    /* and no concrete format */
+
+      /* calculate the result using exp(ln(lhs)*rhs), which can */
+      /* all be done into the accumulator, dac.         The precision needed */
+      /* is enough to contain the full information in the lhs (which */
+      /* is the total digits, including exponent), or the requested */
+      /* precision, if larger, + 4; 6 is used for the exponent */
+      /* maximum length, and this is also used when it is shorter */
+      /* than the requested digits as it greatly reduces the >0.5 ulp */
+      /* cases at little cost (because Ln doubles digits each */
+      /* iteration so a few extra digits rarely causes an extra */
+      /* iteration) */
+      aset.digits=MAXI(lhs->digits, set->digits)+6+4;
+      } /* non-integer rhs */
+
+     else { /* rhs is in-range integer */
+      if (n==0) {                      /* x**0 = 1 */
+       /* (0**0 was handled above) */
+       decNumberZero(res);             /* result=1 */
+       *res->lsu=1;                    /* .. */
+       break;}
+      /* rhs is a non-zero integer */
+      if (n<0) n=-n;                   /* use abs(n) */
+
+      aset=*set;                       /* clone the context */
+      aset.round=DEC_ROUND_HALF_EVEN;  /* internally use balanced */
       /* calculate the working DIGITS */
-      workset.digits = reqdigits + (inrhs->digits + inrhs->exponent) + 1;
-      /* it's an error if this is more than we can handle */
-      if (workset.digits > DECNUMMAXP)
-       {
-         status |= DEC_Invalid_operation;
-         break;
-       }
-
-      /* workset.digits is the count of digits for the accumulator we need */
-      /* if accumulator is too long for local storage, then allocate */
-      needbytes =
-       sizeof (decNumber) + (D2U (workset.digits) - 1) * sizeof (Unit);
-      /* [needbytes also used below if 1/lhs needed] */
-      if (needbytes > sizeof (dacbuff))
-       {
-         allocdac = (decNumber *) malloc (needbytes);
-         if (allocdac == NULL)
-           {                   /* hopeless -- abandon */
-             status |= DEC_Insufficient_storage;
-             break;
-           }
-         dac = allocdac;       /* use the allocated space */
+      aset.digits=reqdigits+(rhs->digits+rhs->exponent)+2;
+      #if DECSUBSET
+      if (!set->extended) aset.digits--;     /* use classic precision */
+      #endif
+      /* it's an error if this is more than can be handled */
+      if (aset.digits>DECNUMMAXP) {status|=DEC_Invalid_operation; break;}
+      } /* integer path */
+
+    /* aset.digits is the count of digits for the accumulator needed */
+    /* if accumulator is too long for local storage, then allocate */
+    needbytes=sizeof(decNumber)+(D2U(aset.digits)-1)*sizeof(Unit);
+    /* [needbytes also used below if 1/lhs needed] */
+    if (needbytes>sizeof(dacbuff)) {
+      allocdac=(decNumber *)malloc(needbytes);
+      if (allocdac==NULL) {   /* hopeless -- abandon */
+       status|=DEC_Insufficient_storage;
+       break;}
+      dac=allocdac;          /* use the allocated space */
+      }
+    /* here, aset is set up and accumulator is ready for use */
+
+    if (!useint) {                          /* non-integral rhs */
+      /* x ** y; special-case x=1 here as it will otherwise always */
+      /* reduce to integer 1; decLnOp has a fastpath which detects */
+      /* the case of x=1 */
+      decLnOp(dac, lhs, &aset, &status);     /* dac=ln(lhs) */
+      /* [no error possible, as lhs 0 already handled] */
+      if (ISZERO(dac)) {                    /* x==1, 1.0, etc. */
+       /* need to return fully-padded 1.0000 etc., but rhsint->1 */
+       *dac->lsu=1;                         /* was 0, make int 1 */
+       if (!rhsint) {                       /* add padding */
+         Int shift=set->digits-1;
+         dac->digits=decShiftToMost(dac->lsu, 1, shift);
+         dac->exponent=-shift;              /* make 1.0000... */
+         status|=DEC_Inexact|DEC_Rounded;   /* deemed inexact */
+         }
        }
-      decNumberZero (dac);     /* acc=1 */
-      *dac->lsu = 1;           /* .. */
-
-      if (n == 0)
-       {                       /* x**0 is usually 1 */
-         /* 0**0 is bad unless subset, when it becomes 1 */
-         if (ISZERO (lhs)
-#if DECSUBSET
-             && set->extended
-#endif
-           )
-           status |= DEC_Invalid_operation;
-         else
-           decNumberCopy (res, dac);   /* copy the 1 */
-         break;
+       else {
+       decMultiplyOp(dac, dac, rhs, &aset, &status);  /* dac=dac*rhs */
+       decExpOp(dac, dac, &aset, &status);            /* dac=exp(dac) */
        }
-
-      /* if a negative power we'll need the constant 1, and if not subset */
-      /* we'll invert the lhs now rather than inverting the result later */
-      if (decNumberIsNegative (rhs))
-       {                       /* was a **-n [hence digits>0] */
-         decNumber * newlhs;
-         decNumberCopy (&dnOne, dac);  /* dnOne=1;  [needed now or later] */
-#if DECSUBSET
-         if (set->extended)
-           {                   /* need to calculate 1/lhs */
-#endif
-             /* divide lhs into 1, putting result in dac [dac=1/dac] */
-             decDivideOp (dac, &dnOne, lhs, &workset, DIVIDE, &status);
-             if (alloclhs != NULL)
-               {
-                 free (alloclhs);      /* done with intermediate */
-                 alloclhs = NULL;      /* indicate freed */
-               }
-             /* now locate or allocate space for the inverted lhs */
-             if (needbytes > sizeof (lhsbuff))
-               {
-                 alloclhs = (decNumber *) malloc (needbytes);
-                 if (alloclhs == NULL)
-                   {           /* hopeless -- abandon */
-                     status |= DEC_Insufficient_storage;
-                     break;
-                   }
-                 newlhs = alloclhs;    /* use the allocated space */
-               }
-             else
-               newlhs = (decNumber *) lhsbuff; /* use stack storage */
-             /* [lhs now points to buffer or allocated storage] */
-             decNumberCopy (newlhs, dac);      /* copy the 1/lhs */
-             decNumberCopy (dac, &dnOne);      /* restore acc=1 */
-             lhs = newlhs;
-#if DECSUBSET
+      /* and drop through for final rounding */
+      } /* non-integer rhs */
+
+     else {                            /* carry on with integer */
+      decNumberZero(dac);              /* acc=1 */
+      *dac->lsu=1;                     /* .. */
+
+      /* if a negative power the constant 1 is needed, and if not subset */
+      /* invert the lhs now rather than inverting the result later */
+      if (decNumberIsNegative(rhs)) {  /* was a **-n [hence digits>0] */
+       decNumber *inv=invbuff;         /* asssume use fixed buffer */
+       decNumberCopy(&dnOne, dac);     /* dnOne=1;  [needed now or later] */
+       #if DECSUBSET
+       if (set->extended) {            /* need to calculate 1/lhs */
+       #endif
+         /* divide lhs into 1, putting result in dac [dac=1/dac] */
+         decDivideOp(dac, &dnOne, lhs, &aset, DIVIDE, &status);
+         /* now locate or allocate space for the inverted lhs */
+         if (needbytes>sizeof(invbuff)) {
+           allocinv=(decNumber *)malloc(needbytes);
+           if (allocinv==NULL) {       /* hopeless -- abandon */
+             status|=DEC_Insufficient_storage;
+             break;}
+           inv=allocinv;               /* use the allocated space */
            }
-#endif
+         /* [inv now points to big-enough buffer or allocated storage] */
+         decNumberCopy(inv, dac);      /* copy the 1/lhs */
+         decNumberCopy(dac, &dnOne);   /* restore acc=1 */
+         lhs=inv;                      /* .. and go forward with new lhs */
+       #if DECSUBSET
+         }
+       #endif
        }
 
       /* Raise-to-the-power loop... */
-      seenbit = 0;             /* set once we've seen a 1-bit */
-      for (i = 1;; i++)
-       {                       /* for each bit [top bit ignored] */
-         /* abandon if we have had overflow or terminal underflow */
-         if (status & (DEC_Overflow | DEC_Underflow))
-           {                   /* interesting? */
-             if (status & DEC_Overflow || ISZERO (dac))
-               break;
-           }
-         /* [the following two lines revealed an optimizer bug in a C++ */
-         /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */
-         n = n << 1;           /* move next bit to testable position */
-         if (n < 0)
-           {                   /* top bit is set */
-             seenbit = 1;      /* OK, we're off */
-             decMultiplyOp (dac, dac, lhs, &workset, &status); /* dac=dac*x */
-           }
-         if (i == 31)
-           break;              /* that was the last bit */
-         if (!seenbit)
-           continue;           /* we don't have to square 1 */
-         decMultiplyOp (dac, dac, dac, &workset, &status);     /* dac=dac*dac [square] */
-       }                       /*i *//* 32 bits */
+      seenbit=0;                  /* set once a 1-bit is encountered */
+      for (i=1;;i++){             /* for each bit [top bit ignored] */
+       /* abandon if had overflow or terminal underflow */
+       if (status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
+         if (status&DEC_Overflow || ISZERO(dac)) break;
+         }
+       /* [the following two lines revealed an optimizer bug in a C++ */
+       /* compiler, with symptom: 5**3 -> 25, when n=n+n was used] */
+       n=n<<1;                    /* move next bit to testable position */
+       if (n<0) {                 /* top bit is set */
+         seenbit=1;               /* OK, significant bit seen */
+         decMultiplyOp(dac, dac, lhs, &aset, &status); /* dac=dac*x */
+         }
+       if (i==31) break;          /* that was the last bit */
+       if (!seenbit) continue;    /* no need to square 1 */
+       decMultiplyOp(dac, dac, dac, &aset, &status); /* dac=dac*dac [square] */
+       } /*i*/ /* 32 bits */
 
       /* complete internal overflow or underflow processing */
-      if (status & (DEC_Overflow | DEC_Subnormal))
-       {
-#if DECSUBSET
-         /* If subset, and power was negative, reverse the kind of -erflow */
-         /* [1/x not yet done] */
-         if (!set->extended && decNumberIsNegative (rhs))
-           {
-             if (status & DEC_Overflow)
-               status ^= DEC_Overflow | DEC_Underflow | DEC_Subnormal;
-             else
-               {               /* trickier -- Underflow may or may not be set */
-                 status &= ~(DEC_Underflow | DEC_Subnormal);   /* [one or both] */
-                 status |= DEC_Overflow;
-               }
+      if (status & (DEC_Overflow|DEC_Underflow)) {
+       #if DECSUBSET
+       /* If subset, and power was negative, reverse the kind of -erflow */
+       /* [1/x not yet done] */
+       if (!set->extended && decNumberIsNegative(rhs)) {
+         if (status & DEC_Overflow)
+           status^=DEC_Overflow | DEC_Underflow | DEC_Subnormal;
+          else { /* trickier -- Underflow may or may not be set */
+           status&=~(DEC_Underflow | DEC_Subnormal); /* [one or both] */
+           status|=DEC_Overflow;
            }
-#endif
-         dac->bits = (dac->bits & ~DECNEG) | bits;     /* force correct sign */
-         /* round subnormals [to set.digits rather than workset.digits] */
-         /* or set overflow result similarly as required */
-         decFinalize (dac, set, &residue, &status);
-         decNumberCopy (res, dac);     /* copy to result (is now OK length) */
-         break;
+         }
+       #endif
+       dac->bits=(dac->bits & ~DECNEG) | bits; /* force correct sign */
+       /* round subnormals [to set.digits rather than aset.digits] */
+       /* or set overflow result similarly as required */
+       decFinalize(dac, set, &residue, &status);
+       decNumberCopy(res, dac);   /* copy to result (is now OK length) */
+       break;
        }
 
-#if DECSUBSET
-      if (!set->extended &&    /* subset math */
-         decNumberIsNegative (rhs))
-       {                       /* was a **-n [hence digits>0] */
-         /* so divide result into 1 [dac=1/dac] */
-         decDivideOp (dac, &dnOne, dac, &workset, DIVIDE, &status);
+      #if DECSUBSET
+      if (!set->extended &&                 /* subset math */
+         decNumberIsNegative(rhs)) {        /* was a **-n [hence digits>0] */
+       /* so divide result into 1 [dac=1/dac] */
+       decDivideOp(dac, &dnOne, dac, &aset, DIVIDE, &status);
        }
-#endif
-
-      /* reduce result to the requested length and copy to result */
-      decCopyFit (res, dac, set, &residue, &status);
-      decFinish (res, set, &residue, &status); /* final cleanup */
-#if DECSUBSET
-      if (!set->extended)
-       decTrim (res, 0, &dropped);     /* trailing zeros */
-#endif
-    }
-  while (0);                   /* end protected */
-
-  if (allocdac != NULL)
-    free (allocdac);           /* drop any storage we used */
-  if (allocrhs != NULL)
-    free (allocrhs);           /* .. */
-  if (alloclhs != NULL)
-    free (alloclhs);           /* .. */
-  if (status != 0)
-    decStatus (res, status, set);
+      #endif
+      } /* rhs integer path */
+
+    /* reduce result to the requested length and copy to result */
+    decCopyFit(res, dac, set, &residue, &status);
+    decFinish(res, set, &residue, &status);  /* final cleanup */
+    #if DECSUBSET
+    if (!set->extended) decTrim(res, set, 0, &dropped); /* trailing zeros */
+    #endif
+    } while(0);                                /* end protected */
+
+  if (allocdac!=NULL) free(allocdac);  /* drop any storage used */
+  if (allocinv!=NULL) free(allocinv);  /* .. */
+  #if DECSUBSET
+  if (alloclhs!=NULL) free(alloclhs);  /* .. */
+  if (allocrhs!=NULL) free(allocrhs);  /* .. */
+  #endif
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
+  } /* decNumberPower */
 
 /* ------------------------------------------------------------------ */
-/* decNumberQuantize -- force exponent to requested value             */
-/*                                                                    */
+/* decNumberQuantize -- force exponent to requested value            */
+/*                                                                   */
 /*   This computes C = op(A, B), where op adjusts the coefficient     */
 /*   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,  */
-/*   except for the effects of any rounding that occurred.            */
-/*                                                                    */
-/*   res is C, the result.  C may be A or B                           */
-/*   lhs is A, the number to adjust                                   */
-/*   rhs is B, the number with exponent to match                      */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/*                                                                    */
+/*   except for the effects of any rounding that occurred.           */
+/*                                                                   */
+/*   res is C, the result.  C may be A or B                          */
+/*   lhs is A, the number to adjust                                  */
+/*   rhs is B, the number with exponent to match                     */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
 /* Unless there is an error or the result is infinite, the exponent   */
-/* after the operation is guaranteed to be equal to that of B.        */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberQuantize (decNumber * res, const decNumber * lhs,
-                  const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decQuantizeOp (res, lhs, rhs, set, 1, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+/* after the operation is guaranteed to be equal to that of B.       */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberQuantize(decNumber *res, const decNumber *lhs,
+                             const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decQuantizeOp(res, lhs, rhs, set, 1, &status);
+  if (status!=0) decStatus(res, status, set);
+  return res;
+  } /* decNumberQuantize */
+
+/* ------------------------------------------------------------------ */
+/* decNumberReduce -- remove trailing zeros                          */
+/*                                                                   */
+/*   This computes C = 0 + A, and normalizes the result                      */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+/* Previously known as Normalize */
+decNumber * decNumberNormalize(decNumber *res, const decNumber *rhs,
+                              decContext *set) {
+  return decNumberReduce(res, rhs, set);
+  } /* decNumberNormalize */
+
+decNumber * decNumberReduce(decNumber *res, const decNumber *rhs,
+                           decContext *set) {
+  #if DECSUBSET
+  decNumber *allocrhs=NULL;       /* non-NULL if rounded rhs allocated */
+  #endif
+  uInt status=0;                  /* as usual */
+  Int  residue=0;                 /* as usual */
+  Int  dropped;                           /* work */
+
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  do {                            /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operand and set lostDigits status, as needed */
+      if (rhs->digits>set->digits) {
+       allocrhs=decRoundOperand(rhs, set, &status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
+       }
+      }
+    #endif
+    /* [following code does not require input rounding] */
+
+    /* Infinities copy through; NaNs need usual treatment */
+    if (decNumberIsNaN(rhs)) {
+      decNaNs(res, rhs, NULL, set, &status);
+      break;
+      }
+
+    /* reduce result to the requested length and copy to result */
+    decCopyFit(res, rhs, set, &residue, &status); /* copy & round */
+    decFinish(res, set, &residue, &status);      /* cleanup/set flags */
+    decTrim(res, set, 1, &dropped);              /* normalize in place */
+    } while(0);                                     /* end protected */
+
+  #if DECSUBSET
+  if (allocrhs !=NULL) free(allocrhs);      /* .. */
+  #endif
+  if (status!=0) decStatus(res, status, set);/* then report status */
   return res;
-}
+  } /* decNumberReduce */
 
 /* ------------------------------------------------------------------ */
-/* decNumberRescale -- force exponent to requested value              */
-/*                                                                    */
+/* decNumberRescale -- force exponent to requested value             */
+/*                                                                   */
 /*   This computes C = op(A, B), where op adjusts the coefficient     */
 /*   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,    */
-/*   except for the effects of any rounding that occurred.            */
-/*                                                                    */
-/*   res is C, the result.  C may be A or B                           */
-/*   lhs is A, the number to adjust                                   */
-/*   rhs is B, the requested exponent                                 */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/*                                                                    */
+/*   except for the effects of any rounding that occurred.           */
+/*                                                                   */
+/*   res is C, the result.  C may be A or B                          */
+/*   lhs is A, the number to adjust                                  */
+/*   rhs is B, the requested exponent                                */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
 /* Unless there is an error or the result is infinite, the exponent   */
-/* after the operation is guaranteed to be equal to B.                */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberRescale (decNumber * res, const decNumber * lhs,
-                 const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decQuantizeOp (res, lhs, rhs, set, 0, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+/* after the operation is guaranteed to be equal to B.               */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberRescale(decNumber *res, const decNumber *lhs,
+                            const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decQuantizeOp(res, lhs, rhs, set, 0, &status);
+  if (status!=0) decStatus(res, status, set);
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberRemainder -- divide and return remainder                  */
-/*                                                                    */
-/*   This computes C = A % B                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X%X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberRemainder (decNumber * res, const decNumber * lhs,
-                   const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decDivideOp (res, lhs, rhs, set, REMAINDER, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  } /* decNumberRescale */
+
+/* ------------------------------------------------------------------ */
+/* decNumberRemainder -- divide and return remainder                 */
+/*                                                                   */
+/*   This computes C = A % B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X%X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberRemainder(decNumber *res, const decNumber *lhs,
+                              const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decDivideOp(res, lhs, rhs, set, REMAINDER, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
+  } /* decNumberRemainder */
 
 /* ------------------------------------------------------------------ */
 /* decNumberRemainderNear -- divide and return remainder from nearest */
-/*                                                                    */
+/*                                                                   */
 /*   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)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberRemainderNear (decNumber * res, const decNumber * lhs,
-                       const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-  decDivideOp (res, lhs, rhs, set, REMNEAR, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X%X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberRemainderNear(decNumber *res, const decNumber *lhs,
+                                  const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+  decDivideOp(res, lhs, rhs, set, REMNEAR, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
+  return res;
+  } /* decNumberRemainderNear */
+
+/* ------------------------------------------------------------------ */
+/* decNumberRotate -- rotate the coefficient of a Number left/right   */
+/*                                                                   */
+/*   This computes C = A rot B (in base ten and rotating set->digits */
+/*   digits).                                                        */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=XrotX)              */
+/*   lhs is A                                                        */
+/*   rhs is B, the number of digits to rotate (-ve to right)         */
+/*   set is the context                                                      */
+/*                                                                   */
+/* 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  */
+/* the exponent or the sign of A.  If lhs->digits is less than       */
+/* set->digits the coefficient is padded with zeros on the left              */
+/* before the rotate.  Any leading zeros in the result are removed    */
+/* as usual.                                                         */
+/*                                                                   */
+/* B must be an integer (q=0) and in the range -set->digits through   */
+/* +set->digits.                                                     */
+/* C must have space for set->digits digits.                         */
+/* NaNs are propagated as usual.  Infinities are unaffected (but      */
+/* B must be valid).  No status is set unless B is invalid or an      */
+/* operand is an sNaN.                                               */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberRotate(decNumber *res, const decNumber *lhs,
+                          const decNumber *rhs, decContext *set) {
+  uInt status=0;             /* accumulator */
+  Int  rotate;               /* rhs as an Int */
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  /* NaNs propagate as normal */
+  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
+    decNaNs(res, lhs, rhs, set, &status);
+   /* rhs must be an integer */
+   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
+    status=DEC_Invalid_operation;
+   else { /* both numeric, rhs is an integer */
+    rotate=decGetInt(rhs);                  /* [cannot fail] */
+    if (rotate==BADINT                      /* something bad .. */
+     || rotate==BIGODD || rotate==BIGEVEN    /* .. very big .. */
+     || abs(rotate)>set->digits)            /* .. or out of range */
+      status=DEC_Invalid_operation;
+     else {                                 /* rhs is OK */
+      decNumberCopy(res, lhs);
+      /* convert -ve rotate to equivalent positive rotation */
+      if (rotate<0) rotate=set->digits+rotate;
+      if (rotate!=0 && rotate!=set->digits   /* zero or full rotation */
+       && !decNumberIsInfinite(res)) {      /* lhs was infinite */
+       /* left-rotate to do; 0 < rotate < set->digits */
+       uInt units, shift;                   /* work */
+       uInt msudigits;                      /* digits in result msu */
+       Unit *msu=res->lsu+D2U(res->digits)-1;    /* current msu */
+       Unit *msumax=res->lsu+D2U(set->digits)-1; /* rotation msu */
+       for (msu++; msu<=msumax; msu++) *msu=0;   /* ensure high units=0 */
+       res->digits=set->digits;                  /* now full-length */
+       msudigits=MSUDIGITS(res->digits);         /* actual digits in msu */
+
+       /* rotation here is done in-place, in three steps */
+       /* 1. shift all to least up to one unit to unit-align final */
+       /*    lsd [any digits shifted out are rotated to the left, */
+       /*    abutted to the original msd (which may require split)] */
+       /* */
+       /*    [if there are no whole units left to rotate, the */
+       /*    rotation is now complete] */
+       /* */
+       /* 2. shift to least, from below the split point only, so that */
+       /*    the final msd is in the right place in its Unit [any */
+       /*    digits shifted out will fit exactly in the current msu, */
+       /*    left aligned, no split required] */
+       /* */
+       /* 3. rotate all the units by reversing left part, right */
+       /*    part, and then whole */
+       /* */
+       /* example: rotate right 8 digits (2 units + 2), DECDPUN=3. */
+       /* */
+       /*   start: 00a bcd efg hij klm npq */
+       /* */
+       /*      1a  000 0ab cde fgh|ijk lmn [pq saved] */
+       /*      1b  00p qab cde fgh|ijk lmn */
+       /* */
+       /*      2a  00p qab cde fgh|00i jkl [mn saved] */
+       /*      2b  mnp qab cde fgh|00i jkl */
+       /* */
+       /*      3a  fgh cde qab mnp|00i jkl */
+       /*      3b  fgh cde qab mnp|jkl 00i */
+       /*      3c  00i jkl mnp qab cde fgh */
+
+       /* Step 1: amount to shift is the partial right-rotate count */
+       rotate=set->digits-rotate;      /* make it right-rotate */
+       units=rotate/DECDPUN;           /* whole units to rotate */
+       shift=rotate%DECDPUN;           /* left-over digits count */
+       if (shift>0) {                  /* not an exact number of units */
+         uInt save=res->lsu[0]%powers[shift];    /* save low digit(s) */
+         decShiftToLeast(res->lsu, D2U(res->digits), shift);
+         if (shift>msudigits) {        /* msumax-1 needs >0 digits */
+           uInt rem=save%powers[shift-msudigits];/* split save */
+           *msumax=(Unit)(save/powers[shift-msudigits]); /* and insert */
+           *(msumax-1)=*(msumax-1)
+                      +(Unit)(rem*powers[DECDPUN-(shift-msudigits)]); /* .. */
+           }
+          else { /* all fits in msumax */
+           *msumax=*msumax+(Unit)(save*powers[msudigits-shift]); /* [maybe *1] */
+           }
+         } /* digits shift needed */
+
+       /* If whole units to rotate... */
+       if (units>0) {                  /* some to do */
+         /* Step 2: the units to touch are the whole ones in rotate, */
+         /*   if any, and the shift is DECDPUN-msudigits (which may be */
+         /*   0, again) */
+         shift=DECDPUN-msudigits;
+         if (shift>0) {                /* not an exact number of units */
+           uInt save=res->lsu[0]%powers[shift];  /* save low digit(s) */
+           decShiftToLeast(res->lsu, units, shift);
+           *msumax=*msumax+(Unit)(save*powers[msudigits]);
+           } /* partial shift needed */
+
+         /* Step 3: rotate the units array using triple reverse */
+         /* (reversing is easy and fast) */
+         decReverse(res->lsu+units, msumax);     /* left part */
+         decReverse(res->lsu, res->lsu+units-1); /* right part */
+         decReverse(res->lsu, msumax);           /* whole */
+         } /* whole units to rotate */
+       /* the rotation may have left an undetermined number of zeros */
+       /* on the left, so true length needs to be calculated */
+       res->digits=decGetDigits(res->lsu, msumax-res->lsu+1);
+       } /* rotate needed */
+      } /* rhs OK */
+    } /* numerics */
+  if (status!=0) decStatus(res, status, set);
   return res;
-}
+  } /* decNumberRotate */
 
 /* ------------------------------------------------------------------ */
-/* decNumberSameQuantum -- test for equal exponents                   */
-/*                                                                    */
-/*   res is the result number, which will contain either 0 or 1       */
-/*   lhs is a number to test                                          */
-/*   rhs is the second (usually a pattern)                            */
-/*                                                                    */
-/* No errors are possible and no context is needed.                   */
+/* decNumberSameQuantum -- test for equal exponents                  */
+/*                                                                   */
+/*   res is the result number, which will contain either 0 or 1              */
+/*   lhs is a number to test                                         */
+/*   rhs is the second (usually a pattern)                           */
+/*                                                                   */
+/* No errors are possible and no context is needed.                  */
 /* ------------------------------------------------------------------ */
-decNumber *
-decNumberSameQuantum (decNumber * res, const decNumber * lhs, const decNumber * rhs)
-{
-  uByte merged;                        /* merged flags */
-  Unit ret = 0;                        /* return value */
+decNumber * decNumberSameQuantum(decNumber *res, const decNumber *lhs,
+                                const decNumber *rhs) {
+  Unit ret=0;                     /* return value */
 
-#if DECCHECK
-  if (decCheckOperands (res, lhs, rhs, DECUNUSED))
-    return res;
-#endif
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, DECUNCONT)) return res;
+  #endif
 
-  merged = (lhs->bits | rhs->bits) & DECSPECIAL;
-  if (merged)
-    {
-      if (decNumberIsNaN (lhs) && decNumberIsNaN (rhs))
-       ret = 1;
-      else if (decNumberIsInfinite (lhs) && decNumberIsInfinite (rhs))
-       ret = 1;
-      /* [anything else with a special gives 0] */
+  if (SPECIALARGS) {
+    if (decNumberIsNaN(lhs) && decNumberIsNaN(rhs)) ret=1;
+     else if (decNumberIsInfinite(lhs) && decNumberIsInfinite(rhs)) ret=1;
+     /* [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 */
-  *res->lsu = ret;
+  decNumberZero(res);             /* OK to overwrite an operand now */
+  *res->lsu=ret;
+  return res;
+  } /* decNumberSameQuantum */
+
+/* ------------------------------------------------------------------ */
+/* decNumberScaleB -- multiply by a power of 10                              */
+/*                                                                   */
+/* This computes C = A x 10**B where B is an integer (q=0) with              */
+/* maximum magnitude 2*(emax+digits)                                 */
+/*                                                                   */
+/*   res is C, the result.  C may be A or B                          */
+/*   lhs is A, the number to adjust                                  */
+/*   rhs is B, the requested power of ten to use                     */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* The result may underflow or overflow.                             */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberScaleB(decNumber *res, const decNumber *lhs,
+                           const decNumber *rhs, decContext *set) {
+  Int  reqexp;               /* requested exponent change [B] */
+  uInt status=0;             /* accumulator */
+  Int  residue;                      /* work */
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  /* Handle special values except lhs infinite */
+  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
+    decNaNs(res, lhs, rhs, set, &status);
+    /* rhs must be an integer */
+   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
+    status=DEC_Invalid_operation;
+   else {
+    /* lhs is a number; rhs is a finite with q==0 */
+    reqexp=decGetInt(rhs);                  /* [cannot fail] */
+    if (reqexp==BADINT                      /* something bad .. */
+     || reqexp==BIGODD || reqexp==BIGEVEN    /* .. very big .. */
+     || abs(reqexp)>(2*(set->digits+set->emax))) /* .. or out of range */
+      status=DEC_Invalid_operation;
+     else {                                 /* rhs is OK */
+      decNumberCopy(res, lhs);              /* all done if infinite lhs */
+      if (!decNumberIsInfinite(res)) {      /* prepare to scale */
+       res->exponent+=reqexp;               /* adjust the exponent */
+       residue=0;
+       decFinalize(res, set, &residue, &status); /* .. and check */
+       } /* finite LHS */
+      } /* rhs OK */
+    } /* rhs finite */
+  if (status!=0) decStatus(res, status, set);
+  return res;
+  } /* decNumberScaleB */
+
+/* ------------------------------------------------------------------ */
+/* decNumberShift -- shift the coefficient of a Number left or right  */
+/*                                                                   */
+/*   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)       */
+/*   lhs is A                                                        */
+/*   rhs is B, the number of digits to shift (-ve to right)          */
+/*   set is the context                                                      */
+/*                                                                   */
+/* 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  */
+/* the exponent or the sign of A.                                    */
+/*                                                                   */
+/* B must be an integer (q=0) and in the range -set->digits through   */
+/* +set->digits.                                                     */
+/* C must have space for set->digits digits.                         */
+/* NaNs are propagated as usual.  Infinities are unaffected (but      */
+/* B must be valid).  No status is set unless B is invalid or an      */
+/* operand is an sNaN.                                               */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberShift(decNumber *res, const decNumber *lhs,
+                          const decNumber *rhs, decContext *set) {
+  uInt status=0;             /* accumulator */
+  Int  shift;                /* rhs as an Int */
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  /* NaNs propagate as normal */
+  if (decNumberIsNaN(lhs) || decNumberIsNaN(rhs))
+    decNaNs(res, lhs, rhs, set, &status);
+   /* rhs must be an integer */
+   else if (decNumberIsInfinite(rhs) || rhs->exponent!=0)
+    status=DEC_Invalid_operation;
+   else { /* both numeric, rhs is an integer */
+    shift=decGetInt(rhs);                   /* [cannot fail] */
+    if (shift==BADINT                       /* something bad .. */
+     || shift==BIGODD || shift==BIGEVEN             /* .. very big .. */
+     || abs(shift)>set->digits)                     /* .. or out of range */
+      status=DEC_Invalid_operation;
+     else {                                 /* rhs is OK */
+      decNumberCopy(res, lhs);
+      if (shift!=0 && !decNumberIsInfinite(res)) { /* something to do */
+       if (shift>0) {                       /* to left */
+         if (shift==set->digits) {          /* removing all */
+           *res->lsu=0;                     /* so place 0 */
+           res->digits=1;                   /* .. */
+           }
+          else {                            /* */
+           /* first remove leading digits if necessary */
+           if (res->digits+shift>set->digits) {
+             decDecap(res, res->digits+shift-set->digits);
+             /* that updated res->digits; may have gone to 1 (for a */
+             /* single digit or for zero */
+             }
+           if (res->digits>1 || *res->lsu)  /* if non-zero.. */
+             res->digits=decShiftToMost(res->lsu, res->digits, shift);
+           } /* partial left */
+         } /* left */
+        else { /* to right */
+         if (-shift>=res->digits) {         /* discarding all */
+           *res->lsu=0;                     /* so place 0 */
+           res->digits=1;                   /* .. */
+           }
+          else {
+           decShiftToLeast(res->lsu, D2U(res->digits), -shift);
+           res->digits-=(-shift);
+           }
+         } /* to right */
+       } /* non-0 non-Inf shift */
+      } /* rhs OK */
+    } /* numerics */
+  if (status!=0) decStatus(res, status, set);
   return res;
-}
+  } /* decNumberShift */
 
 /* ------------------------------------------------------------------ */
-/* decNumberSquareRoot -- square root operator                        */
-/*                                                                    */
-/*   This computes C = squareroot(A)                                  */
-/*                                                                    */
-/*   res is C, the result.  C may be A                                */
-/*   rhs is A                                                         */
-/*   set is the context; note that rounding mode has no effect        */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
+/* decNumberSquareRoot -- square root operator                       */
+/*                                                                   */
+/*   This computes C = squareroot(A)                                 */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context; note that rounding mode has no effect       */
+/*                                                                   */
+/* 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  */
 /*   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   */
+/* a check is made to ensure the result is correctly rounded.        */
+/*                                                                   */
 /* % [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 */
 /* % root of x, in the precision of the calling environment, or it    */
-/* % fails if x < 0.                                                  */
-/* % t e hull and a abrham, august, 1984                              */
-/* if x <= 0 then                                                     */
-/*   if x < 0 then                                                    */
-/*     assert false                                                   */
-/*   else                                                             */
-/*     result 0                                                       */
-/*   end if                                                           */
-/* end if                                                             */
-/* var f := setexp(x, 0)  % fraction part of x   [0.1 <= x < 1]       */
-/* var e := getexp(x)     % exponent part of x                        */
-/* var approx : real                                                  */
-/* if e mod 2 = 0  then                                               */
-/*   approx := .259 + .819 * f   % approx to root of f                */
-/* else                                                               */
-/*   f := f/l0                   % adjustments                        */
-/*   e := e + 1                  %   for odd                          */
-/*   approx := .0819 + 2.59 * f  %   exponent                         */
-/* end if                                                             */
-/*                                                                    */
-/* var p:= 3                                                          */
-/* const maxp := currentprecision + 2                                 */
-/* loop                                                               */
-/*   p := min(2*p - 2, maxp)     % p = 4,6,10, . . . , maxp           */
-/*   precision p                                                      */
-/*   approx := .5 * (approx + f/approx)                               */
-/*   exit when p = maxp                                               */
-/* end loop                                                           */
-/*                                                                    */
+/* % fails if x < 0.                                                 */
+/* % t e hull and a abrham, august, 1984                             */
+/* if x <= 0 then                                                    */
+/*   if x < 0 then                                                   */
+/*     assert false                                                  */
+/*   else                                                            */
+/*     result 0                                                              */
+/*   end if                                                          */
+/* end if                                                            */
+/* var f := setexp(x, 0)  % fraction part of x  [0.1 <= x < 1]       */
+/* var e := getexp(x)    % exponent part of x                        */
+/* var approx : real                                                 */
+/* if e mod 2 = 0  then                                                      */
+/*   approx := .259 + .819 * f  % approx to root of f                */
+/* else                                                                      */
+/*   f := f/l0                  % adjustments                        */
+/*   e := e + 1                         %   for odd                          */
+/*   approx := .0819 + 2.59 * f         %   exponent                         */
+/* end if                                                            */
+/*                                                                   */
+/* var p:= 3                                                         */
+/* const maxp := currentprecision + 2                                */
+/* loop                                                                      */
+/*   p := min(2*p - 2, maxp)    % p = 4,6,10, . . . , maxp           */
+/*   precision p                                                     */
+/*   approx := .5 * (approx + f/approx)                                      */
+/*   exit when p = maxp                                                      */
+/* end loop                                                          */
+/*                                                                   */
 /* % approx is now within 1 ulp of the properly rounded square root   */
 /* % of f; to ensure proper rounding, compare squares of (approx -    */
-/* % l/2 ulp) and (approx + l/2 ulp) with f.                          */
-/* p := currentprecision                                              */
-/* begin                                                              */
-/*   precision p + 2                                                  */
-/*   const approxsubhalf := approx - setexp(.5, -p)                   */
-/*   if mulru(approxsubhalf, approxsubhalf) > f then                  */
-/*     approx := approx - setexp(.l, -p + 1)                          */
-/*   else                                                             */
-/*     const approxaddhalf := approx + setexp(.5, -p)                 */
-/*     if mulrd(approxaddhalf, approxaddhalf) < f then                */
-/*       approx := approx + setexp(.l, -p + 1)                        */
-/*     end if                                                         */
-/*   end if                                                           */
-/* end                                                                */
-/* result setexp(approx, e div 2)  % fix exponent                     */
-/* end sqrt                                                           */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberSquareRoot (decNumber * res, const decNumber * rhs, decContext * set)
-{
-  decContext workset, approxset;       /* work contexts */
-  decNumber dzero;             /* used for constant zero */
-  Int maxp = set->digits + 2;  /* largest working precision */
-  Int residue = 0;             /* rounding residue */
-  uInt status = 0, ignore = 0; /* status accumulators */
-  Int exp;                     /* working exponent */
-  Int ideal;                   /* ideal (preferred) exponent */
-  uInt needbytes;              /* work */
-  Int dropped;                 /* .. */
-
-  decNumber *allocrhs = NULL;  /* non-NULL if rounded rhs allocated */
+/* % l/2 ulp) and (approx + l/2 ulp) with f.                         */
+/* p := currentprecision                                             */
+/* begin                                                             */
+/*   precision p + 2                                                 */
+/*   const approxsubhalf := approx - setexp(.5, -p)                  */
+/*   if mulru(approxsubhalf, approxsubhalf) > f then                 */
+/*     approx := approx - setexp(.l, -p + 1)                         */
+/*   else                                                            */
+/*     const approxaddhalf := approx + setexp(.5, -p)                */
+/*     if mulrd(approxaddhalf, approxaddhalf) < f then               */
+/*      approx := approx + setexp(.l, -p + 1)                        */
+/*     end if                                                        */
+/*   end if                                                          */
+/* end                                                               */
+/* result setexp(approx, e div 2)  % fix exponent                    */
+/* end sqrt                                                          */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberSquareRoot(decNumber *res, const decNumber *rhs,
+                               decContext *set) {
+  decContext workset, approxset;   /* work contexts */
+  decNumber dzero;                /* used for constant zero */
+  Int  maxp;                      /* largest working precision */
+  Int  workp;                     /* working precision */
+  Int  residue=0;                 /* rounding residue */
+  uInt status=0, ignore=0;        /* status accumulators */
+  uInt rstatus;                           /* .. */
+  Int  exp;                       /* working exponent */
+  Int  ideal;                     /* ideal (preferred) exponent */
+  Int  needbytes;                 /* work */
+  Int  dropped;                           /* .. */
+
+  #if DECSUBSET
+  decNumber *allocrhs=NULL;       /* non-NULL if rounded rhs allocated */
+  #endif
   /* buffer for f [needs +1 in case DECBUFFER 0] */
-  uByte buff[sizeof (decNumber) + (D2U (DECBUFFER + 1) - 1) * sizeof (Unit)];
-  /* buffer for a [needs +2 to match maxp] */
-  uByte bufa[sizeof (decNumber) + (D2U (DECBUFFER + 2) - 1) * sizeof (Unit)];
+  decNumber buff[D2N(DECBUFFER+1)];
+  /* buffer for a [needs +2 to match likely maxp] */
+  decNumber bufa[D2N(DECBUFFER+2)];
   /* buffer for temporary, b [must be same size as a] */
-  uByte bufb[sizeof (decNumber) + (D2U (DECBUFFER + 2) - 1) * sizeof (Unit)];
-  decNumber *allocbuff = NULL; /* -> allocated buff, iff allocated */
-  decNumber *allocbufa = NULL; /* -> allocated bufa, iff allocated */
-  decNumber *allocbufb = NULL; /* -> allocated bufb, iff allocated */
-  decNumber *f = (decNumber *) buff;   /* reduced fraction */
-  decNumber *a = (decNumber *) bufa;   /* approximation to result */
-  decNumber *b = (decNumber *) bufb;   /* intermediate result */
+  decNumber bufb[D2N(DECBUFFER+2)];
+  decNumber *allocbuff=NULL;      /* -> allocated buff, iff allocated */
+  decNumber *allocbufa=NULL;      /* -> allocated bufa, iff allocated */
+  decNumber *allocbufb=NULL;      /* -> allocated bufb, iff allocated */
+  decNumber *f=buff;              /* reduced fraction */
+  decNumber *a=bufa;              /* approximation to result */
+  decNumber *b=bufb;              /* intermediate result */
   /* buffer for temporary variable, up to 3 digits */
-  uByte buft[sizeof (decNumber) + (D2U (3) - 1) * sizeof (Unit)];
-  decNumber *t = (decNumber *) buft;   /* up-to-3-digit constant or work */
-
-#if DECCHECK
-  if (decCheckOperands (res, DECUNUSED, rhs, set))
-    return res;
-#endif
-
-  do
-    {                          /* protect allocated storage */
-#if DECSUBSET
-      if (!set->extended)
-       {
-         /* reduce operand and set lostDigits status, as needed */
-         if (rhs->digits > set->digits)
-           {
-             allocrhs = decRoundOperand (rhs, set, &status);
-             if (allocrhs == NULL)
-               break;
-             /* [Note: 'f' allocation below could reuse this buffer if */
-             /* used, but as this is rare we keep them separate for clarity.] */
-             rhs = allocrhs;
-           }
+  decNumber buft[D2N(3)];
+  decNumber *t=buft;              /* up-to-3-digit constant or work */
+
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  do {                            /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operand and set lostDigits status, as needed */
+      if (rhs->digits>set->digits) {
+       allocrhs=decRoundOperand(rhs, set, &status);
+       if (allocrhs==NULL) break;
+       /* [Note: 'f' allocation below could reuse this buffer if */
+       /* used, but as this is rare they are kept separate for clarity.] */
+       rhs=allocrhs;
        }
-#endif
-      /* [following code does not require input rounding] */
-
-      /* handle infinities and NaNs */
-      if (rhs->bits & DECSPECIAL)
-       {
-         if (decNumberIsInfinite (rhs))
-           {                   /* an infinity */
-             if (decNumberIsNegative (rhs))
-               status |= DEC_Invalid_operation;
-             else
-               decNumberCopy (res, rhs);       /* +Infinity */
-           }
-         else
-           decNaNs (res, rhs, NULL, &status);  /* a NaN */
-         break;
+      }
+    #endif
+    /* [following code does not require input rounding] */
+
+    /* handle infinities and NaNs */
+    if (SPECIALARG) {
+      if (decNumberIsInfinite(rhs)) {        /* an infinity */
+       if (decNumberIsNegative(rhs)) status|=DEC_Invalid_operation;
+        else decNumberCopy(res, rhs);        /* +Infinity */
        }
+       else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
+      break;
+      }
 
-      /* calculate the ideal (preferred) exponent [floor(exp/2)] */
-      /* [We would like to write: ideal=rhs->exponent>>1, but this */
-      /* generates a compiler warning.  Generated code is the same.] */
-      ideal = (rhs->exponent & ~1) / 2;        /* target */
+    /* calculate the ideal (preferred) exponent [floor(exp/2)] */
+    /* [We would like to write: ideal=rhs->exponent>>1, but this */
+    /* generates a compiler warning.  Generated code is the same.] */
+    ideal=(rhs->exponent&~1)/2;                /* target */
+
+    /* handle zeros */
+    if (ISZERO(rhs)) {
+      decNumberCopy(res, rhs);         /* could be 0 or -0 */
+      res->exponent=ideal;             /* use the ideal [safe] */
+      /* use decFinish to clamp any out-of-range exponent, etc. */
+      decFinish(res, set, &residue, &status);
+      break;
+      }
 
-      /* handle zeros */
-      if (ISZERO (rhs))
-       {
-         decNumberCopy (res, rhs);     /* could be 0 or -0 */
-         res->exponent = ideal;        /* use the ideal [safe] */
-         break;
-       }
+    /* any other -x is an oops */
+    if (decNumberIsNegative(rhs)) {
+      status|=DEC_Invalid_operation;
+      break;
+      }
 
-      /* any other -x is an oops */
-      if (decNumberIsNegative (rhs))
-       {
-         status |= DEC_Invalid_operation;
-         break;
-       }
+    /* space is needed for three working variables */
+    /*  f -- the same precision as the RHS, reduced to 0.01->0.99... */
+    /*  a -- Hull's approximation -- precision, when assigned, is */
+    /*       currentprecision+1 or the input argument precision, */
+    /*       whichever is larger (+2 for use as temporary) */
+    /*  b -- intermediate temporary result (same size as a) */
+    /* if any is too long for local storage, then allocate */
+    workp=MAXI(set->digits+1, rhs->digits);  /* actual rounding precision */
+    maxp=workp+2;                           /* largest working precision */
+
+    needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
+    if (needbytes>(Int)sizeof(buff)) {
+      allocbuff=(decNumber *)malloc(needbytes);
+      if (allocbuff==NULL) {  /* hopeless -- abandon */
+       status|=DEC_Insufficient_storage;
+       break;}
+      f=allocbuff;           /* use the allocated space */
+      }
+    /* a and b both need to be able to hold a maxp-length number */
+    needbytes=sizeof(decNumber)+(D2U(maxp)-1)*sizeof(Unit);
+    if (needbytes>(Int)sizeof(bufa)) {           /* [same applies to b] */
+      allocbufa=(decNumber *)malloc(needbytes);
+      allocbufb=(decNumber *)malloc(needbytes);
+      if (allocbufa==NULL || allocbufb==NULL) {          /* hopeless */
+       status|=DEC_Insufficient_storage;
+       break;}
+      a=allocbufa;           /* use the allocated spaces */
+      b=allocbufb;           /* .. */
+      }
 
-      /* we need space for three working variables */
-      /*   f -- the same precision as the RHS, reduced to 0.01->0.99... */
-      /*   a -- Hull's approx -- precision, when assigned, is */
-      /*        currentprecision (we allow +2 for use as temporary) */
-      /*   b -- intermediate temporary result */
-      /* if any is too long for local storage, then allocate */
-      needbytes =
-       sizeof (decNumber) + (D2U (rhs->digits) - 1) * sizeof (Unit);
-      if (needbytes > sizeof (buff))
-       {
-         allocbuff = (decNumber *) malloc (needbytes);
-         if (allocbuff == NULL)
-           {                   /* hopeless -- abandon */
-             status |= DEC_Insufficient_storage;
-             break;
-           }
-         f = allocbuff;        /* use the allocated space */
-       }
-      /* a and b both need to be able to hold a maxp-length number */
-      needbytes = sizeof (decNumber) + (D2U (maxp) - 1) * sizeof (Unit);
-      if (needbytes > sizeof (bufa))
-       {                       /* [same applies to b] */
-         allocbufa = (decNumber *) malloc (needbytes);
-         allocbufb = (decNumber *) malloc (needbytes);
-         if (allocbufa == NULL || allocbufb == NULL)
-           {                   /* hopeless */
-             status |= DEC_Insufficient_storage;
-             break;
-           }
-         a = allocbufa;        /* use the allocated space */
-         b = allocbufb;        /* .. */
-       }
+    /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */
+    decNumberCopy(f, rhs);
+    exp=f->exponent+f->digits;              /* adjusted to Hull rules */
+    f->exponent=-(f->digits);               /* to range */
+
+    /* set up working context */
+    decContextDefault(&workset, DEC_INIT_DECIMAL64);
+
+    /* [Until further notice, no error is possible and status bits */
+    /* (Rounded, etc.) should be ignored, not accumulated.] */
+
+    /* Calculate initial approximation, and allow for odd exponent */
+    workset.digits=workp;                   /* p for initial calculation */
+    t->bits=0; t->digits=3;
+    a->bits=0; a->digits=3;
+    if ((exp & 1)==0) {                             /* even exponent */
+      /* Set t=0.259, a=0.819 */
+      t->exponent=-3;
+      a->exponent=-3;
+      #if DECDPUN>=3
+       t->lsu[0]=259;
+       a->lsu[0]=819;
+      #elif DECDPUN==2
+       t->lsu[0]=59; t->lsu[1]=2;
+       a->lsu[0]=19; a->lsu[1]=8;
+      #else
+       t->lsu[0]=9; t->lsu[1]=5; t->lsu[2]=2;
+       a->lsu[0]=9; a->lsu[1]=1; a->lsu[2]=8;
+      #endif
+      }
+     else {                                 /* odd exponent */
+      /* Set t=0.0819, a=2.59 */
+      f->exponent--;                        /* f=f/10 */
+      exp++;                                /* e=e+1 */
+      t->exponent=-4;
+      a->exponent=-2;
+      #if DECDPUN>=3
+       t->lsu[0]=819;
+       a->lsu[0]=259;
+      #elif DECDPUN==2
+       t->lsu[0]=19; t->lsu[1]=8;
+       a->lsu[0]=59; a->lsu[1]=2;
+      #else
+       t->lsu[0]=9; t->lsu[1]=1; t->lsu[2]=8;
+       a->lsu[0]=9; a->lsu[1]=5; a->lsu[2]=2;
+      #endif
+      }
+    decMultiplyOp(a, a, f, &workset, &ignore);   /* a=a*f */
+    decAddOp(a, a, t, &workset, 0, &ignore);     /* ..+t */
+    /* [a is now the initial approximation for sqrt(f), calculated with */
+    /* currentprecision, which is also a's precision.] */
+
+    /* the main calculation loop */
+    decNumberZero(&dzero);                  /* make 0 */
+    decNumberZero(t);                       /* set t = 0.5 */
+    t->lsu[0]=5;                            /* .. */
+    t->exponent=-1;                         /* .. */
+    workset.digits=3;                       /* initial p */
+    for (;;) {
+      /* set p to min(2*p - 2, maxp)  [hence 3; or: 4, 6, 10, ... , maxp] */
+      workset.digits=workset.digits*2-2;
+      if (workset.digits>maxp) workset.digits=maxp;
+      /* a = 0.5 * (a + f/a) */
+      /* [calculated at p then rounded to currentprecision] */
+      decDivideOp(b, f, a, &workset, DIVIDE, &ignore); /* b=f/a */
+      decAddOp(b, b, a, &workset, 0, &ignore);   /* b=b+a */
+      decMultiplyOp(a, b, t, &workset, &ignore);  /* a=b*0.5 */
+      if (a->digits==maxp) break;           /* have required digits */
+      } /* loop */
+
+    /* Here, 0.1 <= a < 1 [Hull], and a has maxp digits */
+    /* now reduce to length, etc.; this needs to be done with a */
+    /* having the correct exponent so as to handle subnormals */
+    /* correctly */
+    approxset=*set;                         /* get emin, emax, etc. */
+    approxset.round=DEC_ROUND_HALF_EVEN;
+    a->exponent+=exp/2;                             /* set correct exponent */
+
+    rstatus=0;                              /* clear status */
+    residue=0;                              /* .. and accumulator */
+    decCopyFit(a, a, &approxset, &residue, &rstatus);  /* reduce (if needed) */
+    decFinish(a, &approxset, &residue, &rstatus);      /* clean and finalize */
+
+    /* Overflow was possible if the input exponent was out-of-range, */
+    /* in which case quit */
+    if (rstatus&DEC_Overflow) {
+      status=rstatus;                       /* use the status as-is */
+      decNumberCopy(res, a);                /* copy to result */
+      break;
+      }
 
-      /* copy rhs -> f, save exponent, and reduce so 0.1 <= f < 1 */
-      decNumberCopy (f, rhs);
-      exp = f->exponent + f->digits;   /* adjusted to Hull rules */
-      f->exponent = -(f->digits);      /* to range */
-
-      /* set up working contexts (the second is used for Numerical */
-      /* Turing assignment) */
-      decContextDefault (&workset, DEC_INIT_DECIMAL64);
-      decContextDefault (&approxset, DEC_INIT_DECIMAL64);
-      approxset.digits = set->digits;  /* approx's length */
-
-      /* [Until further notice, no error is possible and status bits */
-      /* (Rounded, etc.) should be ignored, not accumulated.] */
-
-      /* Calculate initial approximation, and allow for odd exponent */
-      workset.digits = set->digits;    /* p for initial calculation */
-      t->bits = 0;
-      t->digits = 3;
-      a->bits = 0;
-      a->digits = 3;
-      if ((exp & 1) == 0)
-       {                       /* even exponent */
-         /* Set t=0.259, a=0.819 */
-         t->exponent = -3;
-         a->exponent = -3;
-#if DECDPUN>=3
-         t->lsu[0] = 259;
-         a->lsu[0] = 819;
-#elif DECDPUN==2
-         t->lsu[0] = 59;
-         t->lsu[1] = 2;
-         a->lsu[0] = 19;
-         a->lsu[1] = 8;
-#else
-         t->lsu[0] = 9;
-         t->lsu[1] = 5;
-         t->lsu[2] = 2;
-         a->lsu[0] = 9;
-         a->lsu[1] = 1;
-         a->lsu[2] = 8;
-#endif
-       }
-      else
-       {                       /* odd exponent */
-         /* Set t=0.0819, a=2.59 */
-         f->exponent--;        /* f=f/10 */
-         exp++;                /* e=e+1 */
-         t->exponent = -4;
-         a->exponent = -2;
-#if DECDPUN>=3
-         t->lsu[0] = 819;
-         a->lsu[0] = 259;
-#elif DECDPUN==2
-         t->lsu[0] = 19;
-         t->lsu[1] = 8;
-         a->lsu[0] = 59;
-         a->lsu[1] = 2;
-#else
-         t->lsu[0] = 9;
-         t->lsu[1] = 1;
-         t->lsu[2] = 8;
-         a->lsu[0] = 9;
-         a->lsu[1] = 5;
-         a->lsu[2] = 2;
-#endif
-       }
-      decMultiplyOp (a, a, f, &workset, &ignore);      /* a=a*f */
-      decAddOp (a, a, t, &workset, 0, &ignore);        /* ..+t */
-      /* [a is now the initial approximation for sqrt(f), calculated with */
-      /* currentprecision, which is also a's precision.] */
-
-      /* the main calculation loop */
-      decNumberZero (&dzero);  /* make 0 */
-      decNumberZero (t);       /* set t = 0.5 */
-      t->lsu[0] = 5;           /* .. */
-      t->exponent = -1;                /* .. */
-      workset.digits = 3;      /* initial p */
-      for (;;)
-       {
-         /* set p to min(2*p - 2, maxp)  [hence 3; or: 4, 6, 10, ... , maxp] */
-         workset.digits = workset.digits * 2 - 2;
-         if (workset.digits > maxp)
-           workset.digits = maxp;
-         /* a = 0.5 * (a + f/a) */
-         /* [calculated at p then rounded to currentprecision] */
-         decDivideOp (b, f, a, &workset, DIVIDE, &ignore);     /* b=f/a */
-         decAddOp (b, b, a, &workset, 0, &ignore);     /* b=b+a */
-         decMultiplyOp (a, b, t, &workset, &ignore);   /* a=b*0.5 */
-         /* assign to approx [round to length] */
-         decAddOp (a, &dzero, a, &approxset, 0, &ignore);
-         if (workset.digits == maxp)
-           break;              /* just did final */
-       }                       /* loop */
-
-      /* a is now at currentprecision and within 1 ulp of the properly */
-      /* rounded square root of f; to ensure proper rounding, compare */
-      /* squares of (a - l/2 ulp) and (a + l/2 ulp) with f. */
-      /* Here workset.digits=maxp and t=0.5 */
-      workset.digits--;                /* maxp-1 is OK now */
-      t->exponent = -set->digits - 1;  /* make 0.5 ulp */
-      decNumberCopy (b, a);
-      decAddOp (b, b, t, &workset, DECNEG, &ignore);   /* b = a - 0.5 ulp */
-      workset.round = DEC_ROUND_UP;
-      decMultiplyOp (b, b, b, &workset, &ignore);      /* b = mulru(b, b) */
-      decCompareOp (b, f, b, &workset, COMPARE, &ignore);      /* b ? f, reversed */
-      if (decNumberIsNegative (b))
-       {                       /* f < b [i.e., b > f] */
-         /* this is the more common adjustment, though both are rare */
-         t->exponent++;        /* make 1.0 ulp */
-         t->lsu[0] = 1;        /* .. */
-         decAddOp (a, a, t, &workset, DECNEG, &ignore);        /* a = a - 1 ulp */
-         /* assign to approx [round to length] */
-         decAddOp (a, &dzero, a, &approxset, 0, &ignore);
-       }
-      else
-       {
-         decNumberCopy (b, a);
-         decAddOp (b, b, t, &workset, 0, &ignore);     /* b = a + 0.5 ulp */
-         workset.round = DEC_ROUND_DOWN;
-         decMultiplyOp (b, b, b, &workset, &ignore);   /* b = mulrd(b, b) */
-         decCompareOp (b, b, f, &workset, COMPARE, &ignore);   /* b ? f */
-         if (decNumberIsNegative (b))
-           {                   /* b < f */
-             t->exponent++;    /* make 1.0 ulp */
-             t->lsu[0] = 1;    /* .. */
-             decAddOp (a, a, t, &workset, 0, &ignore); /* a = a + 1 ulp */
-             /* assign to approx [round to length] */
-             decAddOp (a, &dzero, a, &approxset, 0, &ignore);
-           }
+    /* Preserve status except Inexact/Rounded */
+    status|=(rstatus & ~(DEC_Rounded|DEC_Inexact));
+
+    /* Carry out the Hull correction */
+    a->exponent-=exp/2;                             /* back to 0.1->1 */
+
+    /* a is now at final precision and within 1 ulp of the properly */
+    /* rounded square root of f; to ensure proper rounding, compare */
+    /* 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 */
+    /* the ulp */
+    workset.digits--;                            /* maxp-1 is OK now */
+    t->exponent=-a->digits-1;                    /* make 0.5 ulp */
+    decAddOp(b, a, t, &workset, DECNEG, &ignore); /* b = a - 0.5 ulp */
+    workset.round=DEC_ROUND_UP;
+    decMultiplyOp(b, b, b, &workset, &ignore);   /* b = mulru(b, b) */
+    decCompareOp(b, f, b, &workset, COMPARE, &ignore); /* b ? f, reversed */
+    if (decNumberIsNegative(b)) {                /* f < b [i.e., b > f] */
+      /* this is the more common adjustment, though both are rare */
+      t->exponent++;                             /* make 1.0 ulp */
+      t->lsu[0]=1;                               /* .. */
+      decAddOp(a, a, t, &workset, DECNEG, &ignore); /* a = a - 1 ulp */
+      /* assign to approx [round to length] */
+      approxset.emin-=exp/2;                     /* adjust to match a */
+      approxset.emax-=exp/2;
+      decAddOp(a, &dzero, a, &approxset, 0, &ignore);
+      }
+     else {
+      decAddOp(b, a, t, &workset, 0, &ignore);   /* b = a + 0.5 ulp */
+      workset.round=DEC_ROUND_DOWN;
+      decMultiplyOp(b, b, b, &workset, &ignore);  /* b = mulrd(b, b) */
+      decCompareOp(b, b, f, &workset, COMPARE, &ignore);   /* b ? f */
+      if (decNumberIsNegative(b)) {              /* b < f */
+       t->exponent++;                            /* make 1.0 ulp */
+       t->lsu[0]=1;                              /* .. */
+       decAddOp(a, a, t, &workset, 0, &ignore);  /* a = a + 1 ulp */
+       /* assign to approx [round to length] */
+       approxset.emin-=exp/2;                    /* adjust to match a */
+       approxset.emax-=exp/2;
+       decAddOp(a, &dzero, a, &approxset, 0, &ignore);
        }
-      /* [no errors are possible in the above, and rounding/inexact during */
-      /* estimation are irrelevant, so status was not accumulated] */
-
-      /* Here, 0.1 <= a < 1  [Hull] */
-      a->exponent += exp / 2;  /* set correct exponent */
-
-      /* Process Subnormals */
-      decFinalize (a, set, &residue, &status);
-
-      /* count dropable zeros [after any subnormal rounding] */
-      decNumberCopy (b, a);
-      decTrim (b, 1, &dropped);        /* [drops trailing zeros] */
-
-      /* Finally set Inexact and Rounded.  The answer can only be exact if */
-      /* it is short enough so that squaring it could fit in set->digits, */
-      /* so this is the only (relatively rare) time we have to check */
-      /* carefully */
-      if (b->digits * 2 - 1 > set->digits)
-       {                       /* cannot fit */
-         status |= DEC_Inexact | DEC_Rounded;
+      }
+    /* [no errors are possible in the above, and rounding/inexact during */
+    /* estimation are irrelevant, so status was not accumulated] */
+
+    /* Here, 0.1 <= a < 1  (still), so adjust back */
+    a->exponent+=exp/2;                             /* set correct exponent */
+
+    /* count droppable zeros [after any subnormal rounding] by */
+    /* trimming a copy */
+    decNumberCopy(b, a);
+    decTrim(b, set, 1, &dropped);           /* [drops trailing zeros] */
+
+    /* Set Inexact and Rounded.         The answer can only be exact if */
+    /* 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 */
+    /* the only (relatively rare) conditions a careful check is needed */
+    if (b->digits*2-1 > workp && !set->clamp) { /* cannot fit */
+      status|=DEC_Inexact|DEC_Rounded;
+      }
+     else {                                 /* could be exact/unrounded */
+      uInt mstatus=0;                       /* local status */
+      decMultiplyOp(b, b, b, &workset, &mstatus); /* try the multiply */
+      if (mstatus&DEC_Overflow) {           /* result just won't fit */
+       status|=DEC_Inexact|DEC_Rounded;
        }
-      else
-       {                       /* could be exact/unrounded */
-         uInt mstatus = 0;     /* local status */
-         decMultiplyOp (b, b, b, &workset, &mstatus);  /* try the multiply */
-         if (mstatus != 0)
-           {                   /* result won't fit */
-             status |= DEC_Inexact | DEC_Rounded;
-           }
-         else
-           {                   /* plausible */
-             decCompareOp (t, b, rhs, &workset, COMPARE, &mstatus);    /* b ? rhs */
-             if (!ISZERO (t))
-               {
-                 status |= DEC_Inexact | DEC_Rounded;
-               }
-             else
-               {               /* is Exact */
-                 /* here, dropped is the count of trailing zeros in 'a' */
-                 /* use closest exponent to ideal... */
-                 Int todrop = ideal - a->exponent;     /* most we can drop */
-
-                 if (todrop < 0)
-                   {           /* ideally would add 0s */
-                     status |= DEC_Rounded;
-                   }
-                 else
-                   {           /* unrounded */
-                     if (dropped < todrop)
-                       todrop = dropped;       /* clamp to those available */
-                     if (todrop > 0)
-                       {       /* OK, some to drop */
-                         decShiftToLeast (a->lsu, D2U (a->digits), todrop);
-                         a->exponent += todrop;        /* maintain numerical value */
-                         a->digits -= todrop;  /* new length */
-                       }
-                   }
-               }
+       else {                               /* plausible */
+       decCompareOp(t, b, rhs, &workset, COMPARE, &mstatus); /* b ? rhs */
+       if (!ISZERO(t)) status|=DEC_Inexact|DEC_Rounded; /* not equal */
+        else {                              /* is Exact */
+         /* here, dropped is the count of trailing zeros in 'a' */
+         /* use closest exponent to ideal... */
+         Int todrop=ideal-a->exponent;      /* most that can be dropped */
+         if (todrop<0) status|=DEC_Rounded; /* ideally would add 0s */
+          else {                            /* unrounded */
+           if (dropped<todrop) {            /* clamp to those available */
+             todrop=dropped;
+             status|=DEC_Clamped;
+             }
+           if (todrop>0) {                  /* have some to drop */
+             decShiftToLeast(a->lsu, D2U(a->digits), todrop);
+             a->exponent+=todrop;           /* maintain numerical value */
+             a->digits-=todrop;             /* new length */
+             }
            }
+         }
        }
-      decNumberCopy (res, a);  /* assume this is the result */
-    }
-  while (0);                   /* end protected */
-
-  if (allocbuff != NULL)
-    free (allocbuff);          /* drop any storage we used */
-  if (allocbufa != NULL)
-    free (allocbufa);          /* .. */
-  if (allocbufb != NULL)
-    free (allocbufb);          /* .. */
-  if (allocrhs != NULL)
-    free (allocrhs);           /* .. */
-  if (status != 0)
-    decStatus (res, status, set);      /* then report status */
+      }
+
+    /* double-check Underflow, as perhaps the result could not have */
+    /* been subnormal (initial argument too big), or it is now Exact */
+    if (status&DEC_Underflow) {
+      Int ae=rhs->exponent+rhs->digits-1;    /* adjusted exponent */
+      /* check if truly subnormal */
+      #if DECEXTFLAG                        /* DEC_Subnormal too */
+       if (ae>=set->emin*2) status&=~(DEC_Subnormal|DEC_Underflow);
+      #else
+       if (ae>=set->emin*2) status&=~DEC_Underflow;
+      #endif
+      /* check if truly inexact */
+      if (!(status&DEC_Inexact)) status&=~DEC_Underflow;
+      }
+
+    decNumberCopy(res, a);                  /* a is now the result */
+    } while(0);                                     /* end protected */
+
+  if (allocbuff!=NULL) free(allocbuff);             /* drop any storage used */
+  if (allocbufa!=NULL) free(allocbufa);             /* .. */
+  if (allocbufb!=NULL) free(allocbufb);             /* .. */
+  #if DECSUBSET
+  if (allocrhs !=NULL) free(allocrhs);      /* .. */
+  #endif
+  if (status!=0) decStatus(res, status, set);/* then report status */
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberSubtract -- subtract two Numbers                          */
-/*                                                                    */
-/*   This computes C = A - B                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X-X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-decNumber *
-decNumberSubtract (decNumber * res, const decNumber * lhs,
-                  const decNumber * rhs, decContext * set)
-{
-  uInt status = 0;             /* accumulator */
-
-  decAddOp (res, lhs, rhs, set, DECNEG, &status);
-  if (status != 0)
-    decStatus (res, status, set);
+  } /* decNumberSquareRoot */
+
+/* ------------------------------------------------------------------ */
+/* decNumberSubtract -- subtract two Numbers                         */
+/*                                                                   */
+/*   This computes C = A - B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X-X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberSubtract(decNumber *res, const decNumber *lhs,
+                             const decNumber *rhs, decContext *set) {
+  uInt status=0;                       /* accumulator */
+
+  decAddOp(res, lhs, rhs, set, DECNEG, &status);
+  if (status!=0) decStatus(res, status, set);
+  #if DECCHECK
+  decCheckInexact(res, set);
+  #endif
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNumberToIntegralValue -- round-to-integral-value                */
-/*                                                                    */
-/*   res is the result                                                */
-/*   rhs is input number                                              */
-/*   set is the context                                               */
-/*                                                                    */
-/* res must have space for any value of rhs.                          */
-/*                                                                    */
-/* This implements the IEEE special operator and therefore treats     */
-/* special values as valid, and also never sets Inexact.  For finite  */
-/* numbers it returns rescale(rhs, 0) if rhs->exponent is <0.         */
-/* Otherwise the result is rhs (so no error is possible).             */
-/*                                                                    */
+  } /* decNumberSubtract */
+
+/* ------------------------------------------------------------------ */
+/* decNumberToIntegralExact -- round-to-integral-value with InExact   */
+/* decNumberToIntegralValue -- round-to-integral-value               */
+/*                                                                   */
+/*   res is the result                                               */
+/*   rhs is input number                                             */
+/*   set is the context                                                      */
+/*                                                                   */
+/* res must have space for any value of rhs.                         */
+/*                                                                   */
+/* This implements the IEEE special operators and therefore treats    */
+/* special values as valid.  For finite numbers it returns           */
+/* rescale(rhs, 0) if rhs->exponent is <0.                           */
+/* Otherwise the result is rhs (so no error is possible, except for   */
+/* sNaN).                                                            */
+/*                                                                   */
 /* The context is used for rounding mode and status after sNaN, but   */
-/* the digits setting is ignored.                                     */
+/* the digits setting is ignored.  The Exact version will signal      */
+/* Inexact if the result differs numerically from rhs; the other      */
+/* never signals Inexact.                                            */
 /* ------------------------------------------------------------------ */
-decNumber *
-decNumberToIntegralValue (decNumber * res, const decNumber * rhs, decContext * set)
-{
+decNumber * decNumberToIntegralExact(decNumber *res, const decNumber *rhs,
+                                    decContext *set) {
   decNumber dn;
-  decContext workset;          /* working context */
+  decContext workset;             /* working context */
+  uInt status=0;                  /* accumulator */
 
-#if DECCHECK
-  if (decCheckOperands (res, DECUNUSED, rhs, set))
-    return res;
-#endif
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
 
   /* handle infinities and NaNs */
-  if (rhs->bits & DECSPECIAL)
-    {
-      uInt status = 0;
-      if (decNumberIsInfinite (rhs))
-       decNumberCopy (res, rhs);       /* an Infinity */
-      else
-       decNaNs (res, rhs, NULL, &status);      /* a NaN */
-      if (status != 0)
-       decStatus (res, status, set);
-      return res;
+  if (SPECIALARG) {
+    if (decNumberIsInfinite(rhs)) decNumberCopy(res, rhs); /* an Infinity */
+     else decNaNs(res, rhs, NULL, set, &status); /* a NaN */
+    }
+   else { /* finite */
+    /* have a finite number; no error possible (res must be big enough) */
+    if (rhs->exponent>=0) return decNumberCopy(res, rhs);
+    /* that was easy, but if negative exponent there is work to do... */
+    workset=*set;                 /* clone rounding, etc. */
+    workset.digits=rhs->digits;           /* no length rounding */
+    workset.traps=0;              /* no traps */
+    decNumberZero(&dn);                   /* make a number with exponent 0 */
+    decNumberQuantize(res, rhs, &dn, &workset);
+    status|=workset.status;
+    }
+  if (status!=0) decStatus(res, status, set);
+  return res;
+  } /* decNumberToIntegralExact */
+
+decNumber * decNumberToIntegralValue(decNumber *res, const decNumber *rhs,
+                                    decContext *set) {
+  decContext workset=*set;        /* working context */
+  workset.traps=0;                /* no traps */
+  decNumberToIntegralExact(res, rhs, &workset);
+  /* this never affects set, except for sNaNs; NaN will have been set */
+  /* or propagated already, so no need to call decStatus */
+  set->status|=workset.status&DEC_Invalid_operation;
+  return res;
+  } /* decNumberToIntegralValue */
+
+/* ------------------------------------------------------------------ */
+/* decNumberXor -- XOR two Numbers, digitwise                        */
+/*                                                                   */
+/*   This computes C = A ^ B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X^X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context (used for result length and error report)     */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Logical function restrictions apply (see above); a NaN is         */
+/* returned with Invalid_operation if a restriction is violated.      */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberXor(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, decContext *set) {
+  const Unit *ua, *ub;                 /* -> operands */
+  const Unit *msua, *msub;             /* -> operand msus */
+  Unit *uc, *msuc;                     /* -> result and its msu */
+  Int  msudigs;                        /* digits in res msu */
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  if (lhs->exponent!=0 || decNumberIsSpecial(lhs) || decNumberIsNegative(lhs)
+   || rhs->exponent!=0 || decNumberIsSpecial(rhs) || decNumberIsNegative(rhs)) {
+    decStatus(res, DEC_Invalid_operation, set);
+    return res;
     }
+  /* operands are valid */
+  ua=lhs->lsu;                         /* bottom-up */
+  ub=rhs->lsu;                         /* .. */
+  uc=res->lsu;                         /* .. */
+  msua=ua+D2U(lhs->digits)-1;          /* -> msu of lhs */
+  msub=ub+D2U(rhs->digits)-1;          /* -> msu of rhs */
+  msuc=uc+D2U(set->digits)-1;          /* -> msu of result */
+  msudigs=MSUDIGITS(set->digits);      /* [faster than remainder] */
+  for (; uc<=msuc; ua++, ub++, uc++) { /* Unit loop */
+    Unit a, b;                         /* extract units */
+    if (ua>msua) a=0;
+     else a=*ua;
+    if (ub>msub) b=0;
+     else b=*ub;
+    *uc=0;                             /* can now write back */
+    if (a|b) {                         /* maybe 1 bits to examine */
+      Int i, j;
+      /* This loop could be unrolled and/or use BIN2BCD tables */
+      for (i=0; i<DECDPUN; i++) {
+       if ((a^b)&1) *uc=*uc+(Unit)powers[i];     /* effect XOR */
+       j=a%10;
+       a=a/10;
+       j|=b%10;
+       b=b/10;
+       if (j>1) {
+         decStatus(res, DEC_Invalid_operation, set);
+         return res;
+         }
+       if (uc==msuc && i==msudigs-1) break;      /* just did final digit */
+       } /* each digit */
+      } /* non-zero */
+    } /* each unit */
+  /* [here uc-1 is the msu of the result] */
+  res->digits=decGetDigits(res->lsu, uc-res->lsu);
+  res->exponent=0;                     /* integer */
+  res->bits=0;                         /* sign=0 */
+  return res;  /* [no status to set] */
+  } /* decNumberXor */
 
-  /* we have a finite number; no error possible */
-  if (rhs->exponent >= 0)
-    return decNumberCopy (res, rhs);
-  /* that was easy, but if negative exponent we have work to do... */
-  workset = *set;              /* clone rounding, etc. */
-  workset.digits = rhs->digits;        /* no length rounding */
-  workset.traps = 0;           /* no traps */
-  decNumberZero (&dn);         /* make a number with exponent 0 */
-  return decNumberQuantize (res, rhs, &dn, &workset);
-}
 
 /* ================================================================== */
-/* Utility routines                                                   */
+/* Utility routines                                                  */
 /* ================================================================== */
 
 /* ------------------------------------------------------------------ */
-/* decNumberCopy -- copy a number                                     */
-/*                                                                    */
-/*   dest is the target decNumber                                     */
-/*   src  is the source decNumber                                     */
-/*   returns dest                                                     */
-/*                                                                    */
-/* (dest==src is allowed and is a no-op)                              */
-/* All fields are updated as required.  This is a utility operation,  */
-/* so special values are unchanged and no error is possible.          */
+/* decNumberClass -- return the decClass of a decNumber                      */
+/*   dn -- the decNumber to test                                     */
+/*   set -- the context to use for Emin                                      */
+/*   returns the decClass enum                                       */
 /* ------------------------------------------------------------------ */
-decNumber *
-decNumberCopy (decNumber * dest, const decNumber * src)
-{
-
-#if DECCHECK
-  if (src == NULL)
-    return decNumberZero (dest);
-#endif
-
-  if (dest == src)
-    return dest;               /* no copy required */
-
-  /* We use explicit assignments here as structure assignment can copy */
+enum decClass decNumberClass(const decNumber *dn, decContext *set) {
+  if (decNumberIsSpecial(dn)) {
+    if (decNumberIsQNaN(dn)) return DEC_CLASS_QNAN;
+    if (decNumberIsSNaN(dn)) return DEC_CLASS_SNAN;
+    /* must be an infinity */
+    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_INF;
+    return DEC_CLASS_POS_INF;
+    }
+  /* is finite */
+  if (decNumberIsNormal(dn, set)) { /* most common */
+    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_NORMAL;
+    return DEC_CLASS_POS_NORMAL;
+    }
+  /* is subnormal or zero */
+  if (decNumberIsZero(dn)) {   /* most common */
+    if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_ZERO;
+    return DEC_CLASS_POS_ZERO;
+    }
+  if (decNumberIsNegative(dn)) return DEC_CLASS_NEG_SUBNORMAL;
+  return DEC_CLASS_POS_SUBNORMAL;
+  } /* decNumberClass */
+
+/* ------------------------------------------------------------------ */
+/* decNumberClassToString -- convert decClass to a string            */
+/*                                                                   */
+/*  eclass is a valid decClass                                       */
+/*  returns a constant string describing the class (max 13+1 chars)   */
+/* ------------------------------------------------------------------ */
+const char *decNumberClassToString(enum decClass eclass) {
+  if (eclass==DEC_CLASS_POS_NORMAL)    return DEC_ClassString_PN;
+  if (eclass==DEC_CLASS_NEG_NORMAL)    return DEC_ClassString_NN;
+  if (eclass==DEC_CLASS_POS_ZERO)      return DEC_ClassString_PZ;
+  if (eclass==DEC_CLASS_NEG_ZERO)      return DEC_ClassString_NZ;
+  if (eclass==DEC_CLASS_POS_SUBNORMAL) return DEC_ClassString_PS;
+  if (eclass==DEC_CLASS_NEG_SUBNORMAL) return DEC_ClassString_NS;
+  if (eclass==DEC_CLASS_POS_INF)       return DEC_ClassString_PI;
+  if (eclass==DEC_CLASS_NEG_INF)       return DEC_ClassString_NI;
+  if (eclass==DEC_CLASS_QNAN)         return DEC_ClassString_QN;
+  if (eclass==DEC_CLASS_SNAN)         return DEC_ClassString_SN;
+  return DEC_ClassString_UN;          /* Unknown */
+  } /* decNumberClassToString */
+
+/* ------------------------------------------------------------------ */
+/* decNumberCopy -- copy a number                                    */
+/*                                                                   */
+/*   dest is the target decNumber                                    */
+/*   src  is the source decNumber                                    */
+/*   returns dest                                                    */
+/*                                                                   */
+/* (dest==src is allowed and is a no-op)                             */
+/* All fields are updated as required. This is a utility operation,  */
+/* so special values are unchanged and no error is possible.         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberCopy(decNumber *dest, const decNumber *src) {
+
+  #if DECCHECK
+  if (src==NULL) return decNumberZero(dest);
+  #endif
+
+  if (dest==src) return dest;               /* no copy required */
+
+  /* Use explicit assignments here as structure assignment could copy */
   /* more than just the lsu (for small DECDPUN).  This would not affect */
-  /* the value of the results, but would disturb test harness spill */
+  /* the value of the results, but could disturb test harness spill */
   /* checking. */
-  dest->bits = src->bits;
-  dest->exponent = src->exponent;
-  dest->digits = src->digits;
-  dest->lsu[0] = src->lsu[0];
-  if (src->digits > DECDPUN)
-    {                          /* more Units to come */
-      Unit *d;                 /* work */
-      const Unit *s, *smsup;   /* work */
-      /* memcpy for the remaining Units would be safe as they cannot */
-      /* overlap.  However, this explicit loop is faster in short cases. */
-      d = dest->lsu + 1;       /* -> first destination */
-      smsup = src->lsu + D2U (src->digits);    /* -> source msu+1 */
-      for (s = src->lsu + 1; s < smsup; s++, d++)
-       *d = *s;
+  dest->bits=src->bits;
+  dest->exponent=src->exponent;
+  dest->digits=src->digits;
+  dest->lsu[0]=src->lsu[0];
+  if (src->digits>DECDPUN) {                /* more Units to come */
+    const Unit *smsup, *s;                  /* work */
+    Unit  *d;                               /* .. */
+    /* memcpy for the remaining Units would be safe as they cannot */
+    /* overlap.         However, this explicit loop is faster in short cases. */
+    d=dest->lsu+1;                          /* -> first destination */
+    smsup=src->lsu+D2U(src->digits);        /* -> source msu+1 */
+    for (s=src->lsu+1; s<smsup; s++, d++) *d=*s;
     }
   return dest;
-}
+  } /* decNumberCopy */
+
+/* ------------------------------------------------------------------ */
+/* decNumberCopyAbs -- quiet absolute value operator                 */
+/*                                                                   */
+/*   This sets C = abs(A)                                            */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* No exception or error can occur; this is a quiet bitwise operation.*/
+/* See also decNumberAbs for a checking version of this.             */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberCopyAbs(decNumber *res, const decNumber *rhs) {
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
+  #endif
+  decNumberCopy(res, rhs);
+  res->bits&=~DECNEG;                  /* turn off sign */
+  return res;
+  } /* decNumberCopyAbs */
+
+/* ------------------------------------------------------------------ */
+/* decNumberCopyNegate -- quiet negate value operator                */
+/*                                                                   */
+/*   This sets C = negate(A)                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* No exception or error can occur; this is a quiet bitwise operation.*/
+/* See also decNumberMinus for a checking version of this.           */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberCopyNegate(decNumber *res, const decNumber *rhs) {
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
+  #endif
+  decNumberCopy(res, rhs);
+  res->bits^=DECNEG;                   /* invert the sign */
+  return res;
+  } /* decNumberCopyNegate */
+
+/* ------------------------------------------------------------------ */
+/* decNumberCopySign -- quiet copy and set sign operator             */
+/*                                                                   */
+/*   This sets C = A with the sign of B                                      */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* No exception or error can occur; this is a quiet bitwise operation.*/
+/* ------------------------------------------------------------------ */
+decNumber * decNumberCopySign(decNumber *res, const decNumber *lhs,
+                             const decNumber *rhs) {
+  uByte sign;                          /* rhs sign */
+  #if DECCHECK
+  if (decCheckOperands(res, DECUNUSED, rhs, DECUNCONT)) return res;
+  #endif
+  sign=rhs->bits & DECNEG;             /* save sign bit */
+  decNumberCopy(res, lhs);
+  res->bits&=~DECNEG;                  /* clear the sign */
+  res->bits|=sign;                     /* set from rhs */
+  return res;
+  } /* decNumberCopySign */
+
+/* ------------------------------------------------------------------ */
+/* decNumberGetBCD -- get the coefficient in BCD8                    */
+/*   dn is the source decNumber                                              */
+/*   bcd is the uInt array that will receive dn->digits BCD bytes,    */
+/*     most-significant at offset 0                                  */
+/*   returns bcd                                                     */
+/*                                                                   */
+/* 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.   */
+/* ------------------------------------------------------------------ */
+uByte * decNumberGetBCD(const decNumber *dn, uint8_t *bcd) {
+  uByte *ub=bcd+dn->digits-1;     /* -> lsd */
+  const Unit *up=dn->lsu;         /* Unit pointer, -> lsu */
+
+  #if DECDPUN==1                  /* trivial simple copy */
+    for (; ub>=bcd; ub--, up++) *ub=*up;
+  #else                                   /* chopping needed */
+    uInt u=*up;                           /* work */
+    uInt cut=DECDPUN;             /* downcounter through unit */
+    for (; ub>=bcd; ub--) {
+      *ub=(uByte)(u%10);          /* [*6554 trick inhibits, here] */
+      u=u/10;
+      cut--;
+      if (cut>0) continue;        /* more in this unit */
+      up++;
+      u=*up;
+      cut=DECDPUN;
+      }
+  #endif
+  return bcd;
+  } /* decNumberGetBCD */
+
+/* ------------------------------------------------------------------ */
+/* decNumberSetBCD -- set (replace) the coefficient from BCD8        */
+/*   dn is the target decNumber                                              */
+/*   bcd is the uInt array that will source n BCD bytes, most-       */
+/*     significant at offset 0                                       */
+/*   n is the number of digits in the source BCD array (bcd)         */
+/*   returns dn                                                              */
+/*                                                                   */
+/* 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   */
+/* and bcd[0] zero.                                                  */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberSetBCD(decNumber *dn, const uByte *bcd, uInt n) {
+  Unit *up=dn->lsu+D2U(dn->digits)-1;  /* -> msu [target pointer] */
+  const uByte *ub=bcd;                 /* -> source msd */
+
+  #if DECDPUN==1                       /* trivial simple copy */
+    for (; ub<bcd+n; ub++, up--) *up=*ub;
+  #else                                        /* some assembly needed */
+    /* calculate how many digits in msu, and hence first cut */
+    Int cut=MSUDIGITS(n);              /* [faster than remainder] */
+    for (;up>=dn->lsu; up--) {         /* each Unit from msu */
+      *up=0;                           /* will take <=DECDPUN digits */
+      for (; cut>0; ub++, cut--) *up=X10(*up)+*ub;
+      cut=DECDPUN;                     /* next Unit has all digits */
+      }
+  #endif
+  dn->digits=n;                                /* set digit count */
+  return dn;
+  } /* decNumberSetBCD */
+
+/* ------------------------------------------------------------------ */
+/* decNumberIsNormal -- test normality of a decNumber                */
+/*   dn is the decNumber to test                                     */
+/*   set is the context to use for Emin                                      */
+/*   returns 1 if |dn| is finite and >=Nmin, 0 otherwise             */
+/* ------------------------------------------------------------------ */
+Int decNumberIsNormal(const decNumber *dn, decContext *set) {
+  Int ae;                              /* adjusted exponent */
+  #if DECCHECK
+  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
+  #endif
+
+  if (decNumberIsSpecial(dn)) return 0; /* not finite */
+  if (decNumberIsZero(dn)) return 0;   /* not non-zero */
+
+  ae=dn->exponent+dn->digits-1;                /* adjusted exponent */
+  if (ae<set->emin) return 0;          /* is subnormal */
+  return 1;
+  } /* decNumberIsNormal */
 
 /* ------------------------------------------------------------------ */
-/* decNumberTrim -- remove insignificant zeros                        */
-/*                                                                    */
-/*   dn is the number to trim                                         */
-/*   returns dn                                                       */
-/*                                                                    */
-/* All fields are updated as required.  This is a utility operation,  */
-/* so special values are unchanged and no error is possible.          */
+/* decNumberIsSubnormal -- test subnormality of a decNumber          */
+/*   dn is the decNumber to test                                     */
+/*   set is the context to use for Emin                                      */
+/*   returns 1 if |dn| is finite, non-zero, and <Nmin, 0 otherwise    */
 /* ------------------------------------------------------------------ */
-decNumber *
-decNumberTrim (decNumber * dn)
-{
-  Int dropped;                 /* work */
-  return decTrim (dn, 0, &dropped);
-}
+Int decNumberIsSubnormal(const decNumber *dn, decContext *set) {
+  Int ae;                              /* adjusted exponent */
+  #if DECCHECK
+  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, set)) return 0;
+  #endif
+
+  if (decNumberIsSpecial(dn)) return 0; /* not finite */
+  if (decNumberIsZero(dn)) return 0;   /* not non-zero */
+
+  ae=dn->exponent+dn->digits-1;                /* adjusted exponent */
+  if (ae<set->emin) return 1;          /* is subnormal */
+  return 0;
+  } /* decNumberIsSubnormal */
+
+/* ------------------------------------------------------------------ */
+/* decNumberTrim -- remove insignificant zeros                       */
+/*                                                                   */
+/*   dn is the number to trim                                        */
+/*   returns dn                                                              */
+/*                                                                   */
+/* All fields are updated as required. This is a utility operation,  */
+/* so special values are unchanged and no error is possible.         */
+/* ------------------------------------------------------------------ */
+decNumber * decNumberTrim(decNumber *dn) {
+  Int  dropped;                           /* work */
+  decContext set;                 /* .. */
+  #if DECCHECK
+  if (decCheckOperands(DECUNRESU, DECUNUSED, dn, DECUNCONT)) return dn;
+  #endif
+  decContextDefault(&set, DEC_INIT_BASE);    /* clamp=0 */
+  return decTrim(dn, &set, 0, &dropped);
+  } /* decNumberTrim */
 
 /* ------------------------------------------------------------------ */
 /* 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;
-}
+  } /* decNumberVersion */
 
 /* ------------------------------------------------------------------ */
-/* decNumberZero -- set a number to 0                                 */
-/*                                                                    */
-/*   dn is the number to set, with space for one digit                */
-/*   returns dn                                                       */
-/*                                                                    */
-/* No error is possible.                                              */
+/* decNumberZero -- set a number to 0                                */
+/*                                                                   */
+/*   dn is the number to set, with space for one digit               */
+/*   returns dn                                                              */
+/*                                                                   */
+/* No error is possible.                                             */
 /* ------------------------------------------------------------------ */
 /* Memset is not used as it is much slower in some environments. */
-decNumber *
-decNumberZero (decNumber * dn)
-{
+decNumber * decNumberZero(decNumber *dn) {
 
-#if DECCHECK
-  if (decCheckOperands (dn, DECUNUSED, DECUNUSED, DECUNUSED))
-    return dn;
-#endif
+  #if DECCHECK
+  if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
+  #endif
 
-  dn->bits = 0;
-  dn->exponent = 0;
-  dn->digits = 1;
-  dn->lsu[0] = 0;
+  dn->bits=0;
+  dn->exponent=0;
+  dn->digits=1;
+  dn->lsu[0]=0;
   return dn;
-}
+  } /* decNumberZero */
 
 /* ================================================================== */
-/* Local routines                                                     */
+/* Local routines                                                    */
 /* ================================================================== */
 
 /* ------------------------------------------------------------------ */
-/* decToString -- lay out a number into a string                      */
-/*                                                                    */
-/*   dn     is the number to lay out                                  */
-/*   string is where to lay out the number                            */
-/*   eng    is 1 if Engineering, 0 if Scientific                      */
-/*                                                                    */
-/* str must be at least dn->digits+14 characters long                 */
-/* No error is possible.                                              */
-/*                                                                    */
+/* decToString -- lay out a number into a string                     */
+/*                                                                   */
+/*   dn            is the number to lay out                                  */
+/*   string is where to lay out the number                           */
+/*   eng    is 1 if Engineering, 0 if Scientific                     */
+/*                                                                   */
+/* string must be at least dn->digits+14 characters long             */
+/* No error is possible.                                             */
+/*                                                                   */
 /* Note that this routine can generate a -0 or 0.000.  These are      */
 /* 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 */
 /* invalid. */
-
-/* TODIGIT -- macro to remove the leading digit from the unsigned */
-/* integer u at column cut (counting from the right, LSD=0) and place */
-/* it as an ASCII character into the character pointed to by c.  Note */
-/* that cut must be <= 9, and the maximum value for u is 2,000,000,000 */
-/* (as is needed for negative exponents of subnormals).  The unsigned */
-/* integer pow is used as a temporary variable. */
-#define TODIGIT(u, cut, c) {            \
-  *(c)='0';                             \
-  pow=powers[cut]*2;                    \
-  if ((u)>pow) {                        \
-    pow*=4;                             \
-    if ((u)>=pow) {(u)-=pow; *(c)+=8;}  \
-    pow/=2;                             \
-    if ((u)>=pow) {(u)-=pow; *(c)+=4;}  \
-    pow/=2;                             \
-    }                                   \
-  if ((u)>=pow) {(u)-=pow; *(c)+=2;}    \
-  pow/=2;                               \
-  if ((u)>=pow) {(u)-=pow; *(c)+=1;}    \
-  }
-
-static void
-decToString (const decNumber * dn, char *string, Flag eng)
-{
-  Int exp = dn->exponent;      /* local copy */
-  Int e;                       /* E-part value */
-  Int pre;                     /* digits before the '.' */
-  Int cut;                     /* for counting digits in a Unit */
-  char *c = string;            /* work [output pointer] */
-  const Unit *up = dn->lsu + D2U (dn->digits) - 1;     /* -> msu [input pointer] */
-  uInt u, pow;                 /* work */
-
-#if DECCHECK
-  if (decCheckOperands (DECUNUSED, dn, DECUNUSED, DECUNUSED))
-    {
-      strcpy (string, "?");
-      return;
+static void decToString(const decNumber *dn, char *string, Flag eng) {
+  Int exp=dn->exponent;              /* local copy */
+  Int e;                     /* E-part value */
+  Int pre;                   /* digits before the '.' */
+  Int cut;                   /* for counting digits in a Unit */
+  char *c=string;            /* work [output pointer] */
+  const Unit *up=dn->lsu+D2U(dn->digits)-1; /* -> msu [input pointer] */
+  uInt u, pow;               /* work */
+
+  #if DECCHECK
+  if (decCheckOperands(DECUNRESU, dn, DECUNUSED, DECUNCONT)) {
+    strcpy(string, "?");
+    return;}
+  #endif
+
+  if (decNumberIsNegative(dn)) {   /* Negatives get a minus */
+    *c='-';
+    c++;
     }
-#endif
-
-  if (decNumberIsNegative (dn))
-    {                          /* Negatives get a minus (except */
-      *c = '-';                        /* NaNs, which remove the '-' below) */
+  if (dn->bits&DECSPECIAL) {      /* Is a special value */
+    if (decNumberIsInfinite(dn)) {
+      strcpy(c,          "Inf");
+      strcpy(c+3, "inity");
+      return;}
+    /* a NaN */
+    if (dn->bits&DECSNAN) {       /* signalling NaN */
+      *c='s';
       c++;
-    }
-  if (dn->bits & DECSPECIAL)
-    {                          /* Is a special value */
-      if (decNumberIsInfinite (dn))
-       {
-         strcpy (c, "Infinity");
-         return;
-       }
-      /* a NaN */
-      if (dn->bits & DECSNAN)
-       {                       /* signalling NaN */
-         *c = 's';
-         c++;
-       }
-      strcpy (c, "NaN");
-      c += 3;                  /* step past */
-      /* if not a clean non-zero coefficient, that's all we have in a */
-      /* NaN string */
-      if (exp != 0 || (*dn->lsu == 0 && dn->digits == 1))
-       return;
-      /* [drop through to add integer] */
+      }
+    strcpy(c, "NaN");
+    c+=3;                         /* step past */
+    /* if not a clean non-zero coefficient, that's all there is in a */
+    /* NaN string */
+    if (exp!=0 || (*dn->lsu==0 && dn->digits==1)) return;
+    /* [drop through to add integer] */
     }
 
   /* calculate how many digits in msu, and hence first cut */
-  cut = dn->digits % DECDPUN;
-  if (cut == 0)
-    cut = DECDPUN;             /* msu is full */
-  cut--;                       /* power of ten for digit */
-
-  if (exp == 0)
-    {                          /* simple integer [common fastpath, */
-      /*   used for NaNs, too] */
-      for (; up >= dn->lsu; up--)
-       {                       /* each Unit from msu */
-         u = *up;              /* contains DECDPUN digits to lay out */
-         for (; cut >= 0; c++, cut--)
-           TODIGIT (u, cut, c);
-         cut = DECDPUN - 1;    /* next Unit has all digits */
-       }
-      *c = '\0';               /* terminate the string */
-      return;
-    }
+  cut=MSUDIGITS(dn->digits);      /* [faster than remainder] */
+  cut--;                          /* power of ten for digit */
+
+  if (exp==0) {                           /* simple integer [common fastpath] */
+    for (;up>=dn->lsu; up--) {    /* each Unit from msu */
+      u=*up;                      /* contains DECDPUN digits to lay out */
+      for (; cut>=0; c++, cut--) TODIGIT(u, cut, c, pow);
+      cut=DECDPUN-1;              /* next Unit has all digits */
+      }
+    *c='\0';                      /* terminate the string */
+    return;}
 
   /* non-0 exponent -- assume plain form */
-  pre = dn->digits + exp;      /* digits before '.' */
-  e = 0;                       /* no E */
-  if ((exp > 0) || (pre < -5))
-    {                          /* need exponential form */
-      e = exp + dn->digits - 1;        /* calculate E value */
-      pre = 1;                 /* assume one digit before '.' */
-      if (eng && (e != 0))
-       {                       /* may need to adjust */
-         Int adj;              /* adjustment */
-         /* The C remainder operator is undefined for negative numbers, so */
-         /* we must use positive remainder calculation here */
-         if (e < 0)
-           {
-             adj = (-e) % 3;
-             if (adj != 0)
-               adj = 3 - adj;
-           }
-         else
-           {                   /* e>0 */
-             adj = e % 3;
-           }
-         e = e - adj;
-         /* if we are dealing with zero we will use exponent which is a */
-         /* multiple of three, as expected, but there will only be the */
-         /* one zero before the E, still.  Otherwise note the padding. */
-         if (!ISZERO (dn))
-           pre += adj;
-         else
-           {                   /* is zero */
-             if (adj != 0)
-               {               /* 0.00Esnn needed */
-                 e = e + 3;
-                 pre = -(2 - adj);
-               }
-           }                   /* zero */
-       }                       /* eng */
-    }
+  pre=dn->digits+exp;             /* digits before '.' */
+  e=0;                            /* no E */
+  if ((exp>0) || (pre<-5)) {      /* need exponential form */
+    e=exp+dn->digits-1;                   /* calculate E value */
+    pre=1;                        /* assume one digit before '.' */
+    if (eng && (e!=0)) {          /* engineering: may need to adjust */
+      Int adj;                    /* adjustment */
+      /* The C remainder operator is undefined for negative numbers, so */
+      /* a positive remainder calculation must be used here */
+      if (e<0) {
+       adj=(-e)%3;
+       if (adj!=0) adj=3-adj;
+       }
+       else { /* e>0 */
+       adj=e%3;
+       }
+      e=e-adj;
+      /* if dealing with zero still produce an exponent which is a */
+      /* multiple of three, as expected, but there will only be the */
+      /* one zero before the E, still. Otherwise note the padding. */
+      if (!ISZERO(dn)) pre+=adj;
+       else {  /* is zero */
+       if (adj!=0) {              /* 0.00Esnn needed */
+         e=e+3;
+         pre=-(2-adj);
+         }
+       } /* zero */
+      } /* eng */
+    } /* need exponent */
 
   /* lay out the digits of the coefficient, adding 0s and . as needed */
-  u = *up;
-  if (pre > 0)
-    {                          /* xxx.xxx or xx00 (engineering) form */
-      for (; pre > 0; pre--, c++, cut--)
-       {
-         if (cut < 0)
-           {                   /* need new Unit */
-             if (up == dn->lsu)
-               break;          /* out of input digits (pre>digits) */
-             up--;
-             cut = DECDPUN - 1;
-             u = *up;
-           }
-         TODIGIT (u, cut, c);
+  u=*up;
+  if (pre>0) {                    /* xxx.xxx or xx00 (engineering) form */
+    Int n=pre;
+    for (; pre>0; pre--, c++, cut--) {
+      if (cut<0) {                /* need new Unit */
+       if (up==dn->lsu) break;    /* out of input digits (pre>digits) */
+       up--;
+       cut=DECDPUN-1;
+       u=*up;
        }
-      if (up > dn->lsu || (up == dn->lsu && cut >= 0))
-       {                       /* more to come, after '.' */
-         *c = '.';
-         c++;
-         for (;; c++, cut--)
-           {
-             if (cut < 0)
-               {               /* need new Unit */
-                 if (up == dn->lsu)
-                   break;      /* out of input digits */
-                 up--;
-                 cut = DECDPUN - 1;
-                 u = *up;
-               }
-             TODIGIT (u, cut, c);
-           }
+      TODIGIT(u, cut, c, pow);
+      }
+    if (n<dn->digits) {                   /* more to come, after '.' */
+      *c='.'; c++;
+      for (;; c++, cut--) {
+       if (cut<0) {               /* need new Unit */
+         if (up==dn->lsu) break;  /* out of input digits */
+         up--;
+         cut=DECDPUN-1;
+         u=*up;
+         }
+       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 */
-      *c = '0';
-      c++;
-      *c = '.';
-      c++;
-      for (; pre < 0; pre++, c++)
-       *c = '0';               /* add any 0's after '.' */
-      for (;; c++, cut--)
-       {
-         if (cut < 0)
-           {                   /* need new Unit */
-             if (up == dn->lsu)
-               break;          /* out of input digits */
-             up--;
-             cut = DECDPUN - 1;
-             u = *up;
-           }
-         TODIGIT (u, cut, c);
+   else {                         /* 0.xxx or 0.000xxx form */
+    *c='0'; c++;
+    *c='.'; c++;
+    for (; pre<0; pre++, c++) *c='0';  /* add any 0's after '.' */
+    for (; ; c++, cut--) {
+      if (cut<0) {                /* need new Unit */
+       if (up==dn->lsu) break;    /* out of input digits */
+       up--;
+       cut=DECDPUN-1;
+       u=*up;
        }
+      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
-     could range down to -1999999998 for subnormal numbers */
-  if (e != 0)
-    {
-      Flag had = 0;            /* 1=had non-zero */
-      *c = 'E';
-      c++;
-      *c = '+';
-      c++;                     /* assume positive */
-      u = e;                   /* .. */
-      if (e < 0)
-       {
-         *(c - 1) = '-';       /* oops, need - */
-         u = -e;               /* uInt, please */
-       }
-      /* layout the exponent (_itoa is not ANSI C) */
-      for (cut = 9; cut >= 0; cut--)
-       {
-         TODIGIT (u, cut, c);
-         if (*c == '0' && !had)
-           continue;           /* skip leading zeros */
-         had = 1;              /* had non-0 */
-         c++;                  /* step for next */
-       }                       /* cut */
+     could range down to -1999999998 for anormal numbers */
+  if (e!=0) {
+    Flag had=0;                      /* 1=had non-zero */
+    *c='E'; c++;
+    *c='+'; c++;             /* assume positive */
+    u=e;                     /* .. */
+    if (e<0) {
+      *(c-1)='-';            /* oops, need - */
+      u=-e;                  /* uInt, please */
+      }
+    /* lay out the exponent [_itoa or equivalent is not ANSI C] */
+    for (cut=9; cut>=0; cut--) {
+      TODIGIT(u, cut, c, pow);
+      if (*c=='0' && !had) continue;   /* skip leading zeros */
+      had=1;                           /* had non-0 */
+      c++;                             /* step for next */
+      } /* cut */
     }
-  *c = '\0';                   /* terminate the string (all paths) */
+  *c='\0';         /* terminate the string (all paths) */
   return;
-}
-
-/* ------------------------------------------------------------------ */
-/* decAddOp -- add/subtract operation                                 */
-/*                                                                    */
-/*   This computes C = A + B                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*   negate is DECNEG if rhs should be negated, or 0 otherwise        */
-/*   status accumulates status for the caller                         */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/* ------------------------------------------------------------------ */
-/* If possible, we calculate the coefficient directly into C.         */
-/* However, if:                                                       */
-/*   -- we need a digits+1 calculation because numbers are unaligned  */
-/*      and span more than set->digits digits                         */
-/*   -- a carry to digits+1 digits looks possible                     */
+  } /* decToString */
+
+/* ------------------------------------------------------------------ */
+/* decAddOp -- add/subtract operation                                */
+/*                                                                   */
+/*   This computes C = A + B                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X+X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*   negate is DECNEG if rhs should be negated, or 0 otherwise       */
+/*   status accumulates status for the caller                        */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/* Inexact in status must be 0 for correct Exact zero sign in result  */
+/* ------------------------------------------------------------------ */
+/* If possible, the coefficient is calculated directly into C.       */
+/* However, if:                                                              */
+/*   -- a digits+1 calculation is needed because the numbers are      */
+/*     unaligned and span more than set->digits digits               */
+/*   -- a carry to digits+1 digits looks possible                    */
 /*   -- C is the same as A or B, and the result would destructively   */
-/*      overlap the A or B coefficient                                */
-/* then we must calculate into a temporary buffer.  In this latter    */
-/* case we use the local (stack) buffer if possible, and only if too  */
-/* long for that do we resort to malloc.                              */
-/*                                                                    */
-/* Misalignment is handled as follows:                                */
+/*     overlap the A or B coefficient                                */
+/* then the result must be calculated into a temporary buffer. In    */
+/* this case a local (stack) buffer is used if possible, and only if  */
+/* too long for that does malloc become the final resort.            */
+/*                                                                   */
+/* Misalignment is handled as follows:                               */
 /*   Apad: (AExp>BExp) Swap operands and proceed as for BExp>AExp.    */
 /*   BPad: Apply the padding by a combination of shifting (whole      */
-/*         units) and multiplication (part units).                    */
-/*                                                                    */
-/* Addition, especially x=x+1, is speed-critical, so we take pains    */
-/* to make returning as fast as possible, by flagging any allocation. */
-/* ------------------------------------------------------------------ */
-static decNumber *
-decAddOp (decNumber * res, const decNumber * lhs,
-         const decNumber * rhs, decContext * set, uByte negate, uInt * status)
-{
-  decNumber *alloclhs = NULL;  /* non-NULL if rounded lhs allocated */
-  decNumber *allocrhs = NULL;  /* .., rhs */
-  Int rhsshift;                        /* working shift (in Units) */
-  Int maxdigits;               /* longest logical length */
-  Int mult;                    /* multiplier */
-  Int residue;                 /* rounding accumulator */
-  uByte bits;                  /* result bits */
-  Flag diffsign;               /* non-0 if arguments have different sign */
-  Unit *acc;                   /* accumulator for result */
-  Unit accbuff[D2U (DECBUFFER + 1)];   /* local buffer [+1 is for possible */
-  /* final carry digit or DECBUFFER=0] */
-  Unit *allocacc = NULL;       /* -> allocated acc buffer, iff allocated */
-  Flag alloced = 0;            /* set non-0 if any allocations */
-  Int reqdigits = set->digits; /* local copy; requested DIGITS */
-  uByte merged;                        /* merged flags */
-  Int padding;                 /* work */
-
-#if DECCHECK
-  if (decCheckOperands (res, lhs, rhs, set))
-    return res;
-#endif
+/*        units) and multiplication (part units).                    */
+/*                                                                   */
+/* Addition, especially x=x+1, is speed-critical.                    */
+/* The static buffer is larger than might be expected to allow for    */
+/* calls from higher-level funtions (notable exp).                   */
+/* ------------------------------------------------------------------ */
+static decNumber * decAddOp(decNumber *res, const decNumber *lhs,
+                           const decNumber *rhs, decContext *set,
+                           uByte negate, uInt *status) {
+  #if DECSUBSET
+  decNumber *alloclhs=NULL;       /* non-NULL if rounded lhs allocated */
+  decNumber *allocrhs=NULL;       /* .., rhs */
+  #endif
+  Int  rhsshift;                  /* working shift (in Units) */
+  Int  maxdigits;                 /* longest logical length */
+  Int  mult;                      /* multiplier */
+  Int  residue;                   /* rounding accumulator */
+  uByte bits;                     /* result bits */
+  Flag diffsign;                  /* non-0 if arguments have different sign */
+  Unit *acc;                      /* accumulator for result */
+  Unit accbuff[SD2U(DECBUFFER*2+20)]; /* local buffer [*2+20 reduces many */
+                                  /* allocations when called from */
+                                  /* other operations, notable exp] */
+  Unit *allocacc=NULL;            /* -> allocated acc buffer, iff allocated */
+  Int  reqdigits=set->digits;     /* local copy; requested DIGITS */
+  Int  padding;                   /* work */
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  do {                            /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operands and set lostDigits status, as needed */
+      if (lhs->digits>reqdigits) {
+       alloclhs=decRoundOperand(lhs, set, status);
+       if (alloclhs==NULL) break;
+       lhs=alloclhs;
+       }
+      if (rhs->digits>reqdigits) {
+       allocrhs=decRoundOperand(rhs, set, status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
+       }
+      }
+    #endif
+    /* [following code does not require input rounding] */
+
+    /* note whether signs differ [used all paths] */
+    diffsign=(Flag)((lhs->bits^rhs->bits^negate)&DECNEG);
+
+    /* handle infinities and NaNs */
+    if (SPECIALARGS) {                 /* a special bit set */
+      if (SPECIALARGS & (DECSNAN | DECNAN))  /* a NaN */
+       decNaNs(res, lhs, rhs, set, status);
+       else { /* one or two infinities */
+       if (decNumberIsInfinite(lhs)) { /* LHS is infinity */
+         /* two infinities with different signs is invalid */
+         if (decNumberIsInfinite(rhs) && diffsign) {
+           *status|=DEC_Invalid_operation;
+           break;
+           }
+         bits=lhs->bits & DECNEG;      /* get sign from LHS */
+         }
+        else bits=(rhs->bits^negate) & DECNEG;/* RHS must be Infinity */
+       bits|=DECINF;
+       decNumberZero(res);
+       res->bits=bits;                 /* set +/- infinity */
+       } /* an infinity */
+      break;
+      }
 
-  do
-    {                          /* protect allocated storage */
-#if DECSUBSET
-      if (!set->extended)
-       {
-         /* reduce operands and set lostDigits status, as needed */
-         if (lhs->digits > reqdigits)
-           {
-             alloclhs = decRoundOperand (lhs, set, status);
-             if (alloclhs == NULL)
-               break;
-             lhs = alloclhs;
-             alloced = 1;
+    /* Quick exit for add 0s; return the non-0, modified as need be */
+    if (ISZERO(lhs)) {
+      Int adjust;                      /* work */
+      Int lexp=lhs->exponent;          /* save in case LHS==RES */
+      bits=lhs->bits;                  /* .. */
+      residue=0;                       /* clear accumulator */
+      decCopyFit(res, rhs, set, &residue, status); /* copy (as needed) */
+      res->bits^=negate;               /* flip if rhs was negated */
+      #if DECSUBSET
+      if (set->extended) {             /* exponents on zeros count */
+      #endif
+       /* exponent will be the lower of the two */
+       adjust=lexp-res->exponent;      /* adjustment needed [if -ve] */
+       if (ISZERO(res)) {              /* both 0: special IEEE 854 rules */
+         if (adjust<0) res->exponent=lexp;  /* set exponent */
+         /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */
+         if (diffsign) {
+           if (set->round!=DEC_ROUND_FLOOR) res->bits=0;
+            else res->bits=DECNEG;     /* preserve 0 sign */
            }
-         if (rhs->digits > reqdigits)
-           {
-             allocrhs = decRoundOperand (rhs, set, status);
-             if (allocrhs == NULL)
-               break;
-             rhs = allocrhs;
-             alloced = 1;
+         }
+        else { /* non-0 res */
+         if (adjust<0) {     /* 0-padding needed */
+           if ((res->digits-adjust)>set->digits) {
+             adjust=res->digits-set->digits;     /* to fit exactly */
+             *status|=DEC_Rounded;               /* [but exact] */
+             }
+           res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
+           res->exponent+=adjust;                /* set the exponent. */
            }
-       }
-#endif
-      /* [following code does not require input rounding] */
-
-      /* note whether signs differ */
-      diffsign = (Flag) ((lhs->bits ^ rhs->bits ^ negate) & DECNEG);
-
-      /* handle infinities and NaNs */
-      merged = (lhs->bits | rhs->bits) & DECSPECIAL;
-      if (merged)
-       {                       /* a special bit set */
-         if (merged & (DECSNAN | DECNAN))      /* a NaN */
-           decNaNs (res, lhs, rhs, status);
-         else
-           {                   /* one or two infinities */
-             if (decNumberIsInfinite (lhs))
-               {               /* LHS is infinity */
-                 /* two infinities with different signs is invalid */
-                 if (decNumberIsInfinite (rhs) && diffsign)
-                   {
-                     *status |= DEC_Invalid_operation;
-                     break;
-                   }
-                 bits = lhs->bits & DECNEG;    /* get sign from LHS */
-               }
-             else
-               bits = (rhs->bits ^ negate) & DECNEG;   /* RHS must be Infinity */
-             bits |= DECINF;
-             decNumberZero (res);
-             res->bits = bits; /* set +/- infinity */
-           }                   /* an infinity */
+         } /* non-0 res */
+      #if DECSUBSET
+       } /* extended */
+      #endif
+      decFinish(res, set, &residue, status);     /* clean and finalize */
+      break;}
+
+    if (ISZERO(rhs)) {                 /* [lhs is non-zero] */
+      Int adjust;                      /* work */
+      Int rexp=rhs->exponent;          /* save in case RHS==RES */
+      bits=rhs->bits;                  /* be clean */
+      residue=0;                       /* clear accumulator */
+      decCopyFit(res, lhs, set, &residue, status); /* copy (as needed) */
+      #if DECSUBSET
+      if (set->extended) {             /* exponents on zeros count */
+      #endif
+       /* exponent will be the lower of the two */
+       /* [0-0 case handled above] */
+       adjust=rexp-res->exponent;      /* adjustment needed [if -ve] */
+       if (adjust<0) {     /* 0-padding needed */
+         if ((res->digits-adjust)>set->digits) {
+           adjust=res->digits-set->digits;     /* to fit exactly */
+           *status|=DEC_Rounded;               /* [but exact] */
+           }
+         res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
+         res->exponent+=adjust;                /* set the exponent. */
+         }
+      #if DECSUBSET
+       } /* extended */
+      #endif
+      decFinish(res, set, &residue, status);     /* clean and finalize */
+      break;}
+
+    /* [NB: both fastpath and mainpath code below assume these cases */
+    /* (notably 0-0) have already been handled] */
+
+    /* calculate the padding needed to align the operands */
+    padding=rhs->exponent-lhs->exponent;
+
+    /* Fastpath cases where the numbers are aligned and normal, the RHS */
+    /* is all in one unit, no operand rounding is needed, and no carry, */
+    /* lengthening, or borrow is needed */
+    if (padding==0
+       && rhs->digits<=DECDPUN
+       && rhs->exponent>=set->emin     /* [some normals drop through] */
+       && rhs->exponent<=set->emax-set->digits+1 /* [could clamp] */
+       && rhs->digits<=reqdigits
+       && lhs->digits<=reqdigits) {
+      Int partial=*lhs->lsu;
+      if (!diffsign) {                 /* adding */
+       partial+=*rhs->lsu;
+       if ((partial<=DECDPUNMAX)       /* result fits in unit */
+        && (lhs->digits>=DECDPUN ||    /* .. and no digits-count change */
+            partial<(Int)powers[lhs->digits])) { /* .. */
+         if (res!=lhs) decNumberCopy(res, lhs);  /* not in place */
+         *res->lsu=(Unit)partial;      /* [copy could have overwritten RHS] */
          break;
+         }
+       /* else drop out for careful add */
        }
-
-      /* Quick exit for add 0s; return the non-0, modified as need be */
-      if (ISZERO (lhs))
-       {
-         Int adjust;           /* work */
-         Int lexp = lhs->exponent;     /* save in case LHS==RES */
-         bits = lhs->bits;     /* .. */
-         residue = 0;          /* clear accumulator */
-         decCopyFit (res, rhs, set, &residue, status); /* copy (as needed) */
-         res->bits ^= negate;  /* flip if rhs was negated */
-#if DECSUBSET
-         if (set->extended)
-           {                   /* exponents on zeros count */
-#endif
-             /* exponent will be the lower of the two */
-             adjust = lexp - res->exponent;    /* adjustment needed [if -ve] */
-             if (ISZERO (res))
-               {               /* both 0: special IEEE 854 rules */
-                 if (adjust < 0)
-                   res->exponent = lexp;       /* set exponent */
-                 /* 0-0 gives +0 unless rounding to -infinity, and -0-0 gives -0 */
-                 if (diffsign)
-                   {
-                     if (set->round != DEC_ROUND_FLOOR)
-                       res->bits = 0;
-                     else
-                       res->bits = DECNEG;     /* preserve 0 sign */
-                   }
-               }
-             else
-               {               /* non-0 res */
-                 if (adjust < 0)
-                   {           /* 0-padding needed */
-                     if ((res->digits - adjust) > set->digits)
-                       {
-                         adjust = res->digits - set->digits;   /* to fit exactly */
-                         *status |= DEC_Rounded;       /* [but exact] */
-                       }
-                     res->digits =
-                       decShiftToMost (res->lsu, res->digits, -adjust);
-                     res->exponent += adjust;  /* set the exponent. */
-                   }
-               }               /* non-0 res */
-#if DECSUBSET
-           }                   /* extended */
-#endif
-         decFinish (res, set, &residue, status);       /* clean and finalize */
+       else {                          /* signs differ */
+       partial-=*rhs->lsu;
+       if (partial>0) { /* no borrow needed, and non-0 result */
+         if (res!=lhs) decNumberCopy(res, lhs);  /* not in place */
+         *res->lsu=(Unit)partial;
+         /* this could have reduced digits [but result>0] */
+         res->digits=decGetDigits(res->lsu, D2U(res->digits));
          break;
+         }
+       /* else drop out for careful subtract */
        }
+      }
 
-      if (ISZERO (rhs))
-       {                       /* [lhs is non-zero] */
-         Int adjust;           /* work */
-         Int rexp = rhs->exponent;     /* save in case RHS==RES */
-         bits = rhs->bits;     /* be clean */
-         residue = 0;          /* clear accumulator */
-         decCopyFit (res, lhs, set, &residue, status); /* copy (as needed) */
-#if DECSUBSET
-         if (set->extended)
-           {                   /* exponents on zeros count */
-#endif
-             /* exponent will be the lower of the two */
-             /* [0-0 case handled above] */
-             adjust = rexp - res->exponent;    /* adjustment needed [if -ve] */
-             if (adjust < 0)
-               {               /* 0-padding needed */
-                 if ((res->digits - adjust) > set->digits)
-                   {
-                     adjust = res->digits - set->digits;       /* to fit exactly */
-                     *status |= DEC_Rounded;   /* [but exact] */
-                   }
-                 res->digits =
-                   decShiftToMost (res->lsu, res->digits, -adjust);
-                 res->exponent += adjust;      /* set the exponent. */
-               }
-#if DECSUBSET
-           }                   /* extended */
-#endif
-         decFinish (res, set, &residue, status);       /* clean and finalize */
-         break;
+    /* Now align (pad) the lhs or rhs so they can be added or */
+    /* subtracted, as necessary.  If one number is much larger than */
+    /* 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 */
+    /* other) padding with up to DIGITS-1 trailing zeros may be */
+    /* needed; then apply rounding (as exotic rounding modes may be */
+    /* affected by the residue). */
+    rhsshift=0;                      /* rhs shift to left (padding) in Units */
+    bits=lhs->bits;          /* assume sign is that of LHS */
+    mult=1;                  /* likely multiplier */
+
+    /* [if padding==0 the operands are aligned; no padding is needed] */
+    if (padding!=0) {
+      /* some padding needed; always pad the RHS, as any required */
+      /* padding can then be effected by a simple combination of */
+      /* shifts and a multiply */
+      Flag swapped=0;
+      if (padding<0) {                 /* LHS needs the padding */
+       const decNumber *t;
+       padding=-padding;               /* will be +ve */
+       bits=(uByte)(rhs->bits^negate); /* assumed sign is now that of RHS */
+       t=lhs; lhs=rhs; rhs=t;
+       swapped=1;
        }
-      /* [both fastpath and mainpath code below assume these cases */
-      /* (notably 0-0) have already been handled] */
-
-      /* calculate the padding needed to align the operands */
-      padding = rhs->exponent - lhs->exponent;
-
-      /* Fastpath cases where the numbers are aligned and normal, the RHS */
-      /* is all in one unit, no operand rounding is needed, and no carry, */
-      /* lengthening, or borrow is needed */
-      if (rhs->digits <= DECDPUN && padding == 0 && rhs->exponent >= set->emin /* [some normals drop through] */
-         && rhs->digits <= reqdigits && lhs->digits <= reqdigits)
-       {
-         Int partial = *lhs->lsu;
-         if (!diffsign)
-           {                   /* adding */
-             Int maxv = DECDPUNMAX;    /* highest no-overflow */
-             if (lhs->digits < DECDPUN)
-               maxv = powers[lhs->digits] - 1;
-             partial += *rhs->lsu;
-             if (partial <= maxv)
-               {               /* no carry */
-                 if (res != lhs)
-                   decNumberCopy (res, lhs);   /* not in place */
-                 *res->lsu = (Unit) partial;   /* [copy could have overwritten RHS] */
-                 break;
-               }
-             /* else drop out for careful add */
-           }
-         else
-           {                   /* signs differ */
-             partial -= *rhs->lsu;
-             if (partial > 0)
-               {               /* no borrow needed, and non-0 result */
-                 if (res != lhs)
-                   decNumberCopy (res, lhs);   /* not in place */
-                 *res->lsu = (Unit) partial;
-                 /* this could have reduced digits [but result>0] */
-                 res->digits = decGetDigits (res->lsu, D2U (res->digits));
-                 break;
-               }
-             /* else drop out for careful subtract */
-           }
-       }
-
-      /* Now align (pad) the lhs or rhs so we can add or subtract them, as
-         necessary.  If one number is much larger than the other (that is,
-         if in plain form there is a least one digit between the lowest
-         digit or one and the highest of the other) we need to pad with up
-         to DIGITS-1 trailing zeros, and then apply rounding (as exotic
-         rounding modes may be affected by the residue).
-       */
-      rhsshift = 0;            /* rhs shift to left (padding) in Units */
-      bits = lhs->bits;                /* assume sign is that of LHS */
-      mult = 1;                        /* likely multiplier */
-
-      /* if padding==0 the operands are aligned; no padding needed */
-      if (padding != 0)
-       {
-         /* some padding needed */
-         /* We always pad the RHS, as we can then effect any required */
-         /* padding by a combination of shifts and a multiply */
-         Flag swapped = 0;
-         if (padding < 0)
-           {                   /* LHS needs the padding */
-             const decNumber *t;
-             padding = -padding;       /* will be +ve */
-             bits = (uByte) (rhs->bits ^ negate);      /* assumed sign is now that of RHS */
-             t = lhs;
-             lhs = rhs;
-             rhs = t;
-             swapped = 1;
-           }
 
-         /* If, after pad, rhs would be longer than lhs by digits+1 or */
-         /* more then lhs cannot affect the answer, except as a residue, */
-         /* so we only need to pad up to a length of DIGITS+1. */
-         if (rhs->digits + padding > lhs->digits + reqdigits + 1)
-           {
-             /* The RHS is sufficient */
-             /* for residue we use the relative sign indication... */
-             Int shift = reqdigits - rhs->digits;      /* left shift needed */
-             residue = 1;      /* residue for rounding */
-             if (diffsign)
-               residue = -residue;     /* signs differ */
-             /* copy, shortening if necessary */
-             decCopyFit (res, rhs, set, &residue, status);
-             /* if it was already shorter, then need to pad with zeros */
-             if (shift > 0)
-               {
-                 res->digits = decShiftToMost (res->lsu, res->digits, shift);
-                 res->exponent -= shift;       /* adjust the exponent. */
-               }
-             /* flip the result sign if unswapped and rhs was negated */
-             if (!swapped)
-               res->bits ^= negate;
-             decFinish (res, set, &residue, status);   /* done */
-             break;
-           }
-
-         /* LHS digits may affect result */
-         rhsshift = D2U (padding + 1) - 1;     /* this much by Unit shift .. */
-         mult = powers[padding - (rhsshift * DECDPUN)];        /* .. this by multiplication */
-       }                       /* padding needed */
-
-      if (diffsign)
-       mult = -mult;           /* signs differ */
-
-      /* determine the longer operand */
-      maxdigits = rhs->digits + padding;       /* virtual length of RHS */
-      if (lhs->digits > maxdigits)
-       maxdigits = lhs->digits;
-
-      /* Decide on the result buffer to use; if possible place directly */
-      /* into result. */
-      acc = res->lsu;          /* assume build direct */
-      /* If destructive overlap, or the number is too long, or a carry or */
-      /* borrow to DIGITS+1 might be possible we must use a buffer. */
-      /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */
-      if ((maxdigits >= reqdigits)     /* is, or could be, too large */
-         || (res == rhs && rhsshift > 0))
-       {                       /* destructive overlap */
-         /* buffer needed; choose it */
-         /* we'll need units for maxdigits digits, +1 Unit for carry or borrow */
-         Int need = D2U (maxdigits) + 1;
-         acc = accbuff;        /* assume use local buffer */
-         if (need * sizeof (Unit) > sizeof (accbuff))
-           {
-             allocacc = (Unit *) malloc (need * sizeof (Unit));
-             if (allocacc == NULL)
-               {               /* hopeless -- abandon */
-                 *status |= DEC_Insufficient_storage;
-                 break;
-               }
-             acc = allocacc;
-             alloced = 1;
-           }
+      /* If, after pad, rhs would be longer than lhs by digits+1 or */
+      /* more then lhs cannot affect the answer, except as a residue, */
+      /* so only need to pad up to a length of DIGITS+1. */
+      if (rhs->digits+padding > lhs->digits+reqdigits+1) {
+       /* The RHS is sufficient */
+       /* for residue use the relative sign indication... */
+       Int shift=reqdigits-rhs->digits;     /* left shift needed */
+       residue=1;                           /* residue for rounding */
+       if (diffsign) residue=-residue;      /* signs differ */
+       /* copy, shortening if necessary */
+       decCopyFit(res, rhs, set, &residue, status);
+       /* if it was already shorter, then need to pad with zeros */
+       if (shift>0) {
+         res->digits=decShiftToMost(res->lsu, res->digits, shift);
+         res->exponent-=shift;              /* adjust the exponent. */
+         }
+       /* flip the result sign if unswapped and rhs was negated */
+       if (!swapped) res->bits^=negate;
+       decFinish(res, set, &residue, status);    /* done */
+       break;}
+
+      /* LHS digits may affect result */
+      rhsshift=D2U(padding+1)-1;       /* this much by Unit shift .. */
+      mult=powers[padding-(rhsshift*DECDPUN)]; /* .. this by multiplication */
+      } /* padding needed */
+
+    if (diffsign) mult=-mult;          /* signs differ */
+
+    /* determine the longer operand */
+    maxdigits=rhs->digits+padding;     /* virtual length of RHS */
+    if (lhs->digits>maxdigits) maxdigits=lhs->digits;
+
+    /* Decide on the result buffer to use; if possible place directly */
+    /* into result. */
+    acc=res->lsu;                      /* assume add direct to result */
+    /* 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. */
+    /* [Might be worth more sophisticated tests when maxdigits==reqdigits] */
+    if ((maxdigits>=reqdigits)         /* is, or could be, too large */
+     || (res==rhs && rhsshift>0)) {    /* destructive overlap */
+      /* buffer needed, choose it; units for maxdigits digits will be */
+      /* needed, +1 Unit for carry or borrow */
+      Int need=D2U(maxdigits)+1;
+      acc=accbuff;                     /* assume use local buffer */
+      if (need*sizeof(Unit)>sizeof(accbuff)) {
+       /* printf("malloc add %ld %ld\n", need, sizeof(accbuff)); */
+       allocacc=(Unit *)malloc(need*sizeof(Unit));
+       if (allocacc==NULL) {           /* hopeless -- abandon */
+         *status|=DEC_Insufficient_storage;
+         break;}
+       acc=allocacc;
        }
+      }
 
-      res->bits = (uByte) (bits & DECNEG);     /* it's now safe to overwrite.. */
-      res->exponent = lhs->exponent;   /* .. operands (even if aliased) */
-
-#if DECTRACE
-      decDumpAr ('A', lhs->lsu, D2U (lhs->digits));
-      decDumpAr ('B', rhs->lsu, D2U (rhs->digits));
-      printf ("  :h: %d %d\n", rhsshift, mult);
-#endif
-
-      /* add [A+B*m] or subtract [A+B*(-m)] */
-      res->digits = decUnitAddSub (lhs->lsu, D2U (lhs->digits), rhs->lsu, D2U (rhs->digits), rhsshift, acc, mult) * DECDPUN;   /* [units -> digits] */
-      if (res->digits < 0)
-       {                       /* we borrowed */
-         res->digits = -res->digits;
-         res->bits ^= DECNEG;  /* flip the sign */
+    res->bits=(uByte)(bits&DECNEG);    /* it's now safe to overwrite.. */
+    res->exponent=lhs->exponent;       /* .. operands (even if aliased) */
+
+    #if DECTRACE
+      decDumpAr('A', lhs->lsu, D2U(lhs->digits));
+      decDumpAr('B', rhs->lsu, D2U(rhs->digits));
+      printf(" :h: %ld %ld\n", rhsshift, mult);
+    #endif
+
+    /* add [A+B*m] or subtract [A+B*(-m)] */
+    res->digits=decUnitAddSub(lhs->lsu, D2U(lhs->digits),
+                             rhs->lsu, D2U(rhs->digits),
+                             rhsshift, acc, mult)
+              *DECDPUN;           /* [units -> digits] */
+    if (res->digits<0) {          /* borrowed... */
+      res->digits=-res->digits;
+      res->bits^=DECNEG;          /* flip the sign */
+      }
+    #if DECTRACE
+      decDumpAr('+', acc, D2U(res->digits));
+    #endif
+
+    /* If a buffer was used the result must be copied back, possibly */
+    /* shortening.  (If no buffer was used then the result must have */
+    /* fit, so can't need rounding and residue must be 0.) */
+    residue=0;                    /* clear accumulator */
+    if (acc!=res->lsu) {
+      #if DECSUBSET
+      if (set->extended) {        /* round from first significant digit */
+      #endif
+       /* remove leading zeros that were added due to rounding up to */
+       /* integral Units -- before the test for rounding. */
+       if (res->digits>reqdigits)
+         res->digits=decGetDigits(acc, D2U(res->digits));
+       decSetCoeff(res, set, acc, res->digits, &residue, status);
+      #if DECSUBSET
        }
-#if DECTRACE
-      decDumpAr ('+', acc, D2U (res->digits));
-#endif
-
-      /* If we used a buffer we need to copy back, possibly shortening */
-      /* (If we didn't use buffer it must have fit, so can't need rounding */
-      /* and residue must be 0.) */
-      residue = 0;             /* clear accumulator */
-      if (acc != res->lsu)
-       {
-#if DECSUBSET
-         if (set->extended)
-           {                   /* round from first significant digit */
-#endif
-             /* remove leading zeros that we added due to rounding up to */
-             /* integral Units -- before the test for rounding. */
-             if (res->digits > reqdigits)
-               res->digits = decGetDigits (acc, D2U (res->digits));
-             decSetCoeff (res, set, acc, res->digits, &residue, status);
-#if DECSUBSET
+       else { /* subset arithmetic rounds from original significant digit */
+       /* May have an underestimate.  This only occurs when both */
+       /* numbers fit in DECDPUN digits and are padding with a */
+       /* negative multiple (-10, -100...) and the top digit(s) become */
+       /* 0.  (This only matters when using X3.274 rules where the */
+       /* leading zero could be included in the rounding.) */
+       if (res->digits<maxdigits) {
+         *(acc+D2U(res->digits))=0; /* ensure leading 0 is there */
+         res->digits=maxdigits;
+         }
+        else {
+         /* remove leading zeros that added due to rounding up to */
+         /* integral Units (but only those in excess of the original */
+         /* maxdigits length, unless extended) before test for rounding. */
+         if (res->digits>reqdigits) {
+           res->digits=decGetDigits(acc, D2U(res->digits));
+           if (res->digits<maxdigits) res->digits=maxdigits;
            }
-         else
-           {                   /* subset arithmetic rounds from original significant digit */
-             /* We may have an underestimate.  This only occurs when both */
-             /* numbers fit in DECDPUN digits and we are padding with a */
-             /* negative multiple (-10, -100...) and the top digit(s) become */
-             /* 0.  (This only matters if we are using X3.274 rules where the */
-             /* leading zero could be included in the rounding.) */
-             if (res->digits < maxdigits)
-               {
-                 *(acc + D2U (res->digits)) = 0;       /* ensure leading 0 is there */
-                 res->digits = maxdigits;
-               }
-             else
-               {
-                 /* remove leading zeros that we added due to rounding up to */
-                 /* integral Units (but only those in excess of the original */
-                 /* maxdigits length, unless extended) before test for rounding. */
-                 if (res->digits > reqdigits)
-                   {
-                     res->digits = decGetDigits (acc, D2U (res->digits));
-                     if (res->digits < maxdigits)
-                       res->digits = maxdigits;
-                   }
-               }
-             decSetCoeff (res, set, acc, res->digits, &residue, status);
-             /* Now apply rounding if needed before removing leading zeros. */
-             /* This is safe because subnormals are not a possibility */
-             if (residue != 0)
-               {
-                 decApplyRound (res, set, residue, status);
-                 residue = 0;  /* we did what we had to do */
-               }
-           }                   /* subset */
-#endif
-       }                       /* used buffer */
-
-      /* strip leading zeros [these were left on in case of subset subtract] */
-      res->digits = decGetDigits (res->lsu, D2U (res->digits));
-
-      /* apply checks and rounding */
-      decFinish (res, set, &residue, status);
+         }
+       decSetCoeff(res, set, acc, res->digits, &residue, status);
+       /* Now apply rounding if needed before removing leading zeros. */
+       /* This is safe because subnormals are not a possibility */
+       if (residue!=0) {
+         decApplyRound(res, set, residue, status);
+         residue=0;                 /* did what needed to be done */
+         }
+       } /* subset */
+      #endif
+      } /* used buffer */
+
+    /* strip leading zeros [these were left on in case of subset subtract] */
+    res->digits=decGetDigits(res->lsu, D2U(res->digits));
+
+    /* apply checks and rounding */
+    decFinish(res, set, &residue, status);
+
+    /* "When the sum of two operands with opposite signs is exactly */
+    /* zero, the sign of that sum shall be '+' in all rounding modes */
+    /* except round toward -Infinity, in which mode that sign shall be */
+    /* '-'."  [Subset zeros also never have '-', set by decFinish.] */
+    if (ISZERO(res) && diffsign
+     #if DECSUBSET
+     && set->extended
+     #endif
+     && (*status&DEC_Inexact)==0) {
+      if (set->round==DEC_ROUND_FLOOR) res->bits|=DECNEG;   /* sign - */
+                                 else res->bits&=~DECNEG;  /* sign + */
+      }
+    } while(0);                                     /* end protected */
 
-      /* "When the sum of two operands with opposite signs is exactly */
-      /* zero, the sign of that sum shall be '+' in all rounding modes */
-      /* except round toward -Infinity, in which mode that sign shall be */
-      /* '-'."  [Subset zeros also never have '-', set by decFinish.] */
-      if (ISZERO (res) && diffsign
-#if DECSUBSET
-         && set->extended
-#endif
-         && (*status & DEC_Inexact) == 0)
-       {
-         if (set->round == DEC_ROUND_FLOOR)
-           res->bits |= DECNEG;        /* sign - */
-         else
-           res->bits &= ~DECNEG;       /* sign + */
-       }
-    }
-  while (0);                   /* end protected */
-
-  if (alloced)
-    {
-      if (allocacc != NULL)
-       free (allocacc);        /* drop any storage we used */
-      if (allocrhs != NULL)
-       free (allocrhs);        /* .. */
-      if (alloclhs != NULL)
-       free (alloclhs);        /* .. */
-    }
+  if (allocacc!=NULL) free(allocacc);       /* drop any storage used */
+  #if DECSUBSET
+  if (allocrhs!=NULL) free(allocrhs);       /* .. */
+  if (alloclhs!=NULL) free(alloclhs);       /* .. */
+  #endif
   return res;
-}
+  } /* decAddOp */
 
 /* ------------------------------------------------------------------ */
-/* decDivideOp -- division operation                                  */
-/*                                                                    */
+/* decDivideOp -- division operation                                 */
+/*                                                                   */
 /*  This routine performs the calculations for all four division      */
 /*  operators (divide, divideInteger, remainder, remainderNear).      */
-/*                                                                    */
-/*  C=A op B                                                          */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X/X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*   op  is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively.    */
-/*   status is the usual accumulator                                  */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/*                                                                    */
+/*                                                                   */
+/*  C=A op B                                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A and/or B (e.g., X=X/X)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*   op         is DIVIDE, DIVIDEINT, REMAINDER, or REMNEAR respectively.    */
+/*   status is the usual accumulator                                 */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
 /* ------------------------------------------------------------------ */
 /*   The underlying algorithm of this routine is the same as in the   */
 /*   1981 S/370 implementation, that is, non-restoring long division  */
 /*   with bi-unit (rather than bi-digit) estimation for each unit     */
 /*   multiplier.  In this pseudocode overview, complications for the  */
 /*   Remainder operators and division residues for exact rounding are */
-/*   omitted for clarity.                                             */
-/*                                                                    */
-/*     Prepare operands and handle special values                     */
-/*     Test for x/0 and then 0/x                                      */
-/*     Exp =Exp1 - Exp2                                               */
-/*     Exp =Exp +len(var1) -len(var2)                                 */
-/*     Sign=Sign1 * Sign2                                             */
-/*     Pad accumulator (Var1) to double-length with 0's (pad1)        */
-/*     Pad Var2 to same length as Var1                                */
+/*   omitted for clarity.                                            */
+/*                                                                   */
+/*     Prepare operands and handle special values                    */
+/*     Test for x/0 and then 0/x                                     */
+/*     Exp =Exp1 - Exp2                                                      */
+/*     Exp =Exp +len(var1) -len(var2)                                */
+/*     Sign=Sign1 * Sign2                                            */
+/*     Pad accumulator (Var1) to double-length with 0's (pad1)       */
+/*     Pad Var2 to same length as Var1                               */
 /*     msu2pair/plus=1st 2 or 1 units of var2, +1 to allow for round  */
-/*     have=0                                                         */
-/*     Do until (have=digits+1 OR residue=0)                          */
-/*       if exp<0 then if integer divide/residue then leave           */
-/*       this_unit=0                                                  */
-/*       Do forever                                                   */
-/*          compare numbers                                           */
-/*          if <0 then leave inner_loop                               */
-/*          if =0 then (* quick exit without subtract *) do           */
-/*             this_unit=this_unit+1; output this_unit                */
-/*             leave outer_loop; end                                  */
-/*          Compare lengths of numbers (mantissae):                   */
-/*          If same then tops2=msu2pair -- {units 1&2 of var2}        */
-/*                  else tops2=msu2plus -- {0, unit 1 of var2}        */
-/*          tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */
-/*          mult=tops1/tops2  -- Good and safe guess at divisor       */
-/*          if mult=0 then mult=1                                     */
-/*          this_unit=this_unit+mult                                  */
-/*          subtract                                                  */
-/*          end inner_loop                                            */
-/*        if have\=0 | this_unit\=0 then do                           */
-/*          output this_unit                                          */
-/*          have=have+1; end                                          */
-/*        var2=var2/10                                                */
-/*        exp=exp-1                                                   */
-/*        end outer_loop                                              */
-/*     exp=exp+1   -- set the proper exponent                         */
-/*     if have=0 then generate answer=0                               */
-/*     Return (Result is defined by Var1)                             */
-/*                                                                    */
-/* ------------------------------------------------------------------ */
-/* We need two working buffers during the long division; one (digits+ */
+/*     have=0                                                        */
+/*     Do until (have=digits+1 OR residue=0)                         */
+/*      if exp<0 then if integer divide/residue then leave           */
+/*      this_unit=0                                                  */
+/*      Do forever                                                   */
+/*         compare numbers                                           */
+/*         if <0 then leave inner_loop                               */
+/*         if =0 then (* quick exit without subtract *) do           */
+/*            this_unit=this_unit+1; output this_unit                */
+/*            leave outer_loop; end                                  */
+/*         Compare lengths of numbers (mantissae):                   */
+/*         If same then tops2=msu2pair -- {units 1&2 of var2}        */
+/*                 else tops2=msu2plus -- {0, unit 1 of var2}        */
+/*         tops1=first_unit_of_Var1*10**DECDPUN +second_unit_of_var1 */
+/*         mult=tops1/tops2  -- Good and safe guess at divisor       */
+/*         if mult=0 then mult=1                                     */
+/*         this_unit=this_unit+mult                                  */
+/*         subtract                                                  */
+/*         end inner_loop                                            */
+/*       if have\=0 | this_unit\=0 then do                           */
+/*         output this_unit                                          */
+/*         have=have+1; end                                          */
+/*       var2=var2/10                                                */
+/*       exp=exp-1                                                   */
+/*       end outer_loop                                              */
+/*     exp=exp+1   -- set the proper exponent                        */
+/*     if have=0 then generate answer=0                                      */
+/*     Return (Result is defined by Var1)                            */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+/* Two working buffers are needed during the division; one (digits+   */
 /* 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.*/
-/* ------------------------------------------------------------------ */
-static decNumber *
-decDivideOp (decNumber * res,
-            const decNumber * lhs, const decNumber * rhs,
-            decContext * set, Flag op, uInt * status)
-{
-  decNumber *alloclhs = NULL;  /* non-NULL if rounded lhs allocated */
-  decNumber *allocrhs = NULL;  /* .., rhs */
-  Unit accbuff[D2U (DECBUFFER + DECDPUN)];     /* local buffer */
-  Unit *acc = accbuff;         /* -> accumulator array for result */
-  Unit *allocacc = NULL;       /* -> allocated buffer, iff allocated */
-  Unit *accnext;               /* -> where next digit will go */
-  Int acclength;               /* length of acc needed [Units] */
-  Int accunits;                        /* count of units accumulated */
-  Int accdigits;               /* count of digits accumulated */
-
-  Unit varbuff[D2U (DECBUFFER * 2 + DECDPUN) * sizeof (Unit)]; /* buffer for var1 */
-  Unit *var1 = varbuff;                /* -> var1 array for long subtraction */
-  Unit *varalloc = NULL;       /* -> allocated buffer, iff used */
-
-  const Unit *var2;            /* -> var2 array */
-
-  Int var1units, var2units;    /* actual lengths */
-  Int var2ulen;                        /* logical length (units) */
-  Int var1initpad = 0;         /* var1 initial padding (digits) */
-  Unit *msu1;                  /* -> msu of each var */
-  const Unit *msu2;            /* -> msu of each var */
-  Int msu2plus;                        /* msu2 plus one [does not vary] */
-  eInt msu2pair;               /* msu2 pair plus one [does not vary] */
-  Int maxdigits;               /* longest LHS or required acc length */
-  Int mult;                    /* multiplier for subtraction */
-  Unit thisunit;               /* current unit being accumulated */
-  Int residue;                 /* for rounding */
-  Int reqdigits = set->digits; /* requested DIGITS */
-  Int exponent;                        /* working exponent */
-  Int maxexponent = 0;         /* DIVIDE maximum exponent if unrounded */
-  uByte bits;                  /* working sign */
-  uByte merged;                        /* merged flags */
-  Unit *target;                        /* work */
-  const Unit *source;          /* work */
-  uInt const *pow;             /* .. */
-  Int shift, cut;              /* .. */
-#if DECSUBSET
-  Int dropped;                 /* work */
-#endif
+/* The static buffers may be larger than might be expected to allow   */
+/* for calls from higher-level funtions (notable exp).               */
+/* ------------------------------------------------------------------ */
+static decNumber * decDivideOp(decNumber *res,
+                              const decNumber *lhs, const decNumber *rhs,
+                              decContext *set, Flag op, uInt *status) {
+  #if DECSUBSET
+  decNumber *alloclhs=NULL;       /* non-NULL if rounded lhs allocated */
+  decNumber *allocrhs=NULL;       /* .., rhs */
+  #endif
+  Unit accbuff[SD2U(DECBUFFER+DECDPUN+10)]; /* local buffer */
+  Unit *acc=accbuff;              /* -> accumulator array for result */
+  Unit *allocacc=NULL;            /* -> allocated buffer, iff allocated */
+  Unit *accnext;                  /* -> where next digit will go */
+  Int  acclength;                 /* length of acc needed [Units] */
+  Int  accunits;                  /* count of units accumulated */
+  Int  accdigits;                 /* count of digits accumulated */
+
+  Unit varbuff[SD2U(DECBUFFER*2+DECDPUN)*sizeof(Unit)]; /* buffer for var1 */
+  Unit *var1=varbuff;             /* -> var1 array for long subtraction */
+  Unit *varalloc=NULL;            /* -> allocated buffer, iff used */
+  Unit *msu1;                     /* -> msu of var1 */
+
+  const Unit *var2;               /* -> var2 array */
+  const Unit *msu2;               /* -> msu of var2 */
+  Int  msu2plus;                  /* msu2 plus one [does not vary] */
+  eInt msu2pair;                  /* msu2 pair plus one [does not vary] */
+
+  Int  var1units, var2units;      /* actual lengths */
+  Int  var2ulen;                  /* logical length (units) */
+  Int  var1initpad=0;             /* var1 initial padding (digits) */
+  Int  maxdigits;                 /* longest LHS or required acc length */
+  Int  mult;                      /* multiplier for subtraction */
+  Unit thisunit;                  /* current unit being accumulated */
+  Int  residue;                   /* for rounding */
+  Int  reqdigits=set->digits;     /* requested DIGITS */
+  Int  exponent;                  /* working exponent */
+  Int  maxexponent=0;             /* DIVIDE maximum exponent if unrounded */
+  uByte bits;                     /* working sign */
+  Unit *target;                   /* work */
+  const Unit *source;             /* .. */
+  uInt const *pow;                /* .. */
+  Int  shift, cut;                /* .. */
+  #if DECSUBSET
+  Int  dropped;                   /* work */
+  #endif
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  do {                            /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operands and set lostDigits status, as needed */
+      if (lhs->digits>reqdigits) {
+       alloclhs=decRoundOperand(lhs, set, status);
+       if (alloclhs==NULL) break;
+       lhs=alloclhs;
+       }
+      if (rhs->digits>reqdigits) {
+       allocrhs=decRoundOperand(rhs, set, status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
+       }
+      }
+    #endif
+    /* [following code does not require input rounding] */
 
-#if DECCHECK
-  if (decCheckOperands (res, lhs, rhs, set))
-    return res;
-#endif
+    bits=(lhs->bits^rhs->bits)&DECNEG; /* assumed sign for divisions */
 
-  do
-    {                          /* protect allocated storage */
-#if DECSUBSET
-      if (!set->extended)
-       {
-         /* reduce operands and set lostDigits status, as needed */
-         if (lhs->digits > reqdigits)
-           {
-             alloclhs = decRoundOperand (lhs, set, status);
-             if (alloclhs == NULL)
-               break;
-             lhs = alloclhs;
-           }
-         if (rhs->digits > reqdigits)
-           {
-             allocrhs = decRoundOperand (rhs, set, status);
-             if (allocrhs == NULL)
-               break;
-             rhs = allocrhs;
-           }
+    /* handle infinities and NaNs */
+    if (SPECIALARGS) {                 /* a special bit set */
+      if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
+       decNaNs(res, lhs, rhs, set, status);
+       break;
        }
-#endif
-      /* [following code does not require input rounding] */
-
-      bits = (lhs->bits ^ rhs->bits) & DECNEG; /* assumed sign for divisions */
-
-      /* handle infinities and NaNs */
-      merged = (lhs->bits | rhs->bits) & DECSPECIAL;
-      if (merged)
-       {                       /* a special bit set */
-         if (merged & (DECSNAN | DECNAN))
-           {                   /* one or two NaNs */
-             decNaNs (res, lhs, rhs, status);
-             break;
-           }
-         /* one or two infinities */
-         if (decNumberIsInfinite (lhs))
-           {                   /* LHS (dividend) is infinite */
-             if (decNumberIsInfinite (rhs) ||  /* two infinities are invalid .. */
-                 op & (REMAINDER | REMNEAR))
-               {               /* as is remainder of infinity */
-                 *status |= DEC_Invalid_operation;
-                 break;
-               }
-             /* [Note that infinity/0 raises no exceptions] */
-             decNumberZero (res);
-             res->bits = bits | DECINF;        /* set +/- infinity */
-             break;
-           }
-         else
-           {                   /* RHS (divisor) is infinite */
-             residue = 0;
-             if (op & (REMAINDER | REMNEAR))
-               {
-                 /* result is [finished clone of] lhs */
-                 decCopyFit (res, lhs, set, &residue, status);
-               }
-             else
-               {               /* a division */
-                 decNumberZero (res);
-                 res->bits = bits;     /* set +/- zero */
-                 /* for DIVIDEINT the exponent is always 0.  For DIVIDE, result */
-                 /* is a 0 with infinitely negative exponent, clamped to minimum */
-                 if (op & DIVIDE)
-                   {
-                     res->exponent = set->emin - set->digits + 1;
-                     *status |= DEC_Clamped;
-                   }
-               }
-             decFinish (res, set, &residue, status);
-             break;
-           }
+      /* one or two infinities */
+      if (decNumberIsInfinite(lhs)) {  /* LHS (dividend) is infinite */
+       if (decNumberIsInfinite(rhs) || /* two infinities are invalid .. */
+           op & (REMAINDER | REMNEAR)) { /* as is remainder of infinity */
+         *status|=DEC_Invalid_operation;
+         break;
+         }
+       /* [Note that infinity/0 raises no exceptions] */
+       decNumberZero(res);
+       res->bits=bits|DECINF;          /* set +/- infinity */
+       break;
        }
-
-      /* handle 0 rhs (x/0) */
-      if (ISZERO (rhs))
-       {                       /* x/0 is always exceptional */
-         if (ISZERO (lhs))
-           {
-             decNumberZero (res);      /* [after lhs test] */
-             *status |= DEC_Division_undefined;        /* 0/0 will become NaN */
-           }
-         else
-           {
-             decNumberZero (res);
-             if (op & (REMAINDER | REMNEAR))
-               *status |= DEC_Invalid_operation;
-             else
-               {
-                 *status |= DEC_Division_by_zero;      /* x/0 */
-                 res->bits = bits | DECINF;    /* .. is +/- Infinity */
-               }
+       else {                          /* RHS (divisor) is infinite */
+       residue=0;
+       if (op&(REMAINDER|REMNEAR)) {
+         /* result is [finished clone of] lhs */
+         decCopyFit(res, lhs, set, &residue, status);
+         }
+        else {  /* a division */
+         decNumberZero(res);
+         res->bits=bits;               /* set +/- zero */
+         /* for DIVIDEINT the exponent is always 0.  For DIVIDE, result */
+         /* is a 0 with infinitely negative exponent, clamped to minimum */
+         if (op&DIVIDE) {
+           res->exponent=set->emin-set->digits+1;
+           *status|=DEC_Clamped;
            }
-         break;
+         }
+       decFinish(res, set, &residue, status);
+       break;
        }
+      }
 
-      /* handle 0 lhs (0/x) */
-      if (ISZERO (lhs))
-       {                       /* 0/x [x!=0] */
-#if DECSUBSET
-         if (!set->extended)
-           decNumberZero (res);
-         else
-           {
-#endif
-             if (op & DIVIDE)
-               {
-                 residue = 0;
-                 exponent = lhs->exponent - rhs->exponent;     /* ideal exponent */
-                 decNumberCopy (res, lhs);     /* [zeros always fit] */
-                 res->bits = bits;     /* sign as computed */
-                 res->exponent = exponent;     /* exponent, too */
-                 decFinalize (res, set, &residue, status);     /* check exponent */
-               }
-             else if (op & DIVIDEINT)
-               {
-                 decNumberZero (res);  /* integer 0 */
-                 res->bits = bits;     /* sign as computed */
-               }
-             else
-               {               /* a remainder */
-                 exponent = rhs->exponent;     /* [save in case overwrite] */
-                 decNumberCopy (res, lhs);     /* [zeros always fit] */
-                 if (exponent < res->exponent)
-                   res->exponent = exponent;   /* use lower */
-               }
-#if DECSUBSET
-           }
-#endif
+    /* handle 0 rhs (x/0) */
+    if (ISZERO(rhs)) {                 /* x/0 is always exceptional */
+      if (ISZERO(lhs)) {
+       decNumberZero(res);             /* [after lhs test] */
+       *status|=DEC_Division_undefined;/* 0/0 will become NaN */
+       }
+       else {
+       decNumberZero(res);
+       if (op&(REMAINDER|REMNEAR)) *status|=DEC_Invalid_operation;
+        else {
+         *status|=DEC_Division_by_zero; /* x/0 */
+         res->bits=bits|DECINF;         /* .. is +/- Infinity */
+         }
+       }
+      break;}
+
+    /* handle 0 lhs (0/x) */
+    if (ISZERO(lhs)) {                 /* 0/x [x!=0] */
+      #if DECSUBSET
+      if (!set->extended) decNumberZero(res);
+       else {
+      #endif
+       if (op&DIVIDE) {
+         residue=0;
+         exponent=lhs->exponent-rhs->exponent; /* ideal exponent */
+         decNumberCopy(res, lhs);      /* [zeros always fit] */
+         res->bits=bits;               /* sign as computed */
+         res->exponent=exponent;       /* exponent, too */
+         decFinalize(res, set, &residue, status);   /* check exponent */
+         }
+        else if (op&DIVIDEINT) {
+         decNumberZero(res);           /* integer 0 */
+         res->bits=bits;               /* sign as computed */
+         }
+        else {                         /* a remainder */
+         exponent=rhs->exponent;       /* [save in case overwrite] */
+         decNumberCopy(res, lhs);      /* [zeros always fit] */
+         if (exponent<res->exponent) res->exponent=exponent; /* use lower */
+         }
+      #if DECSUBSET
+       }
+      #endif
+      break;}
+
+    /* Precalculate exponent.  This starts off adjusted (and hence fits */
+    /* in 31 bits) and becomes the usual unadjusted exponent as the */
+    /* division proceeds.  The order of evaluation is important, here, */
+    /* to avoid wrap. */
+    exponent=(lhs->exponent+lhs->digits)-(rhs->exponent+rhs->digits);
+
+    /* If the working exponent is -ve, then some quick exits are */
+    /* possible because the quotient is known to be <1 */
+    /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */
+    if (exponent<0 && !(op==DIVIDE)) {
+      if (op&DIVIDEINT) {
+       decNumberZero(res);                  /* integer part is 0 */
+       #if DECSUBSET
+       if (set->extended)
+       #endif
+         res->bits=bits;                    /* set +/- zero */
+       break;}
+      /* fastpath remainders so long as the lhs has the smaller */
+      /* (or equal) exponent */
+      if (lhs->exponent<=rhs->exponent) {
+       if (op&REMAINDER || exponent<-1) {
+         /* It is REMAINDER or safe REMNEAR; result is [finished */
+         /* clone of] lhs  (r = x - 0*y) */
+         residue=0;
+         decCopyFit(res, lhs, set, &residue, status);
+         decFinish(res, set, &residue, status);
          break;
+         }
+       /* [unsafe REMNEAR drops through] */
        }
+      } /* fastpaths */
+
+    /* Long (slow) division is needed; roll up the sleeves... */
+
+    /* The accumulator will hold the quotient of the division. */
+    /* If it needs to be too long for stack storage, then allocate. */
+    acclength=D2U(reqdigits+DECDPUN);  /* in Units */
+    if (acclength*sizeof(Unit)>sizeof(accbuff)) {
+      /* printf("malloc dvacc %ld units\n", acclength); */
+      allocacc=(Unit *)malloc(acclength*sizeof(Unit));
+      if (allocacc==NULL) {            /* hopeless -- abandon */
+       *status|=DEC_Insufficient_storage;
+       break;}
+      acc=allocacc;                    /* use the allocated space */
+      }
 
-      /* Precalculate exponent.  This starts off adjusted (and hence fits */
-      /* in 31 bits) and becomes the usual unadjusted exponent as the */
-      /* division proceeds.  The order of evaluation is important, here, */
-      /* to avoid wrap. */
-      exponent =
-       (lhs->exponent + lhs->digits) - (rhs->exponent + rhs->digits);
-
-      /* If the working exponent is -ve, then some quick exits are */
-      /* possible because the quotient is known to be <1 */
-      /* [for REMNEAR, it needs to be < -1, as -0.5 could need work] */
-      if (exponent < 0 && !(op == DIVIDE))
-       {
-         if (op & DIVIDEINT)
-           {
-             decNumberZero (res);      /* integer part is 0 */
-#if DECSUBSET
-             if (set->extended)
-#endif
-               res->bits = bits;       /* set +/- zero */
-             break;
-           }
-         /* we can fastpath remainders so long as the lhs has the */
-         /* smaller (or equal) exponent */
-         if (lhs->exponent <= rhs->exponent)
-           {
-             if (op & REMAINDER || exponent < -1)
-               {
-                 /* It is REMAINDER or safe REMNEAR; result is [finished */
-                 /* clone of] lhs  (r = x - 0*y) */
-                 residue = 0;
-                 decCopyFit (res, lhs, set, &residue, status);
-                 decFinish (res, set, &residue, status);
-                 break;
-               }
-             /* [unsafe REMNEAR drops through] */
-           }
-       }                       /* fastpaths */
-
-      /* We need long (slow) division; roll up the sleeves... */
-
-      /* The accumulator will hold the quotient of the division. */
-      /* If it needs to be too long for stack storage, then allocate. */
-      acclength = D2U (reqdigits + DECDPUN);   /* in Units */
-      if (acclength * sizeof (Unit) > sizeof (accbuff))
-       {
-         allocacc = (Unit *) malloc (acclength * sizeof (Unit));
-         if (allocacc == NULL)
-           {                   /* hopeless -- abandon */
-             *status |= DEC_Insufficient_storage;
-             break;
-           }
-         acc = allocacc;       /* use the allocated space */
-       }
+    /* var1 is the padded LHS ready for subtractions. */
+    /* If it needs to be too long for stack storage, then allocate. */
+    /* The maximum units needed for var1 (long subtraction) is: */
+    /* Enough for */
+    /*    (rhs->digits+reqdigits-1) -- to allow full slide to right */
+    /* or  (lhs->digits)            -- to allow for long lhs */
+    /* whichever is larger */
+    /*  +1                -- for rounding of slide to right */
+    /*  +1                -- for leading 0s */
+    /*  +1                -- for pre-adjust if a remainder or DIVIDEINT */
+    /* [Note: unused units do not participate in decUnitAddSub data] */
+    maxdigits=rhs->digits+reqdigits-1;
+    if (lhs->digits>maxdigits) maxdigits=lhs->digits;
+    var1units=D2U(maxdigits)+2;
+    /* allocate a guard unit above msu1 for REMAINDERNEAR */
+    if (!(op&DIVIDE)) var1units++;
+    if ((var1units+1)*sizeof(Unit)>sizeof(varbuff)) {
+      /* printf("malloc dvvar %ld units\n", var1units+1); */
+      varalloc=(Unit *)malloc((var1units+1)*sizeof(Unit));
+      if (varalloc==NULL) {            /* hopeless -- abandon */
+       *status|=DEC_Insufficient_storage;
+       break;}
+      var1=varalloc;                   /* use the allocated space */
+      }
 
-      /* var1 is the padded LHS ready for subtractions. */
-      /* If it needs to be too long for stack storage, then allocate. */
-      /* The maximum units we need for var1 (long subtraction) is: */
-      /* Enough for */
-      /*     (rhs->digits+reqdigits-1) -- to allow full slide to right */
-      /* or  (lhs->digits)             -- to allow for long lhs */
-      /* whichever is larger */
-      /*   +1                -- for rounding of slide to right */
-      /*   +1                -- for leading 0s */
-      /*   +1                -- for pre-adjust if a remainder or DIVIDEINT */
-      /* [Note: unused units do not participate in decUnitAddSub data] */
-      maxdigits = rhs->digits + reqdigits - 1;
-      if (lhs->digits > maxdigits)
-       maxdigits = lhs->digits;
-      var1units = D2U (maxdigits) + 2;
-      /* allocate a guard unit above msu1 for REMAINDERNEAR */
-      if (!(op & DIVIDE))
-       var1units++;
-      if ((var1units + 1) * sizeof (Unit) > sizeof (varbuff))
-       {
-         varalloc = (Unit *) malloc ((var1units + 1) * sizeof (Unit));
-         if (varalloc == NULL)
-           {                   /* hopeless -- abandon */
-             *status |= DEC_Insufficient_storage;
-             break;
-           }
-         var1 = varalloc;      /* use the allocated space */
-       }
+    /* Extend the lhs and rhs to full long subtraction length. The lhs */
+    /* is truly extended into the var1 buffer, with 0 padding, so a */
+    /* subtract in place is always possible.  The rhs (var2) has */
+    /* virtual padding (implemented by decUnitAddSub). */
+    /* One guard unit was allocated above msu1 for rem=rem+rem in */
+    /* REMAINDERNEAR. */
+    msu1=var1+var1units-1;             /* msu of var1 */
+    source=lhs->lsu+D2U(lhs->digits)-1; /* msu of input array */
+    for (target=msu1; source>=lhs->lsu; source--, target--) *target=*source;
+    for (; target>=var1; target--) *target=0;
+
+    /* rhs (var2) is left-aligned with var1 at the start */
+    var2ulen=var1units;                        /* rhs logical length (units) */
+    var2units=D2U(rhs->digits);                /* rhs actual length (units) */
+    var2=rhs->lsu;                     /* -> rhs array */
+    msu2=var2+var2units-1;             /* -> msu of var2 [never changes] */
+    /* now set up the variables which will be used for estimating the */
+    /* multiplication factor.  If these variables are not exact, add */
+    /* 1 to make sure that the multiplier is never overestimated. */
+    msu2plus=*msu2;                    /* it's value .. */
+    if (var2units>1) msu2plus++;       /* .. +1 if any more */
+    msu2pair=(eInt)*msu2*(DECDPUNMAX+1);/* top two pair .. */
+    if (var2units>1) {                 /* .. [else treat 2nd as 0] */
+      msu2pair+=*(msu2-1);             /* .. */
+      if (var2units>2) msu2pair++;     /* .. +1 if any more */
+      }
 
-      /* Extend the lhs and rhs to full long subtraction length.  The lhs */
-      /* is truly extended into the var1 buffer, with 0 padding, so we can */
-      /* subtract in place.  The rhs (var2) has virtual padding */
-      /* (implemented by decUnitAddSub). */
-      /* We allocated one guard unit above msu1 for rem=rem+rem in REMAINDERNEAR */
-      msu1 = var1 + var1units - 1;     /* msu of var1 */
-      source = lhs->lsu + D2U (lhs->digits) - 1;       /* msu of input array */
-      for (target = msu1; source >= lhs->lsu; source--, target--)
-       *target = *source;
-      for (; target >= var1; target--)
-       *target = 0;
-
-      /* rhs (var2) is left-aligned with var1 at the start */
-      var2ulen = var1units;    /* rhs logical length (units) */
-      var2units = D2U (rhs->digits);   /* rhs actual length (units) */
-      var2 = rhs->lsu;         /* -> rhs array */
-      msu2 = var2 + var2units - 1;     /* -> msu of var2 [never changes] */
-      /* now set up the variables which we'll use for estimating the */
-      /* multiplication factor.  If these variables are not exact, we add */
-      /* 1 to make sure that we never overestimate the multiplier. */
-      msu2plus = *msu2;                /* it's value .. */
-      if (var2units > 1)
-       msu2plus++;             /* .. +1 if any more */
-      msu2pair = (eInt) * msu2 * (DECDPUNMAX + 1);     /* top two pair .. */
-      if (var2units > 1)
-       {                       /* .. [else treat 2nd as 0] */
-         msu2pair += *(msu2 - 1);      /* .. */
-         if (var2units > 2)
-           msu2pair++;         /* .. +1 if any more */
+    /* The calculation is working in units, which may have leading zeros, */
+    /* but the exponent was calculated on the assumption that they are */
+    /* both left-aligned.  Adjust the exponent to compensate: add the */
+    /* number of leading zeros in var1 msu and subtract those in var2 msu. */
+    /* [This is actually done by counting the digits and negating, as */
+    /* lead1=DECDPUN-digits1, and similarly for lead2.] */
+    for (pow=&powers[1]; *msu1>=*pow; pow++) exponent--;
+    for (pow=&powers[1]; *msu2>=*pow; pow++) exponent++;
+
+    /* Now, if doing an integer divide or remainder, ensure that */
+    /* the result will be Unit-aligned.         To do this, shift the var1 */
+    /* accumulator towards least if need be.  (It's much easier to */
+    /* do this now than to reassemble the residue afterwards, if */
+    /* doing a remainder.)  Also ensure the exponent is not negative. */
+    if (!(op&DIVIDE)) {
+      Unit *u;                         /* work */
+      /* save the initial 'false' padding of var1, in digits */
+      var1initpad=(var1units-D2U(lhs->digits))*DECDPUN;
+      /* Determine the shift to do. */
+      if (exponent<0) cut=-exponent;
+       else cut=DECDPUN-exponent%DECDPUN;
+      decShiftToLeast(var1, var1units, cut);
+      exponent+=cut;                   /* maintain numerical value */
+      var1initpad-=cut;                        /* .. and reduce padding */
+      /* clean any most-significant units which were just emptied */
+      for (u=msu1; cut>=DECDPUN; cut-=DECDPUN, u--) *u=0;
+      } /* align */
+     else { /* is DIVIDE */
+      maxexponent=lhs->exponent-rhs->exponent;   /* save */
+      /* optimization: if the first iteration will just produce 0, */
+      /* preadjust to skip it [valid for DIVIDE only] */
+      if (*msu1<*msu2) {
+       var2ulen--;                     /* shift down */
+       exponent-=DECDPUN;              /* update the exponent */
        }
+      }
 
-      /* Since we are working in units, the units may have leading zeros, */
-      /* but we calculated the exponent on the assumption that they are */
-      /* both left-aligned.  Adjust the exponent to compensate: add the */
-      /* number of leading zeros in var1 msu and subtract those in var2 msu. */
-      /* [We actually do this by counting the digits and negating, as */
-      /* lead1=DECDPUN-digits1, and similarly for lead2.] */
-      for (pow = &powers[1]; *msu1 >= *pow; pow++)
-       exponent--;
-      for (pow = &powers[1]; *msu2 >= *pow; pow++)
-       exponent++;
-
-      /* Now, if doing an integer divide or remainder, we want to ensure */
-      /* that the result will be Unit-aligned.  To do this, we shift the */
-      /* var1 accumulator towards least if need be.  (It's much easier to */
-      /* do this now than to reassemble the residue afterwards, if we are */
-      /* doing a remainder.)  Also ensure the exponent is not negative. */
-      if (!(op & DIVIDE))
-       {
-         Unit *u;
-         /* save the initial 'false' padding of var1, in digits */
-         var1initpad = (var1units - D2U (lhs->digits)) * DECDPUN;
-         /* Determine the shift to do. */
-         if (exponent < 0)
-           cut = -exponent;
-         else
-           cut = DECDPUN - exponent % DECDPUN;
-         decShiftToLeast (var1, var1units, cut);
-         exponent += cut;      /* maintain numerical value */
-         var1initpad -= cut;   /* .. and reduce padding */
-         /* clean any most-significant units we just emptied */
-         for (u = msu1; cut >= DECDPUN; cut -= DECDPUN, u--)
-           *u = 0;
-       }                       /* align */
-      else
-       {                       /* is DIVIDE */
-         maxexponent = lhs->exponent - rhs->exponent;  /* save */
-         /* optimization: if the first iteration will just produce 0, */
-         /* preadjust to skip it [valid for DIVIDE only] */
-         if (*msu1 < *msu2)
-           {
-             var2ulen--;       /* shift down */
-             exponent -= DECDPUN;      /* update the exponent */
+    /* ---- start the long-division loops ------------------------------ */
+    accunits=0;                                /* no units accumulated yet */
+    accdigits=0;                       /* .. or digits */
+    accnext=acc+acclength-1;           /* -> msu of acc [NB: allows digits+1] */
+    for (;;) {                         /* outer forever loop */
+      thisunit=0;                      /* current unit assumed 0 */
+      /* find the next unit */
+      for (;;) {                       /* inner forever loop */
+       /* strip leading zero units [from either pre-adjust or from */
+       /* subtract last time around].  Leave at least one unit. */
+       for (; *msu1==0 && msu1>var1; msu1--) var1units--;
+
+       if (var1units<var2ulen) break;       /* var1 too low for subtract */
+       if (var1units==var2ulen) {           /* unit-by-unit compare needed */
+         /* compare the two numbers, from msu */
+         const Unit *pv1, *pv2;
+         Unit v2;                           /* units to compare */
+         pv2=msu2;                          /* -> msu */
+         for (pv1=msu1; ; pv1--, pv2--) {
+           /* v1=*pv1 -- always OK */
+           v2=0;                            /* assume in padding */
+           if (pv2>=var2) v2=*pv2;          /* in range */
+           if (*pv1!=v2) break;             /* no longer the same */
+           if (pv1==var1) break;            /* done; leave pv1 as is */
            }
+         /* here when all inspected or a difference seen */
+         if (*pv1<v2) break;                /* var1 too low to subtract */
+         if (*pv1==v2) {                    /* var1 == var2 */
+           /* reach here if var1 and var2 are identical; subtraction */
+           /* would increase digit by one, and the residue will be 0 so */
+           /* the calculation is done; leave the loop with residue=0. */
+           thisunit++;                      /* as though subtracted */
+           *var1=0;                         /* set var1 to 0 */
+           var1units=1;                     /* .. */
+           break;  /* from inner */
+           } /* var1 == var2 */
+         /* *pv1>v2.  Prepare for real subtraction; the lengths are equal */
+         /* Estimate the multiplier (there's always a msu1-1)... */
+         /* Bring in two units of var2 to provide a good estimate. */
+         mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2pair);
+         } /* lengths the same */
+        else { /* var1units > var2ulen, so subtraction is safe */
+         /* The var2 msu is one unit towards the lsu of the var1 msu, */
+         /* so only one unit for var2 can be used. */
+         mult=(Int)(((eInt)*msu1*(DECDPUNMAX+1)+*(msu1-1))/msu2plus);
+         }
+       if (mult==0) mult=1;                 /* must always be at least 1 */
+       /* subtraction needed; var1 is > var2 */
+       thisunit=(Unit)(thisunit+mult);      /* accumulate */
+       /* subtract var1-var2, into var1; only the overlap needs */
+       /* processing, as this is an in-place calculation */
+       shift=var2ulen-var2units;
+       #if DECTRACE
+         decDumpAr('1', &var1[shift], var1units-shift);
+         decDumpAr('2', var2, var2units);
+         printf("m=%ld\n", -mult);
+       #endif
+       decUnitAddSub(&var1[shift], var1units-shift,
+                     var2, var2units, 0,
+                     &var1[shift], -mult);
+       #if DECTRACE
+         decDumpAr('#', &var1[shift], var1units-shift);
+       #endif
+       /* var1 now probably has leading zeros; these are removed at the */
+       /* top of the inner loop. */
+       } /* inner loop */
+
+      /* The next unit has been calculated in full; unless it's a */
+      /* leading zero, add to acc */
+      if (accunits!=0 || thisunit!=0) {             /* is first or non-zero */
+       *accnext=thisunit;                   /* store in accumulator */
+       /* account exactly for the new digits */
+       if (accunits==0) {
+         accdigits++;                       /* at least one */
+         for (pow=&powers[1]; thisunit>=*pow; pow++) accdigits++;
+         }
+        else accdigits+=DECDPUN;
+       accunits++;                          /* update count */
+       accnext--;                           /* ready for next */
+       if (accdigits>reqdigits) break;      /* have enough digits */
        }
 
-      /* ---- start the long-division loops ------------------------------ */
-      accunits = 0;            /* no units accumulated yet */
-      accdigits = 0;           /* .. or digits */
-      accnext = acc + acclength - 1;   /* -> msu of acc [NB: allows digits+1] */
-      for (;;)
-       {                       /* outer forever loop */
-         thisunit = 0;         /* current unit assumed 0 */
-         /* find the next unit */
-         for (;;)
-           {                   /* inner forever loop */
-             /* strip leading zero units [from either pre-adjust or from */
-             /* subtract last time around].  Leave at least one unit. */
-             for (; *msu1 == 0 && msu1 > var1; msu1--)
-               var1units--;
-
-             if (var1units < var2ulen)
-               break;          /* var1 too low for subtract */
-             if (var1units == var2ulen)
-               {               /* unit-by-unit compare needed */
-                 /* compare the two numbers, from msu */
-                 Unit *pv1, v2;        /* units to compare */
-                 const Unit *pv2;      /* units to compare */
-                 pv2 = msu2;   /* -> msu */
-                 for (pv1 = msu1;; pv1--, pv2--)
-                   {
-                     /* v1=*pv1 -- always OK */
-                     v2 = 0;   /* assume in padding */
-                     if (pv2 >= var2)
-                       v2 = *pv2;      /* in range */
-                     if (*pv1 != v2)
-                       break;  /* no longer the same */
-                     if (pv1 == var1)
-                       break;  /* done; leave pv1 as is */
-                   }
-                 /* here when all inspected or a difference seen */
-                 if (*pv1 < v2)
-                   break;      /* var1 too low to subtract */
-                 if (*pv1 == v2)
-                   {           /* var1 == var2 */
-                     /* reach here if var1 and var2 are identical; subtraction */
-                     /* would increase digit by one, and the residue will be 0 so */
-                     /* we are done; leave the loop with residue set to 0. */
-                     thisunit++;       /* as though subtracted */
-                     *var1 = 0;        /* set var1 to 0 */
-                     var1units = 1;    /* .. */
-                     break;    /* from inner */
-                   }           /* var1 == var2 */
-                 /* *pv1>v2.  Prepare for real subtraction; the lengths are equal */
-                 /* Estimate the multiplier (there's always a msu1-1)... */
-                 /* Bring in two units of var2 to provide a good estimate. */
-                 mult =
-                   (Int) (((eInt) * msu1 * (DECDPUNMAX + 1) +
-                           *(msu1 - 1)) / msu2pair);
-               }               /* lengths the same */
-             else
-               {               /* var1units > var2ulen, so subtraction is safe */
-                 /* The var2 msu is one unit towards the lsu of the var1 msu, */
-                 /* so we can only use one unit for var2. */
-                 mult =
-                   (Int) (((eInt) * msu1 * (DECDPUNMAX + 1) +
-                           *(msu1 - 1)) / msu2plus);
-               }
-             if (mult == 0)
-               mult = 1;       /* must always be at least 1 */
-             /* subtraction needed; var1 is > var2 */
-             thisunit = (Unit) (thisunit + mult);      /* accumulate */
-             /* subtract var1-var2, into var1; only the overlap needs */
-             /* processing, as we are in place */
-             shift = var2ulen - var2units;
-#if DECTRACE
-             decDumpAr ('1', &var1[shift], var1units - shift);
-             decDumpAr ('2', var2, var2units);
-             printf ("m=%d\n", -mult);
-#endif
-             decUnitAddSub (&var1[shift], var1units - shift,
-                            var2, var2units, 0, &var1[shift], -mult);
-#if DECTRACE
-             decDumpAr ('#', &var1[shift], var1units - shift);
-#endif
-             /* var1 now probably has leading zeros; these are removed at the */
-             /* top of the inner loop. */
-           }                   /* inner loop */
-
-         /* We have the next unit; unless it's a leading zero, add to acc */
-         if (accunits != 0 || thisunit != 0)
-           {                   /* put the unit we got */
-             *accnext = thisunit;      /* store in accumulator */
-             /* account exactly for the digits we got */
-             if (accunits == 0)
-               {
-                 accdigits++;  /* at least one */
-                 for (pow = &powers[1]; thisunit >= *pow; pow++)
-                   accdigits++;
-               }
-             else
-               accdigits += DECDPUN;
-             accunits++;       /* update count */
-             accnext--;        /* ready for next */
-             if (accdigits > reqdigits)
-               break;          /* we have all we need */
+      /* if the residue is zero, the operation is done (unless divide */
+      /* or divideInteger and still not enough digits yet) */
+      if (*var1==0 && var1units==1) {       /* residue is 0 */
+       if (op&(REMAINDER|REMNEAR)) break;
+       if ((op&DIVIDE) && (exponent<=maxexponent)) break;
+       /* [drop through if divideInteger] */
+       }
+      /* also done enough if calculating remainder or integer */
+      /* divide and just did the last ('units') unit */
+      if (exponent==0 && !(op&DIVIDE)) break;
+
+      /* to get here, var1 is less than var2, so divide var2 by the per- */
+      /* Unit power of ten and go for the next digit */
+      var2ulen--;                           /* shift down */
+      exponent-=DECDPUN;                    /* update the exponent */
+      } /* outer loop */
+
+    /* ---- division is complete --------------------------------------- */
+    /* here: acc      has at least reqdigits+1 of good results (or fewer */
+    /*               if early stop), starting at accnext+1 (its lsu) */
+    /*      var1     has any residue at the stopping point */
+    /*      accunits is the number of digits collected in acc */
+    if (accunits==0) {            /* acc is 0 */
+      accunits=1;                 /* show have a unit .. */
+      accdigits=1;                /* .. */
+      *accnext=0;                 /* .. whose value is 0 */
+      }
+     else accnext++;              /* back to last placed */
+    /* accnext now -> lowest unit of result */
+
+    residue=0;                    /* assume no residue */
+    if (op&DIVIDE) {
+      /* record the presence of any residue, for rounding */
+      if (*var1!=0 || var1units>1) residue=1;
+       else { /* no residue */
+       /* Had an exact division; clean up spurious trailing 0s. */
+       /* There will be at most DECDPUN-1, from the final multiply, */
+       /* and then only if the result is non-0 (and even) and the */
+       /* exponent is 'loose'. */
+       #if DECDPUN>1
+       Unit lsu=*accnext;
+       if (!(lsu&0x01) && (lsu!=0)) {
+         /* count the trailing zeros */
+         Int drop=0;
+         for (;; drop++) {    /* [will terminate because lsu!=0] */
+           if (exponent>=maxexponent) break;     /* don't chop real 0s */
+           #if DECDPUN<=4
+             if ((lsu-QUOT10(lsu, drop+1)
+                 *powers[drop+1])!=0) break;     /* found non-0 digit */
+           #else
+             if (lsu%powers[drop+1]!=0) break;   /* found non-0 digit */
+           #endif
+           exponent++;
            }
-
-         /* if the residue is zero, we're done (unless divide or */
-         /* divideInteger and we haven't got enough digits yet) */
-         if (*var1 == 0 && var1units == 1)
-           {                   /* residue is 0 */
-             if (op & (REMAINDER | REMNEAR))
-               break;
-             if ((op & DIVIDE) && (exponent <= maxexponent))
-               break;
-             /* [drop through if divideInteger] */
+         if (drop>0) {
+           accunits=decShiftToLeast(accnext, accunits, drop);
+           accdigits=decGetDigits(accnext, accunits);
+           accunits=D2U(accdigits);
+           /* [exponent was adjusted in the loop] */
            }
-         /* we've also done enough if calculating remainder or integer */
-         /* divide and we just did the last ('units') unit */
-         if (exponent == 0 && !(op & DIVIDE))
-           break;
-
-         /* to get here, var1 is less than var2, so divide var2 by the per- */
-         /* Unit power of ten and go for the next digit */
-         var2ulen--;           /* shift down */
-         exponent -= DECDPUN;  /* update the exponent */
-       }                       /* outer loop */
-
-      /* ---- division is complete --------------------------------------- */
-      /* here: acc      has at least reqdigits+1 of good results (or fewer */
-      /*                if early stop), starting at accnext+1 (its lsu) */
-      /*       var1     has any residue at the stopping point */
-      /*       accunits is the number of digits we collected in acc */
-      if (accunits == 0)
-       {                       /* acc is 0 */
-         accunits = 1;         /* show we have one .. */
-         accdigits = 1;        /* .. */
-         *accnext = 0;         /* .. whose value is 0 */
+         } /* neither odd nor 0 */
+       #endif
+       } /* exact divide */
+      } /* divide */
+     else /* op!=DIVIDE */ {
+      /* check for coefficient overflow */
+      if (accdigits+exponent>reqdigits) {
+       *status|=DEC_Division_impossible;
+       break;
        }
-      else
-       accnext++;              /* back to last placed */
-      /* accnext now -> lowest unit of result */
-
-      residue = 0;             /* assume no residue */
-      if (op & DIVIDE)
-       {
-         /* record the presence of any residue, for rounding */
-         if (*var1 != 0 || var1units > 1)
-           residue = 1;
-         else
-           {                   /* no residue */
-             /* We had an exact division; clean up spurious trailing 0s. */
-             /* There will be at most DECDPUN-1, from the final multiply, */
-             /* and then only if the result is non-0 (and even) and the */
-             /* exponent is 'loose'. */
-#if DECDPUN>1
-             Unit lsu = *accnext;
-             if (!(lsu & 0x01) && (lsu != 0))
-               {
-                 /* count the trailing zeros */
-                 Int drop = 0;
-                 for (;; drop++)
-                   {           /* [will terminate because lsu!=0] */
-                     if (exponent >= maxexponent)
-                       break;  /* don't chop real 0s */
-#if DECDPUN<=4
-                     if ((lsu - QUOT10 (lsu, drop + 1)
-                          * powers[drop + 1]) != 0)
-                       break;  /* found non-0 digit */
-#else
-                     if (lsu % powers[drop + 1] != 0)
-                       break;  /* found non-0 digit */
-#endif
-                     exponent++;
-                   }
-                 if (drop > 0)
-                   {
-                     accunits = decShiftToLeast (accnext, accunits, drop);
-                     accdigits = decGetDigits (accnext, accunits);
-                     accunits = D2U (accdigits);
-                     /* [exponent was adjusted in the loop] */
-                   }
-               }               /* neither odd nor 0 */
-#endif
-           }                   /* exact divide */
-       }                       /* divide */
-      else                     /* op!=DIVIDE */
-       {
-         /* check for coefficient overflow */
-         if (accdigits + exponent > reqdigits)
-           {
-             *status |= DEC_Division_impossible;
-             break;
+      if (op & (REMAINDER|REMNEAR)) {
+       /* [Here, the exponent will be 0, because var1 was adjusted */
+       /* appropriately.] */
+       Int postshift;                       /* work */
+       Flag wasodd=0;                       /* integer was odd */
+       Unit *quotlsu;                       /* for save */
+       Int  quotdigits;                     /* .. */
+
+       bits=lhs->bits;                      /* remainder sign is always as lhs */
+
+       /* Fastpath when residue is truly 0 is worthwhile [and */
+       /* simplifies the code below] */
+       if (*var1==0 && var1units==1) {      /* residue is 0 */
+         Int exp=lhs->exponent;             /* save min(exponents) */
+         if (rhs->exponent<exp) exp=rhs->exponent;
+         decNumberZero(res);                /* 0 coefficient */
+         #if DECSUBSET
+         if (set->extended)
+         #endif
+         res->exponent=exp;                 /* .. with proper exponent */
+         res->bits=(uByte)(bits&DECNEG);          /* [cleaned] */
+         decFinish(res, set, &residue, status);   /* might clamp */
+         break;
+         }
+       /* note if the quotient was odd */
+       if (*accnext & 0x01) wasodd=1;       /* acc is odd */
+       quotlsu=accnext;                     /* save in case need to reinspect */
+       quotdigits=accdigits;                /* .. */
+
+       /* treat the residue, in var1, as the value to return, via acc */
+       /* calculate the unused zero digits.  This is the smaller of: */
+       /*   var1 initial padding (saved above) */
+       /*   var2 residual padding, which happens to be given by: */
+       postshift=var1initpad+exponent-lhs->exponent+rhs->exponent;
+       /* [the 'exponent' term accounts for the shifts during divide] */
+       if (var1initpad<postshift) postshift=var1initpad;
+
+       /* shift var1 the requested amount, and adjust its digits */
+       var1units=decShiftToLeast(var1, var1units, postshift);
+       accnext=var1;
+       accdigits=decGetDigits(var1, var1units);
+       accunits=D2U(accdigits);
+
+       exponent=lhs->exponent;         /* exponent is smaller of lhs & rhs */
+       if (rhs->exponent<exponent) exponent=rhs->exponent;
+
+       /* Now correct the result if doing remainderNear; if it */
+       /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */
+       /* the integer was odd then the result should be rem-rhs. */
+       if (op&REMNEAR) {
+         Int compare, tarunits;        /* work */
+         Unit *up;                     /* .. */
+         /* calculate remainder*2 into the var1 buffer (which has */
+         /* 'headroom' of an extra unit and hence enough space) */
+         /* [a dedicated 'double' loop would be faster, here] */
+         tarunits=decUnitAddSub(accnext, accunits, accnext, accunits,
+                                0, accnext, 1);
+         /* decDumpAr('r', accnext, tarunits); */
+
+         /* Here, accnext (var1) holds tarunits Units with twice the */
+         /* remainder's coefficient, which must now be compared to the */
+         /* RHS.  The remainder's exponent may be smaller than the RHS's. */
+         compare=decUnitCompare(accnext, tarunits, rhs->lsu, D2U(rhs->digits),
+                                rhs->exponent-exponent);
+         if (compare==BADINT) {             /* deep trouble */
+           *status|=DEC_Insufficient_storage;
+           break;}
+
+         /* now restore the remainder by dividing by two; the lsu */
+         /* is known to be even. */
+         for (up=accnext; up<accnext+tarunits; up++) {
+           Int half;              /* half to add to lower unit */
+           half=*up & 0x01;
+           *up/=2;                /* [shift] */
+           if (!half) continue;
+           *(up-1)+=(DECDPUNMAX+1)/2;
            }
-         if (op & (REMAINDER | REMNEAR))
-           {
-             /* [Here, the exponent will be 0, because we adjusted var1 */
-             /* appropriately.] */
-             Int postshift;    /* work */
-             Flag wasodd = 0;  /* integer was odd */
-             Unit *quotlsu;    /* for save */
-             Int quotdigits;   /* .. */
-
-             /* Fastpath when residue is truly 0 is worthwhile [and */
-             /* simplifies the code below] */
-             if (*var1 == 0 && var1units == 1)
-               {               /* residue is 0 */
-                 Int exp = lhs->exponent;      /* save min(exponents) */
-                 if (rhs->exponent < exp)
-                   exp = rhs->exponent;
-                 decNumberZero (res);  /* 0 coefficient */
-#if DECSUBSET
-                 if (set->extended)
-#endif
-                   res->exponent = exp;        /* .. with proper exponent */
+         /* [accunits still describes the original remainder length] */
+
+         if (compare>0 || (compare==0 && wasodd)) { /* adjustment needed */
+           Int exp, expunits, exprem;       /* work */
+           /* This is effectively causing round-up of the quotient, */
+           /* so if it was the rare case where it was full and all */
+           /* nines, it would overflow and hence division-impossible */
+           /* should be raised */
+           Flag allnines=0;                 /* 1 if quotient all nines */
+           if (quotdigits==reqdigits) {     /* could be borderline */
+             for (up=quotlsu; ; up++) {
+               if (quotdigits>DECDPUN) {
+                 if (*up!=DECDPUNMAX) break;/* non-nines */
+                 }
+                else {                      /* this is the last Unit */
+                 if (*up==powers[quotdigits]-1) allnines=1;
                  break;
-               }
-             /* note if the quotient was odd */
-             if (*accnext & 0x01)
-               wasodd = 1;     /* acc is odd */
-             quotlsu = accnext;        /* save in case need to reinspect */
-             quotdigits = accdigits;   /* .. */
-
-             /* treat the residue, in var1, as the value to return, via acc */
-             /* calculate the unused zero digits.  This is the smaller of: */
-             /*   var1 initial padding (saved above) */
-             /*   var2 residual padding, which happens to be given by: */
-             postshift =
-               var1initpad + exponent - lhs->exponent + rhs->exponent;
-             /* [the 'exponent' term accounts for the shifts during divide] */
-             if (var1initpad < postshift)
-               postshift = var1initpad;
-
-             /* shift var1 the requested amount, and adjust its digits */
-             var1units = decShiftToLeast (var1, var1units, postshift);
-             accnext = var1;
-             accdigits = decGetDigits (var1, var1units);
-             accunits = D2U (accdigits);
-
-             exponent = lhs->exponent; /* exponent is smaller of lhs & rhs */
-             if (rhs->exponent < exponent)
-               exponent = rhs->exponent;
-             bits = lhs->bits; /* remainder sign is always as lhs */
-
-             /* Now correct the result if we are doing remainderNear; if it */
-             /* (looking just at coefficients) is > rhs/2, or == rhs/2 and */
-             /* the integer was odd then the result should be rem-rhs. */
-             if (op & REMNEAR)
-               {
-                 Int compare, tarunits;        /* work */
-                 Unit *up;     /* .. */
-
-
-                 /* calculate remainder*2 into the var1 buffer (which has */
-                 /* 'headroom' of an extra unit and hence enough space) */
-                 /* [a dedicated 'double' loop would be faster, here] */
-                 tarunits =
-                   decUnitAddSub (accnext, accunits, accnext, accunits, 0,
-                                  accnext, 1);
-                 /* decDumpAr('r', accnext, tarunits); */
-
-                 /* Here, accnext (var1) holds tarunits Units with twice the */
-                 /* remainder's coefficient, which we must now compare to the */
-                 /* RHS.  The remainder's exponent may be smaller than the RHS's. */
-                 compare =
-                   decUnitCompare (accnext, tarunits, rhs->lsu,
-                                   D2U (rhs->digits),
-                                   rhs->exponent - exponent);
-                 if (compare == BADINT)
-                   {           /* deep trouble */
-                     *status |= DEC_Insufficient_storage;
-                     break;
-                   }
-
-                 /* now restore the remainder by dividing by two; we know the */
-                 /* lsu is even. */
-                 for (up = accnext; up < accnext + tarunits; up++)
-                   {
-                     Int half; /* half to add to lower unit */
-                     half = *up & 0x01;
-                     *up /= 2; /* [shift] */
-                     if (!half)
-                       continue;
-                     *(up - 1) += (DECDPUNMAX + 1) / 2;
-                   }
-                 /* [accunits still describes the original remainder length] */
-
-                 if (compare > 0 || (compare == 0 && wasodd))
-                   {           /* adjustment needed */
-                     Int exp, expunits, exprem;        /* work */
-                     /* This is effectively causing round-up of the quotient, */
-                     /* so if it was the rare case where it was full and all */
-                     /* nines, it would overflow and hence division-impossible */
-                     /* should be raised */
-                     Flag allnines = 0;        /* 1 if quotient all nines */
-                     if (quotdigits == reqdigits)
-                       {       /* could be borderline */
-                         for (up = quotlsu;; up++)
-                           {
-                             if (quotdigits > DECDPUN)
-                               {
-                                 if (*up != DECDPUNMAX)
-                                   break;      /* non-nines */
-                               }
-                             else
-                               {       /* this is the last Unit */
-                                 if (*up == powers[quotdigits] - 1)
-                                   allnines = 1;
-                                 break;
-                               }
-                             quotdigits -= DECDPUN;    /* checked those digits */
-                           }   /* up */
-                       }       /* borderline check */
-                     if (allnines)
-                       {
-                         *status |= DEC_Division_impossible;
-                         break;
-                       }
-
-                     /* we need rem-rhs; the sign will invert.  Again we can */
-                     /* safely use var1 for the working Units array. */
-                     exp = rhs->exponent - exponent;   /* RHS padding needed */
-                     /* Calculate units and remainder from exponent. */
-                     expunits = exp / DECDPUN;
-                     exprem = exp % DECDPUN;
-                     /* subtract [A+B*(-m)]; the result will always be negative */
-                     accunits = -decUnitAddSub (accnext, accunits,
-                                                rhs->lsu, D2U (rhs->digits),
-                                                expunits, accnext,
-                                                -(Int) powers[exprem]);
-                     accdigits = decGetDigits (accnext, accunits);     /* count digits exactly */
-                     accunits = D2U (accdigits);       /* and recalculate the units for copy */
-                     /* [exponent is as for original remainder] */
-                     bits ^= DECNEG;   /* flip the sign */
-                   }
-               }               /* REMNEAR */
-           }                   /* REMAINDER or REMNEAR */
-       }                       /* not DIVIDE */
-
-      /* Set exponent and bits */
-      res->exponent = exponent;
-      res->bits = (uByte) (bits & DECNEG);     /* [cleaned] */
-
-      /* Now the coefficient. */
-      decSetCoeff (res, set, accnext, accdigits, &residue, status);
-
-      decFinish (res, set, &residue, status);  /* final cleanup */
-
-#if DECSUBSET
-      /* If a divide then strip trailing zeros if subset [after round] */
-      if (!set->extended && (op == DIVIDE))
-       decTrim (res, 0, &dropped);
-#endif
-    }
-  while (0);                   /* end protected */
-
-  if (varalloc != NULL)
-    free (varalloc);           /* drop any storage we used */
-  if (allocacc != NULL)
-    free (allocacc);           /* .. */
-  if (allocrhs != NULL)
-    free (allocrhs);           /* .. */
-  if (alloclhs != NULL)
-    free (alloclhs);           /* .. */
+                 }
+               quotdigits-=DECDPUN;         /* checked those digits */
+               } /* up */
+             } /* borderline check */
+           if (allnines) {
+             *status|=DEC_Division_impossible;
+             break;}
+
+           /* rem-rhs is needed; the sign will invert.  Again, var1 */
+           /* can safely be used for the working Units array. */
+           exp=rhs->exponent-exponent;      /* RHS padding needed */
+           /* Calculate units and remainder from exponent. */
+           expunits=exp/DECDPUN;
+           exprem=exp%DECDPUN;
+           /* subtract [A+B*(-m)]; the result will always be negative */
+           accunits=-decUnitAddSub(accnext, accunits,
+                                   rhs->lsu, D2U(rhs->digits),
+                                   expunits, accnext, -(Int)powers[exprem]);
+           accdigits=decGetDigits(accnext, accunits); /* count digits exactly */
+           accunits=D2U(accdigits);    /* and recalculate the units for copy */
+           /* [exponent is as for original remainder] */
+           bits^=DECNEG;               /* flip the sign */
+           }
+         } /* REMNEAR */
+       } /* REMAINDER or REMNEAR */
+      } /* not DIVIDE */
+
+    /* Set exponent and bits */
+    res->exponent=exponent;
+    res->bits=(uByte)(bits&DECNEG);         /* [cleaned] */
+
+    /* Now the coefficient. */
+    decSetCoeff(res, set, accnext, accdigits, &residue, status);
+
+    decFinish(res, set, &residue, status);   /* final cleanup */
+
+    #if DECSUBSET
+    /* If a divide then strip trailing zeros if subset [after round] */
+    if (!set->extended && (op==DIVIDE)) decTrim(res, set, 0, &dropped);
+    #endif
+    } while(0);                                     /* end protected */
+
+  if (varalloc!=NULL) free(varalloc);  /* drop any storage used */
+  if (allocacc!=NULL) free(allocacc);  /* .. */
+  #if DECSUBSET
+  if (allocrhs!=NULL) free(allocrhs);  /* .. */
+  if (alloclhs!=NULL) free(alloclhs);  /* .. */
+  #endif
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decMultiplyOp -- multiplication operation                          */
-/*                                                                    */
-/*  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)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*   status is the usual accumulator                                  */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/*                                                                    */
-/* ------------------------------------------------------------------ */
-/* Note: We use 'long' multiplication rather than Karatsuba, as the   */
+  } /* decDivideOp */
+
+/* ------------------------------------------------------------------ */
+/* decMultiplyOp -- multiplication operation                         */
+/*                                                                   */
+/*  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)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*   status is the usual accumulator                                 */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* ------------------------------------------------------------------ */
+/* 'Classic' multiplication is used rather than Karatsuba, as the     */
 /* latter would give only a minor improvement for the short numbers   */
-/* we expect to handle most (and uses much more memory).              */
-/*                                                                    */
-/* We always have to use a buffer for the accumulator.                */
-/* ------------------------------------------------------------------ */
-static decNumber *
-decMultiplyOp (decNumber * res, const decNumber * lhs,
-              const decNumber * rhs, decContext * set, uInt * status)
-{
-  decNumber *alloclhs = NULL;  /* non-NULL if rounded lhs allocated */
-  decNumber *allocrhs = NULL;  /* .., rhs */
-  Unit accbuff[D2U (DECBUFFER * 2 + 1)];       /* local buffer (+1 in case DECBUFFER==0) */
-  Unit *acc = accbuff;         /* -> accumulator array for exact result */
-  Unit *allocacc = NULL;       /* -> allocated buffer, iff allocated */
-  const Unit *mer, *mermsup;   /* work */
-  Int accunits;                        /* Units of accumulator in use */
-  Int madlength;               /* Units in multiplicand */
-  Int shift;                   /* Units to shift multiplicand by */
-  Int need;                    /* Accumulator units needed */
-  Int exponent;                        /* work */
-  Int residue = 0;             /* rounding residue */
-  uByte bits;                  /* result sign */
-  uByte merged;                        /* merged flags */
+/* expected to be handled most (and uses much more memory).          */
+/*                                                                   */
+/* There are two major paths here: the general-purpose ('old code')   */
+/* path which handles all DECDPUN values, and a fastpath version      */
+/* which is used if 64-bit ints are available, DECDPUN<=4, and more   */
+/* than two calls to decUnitAddSub would be made.                    */
+/*                                                                   */
+/* The fastpath version lumps units together into 8-digit or 9-digit  */
+/* chunks, and also uses a lazy carry strategy to minimise expensive  */
+/* 64-bit divisions.  The chunks are then broken apart again into     */
+/* units for continuing processing.  Despite this overhead, the              */
+/* fastpath can speed up some 16-digit operations by 10x (and much    */
+/* more for higher-precision calculations).                          */
+/*                                                                   */
+/* A buffer always has to be used for the accumulator; in the        */
+/* fastpath, buffers are also always needed for the chunked copies of */
+/* of the operand coefficients.                                              */
+/* Static buffers are larger than needed just for multiply, to allow  */
+/* for calls from other operations (notably exp).                    */
+/* ------------------------------------------------------------------ */
+#define FASTMUL (DECUSE64 && DECDPUN<5)
+static decNumber * decMultiplyOp(decNumber *res, const decNumber *lhs,
+                                const decNumber *rhs, decContext *set,
+                                uInt *status) {
+  Int   accunits;                 /* Units of accumulator in use */
+  Int   exponent;                 /* work */
+  Int   residue=0;                /* rounding residue */
+  uByte         bits;                     /* result sign */
+  Unit *acc;                      /* -> accumulator Unit array */
+  Int   needbytes;                /* size calculator */
+  void *allocacc=NULL;            /* -> allocated accumulator, iff allocated */
+  Unit accbuff[SD2U(DECBUFFER*4+1)]; /* buffer (+1 for DECBUFFER==0, */
+                                  /* *4 for calls from other operations) */
+  const Unit *mer, *mermsup;      /* work */
+  Int  madlength;                 /* Units in multiplicand */
+  Int  shift;                     /* Units to shift multiplicand by */
+
+  #if FASTMUL
+    /* if DECDPUN is 1 or 3 work in base 10**9, otherwise */
+    /* (DECDPUN is 2 or 4) then work in base 10**8 */
+    #if DECDPUN & 1               /* odd */
+      #define FASTBASE 1000000000  /* base */
+      #define FASTDIGS         9  /* digits in base */
+      #define FASTLAZY        18  /* carry resolution point [1->18] */
+    #else
+      #define FASTBASE 100000000
+      #define FASTDIGS         8
+      #define FASTLAZY      1844  /* carry resolution point [1->1844] */
+    #endif
+    /* 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 */
+    /* lazy carry evaluation */
+    uInt   zlhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
+    uInt  *zlhi=zlhibuff;                /* -> lhs array */
+    uInt  *alloclhi=NULL;                /* -> allocated buffer, iff allocated */
+    uInt   zrhibuff[(DECBUFFER*2+1)/8+1]; /* buffer (+1 for DECBUFFER==0) */
+    uInt  *zrhi=zrhibuff;                /* -> rhs array */
+    uInt  *allocrhi=NULL;                /* -> allocated buffer, iff allocated */
+    uLong  zaccbuff[(DECBUFFER*2+1)/4+2]; /* buffer (+1 for DECBUFFER==0) */
+    /* [allocacc is shared for both paths, as only one will run] */
+    uLong *zacc=zaccbuff;         /* -> accumulator array for exact result */
+    #if DECDPUN==1
+    Int           zoff;                   /* accumulator offset */
+    #endif
+    uInt  *lip, *rip;             /* item pointers */
+    uInt  *lmsi, *rmsi;                   /* most significant items */
+    Int           ilhs, irhs, iacc;       /* item counts in the arrays */
+    Int           lazy;                   /* lazy carry counter */
+    uLong  lcarry;                /* uLong carry */
+    uInt   carry;                 /* carry (NB not uLong) */
+    Int           count;                  /* work */
+    const  Unit *cup;             /* .. */
+    Unit  *up;                    /* .. */
+    uLong *lp;                    /* .. */
+    Int           p;                      /* .. */
+  #endif
+
+  #if DECSUBSET
+    decNumber *alloclhs=NULL;     /* -> allocated buffer, iff allocated */
+    decNumber *allocrhs=NULL;     /* -> allocated buffer, iff allocated */
+  #endif
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  /* precalculate result sign */
+  bits=(uByte)((lhs->bits^rhs->bits)&DECNEG);
 
-#if DECCHECK
-  if (decCheckOperands (res, lhs, rhs, set))
-    return res;
-#endif
+  /* handle infinities and NaNs */
+  if (SPECIALARGS) {              /* a special bit set */
+    if (SPECIALARGS & (DECSNAN | DECNAN)) { /* one or two NaNs */
+      decNaNs(res, lhs, rhs, set, status);
+      return res;}
+    /* one or two infinities; Infinity * 0 is invalid */
+    if (((lhs->bits & DECINF)==0 && ISZERO(lhs))
+      ||((rhs->bits & DECINF)==0 && ISZERO(rhs))) {
+      *status|=DEC_Invalid_operation;
+      return res;}
+    decNumberZero(res);
+    res->bits=bits|DECINF;        /* infinity */
+    return res;}
+
+  /* For best speed, as in DMSRCN [the original Rexx numerics */
+  /* module], use the shorter number as the multiplier (rhs) and */
+  /* the longer as the multiplicand (lhs) to minimise the number of */
+  /* adds (partial products) */
+  if (lhs->digits<rhs->digits) {   /* swap... */
+    const decNumber *hold=lhs;
+    lhs=rhs;
+    rhs=hold;
+    }
 
-  do
-    {                          /* protect allocated storage */
-#if DECSUBSET
-      if (!set->extended)
-       {
-         /* reduce operands and set lostDigits status, as needed */
-         if (lhs->digits > set->digits)
-           {
-             alloclhs = decRoundOperand (lhs, set, status);
-             if (alloclhs == NULL)
-               break;
-             lhs = alloclhs;
-           }
-         if (rhs->digits > set->digits)
-           {
-             allocrhs = decRoundOperand (rhs, set, status);
-             if (allocrhs == NULL)
-               break;
-             rhs = allocrhs;
-           }
+  do {                            /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operands and set lostDigits status, as needed */
+      if (lhs->digits>set->digits) {
+       alloclhs=decRoundOperand(lhs, set, status);
+       if (alloclhs==NULL) break;
+       lhs=alloclhs;
        }
-#endif
-      /* [following code does not require input rounding] */
-
-      /* precalculate result sign */
-      bits = (uByte) ((lhs->bits ^ rhs->bits) & DECNEG);
-
-      /* handle infinities and NaNs */
-      merged = (lhs->bits | rhs->bits) & DECSPECIAL;
-      if (merged)
-       {                       /* a special bit set */
-         if (merged & (DECSNAN | DECNAN))
-           {                   /* one or two NaNs */
-             decNaNs (res, lhs, rhs, status);
-             break;
-           }
-         /* one or two infinities. Infinity * 0 is invalid */
-         if (((lhs->bits & DECSPECIAL) == 0 && ISZERO (lhs))
-             || ((rhs->bits & DECSPECIAL) == 0 && ISZERO (rhs)))
-           {
-             *status |= DEC_Invalid_operation;
-             break;
-           }
-         decNumberZero (res);
-         res->bits = bits | DECINF;    /* infinity */
-         break;
-       }
-
-      /* For best speed, as in DMSRCN, we use the shorter number as the */
-      /* multiplier (rhs) and the longer as the multiplicand (lhs) */
-      if (lhs->digits < rhs->digits)
-       {                       /* swap... */
-         const decNumber *hold = lhs;
-         lhs = rhs;
-         rhs = hold;
+      if (rhs->digits>set->digits) {
+       allocrhs=decRoundOperand(rhs, set, status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
        }
-
-      /* if accumulator is too long for local storage, then allocate */
-      need = D2U (lhs->digits) + D2U (rhs->digits);    /* maximum units in result */
-      if (need * sizeof (Unit) > sizeof (accbuff))
-       {
-         allocacc = (Unit *) malloc (need * sizeof (Unit));
-         if (allocacc == NULL)
-           {
-             *status |= DEC_Insufficient_storage;
-             break;
+      }
+    #endif
+    /* [following code does not require input rounding] */
+
+    #if FASTMUL                           /* fastpath can be used */
+    /* use the fast path if there are enough digits in the shorter */
+    /* operand to make the setup and takedown worthwhile */
+    #define NEEDTWO (DECDPUN*2)           /* within two decUnitAddSub calls */
+    if (rhs->digits>NEEDTWO) {    /* use fastpath... */
+      /* calculate the number of elements in each array */
+      ilhs=(lhs->digits+FASTDIGS-1)/FASTDIGS; /* [ceiling] */
+      irhs=(rhs->digits+FASTDIGS-1)/FASTDIGS; /* .. */
+      iacc=ilhs+irhs;
+
+      /* allocate buffers if required, as usual */
+      needbytes=ilhs*sizeof(uInt);
+      if (needbytes>(Int)sizeof(zlhibuff)) {
+       alloclhi=(uInt *)malloc(needbytes);
+       zlhi=alloclhi;}
+      needbytes=irhs*sizeof(uInt);
+      if (needbytes>(Int)sizeof(zrhibuff)) {
+       allocrhi=(uInt *)malloc(needbytes);
+       zrhi=allocrhi;}
+
+      /* Allocating the accumulator space needs a special case when */
+      /* DECDPUN=1 because when converting the accumulator to Units */
+      /* after the multiplication each 8-byte item becomes 9 1-byte */
+      /* units.         Therefore iacc extra bytes are needed at the front */
+      /* (rounded up to a multiple of 8 bytes), and the uLong */
+      /* accumulator starts offset the appropriate number of units */
+      /* to the right to avoid overwrite during the unchunking. */
+      needbytes=iacc*sizeof(uLong);
+      #if DECDPUN==1
+      zoff=(iacc+7)/8;       /* items to offset by */
+      needbytes+=zoff*8;
+      #endif
+      if (needbytes>(Int)sizeof(zaccbuff)) {
+       allocacc=(uLong *)malloc(needbytes);
+       zacc=(uLong *)allocacc;}
+      if (zlhi==NULL||zrhi==NULL||zacc==NULL) {
+       *status|=DEC_Insufficient_storage;
+       break;}
+
+      acc=(Unit *)zacc;              /* -> target Unit array */
+      #if DECDPUN==1
+      zacc+=zoff;            /* start uLong accumulator to right */
+      #endif
+
+      /* assemble the chunked copies of the left and right sides */
+      for (count=lhs->digits, cup=lhs->lsu, lip=zlhi; count>0; lip++)
+       for (p=0, *lip=0; p<FASTDIGS && count>0;
+            p+=DECDPUN, cup++, count-=DECDPUN)
+         *lip+=*cup*powers[p];
+      lmsi=lip-1;     /* save -> msi */
+      for (count=rhs->digits, cup=rhs->lsu, rip=zrhi; count>0; rip++)
+       for (p=0, *rip=0; p<FASTDIGS && count>0;
+            p+=DECDPUN, cup++, count-=DECDPUN)
+         *rip+=*cup*powers[p];
+      rmsi=rip-1;     /* save -> msi */
+
+      /* zero the accumulator */
+      for (lp=zacc; lp<zacc+iacc; lp++) *lp=0;
+
+      /* Start the multiplication */
+      /* Resolving carries can dominate the cost of accumulating the */
+      /* partial products, so this is only done when necessary. */
+      /* Each uLong item in the accumulator can hold values up to */
+      /* 2**64-1, and each partial product can be as large as */
+      /* (10**FASTDIGS-1)**2.  When FASTDIGS=9, this can be added to */
+      /* itself 18.4 times in a uLong without overflowing, so during */
+      /* the main calculation resolution is carried out every 18th */
+      /* add -- every 162 digits.  Similarly, when FASTDIGS=8, the */
+      /* partial products can be added to themselves 1844.6 times in */
+      /* a uLong without overflowing, so intermediate carry */
+      /* resolution occurs only every 14752 digits.  Hence for common */
+      /* short numbers usually only the one final carry resolution */
+      /* occurs. */
+      /* (The count is set via FASTLAZY to simplify experiments to */
+      /* measure the value of this approach: a 35% improvement on a */
+      /* [34x34] multiply.) */
+      lazy=FASTLAZY;                        /* carry delay count */
+      for (rip=zrhi; rip<=rmsi; rip++) {     /* over each item in rhs */
+       lp=zacc+(rip-zrhi);                  /* where to add the lhs */
+       for (lip=zlhi; lip<=lmsi; lip++, lp++) { /* over each item in lhs */
+         *lp+=(uLong)(*lip)*(*rip);         /* [this should in-line] */
+         } /* lip loop */
+       lazy--;
+       if (lazy>0 && rip!=rmsi) continue;
+       lazy=FASTLAZY;                       /* reset delay count */
+       /* spin up the accumulator resolving overflows */
+       for (lp=zacc; lp<zacc+iacc; lp++) {
+         if (*lp<FASTBASE) continue;        /* it fits */
+         lcarry=*lp/FASTBASE;               /* top part [slow divide] */
+         /* lcarry can exceed 2**32-1, so check again; this check */
+         /* and occasional extra divide (slow) is well worth it, as */
+         /* it allows FASTLAZY to be increased to 18 rather than 4 */
+         /* in the FASTDIGS=9 case */
+         if (lcarry<FASTBASE) carry=(uInt)lcarry;  /* [usual] */
+          else { /* two-place carry [fairly rare] */
+           uInt carry2=(uInt)(lcarry/FASTBASE);    /* top top part */
+           *(lp+2)+=carry2;                        /* add to item+2 */
+           *lp-=((uLong)FASTBASE*FASTBASE*carry2); /* [slow] */
+           carry=(uInt)(lcarry-((uLong)FASTBASE*carry2)); /* [inline] */
            }
-         acc = allocacc;       /* use the allocated space */
+         *(lp+1)+=carry;                    /* add to item above [inline] */
+         *lp-=((uLong)FASTBASE*carry);      /* [inline] */
+         } /* carry resolution */
+       } /* rip loop */
+
+      /* The multiplication is complete; time to convert back into */
+      /* units.         This can be done in-place in the accumulator and in */
+      /* 32-bit operations, because carries were resolved after the */
+      /* final add.  This needs N-1 divides and multiplies for */
+      /* each item in the accumulator (which will become up to N */
+      /* units, where 2<=N<=9). */
+      for (lp=zacc, up=acc; lp<zacc+iacc; lp++) {
+       uInt item=(uInt)*lp;                 /* decapitate to uInt */
+       for (p=0; p<FASTDIGS-DECDPUN; p+=DECDPUN, up++) {
+         uInt part=item/(DECDPUNMAX+1);
+         *up=(Unit)(item-(part*(DECDPUNMAX+1)));
+         item=part;
+         } /* p */
+       *up=(Unit)item; up++;                /* [final needs no division] */
+       } /* lp */
+      accunits=up-acc;                      /* count of units */
+      }
+     else { /* here to use units directly, without chunking ['old code'] */
+    #endif
+
+      /* if accumulator will be too long for local storage, then allocate */
+      acc=accbuff;                /* -> assume buffer for accumulator */
+      needbytes=(D2U(lhs->digits)+D2U(rhs->digits))*sizeof(Unit);
+      if (needbytes>(Int)sizeof(accbuff)) {
+       allocacc=(Unit *)malloc(needbytes);
+       if (allocacc==NULL) {*status|=DEC_Insufficient_storage; break;}
+       acc=(Unit *)allocacc;                /* use the allocated space */
        }
 
       /* Now the main long multiplication loop */
       /* Unlike the equivalent in the IBM Java implementation, there */
-      /* is no advantage in calculating from msu to lsu.  So we do it */
+      /* is no advantage in calculating from msu to lsu.  So, do it */
       /* by the book, as it were. */
       /* Each iteration calculates ACC=ACC+MULTAND*MULT */
-      accunits = 1;            /* accumulator starts at '0' */
-      *acc = 0;                        /* .. (lsu=0) */
-      shift = 0;               /* no multiplicand shift at first */
-      madlength = D2U (lhs->digits);   /* we know this won't change */
-      mermsup = rhs->lsu + D2U (rhs->digits);  /* -> msu+1 of multiplier */
-
-      for (mer = rhs->lsu; mer < mermsup; mer++)
-       {
-         /* Here, *mer is the next Unit in the multiplier to use */
-         /* If non-zero [optimization] add it... */
-         if (*mer != 0)
-           {
-             accunits =
-               decUnitAddSub (&acc[shift], accunits - shift, lhs->lsu,
-                              madlength, 0, &acc[shift], *mer) + shift;
-           }
-         else
-           {                   /* extend acc with a 0; we'll use it shortly */
-             /* [this avoids length of <=0 later] */
-             *(acc + accunits) = 0;
-             accunits++;
-           }
-         /* multiply multiplicand by 10**DECDPUN for next Unit to left */
-         shift++;              /* add this for 'logical length' */
-       }                       /* n */
-#if DECTRACE
-      /* Show exact result */
-      decDumpAr ('*', acc, accunits);
-#endif
+      accunits=1;                 /* accumulator starts at '0' */
+      *acc=0;                     /* .. (lsu=0) */
+      shift=0;                    /* no multiplicand shift at first */
+      madlength=D2U(lhs->digits);  /* this won't change */
+      mermsup=rhs->lsu+D2U(rhs->digits); /* -> msu+1 of multiplier */
+
+      for (mer=rhs->lsu; mer<mermsup; mer++) {
+       /* Here, *mer is the next Unit in the multiplier to use */
+       /* If non-zero [optimization] add it... */
+       if (*mer!=0) accunits=decUnitAddSub(&acc[shift], accunits-shift,
+                                           lhs->lsu, madlength, 0,
+                                           &acc[shift], *mer)
+                                           + shift;
+        else { /* extend acc with a 0; it will be used shortly */
+         *(acc+accunits)=0;       /* [this avoids length of <=0 later] */
+         accunits++;
+         }
+       /* multiply multiplicand by 10**DECDPUN for next Unit to left */
+       shift++;                   /* add this for 'logical length' */
+       } /* n */
+    #if FASTMUL
+      } /* unchunked units */
+    #endif
+    /* common end-path */
+    #if DECTRACE
+      decDumpAr('*', acc, accunits);        /* Show exact result */
+    #endif
+
+    /* acc now contains the exact result of the multiplication, */
+    /* possibly with a leading zero unit; build the decNumber from */
+    /* it, noting if any residue */
+    res->bits=bits;                         /* set sign */
+    res->digits=decGetDigits(acc, accunits); /* count digits exactly */
+
+    /* There can be a 31-bit wrap in calculating the exponent. */
+    /* This can only happen if both input exponents are negative and */
+    /* both their magnitudes are large.         If there was a wrap, set a */
+    /* safe very negative exponent, from which decFinalize() will */
+    /* raise a hard underflow shortly. */
+    exponent=lhs->exponent+rhs->exponent;    /* calculate exponent */
+    if (lhs->exponent<0 && rhs->exponent<0 && exponent>0)
+      exponent=-2*DECNUMMAXE;               /* force underflow */
+    res->exponent=exponent;                 /* OK to overwrite now */
+
+
+    /* Set the coefficient.  If any rounding, residue records */
+    decSetCoeff(res, set, acc, res->digits, &residue, status);
+    decFinish(res, set, &residue, status);   /* final cleanup */
+    } while(0);                                /* end protected */
+
+  if (allocacc!=NULL) free(allocacc);  /* drop any storage used */
+  #if DECSUBSET
+  if (allocrhs!=NULL) free(allocrhs);  /* .. */
+  if (alloclhs!=NULL) free(alloclhs);  /* .. */
+  #endif
+  #if FASTMUL
+  if (allocrhi!=NULL) free(allocrhi);  /* .. */
+  if (alloclhi!=NULL) free(alloclhi);  /* .. */
+  #endif
+  return res;
+  } /* decMultiplyOp */
+
+/* ------------------------------------------------------------------ */
+/* decExpOp -- effect exponentiation                                 */
+/*                                                                   */
+/*   This computes C = exp(A)                                        */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context; note that rounding mode has no effect       */
+/*                                                                   */
+/* C must have space for set->digits digits. status is updated but    */
+/* not set.                                                          */
+/*                                                                   */
+/* Restrictions:                                                     */
+/*                                                                   */
+/*   digits, emax, and -emin in the context must be less than        */
+/*   2*DEC_MAX_MATH (1999998), and the rhs must be within these              */
+/*   bounds or a zero. This is an internal routine, so these         */
+/*   restrictions are contractual and not enforced.                  */
+/*                                                                   */
+/* 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      */
+/* error in rare cases.                                                      */
+/*                                                                   */
+/* Finite results will always be full precision and Inexact, except   */
+/* when A is a zero or -Infinity (giving 1 or 0 respectively).       */
+/* ------------------------------------------------------------------ */
+/* This approach used here is similar to the algorithm described in   */
+/*                                                                   */
+/*   Variable Precision Exponential Function, T. E. Hull and         */
+/*   A. Abrham, ACM Transactions on Mathematical Software, Vol 12 #2, */
+/*   pp79-91, ACM, June 1986.                                        */
+/*                                                                   */
+/* with the main difference being that the iterations in the series   */
+/* evaluation are terminated dynamically (which does not require the  */
+/* extra variable-precision variables which are expensive in this     */
+/* context).                                                         */
+/*                                                                   */
+/* The error analysis in Hull & Abrham's paper applies except for the */
+/* round-off error accumulation during the series evaluation.  This   */
+/* code does not precalculate the number of iterations and so cannot  */
+/* use Horner's scheme.         Instead, the accumulation is done at double- */
+/* precision, which ensures that the additions of the terms are exact */
+/* and do not accumulate round-off (and any round-off errors in the   */
+/* terms themselves move 'to the right' faster than they can         */
+/* accumulate).         This code also extends the calculation by allowing,  */
+/* 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 of the input or requested result).                        */
+/*                                                                   */
+/* Implementation notes:                                             */
+/*                                                                   */
+/* 1. This is separated out as decExpOp so it can be called from      */
+/*    other Mathematical functions (notably Ln) with a wider range    */
+/*    than normal.  In particular, it can handle the slightly wider   */
+/*    (double) range needed by Ln (which has to be able to calculate  */
+/*    exp(-x) where x can be the tiniest number (Ntiny).             */
+/*                                                                   */
+/* 2. Normalizing x to be <=0.1 (instead of <=1) reduces loop        */
+/*    iterations by appoximately a third with additional (although    */
+/*    diminishing) returns as the range is reduced to even smaller    */
+/*    fractions.  However, h (the power of 10 used to correct the     */
+/*    result at the end, see below) must be kept <=8 as otherwise     */
+/*    the final result cannot be computed.  Hence the leverage is a   */
+/*    sliding value (8-h), where potentially the range is reduced     */
+/*    more for smaller values.                                       */
+/*                                                                   */
+/*    The leverage that can be applied in this way is severely       */
+/*    limited by the cost of the raise-to-the power at the end,              */
+/*    which dominates when the number of iterations is small (less    */
+/*    than ten) or when rhs is short.  As an example, the adjustment  */
+/*    x**10,000,000 needs 31 multiplications, all but one full-width. */
+/*                                                                   */
+/* 3. The restrictions (especially precision) could be raised with    */
+/*    care, but the full decNumber range seems very hard within the   */
+/*    32-bit limits.                                                 */
+/*                                                                   */
+/* 4. The working precisions for the static buffers are twice the     */
+/*    obvious size to allow for calls from decNumberPower.           */
+/* ------------------------------------------------------------------ */
+decNumber * decExpOp(decNumber *res, const decNumber *rhs,
+                        decContext *set, uInt *status) {
+  uInt ignore=0;                  /* working status */
+  Int h;                          /* adjusted exponent for 0.xxxx */
+  Int p;                          /* working precision */
+  Int residue;                    /* rounding residue */
+  uInt needbytes;                 /* for space calculations */
+  const decNumber *x=rhs;         /* (may point to safe copy later) */
+  decContext aset, tset, dset;    /* working contexts */
+  Int comp;                       /* work */
+
+  /* the argument is often copied to normalize it, so (unusually) it */
+  /* is treated like other buffers, using DECBUFFER, +1 in case */
+  /* DECBUFFER is 0 */
+  decNumber bufr[D2N(DECBUFFER*2+1)];
+  decNumber *allocrhs=NULL;       /* non-NULL if rhs buffer allocated */
+
+  /* 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 */
+  /* is 0 (and twice that for the accumulator) */
+
+  /* buffer for t, term (working precision plus) */
+  decNumber buft[D2N(DECBUFFER*2+9+1)];
+  decNumber *allocbuft=NULL;      /* -> allocated buft, iff allocated */
+  decNumber *t=buft;              /* term */
+  /* buffer for a, accumulator (working precision * 2), at least 9 */
+  decNumber bufa[D2N(DECBUFFER*4+18+1)];
+  decNumber *allocbufa=NULL;      /* -> allocated bufa, iff allocated */
+  decNumber *a=bufa;              /* accumulator */
+  /* decNumber for the divisor term; this needs at most 9 digits */
+  /* and so can be fixed size [16 so can use standard context] */
+  decNumber bufd[D2N(16)];
+  decNumber *d=bufd;              /* divisor */
+  decNumber numone;               /* constant 1 */
+
+  #if DECCHECK
+  Int iterations=0;               /* for later sanity check */
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  do {                                 /* protect allocated storage */
+    if (SPECIALARG) {                  /* handle infinities and NaNs */
+      if (decNumberIsInfinite(rhs)) {  /* an infinity */
+       if (decNumberIsNegative(rhs))   /* -Infinity -> +0 */
+         decNumberZero(res);
+        else decNumberCopy(res, rhs);  /* +Infinity -> self */
+       }
+       else decNaNs(res, rhs, NULL, set, status); /* a NaN */
+      break;}
+
+    if (ISZERO(rhs)) {                 /* zeros -> exact 1 */
+      decNumberZero(res);              /* make clean 1 */
+      *res->lsu=1;                     /* .. */
+      break;}                          /* [no status to set] */
+
+    /* 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 */
+    /* 1.  This also allows the later add-accumulate to always be */
+    /* exact (because its length will never be more than twice the */
+    /* working precision). */
+    /* The comparator (tiny) needs just one digit, so use the */
+    /* decNumber d for it (reused as the divisor, etc., below); its */
+    /* exponent is such that if x is positive it will have */
+    /* 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 */
+    /* 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 */
+    /* or 0.00000004 if digits=7 and x<0.  If RHS not larger than */
+    /* this then the result will be 1.000000 */
+    decNumberZero(d);                  /* clean */
+    *d->lsu=4;                         /* set 4 .. */
+    d->exponent=-set->digits;          /* * 10**(-d) */
+    if (decNumberIsNegative(rhs)) d->exponent--;  /* negative case */
+    comp=decCompare(d, rhs, 1);                /* signless compare */
+    if (comp==BADINT) {
+      *status|=DEC_Insufficient_storage;
+      break;}
+    if (comp>=0) {                     /* rhs < d */
+      Int shift=set->digits-1;
+      decNumberZero(res);              /* set 1 */
+      *res->lsu=1;                     /* .. */
+      res->digits=decShiftToMost(res->lsu, 1, shift);
+      res->exponent=-shift;                 /* make 1.0000... */
+      *status|=DEC_Inexact | DEC_Rounded;    /* .. inexactly */
+      break;} /* tiny */
+
+    /* set up the context to be used for calculating a, as this is */
+    /* used on both paths below */
+    decContextDefault(&aset, DEC_INIT_DECIMAL64);
+    /* accumulator bounds are as requested (could underflow) */
+    aset.emax=set->emax;               /* usual bounds */
+    aset.emin=set->emin;               /* .. */
+    aset.clamp=0;                      /* and no concrete format */
+
+    /* calculate the adjusted (Hull & Abrham) exponent (where the */
+    /* decimal point is just to the left of the coefficient msd) */
+    h=rhs->exponent+rhs->digits;
+    /* 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 */
+    /* least 6.59E+4342944, so (due to the restriction on Emax/Emin) */
+    /* overflow (or underflow to 0) is guaranteed -- so this case can */
+    /* be handled by simply forcing the appropriate excess */
+    if (h>8) {                         /* overflow/underflow */
+      /* set up here so Power call below will over or underflow to */
+      /* zero; set accumulator to either 2 or 0.02 */
+      /* [stack buffer for a is always big enough for this] */
+      decNumberZero(a);
+      *a->lsu=2;                       /* not 1 but < exp(1) */
+      if (decNumberIsNegative(rhs)) a->exponent=-2; /* make 0.02 */
+      h=8;                             /* clamp so 10**h computable */
+      p=9;                             /* set a working precision */
+      }
+     else {                            /* h<=8 */
+      Int maxlever=(rhs->digits>8?1:0);
+      /* [could/should increase this for precisions >40 or so, too] */
+
+      /* if h is 8, cannot normalize to a lower upper limit because */
+      /* the final result will not be computable (see notes above), */
+      /* but leverage can be applied whenever h is less than 8. */
+      /* Apply as much as possible, up to a MAXLEVER digits, which */
+      /* sets the tradeoff against the cost of the later a**(10**h). */
+      /* As h is increased, the working precision below also */
+      /* increases to compensate for the "constant digits at the */
+      /* front" effect. */
+      Int lever=MINI(8-h, maxlever);   /* leverage attainable */
+      Int use=-rhs->digits-lever;      /* exponent to use for RHS */
+      h+=lever;                                /* apply leverage selected */
+      if (h<0) {                       /* clamp */
+       use+=h;                         /* [may end up subnormal] */
+       h=0;
+       }
+      /* Take a copy of RHS if it needs normalization (true whenever x>=1) */
+      if (rhs->exponent!=use) {
+       decNumber *newrhs=bufr;         /* assume will fit on stack */
+       needbytes=sizeof(decNumber)+(D2U(rhs->digits)-1)*sizeof(Unit);
+       if (needbytes>sizeof(bufr)) {   /* need malloc space */
+         allocrhs=(decNumber *)malloc(needbytes);
+         if (allocrhs==NULL) {         /* hopeless -- abandon */
+           *status|=DEC_Insufficient_storage;
+           break;}
+         newrhs=allocrhs;              /* use the allocated space */
+         }
+       decNumberCopy(newrhs, rhs);     /* copy to safe space */
+       newrhs->exponent=use;           /* normalize; now <1 */
+       x=newrhs;                       /* ready for use */
+       /* decNumberShow(x); */
+       }
 
-      /* acc now contains the exact result of the multiplication */
-      /* Build a decNumber from it, noting if any residue */
-      res->bits = bits;                /* set sign */
-      res->digits = decGetDigits (acc, accunits);      /* count digits exactly */
-
-      /* We might have a 31-bit wrap in calculating the exponent. */
-      /* This can only happen if both input exponents are negative and */
-      /* both their magnitudes are large.  If we did wrap, we set a safe */
-      /* very negative exponent, from which decFinalize() will raise a */
-      /* hard underflow. */
-      exponent = lhs->exponent + rhs->exponent;        /* calculate exponent */
-      if (lhs->exponent < 0 && rhs->exponent < 0 && exponent > 0)
-       exponent = -2 * DECNUMMAXE;     /* force underflow */
-      res->exponent = exponent;        /* OK to overwrite now */
-
-      /* Set the coefficient.  If any rounding, residue records */
-      decSetCoeff (res, set, acc, res->digits, &residue, status);
-
-      decFinish (res, set, &residue, status);  /* final cleanup */
-    }
-  while (0);                   /* end protected */
-
-  if (allocacc != NULL)
-    free (allocacc);           /* drop any storage we used */
-  if (allocrhs != NULL)
-    free (allocrhs);           /* .. */
-  if (alloclhs != NULL)
-    free (alloclhs);           /* .. */
+      /* Now use the usual power series to evaluate exp(x).  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 */
+      /* a=1, and the divisor d=2. */
+
+      /* First determine the working precision.         From Hull & Abrham */
+      /* this is set->digits+h+2.  However, if x is 'over-precise' we */
+      /* need to allow for all its digits to potentially participate */
+      /* (consider an x where all the excess digits are 9s) so in */
+      /* this case use x->digits+h+2 */
+      p=MAXI(x->digits, set->digits)+h+2;    /* [h<=8] */
+
+      /* a and t are variable precision, and depend on p, so space */
+      /* must be allocated for them if necessary */
+
+      /* the accumulator needs to be able to hold 2p digits so that */
+      /* the additions on the second and subsequent iterations are */
+      /* sufficiently exact. */
+      needbytes=sizeof(decNumber)+(D2U(p*2)-1)*sizeof(Unit);
+      if (needbytes>sizeof(bufa)) {    /* need malloc space */
+       allocbufa=(decNumber *)malloc(needbytes);
+       if (allocbufa==NULL) {          /* hopeless -- abandon */
+         *status|=DEC_Insufficient_storage;
+         break;}
+       a=allocbufa;                    /* use the allocated space */
+       }
+      /* the term needs to be able to hold p digits (which is */
+      /* guaranteed to be larger than x->digits, so the initial copy */
+      /* is safe); it may also be used for the raise-to-power */
+      /* calculation below, which needs an extra two digits */
+      needbytes=sizeof(decNumber)+(D2U(p+2)-1)*sizeof(Unit);
+      if (needbytes>sizeof(buft)) {    /* need malloc space */
+       allocbuft=(decNumber *)malloc(needbytes);
+       if (allocbuft==NULL) {          /* hopeless -- abandon */
+         *status|=DEC_Insufficient_storage;
+         break;}
+       t=allocbuft;                    /* use the allocated space */
+       }
+
+      decNumberCopy(t, x);             /* term=x */
+      decNumberZero(a); *a->lsu=1;     /* accumulator=1 */
+      decNumberZero(d); *d->lsu=2;     /* divisor=2 */
+      decNumberZero(&numone); *numone.lsu=1; /* constant 1 for increment */
+
+      /* set up the contexts for calculating a, t, and d */
+      decContextDefault(&tset, DEC_INIT_DECIMAL64);
+      dset=tset;
+      /* accumulator bounds are set above, set precision now */
+      aset.digits=p*2;                 /* double */
+      /* term bounds avoid any underflow or overflow */
+      tset.digits=p;
+      tset.emin=DEC_MIN_EMIN;          /* [emax is plenty] */
+      /* [dset.digits=16, etc., are sufficient] */
+
+      /* finally ready to roll */
+      for (;;) {
+       #if DECCHECK
+       iterations++;
+       #endif
+       /* only the status from the accumulation is interesting */
+       /* [but it should remain unchanged after first add] */
+       decAddOp(a, a, t, &aset, 0, status);           /* a=a+t */
+       decMultiplyOp(t, t, x, &tset, &ignore);        /* t=t*x */
+       decDivideOp(t, t, d, &tset, DIVIDE, &ignore);  /* t=t/d */
+       /* the iteration ends when the term cannot affect the result, */
+       /* if rounded to p digits, which is when its value is smaller */
+       /* than the accumulator by p+1 digits.  There must also be */
+       /* full precision in a. */
+       if (((a->digits+a->exponent)>=(t->digits+t->exponent+p+1))
+           && (a->digits>=p)) break;
+       decAddOp(d, d, &numone, &dset, 0, &ignore);    /* d=d+1 */
+       } /* iterate */
+
+      #if DECCHECK
+      /* just a sanity check; comment out test to show always */
+      if (iterations>p+3)
+       printf("Exp iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
+              iterations, *status, p, x->digits);
+      #endif
+      } /* h<=8 */
+
+    /* apply postconditioning: a=a**(10**h) -- this is calculated */
+    /* at a slightly higher precision than Hull & Abrham suggest */
+    if (h>0) {
+      Int seenbit=0;              /* set once a 1-bit is seen */
+      Int i;                      /* counter */
+      Int n=powers[h];            /* always positive */
+      aset.digits=p+2;            /* sufficient precision */
+      /* avoid the overhead and many extra digits of decNumberPower */
+      /* as all that is needed is the short 'multipliers' loop; here */
+      /* accumulate the answer into t */
+      decNumberZero(t); *t->lsu=1; /* acc=1 */
+      for (i=1;;i++){             /* for each bit [top bit ignored] */
+       /* abandon if have had overflow or terminal underflow */
+       if (*status & (DEC_Overflow|DEC_Underflow)) { /* interesting? */
+         if (*status&DEC_Overflow || ISZERO(t)) break;}
+       n=n<<1;                    /* move next bit to testable position */
+       if (n<0) {                 /* top bit is set */
+         seenbit=1;               /* OK, have a significant bit */
+         decMultiplyOp(t, t, a, &aset, status); /* acc=acc*x */
+         }
+       if (i==31) break;          /* that was the last bit */
+       if (!seenbit) continue;    /* no need to square 1 */
+       decMultiplyOp(t, t, t, &aset, status); /* acc=acc*acc [square] */
+       } /*i*/ /* 32 bits */
+      /* decNumberShow(t); */
+      a=t;                        /* and carry on using t instead of a */
+      }
+
+    /* Copy and round the result to res */
+    residue=1;                         /* indicate dirt to right .. */
+    if (ISZERO(a)) residue=0;          /* .. unless underflowed to 0 */
+    aset.digits=set->digits;           /* [use default rounding] */
+    decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
+    decFinish(res, set, &residue, status);      /* cleanup/set flags */
+    } while(0);                                /* end protected */
+
+  if (allocrhs !=NULL) free(allocrhs); /* drop any storage used */
+  if (allocbufa!=NULL) free(allocbufa); /* .. */
+  if (allocbuft!=NULL) free(allocbuft); /* .. */
+  /* [status is handled by caller] */
   return res;
-}
+  } /* decExpOp */
+
+/* ------------------------------------------------------------------ */
+/* Initial-estimate natural logarithm table                          */
+/*                                                                   */
+/*   LNnn -- 90-entry 16-bit table for values from .10 through .99.   */
+/*          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 */
+/*          exponent (e=the bottom 2 bits encoding 0-3)              */
+/*                                                                   */
+/*          The resulting value is given by:                         */
+/*                                                                   */
+/*            v = -c * 10**(-e-3)                                    */
+/*                                                                   */
+/*          where e and c are extracted from entry k = LNnn[x-10]    */
+/*          where x is truncated (NB) into the range 10 through 99,  */
+/*          and then c = k>>2 and e = k&3.                           */
+/* ------------------------------------------------------------------ */
+const uShort LNnn[90]={9016,  8652,  8316,  8008,  7724,  7456,         7208,
+  6972,         6748,  6540,  6340,  6148,  5968,  5792,  5628,  5464,  5312,
+  5164,         5020,  4884,  4748,  4620,  4496,  4376,  4256,  4144,  4032,
+ 39233, 38181, 37157, 36157, 35181, 34229, 33297, 32389, 31501, 30629,
+ 29777, 28945, 28129, 27329, 26545, 25777, 25021, 24281, 23553, 22837,
+ 22137, 21445, 20769, 20101, 19445, 18801, 18165, 17541, 16925, 16321,
+ 15721, 15133, 14553, 13985, 13421, 12865, 12317, 11777, 11241, 10717,
+ 10197,         9685,  9177,  8677,  8185,  7697,  7213,  6737,  6269,  5801,
+  5341,         4889,  4437, 39930, 35534, 31186, 26886, 22630, 18418, 14254,
+ 10130,         6046, 20055};
+
+/* ------------------------------------------------------------------ */
+/* decLnOp -- effect natural logarithm                               */
+/*                                                                   */
+/*   This computes C = ln(A)                                         */
+/*                                                                   */
+/*   res is C, the result.  C may be A                               */
+/*   rhs is A                                                        */
+/*   set is the context; note that rounding mode has no effect       */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
+/* Notable cases:                                                    */
+/*   A<0 -> Invalid                                                  */
+/*   A=0 -> -Infinity (Exact)                                        */
+/*   A=+Infinity -> +Infinity (Exact)                                */
+/*   A=1 exactly -> 0 (Exact)                                        */
+/*                                                                   */
+/* Restrictions (as for Exp):                                        */
+/*                                                                   */
+/*   digits, emax, and -emin in the context must be less than        */
+/*   DEC_MAX_MATH+11 (1000010), and the rhs must be within these      */
+/*   bounds or a zero. This is an internal routine, so these         */
+/*   restrictions are contractual and not enforced.                  */
+/*                                                                   */
+/* 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      */
+/* error in rare cases.                                                      */
+/* ------------------------------------------------------------------ */
+/* The result is calculated using Newton's method, with each         */
+/* iteration calculating a' = a + x * exp(-a) - 1.  See, for example, */
+/* Epperson 1989.                                                    */
+/*                                                                   */
+/* 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 */
+/* working precision.                                                */
+/*                                                                   */
+/* Implementation notes:                                             */
+/*                                                                   */
+/* 1. This is separated out as decLnOp so it can be called from              */
+/*    other Mathematical functions (e.g., Log 10) with a wider range  */
+/*    than normal.  In particular, it can handle the slightly wider   */
+/*    (+9+2) range needed by a power function.                       */
+/*                                                                   */
+/* 2. The speed of this function is about 10x slower than exp, as     */
+/*    it typically needs 4-6 iterations for short numbers, and the    */
+/*    extra precision needed adds a squaring effect, twice.          */
+/*                                                                   */
+/* 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).      */
+/*                                                                   */
+/* 4. An iteration might be saved by widening the LNnn table, and     */
+/*    would certainly save at least one if it were made ten times     */
+/*    bigger, too (for truncated fractions 0.100 through 0.999).      */
+/*    However, for most practical evaluations, at least four or five  */
+/*    iterations will be neede -- so this would only speed up by      */
+/*    20-25% and that probably does not justify increasing the table  */
+/*    size.                                                          */
+/*                                                                   */
+/* 5. The static buffers are larger than might be expected to allow   */
+/*    for calls from decNumberPower.                                 */
+/* ------------------------------------------------------------------ */
+decNumber * decLnOp(decNumber *res, const decNumber *rhs,
+                   decContext *set, uInt *status) {
+  uInt ignore=0;                  /* working status accumulator */
+  uInt needbytes;                 /* for space calculations */
+  Int residue;                    /* rounding residue */
+  Int r;                          /* rhs=f*10**r [see below] */
+  Int p;                          /* working precision */
+  Int pp;                         /* precision for iteration */
+  Int t;                          /* work */
+
+  /* buffers for a (accumulator, typically precision+2) and b */
+  /* (adjustment calculator, same size) */
+  decNumber bufa[D2N(DECBUFFER+12)];
+  decNumber *allocbufa=NULL;      /* -> allocated bufa, iff allocated */
+  decNumber *a=bufa;              /* accumulator/work */
+  decNumber bufb[D2N(DECBUFFER*2+2)];
+  decNumber *allocbufb=NULL;      /* -> allocated bufa, iff allocated */
+  decNumber *b=bufb;              /* adjustment/work */
+
+  decNumber  numone;              /* constant 1 */
+  decNumber  cmp;                 /* work */
+  decContext aset, bset;          /* working contexts */
+
+  #if DECCHECK
+  Int iterations=0;               /* for later sanity check */
+  if (decCheckOperands(res, DECUNUSED, rhs, set)) return res;
+  #endif
+
+  do {                                 /* protect allocated storage */
+    if (SPECIALARG) {                  /* handle infinities and NaNs */
+      if (decNumberIsInfinite(rhs)) {  /* an infinity */
+       if (decNumberIsNegative(rhs))   /* -Infinity -> error */
+         *status|=DEC_Invalid_operation;
+        else decNumberCopy(res, rhs);  /* +Infinity -> self */
+       }
+       else decNaNs(res, rhs, NULL, set, status); /* a NaN */
+      break;}
+
+    if (ISZERO(rhs)) {                 /* +/- zeros -> -Infinity */
+      decNumberZero(res);              /* make clean */
+      res->bits=DECINF|DECNEG;         /* set - infinity */
+      break;}                          /* [no status to set] */
+
+    /* Non-zero negatives are bad... */
+    if (decNumberIsNegative(rhs)) {    /* -x -> error */
+      *status|=DEC_Invalid_operation;
+      break;}
+
+    /* Here, rhs is positive, finite, and in range */
+
+    /* lookaside fastpath code for ln(2) and ln(10) at common lengths */
+    if (rhs->exponent==0 && set->digits<=40) {
+      #if DECDPUN==1
+      if (rhs->lsu[0]==0 && rhs->lsu[1]==1 && rhs->digits==2) { /* ln(10) */
+      #else
+      if (rhs->lsu[0]==10 && rhs->digits==2) {                 /* ln(10) */
+      #endif
+       aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
+       #define LN10 "2.302585092994045684017991454684364207601"
+       decNumberFromString(res, LN10, &aset);
+       *status|=(DEC_Inexact | DEC_Rounded); /* is inexact */
+       break;}
+      if (rhs->lsu[0]==2 && rhs->digits==1) { /* ln(2) */
+       aset=*set; aset.round=DEC_ROUND_HALF_EVEN;
+       #define LN2 "0.6931471805599453094172321214581765680755"
+       decNumberFromString(res, LN2, &aset);
+       *status|=(DEC_Inexact | DEC_Rounded);
+       break;}
+      } /* integer and short */
+
+    /* Determine the working precision.         This is normally the */
+    /* requested precision + 2, with a minimum of 9.  However, if */
+    /* the rhs is 'over-precise' then allow for all its digits to */
+    /* potentially participate (consider an rhs where all the excess */
+    /* digits are 9s) so in this case use rhs->digits+2. */
+    p=MAXI(rhs->digits, MAXI(set->digits, 7))+2;
+
+    /* Allocate space for the accumulator and the high-precision */
+    /* adjustment calculator, if necessary.  The accumulator must */
+    /* be able to hold p digits, and the adjustment up to */
+    /* rhs->digits+p digits.  They are also made big enough for 16 */
+    /* digits so that they can be used for calculating the initial */
+    /* estimate. */
+    needbytes=sizeof(decNumber)+(D2U(MAXI(p,16))-1)*sizeof(Unit);
+    if (needbytes>sizeof(bufa)) {     /* need malloc space */
+      allocbufa=(decNumber *)malloc(needbytes);
+      if (allocbufa==NULL) {         /* hopeless -- abandon */
+       *status|=DEC_Insufficient_storage;
+       break;}
+      a=allocbufa;                   /* use the allocated space */
+      }
+    pp=p+rhs->digits;
+    needbytes=sizeof(decNumber)+(D2U(MAXI(pp,16))-1)*sizeof(Unit);
+    if (needbytes>sizeof(bufb)) {     /* need malloc space */
+      allocbufb=(decNumber *)malloc(needbytes);
+      if (allocbufb==NULL) {         /* hopeless -- abandon */
+       *status|=DEC_Insufficient_storage;
+       break;}
+      b=allocbufb;                   /* use the allocated space */
+      }
+
+    /* Prepare an initial estimate in acc. Calculate this by */
+    /* considering the coefficient of x to be a normalized fraction, */
+    /* f, with the decimal point at far left and multiplied by */
+    /* 10**r.  Then, rhs=f*10**r and 0.1<=f<1, and */
+    /*  ln(x) = ln(f) + ln(10)*r */
+    /* Get the initial estimate for ln(f) from a small lookup */
+    /* table (see above) indexed by the first two digits of f, */
+    /* truncated. */
+
+    decContextDefault(&aset, DEC_INIT_DECIMAL64); /* 16-digit extended */
+    r=rhs->exponent+rhs->digits;       /* 'normalised' exponent */
+    decNumberFromInt32(a, r);          /* a=r */
+    decNumberFromInt32(b, 2302585);    /* b=ln(10) (2.302585) */
+    b->exponent=-6;                    /*  .. */
+    decMultiplyOp(a, a, b, &aset, &ignore);  /* a=a*b */
+    /* now get top two digits of rhs into b by simple truncate and */
+    /* force to integer */
+    residue=0;                         /* (no residue) */
+    aset.digits=2; aset.round=DEC_ROUND_DOWN;
+    decCopyFit(b, rhs, &aset, &residue, &ignore); /* copy & shorten */
+    b->exponent=0;                     /* make integer */
+    t=decGetInt(b);                    /* [cannot fail] */
+    if (t<10) t=X10(t);                        /* adjust single-digit b */
+    t=LNnn[t-10];                      /* look up ln(b) */
+    decNumberFromInt32(b, t>>2);       /* b=ln(b) coefficient */
+    b->exponent=-(t&3)-3;              /* set exponent */
+    b->bits=DECNEG;                    /* ln(0.10)->ln(0.99) always -ve */
+    aset.digits=16; aset.round=DEC_ROUND_HALF_EVEN; /* restore */
+    decAddOp(a, a, b, &aset, 0, &ignore); /* acc=a+b */
+    /* 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 */
+    /* will approach it from below, avoiding overflow when calling exp. */
+
+    decNumberZero(&numone); *numone.lsu=1;   /* constant 1 for adjustment */
+
+    /* accumulator bounds are as requested (could underflow, but */
+    /* cannot overflow) */
+    aset.emax=set->emax;
+    aset.emin=set->emin;
+    aset.clamp=0;                      /* no concrete format */
+    /* set up a context to be used for the multiply and subtract */
+    bset=aset;
+    bset.emax=DEC_MAX_MATH*2;          /* use double bounds for the */
+    bset.emin=-DEC_MAX_MATH*2;         /* adjustment calculation */
+                                       /* [see decExpOp call below] */
+    /* for each iteration double the number of digits to calculate, */
+    /* up to a maximum of p */
+    pp=9;                              /* initial precision */
+    /* [initially 9 as then the sequence starts 7+2, 16+2, and */
+    /* 34+2, which is ideal for standard-sized numbers] */
+    aset.digits=pp;                    /* working context */
+    bset.digits=pp+rhs->digits;                /* wider context */
+    for (;;) {                         /* iterate */
+      #if DECCHECK
+      iterations++;
+      if (iterations>24) break;                /* consider 9 * 2**24 */
+      #endif
+      /* calculate the adjustment (exp(-a)*x-1) into b.         This is a */
+      /* catastrophic subtraction but it really is the difference */
+      /* from 1 that is of interest. */
+      /* Use the internal entry point to Exp as it allows the double */
+      /* range for calculating exp(-a) when a is the tiniest subnormal. */
+      a->bits^=DECNEG;                 /* make -a */
+      decExpOp(b, a, &bset, &ignore);  /* b=exp(-a) */
+      a->bits^=DECNEG;                 /* restore sign of a */
+      /* now multiply by rhs and subtract 1, at the wider precision */
+      decMultiplyOp(b, b, rhs, &bset, &ignore);               /* b=b*rhs */
+      decAddOp(b, b, &numone, &bset, DECNEG, &ignore); /* b=b-1 */
+
+      /* the iteration ends when the adjustment cannot affect the */
+      /* result by >=0.5 ulp (at the requested digits), which */
+      /* is when its value is smaller than the accumulator by */
+      /* set->digits+1 digits (or it is zero) -- this is a looser */
+      /* requirement than for Exp because all that happens to the */
+      /* accumulator after this is the final rounding (but note that */
+      /* there must also be full precision in a, or a=0). */
+
+      if (decNumberIsZero(b) ||
+         (a->digits+a->exponent)>=(b->digits+b->exponent+set->digits+1)) {
+       if (a->digits==p) break;
+       if (decNumberIsZero(a)) {
+         decCompareOp(&cmp, rhs, &numone, &aset, COMPARE, &ignore); /* rhs=1 ? */
+         if (cmp.lsu[0]==0) a->exponent=0;            /* yes, exact 0 */
+          else *status|=(DEC_Inexact | DEC_Rounded);  /* no, inexact */
+         break;
+         }
+       /* force padding if adjustment has gone to 0 before full length */
+       if (decNumberIsZero(b)) b->exponent=a->exponent-p;
+       }
+
+      /* not done yet ... */
+      decAddOp(a, a, b, &aset, 0, &ignore);  /* a=a+b for next estimate */
+      if (pp==p) continue;                  /* precision is at maximum */
+      /* lengthen the next calculation */
+      pp=pp*2;                              /* double precision */
+      if (pp>p) pp=p;                       /* clamp to maximum */
+      aset.digits=pp;                       /* working context */
+      bset.digits=pp+rhs->digits;           /* wider context */
+      } /* Newton's iteration */
+
+    #if DECCHECK
+    /* just a sanity check; remove the test to show always */
+    if (iterations>24)
+      printf("Ln iterations=%ld, status=%08lx, p=%ld, d=%ld\n",
+           iterations, *status, p, rhs->digits);
+    #endif
+
+    /* Copy and round the result to res */
+    residue=1;                         /* indicate dirt to right */
+    if (ISZERO(a)) residue=0;          /* .. unless underflowed to 0 */
+    aset.digits=set->digits;           /* [use default rounding] */
+    decCopyFit(res, a, &aset, &residue, status); /* copy & shorten */
+    decFinish(res, set, &residue, status);      /* cleanup/set flags */
+    } while(0);                                /* end protected */
+
+  if (allocbufa!=NULL) free(allocbufa); /* drop any storage used */
+  if (allocbufb!=NULL) free(allocbufb); /* .. */
+  /* [status is handled by caller] */
+  return res;
+  } /* decLnOp */
 
 /* ------------------------------------------------------------------ */
-/* decQuantizeOp  -- force exponent to requested value                */
-/*                                                                    */
+/* decQuantizeOp  -- force exponent to requested value               */
+/*                                                                   */
 /*   This computes C = op(A, B), where op adjusts the coefficient     */
 /*   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 */
-/*   any rounding that occurred.                                      */
-/*                                                                    */
-/*   res is C, the result.  C may be A or B                           */
-/*   lhs is A, the number to adjust                                   */
-/*   rhs is B, the requested exponent                                 */
-/*   set is the context                                               */
-/*   quant is 1 for quantize or 0 for rescale                         */
+/*   any rounding that occurred.                                     */
+/*                                                                   */
+/*   res is C, the result.  C may be A or B                          */
+/*   lhs is A, the number to adjust                                  */
+/*   rhs is B, the requested exponent                                */
+/*   set is the context                                                      */
+/*   quant is 1 for quantize or 0 for rescale                        */
 /*   status is the status accumulator (this can be called without     */
-/*          risk of control loss)                                     */
-/*                                                                    */
-/* C must have space for set->digits digits.                          */
-/*                                                                    */
+/*         risk of control loss)                                     */
+/*                                                                   */
+/* C must have space for set->digits digits.                         */
+/*                                                                   */
 /* Unless there is an error or the result is infinite, the exponent   */
-/* after the operation is guaranteed to be that requested.            */
-/* ------------------------------------------------------------------ */
-static decNumber *
-decQuantizeOp (decNumber * res, const decNumber * lhs,
-              const decNumber * rhs, decContext * set, Flag quant, uInt * status)
-{
-  decNumber *alloclhs = NULL;  /* non-NULL if rounded lhs allocated */
-  decNumber *allocrhs = NULL;  /* .., rhs */
-  const decNumber *inrhs = rhs;        /* save original rhs */
-  Int reqdigits = set->digits; /* requested DIGITS */
-  Int reqexp;                  /* requested exponent [-scale] */
-  Int residue = 0;             /* rounding residue */
-  uByte merged;                        /* merged flags */
-  Int etiny = set->emin - (set->digits - 1);
-
-#if DECCHECK
-  if (decCheckOperands (res, lhs, rhs, set))
-    return res;
-#endif
-
-  do
-    {                          /* protect allocated storage */
-#if DECSUBSET
-      if (!set->extended)
-       {
-         /* reduce operands and set lostDigits status, as needed */
-         if (lhs->digits > reqdigits)
-           {
-             alloclhs = decRoundOperand (lhs, set, status);
-             if (alloclhs == NULL)
-               break;
-             lhs = alloclhs;
-           }
-         if (rhs->digits > reqdigits)
-           {                   /* [this only checks lostDigits] */
-             allocrhs = decRoundOperand (rhs, set, status);
-             if (allocrhs == NULL)
-               break;
-             rhs = allocrhs;
-           }
-       }
-#endif
-      /* [following code does not require input rounding] */
-
-      /* Handle special values */
-      merged = (lhs->bits | rhs->bits) & DECSPECIAL;
-      if ((lhs->bits | rhs->bits) & DECSPECIAL)
-       {
-         /* NaNs get usual processing */
-         if (merged & (DECSNAN | DECNAN))
-           decNaNs (res, lhs, rhs, status);
-         /* one infinity but not both is bad */
-         else if ((lhs->bits ^ rhs->bits) & DECINF)
-           *status |= DEC_Invalid_operation;
-         /* both infinity: return lhs */
-         else
-           decNumberCopy (res, lhs);   /* [nop if in place] */
-         break;
+/* after the operation is guaranteed to be that requested.           */
+/* ------------------------------------------------------------------ */
+static decNumber * decQuantizeOp(decNumber *res, const decNumber *lhs,
+                                const decNumber *rhs, decContext *set,
+                                Flag quant, uInt *status) {
+  #if DECSUBSET
+  decNumber *alloclhs=NULL;       /* non-NULL if rounded lhs allocated */
+  decNumber *allocrhs=NULL;       /* .., rhs */
+  #endif
+  const decNumber *inrhs=rhs;     /* save original rhs */
+  Int  reqdigits=set->digits;     /* requested DIGITS */
+  Int  reqexp;                    /* requested exponent [-scale] */
+  Int  residue=0;                 /* rounding residue */
+  Int  etiny=set->emin-(reqdigits-1);
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  do {                            /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operands and set lostDigits status, as needed */
+      if (lhs->digits>reqdigits) {
+       alloclhs=decRoundOperand(lhs, set, status);
+       if (alloclhs==NULL) break;
+       lhs=alloclhs;
        }
-
-      /* set requested exponent */
-      if (quant)
-       reqexp = inrhs->exponent;       /* quantize -- match exponents */
-      else
-       {                       /* rescale -- use value of rhs */
-         /* Original rhs must be an integer that fits and is in range */
-#if DECSUBSET
-         reqexp = decGetInt (inrhs, set);
-#else
-         reqexp = decGetInt (inrhs);
-#endif
+      if (rhs->digits>reqdigits) { /* [this only checks lostDigits] */
+       allocrhs=decRoundOperand(rhs, set, status);
+       if (allocrhs==NULL) break;
+       rhs=allocrhs;
        }
+      }
+    #endif
+    /* [following code does not require input rounding] */
+
+    /* Handle special values */
+    if (SPECIALARGS) {
+      /* NaNs get usual processing */
+      if (SPECIALARGS & (DECSNAN | DECNAN))
+       decNaNs(res, lhs, rhs, set, status);
+      /* one infinity but not both is bad */
+      else if ((lhs->bits ^ rhs->bits) & DECINF)
+       *status|=DEC_Invalid_operation;
+      /* both infinity: return lhs */
+      else decNumberCopy(res, lhs);         /* [nop if in place] */
+      break;
+      }
 
-#if DECSUBSET
-      if (!set->extended)
-       etiny = set->emin;      /* no subnormals */
-#endif
+    /* set requested exponent */
+    if (quant) reqexp=inrhs->exponent; /* quantize -- match exponents */
+     else {                            /* rescale -- use value of rhs */
+      /* Original rhs must be an integer that fits and is in range, */
+      /* which could be from -1999999997 to +999999999, thanks to */
+      /* subnormals */
+      reqexp=decGetInt(inrhs);              /* [cannot fail] */
+      }
 
-      if (reqexp == BADINT     /* bad (rescale only) or .. */
-         || (reqexp < etiny)   /* < lowest */
-         || (reqexp > set->emax))
-       {                       /* > Emax */
-         *status |= DEC_Invalid_operation;
-         break;
+    #if DECSUBSET
+    if (!set->extended) etiny=set->emin;     /* no subnormals */
+    #endif
+
+    if (reqexp==BADINT                      /* bad (rescale only) or .. */
+     || reqexp==BIGODD || reqexp==BIGEVEN    /* very big (ditto) or .. */
+     || (reqexp<etiny)                      /* < lowest */
+     || (reqexp>set->emax)) {               /* > emax */
+      *status|=DEC_Invalid_operation;
+      break;}
+
+    /* the RHS has been processed, so it can be overwritten now if necessary */
+    if (ISZERO(lhs)) {                      /* zero coefficient unchanged */
+      decNumberCopy(res, lhs);              /* [nop if in place] */
+      res->exponent=reqexp;                 /* .. just set exponent */
+      #if DECSUBSET
+      if (!set->extended) res->bits=0;      /* subset specification; no -0 */
+      #endif
+      }
+     else {                                 /* non-zero lhs */
+      Int adjust=reqexp-lhs->exponent;      /* digit adjustment needed */
+      /* if adjusted coefficient will definitely not fit, give up now */
+      if ((lhs->digits-adjust)>reqdigits) {
+       *status|=DEC_Invalid_operation;
+       break;
        }
 
-      /* we've processed the RHS, so we can overwrite it now if necessary */
-      if (ISZERO (lhs))
-       {                       /* zero coefficient unchanged */
-         decNumberCopy (res, lhs);     /* [nop if in place] */
-         res->exponent = reqexp;       /* .. just set exponent */
-#if DECSUBSET
-         if (!set->extended)
-           res->bits = 0;      /* subset specification; no -0 */
-#endif
-       }
-      else
-       {                       /* non-zero lhs */
-         Int adjust = reqexp - lhs->exponent;  /* digit adjustment needed */
-         /* if adjusted coefficient will not fit, give up now */
-         if ((lhs->digits - adjust) > reqdigits)
-           {
-             *status |= DEC_Invalid_operation;
-             break;
+      if (adjust>0) {                       /* increasing exponent */
+       /* this will decrease the length of the coefficient by adjust */
+       /* digits, and must round as it does so */
+       decContext workset;                  /* work */
+       workset=*set;                        /* clone rounding, etc. */
+       workset.digits=lhs->digits-adjust;   /* set requested length */
+       /* [note that the latter can be <1, here] */
+       decCopyFit(res, lhs, &workset, &residue, status); /* fit to result */
+       decApplyRound(res, &workset, residue, status);    /* .. and round */
+       residue=0;                                        /* [used] */
+       /* If just rounded a 999s case, exponent will be off by one; */
+       /* adjust back (after checking space), if so. */
+       if (res->exponent>reqexp) {
+         /* re-check needed, e.g., for quantize(0.9999, 0.001) under */
+         /* set->digits==3 */
+         if (res->digits==reqdigits) {      /* cannot shift by 1 */
+           *status&=~(DEC_Inexact | DEC_Rounded); /* [clean these] */
+           *status|=DEC_Invalid_operation;
+           break;
            }
+         res->digits=decShiftToMost(res->lsu, res->digits, 1); /* shift */
+         res->exponent--;                   /* (re)adjust the exponent. */
+         }
+       #if DECSUBSET
+       if (ISZERO(res) && !set->extended) res->bits=0; /* subset; no -0 */
+       #endif
+       } /* increase */
+       else /* adjust<=0 */ {               /* decreasing or = exponent */
+       /* this will increase the length of the coefficient by -adjust */
+       /* digits, by adding zero or more trailing zeros; this is */
+       /* already checked for fit, above */
+       decNumberCopy(res, lhs);             /* [it will fit] */
+       /* if padding needed (adjust<0), add it now... */
+       if (adjust<0) {
+         res->digits=decShiftToMost(res->lsu, res->digits, -adjust);
+         res->exponent+=adjust;             /* adjust the exponent */
+         }
+       } /* decrease */
+      } /* non-zero */
 
-         if (adjust > 0)
-           {                   /* increasing exponent */
-             /* this will decrease the length of the coefficient by adjust */
-             /* digits, and must round as it does so */
-             decContext workset;       /* work */
-             workset = *set;   /* clone rounding, etc. */
-             workset.digits = lhs->digits - adjust;    /* set requested length */
-             /* [note that the latter can be <1, here] */
-             decCopyFit (res, lhs, &workset, &residue, status);        /* fit to result */
-             decApplyRound (res, &workset, residue, status);   /* .. and round */
-             residue = 0;      /* [used] */
-             /* If we rounded a 999s case, exponent will be off by one; */
-             /* adjust back if so. */
-             if (res->exponent > reqexp)
-               {
-                 res->digits = decShiftToMost (res->lsu, res->digits, 1);      /* shift */
-                 res->exponent--;      /* (re)adjust the exponent. */
-               }
-#if DECSUBSET
-             if (ISZERO (res) && !set->extended)
-               res->bits = 0;  /* subset; no -0 */
-#endif
-           }                   /* increase */
-         else                  /* adjust<=0 */
-           {                   /* decreasing or = exponent */
-             /* this will increase the length of the coefficient by -adjust */
-             /* digits, by adding trailing zeros. */
-             decNumberCopy (res, lhs); /* [it will fit] */
-             /* if padding needed (adjust<0), add it now... */
-             if (adjust < 0)
-               {
-                 res->digits =
-                   decShiftToMost (res->lsu, res->digits, -adjust);
-                 res->exponent += adjust;      /* adjust the exponent */
-               }
-           }                   /* decrease */
-       }                       /* non-zero */
-
-      /* Check for overflow [do not use Finalize in this case, as an */
-      /* overflow here is a "don't fit" situation] */
-      if (res->exponent > set->emax - res->digits + 1)
-       {                       /* too big */
-         *status |= DEC_Invalid_operation;
-         break;
-       }
-      else
-       {
-         decFinalize (res, set, &residue, status);     /* set subnormal flags */
-         *status &= ~DEC_Underflow;    /* suppress Underflow [754r] */
-       }
-    }
-  while (0);                   /* end protected */
+    /* Check for overflow [do not use Finalize in this case, as an */
+    /* overflow here is a "don't fit" situation] */
+    if (res->exponent>set->emax-res->digits+1) {  /* too big */
+      *status|=DEC_Invalid_operation;
+      break;
+      }
+     else {
+      decFinalize(res, set, &residue, status);   /* set subnormal flags */
+      *status&=~DEC_Underflow;         /* suppress Underflow [754r] */
+      }
+    } while(0);                                /* end protected */
 
-  if (allocrhs != NULL)
-    free (allocrhs);           /* drop any storage we used */
-  if (alloclhs != NULL)
-    free (alloclhs);           /* .. */
+  #if DECSUBSET
+  if (allocrhs!=NULL) free(allocrhs);  /* drop any storage used */
+  if (alloclhs!=NULL) free(alloclhs);  /* .. */
+  #endif
   return res;
-}
-
-/* ------------------------------------------------------------------ */
-/* decCompareOp -- compare, min, or max two Numbers                   */
-/*                                                                    */
-/*   This computes C = A ? B and returns the signum (as a Number)     */
-/*   for COMPARE or the maximum or minimum (for COMPMAX and COMPMIN). */
-/*                                                                    */
-/*   res is C, the result.  C may be A and/or B (e.g., X=X?X)         */
-/*   lhs is A                                                         */
-/*   rhs is B                                                         */
-/*   set is the context                                               */
-/*   op  is the operation flag                                        */
-/*   status is the usual accumulator                                  */
-/*                                                                    */
+  } /* decQuantizeOp */
+
+/* ------------------------------------------------------------------ */
+/* decCompareOp -- compare, min, or max two Numbers                  */
+/*                                                                   */
+/*   This computes C = A ? B and carries out one of four operations:  */
+/*     COMPARE   -- returns the signum (as a number) giving the      */
+/*                  result of a comparison unless one or both        */
+/*                  operands is a NaN (in which case a NaN results)  */
+/*     COMPSIG   -- as COMPARE except that a quiet NaN raises        */
+/*                  Invalid operation.                               */
+/*     COMPMAX   -- returns the larger of the operands, using the    */
+/*                  754r maxnum operation                            */
+/*     COMPMAXMAG -- ditto, comparing absolute values                */
+/*     COMPMIN   -- the 754r minnum operation                        */
+/*     COMPMINMAG -- ditto, comparing absolute values                */
+/*     COMTOTAL          -- returns the signum (as a number) giving the      */
+/*                  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)        */
+/*   lhs is A                                                        */
+/*   rhs is B                                                        */
+/*   set is the context                                                      */
+/*   op         is the operation flag                                        */
+/*   status is the usual accumulator                                 */
+/*                                                                   */
 /* C must have space for one digit for COMPARE or set->digits for     */
-/* COMPMAX and COMPMIN.                                               */
-/* ------------------------------------------------------------------ */
-/* The emphasis here is on speed for common cases, and avoiding       */
-/* coefficient comparison if possible.                                */
-/* ------------------------------------------------------------------ */
-decNumber *
-decCompareOp (decNumber * res, const decNumber * lhs, const decNumber * rhs,
-             decContext * set, Flag op, uInt * status)
-{
-  decNumber *alloclhs = NULL;  /* non-NULL if rounded lhs allocated */
-  decNumber *allocrhs = NULL;  /* .., rhs */
-  Int result = 0;              /* default result value */
-  uByte merged;                        /* merged flags */
-  uByte bits = 0;              /* non-0 for NaN */
-
-#if DECCHECK
-  if (decCheckOperands (res, lhs, rhs, set))
-    return res;
-#endif
-
-  do
-    {                          /* protect allocated storage */
-#if DECSUBSET
-      if (!set->extended)
-       {
-         /* reduce operands and set lostDigits status, as needed */
-         if (lhs->digits > set->digits)
-           {
-             alloclhs = decRoundOperand (lhs, set, status);
-             if (alloclhs == NULL)
-               {
-                 result = BADINT;
-                 break;
-               }
-             lhs = alloclhs;
-           }
-         if (rhs->digits > set->digits)
-           {
-             allocrhs = decRoundOperand (rhs, set, status);
-             if (allocrhs == NULL)
-               {
-                 result = BADINT;
-                 break;
-               }
-             rhs = allocrhs;
-           }
+/* COMPMAX, COMPMIN, COMPMAXMAG, or COMPMINMAG.                              */
+/* ------------------------------------------------------------------ */
+/* The emphasis here is on speed for common cases, and avoiding              */
+/* coefficient comparison if possible.                               */
+/* ------------------------------------------------------------------ */
+decNumber * decCompareOp(decNumber *res, const decNumber *lhs,
+                        const decNumber *rhs, decContext *set,
+                        Flag op, uInt *status) {
+  #if DECSUBSET
+  decNumber *alloclhs=NULL;       /* non-NULL if rounded lhs allocated */
+  decNumber *allocrhs=NULL;       /* .., rhs */
+  #endif
+  Int  result=0;                  /* default result value */
+  uByte merged;                           /* work */
+
+  #if DECCHECK
+  if (decCheckOperands(res, lhs, rhs, set)) return res;
+  #endif
+
+  do {                            /* protect allocated storage */
+    #if DECSUBSET
+    if (!set->extended) {
+      /* reduce operands and set lostDigits status, as needed */
+      if (lhs->digits>set->digits) {
+       alloclhs=decRoundOperand(lhs, set, status);
+       if (alloclhs==NULL) {result=BADINT; break;}
+       lhs=alloclhs;
        }
-#endif
-      /* [following code does not require input rounding] */
-
-      /* handle NaNs now; let infinities drop through */
-      /* +++ review sNaN handling with 754r, for now assumes sNaN */
-      /* (even just one) leads to NaN. */
-      merged = (lhs->bits | rhs->bits) & (DECSNAN | DECNAN);
-      if (merged)
-       {                       /* a NaN bit set */
-         if (op == COMPARE);
-         else if (merged & DECSNAN);
-         else
-           {                   /* 754r rules for MIN and MAX ignore single NaN */
-             /* here if MIN or MAX, and one or two quiet NaNs */
-             if (lhs->bits & rhs->bits & DECNAN);
-             else
-               {               /* just one quiet NaN */
-                 /* force choice to be the non-NaN operand */
-                 op = COMPMAX;
-                 if (lhs->bits & DECNAN)
-                   result = -1;        /* pick rhs */
-                 else
-                   result = +1;        /* pick lhs */
-                 break;
-               }
-           }
-         op = COMPNAN;         /* use special path */
-         decNaNs (res, lhs, rhs, status);
-         break;
+      if (rhs->digits>set->digits) {
+       allocrhs=decRoundOperand(rhs, set, status);
+       if (allocrhs==NULL) {result=BADINT; break;}
+       rhs=allocrhs;
        }
+      }
+    #endif
+    /* [following code does not require input rounding] */
 
-      result = decCompare (lhs, rhs);  /* we have numbers */
-    }
-  while (0);                   /* end protected */
-
-  if (result == BADINT)
-    *status |= DEC_Insufficient_storage;       /* rare */
-  else
-    {
-      if (op == COMPARE)
-       {                       /* return signum */
-         decNumberZero (res);  /* [always a valid result] */
-         if (result == 0)
-           res->bits = bits;   /* (maybe qNaN) */
-         else
-           {
-             *res->lsu = 1;
-             if (result < 0)
-               res->bits = DECNEG;
-           }
+    /* If total ordering then handle differing signs 'up front' */
+    if (op==COMPTOTAL) {               /* total ordering */
+      if (decNumberIsNegative(lhs) & !decNumberIsNegative(rhs)) {
+       result=-1;
+       break;
        }
-      else if (op == COMPNAN); /* special, drop through */
-      else
-       {                       /* MAX or MIN, non-NaN result */
-         Int residue = 0;      /* rounding accumulator */
-         /* choose the operand for the result */
-         const decNumber *choice;
-         if (result == 0)
-           {                   /* operands are numerically equal */
-             /* choose according to sign then exponent (see 754r) */
-             uByte slhs = (lhs->bits & DECNEG);
-             uByte srhs = (rhs->bits & DECNEG);
-#if DECSUBSET
-             if (!set->extended)
-               {               /* subset: force left-hand */
-                 op = COMPMAX;
-                 result = +1;
-               }
-             else
-#endif
-             if (slhs != srhs)
-               {               /* signs differ */
-                 if (slhs)
-                   result = -1;        /* rhs is max */
-                 else
-                   result = +1;        /* lhs is max */
-               }
-             else if (slhs && srhs)
-               {               /* both negative */
-                 if (lhs->exponent < rhs->exponent)
-                   result = +1;
-                 else
-                   result = -1;
-                 /* [if equal, we use lhs, technically identical] */
-               }
-             else
-               {               /* both positive */
-                 if (lhs->exponent > rhs->exponent)
-                   result = +1;
-                 else
-                   result = -1;
-                 /* [ditto] */
-               }
-           }                   /* numerically equal */
-         /* here result will be non-0 */
-         if (op == COMPMIN)
-           result = -result;   /* reverse if looking for MIN */
-         choice = (result > 0 ? lhs : rhs);    /* choose */
-         /* copy chosen to result, rounding if need be */
-         decCopyFit (res, choice, set, &residue, status);
-         decFinish (res, set, &residue, status);
+      if (!decNumberIsNegative(lhs) & decNumberIsNegative(rhs)) {
+       result=+1;
+       break;
        }
+      }
+
+    /* handle NaNs specially; let infinities drop through */
+    /* This assumes sNaN (even just one) leads to NaN. */
+    merged=(lhs->bits | rhs->bits) & (DECSNAN | DECNAN);
+    if (merged) {                      /* a NaN bit set */
+      if (op==COMPARE);                        /* result will be NaN */
+       else if (op==COMPSIG)           /* treat qNaN as sNaN */
+       *status|=DEC_Invalid_operation | DEC_sNaN;
+       else if (op==COMPTOTAL) {       /* total ordering, always finite */
+       /* signs are known to be the same; compute the ordering here */
+       /* as if the signs are both positive, then invert for negatives */
+       if (!decNumberIsNaN(lhs)) result=-1;
+        else if (!decNumberIsNaN(rhs)) result=+1;
+        /* here if both NaNs */
+        else if (decNumberIsSNaN(lhs) && decNumberIsQNaN(rhs)) result=-1;
+        else if (decNumberIsQNaN(lhs) && decNumberIsSNaN(rhs)) result=+1;
+        else { /* both NaN or both sNaN */
+         /* now it just depends on the payload */
+         result=decUnitCompare(lhs->lsu, D2U(lhs->digits),
+                               rhs->lsu, D2U(rhs->digits), 0);
+         /* [Error not possible, as these are 'aligned'] */
+         } /* both same NaNs */
+       if (decNumberIsNegative(lhs)) result=-result;
+       break;
+       } /* total order */
+
+       else if (merged & DECSNAN);          /* sNaN -> qNaN */
+       else { /* here if MIN or MAX and one or two quiet NaNs */
+       /* min or max -- 754r rules ignore single NaN */
+       if (!decNumberIsNaN(lhs) || !decNumberIsNaN(rhs)) {
+         /* just one NaN; force choice to be the non-NaN operand */
+         op=COMPMAX;
+         if (lhs->bits & DECNAN) result=-1; /* pick rhs */
+                            else result=+1; /* pick lhs */
+         break;
+         }
+       } /* max or min */
+      op=COMPNAN;                           /* use special path */
+      decNaNs(res, lhs, rhs, set, status);   /* propagate NaN */
+      break;
+      }
+    /* have numbers */
+    if (op==COMPMAXMAG || op==COMPMINMAG) result=decCompare(lhs, rhs, 1);
+     else result=decCompare(lhs, rhs, 0);    /* sign matters */
+    } while(0);                                     /* end protected */
+
+  if (result==BADINT) *status|=DEC_Insufficient_storage; /* rare */
+   else {
+    if (op==COMPARE || op==COMPSIG ||op==COMPTOTAL) { /* returning signum */
+      if (op==COMPTOTAL && result==0) {
+       /* operands are numerically equal or same NaN (and same sign, */
+       /* tested first); if identical, leave result 0 */
+       if (lhs->exponent!=rhs->exponent) {
+         if (lhs->exponent<rhs->exponent) result=-1;
+          else result=+1;
+         if (decNumberIsNegative(lhs)) result=-result;
+         } /* lexp!=rexp */
+       } /* total-order by exponent */
+      decNumberZero(res);              /* [always a valid result] */
+      if (result!=0) {                 /* must be -1 or +1 */
+       *res->lsu=1;
+       if (result<0) res->bits=DECNEG;
+       }
+      }
+     else if (op==COMPNAN);            /* special, drop through */
+     else {                            /* MAX or MIN, non-NaN result */
+      Int residue=0;                   /* rounding accumulator */
+      /* choose the operand for the result */
+      const decNumber *choice;
+      if (result==0) { /* operands are numerically equal */
+       /* choose according to sign then exponent (see 754r) */
+       uByte slhs=(lhs->bits & DECNEG);
+       uByte srhs=(rhs->bits & DECNEG);
+       #if DECSUBSET
+       if (!set->extended) {           /* subset: force left-hand */
+         op=COMPMAX;
+         result=+1;
+         }
+       else
+       #endif
+       if (slhs!=srhs) {          /* signs differ */
+         if (slhs) result=-1;     /* rhs is max */
+              else result=+1;     /* lhs is max */
+         }
+        else if (slhs && srhs) {  /* both negative */
+         if (lhs->exponent<rhs->exponent) result=+1;
+                                     else result=-1;
+         /* [if equal, use lhs, technically identical] */
+         }
+        else {                    /* both positive */
+         if (lhs->exponent>rhs->exponent) result=+1;
+                                     else result=-1;
+         /* [ditto] */
+         }
+       } /* numerically equal */
+      /* here result will be non-0; reverse if looking for MIN */
+      if (op==COMPMIN || op==COMPMINMAG) result=-result;
+      choice=(result>0 ? lhs : rhs);   /* choose */
+      /* copy chosen to result, rounding if need be */
+      decCopyFit(res, choice, set, &residue, status);
+      decFinish(res, set, &residue, status);
+      }
     }
-  if (allocrhs != NULL)
-    free (allocrhs);           /* free any storage we used */
-  if (alloclhs != NULL)
-    free (alloclhs);           /* .. */
+  #if DECSUBSET
+  if (allocrhs!=NULL) free(allocrhs);  /* free any storage used */
+  if (alloclhs!=NULL) free(alloclhs);  /* .. */
+  #endif
   return res;
-}
+  } /* decCompareOp */
 
 /* ------------------------------------------------------------------ */
-/* decCompare -- compare two decNumbers by numerical value            */
-/*                                                                    */
-/*  This routine compares A ? B without altering them.                */
-/*                                                                    */
-/*  Arg1 is A, a decNumber which is not a NaN                         */
-/*  Arg2 is B, a decNumber which is not a NaN                         */
-/*                                                                    */
+/* decCompare -- compare two decNumbers by numerical value           */
+/*                                                                   */
+/*  This routine compares A ? B without altering them.               */
+/*                                                                   */
+/*  Arg1 is A, 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            */
+/*                                                                   */
 /*  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)                */
-/* ------------------------------------------------------------------ */
-/* This could be merged into decCompareOp */
-static Int
-decCompare (const decNumber * lhs, const decNumber * rhs)
-{
-  Int result;                  /* result value */
-  Int sigr;                    /* rhs signum */
-  Int compare;                 /* work */
-  result = 1;                  /* assume signum(lhs) */
-  if (ISZERO (lhs))
-    result = 0;
-  else if (decNumberIsNegative (lhs))
-    result = -1;
-  sigr = 1;                    /* compute signum(rhs) */
-  if (ISZERO (rhs))
-    sigr = 0;
-  else if (decNumberIsNegative (rhs))
-    sigr = -1;
-  if (result > sigr)
-    return +1;                 /* L > R, return 1 */
-  if (result < sigr)
-    return -1;                 /* R < L, return -1 */
-
-  /* signums are the same */
-  if (result == 0)
-    return 0;                  /* both 0 */
-  /* Both non-zero */
-  if ((lhs->bits | rhs->bits) & DECINF)
-    {                          /* one or more infinities */
-      if (lhs->bits == rhs->bits)
-       result = 0;             /* both the same */
-      else if (decNumberIsInfinite (rhs))
-       result = -result;
-      return result;
+/*  (the only possible failure is an allocation error)               */
+/* ------------------------------------------------------------------ */
+static Int decCompare(const decNumber *lhs, const decNumber *rhs,
+                     Flag abs) {
+  Int  result;                    /* result value */
+  Int  sigr;                      /* rhs signum */
+  Int  compare;                   /* work */
+
+  result=1;                                 /* assume signum(lhs) */
+  if (ISZERO(lhs)) result=0;
+  if (abs) {
+    if (ISZERO(rhs)) return result;         /* LHS wins or both 0 */
+    /* RHS is non-zero */
+    if (result==0) return -1;               /* LHS is 0; RHS wins */
+    /* [here, both non-zero, result=1] */
     }
-
-  /* we must compare the coefficients, allowing for exponents */
-  if (lhs->exponent > rhs->exponent)
-    {                          /* LHS exponent larger */
-      /* swap sides, and sign */
-      const decNumber *temp = lhs;
-      lhs = rhs;
-      rhs = temp;
-      result = -result;
+   else {                                   /* signs matter */
+    if (result && decNumberIsNegative(lhs)) result=-1;
+    sigr=1;                                 /* compute signum(rhs) */
+    if (ISZERO(rhs)) sigr=0;
+     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==0) return 0;                  /* both 0 */
     }
 
-  compare = decUnitCompare (lhs->lsu, D2U (lhs->digits),
-                           rhs->lsu, D2U (rhs->digits),
-                           rhs->exponent - lhs->exponent);
-
-  if (compare != BADINT)
-    compare *= result;         /* comparison succeeded */
-  return compare;              /* what we got */
-}
+  /* signums are the same; both are non-zero */
+  if ((lhs->bits | rhs->bits) & DECINF) {    /* one or more infinities */
+    if (decNumberIsInfinite(rhs)) {
+      if (decNumberIsInfinite(lhs)) result=0;/* both infinite */
+       else result=-result;                 /* only rhs infinite */
+      }
+    return result;
+    }
+  /* must compare the coefficients, allowing for exponents */
+  if (lhs->exponent>rhs->exponent) {        /* LHS exponent larger */
+    /* swap sides, and sign */
+    const decNumber *temp=lhs;
+    lhs=rhs;
+    rhs=temp;
+    result=-result;
+    }
+  compare=decUnitCompare(lhs->lsu, D2U(lhs->digits),
+                        rhs->lsu, D2U(rhs->digits),
+                        rhs->exponent-lhs->exponent);
+  if (compare!=BADINT) compare*=result;             /* comparison succeeded */
+  return compare;
+  } /* 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   */
-/*  A is a plain integer                                              */
-/*  B has an exponent of E (which must be non-negative)               */
-/*                                                                    */
-/*  Arg1 is A first Unit (lsu)                                        */
-/*  Arg2 is A length in Units                                         */
-/*  Arg3 is B first Unit (lsu)                                        */
-/*  Arg4 is B length in Units                                         */
-/*  Arg5 is E                                                         */
-/*                                                                    */
+/*  A is a plain integer                                             */
+/*  B has an exponent of E (which must be non-negative)                      */
+/*                                                                   */
+/*  Arg1 is A first Unit (lsu)                                       */
+/*  Arg2 is A length in Units                                        */
+/*  Arg3 is B first Unit (lsu)                                       */
+/*  Arg4 is B length in Units                                        */
+/*  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   */
-/*  (the only possible failure is an allocation error)                */
-/* ------------------------------------------------------------------ */
-static Int
-decUnitCompare (const Unit * a, Int alength, const Unit * b, Int blength, Int exp)
-{
-  Unit *acc;                   /* accumulator for result */
-  Unit accbuff[D2U (DECBUFFER + 1)];   /* local buffer */
-  Unit *allocacc = NULL;       /* -> allocated acc buffer, iff allocated */
-  Int accunits, need;          /* units in use or needed for acc */
-  const Unit *l, *r, *u;       /* work */
-  Int expunits, exprem, result;        /* .. */
-
-  if (exp == 0)
-    {                          /* aligned; fastpath */
-      if (alength > blength)
-       return 1;
-      if (alength < blength)
-       return -1;
-      /* same number of units in both -- need unit-by-unit compare */
-      l = a + alength - 1;
-      r = b + alength - 1;
-      for (; l >= a; l--, r--)
-       {
-         if (*l > *r)
-           return 1;
-         if (*l < *r)
-           return -1;
-       }
-      return 0;                        /* all units match */
-    }                          /* aligned */
-
-  /* Unaligned.  If one is >1 unit longer than the other, padded */
-  /* approximately, then we can return easily */
-  if (alength > blength + (Int) D2U (exp))
-    return 1;
-  if (alength + 1 < blength + (Int) D2U (exp))
-    return -1;
-
-  /* We need to do a real subtract.  For this, we need a result buffer */
-  /* even though we only are interested in the sign.  Its length needs */
+/*  (the only possible failure is an allocation error, which can      */
+/*  only occur if E!=0)                                                      */
+/* ------------------------------------------------------------------ */
+static Int decUnitCompare(const Unit *a, Int alength,
+                         const Unit *b, Int blength, Int exp) {
+  Unit *acc;                      /* accumulator for result */
+  Unit accbuff[SD2U(DECBUFFER*2+1)]; /* local buffer */
+  Unit *allocacc=NULL;            /* -> allocated acc buffer, iff allocated */
+  Int  accunits, need;            /* units in use or needed for acc */
+  const Unit *l, *r, *u;          /* work */
+  Int  expunits, exprem, result;  /* .. */
+
+  if (exp==0) {                           /* aligned; fastpath */
+    if (alength>blength) return 1;
+    if (alength<blength) return -1;
+    /* same number of units in both -- need unit-by-unit compare */
+    l=a+alength-1;
+    r=b+alength-1;
+    for (;l>=a; l--, r--) {
+      if (*l>*r) return 1;
+      if (*l<*r) return -1;
+      }
+    return 0;                     /* all units match */
+    } /* aligned */
+
+  /* Unaligned.         If one is >1 unit longer than the other, padded */
+  /* approximately, then can return easily */
+  if (alength>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 */
+  /* even though only the sign is of interest. Its length needs */
   /* to be the larger of alength and padded blength, +2 */
-  need = blength + D2U (exp);  /* maximum real length of B */
-  if (need < alength)
-    need = alength;
-  need += 2;
-  acc = accbuff;               /* assume use local buffer */
-  if (need * sizeof (Unit) > sizeof (accbuff))
-    {
-      allocacc = (Unit *) malloc (need * sizeof (Unit));
-      if (allocacc == NULL)
-       return BADINT;          /* hopeless -- abandon */
-      acc = allocacc;
+  need=blength+D2U(exp);               /* maximum real length of B */
+  if (need<alength) need=alength;
+  need+=2;
+  acc=accbuff;                         /* assume use local buffer */
+  if (need*sizeof(Unit)>sizeof(accbuff)) {
+    allocacc=(Unit *)malloc(need*sizeof(Unit));
+    if (allocacc==NULL) return BADINT; /* hopeless -- abandon */
+    acc=allocacc;
     }
   /* Calculate units and remainder from exponent. */
-  expunits = exp / DECDPUN;
-  exprem = exp % DECDPUN;
+  expunits=exp/DECDPUN;
+  exprem=exp%DECDPUN;
   /* subtract [A+B*(-m)] */
-  accunits = decUnitAddSub (a, alength, b, blength, expunits, acc,
-                           -(Int) powers[exprem]);
+  accunits=decUnitAddSub(a, alength, b, blength, expunits, acc,
+                        -(Int)powers[exprem]);
   /* [UnitAddSub result may have leading zeros, even on zero] */
-  if (accunits < 0)
-    result = -1;               /* negative result */
-  else
-    {                          /* non-negative result */
-      /* check units of the result before freeing any storage */
-      for (u = acc; u < acc + accunits - 1 && *u == 0;)
-       u++;
-      result = (*u == 0 ? 0 : +1);
+  if (accunits<0) result=-1;           /* negative result */
+   else {                              /* non-negative result */
+    /* check units of the result before freeing any storage */
+    for (u=acc; u<acc+accunits-1 && *u==0;) u++;
+    result=(*u==0 ? 0 : +1);
     }
   /* clean up and return the result */
-  if (allocacc != NULL)
-    free (allocacc);           /* drop any storage we used */
+  if (allocacc!=NULL) free(allocacc);  /* drop any storage used */
   return result;
-}
+  } /* decUnitCompare */
 
 /* ------------------------------------------------------------------ */
 /* decUnitAddSub -- add or subtract two >=0 integers in Unit arrays   */
-/*                                                                    */
-/*  This routine performs the calculation:                            */
-/*                                                                    */
-/*  C=A+(B*M)                                                         */
-/*                                                                    */
-/*  Where M is in the range -DECDPUNMAX through +DECDPUNMAX.          */
-/*                                                                    */
-/*  A may be shorter or longer than B.                                */
-/*                                                                    */
-/*  Leading zeros are not removed after a calculation.  The result is */
-/*  either the same length as the longer of A and B (adding any       */
+/*                                                                   */
+/*  This routine performs the calculation:                           */
+/*                                                                   */
+/*  C=A+(B*M)                                                        */
+/*                                                                   */
+/*  Where M is in the range -DECDPUNMAX through +DECDPUNMAX.         */
+/*                                                                   */
+/*  A may be shorter or longer than B.                               */
+/*                                                                   */
+/*  Leading zeros are not removed after a calculation. The result is */
+/*  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).  */
-/*                                                                    */
-/*  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 */
-/*  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  */
-/*  the calculation are referenced.                                   */
-/*                                                                    */
-/*  Arg1 is A first Unit (lsu)                                        */
-/*  Arg2 is A length in Units                                         */
-/*  Arg3 is B first Unit (lsu)                                        */
-/*  Arg4 is B length in Units                                         */
+/*  the calculation are referenced.                                  */
+/*                                                                   */
+/*  Arg1 is A first Unit (lsu)                                       */
+/*  Arg2 is A length in Units                                        */
+/*  Arg3 is B first Unit (lsu)                                       */
+/*  Arg4 is B length in Units                                        */
 /*  Arg5 is B shift in Units  (>=0; pads with 0 units if positive)    */
-/*  Arg6 is C first Unit (lsu)                                        */
-/*  Arg7 is M, the multiplier                                         */
-/*                                                                    */
+/*  Arg6 is C first Unit (lsu)                                       */
+/*  Arg7 is M, the multiplier                                        */
+/*                                                                   */
 /*  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  */
 /*  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     */
-/*  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  */
 /*  must be measured (timed) to assure no performance degradation.    */
 /*  In particular, trickery here tends to be counter-productive, as   */
 /*  increased complexity of code hurts register optimizations on      */
-/*  register-poor architectures.  Avoiding divisions is nearly        */
-/*  always a Good Idea, however.                                      */
-/*                                                                    */
+/*  register-poor architectures.  Avoiding divisions is nearly       */
+/*  always a Good Idea, however.                                     */
+/*                                                                   */
 /* Special thanks to Rick McGuire (IBM Cambridge, MA) and Dave Clark  */
 /* (IBM Warwick, UK) for some of the ideas used in this routine.      */
 /* ------------------------------------------------------------------ */
-static Int
-decUnitAddSub (const Unit * a, Int alength,
-              const Unit * b, Int blength, Int bshift, Unit * c, Int m)
-{
-  const Unit *alsu = a;                /* A lsu [need to remember it] */
-  Unit *clsu = c;              /* C ditto */
-  Unit *minC;                  /* low water mark for C */
-  Unit *maxC;                  /* high water mark for C */
-  eInt carry = 0;              /* carry integer (could be Long) */
-  Int add;                     /* work */
-#if DECDPUN==4                 /* myriadal */
-  Int est;                     /* estimated quotient */
-#endif
-
-#if DECTRACE
-  if (alength < 1 || blength < 1)
-    printf ("decUnitAddSub: alen blen m %d %d [%d]\n", alength, blength, m);
-#endif
-
-  maxC = c + alength;          /* A is usually the longer */
-  minC = c + blength;          /* .. and B the shorter */
-  if (bshift != 0)
-    {                          /* B is shifted; low As copy across */
-      minC += bshift;
-      /* if in place [common], skip copy unless there's a gap [rare] */
-      if (a == c && bshift <= alength)
-       {
-         c += bshift;
-         a += bshift;
-       }
-      else
-       for (; c < clsu + bshift; a++, c++)
-         {                     /* copy needed */
-           if (a < alsu + alength)
-             *c = *a;
-           else
-             *c = 0;
-         }
+static Int decUnitAddSub(const Unit *a, Int alength,
+                        const Unit *b, Int blength, Int bshift,
+                        Unit *c, Int m) {
+  const Unit *alsu=a;             /* A lsu [need to remember it] */
+  Unit *clsu=c;                           /* C ditto */
+  Unit *minC;                     /* low water mark for C */
+  Unit *maxC;                     /* high water mark for C */
+  eInt carry=0;                           /* carry integer (could be Long) */
+  Int  add;                       /* work */
+  #if DECDPUN<=4                  /* myriadal, millenary, etc. */
+  Int  est;                       /* estimated quotient */
+  #endif
+
+  #if DECTRACE
+  if (alength<1 || blength<1)
+    printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m);
+  #endif
+
+  maxC=c+alength;                 /* A is usually the longer */
+  minC=c+blength;                 /* .. and B the shorter */
+  if (bshift!=0) {                /* B is shifted; low As copy across */
+    minC+=bshift;
+    /* if in place [common], skip copy unless there's a gap [rare] */
+    if (a==c && bshift<=alength) {
+      c+=bshift;
+      a+=bshift;
+      }
+     else for (; c<clsu+bshift; a++, c++) {  /* copy needed */
+      if (a<alsu+alength) *c=*a;
+       else *c=0;
+      }
     }
-  if (minC > maxC)
-    {                          /* swap */
-      Unit *hold = minC;
-      minC = maxC;
-      maxC = hold;
+  if (minC>maxC) { /* swap */
+    Unit *hold=minC;
+    minC=maxC;
+    maxC=hold;
     }
 
-  /* For speed, we 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 */
   /* other of the numbers contribute. */
   /* Carry handling is the same (i.e., duplicated) in each case. */
-  for (; c < minC; c++)
-    {
-      carry += *a;
+  for (; c<minC; c++) {
+    carry+=*a;
+    a++;
+    carry+=((eInt)*b)*m;               /* [special-casing m=1/-1 */
+    b++;                               /* here is not a win] */
+    /* here carry is new Unit of digits; it could be +ve or -ve */
+    if ((ueInt)carry<=DECDPUNMAX) {    /* fastpath 0-DECDPUNMAX */
+      *c=(Unit)carry;
+      carry=0;
+      continue;
+      }
+    #if DECDPUN==4                          /* use divide-by-multiply */
+      if (carry>=0) {
+       est=(((ueInt)carry>>11)*53687)>>18;
+       *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
+       carry=est;                           /* likely quotient [89%] */
+       if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
+       carry++;
+       *c-=DECDPUNMAX+1;
+       continue;
+       }
+      /* negative case */
+      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
+      est=(((ueInt)carry>>11)*53687)>>18;
+      *c=(Unit)(carry-est*(DECDPUNMAX+1));
+      carry=est-(DECDPUNMAX+1);                     /* correctly negative */
+      if (*c<DECDPUNMAX+1) continue;        /* was OK */
+      carry++;
+      *c-=DECDPUNMAX+1;
+    #elif DECDPUN==3
+      if (carry>=0) {
+       est=(((ueInt)carry>>3)*16777)>>21;
+       *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
+       carry=est;                           /* likely quotient [99%] */
+       if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
+       carry++;
+       *c-=DECDPUNMAX+1;
+       continue;
+       }
+      /* negative case */
+      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
+      est=(((ueInt)carry>>3)*16777)>>21;
+      *c=(Unit)(carry-est*(DECDPUNMAX+1));
+      carry=est-(DECDPUNMAX+1);                     /* correctly negative */
+      if (*c<DECDPUNMAX+1) continue;        /* was OK */
+      carry++;
+      *c-=DECDPUNMAX+1;
+    #elif DECDPUN<=2
+      /* Can use QUOT10 as carry <= 4 digits */
+      if (carry>=0) {
+       est=QUOT10(carry, DECDPUN);
+       *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
+       carry=est;                           /* quotient */
+       continue;
+       }
+      /* negative case */
+      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
+      est=QUOT10(carry, DECDPUN);
+      *c=(Unit)(carry-est*(DECDPUNMAX+1));
+      carry=est-(DECDPUNMAX+1);                     /* correctly negative */
+    #else
+      /* remainder operator is undefined if negative, so must test */
+      if ((ueInt)carry<(DECDPUNMAX+1)*2) {   /* fastpath carry +1 */
+       *c=(Unit)(carry-(DECDPUNMAX+1));     /* [helps additions] */
+       carry=1;
+       continue;
+       }
+      if (carry>=0) {
+       *c=(Unit)(carry%(DECDPUNMAX+1));
+       carry=carry/(DECDPUNMAX+1);
+       continue;
+       }
+      /* negative case */
+      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
+      *c=(Unit)(carry%(DECDPUNMAX+1));
+      carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
+    #endif
+    } /* c */
+
+  /* now may have one or other to complete */
+  /* [pretest to avoid loop setup/shutdown] */
+  if (c<maxC) for (; c<maxC; c++) {
+    if (a<alsu+alength) {              /* still in A */
+      carry+=*a;
       a++;
-      carry += ((eInt) * b) * m;       /* [special-casing m=1/-1 */
-      b++;                     /* here is not a win] */
-      /* here carry is new Unit of digits; it could be +ve or -ve */
-      if ((ueInt) carry <= DECDPUNMAX)
-       {                       /* fastpath 0-DECDPUNMAX */
-         *c = (Unit) carry;
-         carry = 0;
-         continue;
+      }
+     else {                            /* inside B */
+      carry+=((eInt)*b)*m;
+      b++;
+      }
+    /* here carry is new Unit of digits; it could be +ve or -ve and */
+    /* magnitude up to DECDPUNMAX squared */
+    if ((ueInt)carry<=DECDPUNMAX) {    /* fastpath 0-DECDPUNMAX */
+      *c=(Unit)carry;
+      carry=0;
+      continue;
+      }
+    /* result for this unit is negative or >DECDPUNMAX */
+    #if DECDPUN==4                          /* use divide-by-multiply */
+      if (carry>=0) {
+       est=(((ueInt)carry>>11)*53687)>>18;
+       *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
+       carry=est;                           /* likely quotient [79.7%] */
+       if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
+       carry++;
+       *c-=DECDPUNMAX+1;
+       continue;
        }
-      /* remainder operator is undefined if negative, so we must test */
-#if DECDPUN==4                 /* use divide-by-multiply */
-      if (carry >= 0)
-       {
-         est = (((ueInt) carry >> 11) * 53687) >> 18;
-         *c = (Unit) (carry - est * (DECDPUNMAX + 1)); /* remainder */
-         carry = est;          /* likely quotient [89%] */
-         if (*c < DECDPUNMAX + 1)
-           continue;           /* estimate was correct */
-         carry++;
-         *c -= DECDPUNMAX + 1;
-         continue;
+      /* negative case */
+      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
+      est=(((ueInt)carry>>11)*53687)>>18;
+      *c=(Unit)(carry-est*(DECDPUNMAX+1));
+      carry=est-(DECDPUNMAX+1);                     /* correctly negative */
+      if (*c<DECDPUNMAX+1) continue;        /* was OK */
+      carry++;
+      *c-=DECDPUNMAX+1;
+    #elif DECDPUN==3
+      if (carry>=0) {
+       est=(((ueInt)carry>>3)*16777)>>21;
+       *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
+       carry=est;                           /* likely quotient [99%] */
+       if (*c<DECDPUNMAX+1) continue;       /* estimate was correct */
+       carry++;
+       *c-=DECDPUNMAX+1;
+       continue;
        }
       /* negative case */
-      carry = carry + (eInt) (DECDPUNMAX + 1) * (DECDPUNMAX + 1);      /* make positive */
-      est = (((ueInt) carry >> 11) * 53687) >> 18;
-      *c = (Unit) (carry - est * (DECDPUNMAX + 1));
-      carry = est - (DECDPUNMAX + 1);  /* correctly negative */
-      if (*c < DECDPUNMAX + 1)
-       continue;               /* was OK */
+      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
+      est=(((ueInt)carry>>3)*16777)>>21;
+      *c=(Unit)(carry-est*(DECDPUNMAX+1));
+      carry=est-(DECDPUNMAX+1);                     /* correctly negative */
+      if (*c<DECDPUNMAX+1) continue;        /* was OK */
       carry++;
-      *c -= DECDPUNMAX + 1;
-#else
-      if ((ueInt) carry < (DECDPUNMAX + 1) * 2)
-       {                       /* fastpath carry +1 */
-         *c = (Unit) (carry - (DECDPUNMAX + 1));       /* [helps additions] */
-         carry = 1;
-         continue;
+      *c-=DECDPUNMAX+1;
+    #elif DECDPUN<=2
+      if (carry>=0) {
+       est=QUOT10(carry, DECDPUN);
+       *c=(Unit)(carry-est*(DECDPUNMAX+1)); /* remainder */
+       carry=est;                           /* quotient */
+       continue;
+       }
+      /* negative case */
+      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
+      est=QUOT10(carry, DECDPUN);
+      *c=(Unit)(carry-est*(DECDPUNMAX+1));
+      carry=est-(DECDPUNMAX+1);                     /* correctly negative */
+    #else
+      if ((ueInt)carry<(DECDPUNMAX+1)*2){    /* fastpath carry 1 */
+       *c=(Unit)(carry-(DECDPUNMAX+1));
+       carry=1;
+       continue;
        }
-      if (carry >= 0)
-       {
-         *c = (Unit) (carry % (DECDPUNMAX + 1));
-         carry = carry / (DECDPUNMAX + 1);
-         continue;
+      /* remainder operator is undefined if negative, so must test */
+      if (carry>=0) {
+       *c=(Unit)(carry%(DECDPUNMAX+1));
+       carry=carry/(DECDPUNMAX+1);
+       continue;
        }
       /* negative case */
-      carry = carry + (eInt) (DECDPUNMAX + 1) * (DECDPUNMAX + 1);      /* make positive */
-      *c = (Unit) (carry % (DECDPUNMAX + 1));
-      carry = carry / (DECDPUNMAX + 1) - (DECDPUNMAX + 1);
-#endif
-    }                          /* c */
-
-  /* we now may have one or other to complete */
-  /* [pretest to avoid loop setup/shutdown] */
-  if (c < maxC)
-    for (; c < maxC; c++)
-      {
-       if (a < alsu + alength)
-         {                     /* still in A */
-           carry += *a;
-           a++;
-         }
-       else
-         {                     /* inside B */
-           carry += ((eInt) * b) * m;
-           b++;
-         }
-       /* here carry is new Unit of digits; it could be +ve or -ve and */
-       /* magnitude up to DECDPUNMAX squared */
-       if ((ueInt) carry <= DECDPUNMAX)
-         {                     /* fastpath 0-DECDPUNMAX */
-           *c = (Unit) carry;
-           carry = 0;
-           continue;
-         }
-       /* result for this unit is negative or >DECDPUNMAX */
-#if DECDPUN==4                 /* use divide-by-multiply */
-       /* remainder is undefined if negative, so we must test */
-       if (carry >= 0)
-         {
-           est = (((ueInt) carry >> 11) * 53687) >> 18;
-           *c = (Unit) (carry - est * (DECDPUNMAX + 1));       /* remainder */
-           carry = est;        /* likely quotient [79.7%] */
-           if (*c < DECDPUNMAX + 1)
-             continue;         /* estimate was correct */
-           carry++;
-           *c -= DECDPUNMAX + 1;
-           continue;
-         }
-       /* negative case */
-       carry = carry + (eInt) (DECDPUNMAX + 1) * (DECDPUNMAX + 1);     /* make positive */
-       est = (((ueInt) carry >> 11) * 53687) >> 18;
-       *c = (Unit) (carry - est * (DECDPUNMAX + 1));
-       carry = est - (DECDPUNMAX + 1); /* correctly negative */
-       if (*c < DECDPUNMAX + 1)
-         continue;             /* was OK */
-       carry++;
-       *c -= DECDPUNMAX + 1;
-#else
-       if ((ueInt) carry < (DECDPUNMAX + 1) * 2)
-         {                     /* fastpath carry 1 */
-           *c = (Unit) (carry - (DECDPUNMAX + 1));
-           carry = 1;
-           continue;
-         }
-       /* remainder is undefined if negative, so we must test */
-       if (carry >= 0)
-         {
-           *c = (Unit) (carry % (DECDPUNMAX + 1));
-           carry = carry / (DECDPUNMAX + 1);
-           continue;
-         }
-       /* negative case */
-       carry = carry + (eInt) (DECDPUNMAX + 1) * (DECDPUNMAX + 1);     /* make positive */
-       *c = (Unit) (carry % (DECDPUNMAX + 1));
-       carry = carry / (DECDPUNMAX + 1) - (DECDPUNMAX + 1);
-#endif
-      }                                /* c */
+      carry=carry+(eInt)(DECDPUNMAX+1)*(DECDPUNMAX+1); /* make positive */
+      *c=(Unit)(carry%(DECDPUNMAX+1));
+      carry=carry/(DECDPUNMAX+1)-(DECDPUNMAX+1);
+    #endif
+    } /* c */
 
   /* OK, all A and B processed; might still have carry or borrow */
   /* return number of Units in the result, negated if a borrow */
-  if (carry == 0)
-    return c - clsu;           /* no carry, we're done */
-  if (carry > 0)
-    {                          /* positive carry */
-      *c = (Unit) carry;       /* place as new unit */
-      c++;                     /* .. */
-      return c - clsu;
+  if (carry==0) return c-clsu;    /* no carry, so no more to do */
+  if (carry>0) {                  /* positive carry */
+    *c=(Unit)carry;               /* place as new unit */
+    c++;                          /* .. */
+    return c-clsu;
     }
   /* -ve carry: it's a borrow; complement needed */
-  add = 1;                     /* temporary carry... */
-  for (c = clsu; c < maxC; c++)
-    {
-      add = DECDPUNMAX + add - *c;
-      if (add <= DECDPUNMAX)
-       {
-         *c = (Unit) add;
-         add = 0;
-       }
-      else
-       {
-         *c = 0;
-         add = 1;
-       }
+  add=1;                          /* temporary carry... */
+  for (c=clsu; c<maxC; c++) {
+    add=DECDPUNMAX+add-*c;
+    if (add<=DECDPUNMAX) {
+      *c=(Unit)add;
+      add=0;
+      }
+     else {
+      *c=0;
+      add=1;
+      }
     }
   /* add an extra unit iff it would be non-zero */
-#if DECTRACE
-  printf ("UAS borrow: add %d, carry %d\n", add, carry);
-#endif
-  if ((add - carry - 1) != 0)
-    {
-      *c = (Unit) (add - carry - 1);
-      c++;                     /* interesting, include it */
+  #if DECTRACE
+    printf("UAS borrow: add %ld, carry %ld\n", add, carry);
+  #endif
+  if ((add-carry-1)!=0) {
+    *c=(Unit)(add-carry-1);
+    c++;                     /* interesting, include it */
     }
-  return clsu - c;             /* -ve result indicates borrowed */
-}
+  return clsu-c;             /* -ve result indicates borrowed */
+  } /* decUnitAddSub */
 
 /* ------------------------------------------------------------------ */
-/* decTrim -- trim trailing zeros or normalize                        */
-/*                                                                    */
-/*   dn is the number to trim or normalize                            */
+/* decTrim -- trim trailing zeros or normalize                       */
+/*                                                                   */
+/*   dn is the number to trim or normalize                           */
+/*   set is the context to use to check for clamp                    */
 /*   all is 1 to remove all trailing zeros, 0 for just fraction ones  */
-/*   dropped returns the number of discarded trailing zeros           */
-/*   returns dn                                                       */
-/*                                                                    */
-/* All fields are updated as required.  This is a utility operation,  */
-/* so special values are unchanged and no error is possible.          */
-/* ------------------------------------------------------------------ */
-static decNumber *
-decTrim (decNumber * dn, Flag all, Int * dropped)
-{
-  Int d, exp;                  /* work */
-  uInt cut;                    /* .. */
-  Unit *up;                    /* -> current Unit */
-
-#if DECCHECK
-  if (decCheckOperands (dn, DECUNUSED, DECUNUSED, DECUNUSED))
+/*   dropped returns the number of discarded trailing zeros          */
+/*   returns dn                                                              */
+/*                                                                   */
+/* If clamp is set in the context then the number of zeros trimmed    */
+/* may be limited if the exponent is high.                           */
+/* All fields are updated as required. This is a utility operation,  */
+/* so special values are unchanged and no error is possible.         */
+/* ------------------------------------------------------------------ */
+static decNumber * decTrim(decNumber *dn, decContext *set, Flag all,
+                          Int *dropped) {
+  Int  d, exp;                    /* work */
+  uInt cut;                       /* .. */
+  Unit *up;                       /* -> current Unit */
+
+  #if DECCHECK
+  if (decCheckOperands(dn, DECUNUSED, DECUNUSED, DECUNCONT)) return dn;
+  #endif
+
+  *dropped=0;                          /* assume no zeros dropped */
+  if ((dn->bits & DECSPECIAL)          /* fast exit if special .. */
+    || (*dn->lsu & 0x01)) return dn;   /* .. or odd */
+  if (ISZERO(dn)) {                    /* .. or 0 */
+    dn->exponent=0;                    /* (sign is preserved) */
     return dn;
-#endif
-
-  *dropped = 0;                        /* assume no zeros dropped */
-  if ((dn->bits & DECSPECIAL)  /* fast exit if special .. */
-      || (*dn->lsu & 0x01))
-    return dn;                 /* .. or odd */
-  if (ISZERO (dn))
-    {                          /* .. or 0 */
-      dn->exponent = 0;                /* (sign is preserved) */
-      return dn;
     }
 
-  /* we have a finite number which is even */
-  exp = dn->exponent;
-  cut = 1;                     /* digit (1-DECDPUN) in Unit */
-  up = dn->lsu;                        /* -> current Unit */
-  for (d = 0; d < dn->digits - 1; d++)
-    {                          /* [don't strip the final digit] */
-      /* slice by powers */
-#if DECDPUN<=4
-      uInt quot = QUOT10 (*up, cut);
-      if ((*up - quot * powers[cut]) != 0)
-       break;                  /* found non-0 digit */
-#else
-      if (*up % powers[cut] != 0)
-       break;                  /* found non-0 digit */
-#endif
-      /* have a trailing 0 */
-      if (!all)
-       {                       /* trimming */
-         /* [if exp>0 then all trailing 0s are significant for trim] */
-         if (exp <= 0)
-           {                   /* if digit might be significant */
-             if (exp == 0)
-               break;          /* then quit */
-             exp++;            /* next digit might be significant */
-           }
+  /* have a finite number which is even */
+  exp=dn->exponent;
+  cut=1;                          /* digit (1-DECDPUN) in Unit */
+  up=dn->lsu;                     /* -> current Unit */
+  for (d=0; d<dn->digits-1; d++) { /* [don't strip the final digit] */
+    /* slice by powers */
+    #if DECDPUN<=4
+      uInt quot=QUOT10(*up, cut);
+      if ((*up-quot*powers[cut])!=0) break;  /* found non-0 digit */
+    #else
+      if (*up%powers[cut]!=0) break;        /* found non-0 digit */
+    #endif
+    /* have a trailing 0 */
+    if (!all) {                           /* trimming */
+      /* [if exp>0 then all trailing 0s are significant for trim] */
+      if (exp<=0) {               /* if digit might be significant */
+       if (exp==0) break;         /* then quit */
+       exp++;                     /* next digit might be significant */
        }
-      cut++;                   /* next power */
-      if (cut > DECDPUN)
-       {                       /* need new Unit */
-         up++;
-         cut = 1;
-       }
-    }                          /* d */
-  if (d == 0)
-    return dn;                 /* none dropped */
+      }
+    cut++;                        /* next power */
+    if (cut>DECDPUN) {            /* need new Unit */
+      up++;
+      cut=1;
+      }
+    } /* d */
+  if (d==0) return dn;            /* none to drop */
+
+  /* may need to limit drop if clamping */
+  if (set->clamp) {
+    Int maxd=set->emax-set->digits+1-dn->exponent;
+    if (maxd<=0) return dn;       /* nothing possible */
+    if (d>maxd) d=maxd;
+    }
 
   /* effect the drop */
-  decShiftToLeast (dn->lsu, D2U (dn->digits), d);
-  dn->exponent += d;           /* maintain numerical value */
-  dn->digits -= d;             /* new length */
-  *dropped = d;                        /* report the count */
+  decShiftToLeast(dn->lsu, D2U(dn->digits), d);
+  dn->exponent+=d;                /* maintain numerical value */
+  dn->digits-=d;                  /* new length */
+  *dropped=d;                     /* report the count */
   return dn;
-}
+  } /* decTrim */
+
+/* ------------------------------------------------------------------ */
+/* decReverse -- reverse a Unit array in place                       */
+/*                                                                   */
+/*   ulo    is the start of the array                                */
+/*   uhi    is the end of the array (highest Unit to include)        */
+/*                                                                   */
+/* The units ulo through uhi are reversed in place (if the number     */
+/* of units is odd, the middle one is untouched).  Note that the      */
+/* digit(s) in each unit are unaffected.                             */
+/* ------------------------------------------------------------------ */
+static void decReverse(Unit *ulo, Unit *uhi) {
+  Unit temp;
+  for (; ulo<uhi; ulo++, uhi--) {
+    temp=*ulo;
+    *ulo=*uhi;
+    *uhi=temp;
+    }
+  return;
+  } /* decReverse */
 
 /* ------------------------------------------------------------------ */
 /* decShiftToMost -- shift digits in array towards most significant   */
-/*                                                                    */
-/*   uar    is the array                                              */
-/*   digits is the count of digits in use in the array                */
+/*                                                                   */
+/*   uar    is the array                                             */
+/*   digits is the count of digits in use in the array               */
 /*   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    */
-/*                                                                    */
+/*                                                                   */
 /* No overflow is permitted (that is, the uar array must be known to  */
-/* be large enough to hold the result, after shifting).               */
-/* ------------------------------------------------------------------ */
-static Int
-decShiftToMost (Unit * uar, Int digits, Int shift)
-{
-  Unit *target, *source, *first;       /* work */
-  uInt rem;                    /* for division */
-  Int cut;                     /* odd 0's to add */
-  uInt next;                   /* work */
-
-  if (shift == 0)
-    return digits;             /* [fastpath] nothing to do */
-  if ((digits + shift) <= DECDPUN)
-    {                          /* [fastpath] single-unit case */
-      *uar = (Unit) (*uar * powers[shift]);
-      return digits + shift;
-    }
+/* be large enough to hold the result, after shifting).                      */
+/* ------------------------------------------------------------------ */
+static Int decShiftToMost(Unit *uar, Int digits, Int shift) {
+  Unit *target, *source, *first;  /* work */
+  Int  cut;                       /* odd 0's to add */
+  uInt next;                      /* work */
 
-  cut = (DECDPUN - shift % DECDPUN) % DECDPUN;
-  source = uar + D2U (digits) - 1;     /* where msu comes from */
-  first = uar + D2U (digits + shift) - 1;      /* where msu of source will end up */
-  target = source + D2U (shift);       /* where upper part of first cut goes */
-  next = 0;
+  if (shift==0) return digits;    /* [fastpath] nothing to do */
+  if ((digits+shift)<=DECDPUN) {   /* [fastpath] single-unit case */
+    *uar=(Unit)(*uar*powers[shift]);
+    return digits+shift;
+    }
 
-  for (; source >= uar; source--, target--)
-    {
-      /* split the source Unit and accumulate remainder for next */
-#if DECDPUN<=4
-      uInt quot = QUOT10 (*source, cut);
-      rem = *source - quot * powers[cut];
-      next += quot;
-#else
-      rem = *source % powers[cut];
-      next += *source / powers[cut];
-#endif
-      if (target <= first)
-       *target = (Unit) next;  /* write to target iff valid */
-      next = rem * powers[DECDPUN - cut];      /* save remainder for next Unit */
+  next=0;                         /* all paths */
+  source=uar+D2U(digits)-1;       /* where msu comes from */
+  target=source+D2U(shift);       /* where upper part of first cut goes */
+  cut=DECDPUN-MSUDIGITS(shift);           /* where to slice */
+  if (cut==0) {                           /* unit-boundary case */
+    for (; source>=uar; source--, target--) *target=*source;
     }
-  /* propagate to one below and clear the rest */
-  for (; target >= uar; target--)
-    {
-      *target = (Unit) next;
-      next = 0;
+   else {
+    first=uar+D2U(digits+shift)-1; /* where msu of source will end up */
+    for (; source>=uar; source--, target--) {
+      /* split the source Unit and accumulate remainder for next */
+      #if DECDPUN<=4
+       uInt quot=QUOT10(*source, cut);
+       uInt rem=*source-quot*powers[cut];
+       next+=quot;
+      #else
+       uInt rem=*source%powers[cut];
+       next+=*source/powers[cut];
+      #endif
+      if (target<=first) *target=(Unit)next;   /* write to target iff valid */
+      next=rem*powers[DECDPUN-cut];           /* save remainder for next Unit */
+      }
+    } /* shift-move */
+
+  /* propagate any partial unit to one below and clear the rest */
+  for (; target>=uar; target--) {
+    *target=(Unit)next;
+    next=0;
     }
-  return digits + shift;
-}
+  return digits+shift;
+  } /* decShiftToMost */
 
 /* ------------------------------------------------------------------ */
 /* decShiftToLeast -- shift digits in array towards least significant */
-/*                                                                    */
-/*   uar   is the array                                               */
-/*   units is length of the array, in units                           */
+/*                                                                   */
+/*   uar   is the array                                                      */
+/*   units is length of the array, in units                          */
 /*   shift is the number of digits to remove from the lsu end; it     */
-/*     must be zero or positive and less than units*DECDPUN.          */
-/*                                                                    */
+/*     must be zero or positive and <= than units*DECDPUN.           */
+/*                                                                   */
 /*   returns the new length of the integer in the array, in units     */
-/*                                                                    */
-/* Removed digits are discarded (lost).  Units not required to hold   */
-/* the final result are unchanged.                                    */
-/* ------------------------------------------------------------------ */
-static Int
-decShiftToLeast (Unit * uar, Int units, Int shift)
-{
-  Unit *target, *up;           /* work */
-  Int cut, count;              /* work */
-  Int quot, rem;               /* for division */
-
-  if (shift == 0)
-    return units;              /* [fastpath] nothing to do */
-
-  up = uar + shift / DECDPUN;  /* source; allow for whole Units */
-  cut = shift % DECDPUN;       /* odd 0's to drop */
-  target = uar;                        /* both paths */
-  if (cut == 0)
-    {                          /* whole units shift */
-      for (; up < uar + units; target++, up++)
-       *target = *up;
-      return target - uar;
+/*                                                                   */
+/* Removed digits are discarded (lost).         Units not required to hold   */
+/* the final result are unchanged.                                   */
+/* ------------------------------------------------------------------ */
+static Int decShiftToLeast(Unit *uar, Int units, Int shift) {
+  Unit *target, *up;              /* work */
+  Int  cut, count;                /* work */
+  Int  quot, rem;                 /* for division */
+
+  if (shift==0) return units;     /* [fastpath] nothing to do */
+  if (shift==units*DECDPUN) {     /* [fastpath] little to do */
+    *uar=0;                       /* all digits cleared gives zero */
+    return 1;                     /* leaves just the one */
+    }
+
+  target=uar;                     /* both paths */
+  cut=MSUDIGITS(shift);
+  if (cut==DECDPUN) {             /* unit-boundary case; easy */
+    up=uar+D2U(shift);
+    for (; up<uar+units; target++, up++) *target=*up;
+    return target-uar;
     }
+
   /* messier */
-  count = units * DECDPUN - shift;     /* the maximum new length */
-#if DECDPUN<=4
-  quot = QUOT10 (*up, cut);
-#else
-  quot = *up / powers[cut];
-#endif
-  for (;; target++)
-    {
-      *target = (Unit) quot;
-      count -= (DECDPUN - cut);
-      if (count <= 0)
-       break;
-      up++;
-      quot = *up;
-#if DECDPUN<=4
-      quot = QUOT10 (quot, cut);
-      rem = *up - quot * powers[cut];
-#else
-      rem = quot % powers[cut];
-      quot = quot / powers[cut];
-#endif
-      *target = (Unit) (*target + rem * powers[DECDPUN - cut]);
-      count -= cut;
-      if (count <= 0)
-       break;
+  up=uar+D2U(shift-cut);          /* source; correct to whole Units */
+  count=units*DECDPUN-shift;      /* the maximum new length */
+  #if DECDPUN<=4
+    quot=QUOT10(*up, cut);
+  #else
+    quot=*up/powers[cut];
+  #endif
+  for (; ; target++) {
+    *target=(Unit)quot;
+    count-=(DECDPUN-cut);
+    if (count<=0) break;
+    up++;
+    quot=*up;
+    #if DECDPUN<=4
+      quot=QUOT10(quot, cut);
+      rem=*up-quot*powers[cut];
+    #else
+      rem=quot%powers[cut];
+      quot=quot/powers[cut];
+    #endif
+    *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
+    count-=cut;
+    if (count<=0) break;
     }
-  return target - uar + 1;
-}
+  return target-uar+1;
+  } /* decShiftToLeast */
 
 #if DECSUBSET
 /* ------------------------------------------------------------------ */
-/* decRoundOperand -- round an operand  [used for subset only]        */
-/*                                                                    */
-/*   dn is the number to round (dn->digits is > set->digits)          */
-/*   set is the relevant context                                      */
-/*   status is the status accumulator                                 */
-/*                                                                    */
-/*   returns an allocated decNumber with the rounded result.          */
-/*                                                                    */
-/* lostDigits and other status may be set by this.                    */
-/*                                                                    */
-/* Since the input is an operand, we are not permitted to modify it.  */
-/* We therefore return an allocated decNumber, rounded as required.   */
+/* decRoundOperand -- round an operand [used for subset only]        */
+/*                                                                   */
+/*   dn is the number to round (dn->digits is > set->digits)         */
+/*   set is the relevant context                                     */
+/*   status is the status accumulator                                */
+/*                                                                   */
+/*   returns an allocated decNumber with the rounded result.         */
+/*                                                                   */
+/* lostDigits and other status may be set by this.                   */
+/*                                                                   */
+/* Since the input is an operand, it must not be modified.           */
+/* Instead, return an allocated decNumber, rounded as required.              */
 /* It is the caller's responsibility to free the allocated storage.   */
-/*                                                                    */
+/*                                                                   */
 /* 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, uInt * status)
-{
-  decNumber *res;              /* result structure */
-  uInt newstatus = 0;          /* status from round */
-  Int residue = 0;             /* rounding accumulator */
+static decNumber *decRoundOperand(const decNumber *dn, decContext *set,
+                                 uInt *status) {
+  decNumber *res;                      /* result structure */
+  uInt newstatus=0;                    /* status from round */
+  Int  residue=0;                      /* rounding accumulator */
 
   /* Allocate storage for the returned decNumber, big enough for the */
   /* length specified by the context */
-  res = (decNumber *) malloc (sizeof (decNumber)
-                             + (D2U (set->digits) - 1) * sizeof (Unit));
-  if (res == NULL)
-    {
-      *status |= DEC_Insufficient_storage;
-      return NULL;
+  res=(decNumber *)malloc(sizeof(decNumber)
+                         +(D2U(set->digits)-1)*sizeof(Unit));
+  if (res==NULL) {
+    *status|=DEC_Insufficient_storage;
+    return NULL;
     }
-  decCopyFit (res, dn, set, &residue, &newstatus);
-  decApplyRound (res, set, residue, &newstatus);
+  decCopyFit(res, dn, set, &residue, &newstatus);
+  decApplyRound(res, set, residue, &newstatus);
 
-  /* If that set Inexact then we "lost digits" */
-  if (newstatus & DEC_Inexact)
-    newstatus |= DEC_Lost_digits;
-  *status |= newstatus;
+  /* If that set Inexact then "lost digits" is raised... */
+  if (newstatus & DEC_Inexact) newstatus|=DEC_Lost_digits;
+  *status|=newstatus;
   return res;
-}
+  } /* decRoundOperand */
 #endif
 
 /* ------------------------------------------------------------------ */
-/* decCopyFit -- copy a number, shortening the coefficient if needed  */
-/*                                                                    */
-/*   dest is the target decNumber                                     */
-/*   src  is the source decNumber                                     */
+/* decCopyFit -- copy a number, truncating the coefficient if needed  */
+/*                                                                   */
+/*   dest is the target decNumber                                    */
+/*   src  is the source decNumber                                    */
 /*   set is the context [used for length (digits) and rounding mode]  */
-/*   residue is the residue accumulator                               */
-/*   status contains the current status to be updated                 */
-/*                                                                    */
-/* (dest==src is allowed and will be a no-op if fits)                 */
-/* All fields are updated as required.                                */
-/* ------------------------------------------------------------------ */
-static void
-decCopyFit (decNumber * dest, const decNumber * src, decContext * set,
-           Int * residue, uInt * status)
-{
-  dest->bits = src->bits;
-  dest->exponent = src->exponent;
-  decSetCoeff (dest, set, src->lsu, src->digits, residue, status);
-}
-
-/* ------------------------------------------------------------------ */
-/* decSetCoeff -- set the coefficient of a number                     */
-/*                                                                    */
-/*   dn    is the number whose coefficient array is to be set.        */
-/*         It must have space for set->digits digits                  */
-/*   set   is the context [for size]                                  */
-/*   lsu   -> lsu of the source coefficient [may be dn->lsu]          */
+/*   residue is the residue accumulator                                      */
+/*   status contains the current status to be updated                */
+/*                                                                   */
+/* (dest==src is allowed and will be a no-op if fits)                */
+/* All fields are updated as required.                               */
+/* ------------------------------------------------------------------ */
+static void decCopyFit(decNumber *dest, const decNumber *src,
+                      decContext *set, Int *residue, uInt *status) {
+  dest->bits=src->bits;
+  dest->exponent=src->exponent;
+  decSetCoeff(dest, set, src->lsu, src->digits, residue, status);
+  } /* decCopyFit */
+
+/* ------------------------------------------------------------------ */
+/* decSetCoeff -- set the coefficient of a number                    */
+/*                                                                   */
+/*   dn           is the number whose coefficient array is to be set.        */
+/*        It must have space for set->digits digits                  */
+/*   set   is the context [for size]                                 */
+/*   lsu   -> lsu of the source coefficient [may be dn->lsu]         */
 /*   len   is digits in the source coefficient [may be dn->digits]    */
-/*   residue is the residue accumulator.  This has values as in       */
-/*         decApplyRound, and will be unchanged unless the            */
-/*         target size is less than len.  In this case, the           */
-/*         coefficient is truncated and the residue is updated to     */
-/*         reflect the previous residue and the dropped digits.       */
-/*   status is the status accumulator, as usual                       */
-/*                                                                    */
+/*   residue is the residue accumulator.  This has values as in              */
+/*        decApplyRound, and will be unchanged unless the            */
+/*        target size is less than len.  In this case, the           */
+/*        coefficient is truncated and the residue is updated to     */
+/*        reflect the previous residue and the dropped digits.       */
+/*   status is the status accumulator, as usual                              */
+/*                                                                   */
 /* The coefficient may already be in the number, or it can be an      */
-/* external intermediate array.  If it is in the number, lsu must ==  */
-/* dn->lsu and len must == dn->digits.                                */
-/*                                                                    */
+/* external intermediate array.         If it is in the number, lsu must ==  */
+/* dn->lsu and len must == dn->digits.                               */
+/*                                                                   */
 /* Note that the coefficient length (len) may be < set->digits, and   */
 /* in this case this merely copies the coefficient (or is a no-op     */
-/* if dn->lsu==lsu).                                                  */
-/*                                                                    */
-/* Note also that (only internally, from decNumberRescale and         */
+/* if dn->lsu==lsu).                                                 */
+/*                                                                   */
+/* Note also that (only internally, from decQuantizeOp and           */
 /* decSetSubnormal) the value of set->digits may be less than one,    */
-/* indicating a round to left.                                        */
-/* This routine handles that case correctly; caller ensures space.    */
-/*                                                                    */
-/* dn->digits, dn->lsu (and as required), and dn->exponent are        */
-/* updated as necessary.   dn->bits (sign) is unchanged.              */
-/*                                                                    */
-/* DEC_Rounded status is set if any digits are discarded.             */
+/* indicating a round to left. This routine handles that case        */
+/* correctly; caller ensures space.                                  */
+/*                                                                   */
+/* dn->digits, dn->lsu (and as required), and dn->exponent are       */
+/* updated as necessary.   dn->bits (sign) is unchanged.             */
+/*                                                                   */
+/* DEC_Rounded status is set if any digits are discarded.            */
 /* DEC_Inexact status is set if any non-zero digits are discarded, or */
-/*                       incoming residue was non-0 (implies rounded) */
-/* ------------------------------------------------------------------ */
-/* mapping array: maps 0-9 to canonical residues, so that we can */
-/* adjust by a residue in range [-1, +1] and achieve correct rounding */
-/*                             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 void
-decSetCoeff (decNumber * dn, decContext * set, const Unit * lsu,
-            Int len, Int * residue, uInt * status)
-{
-  Int discard;                 /* number of digits to discard */
-  uInt discard1;               /* first discarded digit */
-  uInt cut;                    /* cut point in Unit */
-  uInt quot, rem;              /* for divisions */
-  Unit *target;                        /* work */
-  const Unit *up;              /* work */
-  Int count;                   /* .. */
-#if DECDPUN<=4
-  uInt temp;                   /* .. */
-#endif
-
-  discard = len - set->digits; /* digits to discard */
-  if (discard <= 0)
-    {                          /* no digits are being discarded */
-      if (dn->lsu != lsu)
-       {                       /* copy needed */
-         /* copy the coefficient array to the result number; no shift needed */
-         up = lsu;
-         for (target = dn->lsu; target < dn->lsu + D2U (len); target++, up++)
-           {
-             *target = *up;
-           }
-         dn->digits = len;     /* set the new length */
-       }
-      /* dn->exponent and residue are unchanged */
-      if (*residue != 0)
-       *status |= (DEC_Inexact | DEC_Rounded); /* record inexactitude */
-      return;
+/*                      incoming residue was non-0 (implies rounded) */
+/* ------------------------------------------------------------------ */
+/* mapping array: maps 0-9 to canonical residues, so that a residue */
+/* can be adjusted in the range [-1, +1] and achieve correct rounding */
+/*                            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 void decSetCoeff(decNumber *dn, decContext *set, const Unit *lsu,
+                       Int len, Int *residue, uInt *status) {
+  Int  discard;              /* number of digits to discard */
+  uInt cut;                  /* cut point in Unit */
+  const Unit *up;            /* work */
+  Unit *target;              /* .. */
+  Int  count;                /* .. */
+  #if DECDPUN<=4
+  uInt temp;                 /* .. */
+  #endif
+
+  discard=len-set->digits;    /* digits to discard */
+  if (discard<=0) {          /* no digits are being discarded */
+    if (dn->lsu!=lsu) {              /* copy needed */
+      /* copy the coefficient array to the result number; no shift needed */
+      count=len;             /* avoids D2U */
+      up=lsu;
+      for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
+       *target=*up;
+      dn->digits=len;        /* set the new length */
+      }
+    /* dn->exponent and residue are unchanged, record any inexactitude */
+    if (*residue!=0) *status|=(DEC_Inexact | DEC_Rounded);
+    return;
     }
 
-  /* we have to discard some digits */
-  *status |= DEC_Rounded;      /* accumulate Rounded status */
-  if (*residue > 1)
-    *residue = 1;              /* previous residue now to right, so -1 to +1 */
-
-  if (discard > len)
-    {                          /* everything, +1, is being discarded */
-      /* guard digit is 0 */
-      /* residue is all the number [NB could be all 0s] */
-      if (*residue <= 0)
-       for (up = lsu + D2U (len) - 1; up >= lsu; up--)
-         {
-           if (*up != 0)
-             {                 /* found a non-0 */
-               *residue = 1;
-               break;          /* no need to check any others */
-             }
-         }
-      if (*residue != 0)
-       *status |= DEC_Inexact; /* record inexactitude */
-      *dn->lsu = 0;            /* coefficient will now be 0 */
-      dn->digits = 1;          /* .. */
-      dn->exponent += discard; /* maintain numerical value */
-      return;
-    }                          /* total discard */
+  /* some digits must be discarded ... */
+  dn->exponent+=discard;      /* maintain numerical value */
+  *status|=DEC_Rounded;              /* accumulate Rounded status */
+  if (*residue>1) *residue=1; /* previous residue now to right, so reduce */
+
+  if (discard>len) {         /* everything, +1, is being discarded */
+    /* guard digit is 0 */
+    /* residue is all the number [NB could be all 0s] */
+    if (*residue<=0) {       /* not already positive */
+      count=len;             /* avoids D2U */
+      for (up=lsu; count>0; up++, count-=DECDPUN) if (*up!=0) { /* found non-0 */
+       *residue=1;
+       break;                /* no need to check any others */
+       }
+      }
+    if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
+    *dn->lsu=0;                      /* coefficient will now be 0 */
+    dn->digits=1;            /* .. */
+    return;
+    } /* total discard */
 
   /* partial discard [most common case] */
   /* here, at least the first (most significant) discarded digit exists */
 
-  /* spin up the number, noting residue as we pass, until we get to */
-  /* the Unit with the first discarded digit.  When we get there, */
-  /* extract it and remember where we're at */
-  count = 0;
-  for (up = lsu;; up++)
-    {
-      count += DECDPUN;
-      if (count >= discard)
-       break;                  /* full ones all checked */
-      if (*up != 0)
-       *residue = 1;
-    }                          /* up */
-
-  /* here up -> Unit with discarded digit */
-  cut = discard - (count - DECDPUN) - 1;
-  if (cut == DECDPUN - 1)
-    {                          /* discard digit is at top */
-#if DECDPUN<=4
-      discard1 = QUOT10 (*up, DECDPUN - 1);
-      rem = *up - discard1 * powers[DECDPUN - 1];
-#else
-      rem = *up % powers[DECDPUN - 1];
-      discard1 = *up / powers[DECDPUN - 1];
-#endif
-      if (rem != 0)
-       *residue = 1;
-      up++;                    /* move to next */
-      cut = 0;                 /* bottom digit of result */
-      quot = 0;                        /* keep a certain compiler happy */
-    }
-  else
-    {
-      /* discard digit is in low digit(s), not top digit */
-      if (cut == 0)
-       quot = *up;
-      else                     /* cut>0 */
-       {                       /* it's not at bottom of Unit */
-#if DECDPUN<=4
-         quot = QUOT10 (*up, cut);
-         rem = *up - quot * powers[cut];
-#else
-         rem = *up % powers[cut];
-         quot = *up / powers[cut];
-#endif
-         if (rem != 0)
-           *residue = 1;
-       }
-      /* discard digit is now at bottom of quot */
-#if DECDPUN<=4
-      temp = (quot * 6554) >> 16;      /* fast /10 */
+  /* spin up the number, noting residue during the spin, until get to */
+  /* the Unit with the first discarded digit.  When reach it, extract */
+  /* it and remember its position */
+  count=0;
+  for (up=lsu;; up++) {
+    count+=DECDPUN;
+    if (count>=discard) break; /* full ones all checked */
+    if (*up!=0) *residue=1;
+    } /* up */
+
+  /* here up -> Unit with first discarded digit */
+  cut=discard-(count-DECDPUN)-1;
+  if (cut==DECDPUN-1) {              /* unit-boundary case (fast) */
+    Unit half=(Unit)powers[DECDPUN]>>1;
+    /* set residue directly */
+    if (*up>=half) {
+      if (*up>half) *residue=7;
+      else *residue+=5;              /* add sticky bit */
+      }
+     else { /* <half */
+      if (*up!=0) *residue=3; /* [else is 0, leave as sticky bit] */
+      }
+    if (set->digits<=0) {     /* special for Quantize/Subnormal :-( */
+      *dn->lsu=0;            /* .. result is 0 */
+      dn->digits=1;          /* .. */
+      }
+     else {                  /* shift to least */
+      count=set->digits;      /* now digits to end up with */
+      dn->digits=count;              /* set the new length */
+      up++;                  /* move to next */
+      /* on unit boundary, so shift-down copy loop is simple */
+      for (target=dn->lsu; count>0; target++, up++, count-=DECDPUN)
+       *target=*up;
+      }
+    } /* unit-boundary case */
+
+   else { /* discard digit is in low digit(s), and not top digit */
+    uInt  discard1;               /* first discarded digit */
+    uInt  quot, rem;              /* for divisions */
+    if (cut==0) quot=*up;         /* is at bottom of unit */
+     else /* cut>0 */ {                   /* it's not at bottom of unit */
+      #if DECDPUN<=4
+       quot=QUOT10(*up, cut);
+       rem=*up-quot*powers[cut];
+      #else
+       rem=*up%powers[cut];
+       quot=*up/powers[cut];
+      #endif
+      if (rem!=0) *residue=1;
+      }
+    /* discard digit is now at bottom of quot */
+    #if DECDPUN<=4
+      temp=(quot*6554)>>16;       /* fast /10 */
       /* Vowels algorithm here not a win (9 instructions) */
-      discard1 = quot - X10 (temp);
-      quot = temp;
-#else
-      discard1 = quot % 10;
-      quot = quot / 10;
-#endif
-      cut++;                   /* update cut */
-    }
-
-  /* here: up -> Unit of the array with discarded digit */
-  /*       cut is the division point for each Unit */
-  /*       quot holds the uncut high-order digits for the current */
-  /*            Unit, unless cut==0 in which case it's still in *up */
-  /* copy the coefficient array to the result number, shifting as we go */
-  count = set->digits;         /* digits to end up with */
-  if (count <= 0)
-    {                          /* special for Rescale/Subnormal :-( */
-      *dn->lsu = 0;            /* .. result is 0 */
-      dn->digits = 1;          /* .. */
-    }
-  else
-    {                          /* shift to least */
-      /* [this is similar to decShiftToLeast code, with copy] */
-      dn->digits = count;      /* set the new length */
-      if (cut == 0)
-       {
-         /* on unit boundary, so simple shift down copy loop suffices */
-         for (target = dn->lsu; target < dn->lsu + D2U (count);
-              target++, up++)
-           {
-             *target = *up;
-           }
-       }
-      else
-       for (target = dn->lsu;; target++)
-         {
-           *target = (Unit) quot;
-           count -= (DECDPUN - cut);
-           if (count <= 0)
-             break;
-           up++;
-           quot = *up;
-#if DECDPUN<=4
-           quot = QUOT10 (quot, cut);
-           rem = *up - quot * powers[cut];
-#else
-           rem = quot % powers[cut];
-           quot = quot / powers[cut];
-#endif
-           *target = (Unit) (*target + rem * powers[DECDPUN - cut]);
-           count -= cut;
-           if (count <= 0)
-             break;
-         }
-    }                          /* shift to least needed */
-  dn->exponent += discard;     /* maintain numerical value */
-
-  /* here, discard1 is the guard digit, and residue is everything else */
-  /* [use mapping to accumulate residue safely] */
-  *residue += resmap[discard1];
-
-  if (*residue != 0)
-    *status |= DEC_Inexact;    /* record inexactitude */
+      discard1=quot-X10(temp);
+      quot=temp;
+    #else
+      discard1=quot%10;
+      quot=quot/10;
+    #endif
+    /* here, discard1 is the guard digit, and residue is everything */
+    /* else [use mapping array to accumulate residue safely] */
+    *residue+=resmap[discard1];
+    cut++;                        /* update cut */
+    /* here: up -> Unit of the array with bottom digit */
+    /*      cut is the division point for each Unit */
+    /*      quot holds the uncut high-order digits for the current unit */
+    if (set->digits<=0) {         /* special for Quantize/Subnormal :-( */
+      *dn->lsu=0;                 /* .. result is 0 */
+      dn->digits=1;               /* .. */
+      }
+     else {                       /* shift to least needed */
+      count=set->digits;          /* now digits to end up with */
+      dn->digits=count;                   /* set the new length */
+      /* shift-copy the coefficient array to the result number */
+      for (target=dn->lsu; ; target++) {
+       *target=(Unit)quot;
+       count-=(DECDPUN-cut);
+       if (count<=0) break;
+       up++;
+       quot=*up;
+       #if DECDPUN<=4
+         quot=QUOT10(quot, cut);
+         rem=*up-quot*powers[cut];
+       #else
+         rem=quot%powers[cut];
+         quot=quot/powers[cut];
+       #endif
+       *target=(Unit)(*target+rem*powers[DECDPUN-cut]);
+       count-=cut;
+       if (count<=0) break;
+       } /* shift-copy loop */
+      } /* shift to least */
+    } /* not unit boundary */
+
+  if (*residue!=0) *status|=DEC_Inexact; /* record inexactitude */
   return;
-}
-
-/* ------------------------------------------------------------------ */
-/* decApplyRound -- apply pending rounding to a number                */
-/*                                                                    */
-/*   dn    is the number, with space for set->digits digits           */
-/*   set   is the context [for size and rounding mode]                */
-/*   residue indicates pending rounding, being any accumulated        */
-/*         guard and sticky information.  It may be:                  */
-/*         6-9: rounding digit is >5                                  */
-/*         5:   rounding digit is exactly half-way                    */
-/*         1-4: rounding digit is <5 and >0                           */
-/*         0:   the coefficient is exact                              */
-/*        -1:   as 1, but the hidden digits are subtractive, that     */
-/*              is, of the opposite sign to dn.  In this case the     */
-/*              coefficient must be non-0.                            */
-/*   status is the status accumulator, as usual                       */
-/*                                                                    */
+  } /* decSetCoeff */
+
+/* ------------------------------------------------------------------ */
+/* decApplyRound -- apply pending rounding to a number               */
+/*                                                                   */
+/*   dn           is the number, with space for set->digits digits           */
+/*   set   is the context [for size and rounding mode]               */
+/*   residue indicates pending rounding, being any accumulated       */
+/*        guard and sticky information.  It may be:                  */
+/*        6-9: rounding digit is >5                                  */
+/*        5:   rounding digit is exactly half-way                    */
+/*        1-4: rounding digit is <5 and >0                           */
+/*        0:   the coefficient is exact                              */
+/*       -1:   as 1, but the hidden digits are subtractive, that     */
+/*             is, of the opposite sign to dn.  In this case the     */
+/*             coefficient must be non-0.  This case occurs when     */
+/*             subtracting a small number (which can be reduced to   */
+/*             a sticky bit); see decAddOp.                          */
+/*   status is the status accumulator, as usual                              */
+/*                                                                   */
 /* This routine applies rounding while keeping the length of the      */
-/* coefficient constant.  The exponent and status are unchanged       */
-/* except if:                                                         */
-/*                                                                    */
+/* coefficient constant.  The exponent and status are unchanged              */
+/* except if:                                                        */
+/*                                                                   */
 /*   -- the coefficient was increased and is all nines (in which      */
-/*      case Overflow could occur, and is handled directly here so    */
-/*      the caller does not need to re-test for overflow)             */
-/*                                                                    */
+/*     case Overflow could occur, and is handled directly here so    */
+/*     the caller does not need to re-test for overflow)             */
+/*                                                                   */
 /*   -- the coefficient was decreased and becomes all nines (in which */
-/*      case Underflow could occur, and is also handled directly).    */
-/*                                                                    */
-/* All fields in dn are updated as required.                          */
-/*                                                                    */
+/*     case Underflow could occur, and is also handled directly).    */
+/*                                                                   */
+/* All fields in dn are updated as required.                         */
+/*                                                                   */
 /* ------------------------------------------------------------------ */
-static void
-decApplyRound (decNumber * dn, decContext * set, Int residue, uInt * status)
-{
-  Int bump;                    /* 1 if coefficient needs to be incremented */
-  /* -1 if coefficient needs to be decremented */
+static void decApplyRound(decNumber *dn, decContext *set, Int residue,
+                         uInt *status) {
+  Int  bump;                 /* 1 if coefficient needs to be incremented */
+                             /* -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 */
-  switch (set->round)
-    {
-    case DEC_ROUND_DOWN:
-      {
-       /* no change, except if negative residue */
-       if (residue < 0)
-         bump = -1;
-       break;
-      }                                /* r-d */
+  switch (set->round) {
+    case DEC_ROUND_05UP: {    /* round zero or five up (for reround) */
+      /* 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 */
+      /* it is bumped; when residue is <0, the number is therefore */
+      /* bumped down unless the final digit was 1 or 6 (in which */
+      /* case it is bumped down and then up -- a no-op) */
+      Int lsd5=*dn->lsu%5;     /* get lsd and quintate */
+      if (residue<0 && lsd5!=1) bump=-1;
+       else if (residue>0 && lsd5==0) bump=1;
+      /* [bump==1 could be applied directly; use common path for clarity] */
+      break;} /* r-05 */
+
+    case DEC_ROUND_DOWN: {
+      /* no change, except if negative residue */
+      if (residue<0) bump=-1;
+      break;} /* r-d */
+
+    case DEC_ROUND_HALF_DOWN: {
+      if (residue>5) bump=1;
+      break;} /* r-h-d */
+
+    case DEC_ROUND_HALF_EVEN: {
+      if (residue>5) bump=1;           /* >0.5 goes up */
+       else if (residue==5) {          /* exactly 0.5000... */
+       /* 0.5 goes up iff [new] lsd is odd */
+       if (*dn->lsu & 0x01) bump=1;
+       }
+      break;} /* r-h-e */
 
-    case DEC_ROUND_HALF_DOWN:
-      {
-       if (residue > 5)
-         bump = 1;
-       break;
-      }                                /* r-h-d */
-
-    case DEC_ROUND_HALF_EVEN:
-      {
-       if (residue > 5)
-         bump = 1;             /* >0.5 goes up */
-       else if (residue == 5)
-         {                     /* exactly 0.5000... */
-           /* 0.5 goes up iff [new] lsd is odd */
-           if (*dn->lsu & 0x01)
-             bump = 1;
-         }
-       break;
-      }                                /* r-h-e */
+    case DEC_ROUND_HALF_UP: {
+      if (residue>=5) bump=1;
+      break;} /* r-h-u */
 
-    case DEC_ROUND_HALF_UP:
-      {
-       if (residue >= 5)
-         bump = 1;
-       break;
-      }                                /* r-h-u */
+    case DEC_ROUND_UP: {
+      if (residue>0) bump=1;
+      break;} /* r-u */
 
-    case DEC_ROUND_UP:
-      {
-       if (residue > 0)
-         bump = 1;
-       break;
-      }                                /* r-u */
-
-    case DEC_ROUND_CEILING:
-      {
-       /* same as _UP for positive numbers, and as _DOWN for negatives */
-       /* [negative residue cannot occur on 0] */
-       if (decNumberIsNegative (dn))
-         {
-           if (residue < 0)
-             bump = -1;
-         }
-       else
-         {
-           if (residue > 0)
-             bump = 1;
-         }
-       break;
-      }                                /* r-c */
-
-    case DEC_ROUND_FLOOR:
-      {
-       /* same as _UP for negative numbers, and as _DOWN for positive */
-       /* [negative residue cannot occur on 0] */
-       if (!decNumberIsNegative (dn))
-         {
-           if (residue < 0)
-             bump = -1;
-         }
-       else
-         {
-           if (residue > 0)
-             bump = 1;
-         }
-       break;
-      }                                /* r-f */
+    case DEC_ROUND_CEILING: {
+      /* same as _UP for positive numbers, and as _DOWN for negatives */
+      /* [negative residue cannot occur on 0] */
+      if (decNumberIsNegative(dn)) {
+       if (residue<0) bump=-1;
+       }
+       else {
+       if (residue>0) bump=1;
+       }
+      break;} /* r-c */
 
-    default:
-      {                                /* e.g., DEC_ROUND_MAX */
-       *status |= DEC_Invalid_context;
-#if DECTRACE
-       printf ("Unknown rounding mode: %d\n", set->round);
-#endif
-       break;
-      }
-    }                          /* switch */
+    case DEC_ROUND_FLOOR: {
+      /* same as _UP for negative numbers, and as _DOWN for positive */
+      /* [negative residue cannot occur on 0] */
+      if (!decNumberIsNegative(dn)) {
+       if (residue<0) bump=-1;
+       }
+       else {
+       if (residue>0) bump=1;
+       }
+      break;} /* r-f */
+
+    default: {     /* e.g., DEC_ROUND_MAX */
+      *status|=DEC_Invalid_context;
+      #if DECTRACE || (DECCHECK && DECVERB)
+      printf("Unknown rounding mode: %d\n", set->round);
+      #endif
+      break;}
+    } /* switch */
 
   /* 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 we are bumping up and the number */
-  /* is all nines.  In this special case we set to 1000... and adjust */
-  /* the exponent by one (as otherwise we could overflow the array) */
+  /* Simply use decUnitAddSub unless bumping up and the number is */
+  /* all nines.         In this special case set to 100... explicitly */
+  /* and adjust the exponent by one (as otherwise could overflow */
+  /* the array) */
   /* Similarly handle all-nines result if bumping down. */
-  if (bump > 0)
-    {
-      Unit *up;                        /* work */
-      uInt count = dn->digits; /* digits to be checked */
-      for (up = dn->lsu;; up++)
-       {
-         if (count <= DECDPUN)
-           {
-             /* this is the last Unit (the msu) */
-             if (*up != powers[count] - 1)
-               break;          /* not still 9s */
-             /* here if it, too, is all nines */
-             *up = (Unit) powers[count - 1];   /* here 999 -> 100 etc. */
-             for (up = up - 1; up >= dn->lsu; up--)
-               *up = 0;        /* others all to 0 */
-             dn->exponent++;   /* and bump exponent */
-             /* [which, very rarely, could cause Overflow...] */
-             if ((dn->exponent + dn->digits) > set->emax + 1)
-               {
-                 decSetOverflow (dn, set, status);
-               }
-             return;           /* done */
-           }
-         /* a full unit to check, with more to come */
-         if (*up != DECDPUNMAX)
-           break;              /* not still 9s */
-         count -= DECDPUN;
-       }                       /* up */
-    }                          /* bump>0 */
-  else
-    {                          /* -1 */
-      /* here we are lookng for a pre-bump of 1000... (leading 1, */
-      /* all other digits zero) */
-      Unit *up, *sup;          /* work */
-      uInt count = dn->digits; /* digits to be checked */
-      for (up = dn->lsu;; up++)
-       {
-         if (count <= DECDPUN)
-           {
-             /* this is the last Unit (the msu) */
-             if (*up != powers[count - 1])
-               break;          /* not 100.. */
-             /* here if we have the 1000... case */
-             sup = up;         /* save msu pointer */
-             *up = (Unit) powers[count] - 1;   /* here 100 in msu -> 999 */
-             /* others all to all-nines, too */
-             for (up = up - 1; up >= dn->lsu; up--)
-               *up = (Unit) powers[DECDPUN] - 1;
-             dn->exponent--;   /* and bump exponent */
-
-             /* iff the number was at the subnormal boundary (exponent=etiny) */
-             /* then the exponent is now out of range, so it will in fact get */
-             /* clamped to etiny and the final 9 dropped. */
-             /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */
-             /*        dn->exponent, set->digits); */
-             if (dn->exponent + 1 == set->emin - set->digits + 1)
-               {
-                 if (count == 1 && dn->digits == 1)
-                   *sup = 0;   /* here 9 -> 0[.9] */
-                 else
-                   {
-                     *sup = (Unit) powers[count - 1] - 1;      /* here 999.. in msu -> 99.. */
-                     dn->digits--;
-                   }
-                 dn->exponent++;
-                 *status |=
-                   DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
-               }
-             return;           /* done */
+  if (bump>0) {
+    Unit *up;                               /* work */
+    uInt count=dn->digits;                  /* digits to be checked */
+    for (up=dn->lsu; ; up++) {
+      if (count<=DECDPUN) {
+       /* this is the last Unit (the msu) */
+       if (*up!=powers[count]-1) break;     /* not still 9s */
+       /* here if it, too, is all nines */
+       *up=(Unit)powers[count-1];           /* here 999 -> 100 etc. */
+       for (up=up-1; up>=dn->lsu; up--) *up=0; /* others all to 0 */
+       dn->exponent++;                      /* and bump exponent */
+       /* [which, very rarely, could cause Overflow...] */
+       if ((dn->exponent+dn->digits)>set->emax+1) {
+         decSetOverflow(dn, set, status);
+         }
+       return;                              /* done */
+       }
+      /* a full unit to check, with more to come */
+      if (*up!=DECDPUNMAX) break;           /* not still 9s */
+      count-=DECDPUN;
+      } /* up */
+    } /* bump>0 */
+   else {                                   /* -1 */
+    /* here checking for a pre-bump of 1000... (leading 1, all */
+    /* other digits zero) */
+    Unit *up, *sup;                         /* work */
+    uInt count=dn->digits;                  /* digits to be checked */
+    for (up=dn->lsu; ; up++) {
+      if (count<=DECDPUN) {
+       /* this is the last Unit (the msu) */
+       if (*up!=powers[count-1]) break;     /* not 100.. */
+       /* here if have the 1000... case */
+       sup=up;                              /* save msu pointer */
+       *up=(Unit)powers[count]-1;           /* here 100 in msu -> 999 */
+       /* others all to all-nines, too */
+       for (up=up-1; up>=dn->lsu; up--) *up=(Unit)powers[DECDPUN]-1;
+       dn->exponent--;                      /* and bump exponent */
+
+       /* iff the number was at the subnormal boundary (exponent=etiny) */
+       /* then the exponent is now out of range, so it will in fact get */
+       /* clamped to etiny and the final 9 dropped. */
+       /* printf(">> emin=%d exp=%d sdig=%d\n", set->emin, */
+       /*        dn->exponent, set->digits); */
+       if (dn->exponent+1==set->emin-set->digits+1) {
+         if (count==1 && dn->digits==1) *sup=0;  /* here 9 -> 0[.9] */
+          else {
+           *sup=(Unit)powers[count-1]-1;    /* here 999.. in msu -> 99.. */
+           dn->digits--;
            }
+         dn->exponent++;
+         *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
+         }
+       return;                              /* done */
+       }
 
-         /* a full unit to check, with more to come */
-         if (*up != 0)
-           break;              /* not still 0s */
-         count -= DECDPUN;
-       }                       /* up */
+      /* a full unit to check, with more to come */
+      if (*up!=0) break;                    /* not still 0s */
+      count-=DECDPUN;
+      } /* up */
 
-    }                          /* bump<0 */
+    } /* bump<0 */
 
   /* Actual bump needed.  Do it. */
-  decUnitAddSub (dn->lsu, D2U (dn->digits), one, 1, 0, dn->lsu, bump);
-}
+  decUnitAddSub(dn->lsu, D2U(dn->digits), uarrone, 1, 0, dn->lsu, bump);
+  } /* decApplyRound */
 
 #if DECSUBSET
 /* ------------------------------------------------------------------ */
-/* decFinish -- finish processing a number                            */
-/*                                                                    */
-/*   dn is the number                                                 */
-/*   set is the context                                               */
-/*   residue is the rounding accumulator (as in decApplyRound)        */
-/*   status is the accumulator                                        */
-/*                                                                    */
-/* This finishes off the current number by:                           */
-/*    1. If not extended:                                             */
-/*       a. Converting a zero result to clean '0'                     */
-/*       b. Reducing positive exponents to 0, if would fit in digits  */
-/*    2. Checking for overflow and subnormals (always)                */
-/* Note this is just Finalize when no subset arithmetic.              */
-/* All fields are updated as required.                                */
-/* ------------------------------------------------------------------ */
-static void
-decFinish (decNumber * dn, decContext * set, Int * residue, uInt * status)
-{
-  if (!set->extended)
-    {
-      if ISZERO
-       (dn)
-       {                       /* value is zero */
-         dn->exponent = 0;     /* clean exponent .. */
-         dn->bits = 0;         /* .. and sign */
-         return;               /* no error possible */
-       }
-      if (dn->exponent >= 0)
-       {                       /* non-negative exponent */
-         /* >0; reduce to integer if possible */
-         if (set->digits >= (dn->exponent + dn->digits))
-           {
-             dn->digits = decShiftToMost (dn->lsu, dn->digits, dn->exponent);
-             dn->exponent = 0;
-           }
+/* decFinish -- finish processing a number                           */
+/*                                                                   */
+/*   dn is the number                                                */
+/*   set is the context                                                      */
+/*   residue is the rounding accumulator (as in decApplyRound)       */
+/*   status is the accumulator                                       */
+/*                                                                   */
+/* This finishes off the current number by:                          */
+/*    1. If not extended:                                            */
+/*      a. Converting a zero result to clean '0'                     */
+/*      b. Reducing positive exponents to 0, if would fit in digits  */
+/*    2. Checking for overflow and subnormals (always)               */
+/* Note this is just Finalize when no subset arithmetic.             */
+/* All fields are updated as required.                               */
+/* ------------------------------------------------------------------ */
+static void decFinish(decNumber *dn, decContext *set, Int *residue,
+                     uInt *status) {
+  if (!set->extended) {
+    if ISZERO(dn) {               /* value is zero */
+      dn->exponent=0;             /* clean exponent .. */
+      dn->bits=0;                 /* .. and sign */
+      return;                     /* no error possible */
+      }
+    if (dn->exponent>=0) {        /* non-negative exponent */
+      /* >0; reduce to integer if possible */
+      if (set->digits >= (dn->exponent+dn->digits)) {
+       dn->digits=decShiftToMost(dn->lsu, dn->digits, dn->exponent);
+       dn->exponent=0;
        }
-    }                          /* !extended */
+      }
+    } /* !extended */
 
-  decFinalize (dn, set, residue, status);
-}
+  decFinalize(dn, set, residue, status);
+  } /* decFinish */
 #endif
 
 /* ------------------------------------------------------------------ */
-/* decFinalize -- final check, clamp, and round of a number           */
-/*                                                                    */
-/*   dn is the number                                                 */
-/*   set is the context                                               */
-/*   residue is the rounding accumulator (as in decApplyRound)        */
-/*   status is the status accumulator                                 */
-/*                                                                    */
+/* decFinalize -- final check, clamp, and round of a number          */
+/*                                                                   */
+/*   dn is the number                                                */
+/*   set is the context                                                      */
+/*   residue is the rounding accumulator (as in decApplyRound)       */
+/*   status is the status accumulator                                */
+/*                                                                   */
 /* This finishes off the current number by checking for subnormal     */
 /* results, applying any pending rounding, checking for overflow,     */
-/* and applying any clamping.                                         */
-/* Underflow and overflow conditions are raised as appropriate.       */
-/* All fields are updated as required.                                */
+/* and applying any clamping.                                        */
+/* Underflow and overflow conditions are raised as appropriate.              */
+/* All fields are updated as required.                               */
 /* ------------------------------------------------------------------ */
-static void
-decFinalize (decNumber * dn, decContext * set, Int * residue, uInt * status)
-{
-  Int shift;                   /* shift needed if clamping */
+static void decFinalize(decNumber *dn, decContext *set, Int *residue,
+                       uInt *status) {
+  Int shift;                           /* shift needed if clamping */
+  Int tinyexp=set->emin-dn->digits+1;  /* precalculate subnormal boundary */
 
-  /* We have to be careful when checking the exponent as the adjusted */
-  /* exponent could overflow 31 bits [because it may already be up */
-  /* to twice the expected]. */
+  /* Must be careful, here, when checking the exponent as the */
+  /* adjusted exponent could overflow 31 bits [because it may already */
+  /* 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. */
-  if (dn->exponent < 0         /* negative exponent */
-      && (dn->exponent < set->emin - dn->digits + 1))
-    {
+  if (dn->exponent<=tinyexp) {         /* prefilter */
+    Int comp;
+    decNumber nmin;
+    /* A very nasty case here is dn == Nmin and residue<0 */
+    if (dn->exponent<tinyexp) {
       /* Go handle subnormals; this will apply round if needed. */
-      decSetSubnormal (dn, set, residue, status);
+      decSetSubnormal(dn, set, residue, status);
+      return;
+      }
+    /* Equals case: only subnormal if dn=Nmin and negative residue */
+    decNumberZero(&nmin);
+    nmin.lsu[0]=1;
+    nmin.exponent=set->emin;
+    comp=decCompare(dn, &nmin, 1);               /* (signless compare) */
+    if (comp==BADINT) {                                  /* oops */
+      *status|=DEC_Insufficient_storage;         /* abandon... */
+      return;
+      }
+    if (*residue<0 && comp==0) {                 /* neg residue and dn==Nmin */
+      decApplyRound(dn, set, *residue, status);          /* might force down */
+      decSetSubnormal(dn, set, residue, status);
       return;
+      }
     }
 
   /* 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 */
-  if (dn->exponent <= set->emax - set->digits + 1)
-    return;                    /* neither needed */
+  if (dn->exponent<=set->emax-set->digits+1) return;   /* neither needed */
 
-  /* here when we might have an overflow or clamp to do */
-  if (dn->exponent > set->emax - dn->digits + 1)
-    {                          /* too big */
-      decSetOverflow (dn, set, status);
-      return;
+
+  /* here when might have an overflow or clamp to do */
+  if (dn->exponent>set->emax-dn->digits+1) {          /* too big */
+    decSetOverflow(dn, set, status);
+    return;
     }
   /* here when the result is normal but in clamp range */
-  if (!set->clamp)
-    return;
+  if (!set->clamp) return;
 
-  /* here when we need to apply the IEEE exponent clamp (fold-down) */
-  shift = dn->exponent - (set->emax - set->digits + 1);
+  /* here when need to apply the IEEE exponent clamp (fold-down) */
+  shift=dn->exponent-(set->emax-set->digits+1);
 
   /* shift coefficient (if non-zero) */
-  if (!ISZERO (dn))
-    {
-      dn->digits = decShiftToMost (dn->lsu, dn->digits, shift);
+  if (!ISZERO(dn)) {
+    dn->digits=decShiftToMost(dn->lsu, dn->digits, shift);
     }
-  dn->exponent -= shift;       /* adjust the exponent to match */
-  *status |= DEC_Clamped;      /* and record the dirty deed */
+  dn->exponent-=shift;  /* adjust the exponent to match */
+  *status|=DEC_Clamped;         /* and record the dirty deed */
   return;
-}
+  } /* decFinalize */
 
 /* ------------------------------------------------------------------ */
-/* decSetOverflow -- set number to proper overflow value              */
-/*                                                                    */
-/*   dn is the number (used for sign [only] and result)               */
-/*   set is the context [used for the rounding mode]                  */
-/*   status contains the current status to be updated                 */
-/*                                                                    */
-/* This sets the sign of a number and sets its value to either        */
+/* decSetOverflow -- set number to proper overflow value             */
+/*                                                                   */
+/*   dn is the number (used for sign [only] and result)                      */
+/*   set is the context [used for the rounding mode, etc.]           */
+/*   status contains the current status to be updated                */
+/*                                                                   */
+/* This sets the sign of a number and sets its value to either       */
 /* Infinity or the maximum finite value, depending on the sign of     */
-/* dn and therounding mode, following IEEE 854 rules.                 */
-/* ------------------------------------------------------------------ */
-static void
-decSetOverflow (decNumber * dn, decContext * set, uInt * status)
-{
-  Flag needmax = 0;            /* result is maximum finite value */
-  uByte sign = dn->bits & DECNEG;      /* clean and save sign bit */
-
-  if (ISZERO (dn))
-    {                          /* zero does not overflow magnitude */
-      Int emax = set->emax;    /* limit value */
-      if (set->clamp)
-       emax -= set->digits - 1;        /* lower if clamping */
-      if (dn->exponent > emax)
-       {                       /* clamp required */
-         dn->exponent = emax;
-         *status |= DEC_Clamped;
-       }
-      return;
+/* dn and the rounding mode, following IEEE 854 rules.               */
+/* ------------------------------------------------------------------ */
+static void decSetOverflow(decNumber *dn, decContext *set, uInt *status) {
+  Flag needmax=0;                 /* result is maximum finite value */
+  uByte sign=dn->bits&DECNEG;     /* clean and save sign bit */
+
+  if (ISZERO(dn)) {               /* zero does not overflow magnitude */
+    Int emax=set->emax;                             /* limit value */
+    if (set->clamp) emax-=set->digits-1;     /* lower if clamping */
+    if (dn->exponent>emax) {                /* clamp required */
+      dn->exponent=emax;
+      *status|=DEC_Clamped;
+      }
+    return;
     }
 
-  decNumberZero (dn);
-  switch (set->round)
-    {
-    case DEC_ROUND_DOWN:
-      {
-       needmax = 1;            /* never Infinity */
-       break;
-      }                                /* r-d */
-    case DEC_ROUND_CEILING:
-      {
-       if (sign)
-         needmax = 1;          /* Infinity if non-negative */
-       break;
-      }                                /* r-c */
-    case DEC_ROUND_FLOOR:
-      {
-       if (!sign)
-         needmax = 1;          /* Infinity if negative */
-       break;
-      }                                /* r-f */
-    default:
-      break;                   /* Infinity in all other cases */
+  decNumberZero(dn);
+  switch (set->round) {
+    case DEC_ROUND_DOWN: {
+      needmax=1;                  /* never Infinity */
+      break;} /* r-d */
+    case DEC_ROUND_05UP: {
+      needmax=1;                  /* never Infinity */
+      break;} /* r-05 */
+    case DEC_ROUND_CEILING: {
+      if (sign) needmax=1;        /* Infinity if non-negative */
+      break;} /* r-c */
+    case DEC_ROUND_FLOOR: {
+      if (!sign) needmax=1;       /* Infinity if negative */
+      break;} /* r-f */
+    default: break;               /* Infinity in all other cases */
     }
-  if (needmax)
-    {
-      Unit *up;                        /* work */
-      Int count = set->digits; /* nines to add */
-      dn->digits = count;
-      /* fill in all nines to set maximum value */
-      for (up = dn->lsu;; up++)
-       {
-         if (count > DECDPUN)
-           *up = DECDPUNMAX;   /* unit full o'nines */
-         else
-           {                   /* this is the msu */
-             *up = (Unit) (powers[count] - 1);
-             break;
-           }
-         count -= DECDPUN;     /* we filled those digits */
-       }                       /* up */
-      dn->bits = sign;         /* sign */
-      dn->exponent = set->emax - set->digits + 1;
+  if (needmax) {
+    decSetMaxValue(dn, set);
+    dn->bits=sign;                /* set sign */
     }
-  else
-    dn->bits = sign | DECINF;  /* Value is +/-Infinity */
-  *status |= DEC_Overflow | DEC_Inexact | DEC_Rounded;
-}
+   else dn->bits=sign|DECINF;     /* Value is +/-Infinity */
+  *status|=DEC_Overflow | DEC_Inexact | DEC_Rounded;
+  } /* decSetOverflow */
+
+/* ------------------------------------------------------------------ */
+/* decSetMaxValue -- set number to +Nmax (maximum normal value)              */
+/*                                                                   */
+/*   dn is the number to set                                         */
+/*   set is the context [used for digits and emax]                   */
+/*                                                                   */
+/* This sets the number to the maximum positive value.               */
+/* ------------------------------------------------------------------ */
+static void decSetMaxValue(decNumber *dn, decContext *set) {
+  Unit *up;                       /* work */
+  Int count=set->digits;          /* nines to add */
+  dn->digits=count;
+  /* fill in all nines to set maximum value */
+  for (up=dn->lsu; ; up++) {
+    if (count>DECDPUN) *up=DECDPUNMAX; /* unit full o'nines */
+     else {                            /* this is the msu */
+      *up=(Unit)(powers[count]-1);
+      break;
+      }
+    count-=DECDPUN;               /* filled those digits */
+    } /* up */
+  dn->bits=0;                     /* + sign */
+  dn->exponent=set->emax-set->digits+1;
+  } /* 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   */
-/*         an allowed subnormal value, which may need to be rounded)  */
-/*   set is the context [used for the rounding mode]                  */
-/*   residue is any pending residue                                   */
-/*   status contains the current status to be updated                 */
-/*                                                                    */
-/* If subset mode, set result to zero and set Underflow flags.        */
-/*                                                                    */
+/*        an allowed subnormal value, which may need to be rounded)  */
+/*   set is the context [used for the rounding mode]                 */
+/*   residue is any pending residue                                  */
+/*   status contains the current status to be updated                */
+/*                                                                   */
+/* If subset mode, set result to zero and set Underflow flags.       */
+/*                                                                   */
 /* Value may be zero with a low exponent; this does not set Subnormal */
-/* but the exponent will be clamped to Etiny.                         */
-/*                                                                    */
-/* Otherwise ensure exponent is not out of range, and round as        */
-/* necessary.  Underflow is set if the result is Inexact.             */
-/* ------------------------------------------------------------------ */
-static void
-decSetSubnormal (decNumber * dn, decContext * set,
-                Int * residue, uInt * status)
-{
-  decContext workset;          /* work */
-  Int etiny, adjust;           /* .. */
-
-#if DECSUBSET
+/* but the exponent will be clamped to Etiny.                        */
+/*                                                                   */
+/* Otherwise ensure exponent is not out of range, and round as       */
+/* necessary.  Underflow is set if the result is Inexact.            */
+/* ------------------------------------------------------------------ */
+static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
+                           uInt *status) {
+  Int       dnexp;           /* saves original exponent */
+  decContext workset;        /* work */
+  Int       etiny, adjust;   /* .. */
+
+  #if DECSUBSET
   /* simple set to zero and 'hard underflow' for subset */
-  if (!set->extended)
-    {
-      decNumberZero (dn);
-      /* always full overflow */
-      *status |= DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
-      return;
+  if (!set->extended) {
+    decNumberZero(dn);
+    /* always full overflow */
+    *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
+    return;
     }
-#endif
+  #endif
 
   /* Full arithmetic -- allow subnormals, rounded to minimum exponent */
   /* (Etiny) if needed */
-  etiny = set->emin - (set->digits - 1);       /* smallest allowed exponent */
-
-  if ISZERO
-    (dn)
-    {                          /* value is zero */
-      /* residue can never be non-zero here */
-#if DECCHECK
-      if (*residue != 0)
-       {
-         printf ("++ Subnormal 0 residue %d\n", *residue);
-         *status |= DEC_Invalid_operation;
-       }
-#endif
-      if (dn->exponent < etiny)
-       {                       /* clamp required */
-         dn->exponent = etiny;
-         *status |= DEC_Clamped;
+  etiny=set->emin-(set->digits-1);     /* smallest allowed exponent */
+
+  if ISZERO(dn) {                      /* value is zero */
+    /* residue can never be non-zero here */
+    #if DECCHECK
+      if (*residue!=0) {
+       printf("++ Subnormal 0 residue %ld\n", (LI)*residue);
+       *status|=DEC_Invalid_operation;
        }
-      return;
+    #endif
+    if (dn->exponent<etiny) {          /* clamp required */
+      dn->exponent=etiny;
+      *status|=DEC_Clamped;
+      }
+    return;
     }
 
-  *status |= DEC_Subnormal;    /* we have a non-zero subnormal */
-
-  adjust = etiny - dn->exponent;       /* calculate digits to remove */
-  if (adjust <= 0)
-    {                          /* not out of range; unrounded */
-      /* residue can never be non-zero here, so fast-path out */
-#if DECCHECK
-      if (*residue != 0)
-       {
-         printf ("++ Subnormal no-adjust residue %d\n", *residue);
-         *status |= DEC_Invalid_operation;
-       }
-#endif
-      /* it may already be inexact (from setting the coefficient) */
-      if (*status & DEC_Inexact)
-       *status |= DEC_Underflow;
-      return;
+  *status|=DEC_Subnormal;              /* have a non-zero subnormal */
+  adjust=etiny-dn->exponent;           /* calculate digits to remove */
+  if (adjust<=0) {                     /* not out of range; unrounded */
+    /* residue can never be non-zero here, except in the Nmin-residue */
+    /* case (which is a subnormal result), so can take fast-path here */
+    /* it may already be inexact (from setting the coefficient) */
+    if (*status&DEC_Inexact) *status|=DEC_Underflow;
+    return;
     }
 
-  /* adjust>0.  we 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] */
-  workset = *set;              /* clone rounding, etc. */
-  workset.digits = dn->digits - adjust;        /* set requested length */
-  workset.emin -= adjust;      /* and adjust emin to match */
+  dnexp=dn->exponent;                  /* save exponent */
+  workset=*set;                                /* clone rounding, etc. */
+  workset.digits=dn->digits-adjust;    /* set requested length */
+  workset.emin-=adjust;                        /* and adjust emin to match */
   /* [note that the latter can be <1, here, similar to Rescale case] */
-  decSetCoeff (dn, &workset, dn->lsu, dn->digits, residue, status);
-  decApplyRound (dn, &workset, *residue, status);
+  decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status);
+  decApplyRound(dn, &workset, *residue, status);
 
   /* Use 754R/854 default rule: Underflow is set iff Inexact */
   /* [independent of whether trapped] */
-  if (*status & DEC_Inexact)
-    *status |= DEC_Underflow;
-
-  /* if we rounded up a 999s case, exponent will be off by one; adjust */
-  /* back if so [it will fit, because we shortened] */
-  if (dn->exponent > etiny)
-    {
-      dn->digits = decShiftToMost (dn->lsu, dn->digits, 1);
-      dn->exponent--;          /* (re)adjust the exponent. */
+  if (*status&DEC_Inexact) *status|=DEC_Underflow;
+
+  /* if rounded up a 999s case, exponent will be off by one; adjust */
+  /* back if so [it will fit, because it was shortened earlier] */
+  if (dn->exponent>etiny) {
+    dn->digits=decShiftToMost(dn->lsu, dn->digits, 1);
+    dn->exponent--;                    /* (re)adjust the exponent. */
     }
-}
 
-/* ------------------------------------------------------------------ */
-/* decGetInt -- get integer from a number                             */
-/*                                                                    */
-/*   dn is the number [which will not be altered]                     */
-/*   set is the context [requested digits], subset only               */
-/*   returns the converted integer, or BADINT if error                */
-/*                                                                    */
+  /* if rounded to zero, it is by definition clamped... */
+  if (ISZERO(dn)) *status|=DEC_Clamped;
+  } /* decSetSubnormal */
+
+/* ------------------------------------------------------------------ */
+/* decCheckMath - check entry conditions for a math function         */
+/*                                                                   */
+/*   This checks the context and the operand                         */
+/*                                                                   */
+/*   rhs is the operand to check                                     */
+/*   set is the context to check                                     */
+/*   status is unchanged if both are good                            */
+/*                                                                   */
+/* returns non-zero if status is changed, 0 otherwise                */
+/*                                                                   */
+/* Restrictions enforced:                                            */
+/*                                                                   */
+/*   digits, emax, and -emin in the context must be less than        */
+/*   DEC_MAX_MATH (999999), and A must be within these bounds if      */
+/*   non-zero. Invalid_operation is set in the status if a           */
+/*   restriction is violated.                                        */
+/* ------------------------------------------------------------------ */
+static uInt decCheckMath(const decNumber *rhs, decContext *set,
+                        uInt *status) {
+  uInt save=*status;                        /* record */
+  if (set->digits>DEC_MAX_MATH
+   || set->emax>DEC_MAX_MATH
+   || -set->emin>DEC_MAX_MATH) *status|=DEC_Invalid_context;
+   else if ((rhs->digits>DEC_MAX_MATH
+     || rhs->exponent+rhs->digits>DEC_MAX_MATH+1
+     || rhs->exponent+rhs->digits<2*(1-DEC_MAX_MATH))
+     && !ISZERO(rhs)) *status|=DEC_Invalid_operation;
+  return (*status!=save);
+  } /* decCheckMath */
+
+/* ------------------------------------------------------------------ */
+/* decGetInt -- get integer from a number                            */
+/*                                                                   */
+/*   dn is the number [which will not be altered]                    */
+/*                                                                   */
+/*   returns one of:                                                 */
+/*     BADINT if there is a non-zero fraction                        */
+/*     the converted integer                                         */
+/*     BIGEVEN if the integer is even 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.      */
-/* The magnitude of the integer must be <2^31.                        */
-/* Any discarded fractional part must be 0.                           */
-/* If subset it must also fit in set->digits                          */
+/* The sign can be determined from dn by the caller when BIGEVEN or   */
+/* BIGODD is returned.                                               */
 /* ------------------------------------------------------------------ */
-#if DECSUBSET
-static Int
-decGetInt (const decNumber * dn, decContext * set)
-{
-#else
-static Int
-decGetInt (const decNumber * dn)
-{
-#endif
-  Int theInt;                  /* result accumulator */
-  const Unit *up;              /* work */
-  Int got;                     /* digits (real or not) processed */
-  Int ilength = dn->digits + dn->exponent;     /* integral length */
+static Int decGetInt(const decNumber *dn) {
+  Int  theInt;                         /* result accumulator */
+  const Unit *up;                      /* work */
+  Int  got;                            /* digits (real or not) processed */
+  Int  ilength=dn->digits+dn->exponent; /* integral length */
+  Flag neg=decNumberIsNegative(dn);    /* 1 if -ve */
 
   /* The number must be an integer that fits in 10 digits */
   /* Assert, here, that 10 is enough for any rescale Etiny */
-#if DEC_MAX_EMAX > 999999999
-#error GetInt may need updating [for Emax]
-#endif
-#if DEC_MIN_EMIN < -999999999
-#error GetInt may need updating [for Emin]
-#endif
-  if (ISZERO (dn))
-    return 0;                  /* zeros are OK, with any exponent */
-  if (ilength > 10)
-    return BADINT;             /* always too big */
-#if DECSUBSET
-  if (!set->extended && ilength > set->digits)
-    return BADINT;
-#endif
-
-  up = dn->lsu;                        /* ready for lsu */
-  theInt = 0;                  /* ready to accumulate */
-  if (dn->exponent >= 0)
-    {                          /* relatively easy */
-      /* no fractional part [usual]; allow for positive exponent */
-      got = dn->exponent;
+  #if DEC_MAX_EMAX > 999999999
+    #error GetInt may need updating [for Emax]
+  #endif
+  #if DEC_MIN_EMIN < -999999999
+    #error GetInt may need updating [for Emin]
+  #endif
+  if (ISZERO(dn)) return 0;            /* zeros are OK, with any exponent */
+
+  up=dn->lsu;                          /* ready for lsu */
+  theInt=0;                            /* ready to accumulate */
+  if (dn->exponent>=0) {               /* relatively easy */
+    /* no fractional part [usual]; allow for positive exponent */
+    got=dn->exponent;
     }
-  else
-    {                          /* -ve exponent; some fractional part to check and discard */
-      Int count = -dn->exponent;       /* digits to discard */
-      /* spin up whole units until we get to the Unit with the unit digit */
-      for (; count >= DECDPUN; up++)
-       {
-         if (*up != 0)
-           return BADINT;      /* non-zero Unit to discard */
-         count -= DECDPUN;
-       }
-      if (count == 0)
-       got = 0;                /* [a multiple of DECDPUN] */
-      else
-       {                       /* [not multiple of DECDPUN] */
-         Int rem;              /* work */
-         /* slice off fraction digits and check for non-zero */
-#if DECDPUN<=4
-         theInt = QUOT10 (*up, count);
-         rem = *up - theInt * powers[count];
-#else
-         rem = *up % powers[count];    /* slice off discards */
-         theInt = *up / powers[count];
-#endif
-         if (rem != 0)
-           return BADINT;      /* non-zero fraction */
-         /* OK, we're good */
-         got = DECDPUN - count;        /* number of digits so far */
-         up++;                 /* ready for next */
-       }
+   else { /* -ve exponent; some fractional part to check and discard */
+    Int count=-dn->exponent;           /* digits to discard */
+    /* spin up whole units until reach the Unit with the unit digit */
+    for (; count>=DECDPUN; up++) {
+      if (*up!=0) return BADINT;       /* non-zero Unit to discard */
+      count-=DECDPUN;
+      }
+    if (count==0) got=0;               /* [a multiple of DECDPUN] */
+     else {                            /* [not multiple of DECDPUN] */
+      Int rem;                         /* work */
+      /* slice off fraction digits and check for non-zero */
+      #if DECDPUN<=4
+       theInt=QUOT10(*up, count);
+       rem=*up-theInt*powers[count];
+      #else
+       rem=*up%powers[count];          /* slice off discards */
+       theInt=*up/powers[count];
+      #endif
+      if (rem!=0) return BADINT;       /* non-zero fraction */
+      /* it looks good */
+      got=DECDPUN-count;               /* number of digits so far */
+      up++;                            /* ready for next */
+      }
+    }
+  /* now it's known there's no fractional part */
+
+  /* tricky code now, to accumulate up to 9.3 digits */
+  if (got==0) {theInt=*up; got+=DECDPUN; up++;} /* ensure lsu is there */
+
+  if (ilength<11) {
+    Int save=theInt;
+    /* collect any remaining unit(s) */
+    for (; got<ilength; up++) {
+      theInt+=*up*powers[got];
+      got+=DECDPUN;
+      }
+    if (ilength==10) {                 /* need to check for wrap */
+      if (theInt/(Int)powers[got-DECDPUN]!=(Int)*(up-1)) ilength=11;
+        /* [that test also disallows the BADINT result case] */
+       else if (neg && theInt>1999999997) ilength=11;
+       else if (!neg && theInt>999999999) ilength=11;
+      if (ilength==11) theInt=save;    /* restore correct low bit */
+      }
     }
-  /* collect the rest */
-  for (; got < ilength; up++)
-    {
-      theInt += *up * powers[got];
-      got += DECDPUN;
+
+  if (ilength>10) {                    /* too big */
+    if (theInt&1) return BIGODD;       /* bottom bit 1 */
+    return BIGEVEN;                    /* bottom bit 0 */
     }
-  if ((ilength == 10)          /* check no wrap */
-      && (theInt / (Int) powers[got - DECDPUN] != *(up - 1)))
-    return BADINT;
-  /* [that test also disallows the BADINT result case] */
-
-  /* apply any sign and return */
-  if (decNumberIsNegative (dn))
-    theInt = -theInt;
+
+  if (neg) theInt=-theInt;             /* apply sign */
   return theInt;
-}
-
-/* ------------------------------------------------------------------ */
-/* decStrEq -- caseless comparison of strings                         */
-/*                                                                    */
-/*   str1 is one of the strings to compare                            */
-/*   str2 is the other                                                */
-/*                                                                    */
-/*   returns 1 if strings caseless-compare equal, 0 otherwise         */
-/*                                                                    */
-/* Note that the strings must be the same length if they are to       */
-/* compare equal; there is no padding.                                */
-/* ------------------------------------------------------------------ */
-/* [strcmpi is not in ANSI C] */
-static Flag
-decStrEq (const char *str1, const char *str2)
-{
-  for (;; str1++, str2++)
-    {
-      unsigned char u1 = (unsigned char) *str1;
-      unsigned char u2 = (unsigned char) *str2;
-      if (u1 == u2)
-       {
-         if (u1 == '\0')
-           break;
-       }
-      else
-       {
-         if (tolower (u1) != tolower (u2))
-           return 0;
-       }
-    }                          /* stepping */
+  } /* decGetInt */
+
+/* ------------------------------------------------------------------ */
+/* decDecap -- decapitate the coefficient of a number                */
+/*                                                                   */
+/*   dn          is the number to be decapitated                             */
+/*   drop is the number of digits to be removed from the left of dn;  */
+/*     this must be <= dn->digits (if equal, the coefficient is              */
+/*     set to 0)                                                     */
+/*                                                                   */
+/* Returns dn; dn->digits will be <= the initial digits less drop     */
+/* (after removing drop digits there may be leading zero digits              */
+/* which will also be removed).         Only dn->lsu and dn->digits change.  */
+/* ------------------------------------------------------------------ */
+static decNumber *decDecap(decNumber *dn, Int drop) {
+  Unit *msu;                           /* -> target cut point */
+  Int cut;                             /* work */
+  if (drop>=dn->digits) {              /* losing the whole thing */
+    #if DECCHECK
+    if (drop>dn->digits)
+      printf("decDecap called with drop>digits [%ld>%ld]\n",
+            (LI)drop, (LI)dn->digits);
+    #endif
+    dn->lsu[0]=0;
+    dn->digits=1;
+    return dn;
+    }
+  msu=dn->lsu+D2U(dn->digits-drop)-1;  /* -> likely msu */
+  cut=MSUDIGITS(dn->digits-drop);      /* digits to be in use in msu */
+  if (cut!=DECDPUN) *msu%=powers[cut]; /* clear left digits */
+  /* that may have left leading zero digits, so do a proper count... */
+  dn->digits=decGetDigits(dn->lsu, msu-dn->lsu+1);
+  return dn;
+  } /* decDecap */
+
+/* ------------------------------------------------------------------ */
+/* decBiStr -- compare string with pairwise options                  */
+/*                                                                   */
+/*   targ is the string to compare                                   */
+/*   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           */
+/*                                                                   */
+/*   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 */
+/*   str1 or str2 in the corresponding position), or 0 otherwise      */
+/*                                                                   */
+/* This is used for generic caseless compare, including the awkward   */
+/* case of the Turkish dotted and dotless Is.  Use as (for example):  */
+/*   if (decBiStr(test, "mike", "MIKE")) ...                         */
+/* ------------------------------------------------------------------ */
+static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
+  for (;;targ++, str1++, str2++) {
+    if (*targ!=*str1 && *targ!=*str2) return 0;
+    /* *targ has a match in one (or both, if terminator) */
+    if (*targ=='\0') break;
+    } /* forever */
   return 1;
-}
-
-/* ------------------------------------------------------------------ */
-/* decNaNs -- handle NaN operand or operands                          */
-/*                                                                    */
-/*   res    is the result number                                      */
-/*   lhs    is the first operand                                      */
-/*   rhs    is the second operand, or NULL if none                    */
-/*   status contains the current status                               */
-/*   returns res in case convenient                                   */
-/*                                                                    */
+  } /* decBiStr */
+
+/* ------------------------------------------------------------------ */
+/* decNaNs -- handle NaN operand or operands                         */
+/*                                                                   */
+/*   res     is the result number                                    */
+/*   lhs     is the first operand                                    */
+/*   rhs     is the second operand, or NULL if none                  */
+/*   context is used to limit payload length                         */
+/*   status  contains the current status                             */
+/*   returns res in case convenient                                  */
+/*                                                                   */
 /* Called when one or both operands is a NaN, and propagates the      */
 /* 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, const decNumber * rhs, uInt * status)
-{
+static decNumber * decNaNs(decNumber *res, const decNumber *lhs,
+                          const decNumber *rhs, decContext *set,
+                          uInt *status) {
   /* This decision tree ends up with LHS being the source pointer, */
   /* and status updated if need be */
   if (lhs->bits & DECSNAN)
-    *status |= DEC_Invalid_operation | DEC_sNaN;
-  else if (rhs == NULL);
-  else if (rhs->bits & DECSNAN)
-    {
-      lhs = rhs;
-      *status |= DEC_Invalid_operation | DEC_sNaN;
+    *status|=DEC_Invalid_operation | DEC_sNaN;
+   else if (rhs==NULL);
+   else if (rhs->bits & DECSNAN) {
+    lhs=rhs;
+    *status|=DEC_Invalid_operation | DEC_sNaN;
     }
-  else if (lhs->bits & DECNAN);
-  else
-    lhs = rhs;
-
-  decNumberCopy (res, lhs);
-  res->bits &= ~DECSNAN;       /* convert any sNaN to NaN, while */
-  res->bits |= DECNAN;         /* .. preserving sign */
-  res->exponent = 0;           /* clean exponent */
-  /* [coefficient was copied] */
+   else if (lhs->bits & DECNAN);
+   else lhs=rhs;
+
+  /* propagate the payload */
+  if (lhs->digits<=set->digits) decNumberCopy(res, lhs); /* easy */
+   else { /* too long */
+    const Unit *ul;
+    Unit *ur, *uresp1;
+    /* copy safe number of units, then decapitate */
+    res->bits=lhs->bits;               /* need sign etc. */
+    uresp1=res->lsu+D2U(set->digits);
+    for (ur=res->lsu, ul=lhs->lsu; ur<uresp1; ur++, ul++) *ur=*ul;
+    res->digits=D2U(set->digits)*DECDPUN;
+    /* maybe still too long */
+    if (res->digits>set->digits) decDecap(res, res->digits-set->digits);
+    }
+
+  res->bits&=~DECSNAN;       /* convert any sNaN to NaN, while */
+  res->bits|=DECNAN;         /* .. preserving sign */
+  res->exponent=0;           /* clean exponent */
+                             /* [coefficient was copied/decapitated] */
   return res;
-}
+  } /* decNaNs */
 
 /* ------------------------------------------------------------------ */
-/* decStatus -- apply non-zero status                                 */
-/*                                                                    */
-/*   dn     is the number to set if error                             */
-/*   status contains the current status (not yet in context)          */
-/*   set    is the context                                            */
-/*                                                                    */
+/* decStatus -- apply non-zero status                                */
+/*                                                                   */
+/*   dn            is the number to set if error                             */
+/*   status contains the current status (not yet in context)         */
+/*   set    is the context                                           */
+/*                                                                   */
 /* 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,    */
-/* 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 */
 /* this may raise a signal, so control may never return from this     */
 /* routine (hence resources must be recovered before it is called).   */
 /* ------------------------------------------------------------------ */
-static void
-decStatus (decNumber * dn, uInt status, decContext * set)
-{
-  if (status & DEC_NaNs)
-    {                          /* error status -> NaN */
-      /* if cause was an sNaN, clear and propagate [NaN is already set up] */
-      if (status & DEC_sNaN)
-       status &= ~DEC_sNaN;
-      else
-       {
-         decNumberZero (dn);   /* other error: clean throughout */
-         dn->bits = DECNAN;    /* and make a quiet NaN */
-       }
+static void decStatus(decNumber *dn, uInt status, decContext *set) {
+  if (status & DEC_NaNs) {             /* error status -> NaN */
+    /* if cause was an sNaN, clear and propagate [NaN is already set up] */
+    if (status & DEC_sNaN) status&=~DEC_sNaN;
+     else {
+      decNumberZero(dn);               /* other error: clean throughout */
+      dn->bits=DECNAN;                 /* and make a quiet NaN */
+      }
     }
-  decContextSetStatus (set, status);
+  decContextSetStatus(set, status);    /* [may not return] */
   return;
-}
+  } /* decStatus */
 
 /* ------------------------------------------------------------------ */
-/* decGetDigits -- count digits in a Units array                      */
-/*                                                                    */
-/*   uar is the Unit array holding the number [this is often an       */
-/*          accumulator of some sort]                                 */
-/*   len is the length of the array in units                          */
-/*                                                                    */
-/*   returns the number of (significant) digits in the array          */
-/*                                                                    */
+/* decGetDigits -- count digits in a Units array                     */
+/*                                                                   */
+/*   uar is the Unit array holding the number (this is often an              */
+/*         accumulator of some sort)                                 */
+/*   len is the length of the array in units [>=1]                   */
+/*                                                                   */
+/*   returns the number of (significant) digits in the array         */
+/*                                                                   */
 /* 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. */
-static Int
-decGetDigits (const Unit * uar, Int len)
-{
-  const Unit *up = uar + len - 1;      /* -> msu */
-  Int digits = len * DECDPUN;  /* maximum possible digits */
-  uInt const *pow;             /* work */
-
-  for (; up >= uar; up--)
-    {
-      digits -= DECDPUN;
-      if (*up == 0)
-       {                       /* unit is 0 */
-         if (digits != 0)
-           continue;           /* more to check */
-         /* all units were 0 */
-         digits++;             /* .. so bump digits to 1 */
-         break;
-       }
-      /* found the first non-zero Unit */
-      digits++;
-      if (*up < 10)
-       break;                  /* fastpath 1-9 */
-      digits++;
-      for (pow = &powers[2]; *up >= *pow; pow++)
-       digits++;
-      break;
-    }                          /* up */
-
+static Int decGetDigits(Unit *uar, Int len) {
+  Unit *up=uar+(len-1);                   /* -> msu */
+  Int  digits=(len-1)*DECDPUN+1;   /* possible digits excluding msu */
+  #if DECDPUN>4
+  uInt const *pow;                /* work */
+  #endif
+                                  /* (at least 1 in final msu) */
+  #if DECCHECK
+  if (len<1) printf("decGetDigits called with len<1 [%ld]\n", (LI)len);
+  #endif
+
+  for (; up>=uar; up--) {
+    if (*up==0) {                 /* unit is all 0s */
+      if (digits==1) break;       /* a zero has one digit */
+      digits-=DECDPUN;            /* adjust for 0 unit */
+      continue;}
+    /* found the first (most significant) non-zero Unit */
+    #if DECDPUN>1                 /* not done yet */
+    if (*up<10) break;            /* is 1-9 */
+    digits++;
+    #if DECDPUN>2                 /* not done yet */
+    if (*up<100) break;                   /* is 10-99 */
+    digits++;
+    #if DECDPUN>3                 /* not done yet */
+    if (*up<1000) break;          /* is 100-999 */
+    digits++;
+    #if DECDPUN>4                 /* count the rest ... */
+    for (pow=&powers[4]; *up>=*pow; pow++) digits++;
+    #endif
+    #endif
+    #endif
+    #endif
+    break;
+    } /* up */
   return digits;
-}
-
+  } /* decGetDigits */
 
 #if DECTRACE | DECCHECK
 /* ------------------------------------------------------------------ */
-/* decNumberShow -- display a number [debug aid]                      */
-/*   dn is the number to show                                         */
-/*                                                                    */
-/* Shows: sign, exponent, coefficient (msu first), digits             */
-/*    or: sign, special-value                                         */
+/* decNumberShow -- display a number [debug aid]                     */
+/*   dn is the number to show                                        */
+/*                                                                   */
+/* Shows: sign, exponent, coefficient (msu first), digits            */
+/*    or: sign, special-value                                        */
 /* ------------------------------------------------------------------ */
 /* this is public so other modules can use it */
-void
-decNumberShow (const decNumber * dn)
-{
-  const Unit *up;              /* work */
-  uInt u, d;                   /* .. */
-  Int cut;                     /* .. */
-  char isign = '+';            /* main sign */
-  if (dn == NULL)
-    {
-      printf ("NULL\n");
-      return;
-    }
-  if (decNumberIsNegative (dn))
-    isign = '-';
-  printf (" >> %c ", isign);
-  if (dn->bits & DECSPECIAL)
-    {                          /* Is a special value */
-      if (decNumberIsInfinite (dn))
-       printf ("Infinity");
-      else
-       {                       /* a NaN */
-         if (dn->bits & DECSNAN)
-           printf ("sNaN");    /* signalling NaN */
-         else
-           printf ("NaN");
-       }
-      /* if coefficient and exponent are 0, we're done */
-      if (dn->exponent == 0 && dn->digits == 1 && *dn->lsu == 0)
-       {
-         printf ("\n");
-         return;
-       }
-      /* drop through to report other information */
-      printf (" ");
+void decNumberShow(const decNumber *dn) {
+  const Unit *up;                 /* work */
+  uInt u, d;                      /* .. */
+  Int cut;                        /* .. */
+  char isign='+';                 /* main sign */
+  if (dn==NULL) {
+    printf("NULL\n");
+    return;}
+  if (decNumberIsNegative(dn)) isign='-';
+  printf(" >> %c ", isign);
+  if (dn->bits&DECSPECIAL) {      /* Is a special value */
+    if (decNumberIsInfinite(dn)) printf("Infinity");
+     else {                                 /* a NaN */
+      if (dn->bits&DECSNAN) printf("sNaN");  /* signalling NaN */
+       else printf("NaN");
+      }
+    /* if coefficient and exponent are 0, no more to do */
+    if (dn->exponent==0 && dn->digits==1 && *dn->lsu==0) {
+      printf("\n");
+      return;}
+    /* drop through to report other information */
+    printf(" ");
     }
 
   /* now carefully display the coefficient */
-  up = dn->lsu + D2U (dn->digits) - 1; /* msu */
-  printf ("%d", *up);
-  for (up = up - 1; up >= dn->lsu; up--)
-    {
-      u = *up;
-      printf (":");
-      for (cut = DECDPUN - 1; cut >= 0; cut--)
-       {
-         d = u / powers[cut];
-         u -= d * powers[cut];
-         printf ("%d", d);
-       }                       /* cut */
-    }                          /* up */
-  if (dn->exponent != 0)
-    {
-      char esign = '+';
-      if (dn->exponent < 0)
-       esign = '-';
-      printf (" E%c%d", esign, abs (dn->exponent));
+  up=dn->lsu+D2U(dn->digits)-1;                /* msu */
+  printf("%ld", (LI)*up);
+  for (up=up-1; up>=dn->lsu; up--) {
+    u=*up;
+    printf(":");
+    for (cut=DECDPUN-1; cut>=0; cut--) {
+      d=u/powers[cut];
+      u-=d*powers[cut];
+      printf("%ld", (LI)d);
+      } /* cut */
+    } /* up */
+  if (dn->exponent!=0) {
+    char esign='+';
+    if (dn->exponent<0) esign='-';
+    printf(" E%c%ld", esign, (LI)abs(dn->exponent));
     }
-  printf (" [%d]\n", dn->digits);
-}
+  printf(" [%ld]\n", (LI)dn->digits);
+  } /* decNumberShow */
 #endif
 
 #if DECTRACE || DECCHECK
 /* ------------------------------------------------------------------ */
-/* decDumpAr -- display a unit array [debug aid]                      */
-/*   name is a single-character tag name                              */
-/*   ar   is the array to display                                     */
-/*   len  is the length of the array in Units                         */
+/* decDumpAr -- display a unit array [debug/check aid]               */
+/*   name is a single-character tag name                             */
+/*   ar          is the array to display                                     */
+/*   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;
-#if DECDPUN==4
-  const char *spec = "%04d ";
-#else
-  const char *spec = "%d ";
-#endif
-  printf ("  :%c: ", name);
-  for (i = len - 1; i >= 0; i--)
-    {
-      if (i == len - 1)
-       printf ("%d ", ar[i]);
-      else
-       printf (spec, ar[i]);
+  const char *spec;
+  #if DECDPUN==9
+    spec="%09d ";
+  #elif DECDPUN==8
+    spec="%08d ";
+  #elif DECDPUN==7
+    spec="%07d ";
+  #elif DECDPUN==6
+    spec="%06d ";
+  #elif DECDPUN==5
+    spec="%05d ";
+  #elif DECDPUN==4
+    spec="%04d ";
+  #elif DECDPUN==3
+    spec="%03d ";
+  #elif DECDPUN==2
+    spec="%02d ";
+  #else
+    spec="%d ";
+  #endif
+  printf("  :%c: ", name);
+  for (i=len-1; i>=0; i--) {
+    if (i==len-1) printf("%ld ", (LI)ar[i]);
+     else printf(spec, ar[i]);
     }
-  printf ("\n");
-  return;
-}
+  printf("\n");
+  return;}
 #endif
 
 #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      */
-/*          quiet NaN if error found (and it is not NULL))            */
-/*   lhs is the first operand (may be DECUNUSED)                      */
-/*   rhs is the second (may be DECUNUSED)                             */
-/*   set is the context (may be DECUNUSED)                            */
+/*         quiet NaN if error found (and it is not NULL))            */
+/*   lhs is the first operand (may be DECUNRESU)                     */
+/*   rhs is the second (may be DECUNUSED)                            */
+/*   set is the context (may be DECUNCONT)                           */
 /*   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     */
-/*     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.    */
 /* ------------------------------------------------------------------ */
-static Flag
-decCheckOperands (decNumber * res, const decNumber * lhs,
-                 const decNumber * rhs, decContext * set)
-{
-  Flag bad = 0;
-  if (set == NULL)
-    {                          /* oops; hopeless */
-#if DECTRACE
-      printf ("Context is NULL.\n");
-#endif
-      bad = 1;
-      return 1;
+static Flag decCheckOperands(decNumber *res, const decNumber *lhs,
+                            const decNumber *rhs, decContext *set) {
+  Flag bad=0;
+  if (set==NULL) {                /* oops; hopeless */
+    #if DECTRACE || DECVERB
+    printf("Reference to context is NULL.\n");
+    #endif
+    bad=1;
+    return 1;}
+   else if (set!=DECUNCONT
+     && (set->digits<1 || set->round>=DEC_ROUND_MAX)) {
+    bad=1;
+    #if DECTRACE || DECVERB
+    printf("Bad context [digits=%ld round=%ld].\n",
+          (LI)set->digits, (LI)set->round);
+    #endif
     }
-  else if (set != DECUNUSED
-          && (set->digits < 1 || set->round < 0
-              || set->round >= DEC_ROUND_MAX))
-    {
-      bad = 1;
-#if DECTRACE
-      printf ("Bad context [digits=%d round=%d].\n", set->digits, set->round);
-#endif
-    }
-  else
-    {
-      if (res == NULL)
-       {
-         bad = 1;
-#if DECTRACE
-         printf ("Bad result [is NULL].\n");
-#endif
-       }
-      if (!bad && lhs != DECUNUSED)
-       bad = (decCheckNumber (lhs, set));
-      if (!bad && rhs != DECUNUSED)
-       bad = (decCheckNumber (rhs, set));
+   else {
+    if (res==NULL) {
+      bad=1;
+      #if DECTRACE
+      /* this one not DECVERB as standard tests include NULL */
+      printf("Reference to result is NULL.\n");
+      #endif
+      }
+    if (!bad && lhs!=DECUNUSED) bad=(decCheckNumber(lhs));
+    if (!bad && rhs!=DECUNUSED) bad=(decCheckNumber(rhs));
     }
-  if (bad)
-    {
-      if (set != DECUNUSED)
-       decContextSetStatus (set, DEC_Invalid_operation);
-      if (res != DECUNUSED && res != NULL)
-       {
-         decNumberZero (res);
-         res->bits = DECNAN;   /* qNaN */
-       }
+  if (bad) {
+    if (set!=DECUNCONT) decContextSetStatus(set, DEC_Invalid_operation);
+    if (res!=DECUNRESU && res!=NULL) {
+      decNumberZero(res);
+      res->bits=DECNAN;              /* qNaN */
+      }
     }
   return bad;
-}
+  } /* decCheckOperands */
 
 /* ------------------------------------------------------------------ */
-/* decCheckNumber -- check a number                                   */
-/*   dn is the number to check                                        */
-/*   set is the context (may be DECUNUSED)                            */
-/*   returns 0 if the number is clean, or 1 otherwise                 */
-/*                                                                    */
+/* decCheckNumber -- check a number                                  */
+/*   dn is the number to check                                       */
+/*   returns 0 if the number is clean, or 1 otherwise                */
+/*                                                                   */
 /* The number is considered valid if it could be a result from some   */
-/* operation in some valid context (not necessarily the current one). */
-/* ------------------------------------------------------------------ */
-Flag
-decCheckNumber (const decNumber * dn, decContext * set)
-{
-  const Unit *up;              /* work */
-  uInt maxuint;                        /* .. */
-  Int ae, d, digits;           /* .. */
-  Int emin, emax;              /* .. */
-
-  if (dn == NULL)
-    {                          /* hopeless */
-#if DECTRACE
-      printf ("Reference to decNumber is NULL.\n");
-#endif
-      return 1;
-    }
+/* operation in some valid context.                                  */
+/* ------------------------------------------------------------------ */
+static Flag decCheckNumber(const decNumber *dn) {
+  const Unit *up;            /* work */
+  uInt maxuint;                      /* .. */
+  Int ae, d, digits;         /* .. */
+  Int emin, emax;            /* .. */
 
-  /* check special values */
-  if (dn->bits & DECSPECIAL)
-    {
-      if (dn->exponent != 0)
-       {
-#if DECTRACE
-         printf ("Exponent %d (not 0) for a special value.\n", dn->exponent);
-#endif
-         return 1;
-       }
+  if (dn==NULL) {            /* hopeless */
+    #if DECTRACE
+    /* this one not DECVERB as standard tests include NULL */
+    printf("Reference to decNumber is NULL.\n");
+    #endif
+    return 1;}
 
-      /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */
-      if (decNumberIsInfinite (dn))
-       {
-         if (dn->digits != 1)
-           {
-#if DECTRACE
-             printf ("Digits %d (not 1) for an infinity.\n", dn->digits);
-#endif
-             return 1;
-           }
-         if (*dn->lsu != 0)
-           {
-#if DECTRACE
-             printf ("LSU %d (not 0) for an infinity.\n", *dn->lsu);
-#endif
-             return 1;
-           }
-       }                       /* Inf */
-      /* 2002.12.26: negative NaNs can now appear through proposed IEEE */
-      /*             concrete formats (decimal64, etc.), though they are */
-      /*             never visible in strings. */
-      return 0;
-
-      /* if ((dn->bits & DECINF) || (dn->bits & DECNEG)==0) return 0; */
-      /* #if DECTRACE */
-      /* printf("Negative NaN in number.\n"); */
-      /* #endif */
-      /* return 1; */
+  /* check special values */
+  if (dn->bits & DECSPECIAL) {
+    if (dn->exponent!=0) {
+      #if DECTRACE || DECVERB
+      printf("Exponent %ld (not 0) for a special value [%02x].\n",
+            (LI)dn->exponent, dn->bits);
+      #endif
+      return 1;}
+
+    /* 2003.09.08: NaNs may now have coefficients, so next tests Inf only */
+    if (decNumberIsInfinite(dn)) {
+      if (dn->digits!=1) {
+       #if DECTRACE || DECVERB
+       printf("Digits %ld (not 1) for an infinity.\n", (LI)dn->digits);
+       #endif
+       return 1;}
+      if (*dn->lsu!=0) {
+       #if DECTRACE || DECVERB
+       printf("LSU %ld (not 0) for an infinity.\n", (LI)*dn->lsu);
+       #endif
+       decDumpAr('I', dn->lsu, D2U(dn->digits));
+       return 1;}
+      } /* Inf */
+    /* 2002.12.26: negative NaNs can now appear through proposed IEEE */
+    /*            concrete formats (decimal64, etc.). */
+    return 0;
     }
 
   /* check the coefficient */
-  if (dn->digits < 1 || dn->digits > DECNUMMAXP)
-    {
-#if DECTRACE
-      printf ("Digits %d in number.\n", dn->digits);
-#endif
-      return 1;
-    }
-
-  d = dn->digits;
-
-  for (up = dn->lsu; d > 0; up++)
-    {
-      if (d > DECDPUN)
-       maxuint = DECDPUNMAX;
-      else
-       {                       /* we are at the msu */
-         maxuint = powers[d] - 1;
-         if (dn->digits > 1 && *up < powers[d - 1])
-           {
-#if DECTRACE
-             printf ("Leading 0 in number.\n");
-             decNumberShow (dn);
-#endif
-             return 1;
-           }
-       }
-      if (*up > maxuint)
-       {
-#if DECTRACE
-         printf ("Bad Unit [%08x] in number at offset %d [maxuint %d].\n",
-                 *up, up - dn->lsu, maxuint);
-#endif
-         return 1;
-       }
-      d -= DECDPUN;
+  if (dn->digits<1 || dn->digits>DECNUMMAXP) {
+    #if DECTRACE || DECVERB
+    printf("Digits %ld in number.\n", (LI)dn->digits);
+    #endif
+    return 1;}
+
+  d=dn->digits;
+
+  for (up=dn->lsu; d>0; up++) {
+    if (d>DECDPUN) maxuint=DECDPUNMAX;
+     else {                  /* reached the msu */
+      maxuint=powers[d]-1;
+      if (dn->digits>1 && *up<powers[d-1]) {
+       #if DECTRACE || DECVERB
+       printf("Leading 0 in number.\n");
+       decNumberShow(dn);
+       #endif
+       return 1;}
+      }
+    if (*up>maxuint) {
+      #if DECTRACE || DECVERB
+      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);
+      #endif
+      return 1;}
+    d-=DECDPUN;
     }
 
   /* check the exponent.  Note that input operands can have exponents */
   /* which are out of the set->emin/set->emax and set->digits range */
   /* (just as they can have more digits than set->digits). */
-  ae = dn->exponent + dn->digits - 1;  /* adjusted exponent */
-  emax = DECNUMMAXE;
-  emin = DECNUMMINE;
-  digits = DECNUMMAXP;
-  if (ae < emin - (digits - 1))
-    {
-#if DECTRACE
-      printf ("Adjusted exponent underflow [%d].\n", ae);
-      decNumberShow (dn);
-#endif
-      return 1;
-    }
-  if (ae > +emax)
-    {
-#if DECTRACE
-      printf ("Adjusted exponent overflow [%d].\n", ae);
-      decNumberShow (dn);
-#endif
-      return 1;
-    }
-
-  return 0;                    /* it's OK */
-}
+  ae=dn->exponent+dn->digits-1;           /* adjusted exponent */
+  emax=DECNUMMAXE;
+  emin=DECNUMMINE;
+  digits=DECNUMMAXP;
+  if (ae<emin-(digits-1)) {
+    #if DECTRACE || DECVERB
+    printf("Adjusted exponent underflow [%ld].\n", (LI)ae);
+    decNumberShow(dn);
+    #endif
+    return 1;}
+  if (ae>+emax) {
+    #if DECTRACE || DECVERB
+    printf("Adjusted exponent overflow [%ld].\n", (LI)ae);
+    decNumberShow(dn);
+    #endif
+    return 1;}
+
+  return 0;             /* it's OK */
+  } /* decCheckNumber */
+
+/* ------------------------------------------------------------------ */
+/* decCheckInexact -- check a normal finite inexact result has digits */
+/*   dn is the number to check                                       */
+/*   set is the context (for status and precision)                   */
+/*   sets Invalid operation, etc., if some digits are missing        */
+/* [this check is not made for DECSUBSET compilation or when         */
+/* subnormal is not set]                                             */
+/* ------------------------------------------------------------------ */
+static void decCheckInexact(const decNumber *dn, decContext *set) {
+  #if !DECSUBSET && DECEXTFLAG
+    if ((set->status & (DEC_Inexact|DEC_Subnormal))==DEC_Inexact
+     && (set->digits!=dn->digits) && !(dn->bits & DECSPECIAL)) {
+      #if DECTRACE || DECVERB
+      printf("Insufficient digits [%ld] on normal Inexact result.\n",
+            (LI)dn->digits);
+      decNumberShow(dn);
+      #endif
+      decContextSetStatus(set, DEC_Invalid_operation);
+      }
+  #else
+    /* next is a noop for quiet compiler */
+    if (dn!=NULL && dn->digits==0) set->status|=DEC_Invalid_operation;
+  #endif
+  return;
+  } /* decCheckInexact */
 #endif
 
 #if DECALLOC
 #undef malloc
 #undef free
 /* ------------------------------------------------------------------ */
-/* decMalloc -- accountable allocation routine                        */
-/*   n is the number of bytes to allocate                             */
-/*                                                                    */
+/* decMalloc -- accountable allocation routine                       */
+/*   n is the number of bytes to allocate                            */
+/*                                                                   */
 /* Semantics is the same as the stdlib malloc routine, but bytes      */
 /* 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   */
-/* at the start and hold:                                             */
-/*   0-3 the original length requested                                */
-/*   4-7 buffer corruption detection fence (DECFENCE, x4)             */
+/* at the start and hold:                                            */
+/*   0-3 the original length requested                               */
+/*   4-7 buffer corruption detection fence (DECFENCE, x4)            */
 /* The 4 bytes at the end also hold a corruption fence (DECFENCE, x4) */
 /* ------------------------------------------------------------------ */
-static void *
-decMalloc (uInt n)
-{
-  uInt size = n + 12;          /* true size */
-  void *alloc;                 /* -> allocated storage */
-  uInt *j;                     /* work */
-  uByte *b, *b0;               /* .. */
-
-  alloc = malloc (size);       /* -> allocated storage */
-  if (alloc == NULL)
-    return NULL;               /* out of strorage */
-  b0 = (uByte *) alloc;                /* as bytes */
-  decAllocBytes += n;          /* account for storage */
-  j = (uInt *) alloc;          /* -> first four bytes */
-  *j = n;                      /* save n */
-  /* printf("++ alloc(%d)\n", n); */
-  for (b = b0 + 4; b < b0 + 8; b++)
-    *b = DECFENCE;
-  for (b = b0 + n + 8; b < b0 + n + 12; b++)
-    *b = DECFENCE;
-  return b0 + 8;               /* -> play area */
-}
-
-/* ------------------------------------------------------------------ */
-/* decFree -- accountable free routine                                */
-/*   alloc is the storage to free                                     */
-/*                                                                    */
+static void *decMalloc(size_t n) {
+  uInt size=n+12;                 /* true size */
+  void *alloc;                    /* -> allocated storage */
+  uInt *j;                        /* work */
+  uByte *b, *b0;                  /* .. */
+
+  alloc=malloc(size);             /* -> allocated storage */
+  if (alloc==NULL) return NULL;           /* out of strorage */
+  b0=(uByte *)alloc;              /* as bytes */
+  decAllocBytes+=n;               /* account for storage */
+  j=(uInt *)alloc;                /* -> first four bytes */
+  *j=n;                                   /* save n */
+  /* printf(" alloc ++ dAB: %ld (%d)\n", decAllocBytes, n); */
+  for (b=b0+4; b<b0+8; b++) *b=DECFENCE;
+  for (b=b0+n+8; b<b0+n+12; b++) *b=DECFENCE;
+  return b0+8;                    /* -> play area */
+  } /* decMalloc */
+
+/* ------------------------------------------------------------------ */
+/* decFree -- accountable free routine                               */
+/*   alloc is the storage to free                                    */
+/*                                                                   */
 /* 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'.     */
 /* ------------------------------------------------------------------ */
 /* This routine first checks that the fences have not been corrupted. */
 /* It then frees the storage using the 'truw' storage address (that   */
-/* is, offset by 8).                                                  */
-/* ------------------------------------------------------------------ */
-static void
-decFree (void *alloc)
-{
-  uInt *j, n;                  /* pointer, original length */
-  uByte *b, *b0;               /* work */
-
-  if (alloc == NULL)
-    return;                    /* allowed; it's a nop */
-  b0 = (uByte *) alloc;                /* as bytes */
-  b0 -= 8;                     /* -> true start of storage */
-  j = (uInt *) b0;             /* -> first four bytes */
-  n = *j;                      /* lift */
-  for (b = b0 + 4; b < b0 + 8; b++)
-    if (*b != DECFENCE)
-      printf ("=== Corrupt byte [%02x] at offset %d from %d ===\n", *b,
-             b - b0 - 8, (Int) b0);
-  for (b = b0 + n + 8; b < b0 + n + 12; b++)
-    if (*b != DECFENCE)
-      printf ("=== Corrupt byte [%02x] at offset +%d from %d, n=%d ===\n", *b,
-             b - b0 - 8, (Int) b0, n);
-  free (b0);                   /* drop the storage */
-  decAllocBytes -= n;          /* account for storage */
-}
+/* is, offset by 8).                                                 */
+/* ------------------------------------------------------------------ */
+static void decFree(void *alloc) {
+  uInt *j, n;                     /* pointer, original length */
+  uByte *b, *b0;                  /* work */
+
+  if (alloc==NULL) return;        /* allowed; it's a nop */
+  b0=(uByte *)alloc;              /* as bytes */
+  b0-=8;                          /* -> true start of storage */
+  j=(uInt *)b0;                           /* -> first four bytes */
+  n=*j;                                   /* lift */
+  for (b=b0+4; b<b0+8; b++) if (*b!=DECFENCE)
+    printf("=== Corrupt byte [%02x] at offset %d from %ld ===\n", *b,
+          b-b0-8, (Int)b0);
+  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,
+          b-b0-8, (Int)b0, n);
+  free(b0);                       /* drop the storage */
+  decAllocBytes-=n;               /* account for storage */
+  /* printf(" free -- dAB: %d (%d)\n", decAllocBytes, -n); */
+  } /* decFree */
+#define malloc(a) decMalloc(a)
+#define free(a) decFree(a)
 #endif
index 05a2d869e3e1d09e6c18a7a6bf154f29edb91ff2..0a9fdced8b3f5bd829a20a1a476614d2d8592650 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal Number module header for the decNumber C Library
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Decimal number arithmetic module header for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-#if !defined(DECNUMBER)
-#define DECNUMBER
-#define DECNAME     "decNumber"        /* Short name */
-#define DECVERSION  "decNumber 3.24"   /* Version [16 max.] */
-#define DECFULLNAME "Decimal Number Module"    /* Verbose name */
-#define DECAUTHOR   "Mike Cowlishaw"   /* Who to blame */
-
-#if !defined(DECCONTEXT)
-#include "decContext.h"
-#endif
-
-
-  /* Bit settings for decNumber.bits */
-#define DECNEG    0x80         /* Sign; 1=negative, 0=positive or zero */
-#define DECINF    0x40         /* 1=Infinity */
-#define DECNAN    0x20         /* 1=NaN */
-#define DECSNAN   0x10         /* 1=sNaN */
-  /* The remaining bits are reserved; they must be 0 */
-#define DECSPECIAL (DECINF|DECNAN|DECSNAN)     /* any special value */
-
-  /* DECNUMDIGITS is the default number of digits we can hold in the */
-  /* structure.  If undefined, 1 is assumed and it is assumed that the */
-  /* structure will be immediately followed by extra space (if */
-  /* required).  DECNUMDIGITS is always >0. */
-#if !defined(DECNUMDIGITS)
-#define DECNUMDIGITS 1
-#endif
-
+/* ------------------------------------------------------------------ */
+/* Decimal Number arithmetic module header                           */
+/* ------------------------------------------------------------------ */
 
-  /* Define the decNumber data structure.  The size and shape of the */
-  /* units array in the structure is determined by the following */
-  /* constant.  This must not be changed without recompiling the */
+#if !defined(DECNUMBER)
+  #define DECNUMBER
+  #define DECNAME     "decNumber"                      /* Short name */
+  #define DECFULLNAME "Decimal Number Module"        /* Verbose name */
+  #define DECAUTHOR   "Mike Cowlishaw"               /* Who to blame */
+
+  #if !defined(DECCONTEXT)
+    #include "decContext.h"
+  #endif
+
+  /* Bit settings for decNumber.bits                                 */
+  #define DECNEG    0x80      /* Sign; 1=negative, 0=positive or zero */
+  #define DECINF    0x40      /* 1=Infinity                          */
+  #define DECNAN    0x20      /* 1=NaN                               */
+  #define DECSNAN   0x10      /* 1=sNaN                                      */
+  /* The remaining bits are reserved; they must be 0                 */
+  #define DECSPECIAL (DECINF|DECNAN|DECSNAN) /* any special value     */
+
+  /* Define the decNumber data structure.  The size and shape of the  */
+  /* units array in the structure is determined by the following      */
+  /* constant. This must not be changed without recompiling the      */
   /* decNumber library modules. */
-#define DECDPUN 4              /* Decimal Digits Per UNit [must be in */
-                                  /* range 1-9; power of 2 recommended]. */
-  /* The size (integer data type) of each unit is determined by the */
-  /* number of digits it will hold. */
-#if   DECDPUN<=2
-#define decNumberUnit uint8_t
-#elif DECDPUN<=4
-#define decNumberUnit uint16_t
-#else
-#define decNumberUnit uint32_t
-#endif
-  /* The number of decNumberUnits we need is ceiling of DECNUMDIGITS/DECDPUN */
-#define DECNUMUNITS ((DECNUMDIGITS+DECDPUN-1)/DECDPUN)
 
-  /* The data structure... */
-typedef struct
-{
-  int32_t digits;              /* Count of digits in the coefficient; >0 */
-  int32_t exponent;            /* Unadjusted exponent, unbiased, in */
-  /* range: -1999999997 through 999999999 */
-  uint8_t bits;                        /* Indicator bits (see above) */
-  decNumberUnit lsu[DECNUMUNITS];      /* Coefficient, from least significant unit */
-} decNumber;
-
-  /* Notes: */
-  /* 1. If digits is > DECDPUN then there will be more than one */
-  /*    decNumberUnits immediately following the first element of lsu. */
-  /*    These contain the remaining (more significant) digits of the */
-  /*    number, and may be in the lsu array, or may be guaranteed by */
-  /*    some other mechanism (such as being contained in another */
-  /*    structure, or being overlaid on dynamically allocated storage). */
-  /* */
-  /*    Each integer of the coefficient (except the possibly the last) */
-  /*    contains DECDPUN digits (e.g., a value in the range 0 through */
-  /*    99999999 if DECDPUN is 8, or 0 through 9999 if DECDPUN is 4). */
-  /* */
-  /* 2. A decNumber converted to a string may need up to digits+14 */
-  /*    characters.  The worst cases (non-exponential and exponential */
-  /*    formats) are: -0.00000{9...}# */
-  /*             and: -9.{9...}E+999999999#   (where # is '\0') */
-
-
-  /* ------------------------------------------------------------------ */
-  /* decNumber public functions and macros                              */
-  /* ------------------------------------------------------------------ */
-
-#ifdef IN_LIBGCC2
-#define decNumberFromString __decNumberFromString
-#define decNumberToString __decNumberToString
-#define decNumberToEngString __decNumberToEngString
-#define decNumberAbs __decNumberAbs
-#define decNumberAdd __decNumberAdd
-#define decNumberCompare __decNumberCompare
-#define decNumberDivide __decNumberDivide
-#define decNumberDivideInteger __decNumberDivideInteger
-#define decNumberMax __decNumberMax
-#define decNumberMin __decNumberMin
-#define decNumberMinus __decNumberMinus
-#define decNumberMultiply __decNumberMultiply
-#define decNumberNormalize __decNumberNormalize
-#define decNumberPlus __decNumberPlus
-#define decNumberPower __decNumberPower
-#define decNumberQuantize __decNumberQuantize
-#define decNumberRemainder __decNumberRemainder
-#define decNumberRemainderNear __decNumberRemainderNear
-#define decNumberRescale __decNumberRescale
-#define decNumberSameQuantum __decNumberSameQuantum
-#define decNumberSquareRoot __decNumberSquareRoot
-#define decNumberSubtract __decNumberSubtract
-#define decNumberToIntegralValue __decNumberToIntegralValue
-#define decNumberCopy __decNumberCopy
-#define decNumberTrim __decNumberTrim
-#define decNumberVersion __decNumberVersion
-#define decNumberZero __decNumberZero
-#endif
+  #define DECDPUN 3          /* DECimal Digits Per UNit [must be >0  */
+                             /* and <10; 3 or powers of 2 are best]. */
+
+  /* DECNUMDIGITS is the default number of digits that can be held in */
+  /* the structure.  If undefined, 1 is assumed and it is assumed     */
+  /* that the structure will be immediately followed by extra space,  */
+  /* as required.  DECNUMDIGITS is always >0.                        */
+  #if !defined(DECNUMDIGITS)
+    #define DECNUMDIGITS 1
+  #endif
+
+  /* The size (integer data type) of each unit is determined by the   */
+  /* number of digits it will hold.                                  */
+  #if  DECDPUN<=2
+    #define decNumberUnit uint8_t
+  #elif DECDPUN<=4
+    #define decNumberUnit uint16_t
+  #else
+    #define decNumberUnit uint32_t
+  #endif
+  /* The number of units needed is ceil(DECNUMDIGITS/DECDPUN)        */
+  #define DECNUMUNITS ((DECNUMDIGITS+DECDPUN-1)/DECDPUN)
 
-  /* Conversions */
-decNumber *decNumberFromString (decNumber *, const char *, decContext *);
-char *decNumberToString (const decNumber *, char *);
-char *decNumberToEngString (const decNumber *, char *);
-
-  /* Operators */
-decNumber *decNumberAbs (decNumber *, const decNumber *, decContext *);
-decNumber *decNumberAdd (decNumber *, const decNumber *,
-                        const decNumber *, decContext *);
-decNumber *decNumberCompare (decNumber *, const decNumber *,
-                            const decNumber *, decContext *);
-decNumber *decNumberDivide (decNumber *, const decNumber *,
-                           const decNumber *, decContext *);
-decNumber *decNumberDivideInteger (decNumber *, const decNumber *,
-                                  const decNumber *, decContext *);
-decNumber *decNumberMax (decNumber *, const decNumber *,
-                        const decNumber *, decContext *);
-decNumber *decNumberMin (decNumber *, const decNumber *,
-                        const decNumber *, decContext *);
-decNumber *decNumberMinus (decNumber *, const decNumber *, decContext *);
-decNumber *decNumberMultiply (decNumber *, const decNumber *,
-                             const decNumber *, decContext *);
-decNumber *decNumberNormalize (decNumber *, const decNumber *, decContext *);
-decNumber *decNumberPlus (decNumber *, const decNumber *, decContext *);
-decNumber *decNumberPower (decNumber *, const decNumber *,
-                          const decNumber *, decContext *);
-decNumber *decNumberQuantize (decNumber *, const decNumber *,
-                             const decNumber *, decContext *);
-decNumber *decNumberRemainder (decNumber *, const decNumber *,
-                              const decNumber *, decContext *);
-decNumber *decNumberRemainderNear (decNumber *, const decNumber *,
-                                  const decNumber *, decContext *);
-decNumber *decNumberRescale (decNumber *, const decNumber *,
-                            const decNumber *, decContext *);
-decNumber *decNumberSameQuantum (decNumber *, const decNumber *, const decNumber *);
-decNumber *decNumberSquareRoot (decNumber *, const decNumber *, decContext *);
-decNumber *decNumberSubtract (decNumber *, const decNumber *,
-                             const decNumber *, decContext *);
-decNumber *decNumberToIntegralValue (decNumber *, const decNumber *, decContext *);
-
-  /* Utilities */
-decNumber *decNumberCopy (decNumber *, const decNumber *);
-decNumber *decNumberTrim (decNumber *);
-const char *decNumberVersion (void);
-decNumber *decNumberZero (decNumber *);
-
-  /* Macros */
-#define decNumberIsZero(dn)     (*(dn)->lsu==0 \
-                                   && (dn)->digits==1 \
-                                   && (((dn)->bits&DECSPECIAL)==0))
-#define decNumberIsNegative(dn) (((dn)->bits&DECNEG)!=0)
-#define decNumberIsNaN(dn)      (((dn)->bits&(DECNAN|DECSNAN))!=0)
-#define decNumberIsInfinite(dn) (((dn)->bits&DECINF)!=0)
+  /* The data structure... */
+  typedef struct {
+    int32_t digits;     /* Count of digits in the coefficient; >0    */
+    int32_t exponent;   /* Unadjusted exponent, unbiased, in         */
+                        /* range: -1999999997 through 999999999      */
+    uint8_t bits;       /* Indicator bits (see above)                */
+                        /* Coefficient, from least significant unit  */
+    decNumberUnit lsu[DECNUMUNITS];
+    } decNumber;
+
+  /* Notes:                                                          */
+  /* 1. If digits is > DECDPUN then there will one or more           */
+  /*   decNumberUnits immediately following the first element of lsu.*/
+  /*   These contain the remaining (more significant) digits of the  */
+  /*   number, and may be in the lsu array, or may be guaranteed by  */
+  /*   some other mechanism (such as being contained in another      */
+  /*   structure, or being overlaid on dynamically allocated         */
+  /*   storage).                                                     */
+  /*                                                                 */
+  /*   Each integer of the coefficient (except potentially the last) */
+  /*   contains DECDPUN digits (e.g., a value in the range 0 through */
+  /*   99999999 if DECDPUN is 8, or 0 through 999 if DECDPUN is 3).  */
+  /*                                                                 */
+  /* 2. A decNumber converted to a string may need up to digits+14    */
+  /*   characters.  The worst cases (non-exponential and exponential */
+  /*   formats) are -0.00000{9...}# and -9.{9...}E+999999999#        */
+  /*   (where # is '\0')                                             */
+
+
+  /* ---------------------------------------------------------------- */
+  /* decNumber public functions and macros                           */
+  /* ---------------------------------------------------------------- */
+
+  #include "decNumberSymbols.h"
+
+  /* Conversions                                                     */
+  decNumber * decNumberFromInt32(decNumber *, int32_t);
+  decNumber * decNumberFromUInt32(decNumber *, uint32_t);
+  decNumber * decNumberFromString(decNumber *, const char *, decContext *);
+  char     * decNumberToString(const decNumber *, char *);
+  char     * decNumberToEngString(const decNumber *, char *);
+  uint32_t    decNumberToUInt32(const decNumber *, decContext *);
+  int32_t     decNumberToInt32(const decNumber *, decContext *);
+  uint8_t   * decNumberGetBCD(const decNumber *, uint8_t *);
+  decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
+
+  /* Operators and elementary functions                                      */
+  decNumber * decNumberAbs(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberAdd(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberAnd(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberCompare(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberCompareSignal(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberCompareTotal(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberCompareTotalMag(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberDivide(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberDivideInteger(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberExp(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberFMA(decNumber *, const decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberInvert(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberLn(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberLogB(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberLog10(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberMax(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberMaxMag(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberMin(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberMinMag(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberMinus(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberMultiply(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberNormalize(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberOr(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberPlus(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberPower(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberQuantize(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberReduce(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberRemainder(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberRemainderNear(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberRescale(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberRotate(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberSameQuantum(decNumber *, const decNumber *, const decNumber *);
+  decNumber * decNumberScaleB(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberShift(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberSquareRoot(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberSubtract(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberToIntegralExact(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberToIntegralValue(decNumber *, const decNumber *, decContext *);
+  decNumber * decNumberXor(decNumber *, const decNumber *, const decNumber *, decContext *);
+
+  /* Utilities                                                       */
+  enum decClass decNumberClass(const decNumber *, decContext *);
+  const char * decNumberClassToString(enum decClass);
+  decNumber  * decNumberCopy(decNumber *, const decNumber *);
+  decNumber  * decNumberCopyAbs(decNumber *, const decNumber *);
+  decNumber  * decNumberCopyNegate(decNumber *, const decNumber *);
+  decNumber  * decNumberCopySign(decNumber *, const decNumber *, const decNumber *);
+  decNumber  * decNumberNextMinus(decNumber *, const decNumber *, decContext *);
+  decNumber  * decNumberNextPlus(decNumber *, const decNumber *, decContext *);
+  decNumber  * decNumberNextToward(decNumber *, const decNumber *, const decNumber *, decContext *);
+  decNumber  * decNumberTrim(decNumber *);
+  const char * decNumberVersion(void);
+  decNumber  * decNumberZero(decNumber *);
+
+  /* Functions for testing decNumbers (normality depends on context)  */
+  int32_t decNumberIsNormal(const decNumber *, decContext *);
+  int32_t decNumberIsSubnormal(const decNumber *, decContext *);
+
+  /* Macros for testing decNumber *dn                                */
+  #define decNumberIsCanonical(dn) (1) /* All decNumbers are saintly */
+  #define decNumberIsFinite(dn)           (((dn)->bits&DECSPECIAL)==0)
+  #define decNumberIsInfinite(dn)  (((dn)->bits&DECINF)!=0)
+  #define decNumberIsNaN(dn)      (((dn)->bits&(DECNAN|DECSNAN))!=0)
+  #define decNumberIsNegative(dn)  (((dn)->bits&DECNEG)!=0)
+  #define decNumberIsQNaN(dn)     (((dn)->bits&(DECNAN))!=0)
+  #define decNumberIsSNaN(dn)     (((dn)->bits&(DECSNAN))!=0)
+  #define decNumberIsSpecial(dn)   (((dn)->bits&DECSPECIAL)!=0)
+  #define decNumberIsZero(dn)     (*(dn)->lsu==0 \
+                                   && (dn)->digits==1 \
+                                   && (((dn)->bits&DECSPECIAL)==0))
+  #define decNumberRadix(dn)      (10)
 
 #endif
index 0386736c6f07ef8f923d9082a72a067b588a4e90..891a0841c894edae4df4f62898c5a1eb3678a31a 100644 (file)
@@ -1,5 +1,5 @@
-/* decNumber package local type, tuning, and macro definitions.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Local definitions for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    02110-1301, USA.  */
 
 /* ------------------------------------------------------------------ */
-/* This header file is included by all modules in the decNumber       */
+/* decNumber package local type, tuning, and macro definitions       */
+/* ------------------------------------------------------------------ */
+/* This header file is included by all modules in the decNumber              */
 /* library, and contains local type definitions, tuning parameters,   */
-/* etc.  It must only be included once, and should not need to be     */
-/* used by application programs.  decNumber.h must be included first. */
+/* etc.         It should not need to be used by application programs.       */
+/* decNumber.h or one of decDouble (etc.) must be included first.     */
 /* ------------------------------------------------------------------ */
 
 #if !defined(DECNUMBERLOC)
-#define DECNUMBERLOC
-#define DECNLAUTHOR   "Mike Cowlishaw" /* Who to blame */
-
-  /* Local names for common types -- decNumber modules do not use int or
-     long directly */
-#define Flag   uint8_t
-#define Byte   int8_t
-#define uByte  uint8_t
-#define Short  int16_t
-#define uShort uint16_t
-#define Int    int32_t
-#define uInt   uint32_t
-#define Unit   decNumberUnit
-
-
-  /* Tuning parameter */
-#define DECBUFFER 36           /* Maximum size basis for local buffers. */
-                             /* Should be a common maximum precision */
-                             /* rounded up to a multiple of 4; must */
-                             /* be non-negative. */
-
-  /* Conditional code flags -- set these to 0 for best performance */
-#define DECCHECK  0            /* 1 to enable robust checking */
-#define DECALLOC  0            /* 1 to enable memory allocation accounting */
-#define DECTRACE  0            /* 1 to trace critical intermediates, etc. */
-
-
-  /* Development use defines */
-#if DECALLOC
-     /* if these interfere with your C includes, just comment them out */
-#define  int ?                 /* enable to ensure we do not use plain C */
-#define  long ??               /* .. 'int' or 'long' types from here on */
-#endif
+  #define DECNUMBERLOC
+  #define DECVERSION   "decNumber 3.53" /* Package Version [16 max.] */
+  #define DECNLAUTHOR  "Mike Cowlishaw"              /* Who to blame */
 
-  /* Limits and constants */
-#define DECNUMMAXP 999999999   /* maximum precision we can handle (9 digits) */
-#define DECNUMMAXE 999999999   /* maximum adjusted exponent ditto (9 digits) */
-#define DECNUMMINE -999999999  /* minimum adjusted exponent ditto (9 digits) */
-#if (DECNUMMAXP != DEC_MAX_DIGITS)
-#error Maximum digits mismatch
-#endif
-#if (DECNUMMAXE != DEC_MAX_EMAX)
-#error Maximum exponent mismatch
-#endif
-#if (DECNUMMINE != DEC_MIN_EMIN)
-#error Minimum exponent mismatch
-#endif
+  #include <stdlib.h>        /* for abs                              */
+  #include <string.h>        /* for memset, strcpy                   */
+  #include "config.h"        /* for WORDS_BIGENDIAN                  */
 
-  /* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN digits */
-#if   DECDPUN==1
-#define DECDPUNMAX 9
-#elif DECDPUN==2
-#define DECDPUNMAX 99
-#elif DECDPUN==3
-#define DECDPUNMAX 999
-#elif DECDPUN==4
-#define DECDPUNMAX 9999
-#elif DECDPUN==5
-#define DECDPUNMAX 99999
-#elif DECDPUN==6
-#define DECDPUNMAX 999999
-#elif DECDPUN==7
-#define DECDPUNMAX 9999999
-#elif DECDPUN==8
-#define DECDPUNMAX 99999999
-#elif DECDPUN==9
-#define DECDPUNMAX 999999999
-#elif defined(DECDPUN)
-#error DECDPUN must be in the range 1-9
-#endif
+  /* Conditional code flag -- set this to match hardware platform     */
+  /* 1=little-endian, 0=big-endian                                   */
+  #if WORDS_BIGENDIAN
+  #define DECLITEND 0
+  #else
+  #define DECLITEND 1
+  #endif
+
+  /* Conditional code flag -- set this to 1 for best performance      */
+  #define DECUSE64  1        /* 1=use int64s, 0=int32 & smaller only */
+
+  /* Conditional check flags -- set these to 0 for best performance   */
+  #define DECCHECK  0        /* 1 to enable robust checking          */
+  #define DECALLOC  0        /* 1 to enable memory accounting        */
+  #define DECTRACE  0        /* 1 to trace certain internals, etc.   */
+
+  /* Tuning parameter for decNumber (arbitrary precision) module      */
+  #define DECBUFFER 36       /* Size basis for local buffers.  This  */
+                             /* should be a common maximum precision */
+                             /* rounded up to a multiple of 4; must  */
+                             /* be zero or positive.                 */
+
+  /* ---------------------------------------------------------------- */
+  /* Definitions for all modules (general-purpose)                   */
+  /* ---------------------------------------------------------------- */
+
+  /* Local names for common types -- for safety, decNumber modules do */
+  /* not use int or long directly.                                   */
+  #define Flag  uint8_t
+  #define Byte  int8_t
+  #define uByte         uint8_t
+  #define Short         int16_t
+  #define uShort uint16_t
+  #define Int   int32_t
+  #define uInt  uint32_t
+  #define Unit  decNumberUnit
+  #if DECUSE64
+  #define Long  int64_t
+  #define uLong         uint64_t
+  #endif
+
+  /* Development-use definitions                                     */
+  typedef long int LI;       /* for printf arguments only            */
+  #define DECNOINT  0        /* 1 to check no internal use of 'int'  */
+  #if DECNOINT
+    /* if these interfere with your C includes, do not set DECNOINT   */
+    #define  int ?           /* enable to ensure that plain C 'int'  */
+    #define  long ??         /* .. or 'long' types are not used      */
+  #endif
+
+  /* Shared lookup tables                                            */
+  extern const uByte  DECSTICKYTAB[10]; /* re-round digits if sticky  */
+  extern const uInt   DECPOWERS[10];   /* powers of ten table        */
+  /* The following are included from decDPD.h                        */
+  extern const uShort DPD2BIN[1024];   /* DPD -> 0-999               */
+  extern const uShort BIN2DPD[1000];   /* 0-999 -> DPD               */
+  extern const uInt   DPD2BINK[1024];  /* DPD -> 0-999000            */
+  extern const uInt   DPD2BINM[1024];  /* DPD -> 0-999000000         */
+  extern const uByte  DPD2BCD8[4096];  /* DPD -> ddd + len           */
+  extern const uByte  BIN2BCD8[4000];  /* 0-999 -> ddd + len         */
+  extern const uShort BCD2DPD[2458];   /* 0-0x999 -> DPD (0x999=2457)*/
+
+  /* LONGMUL32HI -- set w=(u*v)>>32, where w, u, and v are uInts      */
+  /* (that is, sets w to be the high-order word of the 64-bit result; */
+  /* the low-order word is simply u*v.)                                      */
+  /* This version is derived from Knuth via Hacker's Delight;        */
+  /* it seems to optimize better than some others tried                      */
+  #define LONGMUL32HI(w, u, v) {            \
+    uInt u0, u1, v0, v1, w0, w1, w2, t;             \
+    u0=u & 0xffff; u1=u>>16;                \
+    v0=v & 0xffff; v1=v>>16;                \
+    w0=u0*v0;                               \
+    t=u1*v0 + (w0>>16);                             \
+    w1=t & 0xffff; w2=t>>16;                \
+    w1=u0*v1 + w1;                          \
+    (w)=u1*v1 + w2 + (w1>>16);}
+
+  /* ROUNDUP -- round an integer up to a multiple of n               */
+  #define ROUNDUP(i, n) ((((i)+(n)-1)/n)*n)
+
+  /* ROUNDDOWN -- round an integer down to a multiple of n           */
+  #define ROUNDDOWN(i, n) (((i)/n)*n)
+  #define ROUNDDOWN4(i)          ((i)&~3)      /* special for n=4            */
+
+  /* References to multi-byte sequences under different sizes        */
+  /* Refer to a uInt from four bytes starting at a char* or uByte*,   */
+  /* etc.                                                            */
+  #define UINTAT(b)   (*((uInt  *)(b)))
+  #define USHORTAT(b) (*((uShort *)(b)))
+  #define UBYTEAT(b)  (*((uByte         *)(b)))
 
+  /* X10 and X100 -- multiply integer i by 10 or 100                 */
+  /* [shifts are usually faster than multiply; could be conditional]  */
+  #define X10(i)  (((i)<<1)+((i)<<3))
+  #define X100(i) (((i)<<2)+((i)<<5)+((i)<<6))
 
-  /* ----- Shared data ----- */
-  /* The powers of of ten array (powers[n]==10**n, 0<=n<=10) */
-extern const uInt powers[];
+  /* MAXI and MINI -- general max & min (not in ANSI) for integers    */
+  #define MAXI(x,y) ((x)<(y)?(y):(x))
+  #define MINI(x,y) ((x)>(y)?(y):(x))
+
+  /* Useful constants                                                */
+  #define BILLION      1000000000           /* 10**9                 */
+  /* CHARMASK: 0x30303030 for ASCII/UTF8; 0xF0F0F0F0 for EBCDIC              */
+  #define CHARMASK ((((((((uInt)'0')<<8)+'0')<<8)+'0')<<8)+'0')
+
+
+  /* ---------------------------------------------------------------- */
+  /* Definitions for arbitary-precision modules (only valid after     */
+  /* decNumber.h has been included)                                  */
+  /* ---------------------------------------------------------------- */
+
+  /* Limits and constants                                            */
+  #define DECNUMMAXP 999999999 /* maximum precision code can handle  */
+  #define DECNUMMAXE 999999999 /* maximum adjusted exponent ditto    */
+  #define DECNUMMINE -999999999 /* minimum adjusted exponent ditto    */
+  #if (DECNUMMAXP != DEC_MAX_DIGITS)
+    #error Maximum digits mismatch
+  #endif
+  #if (DECNUMMAXE != DEC_MAX_EMAX)
+    #error Maximum exponent mismatch
+  #endif
+  #if (DECNUMMINE != DEC_MIN_EMIN)
+    #error Minimum exponent mismatch
+  #endif
+
+  /* Set DECDPUNMAX -- the maximum integer that fits in DECDPUN              */
+  /* digits, and D2UTABLE -- the initializer for the D2U table       */
+  #if  DECDPUN==1
+    #define DECDPUNMAX 9
+    #define D2UTABLE {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,  \
+                     18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, \
+                     33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, \
+                     48,49}
+  #elif DECDPUN==2
+    #define DECDPUNMAX 99
+    #define D2UTABLE {0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,  \
+                     11,11,12,12,13,13,14,14,15,15,16,16,17,17,18, \
+                     18,19,19,20,20,21,21,22,22,23,23,24,24,25}
+  #elif DECDPUN==3
+    #define DECDPUNMAX 999
+    #define D2UTABLE {0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,  \
+                     8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13, \
+                     13,14,14,14,15,15,15,16,16,16,17}
+  #elif DECDPUN==4
+    #define DECDPUNMAX 9999
+    #define D2UTABLE {0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,  \
+                     6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11, \
+                     11,11,11,12,12,12,12,13}
+  #elif DECDPUN==5
+    #define DECDPUNMAX 99999
+    #define D2UTABLE {0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,  \
+                     5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9,  \
+                     9,9,10,10,10,10}
+  #elif DECDPUN==6
+    #define DECDPUNMAX 999999
+    #define D2UTABLE {0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,  \
+                     4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,  \
+                     8,8,8,8,8,9}
+  #elif DECDPUN==7
+    #define DECDPUNMAX 9999999
+    #define D2UTABLE {0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3,  \
+                     4,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,6,6,7,  \
+                     7,7,7,7,7,7}
+  #elif DECDPUN==8
+    #define DECDPUNMAX 99999999
+    #define D2UTABLE {0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,  \
+                     3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,  \
+                     6,6,6,6,6,7}
+  #elif DECDPUN==9
+    #define DECDPUNMAX 999999999
+    #define D2UTABLE {0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,  \
+                     3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,  \
+                     5,5,6,6,6,6}
+  #elif defined(DECDPUN)
+    #error DECDPUN must be in the range 1-9
+  #endif
+
+  /* ----- Shared data (in decNumber.c) ----- */
+  /* Public lookup table used by the D2U macro (see below)           */
+  #define DECMAXD2U 49
+  extern const uByte d2utable[DECMAXD2U+1];
 
   /* ----- Macros ----- */
-  /* ISZERO -- return true if decNumber dn is a zero */
-  /* [performance-critical in some situations] */
-#define ISZERO(dn) decNumberIsZero(dn) /* now just a local name */
-
-  /* X10 and X100 -- multiply integer i by 10 or 100 */
-  /* [shifts are usually faster than multiply; could be conditional] */
-#define X10(i)  (((i)<<1)+((i)<<3))
-#define X100(i) (((i)<<2)+((i)<<5)+((i)<<6))
-
-  /* D2U -- return the number of Units needed to hold d digits */
-#if DECDPUN==8
-#define D2U(d) ((unsigned)((d)+7)>>3)
-#elif DECDPUN==4
-#define D2U(d) ((unsigned)((d)+3)>>2)
-#else
-#define D2U(d) (((d)+DECDPUN-1)/DECDPUN)
-#endif
+  /* ISZERO -- return true if decNumber dn is a zero                 */
+  /* [performance-critical in some situations]                       */
+  #define ISZERO(dn) decNumberIsZero(dn)     /* now just a local name */
+
+  /* D2U -- return the number of Units needed to hold d digits       */
+  /* (runtime version, with table lookaside for small d)             */
+  #if DECDPUN==8
+    #define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+7)>>3))
+  #elif DECDPUN==4
+    #define D2U(d) ((unsigned)((d)<=DECMAXD2U?d2utable[d]:((d)+3)>>2))
+  #else
+    #define D2U(d) ((d)<=DECMAXD2U?d2utable[d]:((d)+DECDPUN-1)/DECDPUN)
+  #endif
+  /* SD2U -- static D2U macro (for compile-time calculation)         */
+  #define SD2U(d) (((d)+DECDPUN-1)/DECDPUN)
+
+  /* MSUDIGITS -- returns digits in msu, from digits, calculated      */
+  /* using D2U                                                       */
+  #define MSUDIGITS(d) ((d)-(D2U(d)-1)*DECDPUN)
+
+  /* D2N -- return the number of decNumber structs that would be      */
+  /* needed to contain that number of digits (and the initial        */
+  /* decNumber struct) safely. Note that one Unit is included in the */
+  /* initial structure.         Used for allocating space that is aligned on */
+  /* a decNumber struct boundary. */
+  #define D2N(d) \
+    ((((SD2U(d)-1)*sizeof(Unit))+sizeof(decNumber)*2-1)/sizeof(decNumber))
+
+  /* TODIGIT -- macro to remove the leading digit from the unsigned   */
+  /* integer u at column cut (counting from the right, LSD=0) and     */
+  /* place it as an ASCII character into the character pointed to by  */
+  /* c.         Note that cut must be <= 9, and the maximum value for u is   */
+  /* 2,000,000,000 (as is needed for negative exponents of           */
+  /* subnormals).  The unsigned integer pow is used as a temporary    */
+  /* variable. */
+  #define TODIGIT(u, cut, c, pow) {      \
+    *(c)='0';                            \
+    pow=DECPOWERS[cut]*2;                \
+    if ((u)>pow) {                       \
+      pow*=4;                            \
+      if ((u)>=pow) {(u)-=pow; *(c)+=8;}  \
+      pow/=2;                            \
+      if ((u)>=pow) {(u)-=pow; *(c)+=4;}  \
+      pow/=2;                            \
+      }                                          \
+    if ((u)>=pow) {(u)-=pow; *(c)+=2;}   \
+    pow/=2;                              \
+    if ((u)>=pow) {(u)-=pow; *(c)+=1;}   \
+    }
+
+  /* ---------------------------------------------------------------- */
+  /* Definitions for fixed-precision modules (only valid after       */
+  /* decSingle.h, decDouble.h, or decQuad.h has been included)       */
+  /* ---------------------------------------------------------------- */
+
+  /* bcdnum -- a structure describing a format-independent finite     */
+  /* number, whose coefficient is a string of bcd8 uBytes            */
+  typedef struct {
+    uByte   *msd;            /* -> most significant digit            */
+    uByte   *lsd;            /* -> least ditto                       */
+    uInt     sign;           /* 0=positive, DECFLOAT_Sign=negative   */
+    Int             exponent;        /* Unadjusted signed exponent (q), or   */
+                             /* DECFLOAT_NaN etc. for a special      */
+    } bcdnum;
+
+  /* Test if exponent or bcdnum exponent must be a special, etc.      */
+  #define EXPISSPECIAL(exp) ((exp)>=DECFLOAT_MinSp)
+  #define EXPISINF(exp) (exp==DECFLOAT_Inf)
+  #define EXPISNAN(exp) (exp==DECFLOAT_qNaN || exp==DECFLOAT_sNaN)
+  #define NUMISSPECIAL(num) (EXPISSPECIAL((num)->exponent))
+
+  /* Refer to a 32-bit word or byte in a decFloat (df) by big-endian  */
+  /* (array) notation (the 0 word or byte contains the sign bit),     */
+  /* automatically adjusting for endianness; similarly address a word */
+  /* in the next-wider format (decFloatWider, or dfw)                */
+  #define DECWORDS  (DECBYTES/4)
+  #define DECWWORDS (DECWBYTES/4)
+  #if DECLITEND
+    #define DFWORD(df, off) UINTAT((df)->bytes+(DECWORDS-1-(off))*4)
+    #define DFBYTE(df, off) UBYTEAT((df)->bytes+(DECBYTES-1-(off)))
+    #define DFWWORD(dfw, off) UINTAT((dfw)->bytes+(DECWWORDS-1-(off))*4)
+  #else
+    #define DFWORD(df, off) UINTAT((df)->bytes+(off)*4)
+    #define DFBYTE(df, off) UBYTEAT((df)->bytes+(off))
+    #define DFWWORD(dfw, off) UINTAT((dfw)->bytes+(off)*4)
+  #endif
+
+  /* Tests for sign or specials, directly on DECFLOATs               */
+  #define DFISSIGNED(df)   (DFWORD(df, 0)&0x80000000)
+  #define DFISSPECIAL(df) ((DFWORD(df, 0)&0x78000000)==0x78000000)
+  #define DFISINF(df)    ((DFWORD(df, 0)&0x7c000000)==0x78000000)
+  #define DFISNAN(df)    ((DFWORD(df, 0)&0x7c000000)==0x7c000000)
+  #define DFISQNAN(df)   ((DFWORD(df, 0)&0x7e000000)==0x7c000000)
+  #define DFISSNAN(df)   ((DFWORD(df, 0)&0x7e000000)==0x7e000000)
+
+  /* Shared lookup tables                                            */
+  extern const uInt   DECCOMBMSD[64];  /* Combination field -> MSD   */
+  extern const uInt   DECCOMBFROM[48]; /* exp+msd -> Combination     */
+
+  /* Private generic (utility) routine                               */
+  #if DECCHECK || DECTRACE
+    extern void decShowNum(const bcdnum *, const char *);
+  #endif
+
+  /* Format-dependent macros and constants                           */
+  #if defined(DECPMAX)
+
+    /* Useful constants                                                      */
+    #define DECPMAX9  (ROUNDUP(DECPMAX, 9)/9)  /* 'Pmax' in 10**9s    */
+    /* Top words for a zero                                          */
+    #define SINGLEZERO  0x22500000
+    #define DOUBLEZERO  0x22380000
+    #define QUADZERO    0x22080000
+    /* [ZEROWORD is defined to be one of these in the DFISZERO macro] */
+
+    /* Format-dependent common tests:                                */
+    /*  DFISZERO   -- test for (any) zero                            */
+    /*  DFISCCZERO -- test for coefficient continuation being zero   */
+    /*  DFISCC01   -- test for coefficient contains only 0s and 1s   */
+    /*  DFISINT    -- test for finite and exponent q=0               */
+    /*  DFISUINT01 -- test for sign=0, finite, exponent q=0, and     */
+    /*                MSD=0 or 1                                     */
+    /*  ZEROWORD is also defined here.                               */
+    /* In DFISZERO the first test checks the least-significant word   */
+    /* (most likely to be non-zero); the penultimate tests MSD and    */
+    /* DPDs in the signword, and the final test excludes specials and */
+    /* MSD>7.  DFISINT similarly has to allow for the two forms of    */
+    /* MSD codes.  DFISUINT01 only has to allow for one form of MSD   */
+    /* code.                                                         */
+    #if DECPMAX==7
+      #define ZEROWORD SINGLEZERO
+      /* [test macros not needed except for Zero]                    */
+      #define DFISZERO(df)  ((DFWORD(df, 0)&0x1c0fffff)==0        \
+                         && (DFWORD(df, 0)&0x60000000)!=0x60000000)
+    #elif DECPMAX==16
+      #define ZEROWORD DOUBLEZERO
+      #define DFISZERO(df)  ((DFWORD(df, 1)==0                    \
+                         && (DFWORD(df, 0)&0x1c03ffff)==0         \
+                         && (DFWORD(df, 0)&0x60000000)!=0x60000000))
+      #define DFISINT(df) ((DFWORD(df, 0)&0x63fc0000)==0x22380000  \
+                        ||(DFWORD(df, 0)&0x7bfc0000)==0x6a380000)
+      #define DFISUINT01(df) ((DFWORD(df, 0)&0xfbfc0000)==0x22380000)
+      #define DFISCCZERO(df) (DFWORD(df, 1)==0                    \
+                         && (DFWORD(df, 0)&0x0003ffff)==0)
+      #define DFISCC01(df)  ((DFWORD(df, 0)&~0xfffc9124)==0       \
+                         && (DFWORD(df, 1)&~0x49124491)==0)
+    #elif DECPMAX==34
+      #define ZEROWORD QUADZERO
+      #define DFISZERO(df)  ((DFWORD(df, 3)==0                    \
+                         &&  DFWORD(df, 2)==0                     \
+                         &&  DFWORD(df, 1)==0                     \
+                         && (DFWORD(df, 0)&0x1c003fff)==0         \
+                         && (DFWORD(df, 0)&0x60000000)!=0x60000000))
+      #define DFISINT(df) ((DFWORD(df, 0)&0x63ffc000)==0x22080000  \
+                        ||(DFWORD(df, 0)&0x7bffc000)==0x6a080000)
+      #define DFISUINT01(df) ((DFWORD(df, 0)&0xfbffc000)==0x22080000)
+      #define DFISCCZERO(df) (DFWORD(df, 3)==0                    \
+                         &&  DFWORD(df, 2)==0                     \
+                         &&  DFWORD(df, 1)==0                     \
+                         && (DFWORD(df, 0)&0x00003fff)==0)
+
+      #define DFISCC01(df)   ((DFWORD(df, 0)&~0xffffc912)==0      \
+                         &&  (DFWORD(df, 1)&~0x44912449)==0       \
+                         &&  (DFWORD(df, 2)&~0x12449124)==0       \
+                         &&  (DFWORD(df, 3)&~0x49124491)==0)
+    #endif
+
+    /* Macros to test if a certain 10 bits of a uInt or pair of uInts */
+    /* are a canonical declet [higher or lower bits are ignored].     */
+    /* declet is at offset 0 (from the right) in a uInt:             */
+    #define CANONDPD(dpd) (((dpd)&0x300)==0 || ((dpd)&0x6e)!=0x6e)
+    /* declet is at offset k (a multiple of 2) in a uInt:            */
+    #define CANONDPDOFF(dpd, k) (((dpd)&(0x300<<(k)))==0           \
+      || ((dpd)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k)))
+    /* declet is at offset k (a multiple of 2) in a pair of uInts:    */
+    /* [the top 2 bits will always be in the more-significant uInt]   */
+    #define CANONDPDTWO(hi, lo, k) (((hi)&(0x300>>(32-(k))))==0            \
+      || ((hi)&(0x6e>>(32-(k))))!=(0x6e>>(32-(k)))                 \
+      || ((lo)&(((uInt)0x6e)<<(k)))!=(((uInt)0x6e)<<(k)))
+
+    /* Macro to test whether a full-length (length DECPMAX) BCD8      */
+    /* coefficient is zero                                           */
+    /* test just the LSWord first, then the remainder                */
+    #if DECPMAX==7
+      #define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0             \
+       && UINTAT((u)+DECPMAX-7)==0)
+    #elif DECPMAX==16
+      #define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0             \
+       && (UINTAT((u)+DECPMAX-8)+UINTAT((u)+DECPMAX-12)            \
+          +UINTAT((u)+DECPMAX-16))==0)
+    #elif DECPMAX==34
+      #define ISCOEFFZERO(u) (UINTAT((u)+DECPMAX-4)==0             \
+       && (UINTAT((u)+DECPMAX-8) +UINTAT((u)+DECPMAX-12)           \
+          +UINTAT((u)+DECPMAX-16)+UINTAT((u)+DECPMAX-20)           \
+          +UINTAT((u)+DECPMAX-24)+UINTAT((u)+DECPMAX-28)           \
+          +UINTAT((u)+DECPMAX-32)+USHORTAT((u)+DECPMAX-34))==0)
+    #endif
+
+    /* Macros and masks for the exponent continuation field and MSD   */
+    /* Get the exponent continuation from a decFloat *df as an Int    */
+    #define GETECON(df) ((Int)((DFWORD((df), 0)&0x03ffffff)>>(32-6-DECECONL)))
+    /* Ditto, from the next-wider format                             */
+    #define GETWECON(df) ((Int)((DFWWORD((df), 0)&0x03ffffff)>>(32-6-DECWECONL)))
+    /* Get the biased exponent similarly                             */
+    #define GETEXP(df) ((Int)(DECCOMBEXP[DFWORD((df), 0)>>26]+GETECON(df)))
+    /* Get the unbiased exponent similarly                           */
+    #define GETEXPUN(df) ((Int)GETEXP(df)-DECBIAS)
+    /* Get the MSD similarly (as uInt)                               */
+    #define GETMSD(df)  (DECCOMBMSD[DFWORD((df), 0)>>26])
+
+    /* Compile-time computes of the exponent continuation field masks */
+    /* full exponent continuation field:                             */
+    #define ECONMASK ((0x03ffffff>>(32-6-DECECONL))<<(32-6-DECECONL))
+    /* same, not including its first digit (the qNaN/sNaN selector):  */
+    #define ECONNANMASK ((0x01ffffff>>(32-6-DECECONL))<<(32-6-DECECONL))
+
+    /* Macros to decode the coefficient in a finite decFloat *df into */
+    /* a BCD string (uByte *bcdin) of length DECPMAX uBytes          */
+
+    /* In-line sequence to convert 10 bits at right end of uInt dpd   */
+    /* to three BCD8 digits starting at uByte u.  Note that an extra  */
+    /* byte is written to the right of the three digits because this  */
+    /* moves four at a time for speed; the alternative macro moves    */
+    /* exactly three bytes                                           */
+    #define dpd2bcd8(u, dpd) {                          \
+      UINTAT(u)=UINTAT(&DPD2BCD8[((dpd)&0x3ff)*4]);}
+
+    #define dpd2bcd83(u, dpd) {                                 \
+      *(u)=DPD2BCD8[((dpd)&0x3ff)*4];                   \
+      *(u+1)=DPD2BCD8[((dpd)&0x3ff)*4+1];               \
+      *(u+2)=DPD2BCD8[((dpd)&0x3ff)*4+2];}
+
+    /* Decode the declets.  After extracting each one, it is decoded  */
+    /* to BCD8 using a table lookup (also used for variable-length    */
+    /* decode).         Each DPD decode is 3 bytes BCD8 plus a one-byte      */
+    /* length which is not used, here).         Fixed-length 4-byte moves    */
+    /* are fast, however, almost everywhere, and so are used except   */
+    /* for the final three bytes (to avoid overrun).  The code below  */
+    /* is 36 instructions for Doubles and about 70 for Quads, even    */
+    /* on IA32.                                                              */
+
+    /* Two macros are defined for each format:                       */
+    /*  GETCOEFF extracts the coefficient of the current format      */
+    /*  GETWCOEFF extracts the coefficient of the next-wider format. */
+    /* The latter is a copy of the next-wider GETCOEFF using DFWWORD. */
+
+    #if DECPMAX==7
+    #define GETCOEFF(df, bcd) {                                 \
+      uInt sourhi=DFWORD(df, 0);                        \
+      *(bcd)=(uByte)DECCOMBMSD[sourhi>>26];             \
+      dpd2bcd8(bcd+1, sourhi>>10);                      \
+      dpd2bcd83(bcd+4, sourhi);}
+    #define GETWCOEFF(df, bcd) {                        \
+      uInt sourhi=DFWWORD(df, 0);                       \
+      uInt sourlo=DFWWORD(df, 1);                       \
+      *(bcd)=(uByte)DECCOMBMSD[sourhi>>26];             \
+      dpd2bcd8(bcd+1, sourhi>>8);                       \
+      dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30));      \
+      dpd2bcd8(bcd+7, sourlo>>20);                      \
+      dpd2bcd8(bcd+10, sourlo>>10);                     \
+      dpd2bcd83(bcd+13, sourlo);}
+
+    #elif DECPMAX==16
+    #define GETCOEFF(df, bcd) {                                 \
+      uInt sourhi=DFWORD(df, 0);                        \
+      uInt sourlo=DFWORD(df, 1);                        \
+      *(bcd)=(uByte)DECCOMBMSD[sourhi>>26];             \
+      dpd2bcd8(bcd+1, sourhi>>8);                       \
+      dpd2bcd8(bcd+4, (sourhi<<2) | (sourlo>>30));      \
+      dpd2bcd8(bcd+7, sourlo>>20);                      \
+      dpd2bcd8(bcd+10, sourlo>>10);                     \
+      dpd2bcd83(bcd+13, sourlo);}
+    #define GETWCOEFF(df, bcd) {                        \
+      uInt sourhi=DFWWORD(df, 0);                       \
+      uInt sourmh=DFWWORD(df, 1);                       \
+      uInt sourml=DFWWORD(df, 2);                       \
+      uInt sourlo=DFWWORD(df, 3);                       \
+      *(bcd)=(uByte)DECCOMBMSD[sourhi>>26];             \
+      dpd2bcd8(bcd+1, sourhi>>4);                       \
+      dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26));    \
+      dpd2bcd8(bcd+7, sourmh>>16);                      \
+      dpd2bcd8(bcd+10, sourmh>>6);                      \
+      dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28));   \
+      dpd2bcd8(bcd+16, sourml>>18);                     \
+      dpd2bcd8(bcd+19, sourml>>8);                      \
+      dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30));   \
+      dpd2bcd8(bcd+25, sourlo>>20);                     \
+      dpd2bcd8(bcd+28, sourlo>>10);                     \
+      dpd2bcd83(bcd+31, sourlo);}
+
+    #elif DECPMAX==34
+    #define GETCOEFF(df, bcd) {                                 \
+      uInt sourhi=DFWORD(df, 0);                        \
+      uInt sourmh=DFWORD(df, 1);                        \
+      uInt sourml=DFWORD(df, 2);                        \
+      uInt sourlo=DFWORD(df, 3);                        \
+      *(bcd)=(uByte)DECCOMBMSD[sourhi>>26];             \
+      dpd2bcd8(bcd+1, sourhi>>4);                       \
+      dpd2bcd8(bcd+4, ((sourhi)<<6) | (sourmh>>26));    \
+      dpd2bcd8(bcd+7, sourmh>>16);                      \
+      dpd2bcd8(bcd+10, sourmh>>6);                      \
+      dpd2bcd8(bcd+13, ((sourmh)<<4) | (sourml>>28));   \
+      dpd2bcd8(bcd+16, sourml>>18);                     \
+      dpd2bcd8(bcd+19, sourml>>8);                      \
+      dpd2bcd8(bcd+22, ((sourml)<<2) | (sourlo>>30));   \
+      dpd2bcd8(bcd+25, sourlo>>20);                     \
+      dpd2bcd8(bcd+28, sourlo>>10);                     \
+      dpd2bcd83(bcd+31, sourlo);}
+
+      #define GETWCOEFF(df, bcd) {??} /* [should never be used]              */
+    #endif
+
+    /* Macros to decode the coefficient in a finite decFloat *df into */
+    /* a base-billion uInt array, with the least-significant         */
+    /* 0-999999999 'digit' at offset 0.                                      */
+
+    /* Decode the declets.  After extracting each one, it is decoded  */
+    /* to binary using a table lookup. Three tables are used; one    */
+    /* the usual DPD to binary, the other two pre-multiplied by 1000  */
+    /* and 1000000 to avoid multiplication during decode.  These      */
+    /* tables can also be used for multiplying up the MSD as the DPD  */
+    /* code for 0 through 9 is the identity.                         */
+    #define DPD2BIN0 DPD2BIN        /* for prettier code             */
+
+    #if DECPMAX==7
+    #define GETCOEFFBILL(df, buf) {                          \
+      uInt sourhi=DFWORD(df, 0);                             \
+      (buf)[0]=DPD2BIN0[sourhi&0x3ff]                        \
+             +DPD2BINK[(sourhi>>10)&0x3ff]                   \
+             +DPD2BINM[DECCOMBMSD[sourhi>>26]];}
+
+    #elif DECPMAX==16
+    #define GETCOEFFBILL(df, buf) {                          \
+      uInt sourhi, sourlo;                                   \
+      sourlo=DFWORD(df, 1);                                  \
+      (buf)[0]=DPD2BIN0[sourlo&0x3ff]                        \
+             +DPD2BINK[(sourlo>>10)&0x3ff]                   \
+             +DPD2BINM[(sourlo>>20)&0x3ff];                  \
+      sourhi=DFWORD(df, 0);                                  \
+      (buf)[1]=DPD2BIN0[((sourhi<<2) | (sourlo>>30))&0x3ff]   \
+             +DPD2BINK[(sourhi>>8)&0x3ff]                    \
+             +DPD2BINM[DECCOMBMSD[sourhi>>26]];}
+
+    #elif DECPMAX==34
+    #define GETCOEFFBILL(df, buf) {                          \
+      uInt sourhi, sourmh, sourml, sourlo;                   \
+      sourlo=DFWORD(df, 3);                                  \
+      (buf)[0]=DPD2BIN0[sourlo&0x3ff]                        \
+             +DPD2BINK[(sourlo>>10)&0x3ff]                   \
+             +DPD2BINM[(sourlo>>20)&0x3ff];                  \
+      sourml=DFWORD(df, 2);                                  \
+      (buf)[1]=DPD2BIN0[((sourml<<2) | (sourlo>>30))&0x3ff]   \
+             +DPD2BINK[(sourml>>8)&0x3ff]                    \
+             +DPD2BINM[(sourml>>18)&0x3ff];                  \
+      sourmh=DFWORD(df, 1);                                  \
+      (buf)[2]=DPD2BIN0[((sourmh<<4) | (sourml>>28))&0x3ff]   \
+             +DPD2BINK[(sourmh>>6)&0x3ff]                    \
+             +DPD2BINM[(sourmh>>16)&0x3ff];                  \
+      sourhi=DFWORD(df, 0);                                  \
+      (buf)[3]=DPD2BIN0[((sourhi<<6) | (sourmh>>26))&0x3ff]   \
+             +DPD2BINK[(sourhi>>4)&0x3ff]                    \
+             +DPD2BINM[DECCOMBMSD[sourhi>>26]];}
+
+    #endif
+
+    /* Macros to decode the coefficient in a finite decFloat *df into */
+    /* a base-thousand uInt array, with the least-significant 0-999   */
+    /* 'digit' at offset 0.                                          */
+
+    /* Decode the declets.  After extracting each one, it is decoded  */
+    /* to binary using a table lookup.                               */
+    #if DECPMAX==7
+    #define GETCOEFFTHOU(df, buf) {                          \
+      uInt sourhi=DFWORD(df, 0);                             \
+      (buf)[0]=DPD2BIN[sourhi&0x3ff];                        \
+      (buf)[1]=DPD2BIN[(sourhi>>10)&0x3ff];                  \
+      (buf)[2]=DECCOMBMSD[sourhi>>26];}
+
+    #elif DECPMAX==16
+    #define GETCOEFFTHOU(df, buf) {                          \
+      uInt sourhi, sourlo;                                   \
+      sourlo=DFWORD(df, 1);                                  \
+      (buf)[0]=DPD2BIN[sourlo&0x3ff];                        \
+      (buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff];                  \
+      (buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff];                  \
+      sourhi=DFWORD(df, 0);                                  \
+      (buf)[3]=DPD2BIN[((sourhi<<2) | (sourlo>>30))&0x3ff];   \
+      (buf)[4]=DPD2BIN[(sourhi>>8)&0x3ff];                   \
+      (buf)[5]=DECCOMBMSD[sourhi>>26];}
+
+    #elif DECPMAX==34
+    #define GETCOEFFTHOU(df, buf) {                          \
+      uInt sourhi, sourmh, sourml, sourlo;                   \
+      sourlo=DFWORD(df, 3);                                  \
+      (buf)[0]=DPD2BIN[sourlo&0x3ff];                        \
+      (buf)[1]=DPD2BIN[(sourlo>>10)&0x3ff];                  \
+      (buf)[2]=DPD2BIN[(sourlo>>20)&0x3ff];                  \
+      sourml=DFWORD(df, 2);                                  \
+      (buf)[3]=DPD2BIN[((sourml<<2) | (sourlo>>30))&0x3ff];   \
+      (buf)[4]=DPD2BIN[(sourml>>8)&0x3ff];                   \
+      (buf)[5]=DPD2BIN[(sourml>>18)&0x3ff];                  \
+      sourmh=DFWORD(df, 1);                                  \
+      (buf)[6]=DPD2BIN[((sourmh<<4) | (sourml>>28))&0x3ff];   \
+      (buf)[7]=DPD2BIN[(sourmh>>6)&0x3ff];                   \
+      (buf)[8]=DPD2BIN[(sourmh>>16)&0x3ff];                  \
+      sourhi=DFWORD(df, 0);                                  \
+      (buf)[9]=DPD2BIN[((sourhi<<6) | (sourmh>>26))&0x3ff];   \
+      (buf)[10]=DPD2BIN[(sourhi>>4)&0x3ff];                  \
+      (buf)[11]=DECCOMBMSD[sourhi>>26];}
+
+    #endif
+
+    /* Set a decFloat to the maximum positive finite number (Nmax)    */
+    #if DECPMAX==7
+    #define DFSETNMAX(df)           \
+      {DFWORD(df, 0)=0x77f3fcff;}
+    #elif DECPMAX==16
+    #define DFSETNMAX(df)           \
+      {DFWORD(df, 0)=0x77fcff3f;     \
+       DFWORD(df, 1)=0xcff3fcff;}
+    #elif DECPMAX==34
+    #define DFSETNMAX(df)           \
+      {DFWORD(df, 0)=0x77ffcff3;     \
+       DFWORD(df, 1)=0xfcff3fcf;     \
+       DFWORD(df, 2)=0xf3fcff3f;     \
+       DFWORD(df, 3)=0xcff3fcff;}
+    #endif
+
+  /* [end of format-dependent macros and constants]                  */
+  #endif
 
 #else
-#error decNumberLocal included more than once
+  #error decNumberLocal included more than once
 #endif
diff --git a/libdecnumber/decNumberSymbols.h b/libdecnumber/decNumberSymbols.h
new file mode 100644 (file)
index 0000000..e638a07
--- /dev/null
@@ -0,0 +1,69 @@
+#if !defined(DECNUMBERSYMBOLS)
+#define DECNUMBERSYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decNumberAbs __decNumberAbs
+#define decNumberAdd __decNumberAdd
+#define decNumberAnd __decNumberAnd
+#define decNumberClass __decNumberClass
+#define decNumberClassToString __decNumberClassToString
+#define decNumberCompare __decNumberCompare
+#define decNumberCompareSignal __decNumberCompareSignal
+#define decNumberCompareTotal __decNumberCompareTotal
+#define decNumberCompareTotalMag __decNumberCompareTotalMag
+#define decNumberCopy __decNumberCopy
+#define decNumberCopyAbs __decNumberCopyAbs
+#define decNumberCopyNegate __decNumberCopyNegate
+#define decNumberCopySign __decNumberCopySign
+#define decNumberDivide __decNumberDivide
+#define decNumberDivideInteger __decNumberDivideInteger
+#define decNumberExp __decNumberExp
+#define decNumberFMA __decNumberFMA
+#define decNumberFromInt32 __decNumberFromInt32
+#define decNumberFromString __decNumberFromString
+#define decNumberFromUInt32 __decNumberFromUInt32
+#define decNumberGetBCD __decNumberGetBCD
+#define decNumberInvert __decNumberInvert
+#define decNumberIsNormal __decNumberIsNormal
+#define decNumberIsSubnormal __decNumberIsSubnormal
+#define decNumberLn __decNumberLn
+#define decNumberLog10 __decNumberLog10
+#define decNumberLogB __decNumberLogB
+#define decNumberMax __decNumberMax
+#define decNumberMaxMag __decNumberMaxMag
+#define decNumberMin __decNumberMin
+#define decNumberMinMag __decNumberMinMag
+#define decNumberMinus __decNumberMinus
+#define decNumberMultiply __decNumberMultiply
+#define decNumberNextMinus __decNumberNextMinus
+#define decNumberNextPlus __decNumberNextPlus
+#define decNumberNextToward __decNumberNextToward
+#define decNumberNormalize __decNumberNormalize
+#define decNumberOr __decNumberOr
+#define decNumberPlus __decNumberPlus
+#define decNumberPower __decNumberPower
+#define decNumberQuantize __decNumberQuantize
+#define decNumberReduce __decNumberReduce
+#define decNumberRemainder __decNumberRemainder
+#define decNumberRemainderNear __decNumberRemainderNear
+#define decNumberRescale __decNumberRescale
+#define decNumberRotate __decNumberRotate
+#define decNumberSameQuantum __decNumberSameQuantum
+#define decNumberScaleB __decNumberScaleB
+#define decNumberSetBCD __decNumberSetBCD
+#define decNumberShift __decNumberShift
+#define decNumberSquareRoot __decNumberSquareRoot
+#define decNumberSubtract __decNumberSubtract
+#define decNumberToEngString __decNumberToEngString
+#define decNumberToInt32 __decNumberToInt32
+#define decNumberToIntegralExact __decNumberToIntegralExact
+#define decNumberToIntegralValue __decNumberToIntegralValue
+#define decNumberToString __decNumberToString
+#define decNumberToUInt32 __decNumberToUInt32
+#define decNumberTrim __decNumberTrim
+#define decNumberVersion __decNumberVersion
+#define decNumberXor __decNumberXor
+#define decNumberZero __decNumberZero
+#endif
+
+#endif
diff --git a/libdecnumber/decPacked.c b/libdecnumber/decPacked.c
new file mode 100644 (file)
index 0000000..2b912fe
--- /dev/null
@@ -0,0 +1,235 @@
+/* Packed decimal conversion module for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* Packed Decimal conversion module                                  */
+/* ------------------------------------------------------------------ */
+/* This module comprises the routines for Packed Decimal format              */
+/* numbers.  Conversions are supplied to and from decNumber, which in */
+/* turn supports:                                                    */
+/*   conversions to and from string                                  */
+/*   arithmetic routines                                             */
+/*   utilities.                                                              */
+/* Conversions from decNumber to and from densely packed decimal      */
+/* formats are provided by the decimal32 through decimal128 modules.  */
+/* ------------------------------------------------------------------ */
+
+#include <string.h>          /* for NULL */
+#include "decNumber.h"       /* base number library */
+#include "decPacked.h"       /* packed decimal */
+#include "decNumberLocal.h"   /* decNumber local types, etc. */
+
+/* ------------------------------------------------------------------ */
+/* decPackedFromNumber -- convert decNumber to BCD Packed Decimal     */
+/*                                                                   */
+/*   bcd    is the BCD bytes                                         */
+/*   length is the length of the BCD array                           */
+/*   scale  is the scale result                                              */
+/*   dn            is the decNumber                                          */
+/*   returns bcd, or NULL if error                                   */
+/*                                                                   */
+/* The number is converted to a BCD packed decimal byte array,       */
+/* right aligned in the bcd array, whose length is indicated by the   */
+/* second parameter.  The final 4-bit nibble in the array will be a   */
+/* sign nibble, C (1100) for + and D (1101) for -.  Unused bytes and  */
+/* nibbles to the left of the number are set to 0.                   */
+/*                                                                   */
+/* scale is set to the scale of the number (this is the exponent,     */
+/* negated).  To force the number to a specified scale, first use the */
+/* decNumberRescale routine, which will round and change the exponent */
+/* as necessary.                                                     */
+/*                                                                   */
+/* If there is an error (that is, the decNumber has too many digits   */
+/* to fit in length bytes, or it is a NaN or Infinity), NULL is              */
+/* returned and the bcd and scale results are unchanged.  Otherwise   */
+/* bcd is returned.                                                  */
+/* ------------------------------------------------------------------ */
+uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale,
+                           const decNumber *dn) {
+  const Unit *up=dn->lsu;     /* Unit array pointer */
+  uByte obyte, *out;         /* current output byte, and where it goes */
+  Int indigs=dn->digits;      /* digits processed */
+  uInt cut=DECDPUN;          /* downcounter per Unit */
+  uInt u=*up;                /* work */
+  uInt nib;                  /* .. */
+  #if DECDPUN<=4
+  uInt temp;                 /* .. */
+  #endif
+
+  if (dn->digits>length*2-1                 /* too long .. */
+   ||(dn->bits & DECSPECIAL)) return NULL;   /* .. or special -- hopeless */
+
+  if (dn->bits&DECNEG) obyte=DECPMINUS;             /* set the sign .. */
+   else                       obyte=DECPPLUS;
+  *scale=-dn->exponent;                             /* .. and scale */
+
+  /* loop from lowest (rightmost) byte */
+  out=bcd+length-1;                         /* -> final byte */
+  for (; out>=bcd; out--) {
+    if (indigs>0) {
+      if (cut==0) {
+       up++;
+       u=*up;
+       cut=DECDPUN;
+       }
+      #if DECDPUN<=4
+       temp=(u*6554)>>16;         /* fast /10 */
+       nib=u-X10(temp);
+       u=temp;
+      #else
+       nib=u%10;                  /* cannot use *6554 trick :-( */
+       u=u/10;
+      #endif
+      obyte|=(nib<<4);
+      indigs--;
+      cut--;
+      }
+    *out=obyte;
+    obyte=0;                      /* assume 0 */
+    if (indigs>0) {
+      if (cut==0) {
+       up++;
+       u=*up;
+       cut=DECDPUN;
+       }
+      #if DECDPUN<=4
+       temp=(u*6554)>>16;         /* as above */
+       obyte=(uByte)(u-X10(temp));
+       u=temp;
+      #else
+       obyte=(uByte)(u%10);
+       u=u/10;
+      #endif
+      indigs--;
+      cut--;
+      }
+    } /* loop */
+
+  return bcd;
+  } /* decPackedFromNumber */
+
+/* ------------------------------------------------------------------ */
+/* decPackedToNumber -- convert BCD Packed Decimal to a decNumber     */
+/*                                                                   */
+/*   bcd    is the BCD bytes                                         */
+/*   length is the length of the BCD array                           */
+/*   scale  is the scale associated with the BCD integer             */
+/*   dn            is the decNumber [with space for length*2 digits]         */
+/*   returns dn, or NULL if error                                    */
+/*                                                                   */
+/* The BCD packed decimal byte array, together with an associated     */
+/* scale, is converted to a decNumber. The BCD array is assumed full */
+/* of digits, and must be ended by a 4-bit sign nibble in the least   */
+/* significant four bits of the final byte.                          */
+/*                                                                   */
+/* The scale is used (negated) as the exponent of the decNumber.      */
+/* Note that zeros may have a sign and/or a scale.                   */
+/*                                                                   */
+/* The decNumber structure is assumed to have sufficient space to     */
+/* hold the converted number (that is, up to length*2-1 digits), so   */
+/* no error is possible unless the adjusted exponent is out of range, */
+/* no sign nibble was found, or a sign nibble was found before the    */
+/* final nibble.  In these error cases, NULL is returned and the      */
+/* decNumber will be 0.                                                      */
+/* ------------------------------------------------------------------ */
+decNumber * decPackedToNumber(const uByte *bcd, Int length,
+                             const Int *scale, decNumber *dn) {
+  const uByte *last=bcd+length-1;  /* -> last byte */
+  const uByte *first;             /* -> first non-zero byte */
+  uInt nib;                       /* work nibble */
+  Unit *up=dn->lsu;               /* output pointer */
+  Int  digits;                    /* digits count */
+  Int  cut=0;                     /* phase of output */
+
+  decNumberZero(dn);              /* default result */
+  last=&bcd[length-1];
+  nib=*last & 0x0f;               /* get the sign */
+  if (nib==DECPMINUS || nib==DECPMINUSALT) dn->bits=DECNEG;
+   else if (nib<=9) return NULL;   /* not a sign nibble */
+
+  /* skip leading zero bytes [final byte is always non-zero, due to sign] */
+  for (first=bcd; *first==0;) first++;
+  digits=(last-first)*2+1;             /* calculate digits .. */
+  if ((*first & 0xf0)==0) digits--;    /* adjust for leading zero nibble */
+  if (digits!=0) dn->digits=digits;    /* count of actual digits [if 0, */
+                                       /* leave as 1] */
+
+  /* check the adjusted exponent; note that scale could be unbounded */
+  dn->exponent=-*scale;                        /* set the exponent */
+  if (*scale>=0) {                     /* usual case */
+    if ((dn->digits-*scale-1)<-DECNUMMAXE) {     /* underflow */
+      decNumberZero(dn);
+      return NULL;}
+    }
+   else { /* -ve scale; +ve exponent */
+    /* need to be careful to avoid wrap, here, also BADINT case */
+    if ((*scale<-DECNUMMAXE)           /* overflow even without digits */
+        || ((dn->digits-*scale-1)>DECNUMMAXE)) { /* overflow */
+      decNumberZero(dn);
+      return NULL;}
+    }
+  if (digits==0) return dn;            /* result was zero */
+
+  /* copy the digits to the number's units, starting at the lsu */
+  /* [unrolled] */
+  for (;;) {                           /* forever */
+    /* left nibble first */
+    nib=(unsigned)(*last & 0xf0)>>4;
+    /* got a digit, in nib */
+    if (nib>9) {decNumberZero(dn); return NULL;}
+
+    if (cut==0) *up=(Unit)nib;
+     else *up=(Unit)(*up+nib*DECPOWERS[cut]);
+    digits--;
+    if (digits==0) break;              /* got them all */
+    cut++;
+    if (cut==DECDPUN) {
+      up++;
+      cut=0;
+      }
+    last--;                            /* ready for next */
+    nib=*last & 0x0f;                  /* get right nibble */
+    if (nib>9) {decNumberZero(dn); return NULL;}
+
+    /* got a digit, in nib */
+    if (cut==0) *up=(Unit)nib;
+     else *up=(Unit)(*up+nib*DECPOWERS[cut]);
+    digits--;
+    if (digits==0) break;              /* got them all */
+    cut++;
+    if (cut==DECDPUN) {
+      up++;
+      cut=0;
+      }
+    } /* forever */
+
+  return dn;
+  } /* decPackedToNumber */
+
diff --git a/libdecnumber/decPacked.h b/libdecnumber/decPacked.h
new file mode 100644 (file)
index 0000000..c76aa09
--- /dev/null
@@ -0,0 +1,70 @@
+/* Packed decimal conversion module header for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* Packed Decimal conversion module header                           */
+/* ------------------------------------------------------------------ */
+
+#if !defined(DECPACKED)
+  #define DECPACKED
+  #define DECPNAME     "decPacked"                     /* Short name */
+  #define DECPFULLNAME "Packed Decimal conversions"   /* Verbose name */
+  #define DECPAUTHOR   "Mike Cowlishaw"                      /* Who to blame */
+
+  #define DECPACKED_DefP 32            /* default precision          */
+
+  #ifndef  DECNUMDIGITS
+    #define DECNUMDIGITS DECPACKED_DefP /* size if not already defined*/
+  #endif
+  #include "decNumber.h"               /* context and number library */
+
+  /* Sign nibble constants                                           */
+  #if !defined(DECPPLUSALT)
+    #define DECPPLUSALT         0x0A /* alternate plus  nibble               */
+    #define DECPMINUSALT 0x0B /* alternate minus nibble                      */
+    #define DECPPLUS    0x0C /* preferred plus  nibble               */
+    #define DECPMINUS   0x0D /* preferred minus nibble               */
+    #define DECPPLUSALT2 0x0E /* alternate plus         nibble               */
+    #define DECPUNSIGNED 0x0F /* alternate plus         nibble (unsigned)    */
+  #endif
+
+  /* ---------------------------------------------------------------- */
+  /* decPacked public routines                                       */
+  /* ---------------------------------------------------------------- */
+
+  #include "decPackedSymbols.h"
+
+  /* Conversions                                                     */
+  uint8_t * decPackedFromNumber(uint8_t *, int32_t, int32_t *,
+                               const decNumber *);
+  decNumber * decPackedToNumber(const uint8_t *, int32_t, const int32_t *,
+                               decNumber *);
+
+#endif
diff --git a/libdecnumber/decPackedSymbols.h b/libdecnumber/decPackedSymbols.h
new file mode 100644 (file)
index 0000000..862db40
--- /dev/null
@@ -0,0 +1,9 @@
+#if !defined(DECPACKEDSYMBOLS)
+#define DECPACKEDSYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decPackedFromNumber __decPackedFromNumber
+#define decPackedToNumber __decPackedToNumber
+#endif
+
+#endif
diff --git a/libdecnumber/decQuad.c b/libdecnumber/decQuad.c
new file mode 100644 (file)
index 0000000..6ec9b7f
--- /dev/null
@@ -0,0 +1,146 @@
+/* decQuad module for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* decQuad.c -- decQuad operations module                            */
+/* ------------------------------------------------------------------ */
+/* This module comprises decQuad operations (including conversions)   */
+/* ------------------------------------------------------------------ */
+
+#include "decContext.h"              /* public includes */
+#include "decQuad.h"         /* .. */
+
+/* Constant mappings for shared code */
+#define DECPMAX            DECQUAD_Pmax
+#define DECEMIN            DECQUAD_Emin
+#define DECEMAX            DECQUAD_Emax
+#define DECEMAXD    DECQUAD_EmaxD
+#define DECBYTES    DECQUAD_Bytes
+#define DECSTRING   DECQUAD_String
+#define DECECONL    DECQUAD_EconL
+#define DECBIAS            DECQUAD_Bias
+#define DECLETS            DECQUAD_Declets
+#define DECQTINY   (-DECQUAD_Bias)
+
+/* Type and function mappings for shared code */
+#define decFloat               decQuad           /* Type name */
+
+/* Utilities and conversions (binary results, extractors, etc.) */
+#define decFloatFromBCD                decQuadFromBCD
+#define decFloatFromInt32      decQuadFromInt32
+#define decFloatFromPacked     decQuadFromPacked
+#define decFloatFromString     decQuadFromString
+#define decFloatFromUInt32     decQuadFromUInt32
+#define decFloatFromWider      decQuadFromWider
+#define decFloatGetCoefficient decQuadGetCoefficient
+#define decFloatGetExponent    decQuadGetExponent
+#define decFloatSetCoefficient decQuadSetCoefficient
+#define decFloatSetExponent    decQuadSetExponent
+#define decFloatShow           decQuadShow
+#define decFloatToBCD          decQuadToBCD
+#define decFloatToEngString    decQuadToEngString
+#define decFloatToInt32                decQuadToInt32
+#define decFloatToInt32Exact   decQuadToInt32Exact
+#define decFloatToPacked       decQuadToPacked
+#define decFloatToString       decQuadToString
+#define decFloatToUInt32       decQuadToUInt32
+#define decFloatToUInt32Exact  decQuadToUInt32Exact
+#define decFloatToWider                decQuadToWider
+#define decFloatZero           decQuadZero
+
+/* Computational (result is a decFloat) */
+#define decFloatAbs            decQuadAbs
+#define decFloatAdd            decQuadAdd
+#define decFloatAnd            decQuadAnd
+#define decFloatDivide         decQuadDivide
+#define decFloatDivideInteger  decQuadDivideInteger
+#define decFloatFMA            decQuadFMA
+#define decFloatInvert         decQuadInvert
+#define decFloatLogB           decQuadLogB
+#define decFloatMax            decQuadMax
+#define decFloatMaxMag         decQuadMaxMag
+#define decFloatMin            decQuadMin
+#define decFloatMinMag         decQuadMinMag
+#define decFloatMinus          decQuadMinus
+#define decFloatMultiply       decQuadMultiply
+#define decFloatNextMinus      decQuadNextMinus
+#define decFloatNextPlus       decQuadNextPlus
+#define decFloatNextToward     decQuadNextToward
+#define decFloatOr             decQuadOr
+#define decFloatPlus           decQuadPlus
+#define decFloatQuantize       decQuadQuantize
+#define decFloatReduce         decQuadReduce
+#define decFloatRemainder      decQuadRemainder
+#define decFloatRemainderNear  decQuadRemainderNear
+#define decFloatRotate         decQuadRotate
+#define decFloatScaleB         decQuadScaleB
+#define decFloatShift          decQuadShift
+#define decFloatSubtract       decQuadSubtract
+#define decFloatToIntegralValue decQuadToIntegralValue
+#define decFloatToIntegralExact decQuadToIntegralExact
+#define decFloatXor            decQuadXor
+
+/* Comparisons */
+#define decFloatCompare                decQuadCompare
+#define decFloatCompareSignal  decQuadCompareSignal
+#define decFloatCompareTotal   decQuadCompareTotal
+#define decFloatCompareTotalMag decQuadCompareTotalMag
+
+/* Copies */
+#define decFloatCanonical      decQuadCanonical
+#define decFloatCopy           decQuadCopy
+#define decFloatCopyAbs                decQuadCopyAbs
+#define decFloatCopyNegate     decQuadCopyNegate
+#define decFloatCopySign       decQuadCopySign
+
+/* Non-computational */
+#define decFloatClass          decQuadClass
+#define decFloatClassString    decQuadClassString
+#define decFloatDigits         decQuadDigits
+#define decFloatIsCanonical    decQuadIsCanonical
+#define decFloatIsFinite       decQuadIsFinite
+#define decFloatIsInfinite     decQuadIsInfinite
+#define decFloatIsInteger      decQuadIsInteger
+#define decFloatIsNaN          decQuadIsNaN
+#define decFloatIsNormal       decQuadIsNormal
+#define decFloatIsSignaling    decQuadIsSignaling
+#define decFloatIsSignalling   decQuadIsSignalling
+#define decFloatIsSigned       decQuadIsSigned
+#define decFloatIsSubnormal    decQuadIsSubnormal
+#define decFloatIsZero         decQuadIsZero
+#define decFloatRadix          decQuadRadix
+#define decFloatSameQuantum    decQuadSameQuantum
+#define decFloatVersion                decQuadVersion
+
+
+#include "decNumberLocal.h"   /* local includes (need DECPMAX) */
+#include "decCommon.c"       /* non-arithmetic decFloat routines */
+#include "decBasic.c"        /* basic formats routines */
+
diff --git a/libdecnumber/decQuad.h b/libdecnumber/decQuad.h
new file mode 100644 (file)
index 0000000..39f75d3
--- /dev/null
@@ -0,0 +1,186 @@
+/* decQuad module header for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* decQuad.h -- Decimal 128-bit format module header                 */
+/* ------------------------------------------------------------------ */
+/* Please see decFloats.h for an overview and documentation details.  */
+/* ------------------------------------------------------------------ */
+/* This include file is always included by decSingle and decDouble,   */
+/* and therefore also holds useful constants used by all three.              */
+
+#if !defined(DECQUAD)
+  #define DECQUAD
+
+  #define DECQUADNAME        "decimalQuad"           /* Short name   */
+  #define DECQUADTITLE       "Decimal 128-bit datum" /* Verbose name */
+  #define DECQUADAUTHOR              "Mike Cowlishaw"        /* Who to blame */
+
+  /* parameters for decQuads */
+  #define DECQUAD_Bytes           16      /* length                          */
+  #define DECQUAD_Pmax    34      /* maximum precision (digits)      */
+  #define DECQUAD_Emin -6143      /* minimum adjusted exponent       */
+  #define DECQUAD_Emax  6144      /* maximum adjusted exponent       */
+  #define DECQUAD_EmaxD            4      /* maximum exponent digits         */
+  #define DECQUAD_Bias  6176      /* bias for the exponent           */
+  #define DECQUAD_String   43     /* maximum string length, +1       */
+  #define DECQUAD_EconL           12      /* exponent continuation length    */
+  #define DECQUAD_Declets  11     /* count of declets                */
+  /* highest biased exponent (Elimit-1) */
+  #define DECQUAD_Ehigh (DECQUAD_Emax + DECQUAD_Bias - (DECQUAD_Pmax-1))
+
+  /* Required include                                                */
+  #include "decContext.h"
+
+  /* The decQuad decimal 128-bit type, accessible by bytes */
+  typedef struct {
+    uint8_t bytes[DECQUAD_Bytes];  /* fields: 1, 5, 12, 110 bits */
+    } decQuad;
+
+  /* ---------------------------------------------------------------- */
+  /* Shared constants                                                */
+  /* ---------------------------------------------------------------- */
+
+  /* sign and special values [top 32-bits; last two bits are don't-care
+     for Infinity on input, last bit don't-care for NaNs] */
+  #define DECFLOAT_Sign         0x80000000     /* 1 00000 00 Sign */
+  #define DECFLOAT_NaN  0x7c000000     /* 0 11111 00 NaN generic */
+  #define DECFLOAT_qNaN         0x7c000000     /* 0 11111 00 qNaN */
+  #define DECFLOAT_sNaN         0x7e000000     /* 0 11111 10 sNaN */
+  #define DECFLOAT_Inf  0x78000000     /* 0 11110 00 Infinity */
+  #define DECFLOAT_MinSp 0x78000000    /* minimum special value */
+                                       /* [specials are all >=MinSp] */
+  /* Sign nibble constants                                           */
+  #if !defined(DECPPLUSALT)
+    #define DECPPLUSALT         0x0A /* alternate plus  nibble               */
+    #define DECPMINUSALT 0x0B /* alternate minus nibble                      */
+    #define DECPPLUS    0x0C /* preferred plus  nibble               */
+    #define DECPMINUS   0x0D /* preferred minus nibble               */
+    #define DECPPLUSALT2 0x0E /* alternate plus         nibble               */
+    #define DECPUNSIGNED 0x0F /* alternate plus         nibble (unsigned)    */
+  #endif
+
+  /* ---------------------------------------------------------------- */
+  /* Routines -- implemented as decFloat routines in common files     */
+  /* ---------------------------------------------------------------- */
+
+  #include "decQuadSymbols.h"
+
+  /* Utilities and conversions, extractors, etc.) */
+  extern decQuad * decQuadFromBCD(decQuad *, int32_t, const uint8_t *, int32_t);
+  extern decQuad * decQuadFromInt32(decQuad *, int32_t);
+  extern decQuad * decQuadFromPacked(decQuad *, int32_t, const uint8_t *);
+  extern decQuad * decQuadFromString(decQuad *, const char *, decContext *);
+  extern decQuad * decQuadFromUInt32(decQuad *, uint32_t);
+  extern int32_t   decQuadGetCoefficient(const decQuad *, uint8_t *);
+  extern int32_t   decQuadGetExponent(const decQuad *);
+  extern decQuad * decQuadSetCoefficient(decQuad *, const uint8_t *, int32_t);
+  extern decQuad * decQuadSetExponent(decQuad *, decContext *, int32_t);
+  extern void     decQuadShow(const decQuad *, const char *);
+  extern int32_t   decQuadToBCD(const decQuad *, int32_t *, uint8_t *);
+  extern char   * decQuadToEngString(const decQuad *, char *);
+  extern int32_t   decQuadToInt32(const decQuad *, decContext *, enum rounding);
+  extern int32_t   decQuadToInt32Exact(const decQuad *, decContext *, enum rounding);
+  extern int32_t   decQuadToPacked(const decQuad *, int32_t *, uint8_t *);
+  extern char   * decQuadToString(const decQuad *, char *);
+  extern uint32_t  decQuadToUInt32(const decQuad *, decContext *, enum rounding);
+  extern uint32_t  decQuadToUInt32Exact(const decQuad *, decContext *, enum rounding);
+  extern decQuad * decQuadZero(decQuad *);
+
+  /* Computational (result is a decQuad) */
+  extern decQuad * decQuadAbs(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadAdd(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadAnd(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadDivide(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadDivideInteger(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadFMA(decQuad *, const decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadInvert(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadLogB(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadMax(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadMaxMag(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadMin(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadMinMag(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadMinus(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadMultiply(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadNextMinus(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadNextPlus(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadNextToward(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadOr(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadPlus(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadQuantize(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadReduce(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadRemainder(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadRemainderNear(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadRotate(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadScaleB(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadShift(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadSubtract(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadToIntegralValue(decQuad *, const decQuad *, decContext *, enum rounding);
+  extern decQuad * decQuadToIntegralExact(decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadXor(decQuad *, const decQuad *, const decQuad *, decContext *);
+
+  /* Comparisons */
+  extern decQuad * decQuadCompare(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadCompareSignal(decQuad *, const decQuad *, const decQuad *, decContext *);
+  extern decQuad * decQuadCompareTotal(decQuad *, const decQuad *, const decQuad *);
+  extern decQuad * decQuadCompareTotalMag(decQuad *, const decQuad *, const decQuad *);
+
+  /* Copies */
+  extern decQuad * decQuadCanonical(decQuad *, const decQuad *);
+  extern decQuad * decQuadCopy(decQuad *, const decQuad *);
+  extern decQuad * decQuadCopyAbs(decQuad *, const decQuad *);
+  extern decQuad * decQuadCopyNegate(decQuad *, const decQuad *);
+  extern decQuad * decQuadCopySign(decQuad *, const decQuad *, const decQuad *);
+
+  /* Non-computational */
+  extern enum decClass decQuadClass(const decQuad *);
+  extern const char *  decQuadClassString(const decQuad *);
+  extern uint32_t      decQuadDigits(const decQuad *);
+  extern uint32_t      decQuadIsCanonical(const decQuad *);
+  extern uint32_t      decQuadIsFinite(const decQuad *);
+  extern uint32_t      decQuadIsInteger(const decQuad *);
+  extern uint32_t      decQuadIsInfinite(const decQuad *);
+  extern uint32_t      decQuadIsNaN(const decQuad *);
+  extern uint32_t      decQuadIsNormal(const decQuad *);
+  extern uint32_t      decQuadIsSignaling(const decQuad *);
+  extern uint32_t      decQuadIsSignalling(const decQuad *);
+  extern uint32_t      decQuadIsSigned(const decQuad *);
+  extern uint32_t      decQuadIsSubnormal(const decQuad *);
+  extern uint32_t      decQuadIsZero(const decQuad *);
+  extern uint32_t      decQuadRadix(const decQuad *);
+  extern uint32_t      decQuadSameQuantum(const decQuad *, const decQuad *);
+  extern const char *  decQuadVersion(void);
+
+  /* decNumber conversions; these are implemented as macros so as not  */
+  /* to force a dependency on decimal128 and decNumber in decQuad.     */
+  #define decQuadToNumber(dq, dn) decimal128ToNumber((decimal128 *)(dq), dn)
+  #define decQuadFromNumber(dq, dn, set) (decQuad *)decimal128FromNumber((decimal128 *)(dq), dn, set)
+
+#endif
diff --git a/libdecnumber/decQuadSymbols.h b/libdecnumber/decQuadSymbols.h
new file mode 100644 (file)
index 0000000..5f614d4
--- /dev/null
@@ -0,0 +1,82 @@
+#if !defined(DECQUADSYMBOLS)
+#define DECQUADSYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decQuadAbs __decQuadAbs
+#define decQuadAdd __decQuadAdd
+#define decQuadAnd __decQuadAnd
+#define decQuadCanonical __decQuadCanonical
+#define decQuadClass __decQuadClass
+#define decQuadClassString __decQuadClassString
+#define decQuadCompare __decQuadCompare
+#define decQuadCompareSignal __decQuadCompareSignal
+#define decQuadCompareTotal __decQuadCompareTotal
+#define decQuadCompareTotalMag __decQuadCompareTotalMag
+#define decQuadCopy __decQuadCopy
+#define decQuadCopyAbs __decQuadCopyAbs
+#define decQuadCopyNegate __decQuadCopyNegate
+#define decQuadCopySign __decQuadCopySign
+#define decQuadDigits __decQuadDigits
+#define decQuadDivide __decQuadDivide
+#define decQuadDivideInteger __decQuadDivideInteger
+#define decQuadFMA __decQuadFMA
+#define decQuadFromBCD __decQuadFromBCD
+#define decQuadFromInt32 __decQuadFromInt32
+#define decQuadFromPacked __decQuadFromPacked
+#define decQuadFromString __decQuadFromString
+#define decQuadFromUInt32 __decQuadFromUInt32
+#define decQuadGetCoefficient __decQuadGetCoefficient
+#define decQuadGetExponent __decQuadGetExponent
+#define decQuadInvert __decQuadInvert
+#define decQuadIsCanonical __decQuadIsCanonical
+#define decQuadIsFinite __decQuadIsFinite
+#define decQuadIsInfinite __decQuadIsInfinite
+#define decQuadIsInteger __decQuadIsInteger
+#define decQuadIsNaN __decQuadIsNaN
+#define decQuadIsNormal __decQuadIsNormal
+#define decQuadIsSignaling __decQuadIsSignaling
+#define decQuadIsSignalling __decQuadIsSignalling
+#define decQuadIsSigned __decQuadIsSigned
+#define decQuadIsSubnormal __decQuadIsSubnormal
+#define decQuadIsZero __decQuadIsZero
+#define decQuadLogB __decQuadLogB
+#define decQuadMax __decQuadMax
+#define decQuadMaxMag __decQuadMaxMag
+#define decQuadMin __decQuadMin
+#define decQuadMinMag __decQuadMinMag
+#define decQuadMinus __decQuadMinus
+#define decQuadMultiply __decQuadMultiply
+#define decQuadNextMinus __decQuadNextMinus
+#define decQuadNextPlus __decQuadNextPlus
+#define decQuadNextToward __decQuadNextToward
+#define decQuadOr __decQuadOr
+#define decQuadPlus __decQuadPlus
+#define decQuadQuantize __decQuadQuantize
+#define decQuadRadix __decQuadRadix
+#define decQuadReduce __decQuadReduce
+#define decQuadRemainder __decQuadRemainder
+#define decQuadRemainderNear __decQuadRemainderNear
+#define decQuadRotate __decQuadRotate
+#define decQuadSameQuantum __decQuadSameQuantum
+#define decQuadScaleB __decQuadScaleB
+#define decQuadSetCoefficient __decQuadSetCoefficient
+#define decQuadSetExponent __decQuadSetExponent
+#define decQuadShift __decQuadShift
+#define decQuadShow __decQuadShow
+#define decQuadSubtract __decQuadSubtract
+#define decQuadToBCD __decQuadToBCD
+#define decQuadToEngString __decQuadToEngString
+#define decQuadToInt32 __decQuadToInt32
+#define decQuadToInt32Exact __decQuadToInt32Exact
+#define decQuadToIntegralExact __decQuadToIntegralExact
+#define decQuadToIntegralValue __decQuadToIntegralValue
+#define decQuadToPacked __decQuadToPacked
+#define decQuadToString __decQuadToString
+#define decQuadToUInt32 __decQuadToUInt32
+#define decQuadToUInt32Exact __decQuadToUInt32Exact
+#define decQuadVersion __decQuadVersion
+#define decQuadXor __decQuadXor
+#define decQuadZero __decQuadZero
+#endif
+
+#endif
diff --git a/libdecnumber/decSingle.c b/libdecnumber/decSingle.c
new file mode 100644 (file)
index 0000000..1123959
--- /dev/null
@@ -0,0 +1,85 @@
+/* decSingle module for the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* decSingle.c -- decSingle operations module                        */
+/* ------------------------------------------------------------------ */
+/* This module comprises decSingle operations (including conversions) */
+/* ------------------------------------------------------------------ */
+
+#include "decContext.h"              /* public includes */
+#include "decSingle.h"       /* public includes */
+
+/* Constant mappings for shared code */
+#define DECPMAX            DECSINGLE_Pmax
+#define DECEMIN            DECSINGLE_Emin
+#define DECEMAX            DECSINGLE_Emax
+#define DECEMAXD    DECSINGLE_EmaxD
+#define DECBYTES    DECSINGLE_Bytes
+#define DECSTRING   DECSINGLE_String
+#define DECECONL    DECSINGLE_EconL
+#define DECBIAS            DECSINGLE_Bias
+#define DECLETS            DECSINGLE_Declets
+#define DECQTINY    (-DECSINGLE_Bias)
+/* parameters of next-wider format */
+#define DECWBYTES   DECDOUBLE_Bytes
+#define DECWPMAX    DECDOUBLE_Pmax
+#define DECWECONL   DECDOUBLE_EconL
+#define DECWBIAS    DECDOUBLE_Bias
+
+/* Type and function mappings for shared code */
+#define decFloat               decSingle         /* Type name */
+#define decFloatWider          decDouble         /* Type name */
+
+/* Utility (binary results, extractors, etc.) */
+#define decFloatFromBCD                decSingleFromBCD
+#define decFloatFromPacked     decSingleFromPacked
+#define decFloatFromString     decSingleFromString
+#define decFloatFromWider      decSingleFromWider
+#define decFloatGetCoefficient decSingleGetCoefficient
+#define decFloatGetExponent    decSingleGetExponent
+#define decFloatSetCoefficient decSingleSetCoefficient
+#define decFloatSetExponent    decSingleSetExponent
+#define decFloatShow           decSingleShow
+#define decFloatToBCD          decSingleToBCD
+#define decFloatToEngString    decSingleToEngString
+#define decFloatToPacked       decSingleToPacked
+#define decFloatToString       decSingleToString
+#define decFloatToWider                decSingleToWider
+#define decFloatZero           decSingleZero
+
+/* Non-computational */
+#define decFloatRadix          decSingleRadix
+#define decFloatVersion                decSingleVersion
+
+#include "decNumberLocal.h"   /* local includes (need DECPMAX) */
+#include "decCommon.c"       /* non-basic decFloat routines */
+/* [Do not include decBasic.c for decimal32] */
+
diff --git a/libdecnumber/decSingle.h b/libdecnumber/decSingle.h
new file mode 100644 (file)
index 0000000..8dd1bd3
--- /dev/null
@@ -0,0 +1,101 @@
+/* decSingle module header for the decNumber C Library.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   Contributed by IBM Corporation.  Author Mike Cowlishaw.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* ------------------------------------------------------------------ */
+/* decSingle.h -- Decimal 32-bit format module header                */
+/* ------------------------------------------------------------------ */
+/* Please see decFloats.h for an overview and documentation details.  */
+/* ------------------------------------------------------------------ */
+
+#if !defined(DECSINGLE)
+  #define DECSINGLE
+
+  #define DECSINGLENAME              "decSingle"             /* Short name   */
+  #define DECSINGLETITLE      "Decimal 32-bit datum"  /* Verbose name */
+  #define DECSINGLEAUTHOR     "Mike Cowlishaw"       /* Who to blame */
+
+  /* parameters for decSingles */
+  #define DECSINGLE_Bytes    4    /* length                          */
+  #define DECSINGLE_Pmax     7    /* maximum precision (digits)      */
+  #define DECSINGLE_Emin   -95    /* minimum adjusted exponent       */
+  #define DECSINGLE_Emax    96    /* maximum adjusted exponent       */
+  #define DECSINGLE_EmaxD    3    /* maximum exponent digits         */
+  #define DECSINGLE_Bias   101    /* bias for the exponent           */
+  #define DECSINGLE_String  16    /* maximum string length, +1       */
+  #define DECSINGLE_EconL    6    /* exponent continuation length    */
+  #define DECSINGLE_Declets  2    /* count of declets                */
+  /* highest biased exponent (Elimit-1) */
+  #define DECSINGLE_Ehigh (DECSINGLE_Emax + DECSINGLE_Bias - (DECSINGLE_Pmax-1))
+
+  /* Required includes                                               */
+  #include "decContext.h"
+  #include "decQuad.h"
+  #include "decDouble.h"
+
+  /* The decSingle decimal 32-bit type, accessible by bytes */
+  typedef struct {
+    uint8_t bytes[DECSINGLE_Bytes];    /* fields: 1, 5, 6, 20 bits */
+    } decSingle;
+
+  /* ---------------------------------------------------------------- */
+  /* Routines -- implemented as decFloat routines in common files     */
+  /* ---------------------------------------------------------------- */
+
+  #include "decSingleSymbols.h"
+
+  /* Utilities (binary argument(s) or result, extractors, etc.) */
+  extern decSingle * decSingleFromBCD(decSingle *, int32_t, const uint8_t *, int32_t);
+  extern decSingle * decSingleFromPacked(decSingle *, int32_t, const uint8_t *);
+  extern decSingle * decSingleFromString(decSingle *, const char *, decContext *);
+  extern decSingle * decSingleFromWider(decSingle *, const decDouble *, decContext *);
+  extern int32_t     decSingleGetCoefficient(const decSingle *, uint8_t *);
+  extern int32_t     decSingleGetExponent(const decSingle *);
+  extern decSingle * decSingleSetCoefficient(decSingle *, const uint8_t *, int32_t);
+  extern decSingle * decSingleSetExponent(decSingle *, decContext *, int32_t);
+  extern void       decSingleShow(const decSingle *, const char *);
+  extern int32_t     decSingleToBCD(const decSingle *, int32_t *, uint8_t *);
+  extern char     * decSingleToEngString(const decSingle *, char *);
+  extern int32_t     decSingleToPacked(const decSingle *, int32_t *, uint8_t *);
+  extern char     * decSingleToString(const decSingle *, char *);
+  extern decDouble * decSingleToWider(const decSingle *, decDouble *);
+  extern decSingle * decSingleZero(decSingle *);
+
+  /* (No Arithmetic routines for decSingle) */
+
+  /* Non-computational */
+  extern uint32_t     decSingleRadix(const decSingle *);
+  extern const char * decSingleVersion(void);
+
+  /* decNumber conversions; these are implemented as macros so as not  */
+  /* to force a dependency on decimal32 and decNumber in decSingle.    */
+  #define decSingleToNumber(dq, dn) decimal32ToNumber((decimal32 *)(dq), dn)
+  #define decSingleFromNumber(dq, dn, set) (decSingle *)decimal32FromNumber((decimal32 *)(dq), dn, set)
+
+#endif
diff --git a/libdecnumber/decSingleSymbols.h b/libdecnumber/decSingleSymbols.h
new file mode 100644 (file)
index 0000000..6eee0e5
--- /dev/null
@@ -0,0 +1,24 @@
+#if !defined(DECSINGLESYMBOLS)
+#define DECSINGLESYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decSingleFromBCD __decSingleFromBCD
+#define decSingleFromPacked __decSingleFromPacked
+#define decSingleFromString __decSingleFromString
+#define decSingleFromWider __decSingleFromWider
+#define decSingleGetCoefficient __decSingleGetCoefficient
+#define decSingleGetExponent __decSingleGetExponent
+#define decSingleRadix __decSingleRadix
+#define decSingleSetCoefficient __decSingleSetCoefficient
+#define decSingleSetExponent __decSingleSetExponent
+#define decSingleShow __decSingleShow
+#define decSingleToBCD __decSingleToBCD
+#define decSingleToEngString __decSingleToEngString
+#define decSingleToPacked __decSingleToPacked
+#define decSingleToString __decSingleToString
+#define decSingleToWider __decSingleToWider
+#define decSingleVersion __decSingleVersion
+#define decSingleZero __decSingleZero
+#endif
+
+#endif
diff --git a/libdecnumber/decUtility.c b/libdecnumber/decUtility.c
deleted file mode 100644 (file)
index 2cbed94..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/* Utility functions for decimal floating point support via decNumber.
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Contributed by IBM Corporation.  Author Mike Cowlishaw.
-
-   This file is part of GCC.
-
-   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
-   Software Foundation; either version 2, or (at your option) any later
-   version.
-
-   In addition to the permissions in the GNU General Public License,
-   the Free Software Foundation gives you unlimited permission to link
-   the compiled version of this file into combinations with other
-   programs, and to distribute those combinations without any
-   restriction coming from the use of this file.  (The General Public
-   License restrictions do apply in other respects; for example, they
-   cover modification of the file, and distribution when not linked
-   into a combine executable.)
-
-   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or
-   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-   for more details.
-
-   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
-   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.  */
-
-#include "config.h"
-#include "decNumber.h"          /* base number library */
-#include "decNumberLocal.h"     /* decNumber local types, etc. */
-#include "decUtility.h"         /* utility routines */
-
-/* ================================================================== */
-/* Shared utility routines                                            */
-/* ================================================================== */
-
-/* define and include the conversion tables to use */
-#define DEC_BIN2DPD 1          /* used for all sizes */
-#if DECDPUN==3
-#define DEC_DPD2BIN 1
-#else
-#define DEC_DPD2BCD 1
-#endif
-#include "decDPD.h"            /* lookup tables */
-
-/* The maximum number of decNumberUnits we need for a working copy of */
-/* the units array is the ceiling of digits/DECDPUN, where digits is */
-/* the maximum number of digits in any of the formats for which this */
-/* is used.  We do not want to include decimal128.h, so, as a very */
-/* special case, that number is defined here. */
-#define DECMAX754   34
-#define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN)
-
-/* ------------------------------------------------------------------ */
-/* decDensePackCoeff -- densely pack coefficient into DPD form        */
-/*                                                                    */
-/*   dn is the source number (assumed valid, max DECMAX754 digits)    */
-/*   bytes is the target's byte array                                 */
-/*   len is length of target format's byte array                      */
-/*   shift is the number of 0 digits to add on the right (normally 0) */
-/*                                                                    */
-/* The coefficient must be known small enough to fit, and is filled   */
-/* in from the right (least significant first).  Note that the full   */
-/* coefficient is copied, including the leading 'odd' digit.  This    */
-/* digit is retrieved and packed into the combination field by the    */
-/* caller.                                                            */
-/*                                                                    */
-/* shift is used for 'fold-down' padding.                             */
-/*                                                                    */
-/* No error is possible.                                              */
-/* ------------------------------------------------------------------ */
-void
-decDensePackCoeff (const decNumber * dn, uByte * bytes, Int len, Int shift)
-{
-  Int cut;                     /* work */
-  Int n;                       /* output bunch counter */
-  Int digits = dn->digits;     /* digit countdown */
-  uInt dpd;                    /* densely packed decimal value */
-  uInt bin;                    /* binary value 0-999 */
-  uByte *bout;                 /* -> current output byte */
-  const Unit *inu = dn->lsu;   /* -> current input unit */
-  Unit uar[DECMAXUNITS];       /* working copy of units, iff shifted */
-#if DECDPUN!=3                 /* not fast path */
-  Unit in;                     /* current input unit */
-#endif
-
-  if (shift != 0)
-    {                          /* shift towards most significant required */
-      /* shift the units array to the left by pad digits and copy */
-      /* [this code is a special case of decShiftToMost, which could */
-      /* be used instead if exposed and the array were copied first] */
-      Unit *target, *first;    /* work */
-      const Unit *source;      /* work */
-      uInt next = 0;           /* work */
-
-      source = dn->lsu + D2U (digits) - 1;     /* where msu comes from */
-      first = uar + D2U (digits + shift) - 1;  /* where msu will end up */
-      target = uar + D2U (digits) - 1 + D2U (shift);   /* where upper part of first cut goes */
-
-      cut = (DECDPUN - shift % DECDPUN) % DECDPUN;
-      for (; source >= dn->lsu; source--, target--)
-       {
-         /* split the source Unit and accumulate remainder for next */
-         uInt rem = *source % powers[cut];
-         next += *source / powers[cut];
-         if (target <= first)
-           *target = (Unit) next;      /* write to target iff valid */
-         next = rem * powers[DECDPUN - cut];   /* save remainder for next Unit */
-       }
-      /* propagate remainder to one below and clear the rest */
-      for (; target >= uar; target--)
-       {
-         *target = (Unit) next;
-         next = 0;
-       }
-      digits += shift;         /* add count (shift) of zeros added */
-      inu = uar;               /* use units in working array */
-    }
-
-  /* densely pack the coefficient into the byte array, starting from
-     the right (optionally padded) */
-  bout = &bytes[len - 1];      /* rightmost result byte for phase */
-
-#if DECDPUN!=3                 /* not fast path */
-  in = *inu;                   /* prime */
-  cut = 0;                     /* at lowest digit */
-  bin = 0;                     /* [keep compiler quiet] */
-#endif
-
-  for (n = 0; digits > 0; n++)
-    {                          /* each output bunch */
-#if DECDPUN==3                 /* fast path, 3-at-a-time */
-      bin = *inu;              /* 3 ready for convert */
-      digits -= 3;             /* [may go negative] */
-      inu++;                   /* may need another */
-
-#else /* must collect digit-by-digit */
-      Unit dig;                        /* current digit */
-      Int j;                   /* digit-in-bunch count */
-      for (j = 0; j < 3; j++)
-       {
-#if DECDPUN<=4
-         Unit temp = (Unit) ((uInt) (in * 6554) >> 16);
-         dig = (Unit) (in - X10 (temp));
-         in = temp;
-#else
-         dig = in % 10;
-         in = in / 10;
-#endif
-
-         if (j == 0)
-           bin = dig;
-         else if (j == 1)
-           bin += X10 (dig);
-         else                  /* j==2 */
-           bin += X100 (dig);
-
-         digits--;
-         if (digits == 0)
-           break;              /* [also protects *inu below] */
-         cut++;
-         if (cut == DECDPUN)
-           {
-             inu++;
-             in = *inu;
-             cut = 0;
-           }
-       }
-#endif
-      /* here we have 3 digits in bin, or have used all input digits */
-
-      dpd = BIN2DPD[bin];
-
-      /* write bunch (bcd) to byte array */
-      switch (n & 0x03)
-       {                       /* phase 0-3 */
-       case 0:
-         *bout = (uByte) dpd;  /* [top 2 bits truncated] */
-         bout--;
-         *bout = (uByte) (dpd >> 8);
-         break;
-       case 1:
-         *bout |= (uByte) (dpd << 2);
-         bout--;
-         *bout = (uByte) (dpd >> 6);
-         break;
-       case 2:
-         *bout |= (uByte) (dpd << 4);
-         bout--;
-         *bout = (uByte) (dpd >> 4);
-         break;
-       case 3:
-         *bout |= (uByte) (dpd << 6);
-         bout--;
-         *bout = (uByte) (dpd >> 2);
-         bout--;
-         break;
-       }                       /* switch */
-    }                          /* n bunches */
-  return;
-}
-
-/* ------------------------------------------------------------------ */
-/* decDenseUnpackCoeff -- unpack a format's coefficient               */
-/*                                                                    */
-/*   byte is the source's byte array                                  */
-/*   len is length of the source's byte array                         */
-/*   dn is the target number, with 7, 16, or 34-digit space.          */
-/*   bunches is the count of DPD groups in the decNumber (2, 5, or 11)*/
-/*   odd is 1 if there is a non-zero leading 10-bit group containing  */
-/*     a single digit, 0 otherwise                                    */
-/*                                                                    */
-/* (This routine works on a copy of the number, if necessary, where   */
-/* an extra 10-bit group is prefixed to the coefficient continuation  */
-/* to hold the most significant digit if the latter is non-0.)        */
-/*                                                                    */
-/* dn->digits is set, but not the sign or exponent.                   */
-/* No error is possible [the redundant 888 codes are allowed].        */
-/* ------------------------------------------------------------------ */
-void
-decDenseUnpackCoeff (const uByte * bytes, Int len, decNumber * dn,
-                    Int bunches, Int odd)
-{
-  uInt dpd = 0;                        /* collector for 10 bits */
-  Int n;                       /* counter */
-  const uByte *bin;            /* -> current input byte */
-  Unit *uout = dn->lsu;                /* -> current output unit */
-  Unit out = 0;                        /* accumulator */
-  Int cut = 0;                 /* power of ten in current unit */
-  Unit *last = uout;           /* will be unit containing msd */
-#if DECDPUN!=3
-  uInt bcd;                    /* BCD result */
-  uInt nibble;                 /* work */
-#endif
-
-  /* Expand the densely-packed integer, right to left */
-  bin = &bytes[len - 1];       /* next input byte to use */
-  for (n = 0; n < bunches + odd; n++)
-    {                          /* N bunches of 10 bits */
-      /* assemble the 10 bits */
-      switch (n & 0x03)
-       {                       /* phase 0-3 */
-       case 0:
-         dpd = *bin;
-         bin--;
-         dpd |= (*bin & 0x03) << 8;
-         break;
-       case 1:
-         dpd = (unsigned) *bin >> 2;
-         bin--;
-         dpd |= (*bin & 0x0F) << 6;
-         break;
-       case 2:
-         dpd = (unsigned) *bin >> 4;
-         bin--;
-         dpd |= (*bin & 0x3F) << 4;
-         break;
-       case 3:
-         dpd = (unsigned) *bin >> 6;
-         bin--;
-         dpd |= (*bin) << 2;
-         bin--;
-         break;
-       }                       /*switch */
-
-#if DECDPUN==3
-      if (dpd == 0)
-       *uout = 0;
-      else
-       {
-         *uout = DPD2BIN[dpd]; /* convert 10 bits to binary 0-999 */
-         last = uout;          /* record most significant unit */
-       }
-      uout++;
-
-#else /* DECDPUN!=3 */
-      if (dpd == 0)
-       {                       /* fastpath [e.g., leading zeros] */
-         cut += 3;
-         for (; cut >= DECDPUN;)
-           {
-             cut -= DECDPUN;
-             *uout = out;
-             uout++;
-             out = 0;
-           }
-         continue;
-       }
-      bcd = DPD2BCD[dpd];      /* convert 10 bits to 12 bits BCD */
-      /* now split the 3 BCD nibbles into bytes, and accumulate into units */
-      /* If this is the last bunch and it is an odd one, we only have one */
-      /* nibble to handle [extras could overflow a Unit] */
-      nibble = bcd & 0x000f;
-      if (nibble)
-       {
-         last = uout;
-         out = (Unit) (out + nibble * powers[cut]);
-       }
-      cut++;
-      if (cut == DECDPUN)
-       {
-         *uout = out;
-         uout++;
-         cut = 0;
-         out = 0;
-       }
-      if (n < bunches)
-       {
-         nibble = bcd & 0x00f0;
-         if (nibble)
-           {
-             nibble >>= 4;
-             last = uout;
-             out = (Unit) (out + nibble * powers[cut]);
-           }
-         cut++;
-         if (cut == DECDPUN)
-           {
-             *uout = out;
-             uout++;
-             cut = 0;
-             out = 0;
-           }
-         nibble = bcd & 0x0f00;
-         if (nibble)
-           {
-             nibble >>= 8;
-             last = uout;
-             out = (Unit) (out + nibble * powers[cut]);
-           }
-         cut++;
-         if (cut == DECDPUN)
-           {
-             *uout = out;
-             uout++;
-             cut = 0;
-             out = 0;
-           }
-       }
-#endif
-    }                          /* n */
-  if (cut != 0)
-    *uout = out;               /* write out final unit */
-
-  /* here, last points to the most significant unit with digits */
-  /* we need to inspect it to get final digits count */
-  dn->digits = (last - dn->lsu) * DECDPUN;     /* floor of digits */
-  for (cut = 0; cut < DECDPUN; cut++)
-    {
-      if (*last < powers[cut])
-       break;
-      dn->digits++;
-    }
-  if (dn->digits == 0)
-    dn->digits++;              /* zero has one digit */
-  return;
-}
diff --git a/libdecnumber/decUtility.h b/libdecnumber/decUtility.h
deleted file mode 100644 (file)
index 4cf65e5..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Utility functions for decimal floating point support via decNumber.
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Contributed by IBM Corporation.  Author Mike Cowlishaw.
-
-   This file is part of GCC.
-
-   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
-   Software Foundation; either version 2, or (at your option) any later
-   version.
-
-   In addition to the permissions in the GNU General Public License,
-   the Free Software Foundation gives you unlimited permission to link
-   the compiled version of this file into combinations with other
-   programs, and to distribute those combinations without any
-   restriction coming from the use of this file.  (The General Public
-   License restrictions do apply in other respects; for example, they
-   cover modification of the file, and distribution when not linked
-   into a combine executable.)
-
-   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or
-   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-   for more details.
-
-   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
-   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.  */
-
-#ifdef IN_LIBGCC2
-#define decDensePackCoeff __decDensePackCoeff
-#define decDenseUnpackCoeff __decDenseUnpackCoeff
-#endif
-
-extern void decDensePackCoeff (const decNumber *, uByte *, Int, Int);
-extern void decDenseUnpackCoeff (const uByte *, Int, decNumber *, Int, Int);
index 92b4f618eff3cb487a9f612e4235e9b39b4bcd56..6aa98b5a21de9a6af03a1f23dc017861848019b9 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal 128-bit format module from the decNumber C Library.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Decimal 128-bit format module for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
+/* ------------------------------------------------------------------ */
+/* Decimal 128-bit format module                                     */
 /* ------------------------------------------------------------------ */
 /* This module comprises the routines for decimal128 format numbers.  */
-/* Conversions are supplied to and from decNumber and String.         */
-/*                                                                    */
-/* No arithmetic routines are included; decNumber provides these.     */
-/*                                                                    */
-/* Error handling is the same as decNumber (qv.).                     */
+/* Conversions are supplied to and from decNumber and String.        */
+/*                                                                   */
+/* This is used when decNumber provides operations, either for all    */
+/* operations or as a proxy between decNumber and decSingle.         */
+/*                                                                   */
+/* Error handling is the same as decNumber (qv.).                    */
 /* ------------------------------------------------------------------ */
-#include <string.h>            /* [for memset/memcpy] */
-#include <stdio.h>             /* [for printf] */
+#include <string.h>          /* [for memset/memcpy] */
+#include <stdio.h>           /* [for printf] */
+
+#include "config.h"          /* GCC definitions */
+#define         DECNUMDIGITS 34      /* make decNumbers with space for 34 */
+#include "decNumber.h"       /* base number library */
+#include "decNumberLocal.h"   /* decNumber local types, etc. */
+#include "decimal128.h"              /* our primary include */
 
-#define  DECNUMDIGITS 34       /* we need decNumbers with space for 34 */
-#include "config.h"
-#include "decNumber.h"         /* base number library */
-#include "decNumberLocal.h"    /* decNumber local types, etc. */
-#include "decimal128.h"                /* our primary include */
-#include "decUtility.h"                /* utility routines */
+/* Utility routines and tables [in decimal64.c] */
+/* DPD2BIN and the reverse are renamed to prevent link-time conflict */
+/* if decQuad is also built in the same executable */
+#define DPD2BIN DPD2BINx
+#define BIN2DPD BIN2DPDx
+extern const uInt   COMBEXP[32], COMBMSD[32];
+extern const uShort DPD2BIN[1024];
+extern const uShort BIN2DPD[1000];     /* [not used] */
+extern const uByte  BIN2CHAR[4001];
+
+extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
+extern void decDigitsToDPD(const decNumber *, uInt *, Int);
 
 #if DECTRACE || DECCHECK
-void decimal128Show (const decimal128 *);      /* for debug */
-void decNumberShow (const decNumber *);        /* .. */
+void decimal128Show(const decimal128 *);         /* for debug */
+extern void decNumberShow(const decNumber *);    /* .. */
 #endif
 
 /* Useful macro */
@@ -56,292 +71,500 @@ void decNumberShow (const decNumber *);   /* .. */
 #define DEC_clear(d) memset(d, 0, sizeof(*d))
 
 /* ------------------------------------------------------------------ */
-/* decimal128FromNumber -- convert decNumber to decimal128            */
-/*                                                                    */
-/*   ds is the target decimal128                                      */
-/*   dn is the source number (assumed valid)                          */
-/*   set is the context, used only for reporting errors               */
-/*                                                                    */
+/* decimal128FromNumber -- convert decNumber to decimal128           */
+/*                                                                   */
+/*   ds is the target decimal128                                     */
+/*   dn is the source number (assumed valid)                         */
+/*   set is the context, used only for reporting errors                      */
+/*                                                                   */
 /* The set argument is used only for status reporting and for the     */
 /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
-/* digits or an overflow is detected).  If the exponent is out of the */
-/* valid range then Overflow or Underflow will be raised.             */
-/* After Underflow a subnormal result is possible.                    */
-/*                                                                    */
+/* digits or an overflow is detected). If the exponent is out of the */
+/* valid range then Overflow or Underflow will be raised.            */
+/* After Underflow a subnormal result is possible.                   */
+/*                                                                   */
 /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
 /* by reducing its exponent and multiplying the coefficient by a      */
 /* power of ten, or if the exponent on a zero had to be clamped.      */
 /* ------------------------------------------------------------------ */
-decimal128 *
-decimal128FromNumber (decimal128 * d128, const decNumber * dn, decContext * set)
-{
-  uInt status = 0;             /* status accumulator */
-  Int pad = 0;                 /* coefficient pad digits */
-  decNumber dw;                        /* work */
-  decContext dc;               /* .. */
-  uByte isneg = dn->bits & DECNEG;     /* non-0 if original sign set */
-  uInt comb, exp;              /* work */
-
-  /* If the number is finite, and has too many digits, or the exponent */
-  /* could be out of range then we reduce the number under the */
-  /* appropriate constraints */
-  if (!(dn->bits & DECSPECIAL))
-    {                          /* not a special value */
-      Int ae = dn->exponent + dn->digits - 1;  /* adjusted exponent */
-      if (dn->digits > DECIMAL128_Pmax /* too many digits */
-         || ae > DECIMAL128_Emax       /* likely overflow */
-         || ae < DECIMAL128_Emin)
-       {                       /* likely underflow */
-         decContextDefault (&dc, DEC_INIT_DECIMAL128); /* [no traps] */
-         dc.round = set->round;        /* use supplied rounding */
-         decNumberPlus (&dw, dn, &dc); /* (round and check) */
-         /* [this changes -0 to 0, but it will be restored below] */
-         status |= dc.status;  /* save status */
-         dn = &dw;             /* use the work number */
-       }
-      /* [this could have pushed number to Infinity or zero, so this */
-      /* rounding must be done before we generate the decimal128] */
-    }
+decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
+                                 decContext *set) {
+  uInt status=0;                  /* status accumulator */
+  Int ae;                         /* adjusted exponent */
+  decNumber  dw;                  /* work */
+  decContext dc;                  /* .. */
+  uInt *pu;                       /* .. */
+  uInt comb, exp;                 /* .. */
+  uInt targar[4]={0,0,0,0};       /* target 128-bit */
+  #define targhi targar[3]        /* name the word with the sign */
+  #define targmh targar[2]        /* name the words */
+  #define targml targar[1]        /* .. */
+  #define targlo targar[0]        /* .. */
+
+  /* If the number has too many digits, or the exponent could be */
+  /* out of range then reduce the number under the appropriate */
+  /* constraints.  This could push the number to Infinity or zero, */
+  /* so this check and rounding must be done before generating the */
+  /* decimal128] */
+  ae=dn->exponent+dn->digits-1;                     /* [0 if special] */
+  if (dn->digits>DECIMAL128_Pmax            /* too many digits */
+   || ae>DECIMAL128_Emax                    /* likely overflow */
+   || ae<DECIMAL128_Emin) {                 /* likely underflow */
+    decContextDefault(&dc, DEC_INIT_DECIMAL128); /* [no traps] */
+    dc.round=set->round;                    /* use supplied rounding */
+    decNumberPlus(&dw, dn, &dc);            /* (round and check) */
+    /* [this changes -0 to 0, so enforce the sign...] */
+    dw.bits|=dn->bits&DECNEG;
+    status=dc.status;                       /* save status */
+    dn=&dw;                                 /* use the work number */
+    } /* maybe out of range */
 
-  DEC_clear (d128);            /* clean the target */
-  if (dn->bits & DECSPECIAL)
-    {                          /* a special value */
-      uByte top;               /* work */
-      if (dn->bits & DECINF)
-       top = DECIMAL_Inf;
-      else
-       {                       /* sNaN or qNaN */
-         if ((*dn->lsu != 0 || dn->digits > 1) /* non-zero coefficient */
-             && (dn->digits < DECIMAL128_Pmax))
-           {                   /* coefficient fits */
-             decDensePackCoeff (dn, d128->bytes, sizeof (d128->bytes), 0);
-           }
-         if (dn->bits & DECNAN)
-           top = DECIMAL_NaN;
-         else
-           top = DECIMAL_sNaN;
+  if (dn->bits&DECSPECIAL) {                     /* a special value */
+    if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
+     else {                                      /* sNaN or qNaN */
+      if ((*dn->lsu!=0 || dn->digits>1)                  /* non-zero coefficient */
+       && (dn->digits<DECIMAL128_Pmax)) {        /* coefficient fits */
+       decDigitsToDPD(dn, targar, 0);
        }
-      d128->bytes[0] = top;
-    }
-  else if (decNumberIsZero (dn))
-    {                          /* a zero */
+      if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
+       else targhi|=DECIMAL_sNaN<<24;
+      } /* a NaN */
+    } /* special */
+
+   else { /* is finite */
+    if (decNumberIsZero(dn)) {              /* is a zero */
       /* set and clamp exponent */
-      if (dn->exponent < -DECIMAL128_Bias)
-       {
-         exp = 0;
-         status |= DEC_Clamped;
+      if (dn->exponent<-DECIMAL128_Bias) {
+       exp=0;                               /* low clamp */
+       status|=DEC_Clamped;
        }
-      else
-       {
-         exp = dn->exponent + DECIMAL128_Bias; /* bias exponent */
-         if (exp > DECIMAL128_Ehigh)
-           {                   /* top clamp */
-             exp = DECIMAL128_Ehigh;
-             status |= DEC_Clamped;
-           }
-       }
-      comb = (exp >> 9) & 0x18;        /* combination field */
-      d128->bytes[0] = (uByte) (comb << 2);
-      exp &= 0xfff;            /* remaining exponent bits */
-      decimal128SetExpCon (d128, exp);
-    }
-  else
-    {                          /* non-zero finite number */
-      uInt msd;                        /* work */
-
-      /* we have a dn that fits, but it may need to be padded */
-      exp = (uInt) (dn->exponent + DECIMAL128_Bias);   /* bias exponent */
-
-      if (exp > DECIMAL128_Ehigh)
-       {                       /* fold-down case */
-         pad = exp - DECIMAL128_Ehigh;
-         exp = DECIMAL128_Ehigh;       /* [to maximum] */
-         status |= DEC_Clamped;
+       else {
+       exp=dn->exponent+DECIMAL128_Bias;    /* bias exponent */
+       if (exp>DECIMAL128_Ehigh) {          /* top clamp */
+         exp=DECIMAL128_Ehigh;
+         status|=DEC_Clamped;
+         }
        }
+      comb=(exp>>9) & 0x18;            /* msd=0, exp top 2 bits .. */
+      }
+     else {                            /* non-zero finite number */
+      uInt msd;                                /* work */
+      Int pad=0;                       /* coefficient pad digits */
 
-      decDensePackCoeff (dn, d128->bytes, sizeof (d128->bytes), pad);
+      /* the dn is known to fit, but it may need to be padded */
+      exp=(uInt)(dn->exponent+DECIMAL128_Bias);           /* bias exponent */
+      if (exp>DECIMAL128_Ehigh) {                 /* fold-down case */
+       pad=exp-DECIMAL128_Ehigh;
+       exp=DECIMAL128_Ehigh;                      /* [to maximum] */
+       status|=DEC_Clamped;
+       }
 
+      /* [fastpath for common case is not a win, here] */
+      decDigitsToDPD(dn, targar, pad);
       /* save and clear the top digit */
-      msd = ((unsigned) d128->bytes[1] << 2) & 0x0c;   /* top 2 bits */
-      msd |= ((unsigned) d128->bytes[2] >> 6); /* low 2 bits */
-      d128->bytes[1] &= 0xfc;
-      d128->bytes[2] &= 0x3f;
+      msd=targhi>>14;
+      targhi&=0x00003fff;
 
       /* create the combination field */
-      if (msd >= 8)
-       comb = 0x18 | (msd & 0x01) | ((exp >> 11) & 0x06);
-      else
-       comb = (msd & 0x07) | ((exp >> 9) & 0x18);
-      d128->bytes[0] = (uByte) (comb << 2);
-      exp &= 0xfff;            /* remaining exponent bits */
-      decimal128SetExpCon (d128, exp);
-    }
+      if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
+            else comb=((exp>>9) & 0x18) | msd;
+      }
+    targhi|=comb<<26;             /* add combination field .. */
+    targhi|=(exp&0xfff)<<14;      /* .. and exponent continuation */
+    } /* finite */
 
-  if (isneg)
-    decimal128SetSign (d128, 1);
-  if (status != 0)
-    decContextSetStatus (set, status); /* pass on status */
+  if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
 
+  /* now write to storage; this is endian */
+  pu=(uInt *)d128->bytes;         /* overlay */
+  if (DECLITEND) {
+    pu[0]=targlo;                 /* directly store the low int */
+    pu[1]=targml;                 /* then the mid-low */
+    pu[2]=targmh;                 /* then the mid-high */
+    pu[3]=targhi;                 /* then the high int */
+    }
+   else {
+    pu[0]=targhi;                 /* directly store the high int */
+    pu[1]=targmh;                 /* then the mid-high */
+    pu[2]=targml;                 /* then the mid-low */
+    pu[3]=targlo;                 /* then the low int */
+    }
+
+  if (status!=0) decContextSetStatus(set, status); /* pass on status */
   /* decimal128Show(d128); */
   return d128;
-}
+  } /* decimal128FromNumber */
 
 /* ------------------------------------------------------------------ */
-/* decimal128ToNumber -- convert decimal128 to decNumber              */
-/*   d128 is the source decimal128                                    */
-/*   dn is the target number, with appropriate space                  */
-/* No error is possible.                                              */
+/* decimal128ToNumber -- convert decimal128 to decNumber             */
+/*   d128 is the source decimal128                                   */
+/*   dn is the target number, with appropriate space                 */
+/* No error is possible.                                             */
 /* ------------------------------------------------------------------ */
-decNumber *
-decimal128ToNumber (const decimal128 * d128, decNumber * dn)
-{
-  uInt msd;                    /* coefficient MSD */
-  decimal128 wk;               /* working copy, if needed */
-  uInt top = d128->bytes[0] & 0x7f;    /* top byte, less sign bit */
-  decNumberZero (dn);          /* clean target */
-  /* set the sign if negative */
-  if (decimal128Sign (d128))
-    dn->bits = DECNEG;
-
-  if (top >= 0x78)
-    {                          /* is a special */
-      if ((top & 0x7c) == (DECIMAL_Inf & 0x7c))
-       dn->bits |= DECINF;
-      else if ((top & 0x7e) == (DECIMAL_NaN & 0x7e))
-       dn->bits |= DECNAN;
-      else
-       dn->bits |= DECSNAN;
-      msd = 0;                 /* no top digit */
+decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
+  uInt msd;                       /* coefficient MSD */
+  uInt exp;                       /* exponent top two bits */
+  uInt comb;                      /* combination field */
+  const uInt *pu;                 /* work */
+  Int  need;                      /* .. */
+  uInt sourar[4];                 /* source 128-bit */
+  #define sourhi sourar[3]        /* name the word with the sign */
+  #define sourmh sourar[2]        /* and the mid-high word */
+  #define sourml sourar[1]        /* and the mod-low word */
+  #define sourlo sourar[0]        /* and the lowest word */
+
+  /* load source from storage; this is endian */
+  pu=(const uInt *)d128->bytes;           /* overlay */
+  if (DECLITEND) {
+    sourlo=pu[0];                 /* directly load the low int */
+    sourml=pu[1];                 /* then the mid-low */
+    sourmh=pu[2];                 /* then the mid-high */
+    sourhi=pu[3];                 /* then the high int */
     }
-  else
-    {                          /* have a finite number */
-      uInt comb = top >> 2;    /* combination field */
-      uInt exp;                        /* exponent */
-
-      if (comb >= 0x18)
-       {
-         msd = 8 + (comb & 0x01);
-         exp = (comb & 0x06) << 11;    /* MSBs */
-       }
-      else
-       {
-         msd = comb & 0x07;
-         exp = (comb & 0x18) << 9;
-       }
-      dn->exponent = exp + decimal128ExpCon (d128) - DECIMAL128_Bias;  /* remove bias */
+   else {
+    sourhi=pu[0];                 /* directly load the high int */
+    sourmh=pu[1];                 /* then the mid-high */
+    sourml=pu[2];                 /* then the mid-low */
+    sourlo=pu[3];                 /* then the low int */
     }
 
-  /* get the coefficient, unless infinite */
-  if (!(dn->bits & DECINF))
-    {
-      Int bunches = DECIMAL128_Pmax / 3;       /* coefficient full bunches to convert */
-      Int odd = 0;             /* assume MSD is 0 (no odd bunch) */
-      if (msd != 0)
-       {                       /* coefficient has leading non-0 digit */
-         /* make a copy of the decimal128, with an extra bunch which has */
-         /* the top digit ready for conversion */
-         wk = *d128;           /* take a copy */
-         wk.bytes[0] = 0;      /* clear all but coecon */
-         wk.bytes[1] = 0;      /* .. */
-         wk.bytes[2] &= 0x3f;  /* .. */
-         wk.bytes[1] |= (msd >> 2);    /* and prefix MSD */
-         wk.bytes[2] |= (msd << 6);    /* .. */
-         odd++;                /* indicate the extra */
-         d128 = &wk;           /* use the work copy */
-       }
-      decDenseUnpackCoeff (d128->bytes, sizeof (d128->bytes), dn, bunches,
-                          odd);
+  comb=(sourhi>>26)&0x1f;         /* combination field */
+
+  decNumberZero(dn);              /* clean number */
+  if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */
+
+  msd=COMBMSD[comb];              /* decode the combination field */
+  exp=COMBEXP[comb];              /* .. */
+
+  if (exp==3) {                           /* is a special */
+    if (msd==0) {
+      dn->bits|=DECINF;
+      return dn;                  /* no coefficient needed */
+      }
+    else if (sourhi&0x02000000) dn->bits|=DECSNAN;
+    else dn->bits|=DECNAN;
+    msd=0;                        /* no top digit */
+    }
+   else {                         /* is a finite number */
+    dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
     }
 
+  /* get the coefficient */
+  sourhi&=0x00003fff;             /* clean coefficient continuation */
+  if (msd) {                      /* non-zero msd */
+    sourhi|=msd<<14;              /* prefix to coefficient */
+    need=12;                      /* process 12 declets */
+    }
+   else { /* msd=0 */
+    if (sourhi) need=11;          /* declets to process */
+     else if (sourmh) need=10;
+     else if (sourml) need=7;
+     else if (sourlo) need=4;
+     else return dn;              /* easy: coefficient is 0 */
+    } /*msd=0 */
+
+  decDigitsFromDPD(dn, sourar, need);  /* process declets */
   /* decNumberShow(dn); */
   return dn;
-}
+  } /* decimal128ToNumber */
 
 /* ------------------------------------------------------------------ */
-/* to-scientific-string -- conversion to numeric string               */
-/* to-engineering-string -- conversion to numeric string              */
-/*                                                                    */
-/*   decimal128ToString(d128, string);                                */
-/*   decimal128ToEngString(d128, string);                             */
-/*                                                                    */
-/*  d128 is the decimal128 format number to convert                   */
-/*  string is the string where the result will be laid out            */
-/*                                                                    */
-/*  string must be at least 24 characters                             */
-/*                                                                    */
-/*  No error is possible, and no status can be set.                   */
+/* to-scientific-string -- conversion to numeric string                      */
+/* to-engineering-string -- conversion to numeric string             */
+/*                                                                   */
+/*   decimal128ToString(d128, string);                               */
+/*   decimal128ToEngString(d128, string);                            */
+/*                                                                   */
+/*  d128 is the decimal128 format number to convert                  */
+/*  string is the string where the result will be laid out           */
+/*                                                                   */
+/*  string must be at least 24 characters                            */
+/*                                                                   */
+/*  No error is possible, and no status can be set.                  */
 /* ------------------------------------------------------------------ */
-char *
-decimal128ToString (const decimal128 * d128, char *string)
-{
-  decNumber dn;                        /* work */
-  decimal128ToNumber (d128, &dn);
-  decNumberToString (&dn, string);
+char * decimal128ToEngString(const decimal128 *d128, char *string){
+  decNumber dn;                                /* work */
+  decimal128ToNumber(d128, &dn);
+  decNumberToEngString(&dn, string);
   return string;
-}
-
-char *
-decimal128ToEngString (const decimal128 * d128, char *string)
-{
-  decNumber dn;                        /* work */
-  decimal128ToNumber (d128, &dn);
-  decNumberToEngString (&dn, string);
+  } /* decimal128ToEngString */
+
+char * decimal128ToString(const decimal128 *d128, char *string){
+  uInt msd;                       /* coefficient MSD */
+  Int  exp;                       /* exponent top two bits or full */
+  uInt comb;                      /* combination field */
+  char *cstart;                           /* coefficient start */
+  char *c;                        /* output pointer in string */
+  const uInt *pu;                 /* work */
+  char *s, *t;                    /* .. (source, target) */
+  Int  dpd;                       /* .. */
+  Int  pre, e;                    /* .. */
+  const uByte *u;                 /* .. */
+
+  uInt sourar[4];                 /* source 128-bit */
+  #define sourhi sourar[3]        /* name the word with the sign */
+  #define sourmh sourar[2]        /* and the mid-high word */
+  #define sourml sourar[1]        /* and the mod-low word */
+  #define sourlo sourar[0]        /* and the lowest word */
+
+  /* load source from storage; this is endian */
+  pu=(const uInt *)d128->bytes;           /* overlay */
+  if (DECLITEND) {
+    sourlo=pu[0];                 /* directly load the low int */
+    sourml=pu[1];                 /* then the mid-low */
+    sourmh=pu[2];                 /* then the mid-high */
+    sourhi=pu[3];                 /* then the high int */
+    }
+   else {
+    sourhi=pu[0];                 /* directly load the high int */
+    sourmh=pu[1];                 /* then the mid-high */
+    sourml=pu[2];                 /* then the mid-low */
+    sourlo=pu[3];                 /* then the low int */
+    }
+
+  c=string;                       /* where result will go */
+  if (((Int)sourhi)<0) *c++='-';   /* handle sign */
+
+  comb=(sourhi>>26)&0x1f;         /* combination field */
+  msd=COMBMSD[comb];              /* decode the combination field */
+  exp=COMBEXP[comb];              /* .. */
+
+  if (exp==3) {
+    if (msd==0) {                 /* infinity */
+      strcpy(c,          "Inf");
+      strcpy(c+3, "inity");
+      return string;              /* easy */
+      }
+    if (sourhi&0x02000000) *c++='s'; /* sNaN */
+    strcpy(c, "NaN");             /* complete word */
+    c+=3;                         /* step past */
+    if (sourlo==0 && sourml==0 && sourmh==0
+     && (sourhi&0x0003ffff)==0) return string; /* zero payload */
+    /* otherwise drop through to add integer; set correct exp */
+    exp=0; msd=0;                 /* setup for following code */
+    }
+   else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
+
+  /* convert 34 digits of significand to characters */
+  cstart=c;                       /* save start of coefficient */
+  if (msd) *c++='0'+(char)msd;    /* non-zero most significant digit */
+
+  /* Now decode the declets.  After extracting each one, it is */
+  /* decoded to binary and then to a 4-char sequence by table lookup; */
+  /* the 4-chars are a 1-char length (significant digits, except 000 */
+  /* has length 0).  This allows us to left-align the first declet */
+  /* with non-zero content, then remaining ones are full 3-char */
+  /* length.  We use fixed-length memcpys because variable-length */
+  /* causes a subroutine call in GCC.  (These are length 4 for speed */
+  /* and are safe because the array has an extra terminator byte.) */
+  #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                          \
+                  if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
+                   else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
+  dpd=(sourhi>>4)&0x3ff;                    /* declet 1 */
+  dpd2char;
+  dpd=((sourhi&0xf)<<6) | (sourmh>>26);             /* declet 2 */
+  dpd2char;
+  dpd=(sourmh>>16)&0x3ff;                   /* declet 3 */
+  dpd2char;
+  dpd=(sourmh>>6)&0x3ff;                    /* declet 4 */
+  dpd2char;
+  dpd=((sourmh&0x3f)<<4) | (sourml>>28);     /* declet 5 */
+  dpd2char;
+  dpd=(sourml>>18)&0x3ff;                   /* declet 6 */
+  dpd2char;
+  dpd=(sourml>>8)&0x3ff;                    /* declet 7 */
+  dpd2char;
+  dpd=((sourml&0xff)<<2) | (sourlo>>30);     /* declet 8 */
+  dpd2char;
+  dpd=(sourlo>>20)&0x3ff;                   /* declet 9 */
+  dpd2char;
+  dpd=(sourlo>>10)&0x3ff;                   /* declet 10 */
+  dpd2char;
+  dpd=(sourlo)&0x3ff;                       /* declet 11 */
+  dpd2char;
+
+  if (c==cstart) *c++='0';        /* all zeros -- make 0 */
+
+  if (exp==0) {                           /* integer or NaN case -- easy */
+    *c='\0';                      /* terminate */
+    return string;
+    }
+
+  /* non-0 exponent */
+  e=0;                            /* assume no E */
+  pre=c-cstart+exp;
+  /* [here, pre-exp is the digits count (==1 for zero)] */
+  if (exp>0 || pre<-5) {          /* need exponential form */
+    e=pre-1;                      /* calculate E value */
+    pre=1;                        /* assume one digit before '.' */
+    } /* exponential form */
+
+  /* modify the coefficient, adding 0s, '.', and E+nn as needed */
+  s=c-1;                          /* source (LSD) */
+  if (pre>0) {                    /* ddd.ddd (plain), perhaps with E */
+    char *dotat=cstart+pre;
+    if (dotat<c) {                /* if embedded dot needed... */
+      t=c;                             /* target */
+      for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
+      *t='.';                          /* insert the dot */
+      c++;                             /* length increased by one */
+      }
+
+    /* finally add the E-part, if needed; it will never be 0, and has */
+    /* a maximum length of 4 digits */
+    if (e!=0) {
+      *c++='E';                           /* starts with E */
+      *c++='+';                           /* assume positive */
+      if (e<0) {
+       *(c-1)='-';                /* oops, need '-' */
+       e=-e;                      /* uInt, please */
+       }
+      if (e<1000) {               /* 3 (or fewer) digits case */
+       u=&BIN2CHAR[e*4];          /* -> length byte */
+       memcpy(c, u+4-*u, 4);      /* copy fixed 4 characters [is safe] */
+       c+=*u;                     /* bump pointer appropriately */
+       }
+       else {                     /* 4-digits */
+       Int thou=((e>>3)*1049)>>17; /* e/1000 */
+       Int rem=e-(1000*thou);      /* e%1000 */
+       *c++='0'+(char)thou;
+       u=&BIN2CHAR[rem*4];        /* -> length byte */
+       memcpy(c, u+1, 4);         /* copy fixed 3+1 characters [is safe] */
+       c+=3;                      /* bump pointer, always 3 digits */
+       }
+      }
+    *c='\0';                      /* add terminator */
+    /*printf("res %s\n", string); */
+    return string;
+    } /* pre>0 */
+
+  /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
+  t=c+1-pre;
+  *(t+1)='\0';                         /* can add terminator now */
+  for (; s>=cstart; s--, t--) *t=*s;   /* shift whole coefficient right */
+  c=cstart;
+  *c++='0';                            /* always starts with 0. */
+  *c++='.';
+  for (; pre<0; pre++) *c++='0';       /* add any 0's after '.' */
+  /*printf("res %s\n", string); */
   return string;
-}
+  } /* decimal128ToString */
 
 /* ------------------------------------------------------------------ */
-/* to-number -- conversion from numeric string                        */
-/*                                                                    */
-/*   decimal128FromString(result, string, set);                       */
-/*                                                                    */
+/* to-number -- conversion from numeric string                       */
+/*                                                                   */
+/*   decimal128FromString(result, string, set);                              */
+/*                                                                   */
 /*  result  is the decimal128 format number which gets the result of  */
-/*          the conversion                                            */
+/*         the conversion                                            */
 /*  *string is the character string which should contain a valid      */
-/*          number (which may be a special value)                     */
-/*  set     is the context                                            */
-/*                                                                    */
+/*         number (which may be a special value)                     */
+/*  set            is the context                                            */
+/*                                                                   */
 /* The context is supplied to this routine is used for error handling */
 /* (setting of status and traps) and for the rounding mode, only.     */
 /* If an error occurs, the result will be a valid decimal128 NaN.     */
 /* ------------------------------------------------------------------ */
-decimal128 *
-decimal128FromString (decimal128 * result, const char *string, decContext * set)
-{
-  decContext dc;               /* work */
-  decNumber dn;                        /* .. */
-
-  decContextDefault (&dc, DEC_INIT_DECIMAL128);        /* no traps, please */
-  dc.round = set->round;       /* use supplied rounding */
-
-  decNumberFromString (&dn, string, &dc);      /* will round if needed */
-  decimal128FromNumber (result, &dn, &dc);
-  if (dc.status != 0)
-    {                          /* something happened */
-      decContextSetStatus (set, dc.status);    /* .. pass it on */
+decimal128 * decimal128FromString(decimal128 *result, const char *string,
+                                 decContext *set) {
+  decContext dc;                            /* work */
+  decNumber dn;                                     /* .. */
+
+  decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */
+  dc.round=set->round;                        /* use supplied rounding */
+
+  decNumberFromString(&dn, string, &dc);     /* will round if needed */
+  decimal128FromNumber(result, &dn, &dc);
+  if (dc.status!=0) {                       /* something happened */
+    decContextSetStatus(set, dc.status);     /* .. pass it on */
     }
   return result;
-}
+  } /* decimal128FromString */
+
+/* ------------------------------------------------------------------ */
+/* decimal128IsCanonical -- test whether encoding is canonical       */
+/*   d128 is the source decimal128                                   */
+/*   returns 1 if the encoding of d128 is canonical, 0 otherwise      */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+uint32_t decimal128IsCanonical(const decimal128 *d128) {
+  decNumber dn;                                /* work */
+  decimal128 canon;                     /* .. */
+  decContext dc;                       /* .. */
+  decContextDefault(&dc, DEC_INIT_DECIMAL128);
+  decimal128ToNumber(d128, &dn);
+  decimal128FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
+  return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
+  } /* decimal128IsCanonical */
 
+/* ------------------------------------------------------------------ */
+/* decimal128Canonical -- copy an encoding, ensuring it is canonical  */
+/*   d128 is the source decimal128                                   */
+/*   result is the target (may be the same decimal128)               */
+/*   returns result                                                  */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
+  decNumber dn;                                /* work */
+  decContext dc;                       /* .. */
+  decContextDefault(&dc, DEC_INIT_DECIMAL128);
+  decimal128ToNumber(d128, &dn);
+  decimal128FromNumber(result, &dn, &dc);/* result will now be canonical */
+  return result;
+  } /* decimal128Canonical */
 
 #if DECTRACE || DECCHECK
+/* Macros for accessing decimal128 fields.  These assume the argument
+   is a reference (pointer) to the decimal128 structure, and the
+   decimal128 is in network byte order (big-endian) */
+/* Get sign */
+#define decimal128Sign(d)      ((unsigned)(d)->bytes[0]>>7)
+
+/* Get combination field */
+#define decimal128Comb(d)      (((d)->bytes[0] & 0x7c)>>2)
+
+/* Get exponent continuation [does not remove bias] */
+#define decimal128ExpCon(d)    ((((d)->bytes[0] & 0x03)<<10)         \
+                             | ((unsigned)(d)->bytes[1]<<2)          \
+                             | ((unsigned)(d)->bytes[2]>>6))
+
+/* Set sign [this assumes sign previously 0] */
+#define decimal128SetSign(d, b) {                                    \
+  (d)->bytes[0]|=((unsigned)(b)<<7);}
+
+/* Set exponent continuation [does not apply bias] */
+/* This assumes range has been checked and exponent previously 0; */
+/* type of exponent must be unsigned */
+#define decimal128SetExpCon(d, e) {                                  \
+  (d)->bytes[0]|=(uint8_t)((e)>>10);                                 \
+  (d)->bytes[1] =(uint8_t)(((e)&0x3fc)>>2);                          \
+  (d)->bytes[2]|=(uint8_t)(((e)&0x03)<<6);}
+
 /* ------------------------------------------------------------------ */
-/* decimal128Show -- display a single in hexadecimal [debug aid]      */
-/*   d128 -- the number to show                                       */
+/* decimal128Show -- display a decimal128 in hexadecimal [debug aid]  */
+/*   d128 -- the number to show                                              */
 /* ------------------------------------------------------------------ */
 /* Also shows sign/cob/expconfields extracted */
-void
-decimal128Show (const decimal128 * d128)
-{
-  char buf[DECIMAL128_Bytes * 2 + 1];
-  Int i, j;
-  j = 0;
-  for (i = 0; i < DECIMAL128_Bytes; i++)
-    {
-      sprintf (&buf[j], "%02x", d128->bytes[i]);
-      j = j + 2;
+void decimal128Show(const decimal128 *d128) {
+  char buf[DECIMAL128_Bytes*2+1];
+  Int i, j=0;
+
+  if (DECLITEND) {
+    for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
+      sprintf(&buf[j], "%02x", d128->bytes[15-i]);
+      }
+    printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
+          d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
+          ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
+          (d128->bytes[13]>>6));
+    }
+   else {
+    for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
+      sprintf(&buf[j], "%02x", d128->bytes[i]);
+      }
+    printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
+          decimal128Sign(d128), decimal128Comb(d128),
+          decimal128ExpCon(d128));
     }
-  printf (" D128> %s [S:%d Cb:%02x E:%d]\n", buf,
-         decimal128Sign (d128), decimal128Comb (d128),
-         decimal128ExpCon (d128));
-}
+  } /* decimal128Show */
 #endif
index a6bc87bb4a3ac39df249796bd7d3e0a042e1ee16..f8f5b5a8ff222aace913bdda0cb09393a7930da3 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal 128-bit format module header for the decNumber C Library
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Decimal 128-bit format module header for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
+/* ------------------------------------------------------------------ */
+/* Decimal 128-bit format module header                                      */
+/* ------------------------------------------------------------------ */
+
 #if !defined(DECIMAL128)
-#define DECIMAL128
-#define DEC128NAME     "decimal128"    /* Short name */
-#define DEC128FULLNAME "Decimal 128-bit Number"        /* Verbose name */
-#define DEC128AUTHOR   "Mike Cowlishaw"        /* Who to blame */
-
-#if defined(DECIMAL32)
-#error decimal128.h must precede decimal32.h for correct DECNUMDIGITS
-#else
-#if defined(DECIMAL64)
-#error decimal128.h must precede decimal64.h for correct DECNUMDIGITS
-#endif
-#endif
+  #define DECIMAL128
+  #define DEC128NAME    "decimal128"                 /* Short name   */
+  #define DEC128FULLNAME "Decimal 128-bit Number"     /* Verbose name */
+  #define DEC128AUTHOR  "Mike Cowlishaw"             /* Who to blame */
 
   /* parameters for decimal128s */
-#define DECIMAL128_Bytes  16   /* length */
-#define DECIMAL128_Pmax   34   /* maximum precision (digits) */
-#define DECIMAL128_Emax   6144 /* maximum adjusted exponent */
-#define DECIMAL128_Emin  -6143 /* minimum adjusted exponent */
-#define DECIMAL128_Bias   6176 /* bias for the exponent */
-#define DECIMAL128_String 43   /* maximum string length, +1 */
-  /* highest biased exponent (Elimit-1) */
-#define DECIMAL128_Ehigh  (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1)
-
-#ifndef DECNUMDIGITS
-#define DECNUMDIGITS DECIMAL128_Pmax   /* size if not already defined */
-#endif
-#ifndef DECNUMBER
-#include "decNumber.h"         /* context and number library */
-#endif
-
-  /* Decimal 128-bit type, accessible by bytes */
-typedef struct
-{
-  uint8_t bytes[DECIMAL128_Bytes];     /* decimal128: 1, 5, 12, 110 bits */
-} decimal128;
-
-  /* special values [top byte excluding sign bit; last two bits are
-     don't-care for Infinity on input, last bit don't-care for NaN] */
-#if !defined(DECIMAL_NaN)
-#define DECIMAL_NaN     0x7c   /* 0 11111 00 NaN */
-#define DECIMAL_sNaN    0x7e   /* 0 11111 10 sNaN */
-#define DECIMAL_Inf     0x78   /* 0 11110 00 Infinity */
-#endif
-
-  /* Macros for accessing decimal128 fields.  These assume the argument
-     is a reference (pointer) to the decimal128 structure */
-  /* Get sign */
-#define decimal128Sign(d)       ((unsigned)(d)->bytes[0]>>7)
-
-  /* Get combination field */
-#define decimal128Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
-
-  /* Get exponent continuation [does not remove bias] */
-#define decimal128ExpCon(d)     ((((d)->bytes[0] & 0x03)<<10)       \
-                                | ((unsigned)(d)->bytes[1]<<2)        \
-                                | ((unsigned)(d)->bytes[2]>>6))
-
-  /* Set sign [this assumes sign previously 0] */
-#define decimal128SetSign(d, b) {                                   \
-    (d)->bytes[0]|=((unsigned)(b)<<7);}
-
-  /* Clear sign */
-#define decimal128ClearSign(d) {(d)->bytes[0]&=~0x80;}
-
-  /* Flip sign */
-#define decimal128FlipSign(d) {(d)->bytes[0]^=0x80;}
-
-  /* Set exponent continuation [does not apply bias] */
-  /* This assumes range has been checked and exponent previously 0; */
-  /* type of exponent must be unsigned */
-#define decimal128SetExpCon(d, e) {                                 \
-    (d)->bytes[0]|=(uint8_t)((e)>>10);                                \
-    (d)->bytes[1] =(uint8_t)(((e)&0x3fc)>>2);                         \
-    (d)->bytes[2]|=(uint8_t)(((e)&0x03)<<6);}
-
-  /* ------------------------------------------------------------------ */
-  /* Routines                                                           */
-  /* ------------------------------------------------------------------ */
-
-#ifdef IN_LIBGCC2
-#ifndef decimal128FromString
-#define decimal128FromString __decimal128FromString
-#define decimal128ToString __decimal128ToString
-#define decimal128ToEngString __decimal128ToEngString
-#define decimal128FromNumber __decimal128FromNumber
-#define decimal128ToNumber __decimal128ToNumber
-#endif
-#endif
-
-  /* String conversions */
-decimal128 *decimal128FromString (decimal128 *, const char *, decContext *);
-char *decimal128ToString (const decimal128 *, char *);
-char *decimal128ToEngString (const decimal128 *, char *);
-
-  /* decNumber conversions */
-decimal128 *decimal128FromNumber (decimal128 *, const decNumber *, decContext *);
-decNumber *decimal128ToNumber (const decimal128 *, decNumber *);
+  #define DECIMAL128_Bytes  16         /* length                     */
+  #define DECIMAL128_Pmax   34         /* maximum precision (digits) */
+  #define DECIMAL128_Emax   6144       /* maximum adjusted exponent  */
+  #define DECIMAL128_Emin  -6143       /* minimum adjusted exponent  */
+  #define DECIMAL128_Bias   6176       /* bias for the exponent      */
+  #define DECIMAL128_String 43         /* maximum string length, +1  */
+  #define DECIMAL128_EconL  12         /* exp. continuation length   */
+  /* highest biased exponent (Elimit-1)                                      */
+  #define DECIMAL128_Ehigh  (DECIMAL128_Emax+DECIMAL128_Bias-DECIMAL128_Pmax+1)
+
+  /* check enough digits, if pre-defined                             */
+  #if defined(DECNUMDIGITS)
+    #if (DECNUMDIGITS<DECIMAL128_Pmax)
+      #error decimal128.h needs pre-defined DECNUMDIGITS>=34 for safe use
+    #endif
+  #endif
+
+  #ifndef DECNUMDIGITS
+    #define DECNUMDIGITS DECIMAL128_Pmax /* size if not already defined*/
+  #endif
+  #ifndef DECNUMBER
+    #include "decNumber.h"             /* context and number library */
+  #endif
+
+  /* Decimal 128-bit type, accessible by bytes                       */
+  typedef struct {
+    uint8_t bytes[DECIMAL128_Bytes]; /* decimal128: 1, 5, 12, 110 bits*/
+    } decimal128;
+
+  /* special values [top byte excluding sign bit; last two bits are   */
+  /* don't-care for Infinity on input, last bit don't-care for NaN]   */
+  #if !defined(DECIMAL_NaN)
+    #define DECIMAL_NaN            0x7c        /* 0 11111 00 NaN             */
+    #define DECIMAL_sNaN    0x7e       /* 0 11111 10 sNaN            */
+    #define DECIMAL_Inf            0x78        /* 0 11110 00 Infinity        */
+  #endif
+
+  #include "decimal128Local.h"
+
+  /* ---------------------------------------------------------------- */
+  /* Routines                                                        */
+  /* ---------------------------------------------------------------- */
+
+  #include "decimal128Symbols.h"
+
+  /* String conversions                                                      */
+  decimal128 * decimal128FromString(decimal128 *, const char *, decContext *);
+  char * decimal128ToString(const decimal128 *, char *);
+  char * decimal128ToEngString(const decimal128 *, char *);
+
+  /* decNumber conversions                                           */
+  decimal128 * decimal128FromNumber(decimal128 *, const decNumber *,
+                                   decContext *);
+  decNumber * decimal128ToNumber(const decimal128 *, decNumber *);
+
+  /* Format-dependent utilities                                              */
+  uint32_t    decimal128IsCanonical(const decimal128 *);
+  decimal128 * decimal128Canonical(decimal128 *, const decimal128 *);
 
 #endif
diff --git a/libdecnumber/dpd/decimal128Local.h b/libdecnumber/dpd/decimal128Local.h
new file mode 100644 (file)
index 0000000..b4130b5
--- /dev/null
@@ -0,0 +1,47 @@
+/* Local definitions for use with the decNumber C Library.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   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
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   In addition to the permissions in the GNU General Public License,
+   the Free Software Foundation gives you unlimited permission to link
+   the compiled version of this file into combinations with other
+   programs, and to distribute those combinations without any
+   restriction coming from the use of this file.  (The General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into a combine executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   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
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#if !defined(DECIMAL128LOCAL)
+
+/* The compiler needs sign manipulation functions for decimal128 which
+   are not part of the decNumber package.  */
+
+/* Set sign; this assumes the sign was previously zero.  */
+#define decimal128SetSign(d,b) \
+  { (d)->bytes[FLOAT_WORDS_BIG_ENDIAN ? 0 : 15] |= ((unsigned) (b) << 7); }
+
+/* Clear sign.  */
+#define decimal128ClearSign(d) \
+  { (d)->bytes[FLOAT_WORDS_BIG_ENDIAN ? 0 : 15] &= ~0x80; }
+
+/* Flip sign.  */
+#define decimal128FlipSign(d) \
+  { (d)->bytes[FLOAT_WORDS_BIG_ENDIAN ? 0 : 15] ^= 0x80; }
+
+#endif
diff --git a/libdecnumber/dpd/decimal128Symbols.h b/libdecnumber/dpd/decimal128Symbols.h
new file mode 100644 (file)
index 0000000..da9d76b
--- /dev/null
@@ -0,0 +1,16 @@
+#if !defined(DECIMAL128SYMBOLS)
+#define DECIMAL128SYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decDigitsFromDPD __decDigitsFromDPD
+#define decDigitsToDPD __decDigitsToDPD
+#define decimal128Canonical __decimal128Canonical
+#define decimal128FromNumber __decimal128FromNumber
+#define decimal128FromString __decimal128FromString
+#define decimal128IsCanonical __decimal128IsCanonical
+#define decimal128ToEngString __decimal128ToEngString
+#define decimal128ToNumber __decimal128ToNumber
+#define decimal128ToString __decimal128ToString
+#endif
+
+#endif
index 86912864c9f7d2df15e32fa2557373c696980212..692c2f70ecbdebe4fce0650c8646ae5582936eb3 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal 32-bit format module for the decNumber C Library
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Decimal 32-bit format module for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
+/* ------------------------------------------------------------------ */
+/* Decimal 32-bit format module                                              */
 /* ------------------------------------------------------------------ */
 /* This module comprises the routines for decimal32 format numbers.   */
-/* Conversions are supplied to and from decNumber and String.         */
-/*                                                                    */
-/* No arithmetic routines are included; decNumber provides these.     */
-/*                                                                    */
-/* Error handling is the same as decNumber (qv.).                     */
+/* Conversions are supplied to and from decNumber and String.        */
+/*                                                                   */
+/* This is used when decNumber provides operations, either for all    */
+/* operations or as a proxy between decNumber and decSingle.         */
+/*                                                                   */
+/* Error handling is the same as decNumber (qv.).                    */
 /* ------------------------------------------------------------------ */
-#include <string.h>            /* [for memset/memcpy] */
-#include <stdio.h>             /* [for printf] */
+#include <string.h>          /* [for memset/memcpy] */
+#include <stdio.h>           /* [for printf] */
+
+#include "config.h"          /* GCC definitions */
+#define         DECNUMDIGITS  7      /* make decNumbers with space for 7 */
+#include "decNumber.h"       /* base number library */
+#include "decNumberLocal.h"   /* decNumber local types, etc. */
+#include "decimal32.h"       /* our primary include */
 
-#define  DECNUMDIGITS  7       /* we need decNumbers with space for 7 */
-#include "config.h"
-#include "decNumber.h"         /* base number library */
-#include "decNumberLocal.h"    /* decNumber local types, etc. */
-#include "decimal32.h"         /* our primary include */
-#include "decUtility.h"                /* utility routines */
+/* Utility tables and routines [in decimal64.c] */
+/* DPD2BIN and the reverse are renamed to prevent link-time conflict */
+/* if decQuad is also built in the same executable */
+#define DPD2BIN DPD2BINx
+#define BIN2DPD BIN2DPDx
+extern const uInt   COMBEXP[32], COMBMSD[32];
+extern const uShort DPD2BIN[1024];
+extern const uShort BIN2DPD[1000];
+extern const uByte  BIN2CHAR[4001];
+
+extern void decDigitsToDPD(const decNumber *, uInt *, Int);
+extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
 
 #if DECTRACE || DECCHECK
-void decimal32Show (const decimal32 *);        /* for debug */
-void decNumberShow (const decNumber *);        /* .. */
+void decimal32Show(const decimal32 *);           /* for debug */
+extern void decNumberShow(const decNumber *);    /* .. */
 #endif
 
 /* Useful macro */
@@ -56,282 +71,425 @@ void decNumberShow (const decNumber *);   /* .. */
 #define DEC_clear(d) memset(d, 0, sizeof(*d))
 
 /* ------------------------------------------------------------------ */
-/* decimal32FromNumber -- convert decNumber to decimal32              */
-/*                                                                    */
-/*   ds is the target decimal32                                       */
-/*   dn is the source number (assumed valid)                          */
-/*   set is the context, used only for reporting errors               */
-/*                                                                    */
+/* decimal32FromNumber -- convert decNumber to decimal32             */
+/*                                                                   */
+/*   ds is the target decimal32                                              */
+/*   dn is the source number (assumed valid)                         */
+/*   set is the context, used only for reporting errors                      */
+/*                                                                   */
 /* The set argument is used only for status reporting and for the     */
 /* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */
-/* digits or an overflow is detected).  If the exponent is out of the */
-/* valid range then Overflow or Underflow will be raised.             */
-/* After Underflow a subnormal result is possible.                    */
-/*                                                                    */
+/* digits or an overflow is detected). If the exponent is out of the */
+/* valid range then Overflow or Underflow will be raised.            */
+/* After Underflow a subnormal result is possible.                   */
+/*                                                                   */
 /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
 /* by reducing its exponent and multiplying the coefficient by a      */
 /* power of ten, or if the exponent on a zero had to be clamped.      */
 /* ------------------------------------------------------------------ */
-decimal32 *
-decimal32FromNumber (decimal32 * d32, const decNumber * dn, decContext * set)
-{
-  uInt status = 0;             /* status accumulator */
-  Int pad = 0;                 /* coefficient pad digits */
-  decNumber dw;                        /* work */
-  decContext dc;               /* .. */
-  uByte isneg = dn->bits & DECNEG;     /* non-0 if original sign set */
-  uInt comb, exp;              /* work */
-
-  /* If the number is finite, and has too many digits, or the exponent */
-  /* could be out of range then we reduce the number under the */
-  /* appropriate constraints */
-  if (!(dn->bits & DECSPECIAL))
-    {                          /* not a special value */
-      Int ae = dn->exponent + dn->digits - 1;  /* adjusted exponent */
-      if (dn->digits > DECIMAL32_Pmax  /* too many digits */
-         || ae > DECIMAL32_Emax        /* likely overflow */
-         || ae < DECIMAL32_Emin)
-       {                       /* likely underflow */
-         decContextDefault (&dc, DEC_INIT_DECIMAL32);  /* [no traps] */
-         dc.round = set->round;        /* use supplied rounding */
-         decNumberPlus (&dw, dn, &dc); /* (round and check) */
-         /* [this changes -0 to 0, but it will be restored below] */
-         status |= dc.status;  /* save status */
-         dn = &dw;             /* use the work number */
-       }
-      /* [this could have pushed number to Infinity or zero, so this */
-      /* rounding must be done before we generate the decimal32] */
-    }
+decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
+                             decContext *set) {
+  uInt status=0;                  /* status accumulator */
+  Int ae;                         /* adjusted exponent */
+  decNumber  dw;                  /* work */
+  decContext dc;                  /* .. */
+  uInt *pu;                       /* .. */
+  uInt comb, exp;                 /* .. */
+  uInt targ=0;                    /* target 32-bit */
+
+  /* If the number has too many digits, or the exponent could be */
+  /* out of range then reduce the number under the appropriate */
+  /* constraints.  This could push the number to Infinity or zero, */
+  /* so this check and rounding must be done before generating the */
+  /* decimal32] */
+  ae=dn->exponent+dn->digits-1;                     /* [0 if special] */
+  if (dn->digits>DECIMAL32_Pmax                     /* too many digits */
+   || ae>DECIMAL32_Emax                             /* likely overflow */
+   || ae<DECIMAL32_Emin) {                  /* likely underflow */
+    decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */
+    dc.round=set->round;                    /* use supplied rounding */
+    decNumberPlus(&dw, dn, &dc);            /* (round and check) */
+    /* [this changes -0 to 0, so enforce the sign...] */
+    dw.bits|=dn->bits&DECNEG;
+    status=dc.status;                       /* save status */
+    dn=&dw;                                 /* use the work number */
+    } /* maybe out of range */
 
-  DEC_clear (d32);             /* clean the target */
-  if (dn->bits & DECSPECIAL)
-    {                          /* a special value */
-      uByte top;               /* work */
-      if (dn->bits & DECINF)
-       top = DECIMAL_Inf;
-      else
-       {                       /* sNaN or qNaN */
-         if ((*dn->lsu != 0 || dn->digits > 1) /* non-zero coefficient */
-             && (dn->digits < DECIMAL32_Pmax))
-           {                   /* coefficient fits */
-             decDensePackCoeff (dn, d32->bytes, sizeof (d32->bytes), 0);
-           }
-         if (dn->bits & DECNAN)
-           top = DECIMAL_NaN;
-         else
-           top = DECIMAL_sNaN;
+  if (dn->bits&DECSPECIAL) {                     /* a special value */
+    if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
+     else {                                      /* sNaN or qNaN */
+      if ((*dn->lsu!=0 || dn->digits>1)                  /* non-zero coefficient */
+       && (dn->digits<DECIMAL32_Pmax)) {         /* coefficient fits */
+       decDigitsToDPD(dn, &targ, 0);
        }
-      d32->bytes[0] = top;
-    }
-  else if (decNumberIsZero (dn))
-    {                          /* a zero */
+      if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
+       else targ|=DECIMAL_sNaN<<24;
+      } /* a NaN */
+    } /* special */
+
+   else { /* is finite */
+    if (decNumberIsZero(dn)) {              /* is a zero */
       /* set and clamp exponent */
-      if (dn->exponent < -DECIMAL32_Bias)
-       {
-         exp = 0;
-         status |= DEC_Clamped;
+      if (dn->exponent<-DECIMAL32_Bias) {
+       exp=0;                               /* low clamp */
+       status|=DEC_Clamped;
        }
-      else
-       {
-         exp = dn->exponent + DECIMAL32_Bias;  /* bias exponent */
-         if (exp > DECIMAL32_Ehigh)
-           {                   /* top clamp */
-             exp = DECIMAL32_Ehigh;
-             status |= DEC_Clamped;
-           }
+       else {
+       exp=dn->exponent+DECIMAL32_Bias;     /* bias exponent */
+       if (exp>DECIMAL32_Ehigh) {           /* top clamp */
+         exp=DECIMAL32_Ehigh;
+         status|=DEC_Clamped;
+         }
        }
-      comb = (exp >> 3) & 0x18;        /* combination field */
-      d32->bytes[0] = (uByte) (comb << 2);
-      exp &= 0x3f;             /* remaining exponent bits */
-      decimal32SetExpCon (d32, exp);
-    }
-  else
-    {                          /* non-zero finite number */
-      uInt msd;                        /* work */
-
-      /* we have a dn that fits, but it may need to be padded */
-      exp = (uInt) (dn->exponent + DECIMAL32_Bias);    /* bias exponent */
-
-      if (exp > DECIMAL32_Ehigh)
-       {                       /* fold-down case */
-         pad = exp - DECIMAL32_Ehigh;
-         exp = DECIMAL32_Ehigh;        /* [to maximum] */
-         status |= DEC_Clamped;
+      comb=(exp>>3) & 0x18;            /* msd=0, exp top 2 bits .. */
+      }
+     else {                            /* non-zero finite number */
+      uInt msd;                                /* work */
+      Int pad=0;                       /* coefficient pad digits */
+
+      /* the dn is known to fit, but it may need to be padded */
+      exp=(uInt)(dn->exponent+DECIMAL32_Bias);   /* bias exponent */
+      if (exp>DECIMAL32_Ehigh) {                 /* fold-down case */
+       pad=exp-DECIMAL32_Ehigh;
+       exp=DECIMAL32_Ehigh;                      /* [to maximum] */
+       status|=DEC_Clamped;
        }
 
-      decDensePackCoeff (dn, d32->bytes, sizeof (d32->bytes), pad);
+      /* fastpath common case */
+      if (DECDPUN==3 && pad==0) {
+       targ=BIN2DPD[dn->lsu[0]];
+       if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
+       msd=(dn->digits==7 ? dn->lsu[2] : 0);
+       }
+       else { /* general case */
+       decDigitsToDPD(dn, &targ, pad);
+       /* save and clear the top digit */
+       msd=targ>>20;
+       targ&=0x000fffff;
+       }
 
-      /* save and clear the top digit */
-      msd = ((unsigned) d32->bytes[1] >> 4);
-      d32->bytes[1] &= 0x0f;
       /* create the combination field */
-      if (msd >= 8)
-       comb = 0x18 | (msd & 0x01) | ((exp >> 5) & 0x06);
-      else
-       comb = (msd & 0x07) | ((exp >> 3) & 0x18);
-      d32->bytes[0] = (uByte) (comb << 2);
-      exp &= 0x3f;             /* remaining exponent bits */
-      decimal32SetExpCon (d32, exp);
-    }
+      if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
+            else comb=((exp>>3) & 0x18) | msd;
+      }
+    targ|=comb<<26;               /* add combination field .. */
+    targ|=(exp&0x3f)<<20;         /* .. and exponent continuation */
+    } /* finite */
+
+  if (dn->bits&DECNEG) targ|=0x80000000;  /* add sign bit */
 
-  if (isneg)
-    decimal32SetSign (d32, 1);
-  if (status != 0)
-    decContextSetStatus (set, status); /* pass on status */
+  /* now write to storage; this is endian */
+  pu=(uInt *)d32->bytes;          /* overlay */
+  *pu=targ;                       /* directly store the int */
 
-  /*decimal32Show(d32); */
+  if (status!=0) decContextSetStatus(set, status); /* pass on status */
+  /* decimal32Show(d32); */
   return d32;
-}
+  } /* decimal32FromNumber */
 
 /* ------------------------------------------------------------------ */
-/* decimal32ToNumber -- convert decimal32 to decNumber                */
-/*   d32 is the source decimal32                                      */
-/*   dn is the target number, with appropriate space                  */
-/* No error is possible.                                              */
+/* decimal32ToNumber -- convert decimal32 to decNumber               */
+/*   d32 is the source decimal32                                     */
+/*   dn is the target number, with appropriate space                 */
+/* No error is possible.                                             */
 /* ------------------------------------------------------------------ */
-decNumber *
-decimal32ToNumber (const decimal32 * d32, decNumber * dn)
-{
-  uInt msd;                    /* coefficient MSD */
-  decimal32 wk;                        /* working copy, if needed */
-  uInt top = d32->bytes[0] & 0x7f;     /* top byte, less sign bit */
-  decNumberZero (dn);          /* clean target */
-  /* set the sign if negative */
-  if (decimal32Sign (d32))
-    dn->bits = DECNEG;
-
-  if (top >= 0x78)
-    {                          /* is a special */
-      if ((top & 0x7c) == (DECIMAL_Inf & 0x7c))
-       dn->bits |= DECINF;
-      else if ((top & 0x7e) == (DECIMAL_NaN & 0x7e))
-       dn->bits |= DECNAN;
-      else
-       dn->bits |= DECSNAN;
-      msd = 0;                 /* no top digit */
+decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
+  uInt msd;                       /* coefficient MSD */
+  uInt exp;                       /* exponent top two bits */
+  uInt comb;                      /* combination field */
+  uInt sour;                      /* source 32-bit */
+  const uInt *pu;                 /* work */
+
+  /* load source from storage; this is endian */
+  pu=(const uInt *)d32->bytes;    /* overlay */
+  sour=*pu;                       /* directly load the int */
+
+  comb=(sour>>26)&0x1f;                   /* combination field */
+
+  decNumberZero(dn);              /* clean number */
+  if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */
+
+  msd=COMBMSD[comb];              /* decode the combination field */
+  exp=COMBEXP[comb];              /* .. */
+
+  if (exp==3) {                           /* is a special */
+    if (msd==0) {
+      dn->bits|=DECINF;
+      return dn;                  /* no coefficient needed */
+      }
+    else if (sour&0x02000000) dn->bits|=DECSNAN;
+    else dn->bits|=DECNAN;
+    msd=0;                        /* no top digit */
     }
-  else
-    {                          /* have a finite number */
-      uInt comb = top >> 2;    /* combination field */
-      uInt exp;                        /* working exponent */
-
-      if (comb >= 0x18)
-       {
-         msd = 8 + (comb & 0x01);
-         exp = (comb & 0x06) << 5;     /* MSBs */
-       }
-      else
-       {
-         msd = comb & 0x07;
-         exp = (comb & 0x18) << 3;
-       }
-      dn->exponent = exp + decimal32ExpCon (d32) - DECIMAL32_Bias;     /* remove bias */
+   else {                         /* is a finite number */
+    dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */
     }
 
-  /* get the coefficient, unless infinite */
-  if (!(dn->bits & DECINF))
-    {
-      Int bunches = DECIMAL32_Pmax / 3;        /* coefficient full bunches to convert */
-      Int odd = 0;             /* assume MSD is 0 (no odd bunch) */
-      if (msd != 0)
-       {                       /* coefficient has leading non-0 digit */
-         /* make a copy of the decimal32, with an extra bunch which has */
-         /* the top digit ready for conversion */
-         wk = *d32;            /* take a copy */
-         wk.bytes[0] = 0;      /* clear all but coecon */
-         wk.bytes[1] &= 0x0f;  /* .. */
-         wk.bytes[1] |= (msd << 4);    /* and prefix MSD */
-         odd++;                /* indicate the extra */
-         d32 = &wk;            /* use the work copy */
-       }
-      decDenseUnpackCoeff (d32->bytes, sizeof (d32->bytes), dn, bunches, odd);
+  /* get the coefficient */
+  sour&=0x000fffff;               /* clean coefficient continuation */
+  if (msd) {                      /* non-zero msd */
+    sour|=msd<<20;                /* prefix to coefficient */
+    decDigitsFromDPD(dn, &sour, 3); /* process 3 declets */
+    return dn;
     }
+  /* msd=0 */
+  if (!sour) return dn;                   /* easy: coefficient is 0 */
+  if (sour&0x000ffc00)            /* need 2 declets? */
+    decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */
+   else
+    decDigitsFromDPD(dn, &sour, 1); /* process 1 declet */
   return dn;
-}
+  } /* decimal32ToNumber */
 
 /* ------------------------------------------------------------------ */
-/* to-scientific-string -- conversion to numeric string               */
-/* to-engineering-string -- conversion to numeric string              */
-/*                                                                    */
-/*   decimal32ToString(d32, string);                                  */
-/*   decimal32ToEngString(d32, string);                               */
-/*                                                                    */
-/*  d32 is the decimal32 format number to convert                     */
-/*  string is the string where the result will be laid out            */
-/*                                                                    */
-/*  string must be at least 24 characters                             */
-/*                                                                    */
-/*  No error is possible, and no status can be set.                   */
+/* to-scientific-string -- conversion to numeric string                      */
+/* to-engineering-string -- conversion to numeric string             */
+/*                                                                   */
+/*   decimal32ToString(d32, string);                                 */
+/*   decimal32ToEngString(d32, string);                                      */
+/*                                                                   */
+/*  d32 is the decimal32 format number to convert                    */
+/*  string is the string where the result will be laid out           */
+/*                                                                   */
+/*  string must be at least 24 characters                            */
+/*                                                                   */
+/*  No error is possible, and no status can be set.                  */
 /* ------------------------------------------------------------------ */
-char *
-decimal32ToString (const decimal32 * d32, char *string)
-{
-  decNumber dn;                        /* work */
-  decimal32ToNumber (d32, &dn);
-  decNumberToString (&dn, string);
+char * decimal32ToEngString(const decimal32 *d32, char *string){
+  decNumber dn;                                /* work */
+  decimal32ToNumber(d32, &dn);
+  decNumberToEngString(&dn, string);
   return string;
-}
-
-char *
-decimal32ToEngString (const decimal32 * d32, char *string)
-{
-  decNumber dn;                        /* work */
-  decimal32ToNumber (d32, &dn);
-  decNumberToEngString (&dn, string);
+  } /* decimal32ToEngString */
+
+char * decimal32ToString(const decimal32 *d32, char *string){
+  uInt msd;                       /* coefficient MSD */
+  Int  exp;                       /* exponent top two bits or full */
+  uInt comb;                      /* combination field */
+  char *cstart;                           /* coefficient start */
+  char *c;                        /* output pointer in string */
+  const uInt *pu;                 /* work */
+  const uByte *u;                 /* .. */
+  char *s, *t;                    /* .. (source, target) */
+  Int  dpd;                       /* .. */
+  Int  pre, e;                    /* .. */
+  uInt sour;                      /* source 32-bit */
+
+  /* load source from storage; this is endian */
+  pu=(const uInt *)d32->bytes;    /* overlay */
+  sour=*pu;                       /* directly load the int */
+
+  c=string;                       /* where result will go */
+  if (((Int)sour)<0) *c++='-';    /* handle sign */
+
+  comb=(sour>>26)&0x1f;                   /* combination field */
+  msd=COMBMSD[comb];              /* decode the combination field */
+  exp=COMBEXP[comb];              /* .. */
+
+  if (exp==3) {
+    if (msd==0) {                 /* infinity */
+      strcpy(c,          "Inf");
+      strcpy(c+3, "inity");
+      return string;              /* easy */
+      }
+    if (sour&0x02000000) *c++='s'; /* sNaN */
+    strcpy(c, "NaN");             /* complete word */
+    c+=3;                         /* step past */
+    if ((sour&0x000fffff)==0) return string; /* zero payload */
+    /* otherwise drop through to add integer; set correct exp */
+    exp=0; msd=0;                 /* setup for following code */
+    }
+   else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */
+
+  /* convert 7 digits of significand to characters */
+  cstart=c;                       /* save start of coefficient */
+  if (msd) *c++='0'+(char)msd;    /* non-zero most significant digit */
+
+  /* Now decode the declets.  After extracting each one, it is */
+  /* decoded to binary and then to a 4-char sequence by table lookup; */
+  /* the 4-chars are a 1-char length (significant digits, except 000 */
+  /* has length 0).  This allows us to left-align the first declet */
+  /* with non-zero content, then remaining ones are full 3-char */
+  /* length.  We use fixed-length memcpys because variable-length */
+  /* causes a subroutine call in GCC.  (These are length 4 for speed */
+  /* and are safe because the array has an extra terminator byte.) */
+  #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                          \
+                  if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
+                   else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
+
+  dpd=(sour>>10)&0x3ff;                   /* declet 1 */
+  dpd2char;
+  dpd=(sour)&0x3ff;               /* declet 2 */
+  dpd2char;
+
+  if (c==cstart) *c++='0';        /* all zeros -- make 0 */
+
+  if (exp==0) {                           /* integer or NaN case -- easy */
+    *c='\0';                      /* terminate */
+    return string;
+    }
+
+  /* non-0 exponent */
+  e=0;                            /* assume no E */
+  pre=c-cstart+exp;
+  /* [here, pre-exp is the digits count (==1 for zero)] */
+  if (exp>0 || pre<-5) {          /* need exponential form */
+    e=pre-1;                      /* calculate E value */
+    pre=1;                        /* assume one digit before '.' */
+    } /* exponential form */
+
+  /* modify the coefficient, adding 0s, '.', and E+nn as needed */
+  s=c-1;                          /* source (LSD) */
+  if (pre>0) {                    /* ddd.ddd (plain), perhaps with E */
+    char *dotat=cstart+pre;
+    if (dotat<c) {                /* if embedded dot needed... */
+      t=c;                             /* target */
+      for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
+      *t='.';                          /* insert the dot */
+      c++;                             /* length increased by one */
+      }
+
+    /* finally add the E-part, if needed; it will never be 0, and has */
+    /* a maximum length of 3 digits (E-101 case) */
+    if (e!=0) {
+      *c++='E';                           /* starts with E */
+      *c++='+';                           /* assume positive */
+      if (e<0) {
+       *(c-1)='-';                /* oops, need '-' */
+       e=-e;                      /* uInt, please */
+       }
+      u=&BIN2CHAR[e*4];                   /* -> length byte */
+      memcpy(c, u+4-*u, 4);       /* copy fixed 4 characters [is safe] */
+      c+=*u;                      /* bump pointer appropriately */
+      }
+    *c='\0';                      /* add terminator */
+    /*printf("res %s\n", string); */
+    return string;
+    } /* pre>0 */
+
+  /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
+  t=c+1-pre;
+  *(t+1)='\0';                         /* can add terminator now */
+  for (; s>=cstart; s--, t--) *t=*s;   /* shift whole coefficient right */
+  c=cstart;
+  *c++='0';                            /* always starts with 0. */
+  *c++='.';
+  for (; pre<0; pre++) *c++='0';       /* add any 0's after '.' */
+  /*printf("res %s\n", string); */
   return string;
-}
+  } /* decimal32ToString */
 
 /* ------------------------------------------------------------------ */
-/* to-number -- conversion from numeric string                        */
-/*                                                                    */
-/*   decimal32FromString(result, string, set);                        */
-/*                                                                    */
+/* to-number -- conversion from numeric string                       */
+/*                                                                   */
+/*   decimal32FromString(result, string, set);                       */
+/*                                                                   */
 /*  result  is the decimal32 format number which gets the result of   */
-/*          the conversion                                            */
+/*         the conversion                                            */
 /*  *string is the character string which should contain a valid      */
-/*          number (which may be a special value)                     */
-/*  set     is the context                                            */
-/*                                                                    */
+/*         number (which may be a special value)                     */
+/*  set            is the context                                            */
+/*                                                                   */
 /* The context is supplied to this routine is used for error handling */
 /* (setting of status and traps) and for the rounding mode, only.     */
 /* If an error occurs, the result will be a valid decimal32 NaN.      */
 /* ------------------------------------------------------------------ */
-decimal32 *
-decimal32FromString (decimal32 * result, const char *string, decContext * set)
-{
-  decContext dc;               /* work */
-  decNumber dn;                        /* .. */
-
-  decContextDefault (&dc, DEC_INIT_DECIMAL32); /* no traps, please */
-  dc.round = set->round;       /* use supplied rounding */
-
-  decNumberFromString (&dn, string, &dc);      /* will round if needed */
-  decimal32FromNumber (result, &dn, &dc);
-  if (dc.status != 0)
-    {                          /* something happened */
-      decContextSetStatus (set, dc.status);    /* .. pass it on */
+decimal32 * decimal32FromString(decimal32 *result, const char *string,
+                               decContext *set) {
+  decContext dc;                            /* work */
+  decNumber dn;                                     /* .. */
+
+  decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */
+  dc.round=set->round;                       /* use supplied rounding */
+
+  decNumberFromString(&dn, string, &dc);     /* will round if needed */
+  decimal32FromNumber(result, &dn, &dc);
+  if (dc.status!=0) {                       /* something happened */
+    decContextSetStatus(set, dc.status);     /* .. pass it on */
     }
   return result;
-}
+  } /* decimal32FromString */
+
+/* ------------------------------------------------------------------ */
+/* decimal32IsCanonical -- test whether encoding is canonical        */
+/*   d32 is the source decimal32                                     */
+/*   returns 1 if the encoding of d32 is canonical, 0 otherwise              */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+uint32_t decimal32IsCanonical(const decimal32 *d32) {
+  decNumber dn;                                /* work */
+  decimal32 canon;                     /* .. */
+  decContext dc;                       /* .. */
+  decContextDefault(&dc, DEC_INIT_DECIMAL32);
+  decimal32ToNumber(d32, &dn);
+  decimal32FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
+  return memcmp(d32, &canon, DECIMAL32_Bytes)==0;
+  } /* decimal32IsCanonical */
+
+/* ------------------------------------------------------------------ */
+/* decimal32Canonical -- copy an encoding, ensuring it is canonical   */
+/*   d32 is the source decimal32                                     */
+/*   result is the target (may be the same decimal32)                */
+/*   returns result                                                  */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
+  decNumber dn;                                /* work */
+  decContext dc;                       /* .. */
+  decContextDefault(&dc, DEC_INIT_DECIMAL32);
+  decimal32ToNumber(d32, &dn);
+  decimal32FromNumber(result, &dn, &dc);/* result will now be canonical */
+  return result;
+  } /* decimal32Canonical */
 
 #if DECTRACE || DECCHECK
+/* Macros for accessing decimal32 fields.  These assume the argument
+   is a reference (pointer) to the decimal32 structure, and the
+   decimal32 is in network byte order (big-endian) */
+/* Get sign */
+#define decimal32Sign(d)       ((unsigned)(d)->bytes[0]>>7)
+
+/* Get combination field */
+#define decimal32Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
+
+/* Get exponent continuation [does not remove bias] */
+#define decimal32ExpCon(d)     ((((d)->bytes[0] & 0x03)<<4)          \
+                            | ((unsigned)(d)->bytes[1]>>4))
+
+/* Set sign [this assumes sign previously 0] */
+#define decimal32SetSign(d, b) {                                     \
+  (d)->bytes[0]|=((unsigned)(b)<<7);}
+
+/* Set exponent continuation [does not apply bias] */
+/* This assumes range has been checked and exponent previously 0; */
+/* type of exponent must be unsigned */
+#define decimal32SetExpCon(d, e) {                                   \
+  (d)->bytes[0]|=(uint8_t)((e)>>4);                                  \
+  (d)->bytes[1]|=(uint8_t)(((e)&0x0F)<<4);}
+
 /* ------------------------------------------------------------------ */
-/* decimal32Show -- display a single in hexadecimal [debug aid]       */
-/*   d32 -- the number to show                                        */
+/* decimal32Show -- display a decimal32 in hexadecimal [debug aid]    */
+/*   d32 -- the number to show                                       */
 /* ------------------------------------------------------------------ */
-/* Also shows sign/cob/expconfields extracted */
-void
-decimal32Show (const decimal32 * d32)
-{
-  char buf[DECIMAL32_Bytes * 2 + 1];
-  Int i, j;
-  j = 0;
-  for (i = 0; i < DECIMAL32_Bytes; i++)
-    {
-      sprintf (&buf[j], "%02x", d32->bytes[i]);
-      j = j + 2;
+/* Also shows sign/cob/expconfields extracted - valid bigendian only */
+void decimal32Show(const decimal32 *d32) {
+  char buf[DECIMAL32_Bytes*2+1];
+  Int i, j=0;
+
+  if (DECLITEND) {
+    for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
+      sprintf(&buf[j], "%02x", d32->bytes[3-i]);
+      }
+    printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
+          d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
+          ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
+    }
+   else {
+    for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
+      sprintf(&buf[j], "%02x", d32->bytes[i]);
+      }
+    printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
+          decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
     }
-  printf (" D32> %s [S:%d Cb:%02x E:%d]\n", buf,
-         decimal32Sign (d32), decimal32Comb (d32), decimal32ExpCon (d32));
-}
+  } /* decimal32Show */
 #endif
index cbe8ab4a65cd134f8e3457884e55ff0853e4fcf8..0d530464172c4a95e4e8a866112bb561efda4fe6 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal 32-bit format module header for the decNumber C Library
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Decimal 32-bit format module header for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
+/* ------------------------------------------------------------------ */
+/* Decimal 32-bit format module header                               */
+/* ------------------------------------------------------------------ */
+
 #if !defined(DECIMAL32)
-#define DECIMAL32
-#define DEC32NAME     "decimal32"      /* Short name */
-#define DEC32FULLNAME "Decimal 32-bit Number"  /* Verbose name */
-#define DEC32AUTHOR   "Mike Cowlishaw" /* Who to blame */
+  #define DECIMAL32
+  #define DEC32NAME    "decimal32"                   /* Short name   */
+  #define DEC32FULLNAME "Decimal 32-bit Number"              /* Verbose name */
+  #define DEC32AUTHOR  "Mike Cowlishaw"              /* Who to blame */
 
   /* parameters for decimal32s */
-#define DECIMAL32_Bytes  4     /* length */
-#define DECIMAL32_Pmax   7     /* maximum precision (digits) */
-#define DECIMAL32_Emax   96    /* maximum adjusted exponent */
-#define DECIMAL32_Emin  -95    /* minimum adjusted exponent */
-#define DECIMAL32_Bias   101   /* bias for the exponent */
-#define DECIMAL32_String 15    /* maximum string length, +1 */
-  /* highest biased exponent (Elimit-1) */
-#define DECIMAL32_Ehigh  (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1)
-
-#ifndef DECNUMDIGITS
-#define DECNUMDIGITS DECIMAL32_Pmax    /* size if not already defined */
-#endif
-#ifndef DECNUMBER
-#include "decNumber.h"         /* context and number library */
-#endif
+  #define DECIMAL32_Bytes  4           /* length                     */
+  #define DECIMAL32_Pmax   7           /* maximum precision (digits) */
+  #define DECIMAL32_Emax   96          /* maximum adjusted exponent  */
+  #define DECIMAL32_Emin  -95          /* minimum adjusted exponent  */
+  #define DECIMAL32_Bias   101         /* bias for the exponent      */
+  #define DECIMAL32_String 15          /* maximum string length, +1  */
+  #define DECIMAL32_EconL  6           /* exp. continuation length   */
+  /* highest biased exponent (Elimit-1)                                      */
+  #define DECIMAL32_Ehigh  (DECIMAL32_Emax+DECIMAL32_Bias-DECIMAL32_Pmax+1)
+
+  /* check enough digits, if pre-defined                             */
+  #if defined(DECNUMDIGITS)
+    #if (DECNUMDIGITS<DECIMAL32_Pmax)
+      #error decimal32.h needs pre-defined DECNUMDIGITS>=7 for safe use
+    #endif
+  #endif
+
+  #ifndef DECNUMDIGITS
+    #define DECNUMDIGITS DECIMAL32_Pmax /* size if not already defined*/
+  #endif
+  #ifndef DECNUMBER
+    #include "decNumber.h"             /* context and number library */
+  #endif
 
   /* Decimal 32-bit type, accessible by bytes */
-typedef struct
-{
-  uint8_t bytes[DECIMAL32_Bytes];      /* decimal32: 1, 5, 6, 20 bits */
-} decimal32;
-
-  /* special values [top byte excluding sign bit; last two bits are
-     don't-care for Infinity on input, last bit don't-care for NaN] */
-#if !defined(DECIMAL_NaN)
-#define DECIMAL_NaN     0x7c   /* 0 11111 00 NaN */
-#define DECIMAL_sNaN    0x7e   /* 0 11111 10 sNaN */
-#define DECIMAL_Inf     0x78   /* 0 11110 00 Infinity */
-#endif
-
-  /* Macros for accessing decimal32 fields.  These assume the argument
-     is a reference (pointer) to the decimal32 structure */
-  /* Get sign */
-#define decimal32Sign(d)       ((unsigned)(d)->bytes[0]>>7)
-
-  /* Get combination field */
-#define decimal32Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
-
-  /* Get exponent continuation [does not remove bias] */
-#define decimal32ExpCon(d)     ((((d)->bytes[0] & 0x03)<<4)         \
-                               | ((unsigned)(d)->bytes[1]>>4))
-
-  /* Set sign [this assumes sign previously 0] */
-#define decimal32SetSign(d, b) {                                    \
-    (d)->bytes[0]|=((unsigned)(b)<<7);}
-
-  /* Clear sign */
-#define decimal32ClearSign(d) {(d)->bytes[0]&=~0x80;}
-
-  /* Flip sign */
-#define decimal32FlipSign(d) {(d)->bytes[0]^=0x80;}
-
-  /* Set exponent continuation [does not apply bias] */
-  /* This assumes range has been checked and exponent previously 0; */
-  /* type of exponent must be unsigned */
-#define decimal32SetExpCon(d, e) {                                  \
-    (d)->bytes[0]|=(uint8_t)((e)>>4);                                 \
-    (d)->bytes[1]|=(uint8_t)(((e)&0x0F)<<4);}
-
-  /* ------------------------------------------------------------------ */
-  /* Routines                                                           */
-  /* ------------------------------------------------------------------ */
-
-#ifdef IN_LIBGCC2
-#ifndef decimal32FromString
-#define decimal32FromString __decimal32FromString
-#define decimal32ToString __decimal32ToString
-#define decimal32ToEngString __decimal32ToEngString
-#define decimal32FromNumber __decimal32FromNumber
-#define decimal32ToNumber __decimal32ToNumber
-#endif
-#endif
-
-/* String conversions.  */
-decimal32 *decimal32FromString (decimal32 *, const char *, decContext *);
-char *decimal32ToString (const decimal32 *, char *);
-char *decimal32ToEngString (const decimal32 *, char *);
-
-/* decNumber conversions.  */
-decimal32 *decimal32FromNumber (decimal32 *, const decNumber *, decContext *);
-decNumber *decimal32ToNumber (const decimal32 *, decNumber *);
+  typedef struct {
+    uint8_t bytes[DECIMAL32_Bytes];    /* decimal32: 1, 5, 6, 20 bits*/
+    } decimal32;
+
+  /* special values [top byte excluding sign bit; last two bits are   */
+  /* don't-care for Infinity on input, last bit don't-care for NaN]   */
+  #if !defined(DECIMAL_NaN)
+    #define DECIMAL_NaN            0x7c        /* 0 11111 00 NaN             */
+    #define DECIMAL_sNaN    0x7e       /* 0 11111 10 sNaN            */
+    #define DECIMAL_Inf            0x78        /* 0 11110 00 Infinity        */
+  #endif
+
+  /* ---------------------------------------------------------------- */
+  /* Routines                                                        */
+  /* ---------------------------------------------------------------- */
+
+  #include "decimal32Symbols.h"
+
+  /* String conversions                                                      */
+  decimal32 * decimal32FromString(decimal32 *, const char *, decContext *);
+  char * decimal32ToString(const decimal32 *, char *);
+  char * decimal32ToEngString(const decimal32 *, char *);
+
+  /* decNumber conversions                                           */
+  decimal32 * decimal32FromNumber(decimal32 *, const decNumber *,
+                                 decContext *);
+  decNumber * decimal32ToNumber(const decimal32 *, decNumber *);
+
+  /* Format-dependent utilities                                              */
+  uint32_t    decimal32IsCanonical(const decimal32 *);
+  decimal32 * decimal32Canonical(decimal32 *, const decimal32 *);
 
 #endif
diff --git a/libdecnumber/dpd/decimal32Symbols.h b/libdecnumber/dpd/decimal32Symbols.h
new file mode 100644 (file)
index 0000000..de11934
--- /dev/null
@@ -0,0 +1,16 @@
+#if !defined(DECIMAL32SYMBOLS)
+#define DECIMAL32SYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decDigitsFromDPD __decDigitsFromDPD
+#define decDigitsToDPD __decDigitsToDPD
+#define decimal32Canonical __decimal32Canonical
+#define decimal32FromNumber __decimal32FromNumber
+#define decimal32FromString __decimal32FromString
+#define decimal32IsCanonical __decimal32IsCanonical
+#define decimal32ToEngString __decimal32ToEngString
+#define decimal32ToNumber __decimal32ToNumber
+#define decimal32ToString __decimal32ToString
+#endif
+
+#endif
index c1c1c7c9b09c95ddcf2992779816e0dcbcb4c380..359214e5dbe1cc6ac7339824688894a64e036fff 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal 64-bit format module for the decNumber C Library
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Decimal 64-bit format module for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
+/* ------------------------------------------------------------------ */
+/* Decimal 64-bit format module                                              */
 /* ------------------------------------------------------------------ */
 /* This module comprises the routines for decimal64 format numbers.   */
-/* Conversions are supplied to and from decNumber and String.         */
-/*                                                                    */
-/* No arithmetic routines are included; decNumber provides these.     */
-/*                                                                    */
-/* Error handling is the same as decNumber (qv.).                     */
+/* Conversions are supplied to and from decNumber and String.        */
+/*                                                                   */
+/* This is used when decNumber provides operations, either for all    */
+/* operations or as a proxy between decNumber and decSingle.         */
+/*                                                                   */
+/* Error handling is the same as decNumber (qv.).                    */
 /* ------------------------------------------------------------------ */
-#include <string.h>            /* [for memset/memcpy] */
-#include <stdio.h>             /* [for printf] */
+#include <string.h>          /* [for memset/memcpy] */
+#include <stdio.h>           /* [for printf] */
+
+#include "config.h"          /* GCC definitions */
+#define         DECNUMDIGITS 16      /* make decNumbers with space for 16 */
+#include "decNumber.h"       /* base number library */
+#include "decNumberLocal.h"   /* decNumber local types, etc. */
+#include "decimal64.h"       /* our primary include */
 
-#define  DECNUMDIGITS 16       /* we need decNumbers with space for 16 */
-#include "config.h"
-#include "decNumber.h"         /* base number library */
-#include "decNumberLocal.h"    /* decNumber local types, etc. */
-#include "decimal64.h"         /* our primary include */
-#include "decUtility.h"                /* utility routines */
+/* Utility routines and tables [in decimal64.c]; externs for C++ */
+/* DPD2BIN and the reverse are renamed to prevent link-time conflict */
+/* if decQuad is also built in the same executable */
+#define DPD2BIN DPD2BINx
+#define BIN2DPD BIN2DPDx
+extern const uInt COMBEXP[32], COMBMSD[32];
+extern const uShort DPD2BIN[1024];
+extern const uShort BIN2DPD[1000];
+extern const uByte  BIN2CHAR[4001];
+
+extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
+extern void decDigitsToDPD(const decNumber *, uInt *, Int);
 
 #if DECTRACE || DECCHECK
-void decimal64Show (const decimal64 *);        /* for debug */
-void decNumberShow (const decNumber *);        /* .. */
+void decimal64Show(const decimal64 *);           /* for debug */
+extern void decNumberShow(const decNumber *);    /* .. */
 #endif
 
 /* Useful macro */
 /* Clear a structure (e.g., a decNumber) */
 #define DEC_clear(d) memset(d, 0, sizeof(*d))
 
+/* define and include the tables to use for conversions */
+#define DEC_BIN2CHAR 1
+#define DEC_DPD2BIN  1
+#define DEC_BIN2DPD  1            /* used for all sizes */
+#include "decDPD.h"               /* lookup tables */
+
 /* ------------------------------------------------------------------ */
-/* decimal64FromNumber -- convert decNumber to decimal64              */
-/*                                                                    */
-/*   ds is the target decimal64                                       */
-/*   dn is the source number (assumed valid)                          */
-/*   set is the context, used only for reporting errors               */
-/*                                                                    */
+/* decimal64FromNumber -- convert decNumber to decimal64             */
+/*                                                                   */
+/*   ds is the target decimal64                                              */
+/*   dn is the source number (assumed valid)                         */
+/*   set is the context, used only for reporting errors                      */
+/*                                                                   */
 /* The set argument is used only for status reporting and for the     */
 /* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */
-/* digits or an overflow is detected).  If the exponent is out of the */
-/* valid range then Overflow or Underflow will be raised.             */
-/* After Underflow a subnormal result is possible.                    */
-/*                                                                    */
+/* digits or an overflow is detected). If the exponent is out of the */
+/* valid range then Overflow or Underflow will be raised.            */
+/* After Underflow a subnormal result is possible.                   */
+/*                                                                   */
 /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
 /* by reducing its exponent and multiplying the coefficient by a      */
 /* power of ten, or if the exponent on a zero had to be clamped.      */
 /* ------------------------------------------------------------------ */
-decimal64 *
-decimal64FromNumber (decimal64 * d64, const decNumber * dn, decContext * set)
-{
-  uInt status = 0;             /* status accumulator */
-  Int pad = 0;                 /* coefficient pad digits */
-  decNumber dw;                        /* work */
-  decContext dc;               /* .. */
-  uByte isneg = dn->bits & DECNEG;     /* non-0 if original sign set */
-  uInt comb, exp;              /* work */
-
-  /* If the number is finite, and has too many digits, or the exponent */
-  /* could be out of range then we reduce the number under the */
-  /* appropriate constraints */
-  if (!(dn->bits & DECSPECIAL))
-    {                          /* not a special value */
-      Int ae = dn->exponent + dn->digits - 1;  /* adjusted exponent */
-      if (dn->digits > DECIMAL64_Pmax  /* too many digits */
-         || ae > DECIMAL64_Emax        /* likely overflow */
-         || ae < DECIMAL64_Emin)
-       {                       /* likely underflow */
-         decContextDefault (&dc, DEC_INIT_DECIMAL64);  /* [no traps] */
-         dc.round = set->round;        /* use supplied rounding */
-         decNumberPlus (&dw, dn, &dc); /* (round and check) */
-         /* [this changes -0 to 0, but it will be restored below] */
-         status |= dc.status;  /* save status */
-         dn = &dw;             /* use the work number */
-       }
-      /* [this could have pushed number to Infinity or zero, so this */
-      /* rounding must be done before we generate the decimal64] */
-    }
+decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn,
+                               decContext *set) {
+  uInt status=0;                  /* status accumulator */
+  Int ae;                         /* adjusted exponent */
+  decNumber  dw;                  /* work */
+  decContext dc;                  /* .. */
+  uInt *pu;                       /* .. */
+  uInt comb, exp;                 /* .. */
+  uInt targar[2]={0, 0};          /* target 64-bit */
+  #define targhi targar[1]        /* name the word with the sign */
+  #define targlo targar[0]        /* and the other */
+
+  /* If the number has too many digits, or the exponent could be */
+  /* out of range then reduce the number under the appropriate */
+  /* constraints.  This could push the number to Infinity or zero, */
+  /* so this check and rounding must be done before generating the */
+  /* decimal64] */
+  ae=dn->exponent+dn->digits-1;                     /* [0 if special] */
+  if (dn->digits>DECIMAL64_Pmax                     /* too many digits */
+   || ae>DECIMAL64_Emax                             /* likely overflow */
+   || ae<DECIMAL64_Emin) {                  /* likely underflow */
+    decContextDefault(&dc, DEC_INIT_DECIMAL64); /* [no traps] */
+    dc.round=set->round;                    /* use supplied rounding */
+    decNumberPlus(&dw, dn, &dc);            /* (round and check) */
+    /* [this changes -0 to 0, so enforce the sign...] */
+    dw.bits|=dn->bits&DECNEG;
+    status=dc.status;                       /* save status */
+    dn=&dw;                                 /* use the work number */
+    } /* maybe out of range */
 
-  DEC_clear (d64);             /* clean the target */
-  if (dn->bits & DECSPECIAL)
-    {                          /* a special value */
-      uByte top;               /* work */
-      if (dn->bits & DECINF)
-       top = DECIMAL_Inf;
-      else
-       {                       /* sNaN or qNaN */
-         if ((*dn->lsu != 0 || dn->digits > 1) /* non-zero coefficient */
-             && (dn->digits < DECIMAL64_Pmax))
-           {                   /* coefficient fits */
-             decDensePackCoeff (dn, d64->bytes, sizeof (d64->bytes), 0);
-           }
-         if (dn->bits & DECNAN)
-           top = DECIMAL_NaN;
-         else
-           top = DECIMAL_sNaN;
+  if (dn->bits&DECSPECIAL) {                     /* a special value */
+    if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
+     else {                                      /* sNaN or qNaN */
+      if ((*dn->lsu!=0 || dn->digits>1)                  /* non-zero coefficient */
+       && (dn->digits<DECIMAL64_Pmax)) {         /* coefficient fits */
+       decDigitsToDPD(dn, targar, 0);
        }
-      d64->bytes[0] = top;
-    }
-  else if (decNumberIsZero (dn))
-    {                          /* a zero */
+      if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
+       else targhi|=DECIMAL_sNaN<<24;
+      } /* a NaN */
+    } /* special */
+
+   else { /* is finite */
+    if (decNumberIsZero(dn)) {              /* is a zero */
       /* set and clamp exponent */
-      if (dn->exponent < -DECIMAL64_Bias)
-       {
-         exp = 0;
-         status |= DEC_Clamped;
+      if (dn->exponent<-DECIMAL64_Bias) {
+       exp=0;                               /* low clamp */
+       status|=DEC_Clamped;
        }
-      else
-       {
-         exp = dn->exponent + DECIMAL64_Bias;  /* bias exponent */
-         if (exp > DECIMAL64_Ehigh)
-           {                   /* top clamp */
-             exp = DECIMAL64_Ehigh;
-             status |= DEC_Clamped;
-           }
+       else {
+       exp=dn->exponent+DECIMAL64_Bias;     /* bias exponent */
+       if (exp>DECIMAL64_Ehigh) {           /* top clamp */
+         exp=DECIMAL64_Ehigh;
+         status|=DEC_Clamped;
+         }
        }
-      comb = (exp >> 5) & 0x18;        /* combination field */
-      d64->bytes[0] = (uByte) (comb << 2);
-      exp &= 0xff;             /* remaining exponent bits */
-      decimal64SetExpCon (d64, exp);
-    }
-  else
-    {                          /* non-zero finite number */
-      uInt msd;                        /* work */
-
-      /* we have a dn that fits, but it may need to be padded */
-      exp = (uInt) (dn->exponent + DECIMAL64_Bias);    /* bias exponent */
-      if (exp > DECIMAL64_Ehigh)
-       {                       /* fold-down case */
-         pad = exp - DECIMAL64_Ehigh;
-         exp = DECIMAL64_Ehigh;        /* [to maximum] */
-         status |= DEC_Clamped;
+      comb=(exp>>5) & 0x18;            /* msd=0, exp top 2 bits .. */
+      }
+     else {                            /* non-zero finite number */
+      uInt msd;                                /* work */
+      Int pad=0;                       /* coefficient pad digits */
+
+      /* the dn is known to fit, but it may need to be padded */
+      exp=(uInt)(dn->exponent+DECIMAL64_Bias);   /* bias exponent */
+      if (exp>DECIMAL64_Ehigh) {                 /* fold-down case */
+       pad=exp-DECIMAL64_Ehigh;
+       exp=DECIMAL64_Ehigh;                      /* [to maximum] */
+       status|=DEC_Clamped;
        }
 
-      decDensePackCoeff (dn, d64->bytes, sizeof (d64->bytes), pad);
+      /* fastpath common case */
+      if (DECDPUN==3 && pad==0) {
+       uInt dpd[6]={0,0,0,0,0,0};
+       uInt i;
+       Int d=dn->digits;
+       for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]];
+       targlo =dpd[0];
+       targlo|=dpd[1]<<10;
+       targlo|=dpd[2]<<20;
+       if (dn->digits>6) {
+         targlo|=dpd[3]<<30;
+         targhi =dpd[3]>>2;
+         targhi|=dpd[4]<<8;
+         }
+       msd=dpd[5];                /* [did not really need conversion] */
+       }
+       else { /* general case */
+       decDigitsToDPD(dn, targar, pad);
+       /* save and clear the top digit */
+       msd=targhi>>18;
+       targhi&=0x0003ffff;
+       }
 
-      /* save and clear the top digit */
-      msd = ((unsigned) d64->bytes[1] >> 2) & 0x0f;
-      d64->bytes[1] &= 0x03;
       /* create the combination field */
-      if (msd >= 8)
-       comb = 0x18 | (msd & 0x01) | ((exp >> 7) & 0x06);
-      else
-       comb = (msd & 0x07) | ((exp >> 5) & 0x18);
-      d64->bytes[0] = (uByte) (comb << 2);
-      exp &= 0xff;             /* remaining exponent bits */
-      decimal64SetExpCon (d64, exp);
-    }
+      if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01);
+            else comb=((exp>>5) & 0x18) | msd;
+      }
+    targhi|=comb<<26;             /* add combination field .. */
+    targhi|=(exp&0xff)<<18;       /* .. and exponent continuation */
+    } /* finite */
+
+  if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
 
-  if (isneg)
-    decimal64SetSign (d64, 1);
-  if (status != 0)
-    decContextSetStatus (set, status); /* pass on status */
+  /* now write to storage; this is now always endian */
+  pu=(uInt *)d64->bytes;          /* overlay */
+  if (DECLITEND) {
+    pu[0]=targar[0];              /* directly store the low int */
+    pu[1]=targar[1];              /* then the high int */
+    }
+   else {
+    pu[0]=targar[1];              /* directly store the high int */
+    pu[1]=targar[0];              /* then the low int */
+    }
 
-  /*decimal64Show(d64); */
+  if (status!=0) decContextSetStatus(set, status); /* pass on status */
+  /* decimal64Show(d64); */
   return d64;
-}
+  } /* decimal64FromNumber */
 
 /* ------------------------------------------------------------------ */
-/* decimal64ToNumber -- convert decimal64 to decNumber                */
-/*   d64 is the source decimal64                                      */
-/*   dn is the target number, with appropriate space                  */
-/* No error is possible.                                              */
+/* decimal64ToNumber -- convert decimal64 to decNumber               */
+/*   d64 is the source decimal64                                     */
+/*   dn is the target number, with appropriate space                 */
+/* No error is possible.                                             */
 /* ------------------------------------------------------------------ */
-decNumber *
-decimal64ToNumber (const decimal64 * d64, decNumber * dn)
-{
-  uInt msd;                    /* coefficient MSD */
-  decimal64 wk;                        /* working copy, if needed */
-  uInt top = d64->bytes[0] & 0x7f;     /* top byte, less sign bit */
-  decNumberZero (dn);          /* clean target */
-  /* set the sign if negative */
-  if (decimal64Sign (d64))
-    dn->bits = DECNEG;
-
-  if (top >= 0x78)
-    {                          /* is a special */
-      if ((top & 0x7c) == (DECIMAL_Inf & 0x7c))
-       dn->bits |= DECINF;
-      else if ((top & 0x7e) == (DECIMAL_NaN & 0x7e))
-       dn->bits |= DECNAN;
-      else
-       dn->bits |= DECSNAN;
-      msd = 0;                 /* no top digit */
+decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) {
+  uInt msd;                       /* coefficient MSD */
+  uInt exp;                       /* exponent top two bits */
+  uInt comb;                      /* combination field */
+  const uInt *pu;                 /* work */
+  Int  need;                      /* .. */
+  uInt sourar[2];                 /* source 64-bit */
+  #define sourhi sourar[1]        /* name the word with the sign */
+  #define sourlo sourar[0]        /* and the lower word */
+
+  /* load source from storage; this is endian */
+  pu=(const uInt *)d64->bytes;    /* overlay */
+  if (DECLITEND) {
+    sourlo=pu[0];                 /* directly load the low int */
+    sourhi=pu[1];                 /* then the high int */
     }
-  else
-    {                          /* have a finite number */
-      uInt comb = top >> 2;    /* combination field */
-      uInt exp;                        /* exponent */
-
-      if (comb >= 0x18)
-       {
-         msd = 8 + (comb & 0x01);
-         exp = (comb & 0x06) << 7;     /* MSBs */
-       }
-      else
-       {
-         msd = comb & 0x07;
-         exp = (comb & 0x18) << 5;
-       }
-      dn->exponent = exp + decimal64ExpCon (d64) - DECIMAL64_Bias;     /* remove bias */
+   else {
+    sourhi=pu[0];                 /* directly load the high int */
+    sourlo=pu[1];                 /* then the low int */
     }
 
-  /* get the coefficient, unless infinite */
-  if (!(dn->bits & DECINF))
-    {
-      Int bunches = DECIMAL64_Pmax / 3;        /* coefficient full bunches to convert */
-      Int odd = 0;             /* assume MSD is 0 (no odd bunch) */
-      if (msd != 0)
-       {                       /* coefficient has leading non-0 digit */
-         /* make a copy of the decimal64, with an extra bunch which has */
-         /* the top digit ready for conversion */
-         wk = *d64;            /* take a copy */
-         wk.bytes[0] = 0;      /* clear all but coecon */
-         wk.bytes[1] &= 0x03;  /* .. */
-         wk.bytes[1] |= (msd << 2);    /* and prefix MSD */
-         odd++;                /* indicate the extra */
-         d64 = &wk;            /* use the work copy */
-       }
-      decDenseUnpackCoeff (d64->bytes, sizeof (d64->bytes), dn, bunches, odd);
+  comb=(sourhi>>26)&0x1f;         /* combination field */
+
+  decNumberZero(dn);              /* clean number */
+  if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */
+
+  msd=COMBMSD[comb];              /* decode the combination field */
+  exp=COMBEXP[comb];              /* .. */
+
+  if (exp==3) {                           /* is a special */
+    if (msd==0) {
+      dn->bits|=DECINF;
+      return dn;                  /* no coefficient needed */
+      }
+    else if (sourhi&0x02000000) dn->bits|=DECSNAN;
+    else dn->bits|=DECNAN;
+    msd=0;                        /* no top digit */
+    }
+   else {                         /* is a finite number */
+    dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; /* unbiased */
     }
+
+  /* get the coefficient */
+  sourhi&=0x0003ffff;             /* clean coefficient continuation */
+  if (msd) {                      /* non-zero msd */
+    sourhi|=msd<<18;              /* prefix to coefficient */
+    need=6;                       /* process 6 declets */
+    }
+   else { /* msd=0 */
+    if (!sourhi) {                /* top word 0 */
+      if (!sourlo) return dn;     /* easy: coefficient is 0 */
+      need=3;                     /* process at least 3 declets */
+      if (sourlo&0xc0000000) need++; /* process 4 declets */
+      /* [could reduce some more, here] */
+      }
+     else {                       /* some bits in top word, msd=0 */
+      need=4;                     /* process at least 4 declets */
+      if (sourhi&0x0003ff00) need++; /* top declet!=0, process 5 */
+      }
+    } /*msd=0 */
+
+  decDigitsFromDPD(dn, sourar, need);  /* process declets */
   return dn;
-}
+  } /* decimal64ToNumber */
+
 
 /* ------------------------------------------------------------------ */
-/* to-scientific-string -- conversion to numeric string               */
-/* to-engineering-string -- conversion to numeric string              */
-/*                                                                    */
-/*   decimal64ToString(d64, string);                                  */
-/*   decimal64ToEngString(d64, string);                               */
-/*                                                                    */
-/*  d64 is the decimal64 format number to convert                     */
-/*  string is the string where the result will be laid out            */
-/*                                                                    */
-/*  string must be at least 24 characters                             */
-/*                                                                    */
-/*  No error is possible, and no status can be set.                   */
+/* to-scientific-string -- conversion to numeric string                      */
+/* to-engineering-string -- conversion to numeric string             */
+/*                                                                   */
+/*   decimal64ToString(d64, string);                                 */
+/*   decimal64ToEngString(d64, string);                                      */
+/*                                                                   */
+/*  d64 is the decimal64 format number to convert                    */
+/*  string is the string where the result will be laid out           */
+/*                                                                   */
+/*  string must be at least 24 characters                            */
+/*                                                                   */
+/*  No error is possible, and no status can be set.                  */
 /* ------------------------------------------------------------------ */
-char *
-decimal64ToString (const decimal64 * d64, char *string)
-{
-  decNumber dn;                        /* work */
-  decimal64ToNumber (d64, &dn);
-  decNumberToString (&dn, string);
+char * decimal64ToEngString(const decimal64 *d64, char *string){
+  decNumber dn;                                /* work */
+  decimal64ToNumber(d64, &dn);
+  decNumberToEngString(&dn, string);
   return string;
-}
-
-char *
-decimal64ToEngString (const decimal64 * d64, char *string)
-{
-  decNumber dn;                        /* work */
-  decimal64ToNumber (d64, &dn);
-  decNumberToEngString (&dn, string);
+  } /* decimal64ToEngString */
+
+char * decimal64ToString(const decimal64 *d64, char *string){
+  uInt msd;                       /* coefficient MSD */
+  Int  exp;                       /* exponent top two bits or full */
+  uInt comb;                      /* combination field */
+  char *cstart;                           /* coefficient start */
+  char *c;                        /* output pointer in string */
+  const uInt *pu;                 /* work */
+  char *s, *t;                    /* .. (source, target) */
+  Int  dpd;                       /* .. */
+  Int  pre, e;                    /* .. */
+  const uByte *u;                 /* .. */
+
+  uInt sourar[2];                 /* source 64-bit */
+  #define sourhi sourar[1]        /* name the word with the sign */
+  #define sourlo sourar[0]        /* and the lower word */
+
+  /* load source from storage; this is endian */
+  pu=(const uInt *)d64->bytes;    /* overlay */
+  if (DECLITEND) {
+    sourlo=pu[0];                 /* directly load the low int */
+    sourhi=pu[1];                 /* then the high int */
+    }
+   else {
+    sourhi=pu[0];                 /* directly load the high int */
+    sourlo=pu[1];                 /* then the low int */
+    }
+
+  c=string;                       /* where result will go */
+  if (((Int)sourhi)<0) *c++='-';   /* handle sign */
+
+  comb=(sourhi>>26)&0x1f;         /* combination field */
+  msd=COMBMSD[comb];              /* decode the combination field */
+  exp=COMBEXP[comb];              /* .. */
+
+  if (exp==3) {
+    if (msd==0) {                 /* infinity */
+      strcpy(c,          "Inf");
+      strcpy(c+3, "inity");
+      return string;              /* easy */
+      }
+    if (sourhi&0x02000000) *c++='s'; /* sNaN */
+    strcpy(c, "NaN");             /* complete word */
+    c+=3;                         /* step past */
+    if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; /* zero payload */
+    /* otherwise drop through to add integer; set correct exp */
+    exp=0; msd=0;                 /* setup for following code */
+    }
+   else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias;
+
+  /* convert 16 digits of significand to characters */
+  cstart=c;                       /* save start of coefficient */
+  if (msd) *c++='0'+(char)msd;    /* non-zero most significant digit */
+
+  /* Now decode the declets.  After extracting each one, it is */
+  /* decoded to binary and then to a 4-char sequence by table lookup; */
+  /* the 4-chars are a 1-char length (significant digits, except 000 */
+  /* has length 0).  This allows us to left-align the first declet */
+  /* with non-zero content, then remaining ones are full 3-char */
+  /* length.  We use fixed-length memcpys because variable-length */
+  /* causes a subroutine call in GCC.  (These are length 4 for speed */
+  /* and are safe because the array has an extra terminator byte.) */
+  #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                          \
+                  if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
+                   else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
+
+  dpd=(sourhi>>8)&0x3ff;                    /* declet 1 */
+  dpd2char;
+  dpd=((sourhi&0xff)<<2) | (sourlo>>30);     /* declet 2 */
+  dpd2char;
+  dpd=(sourlo>>20)&0x3ff;                   /* declet 3 */
+  dpd2char;
+  dpd=(sourlo>>10)&0x3ff;                   /* declet 4 */
+  dpd2char;
+  dpd=(sourlo)&0x3ff;                       /* declet 5 */
+  dpd2char;
+
+  if (c==cstart) *c++='0';        /* all zeros -- make 0 */
+
+  if (exp==0) {                           /* integer or NaN case -- easy */
+    *c='\0';                      /* terminate */
+    return string;
+    }
+
+  /* non-0 exponent */
+  e=0;                            /* assume no E */
+  pre=c-cstart+exp;
+  /* [here, pre-exp is the digits count (==1 for zero)] */
+  if (exp>0 || pre<-5) {          /* need exponential form */
+    e=pre-1;                      /* calculate E value */
+    pre=1;                        /* assume one digit before '.' */
+    } /* exponential form */
+
+  /* modify the coefficient, adding 0s, '.', and E+nn as needed */
+  s=c-1;                          /* source (LSD) */
+  if (pre>0) {                    /* ddd.ddd (plain), perhaps with E */
+    char *dotat=cstart+pre;
+    if (dotat<c) {                /* if embedded dot needed... */
+      t=c;                             /* target */
+      for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
+      *t='.';                          /* insert the dot */
+      c++;                             /* length increased by one */
+      }
+
+    /* finally add the E-part, if needed; it will never be 0, and has */
+    /* a maximum length of 3 digits */
+    if (e!=0) {
+      *c++='E';                           /* starts with E */
+      *c++='+';                           /* assume positive */
+      if (e<0) {
+       *(c-1)='-';                /* oops, need '-' */
+       e=-e;                      /* uInt, please */
+       }
+      u=&BIN2CHAR[e*4];                   /* -> length byte */
+      memcpy(c, u+4-*u, 4);       /* copy fixed 4 characters [is safe] */
+      c+=*u;                      /* bump pointer appropriately */
+      }
+    *c='\0';                      /* add terminator */
+    /*printf("res %s\n", string); */
+    return string;
+    } /* pre>0 */
+
+  /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
+  t=c+1-pre;
+  *(t+1)='\0';                         /* can add terminator now */
+  for (; s>=cstart; s--, t--) *t=*s;   /* shift whole coefficient right */
+  c=cstart;
+  *c++='0';                            /* always starts with 0. */
+  *c++='.';
+  for (; pre<0; pre++) *c++='0';       /* add any 0's after '.' */
+  /*printf("res %s\n", string); */
   return string;
-}
+  } /* decimal64ToString */
 
 /* ------------------------------------------------------------------ */
-/* to-number -- conversion from numeric string                        */
-/*                                                                    */
-/*   decimal64FromString(result, string, set);                        */
-/*                                                                    */
+/* to-number -- conversion from numeric string                       */
+/*                                                                   */
+/*   decimal64FromString(result, string, set);                       */
+/*                                                                   */
 /*  result  is the decimal64 format number which gets the result of   */
-/*          the conversion                                            */
+/*         the conversion                                            */
 /*  *string is the character string which should contain a valid      */
-/*          number (which may be a special value)                     */
-/*  set     is the context                                            */
-/*                                                                    */
+/*         number (which may be a special value)                     */
+/*  set            is the context                                            */
+/*                                                                   */
 /* The context is supplied to this routine is used for error handling */
 /* (setting of status and traps) and for the rounding mode, only.     */
 /* If an error occurs, the result will be a valid decimal64 NaN.      */
 /* ------------------------------------------------------------------ */
-decimal64 *
-decimal64FromString (decimal64 * result, const char *string, decContext * set)
-{
-  decContext dc;               /* work */
-  decNumber dn;                        /* .. */
+decimal64 * decimal64FromString(decimal64 *result, const char *string,
+                               decContext *set) {
+  decContext dc;                            /* work */
+  decNumber dn;                                     /* .. */
 
-  decContextDefault (&dc, DEC_INIT_DECIMAL64); /* no traps, please */
-  dc.round = set->round;       /* use supplied rounding */
+  decContextDefault(&dc, DEC_INIT_DECIMAL64); /* no traps, please */
+  dc.round=set->round;                       /* use supplied rounding */
 
-  decNumberFromString (&dn, string, &dc);      /* will round if needed */
+  decNumberFromString(&dn, string, &dc);     /* will round if needed */
 
-  decimal64FromNumber (result, &dn, &dc);
-  if (dc.status != 0)
-    {                          /* something happened */
-      decContextSetStatus (set, dc.status);    /* .. pass it on */
+  decimal64FromNumber(result, &dn, &dc);
+  if (dc.status!=0) {                       /* something happened */
+    decContextSetStatus(set, dc.status);     /* .. pass it on */
     }
   return result;
-}
+  } /* decimal64FromString */
+
+/* ------------------------------------------------------------------ */
+/* decimal64IsCanonical -- test whether encoding is canonical        */
+/*   d64 is the source decimal64                                     */
+/*   returns 1 if the encoding of d64 is canonical, 0 otherwise              */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+uint32_t decimal64IsCanonical(const decimal64 *d64) {
+  decNumber dn;                                /* work */
+  decimal64 canon;                     /* .. */
+  decContext dc;                       /* .. */
+  decContextDefault(&dc, DEC_INIT_DECIMAL64);
+  decimal64ToNumber(d64, &dn);
+  decimal64FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
+  return memcmp(d64, &canon, DECIMAL64_Bytes)==0;
+  } /* decimal64IsCanonical */
+
+/* ------------------------------------------------------------------ */
+/* decimal64Canonical -- copy an encoding, ensuring it is canonical   */
+/*   d64 is the source decimal64                                     */
+/*   result is the target (may be the same decimal64)                */
+/*   returns result                                                  */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) {
+  decNumber dn;                                /* work */
+  decContext dc;                       /* .. */
+  decContextDefault(&dc, DEC_INIT_DECIMAL64);
+  decimal64ToNumber(d64, &dn);
+  decimal64FromNumber(result, &dn, &dc);/* result will now be canonical */
+  return result;
+  } /* decimal64Canonical */
 
 #if DECTRACE || DECCHECK
+/* Macros for accessing decimal64 fields.  These assume the
+   argument is a reference (pointer) to the decimal64 structure,
+   and the decimal64 is in network byte order (big-endian) */
+/* Get sign */
+#define decimal64Sign(d)       ((unsigned)(d)->bytes[0]>>7)
+
+/* Get combination field */
+#define decimal64Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
+
+/* Get exponent continuation [does not remove bias] */
+#define decimal64ExpCon(d)     ((((d)->bytes[0] & 0x03)<<6)          \
+                            | ((unsigned)(d)->bytes[1]>>2))
+
+/* Set sign [this assumes sign previously 0] */
+#define decimal64SetSign(d, b) {                                     \
+  (d)->bytes[0]|=((unsigned)(b)<<7);}
+
+/* Set exponent continuation [does not apply bias] */
+/* This assumes range has been checked and exponent previously 0; */
+/* type of exponent must be unsigned */
+#define decimal64SetExpCon(d, e) {                                   \
+  (d)->bytes[0]|=(uint8_t)((e)>>6);                                  \
+  (d)->bytes[1]|=(uint8_t)(((e)&0x3F)<<2);}
+
 /* ------------------------------------------------------------------ */
-/* decimal64Show -- display a single in hexadecimal [debug aid]       */
-/*   d64 -- the number to show                                        */
+/* decimal64Show -- display a decimal64 in hexadecimal [debug aid]    */
+/*   d64 -- the number to show                                       */
 /* ------------------------------------------------------------------ */
 /* Also shows sign/cob/expconfields extracted */
-void
-decimal64Show (const decimal64 * d64)
-{
-  char buf[DECIMAL64_Bytes * 2 + 1];
-  Int i, j;
-  j = 0;
-  for (i = 0; i < DECIMAL64_Bytes; i++)
-    {
-      sprintf (&buf[j], "%02x", d64->bytes[i]);
-      j = j + 2;
+void decimal64Show(const decimal64 *d64) {
+  char buf[DECIMAL64_Bytes*2+1];
+  Int i, j=0;
+
+  if (DECLITEND) {
+    for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
+      sprintf(&buf[j], "%02x", d64->bytes[7-i]);
+      }
+    printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
+          d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f,
+          ((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2));
+    }
+   else { /* big-endian */
+    for (i=0; i<DECIMAL64_Bytes; i++, j+=2) {
+      sprintf(&buf[j], "%02x", d64->bytes[i]);
+      }
+    printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
+          decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64));
     }
-  printf (" D64> %s [S:%d Cb:%02x E:%d]\n", buf,
-         decimal64Sign (d64), decimal64Comb (d64), decimal64ExpCon (d64));
-}
+  } /* decimal64Show */
 #endif
+
+/* ================================================================== */
+/* Shared utility routines and tables                                */
+/* ================================================================== */
+/* define and include the conversion tables to use for shared code */
+#if DECDPUN==3
+  #define DEC_DPD2BIN 1
+#else
+  #define DEC_DPD2BCD 1
+#endif
+#include "decDPD.h"          /* lookup tables */
+
+/* The maximum number of decNumberUnits needed for a working copy of */
+/* the units array is the ceiling of digits/DECDPUN, where digits is */
+/* the maximum number of digits in any of the formats for which this */
+/* is used.  decimal128.h must not be included in this module, so, as */
+/* a very special case, that number is defined as a literal here. */
+#define DECMAX754   34
+#define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN)
+
+/* ------------------------------------------------------------------ */
+/* Combination field lookup tables (uInts to save measurable work)    */
+/*                                                                   */
+/*     COMBEXP - 2-bit most-significant-bits of exponent             */
+/*               [11 if an Infinity or NaN]                          */
+/*     COMBMSD - 4-bit most-significant-digit                        */
+/*               [0=Infinity, 1=NaN if COMBEXP=11]                   */
+/*                                                                   */
+/* Both are indexed by the 5-bit combination field (0-31)            */
+/* ------------------------------------------------------------------ */
+const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0,
+                       1, 1, 1, 1, 1, 1, 1, 1,
+                       2, 2, 2, 2, 2, 2, 2, 2,
+                       0, 0, 1, 1, 2, 2, 3, 3};
+const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7,
+                       0, 1, 2, 3, 4, 5, 6, 7,
+                       0, 1, 2, 3, 4, 5, 6, 7,
+                       8, 9, 8, 9, 8, 9, 0, 1};
+
+/* ------------------------------------------------------------------ */
+/* decDigitsToDPD -- pack coefficient into DPD form                  */
+/*                                                                   */
+/*   dn          is the source number (assumed valid, max DECMAX754 digits)  */
+/*   targ is 1, 2, or 4-element uInt array, which the caller must     */
+/*       have cleared to zeros                                       */
+/*   shift is the number of 0 digits to add on the right (normally 0) */
+/*                                                                   */
+/* The coefficient must be known small enough to fit.  The full              */
+/* coefficient is copied, including the leading 'odd' digit.  This    */
+/* digit is retrieved and packed into the combination field by the    */
+/* caller.                                                           */
+/*                                                                   */
+/* The target uInts are altered only as necessary to receive the      */
+/* digits of the decNumber.  When more than one uInt is needed, they  */
+/* are filled from left to right (that is, the uInt at offset 0 will  */
+/* end up with the least-significant digits).                        */
+/*                                                                   */
+/* shift is used for 'fold-down' padding.                            */
+/*                                                                   */
+/* No error is possible.                                             */
+/* ------------------------------------------------------------------ */
+#if DECDPUN<=4
+/* Constant multipliers for divide-by-power-of five using reciprocal */
+/* multiply, after removing powers of 2 by shifting, and final shift */
+/* of 17 [we only need up to **4] */
+static const uInt multies[]={131073, 26215, 5243, 1049, 210};
+/* QUOT10 -- macro to return the quotient of unit u divided by 10**n */
+#define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17)
+#endif
+void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) {
+  Int  cut;                  /* work */
+  Int  n;                    /* output bunch counter */
+  Int  digits=dn->digits;     /* digit countdown */
+  uInt dpd;                  /* densely packed decimal value */
+  uInt bin;                  /* binary value 0-999 */
+  uInt *uout=targ;           /* -> current output uInt */
+  uInt uoff=0;               /* -> current output offset [from right] */
+  const Unit *inu=dn->lsu;    /* -> current input unit */
+  Unit uar[DECMAXUNITS];     /* working copy of units, iff shifted */
+  #if DECDPUN!=3             /* not fast path */
+    Unit in;                 /* current unit */
+  #endif
+
+  if (shift!=0) {            /* shift towards most significant required */
+    /* shift the units array to the left by pad digits and copy */
+    /* [this code is a special case of decShiftToMost, which could */
+    /* be used instead if exposed and the array were copied first] */
+    const Unit *source;                        /* .. */
+    Unit  *target, *first;             /* .. */
+    uInt  next=0;                      /* work */
+
+    source=dn->lsu+D2U(digits)-1;      /* where msu comes from */
+    target=uar+D2U(digits)-1+D2U(shift);/* where upper part of first cut goes */
+    cut=DECDPUN-MSUDIGITS(shift);      /* where to slice */
+    if (cut==0) {                      /* unit-boundary case */
+      for (; source>=dn->lsu; source--, target--) *target=*source;
+      }
+     else {
+      first=uar+D2U(digits+shift)-1;   /* where msu will end up */
+      for (; source>=dn->lsu; source--, target--) {
+       /* split the source Unit and accumulate remainder for next */
+       #if DECDPUN<=4
+         uInt quot=QUOT10(*source, cut);
+         uInt rem=*source-quot*DECPOWERS[cut];
+         next+=quot;
+       #else
+         uInt rem=*source%DECPOWERS[cut];
+         next+=*source/DECPOWERS[cut];
+       #endif
+       if (target<=first) *target=(Unit)next; /* write to target iff valid */
+       next=rem*DECPOWERS[DECDPUN-cut];       /* save remainder for next Unit */
+       }
+      } /* shift-move */
+    /* propagate remainder to one below and clear the rest */
+    for (; target>=uar; target--) {
+      *target=(Unit)next;
+      next=0;
+      }
+    digits+=shift;                /* add count (shift) of zeros added */
+    inu=uar;                      /* use units in working array */
+    }
+
+  /* now densely pack the coefficient into DPD declets */
+
+  #if DECDPUN!=3                  /* not fast path */
+    in=*inu;                      /* current unit */
+    cut=0;                        /* at lowest digit */
+    bin=0;                        /* [keep compiler quiet] */
+  #endif
+
+  for(n=0; digits>0; n++) {       /* each output bunch */
+    #if DECDPUN==3                /* fast path, 3-at-a-time */
+      bin=*inu;                           /* 3 digits ready for convert */
+      digits-=3;                  /* [may go negative] */
+      inu++;                      /* may need another */
+
+    #else                         /* must collect digit-by-digit */
+      Unit dig;                           /* current digit */
+      Int j;                      /* digit-in-declet count */
+      for (j=0; j<3; j++) {
+       #if DECDPUN<=4
+         Unit temp=(Unit)((uInt)(in*6554)>>16);
+         dig=(Unit)(in-X10(temp));
+         in=temp;
+       #else
+         dig=in%10;
+         in=in/10;
+       #endif
+       if (j==0) bin=dig;
+        else if (j==1)  bin+=X10(dig);
+        else /* j==2 */ bin+=X100(dig);
+       digits--;
+       if (digits==0) break;      /* [also protects *inu below] */
+       cut++;
+       if (cut==DECDPUN) {inu++; in=*inu; cut=0;}
+       }
+    #endif
+    /* here there are 3 digits in bin, or have used all input digits */
+
+    dpd=BIN2DPD[bin];
+
+    /* write declet to uInt array */
+    *uout|=dpd<<uoff;
+    uoff+=10;
+    if (uoff<32) continue;        /* no uInt boundary cross */
+    uout++;
+    uoff-=32;
+    *uout|=dpd>>(10-uoff);        /* collect top bits */
+    } /* n declets */
+  return;
+  } /* decDigitsToDPD */
+
+/* ------------------------------------------------------------------ */
+/* decDigitsFromDPD -- unpack a format's coefficient                 */
+/*                                                                   */
+/*   dn is the target number, with 7, 16, or 34-digit space.         */
+/*   sour is a 1, 2, or 4-element uInt array containing only declets  */
+/*   declets is the number of (right-aligned) declets in sour to      */
+/*     be processed.  This may be 1 more than the obvious number in   */
+/*     a format, as any top digit is prefixed to the coefficient      */
+/*     continuation field.  It also may be as small as 1, as the      */
+/*     caller may pre-process leading zero declets.                  */
+/*                                                                   */
+/* When doing the 'extra declet' case care is taken to avoid writing  */
+/* extra digits when there are leading zeros, as these could overflow */
+/* the units array when DECDPUN is not 3.                            */
+/*                                                                   */
+/* The target uInts are used only as necessary to process declets     */
+/* declets into the decNumber. When more than one uInt is needed,    */
+/* they are used from left to right (that is, the uInt at offset 0    */
+/* provides the least-significant digits).                           */
+/*                                                                   */
+/* dn->digits is set, but not the sign or exponent.                  */
+/* No error is possible [the redundant 888 codes are allowed].       */
+/* ------------------------------------------------------------------ */
+void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) {
+
+  uInt dpd;                       /* collector for 10 bits */
+  Int  n;                         /* counter */
+  Unit *uout=dn->lsu;             /* -> current output unit */
+  Unit *last=uout;                /* will be unit containing msd */
+  const uInt *uin=sour;                   /* -> current input uInt */
+  uInt uoff=0;                    /* -> current input offset [from right] */
+
+  #if DECDPUN!=3
+  uInt bcd;                       /* BCD result */
+  uInt nibble;                    /* work */
+  Unit out=0;                     /* accumulator */
+  Int  cut=0;                     /* power of ten in current unit */
+  #endif
+  #if DECDPUN>4
+  uInt const *pow;                /* work */
+  #endif
+
+  /* Expand the densely-packed integer, right to left */
+  for (n=declets-1; n>=0; n--) {   /* count down declets of 10 bits */
+    dpd=*uin>>uoff;
+    uoff+=10;
+    if (uoff>32) {                /* crossed uInt boundary */
+      uin++;
+      uoff-=32;
+      dpd|=*uin<<(10-uoff);       /* get waiting bits */
+      }
+    dpd&=0x3ff;                           /* clear uninteresting bits */
+
+  #if DECDPUN==3
+    if (dpd==0) *uout=0;
+     else {
+      *uout=DPD2BIN[dpd];         /* convert 10 bits to binary 0-999 */
+      last=uout;                  /* record most significant unit */
+      }
+    uout++;
+    } /* n */
+
+  #else /* DECDPUN!=3 */
+    if (dpd==0) {                 /* fastpath [e.g., leading zeros] */
+      /* write out three 0 digits (nibbles); out may have digit(s) */
+      cut++;
+      if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
+      if (n==0) break;            /* [as below, works even if MSD=0] */
+      cut++;
+      if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
+      cut++;
+      if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
+      continue;
+      }
+
+    bcd=DPD2BCD[dpd];             /* convert 10 bits to 12 bits BCD */
+
+    /* now accumulate the 3 BCD nibbles into units */
+    nibble=bcd & 0x00f;
+    if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
+    cut++;
+    if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
+    bcd>>=4;
+
+    /* if this is the last declet and the remaining nibbles in bcd */
+    /* are 00 then process no more nibbles, because this could be */
+    /* the 'odd' MSD declet and writing any more Units would then */
+    /* overflow the unit array */
+    if (n==0 && !bcd) break;
+
+    nibble=bcd & 0x00f;
+    if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
+    cut++;
+    if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
+    bcd>>=4;
+
+    nibble=bcd & 0x00f;
+    if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]);
+    cut++;
+    if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;}
+    } /* n */
+  if (cut!=0) {                                /* some more left over */
+    *uout=out;                         /* write out final unit */
+    if (out) last=uout;                        /* and note if non-zero */
+    }
+  #endif
+
+  /* here, last points to the most significant unit with digits; */
+  /* inspect it to get the final digits count -- this is essentially */
+  /* the same code as decGetDigits in decNumber.c */
+  dn->digits=(last-dn->lsu)*DECDPUN+1; /* floor of digits, plus */
+                                       /* must be at least 1 digit */
+  #if DECDPUN>1
+  if (*last<10) return;                        /* common odd digit or 0 */
+  dn->digits++;                                /* must be 2 at least */
+  #if DECDPUN>2
+  if (*last<100) return;               /* 10-99 */
+  dn->digits++;                                /* must be 3 at least */
+  #if DECDPUN>3
+  if (*last<1000) return;              /* 100-999 */
+  dn->digits++;                                /* must be 4 at least */
+  #if DECDPUN>4
+  for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++;
+  #endif
+  #endif
+  #endif
+  #endif
+  return;
+  } /*decDigitsFromDPD */
index fb7339512dcaaaea6c569408a63e876a09481fe9..549b626536c4dcd6afc0b20713cc49b06bd906c4 100644 (file)
@@ -1,5 +1,5 @@
-/* Decimal 64-bit format module header for the decNumber C Library
-   Copyright (C) 2005 Free Software Foundation, Inc.
+/* Decimal 64-bit format module header for the decNumber C Library.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    Contributed by IBM Corporation.  Author Mike Cowlishaw.
 
    This file is part of GCC.
    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-#if !defined(DECIMAL64)
-#define DECIMAL64
-#define DEC64NAME     "decimal64"      /* Short name */
-#define DEC64FULLNAME "Decimal 64-bit Number"  /* Verbose name */
-#define DEC64AUTHOR   "Mike Cowlishaw" /* Who to blame */
-
-#if defined(DECIMAL32)
-#error decimal64.h must precede decimal32.h for correct DECNUMDIGITS
-#endif
+/* ------------------------------------------------------------------ */
+/* Decimal 64-bit format module header                               */
+/* ------------------------------------------------------------------ */
 
-  /* parameters for decimal64s */
-#define DECIMAL64_Bytes  8     /* length */
-#define DECIMAL64_Pmax   16    /* maximum precision (digits) */
-#define DECIMAL64_Emax   384   /* maximum adjusted exponent */
-#define DECIMAL64_Emin  -383   /* minimum adjusted exponent */
-#define DECIMAL64_Bias   398   /* bias for the exponent */
-#define DECIMAL64_String 24    /* maximum string length, +1 */
-  /* highest biased exponent (Elimit-1) */
-#define DECIMAL64_Ehigh  (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1)
-
-#ifndef DECNUMDIGITS
-#define DECNUMDIGITS DECIMAL64_Pmax    /* size if not already defined */
-#endif
-#ifndef DECNUMBER
-#include "decNumber.h"         /* context and number library */
-#endif
-
-  /* Decimal 64-bit type, accessible by bytes */
-typedef struct
-{
-  uint8_t bytes[DECIMAL64_Bytes];      /* decimal64: 1, 5, 8, 50 bits */
-} decimal64;
-
-  /* special values [top byte excluding sign bit; last two bits are
-     don't-care for Infinity on input, last bit don't-care for NaN] */
-#if !defined(DECIMAL_NaN)
-#define DECIMAL_NaN     0x7c   /* 0 11111 00 NaN */
-#define DECIMAL_sNaN    0x7e   /* 0 11111 10 sNaN */
-#define DECIMAL_Inf     0x78   /* 0 11110 00 Infinity */
-#endif
-
-  /* Macros for accessing decimal64 fields.  These assume the argument
-     is a reference (pointer) to the decimal64 structure */
-  /* Get sign */
-#define decimal64Sign(d)       ((unsigned)(d)->bytes[0]>>7)
-
-  /* Get combination field */
-#define decimal64Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
-
-  /* Get exponent continuation [does not remove bias] */
-#define decimal64ExpCon(d)     ((((d)->bytes[0] & 0x03)<<6)         \
-                               | ((unsigned)(d)->bytes[1]>>2))
-
-  /* Set sign [this assumes sign previously 0] */
-#define decimal64SetSign(d, b) {                                    \
-    (d)->bytes[0]|=((unsigned)(b)<<7);}
-
-  /* Clear sign */
-#define decimal64ClearSign(d) {(d)->bytes[0]&=~0x80;}
-
-  /* Flip sign */
-#define decimal64FlipSign(d) {(d)->bytes[0]^=0x80;}
-
-  /* Set exponent continuation [does not apply bias] */
-  /* This assumes range has been checked and exponent previously 0; type */
-  /* of exponent must be unsigned */
-#define decimal64SetExpCon(d, e) {                                  \
-    (d)->bytes[0]|=(uint8_t)((e)>>6);                                 \
-    (d)->bytes[1]|=(uint8_t)(((e)&0x3F)<<2);}
-
-  /* ------------------------------------------------------------------ */
-  /* Routines                                                           */
-  /* ------------------------------------------------------------------ */
-
-#ifdef IN_LIBGCC2
-#ifndef decimal64FromString
-#define decimal64FromString __decimal64FromString
-#define decimal64ToString __decimal64ToString
-#define decimal64ToEngString __decimal64ToEngString
-#define decimal64FromNumber __decimal64FromNumber
-#define decimal64ToNumber __decimal64ToNumber
-#endif
-#endif
-
-  /* String conversions */
-decimal64 *decimal64FromString (decimal64 *, const char *, decContext *);
-char *decimal64ToString (const decimal64 *, char *);
-char *decimal64ToEngString (const decimal64 *, char *);
-
-  /* decNumber conversions */
-decimal64 *decimal64FromNumber (decimal64 *, const decNumber *, decContext *);
-decNumber *decimal64ToNumber (const decimal64 *, decNumber *);
+#if !defined(DECIMAL64)
+  #define DECIMAL64
+  #define DEC64NAME    "decimal64"                   /* Short name   */
+  #define DEC64FULLNAME "Decimal 64-bit Number"              /* Verbose name */
+  #define DEC64AUTHOR  "Mike Cowlishaw"              /* Who to blame */
+
+
+  /* parameters for decimal64s                                       */
+  #define DECIMAL64_Bytes  8           /* length                     */
+  #define DECIMAL64_Pmax   16          /* maximum precision (digits) */
+  #define DECIMAL64_Emax   384         /* maximum adjusted exponent  */
+  #define DECIMAL64_Emin  -383         /* minimum adjusted exponent  */
+  #define DECIMAL64_Bias   398         /* bias for the exponent      */
+  #define DECIMAL64_String 24          /* maximum string length, +1  */
+  #define DECIMAL64_EconL  8           /* exp. continuation length   */
+  /* highest biased exponent (Elimit-1)                                      */
+  #define DECIMAL64_Ehigh  (DECIMAL64_Emax+DECIMAL64_Bias-DECIMAL64_Pmax+1)
+
+  /* check enough digits, if pre-defined                             */
+  #if defined(DECNUMDIGITS)
+    #if (DECNUMDIGITS<DECIMAL64_Pmax)
+      #error decimal64.h needs pre-defined DECNUMDIGITS>=16 for safe use
+    #endif
+  #endif
+
+
+  #ifndef DECNUMDIGITS
+    #define DECNUMDIGITS DECIMAL64_Pmax /* size if not already defined*/
+  #endif
+  #ifndef DECNUMBER
+    #include "decNumber.h"             /* context and number library */
+  #endif
+
+  /* Decimal 64-bit type, accessible by bytes                        */
+  typedef struct {
+    uint8_t bytes[DECIMAL64_Bytes];    /* decimal64: 1, 5, 8, 50 bits*/
+    } decimal64;
+
+  /* special values [top byte excluding sign bit; last two bits are   */
+  /* don't-care for Infinity on input, last bit don't-care for NaN]   */
+  #if !defined(DECIMAL_NaN)
+    #define DECIMAL_NaN            0x7c        /* 0 11111 00 NaN             */
+    #define DECIMAL_sNaN    0x7e       /* 0 11111 10 sNaN            */
+    #define DECIMAL_Inf            0x78        /* 0 11110 00 Infinity        */
+  #endif
+
+  /* ---------------------------------------------------------------- */
+  /* Routines                                                        */
+  /* ---------------------------------------------------------------- */
+
+  #include "decimal64Symbols.h"
+
+  /* String conversions                                                      */
+  decimal64 * decimal64FromString(decimal64 *, const char *, decContext *);
+  char * decimal64ToString(const decimal64 *, char *);
+  char * decimal64ToEngString(const decimal64 *, char *);
+
+  /* decNumber conversions                                           */
+  decimal64 * decimal64FromNumber(decimal64 *, const decNumber *,
+                                 decContext *);
+  decNumber * decimal64ToNumber(const decimal64 *, decNumber *);
+
+  /* Format-dependent utilities                                              */
+  uint32_t    decimal64IsCanonical(const decimal64 *);
+  decimal64 * decimal64Canonical(decimal64 *, const decimal64 *);
 
 #endif
diff --git a/libdecnumber/dpd/decimal64Symbols.h b/libdecnumber/dpd/decimal64Symbols.h
new file mode 100644 (file)
index 0000000..cf965bf
--- /dev/null
@@ -0,0 +1,16 @@
+#if !defined(DECIMAL64SYMBOLS)
+#define DECIMAL64SYMBOLS
+
+#ifdef IN_LIBGCC2
+#define decDigitsFromDPD __decDigitsFromDPD
+#define decDigitsToDPD __decDigitsToDPD
+#define decimal64Canonical __decimal64Canonical
+#define decimal64FromNumber __decimal64FromNumber
+#define decimal64FromString __decimal64FromString
+#define decimal64IsCanonical __decimal64IsCanonical
+#define decimal64ToEngString __decimal64ToEngString
+#define decimal64ToNumber __decimal64ToNumber
+#define decimal64ToString __decimal64ToString
+#endif
+
+#endif
index 84bb87644e1deb1a5f8580559c365f9833ba0695..e9fed197a8373af669def9f2302d5f182a82bf8e 100644 (file)
@@ -1,3 +1,8 @@
+2007-09-10  Janis Johnson  <janis187@us.ibm.com>
+
+       * Makefile.in (dfp-filenames): Remove decUtility, add
+       decDouble, decPacked, decQuad, decSingle.
+
 2007-08-27  Hans Kester  <hans.kester@ellips.nl>
 
        * config.host : Add x86_64-elf target.
index ca7ed066a83faee2d8f685d750b6c62dcc5c26d4..4b3bcc9df9c36ed92b1ab1689733e2f45dbaa01e 100644 (file)
@@ -488,7 +488,7 @@ dfp-filenames += decimal_globals decimal_data binarydecimal \
                 bid128_to_int32 bid128_to_int64 \
                 bid128_to_uint32 bid128_to_uint64
 else
-dfp-filenames += decContext decNumber decExcept decRound decLibrary decUtility
+dfp-filenames += decContext decNumber decExcept decRound decLibrary decDouble decPacked decQuad decSingle
 endif
 endif