Full big num implementation with preferred serialization and 65-bit negs (#219)

Encoding and decoding of negative big numbers now takes into account the offset of 1 for all CBOR negative numbers. Also, big numbers are encoded with preferred serialization -- when they can be encoded with type 0 and type 1 integers, they are. Encoding and decoding big numbers is no longer a pass through for tagging a binary string.

This is an incompatible change with QCBOR 1.x. A mode configuration call is added to return to the 1.x behavior if desired.

This is because of the realization in work on 65-bit negative numbers that big numbers need preferred serialization.

This affects big floats and decimal fractions when the mantissa is a big number.

New methods to encode big numbers with non-preferred serialization are added.

A new method is added to process a raw big number for the offset of one for negatives. This is outside of spiffy decode. It does a little big number arithmetic.

dCBOR numeric reduction now includes 65-bit integers both for number encoding and decoding.



* Checkpoint work on 65-bit negs

* check point ... mostly working

* Checkpoint work on preferred bignums

* Tests passing...

* bignum encode improved to near completion

* Fix #ifdef fan out and error condition bug

* Code tidiness

* debugging unreplicatable CI failure

* v1 compat mode; EAM encode test fan out starting

* debugging ci...

* hacking ci failures

* CI failure hacking

* CI hacking

* Clean up some left over junk

* more leftover junk

* Clean up test leftovers

* Fixes for #ifdef fan out

* Fix conversion of uint to zero, even though it's never used

* REmove more junk

---------

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/src/ieee754.c b/src/ieee754.c
index f9b7a3f..40421ad 100644
--- a/src/ieee754.c
+++ b/src/ieee754.c
@@ -691,6 +691,7 @@
    /* Cast safe because of mask above; exponents < DOUBLE_EXPONENT_MAX */
    const int64_t  nDoubleUnbiasedExponent = (int64_t)uDoubleBiasedExponent - DOUBLE_EXPONENT_BIAS;
    const uint64_t uDoubleSignificand      = uDouble & DOUBLE_SIGNIFICAND_MASK;
+   const uint64_t bIsNegative             = uDouble & DOUBLE_SIGN_MASK;
 
    if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_ZERO) {
       if(uDoubleSignificand == 0) {
@@ -706,13 +707,21 @@
          /* --- NAN --- */
          Result.type = IEEE754_ToInt_NaN; /* dCBOR doesn't care about payload */
       } else  {
-         /* --- INIFINITY --- */
+         /* --- INFINITY --- */
          Result.type = IEEE754_ToInt_NO_CONVERSION;
       }
-   } else if(nDoubleUnbiasedExponent < 0 ||
-             (nDoubleUnbiasedExponent >= ((uDouble & DOUBLE_SIGN_MASK) ? 63 : 64))) {
+   } else if(nDoubleUnbiasedExponent < 0) {
       /* --- Exponent out of range --- */
       Result.type = IEEE754_ToInt_NO_CONVERSION;
+   } else if(nDoubleUnbiasedExponent >= 64) {
+      if(nDoubleUnbiasedExponent == 64 && uDoubleSignificand == 0 && bIsNegative) {
+         /* Very special case for -18446744073709551616.0 */
+         Result.integer.un_signed = 0; /* No negative 0, use it to indicate 2^64 */
+         Result.type              = IEEE754_ToInt_IS_65BIT_NEG;
+      } else {
+         /* --- Exponent out of range --- */
+         Result.type = IEEE754_ToInt_NO_CONVERSION;
+      }
    } else {
       /* Conversion only fails when the input is too large or is not a
        * whole number, never because of lack of precision because
@@ -737,10 +746,15 @@
             /* Numbers greater than 2^52 with at most 52 significant bits */
             uInteger <<= nDoubleUnbiasedExponent - DOUBLE_NUM_SIGNIFICAND_BITS;
          }
-         if(uDouble & DOUBLE_SIGN_MASK) {
+         if(bIsNegative) {
             /* Cast safe because exponent range check above */
-            Result.integer.is_signed = -((int64_t)uInteger);
-            Result.type              = IEEE754_ToInt_IS_INT;
+            if(nDoubleUnbiasedExponent == 63) {
+               Result.integer.un_signed = uInteger;
+               Result.type              = IEEE754_ToInt_IS_65BIT_NEG;
+            } else {
+               Result.integer.is_signed = -((int64_t)uInteger);
+               Result.type              = IEEE754_ToInt_IS_INT;
+            }
          } else {
             Result.integer.un_signed = uInteger;
             Result.type              = IEEE754_ToInt_IS_UINT;
@@ -769,6 +783,8 @@
    /* Cast safe because of mask above; exponents < SINGLE_EXPONENT_MAX */
    const int32_t  nSingleUnbiasedExponent = (int32_t)uSingleBiasedExponent - SINGLE_EXPONENT_BIAS;
    const uint32_t uSingleleSignificand    = uSingle & SINGLE_SIGNIFICAND_MASK;
+   const uint64_t bIsNegative             = uSingle & SINGLE_SIGN_MASK;
+
 
    if(nSingleUnbiasedExponent == SINGLE_EXPONENT_ZERO) {
       if(uSingleleSignificand == 0 && !(uSingle & SINGLE_SIGN_MASK)) {
@@ -786,10 +802,18 @@
       } else  {
          Result.type = IEEE754_ToInt_NO_CONVERSION;
       }
-   } else if(nSingleUnbiasedExponent < 0 ||
-             (nSingleUnbiasedExponent >= ((uSingle & SINGLE_SIGN_MASK) ? 63 : 64))) {
+   } else if(nSingleUnbiasedExponent < 0) {
       /* --- Exponent out of range --- */
        Result.type = IEEE754_ToInt_NO_CONVERSION;
+   } else if(nSingleUnbiasedExponent >= 64) {
+      if(nSingleUnbiasedExponent == 64 && uSingleleSignificand == 0 && bIsNegative) {
+         /* Very special case for -18446744073709551616.0 */
+         Result.integer.un_signed = 0; /* No negative 0, use it to indicate 2^64 */
+         Result.type              = IEEE754_ToInt_IS_65BIT_NEG;
+      } else {
+         /* --- Exponent out of range --- */
+         Result.type = IEEE754_ToInt_NO_CONVERSION;
+      }
     } else {
       /* Conversion only fails when the input is too large or is not a
        * whole number, never because of lack of precision because
@@ -814,9 +838,15 @@
             /* Numbers greater than 2^23 with at most 23 significant bits*/
             uInteger <<= nSingleUnbiasedExponent - SINGLE_NUM_SIGNIFICAND_BITS;
          }
-         if(uSingle & SINGLE_SIGN_MASK) {
-            Result.integer.is_signed = -((int64_t)uInteger);
-            Result.type              = IEEE754_ToInt_IS_INT;
+         if(bIsNegative) {
+         /* Cast safe because exponent range check above */
+            if(nSingleUnbiasedExponent == 63) {
+               Result.integer.un_signed = uInteger;
+               Result.type              = IEEE754_ToInt_IS_65BIT_NEG;
+            } else {
+               Result.integer.is_signed = -((int64_t)uInteger);
+               Result.type              = IEEE754_ToInt_IS_INT;
+            }
          } else {
             Result.integer.un_signed = uInteger;
             Result.type              = IEEE754_ToInt_IS_UINT;
@@ -837,31 +867,37 @@
    uint64_t uDoubleSignificand;
    int      nPrecisionBits;
 
-   /* Figure out the exponent and normalize the significand. This is
-    * done by shifting out all leading zero bits and counting them. If
-    * none are shifted out, the exponent is 63. */
-   uDoubleSignificand = uInt;
-   nDoubleUnbiasedExponent = 63;
-   while(1) {
-      if(uDoubleSignificand & 0x8000000000000000UL) {
-         break;
+   if(uInt == 0) {
+      uDoubleSignificand      = 0;
+      nDoubleUnbiasedExponent = DOUBLE_EXPONENT_ZERO;
+
+   } else  {
+      /* Figure out the exponent and normalize the significand. This is
+       * done by shifting out all leading zero bits and counting them. If
+       * none are shifted out, the exponent is 63. */
+      uDoubleSignificand = uInt;
+      nDoubleUnbiasedExponent = 63;
+      while(1) {
+         if(uDoubleSignificand & 0x8000000000000000UL) {
+            break;
+         }
+         uDoubleSignificand <<= 1;
+         nDoubleUnbiasedExponent--;
+      };
+
+      /* Position significand correctly for a double. Only shift 63 bits
+       * because of the 1 that is present by implication in IEEE 754.*/
+      uDoubleSignificand >>= 63 - DOUBLE_NUM_SIGNIFICAND_BITS;
+
+      /* Subtract 1 which is present by implication in IEEE 754 */
+      uDoubleSignificand -= 1ULL << (DOUBLE_NUM_SIGNIFICAND_BITS);
+
+      nPrecisionBits = IEEE754_Private_CountPrecisionBits(uInt) - (64 - nDoubleUnbiasedExponent);
+
+      if(nPrecisionBits > DOUBLE_NUM_SIGNIFICAND_BITS) {
+         /* Will lose precision if converted */
+         return IEEE754_UINT_TO_DOUBLE_OOB;
       }
-      uDoubleSignificand <<= 1;
-      nDoubleUnbiasedExponent--;
-   };
-
-   /* Position significand correctly for a double. Only shift 63 bits
-    * because of the 1 that is present by implication in IEEE 754.*/
-   uDoubleSignificand >>= 63 - DOUBLE_NUM_SIGNIFICAND_BITS;
-
-   /* Subtract 1 which is present by implication in IEEE 754 */
-   uDoubleSignificand -= 1ULL << (DOUBLE_NUM_SIGNIFICAND_BITS);
-
-   nPrecisionBits = IEEE754_Private_CountPrecisionBits(uInt) - (64 - nDoubleUnbiasedExponent);
-
-   if(nPrecisionBits > DOUBLE_NUM_SIGNIFICAND_BITS) {
-      /* Will lose precision if converted */
-      return IEEE754_UINT_TO_DOUBLE_OOB;
    }
 
    return IEEE754_AssembleDouble((uint64_t)uIsNegative,