Big number code tidy and documentation update

Move the big number, big float and decimal fractions around to group them better

Clearly comment the deprecated functions

Improve documentation for big numbers, big floats and decimal fractions

Improve test coverage for big numbers a little

Optimize big number encoding



* big number and exp mantissa tidy up

* Big number documentation

* Fix commits of XCode project files

* documentation improvements

* Remove junk

---------

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 73ae425..84bf70f 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -94,13 +94,6 @@
 #endif
 
 
-
-
-#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
-
-
-
-
 static bool
 QCBORItem_IsMapOrArray(const QCBORItem Item)
 {
@@ -5167,53 +5160,6 @@
 
 
 
-
-/**
- * @brief Common processing for a big number tag.
- *
- * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
- * @param[in] pItem            The item with the date.
- * @param[out] pBignumber          The returned big number
- * @param[out] pbIsNegative  The returned sign of the big number.
- *
- * Common processing for the big number tag. Mostly make sure
- * the tag content is correct and copy forward any further other tag
- * numbers.
- */
-static void
-QCBORDecode_Private_BigNumberRawMain(QCBORDecodeContext *pMe,
-                                     const uint8_t       uTagRequirement,
-                                     QCBORItem          *pItem,
-                                     UsefulBufC         *pBignumber,
-                                     bool               *pbIsNegative,
-                                     size_t              uOffset)
-{
-   // TODO: refer to the static const ones instead
-
-   const uint8_t puTypes[] = {QCBOR_TYPE_POSBIGNUM,QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE};
-
-   const uint64_t puTNs[] = {CBOR_TAG_POS_BIGNUM, CBOR_TAG_NEG_BIGNUM, CBOR_TAG_INVALID64};
-
-   QCBORDecode_Private_ProcessTagItemMulti(pMe,
-                                           pItem,
-                                           uTagRequirement,
-                                           puTypes,
-                                           puTNs,
-                                           QCBORDecode_StringsTagCB,
-                                           uOffset);
-   if(pMe->uLastError) {
-      return;
-   }
-
-   if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
-      *pbIsNegative = false;
-   } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
-      *pbIsNegative = true;
-   }
-   *pBignumber = pItem->val.bigNum;
-}
-
-
 static void
 QCBORDecode_Private_GetMIME(QCBORDecodeContext *pMe,
                             const uint8_t       uTagRequirement,
@@ -5310,79 +5256,11 @@
 }
 
 
-/*
- * Public function, see header qcbor/qcbor_spiffy_decode.h
- */
-void
-QCBORDecode_GetTBigNumberRaw(QCBORDecodeContext *pMe,
-                             const uint8_t       uTagRequirement,
-                             UsefulBufC         *pBignumber,
-                             bool               *pbIsNegative)
-{
-   QCBORItem  Item;
-   size_t     uOffset;
-
-   QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberRawMain(pMe,
-                                        uTagRequirement,
-                                       &Item,
-                                        pBignumber,
-                                        pbIsNegative,
-                                        uOffset);
-}
-
-/*
- * Public function, see header qcbor/qcbor_spiffy_decode.h
- */
-void
-QCBORDecode_GetTBigNumberRawInMapN(QCBORDecodeContext *pMe,
-                                   const int64_t       nLabel,
-                                   const uint8_t       uTagRequirement,
-                                   UsefulBufC         *pBigNumber,
-                                   bool               *pbIsNegative)
-{
-   QCBORItem  Item;
-   size_t     uOffset;
-
-   QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberRawMain(pMe,
-                                        uTagRequirement,
-                                       &Item,
-                                        pBigNumber,
-                                        pbIsNegative,
-                                        uOffset);
-}
-
-/*
- * Public function, see header qcbor/qcbor_spiffy_decode.h
- */
-void
-QCBORDecode_GetTBigNumberRawInMapSZ(QCBORDecodeContext *pMe,
-                                    const char         *szLabel,
-                                    const uint8_t       uTagRequirement,
-                                    UsefulBufC         *pBigNumber,
-                                    bool               *pbIsNegative)
-{
-   QCBORItem  Item;
-   size_t     uOffset;
-
-   QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberRawMain(pMe,
-                                        uTagRequirement,
-                                       &Item,
-                                        pBigNumber,
-                                        pbIsNegative,
-                                        uOffset);
-}
-
-
 
 // Improvement: add methods for wrapped CBOR, a simple alternate
 // to EnterBstrWrapped
 
 
-
-
 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 
 /**
@@ -5645,26 +5523,29 @@
 /**
  * @brief Convert a CBOR big number to a uint64_t.
  *
- * @param[in] BigNum  Bytes of the big number to convert.
- * @param[in] uMax  Maximum value allowed for the result.
- * @param[out] pResult  Place to put the unsigned integer result.
+ * @param[in] BigNumber  Bytes of the big number to convert.
+ * @param[in] uMax       Maximum value allowed for the result.
+ * @param[out] pResult   Place to put the unsigned integer result.
  *
- * @returns Error code
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW   When the bignumber is
+ *                                                too large to fit
+ * @retval QCBOR_SUCCESS                          The conversion succeeded.
  *
- * Many values will overflow because  a big num can represent a much
+ * Many values will overflow because a big number can represent a much
  * larger range than uint64_t.
  */
 static QCBORError
-QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
-                                      const uint64_t   uMax,
-                                      uint64_t        *pResult)
+QCBORDecode_Private_BigNumberToUInt(const UsefulBufC BigNumber,
+                                    const uint64_t   uMax,
+                                    uint64_t        *pResult)
 {
    uint64_t uResult;
+   size_t   uLen;
+
+   const uint8_t *pByte = BigNumber.ptr;
 
    uResult = 0;
-   const uint8_t *pByte = BigNum.ptr;
-   size_t uLen = BigNum.len;
-   while(uLen--) {
+   for(uLen = BigNumber.len; uLen > 0; uLen--) {
       if(uResult > (uMax >> 8)) {
          return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
       }
@@ -5679,45 +5560,49 @@
 /**
  * @brief Convert a CBOR postive big number to a uint64_t.
  *
- * @param[in] BigNum  Bytes of the big number to convert.
- * @param[out] pResult  Place to put the unsigned integer result.
+ * @param[in] BigNumber  Bytes of the big number to convert.
+ * @param[out] pResult   Place to put the unsigned integer result.
  *
- * @returns Error code
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW   When the bignumber is
+ *                                                too large to fit
+ * @retval QCBOR_SUCCESS                          The conversion succeeded.
  *
- * Many values will overflow because  a big num can represent a much
+ * Many values will overflow because a big num can represent a much
  * larger range than uint64_t.
  */
 static QCBORError
-QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
-                                              uint64_t        *pResult)
+QCBORDecode_Private_PositiveBigNumberToUInt(const UsefulBufC BigNumber,
+                                            uint64_t        *pResult)
 {
-   return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
+   return QCBORDecode_Private_BigNumberToUInt(BigNumber, UINT64_MAX, pResult);
 }
 
 
 /**
  * @brief Convert a CBOR positive big number to an int64_t.
  *
- * @param[in] BigNum  Bytes of the big number to convert.
- * @param[out] pResult  Place to put the signed integer result.
+ * @param[in] BigNumber  Bytes of the big number to convert.
+ * @param[out] pResult   Place to put the signed integer result.
  *
- * @returns Error code
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW   When the bignumber is
+ *                                                too large to fit
+ * @retval QCBOR_SUCCESS                          The conversion succeeded.
  *
- * Many values will overflow because  a big num can represent a much
+ * Many values will overflow because a big num can represent a much
  * larger range than int64_t.
  */
 static QCBORError
-QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
-                                            int64_t         *pResult)
+QCBORDecode_Private_PositiveBigNumberToInt(const UsefulBufC BigNumber,
+                                           int64_t         *pResult)
 {
-   uint64_t uResult;
-   QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
-                                                             INT64_MAX,
-                                                             &uResult);
-   if(uError) {
+   uint64_t    uResult;
+   QCBORError  uError;
+
+   uError = QCBORDecode_Private_BigNumberToUInt(BigNumber, INT64_MAX, &uResult);
+   if(uError != QCBOR_SUCCESS) {
       return uError;
    }
-   /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
+   /* Cast safe because QCBORDecode_Private_BigNumberToUInt() limits to INT64_MAX */
    *pResult = (int64_t)uResult;
    return QCBOR_SUCCESS;
 }
@@ -5726,20 +5611,22 @@
 /**
  * @brief Convert a CBOR negative big number to an int64_t.
  *
- * @param[in] BigNum  Bytes of the big number to convert.
+ * @param[in] BigNumber  Bytes of the big number to convert.
  * @param[out] pnResult  Place to put the signed integer result.
  *
- * @returns Error code
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW   When the bignumber is
+ *                                                too large to fit
+ * @retval QCBOR_SUCCESS                          The conversion succeeded.
  *
- * Many values will overflow because  a big num can represent a much
+ * Many values will overflow because a big num can represent a much
  * larger range than int64_t.
  */
 static QCBORError
-QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
-                                            int64_t         *pnResult)
+QCBORDecode_Private_NegativeBigNumberToInt(const UsefulBufC BigNumber,
+                                           int64_t         *pnResult)
 {
-   uint64_t uResult;
-   QCBORError uError;
+   uint64_t    uResult;
+   QCBORError  uError;
 
    /* The negative integer furthest from zero for a C int64_t is
     * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
@@ -5753,7 +5640,7 @@
     *   -n - 1 <= -INT64_MAX - 1
     *    n     <= INT64_MAX.
     */
-   uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
+   uError = QCBORDecode_Private_BigNumberToUInt(BigNumber, INT64_MAX, &uResult);
    if(uError != QCBOR_SUCCESS) {
       return uError;
    }
@@ -5767,7 +5654,66 @@
    return QCBOR_SUCCESS;
 }
 
+/**
+ * @brief Convert an integer to a big number.
+ *
+ * @param[in] uNum          The integer to convert.
+ * @param[in] BigNumberBuf  The buffer to output the big number to.
+ *
+ * @returns The big number or NULLUsefulBufC is the buffer is to small.
+ *
+ * This always succeeds unless the buffer is too small.
+ */
+static UsefulBufC
+QCBORDecode_Private_UIntToBigNumber(uint64_t uNum, const UsefulBuf BigNumberBuf)
+{
+   UsefulOutBuf UOB;
 
+   /* With a UsefulOutBuf, there's no pointer math */
+   UsefulOutBuf_Init(&UOB, BigNumberBuf);
+
+   /* Must copy one byte even if zero.  The loop, mask and shift
+    * algorithm provides endian conversion.
+    */
+   do {
+      UsefulOutBuf_InsertByte(&UOB, uNum & 0xff, 0);
+      uNum >>= 8;
+   } while(uNum);
+
+   return UsefulOutBuf_OutUBuf(&UOB);
+}
+
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+/**
+ * @brief Convert a big number to double-precision float.
+ *
+ * @param[in] BigNumber   The big number to convert.
+ *
+ * @returns  The double value.
+ *
+ * This will always succeed. It will lose precision for larger
+ * numbers. If the big number is too large to fit (more than
+ * 1.7976931348623157E+308) infinity will be returned. NaN is never
+ * returned.
+ */
+static double
+QCBORDecode_Private_BigNumberToDouble(const UsefulBufC BigNumber)
+{
+   double dResult;
+   size_t uLen;
+
+   const uint8_t *pByte = BigNumber.ptr;
+
+   dResult = 0.0;
+   /* This will overflow and become the float value INFINITY if the number
+    * is too large to fit. */
+   for(uLen = BigNumber.len; uLen > 0; uLen--){
+      dResult = (dResult * 256.0) + (double)*pByte++;
+   }
+
+   return dResult;
+}
+#endif /* ! QCBOR_DISABLE_FLOAT_HW_USE */
 
 
 /**
@@ -5851,1171 +5797,613 @@
 }
 
 
-/**
- * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] pnValue       Result of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetInt64Convert().
+
+#if !defined(USEFULBUF_DISABLE_ALL_FLOAT) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h file
  */
 void
-QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
-                                    uint32_t            uConvertTypes,
-                                    int64_t            *pnValue,
-                                    QCBORItem          *pItem)
+QCBORDecode_GetNumberConvertPrecisely(QCBORDecodeContext *pMe,
+                                      QCBORItem          *pNumber)
 {
-   QCBORDecode_VGetNext(pMe, pItem);
-   if(pMe->uLastError) {
-      return;
-   }
+   QCBORItem            Item;
+   struct IEEE754_ToInt ToInt;
+   double               dNum;
+   QCBORError           uError;
 
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
-                                                         uConvertTypes,
-                                                         pnValue);
-}
-
-/**
- * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] nLabel         Label to find in map.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] pnValue       Result of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetInt64ConvertInMapN().
- */
-void
-QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
-                                          int64_t             nLabel,
-                                          uint32_t            uConvertTypes,
-                                          int64_t            *pnValue,
-                                          QCBORItem          *pItem)
-{
-   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
    if(pMe->uLastError != QCBOR_SUCCESS) {
       return;
    }
 
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
-                                                         uConvertTypes,
-                                                         pnValue);
-}
-
-/**
- * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] szLabel        Label to find in map.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] pnValue       Result of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetInt64ConvertInMapSZ().
- */
-void
-QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
-                                           const char *         szLabel,
-                                           uint32_t             uConvertTypes,
-                                           int64_t             *pnValue,
-                                           QCBORItem           *pItem)
-{
-   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
-   if(pMe->uLastError != QCBOR_SUCCESS) {
+   // TODO:VGetNext?
+   uError = QCBORDecode_GetNext(pMe, &Item);
+   if(uError != QCBOR_SUCCESS) {
+      *pNumber = Item;
+      pMe->uLastError = (uint8_t)uError;
       return;
    }
 
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
-                                                         uConvertTypes,
-                                                         pnValue);
-}
-
-
-/**
- * @brief Convert many number types to an int64_t.
- *
- * @param[in] pItem   The item to convert.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] pnValue  The resulting converted value.
- *
- * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
- *                                    in uConvertTypes.
- * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
- * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
- *                                               or too small.
- */
-static QCBORError
-QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
-                              const uint32_t   uConvertTypes,
-                              int64_t         *pnValue)
-{
-   switch(pItem->uDataType) {
-
-      case QCBOR_TYPE_POSBIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
-            return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_NEGBIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
-            return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
-      case QCBOR_TYPE_DECIMAL_FRACTION:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
-                                  pItem->val.expAndMantissa.nExponent,
-                                  pnValue,
-                                 &QCBOR_Private_Exponentitate10);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_BIGFLOAT:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
-            return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
-                                  pItem->val.expAndMantissa.nExponent,
-                                  pnValue,
-                                  QCBOR_Private_Exponentitate2);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            int64_t    nMantissa;
-            QCBORError uErr;
-            uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
-            if(uErr) {
-               return uErr;
-            }
-            return QCBOR_Private_ExponentiateNN(nMantissa,
-                                  pItem->val.expAndMantissa.nExponent,
-                                  pnValue,
-                                  QCBOR_Private_Exponentitate10);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            int64_t    nMantissa;
-            QCBORError uErr;
-            uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
-            if(uErr) {
-               return uErr;
-            }
-            return QCBOR_Private_ExponentiateNN(nMantissa,
-                                  pItem->val.expAndMantissa.nExponent,
-                                  pnValue,
-                                  QCBOR_Private_Exponentitate10);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            int64_t    nMantissa;
-            QCBORError uErr;
-            uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
-            if(uErr) {
-               return uErr;
-            }
-            return QCBOR_Private_ExponentiateNN(nMantissa,
-                                  pItem->val.expAndMantissa.nExponent,
-                                  pnValue,
-                                  QCBOR_Private_Exponentitate2);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            int64_t    nMantissa;
-            QCBORError uErr;
-            uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
-            if(uErr) {
-               return uErr;
-            }
-            return QCBOR_Private_ExponentiateNN(nMantissa,
-                                  pItem->val.expAndMantissa.nExponent,
-                                  pnValue,
-                                  QCBOR_Private_Exponentitate2);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
-
-
-      default:
-         return QCBOR_ERR_UNEXPECTED_TYPE;   }
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
-                               const uint32_t      uConvertTypes,
-                               int64_t            *pnValue)
-{
-   QCBORItem Item;
-
-   QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
-                                                            uConvertTypes,
-                                                            pnValue);
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
-                                     const int64_t       nLabel,
-                                     const uint32_t      uConvertTypes,
-                                     int64_t            *pnValue)
-{
-   QCBORItem Item;
-
-   QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
-                                             nLabel,
-                                             uConvertTypes,
-                                             pnValue,
-                                             &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
-                                                            uConvertTypes,
-                                                            pnValue);
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
-                                      const char         *szLabel,
-                                      const uint32_t      uConvertTypes,
-                                      int64_t            *pnValue)
-{
-   QCBORItem Item;
-   QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
-                                              szLabel,
-                                              uConvertTypes,
-                                              pnValue,
-                                              &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
-                                                            uConvertTypes,
-                                                            pnValue);
-}
-
-
-/**
- * @brief Convert many number types to an uint64_t.
- *
- * @param[in] pItem   The item to convert.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] puValue  The resulting converted value.
- *
- * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
- *                                    in uConvertTypes.
- * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
- * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
- *                                               or too small.
- */
-static QCBORError
-QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
-                            const uint32_t   uConvertTypes,
-                            uint64_t        *puValue)
-{
-   switch(pItem->uDataType) {
-      case QCBOR_TYPE_DOUBLE:
-      case QCBOR_TYPE_FLOAT:
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
-            // Can't use llround here because it will not convert values
-            // greater than INT64_MAX and less than UINT64_MAX that
-            // need to be converted so it is more complicated.
-            feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
-            if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
-               if(isnan(pItem->val.dfnum)) {
-                  return QCBOR_ERR_FLOAT_EXCEPTION;
-               } else if(pItem->val.dfnum < 0) {
-                  return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
-               } else {
-                  double dRounded = round(pItem->val.dfnum);
-                  // See discussion in DecodeDateEpoch() for
-                  // explanation of - 0x7ff
-                  if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
-                     return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
-                  }
-                  *puValue = (uint64_t)dRounded;
-               }
-            } else {
-               if(isnan(pItem->val.fnum)) {
-                  return QCBOR_ERR_FLOAT_EXCEPTION;
-               } else if(pItem->val.fnum < 0) {
-                  return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
-               } else {
-                  float fRounded = roundf(pItem->val.fnum);
-                  // See discussion in DecodeDateEpoch() for
-                  // explanation of - 0x7ff
-                  if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
-                     return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
-                  }
-                  *puValue = (uint64_t)fRounded;
-               }
-            }
-            if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
-               // round() and roundf() shouldn't result in exceptions here, but
-               // catch them to be robust and thorough. Don't try to
-               // distinguish between the various exceptions because it seems
-               // they vary by CPU, compiler and OS.
-               return QCBOR_ERR_FLOAT_EXCEPTION;
-            }
-
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-#else
-         return QCBOR_ERR_HW_FLOAT_DISABLED;
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
-         break;
-
+   switch(Item.uDataType) {
       case QCBOR_TYPE_INT64:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
-            if(pItem->val.int64 >= 0) {
-               *puValue = (uint64_t)pItem->val.int64;
+      case QCBOR_TYPE_UINT64:
+         *pNumber = Item;
+         break;
+
+      case QCBOR_TYPE_DOUBLE:
+         ToInt = IEEE754_DoubleToInt(Item.val.dfnum);
+         if(ToInt.type == IEEE754_ToInt_IS_INT) {
+            pNumber->uDataType = QCBOR_TYPE_INT64;
+            pNumber->val.int64 = ToInt.integer.is_signed;
+         } else if(ToInt.type == IEEE754_ToInt_IS_UINT) {
+            if(ToInt.integer.un_signed <= INT64_MAX) {
+               /* Do the same as base QCBOR integer decoding */
+               pNumber->uDataType = QCBOR_TYPE_INT64;
+               pNumber->val.int64 = (int64_t)ToInt.integer.un_signed;
             } else {
-               return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+               pNumber->uDataType = QCBOR_TYPE_UINT64;
+               pNumber->val.uint64 = ToInt.integer.un_signed;
             }
          } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
+            *pNumber = Item;
          }
          break;
 
-      case QCBOR_TYPE_UINT64:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
-            *puValue = pItem->val.uint64;
+      case QCBOR_TYPE_FLOAT:
+         ToInt = IEEE754_SingleToInt(Item.val.fnum);
+         if(ToInt.type == IEEE754_ToInt_IS_INT) {
+            pNumber->uDataType = QCBOR_TYPE_INT64;
+            pNumber->val.int64 = ToInt.integer.is_signed;
+         } else if(ToInt.type == IEEE754_ToInt_IS_UINT) {
+            if(ToInt.integer.un_signed <= INT64_MAX) {
+               /* Do the same as base QCBOR integer decoding */
+               pNumber->uDataType = QCBOR_TYPE_INT64;
+               pNumber->val.int64 = (int64_t)ToInt.integer.un_signed;
+            } else {
+               pNumber->uDataType = QCBOR_TYPE_UINT64;
+               pNumber->val.uint64 = ToInt.integer.un_signed;
+            }
          } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
+            *pNumber = Item;
          }
          break;
 
       case QCBOR_TYPE_65BIT_NEG_INT:
-         return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
-
-      default:
-         return QCBOR_ERR_UNEXPECTED_TYPE;
-   }
-
-   return QCBOR_SUCCESS;
-}
-
-
-/**
- * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] puValue       Result of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetUInt64Convert().
- */
-void
-QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
-                                     const uint32_t      uConvertTypes,
-                                     uint64_t           *puValue,
-                                     QCBORItem          *pItem)
-{
-   QCBORDecode_VGetNext(pMe, pItem);
-   if(pMe->uLastError) {
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
-                                                          uConvertTypes,
-                                                          puValue);
-}
-
-
-/**
- * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] nLabel         Label to find in map.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] puValue       Result of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetUInt64ConvertInMapN().
- */
-void
-QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
-                                           const int64_t       nLabel,
-                                           const uint32_t      uConvertTypes,
-                                           uint64_t            *puValue,
-                                           QCBORItem          *pItem)
-{
-   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
-   if(pMe->uLastError != QCBOR_SUCCESS) {
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
-                                                          uConvertTypes,
-                                                          puValue);
-}
-
-
-/**
- * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] szLabel         Label to find in map.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] puValue       Result of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetUInt64ConvertInMapSZ().
- */
-void
-QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
-                                            const char         *szLabel,
-                                            const uint32_t      uConvertTypes,
-                                            uint64_t           *puValue,
-                                            QCBORItem          *pItem)
-{
-   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
-   if(pMe->uLastError != QCBOR_SUCCESS) {
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
-                                                          uConvertTypes,
-                                                          puValue);
-}
-
-
-/**
- * @brief Convert many number types to an unt64_t.
- *
- * @param[in] pItem   The item to convert.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] puValue  The resulting converted value.
- *
- * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
- *                                    in uConvertTypes.
- * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
- * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
- *                                               or too small.
- */
-static QCBORError
-QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
-                               const uint32_t   uConvertTypes,
-                               uint64_t        *puValue)
-{
-   switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
-
-      case QCBOR_TYPE_POSBIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
-            return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
+         if(Item.val.uint64 == UINT64_MAX) {
+            /* The value -18446744073709551616 is encoded as an
+             * unsigned 18446744073709551615. It's a whole number that
+             * needs to be returned as a double. It can't be handled
+             * by IEEE754_UintToDouble because 18446744073709551616
+             * doesn't fit into a uint64_t. You can't get it by adding
+             * 1 to 18446744073709551615.
+             */
+            pNumber->val.dfnum = -18446744073709551616.0;
+            pNumber->uDataType = QCBOR_TYPE_DOUBLE;
          } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_NEGBIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
-            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
-
-      case QCBOR_TYPE_DECIMAL_FRACTION:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
-                                   pItem->val.expAndMantissa.nExponent,
-                                   puValue,
-                                   QCBOR_Private_Exponentitate10);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_BIGFLOAT:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
-            return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
-                                   pItem->val.expAndMantissa.nExponent,
-                                   puValue,
-                                   QCBOR_Private_Exponentitate2);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            uint64_t   uMantissa;
-            QCBORError uErr;
-            uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
-            if(uErr != QCBOR_SUCCESS) {
-               return uErr;
-            }
-            return QCBOR_Private_ExponentitateUU(uMantissa,
-                                                 pItem->val.expAndMantissa.nExponent,
-                                                 puValue,
-                                                 QCBOR_Private_Exponentitate10);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            uint64_t   uMantissa;
-            QCBORError uErr;
-            uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
-                                                                 &uMantissa);
-            if(uErr != QCBOR_SUCCESS) {
-               return uErr;
-            }
-            return QCBOR_Private_ExponentitateUU(uMantissa,
-                                                 pItem->val.expAndMantissa.nExponent,
-                                                 puValue,
-                                                 QCBOR_Private_Exponentitate2);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
-      default:
-         return QCBOR_ERR_UNEXPECTED_TYPE;
-   }
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
-                                const uint32_t      uConvertTypes,
-                                uint64_t           *puValue)
-{
-   QCBORItem Item;
-
-   QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
-                                                             uConvertTypes,
-                                                             puValue);
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
-                                      const int64_t       nLabel,
-                                      const uint32_t      uConvertTypes,
-                                      uint64_t           *puValue)
-{
-   QCBORItem Item;
-
-   QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
-                                              nLabel,
-                                              uConvertTypes,
-                                              puValue,
-                                              &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
-                                                             uConvertTypes,
-                                                             puValue);
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
-                                       const char         *szLabel,
-                                       const uint32_t      uConvertTypes,
-                                       uint64_t           *puValue)
-{
-   QCBORItem Item;
-   QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
-                                               szLabel,
-                                               uConvertTypes,
-                                               puValue,
-                                               &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
-                                                             uConvertTypes,
-                                                             puValue);
-}
-
-
-
-
-#ifndef USEFULBUF_DISABLE_ALL_FLOAT
-/**
- * @brief Basic conversions to a double.
- *
- * @param[in] pItem          The item to convert
- * @param[in] uConvertTypes  Bit flags indicating source types for conversion
- * @param[out] pdValue       The value converted to a double
- *
- * This does the conversions that don't need much object code,
- * the conversions from int, uint and float to double.
- *
- * See QCBOR_Private_DoubleConvertAll() for the full set
- * of conversions.
- */
-static QCBORError
-QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
-                            const uint32_t   uConvertTypes,
-                            double          *pdValue)
-{
-   switch(pItem->uDataType) {
-      case QCBOR_TYPE_FLOAT:
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
-            if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
-               // Simple cast does the job.
-               *pdValue = (double)pItem->val.fnum;
+            dNum = IEEE754_UintToDouble(Item.val.uint64 + 1, 1);
+            if(dNum == IEEE754_UINT_TO_DOUBLE_OOB) {
+               *pNumber = Item;
             } else {
-               return QCBOR_ERR_UNEXPECTED_TYPE;
-            }
-         }
-#else /* QCBOR_DISABLE_FLOAT_HW_USE */
-         return QCBOR_ERR_HW_FLOAT_DISABLED;
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
-         break;
-
-      case QCBOR_TYPE_DOUBLE:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
-            if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
-               *pdValue = pItem->val.dfnum;
-            } else {
-               return QCBOR_ERR_UNEXPECTED_TYPE;
+               pNumber->val.dfnum = dNum;
+               pNumber->uDataType = QCBOR_TYPE_DOUBLE;
             }
          }
          break;
 
-      case QCBOR_TYPE_INT64:
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
-            // A simple cast seems to do the job with no worry of exceptions.
-            // There will be precision loss for some values.
-            *pdValue = (double)pItem->val.int64;
-
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-#else
-         return QCBOR_ERR_HW_FLOAT_DISABLED;
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
-         break;
-
-      case QCBOR_TYPE_UINT64:
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
-            // A simple cast seems to do the job with no worry of exceptions.
-            // There will be precision loss for some values.
-            *pdValue = (double)pItem->val.uint64;
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-#else
-         return QCBOR_ERR_HW_FLOAT_DISABLED;
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
-
-      case QCBOR_TYPE_65BIT_NEG_INT:
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
-         // TODO: don't use float HW. We have the function to do it.
-         *pdValue = -(double)pItem->val.uint64 - 1;
-         break;
-#else
-         return QCBOR_ERR_HW_FLOAT_DISABLED;
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
-
       default:
-         return QCBOR_ERR_UNEXPECTED_TYPE;
-   }
-
-   return QCBOR_SUCCESS;
-}
-
-
-/**
- * @brief  Almost-public method to decode a number and convert to double (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] uConvertTypes  Bit mask list of conversion options
- * @param[out] pdValue       The output of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetDoubleConvert().
- */
-void
-QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
-                                     const uint32_t      uConvertTypes,
-                                     double             *pdValue,
-                                     QCBORItem          *pItem)
-{
-   QCBORDecode_VGetNext(pMe, pItem);
-   if(pMe->uLastError) {
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
-                                                          uConvertTypes,
-                                                          pdValue);
-}
-
-
-/**
- * @brief  Almost-public method to decode a number and convert to double (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] nLabel         Label to find in map.
- * @param[in] uConvertTypes  Bit mask list of conversion options
- * @param[out] pdValue       The output of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetDoubleConvertInMapN().
- */
-void
-QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
-                                           const int64_t       nLabel,
-                                           const uint32_t      uConvertTypes,
-                                           double             *pdValue,
-                                           QCBORItem          *pItem)
-{
-   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
-   if(pMe->uLastError != QCBOR_SUCCESS) {
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
-                                                          uConvertTypes,
-                                                          pdValue);
-}
-
-
-/**
- * @brief  Almost-public method to decode a number and convert to double (semi-private).
- *
- * @param[in] pMe            The decode context.
- * @param[in] szLabel        Label to find in map.
- * @param[in] uConvertTypes  Bit mask list of conversion options
- * @param[out] pdValue       The output of the conversion.
- * @param[in,out] pItem      Temporary space to store Item, returned item.
- *
- * See QCBORDecode_GetDoubleConvertInMapSZ().
- */
-void
-QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
-                                            const char         *szLabel,
-                                            const uint32_t      uConvertTypes,
-                                            double             *pdValue,
-                                            QCBORItem          *pItem)
-{
-   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
-   if(pMe->uLastError != QCBOR_SUCCESS) {
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
-                                                          uConvertTypes,
-                                                          pdValue);
-}
-
-
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
-/**
- * @brief Convert a big number to double-precision float.
- *
- * @param[in] BigNum   The big number to convert
- *
- * @returns  The double value.
- *
- * This will always succeed. It will lose precision for larger
- * numbers. If the big number is too large to fit (more than
- * 1.7976931348623157E+308) infinity will be returned. NaN is never
- * returned.
- */
-static double
-QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
-{
-   double dResult;
-
-   dResult = 0.0;
-   const uint8_t *pByte = BigNum.ptr;
-   size_t uLen = BigNum.len;
-   /* This will overflow and become the float value INFINITY if the number
-    * is too large to fit. */
-   while(uLen--) {
-      dResult = (dResult * 256.0) + (double)*pByte++;
-   }
-
-   return dResult;
-}
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
-
-
-
-
-/**
- * @brief Convert many number types to a double.
- *
- * @param[in] pItem   The item to convert.
- * @param[in] uConvertTypes  Bit mask list of conversion options.
- * @param[out] pdValue  The resulting converted value.
- *
- * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
- *                                    in uConvertTypes.
- * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
- * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
- *                                               or too small.
- */
-static QCBORError
-QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
-                               const uint32_t   uConvertTypes,
-                               double          *pdValue)
-{
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
-   /*
-    * What Every Computer Scientist Should Know About Floating-Point Arithmetic
-    * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
-    */
-   switch(pItem->uDataType) {
-
-#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
-      case QCBOR_TYPE_DECIMAL_FRACTION:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            // Underflow gives 0, overflow gives infinity
-            *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
-                        pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
+         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+         pNumber->uDataType = QCBOR_TYPE_NONE;
          break;
-
-      case QCBOR_TYPE_BIGFLOAT:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
-            // Underflow gives 0, overflow gives infinity
-            *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
-                              exp2((double)pItem->val.expAndMantissa.nExponent);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
-
-      case QCBOR_TYPE_POSBIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
-            *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_NEGBIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
-            *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
-      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
-            *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            /* Must subtract 1 for CBOR negative integer offset */
-            double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
-            *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
-            double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
-            *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-
-      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
-         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
-            double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
-            *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
-         } else {
-            return QCBOR_ERR_UNEXPECTED_TYPE;
-         }
-         break;
-#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
-
-      default:
-         return QCBOR_ERR_UNEXPECTED_TYPE;
    }
-
-   return QCBOR_SUCCESS;
-
-#else
-   (void)pItem;
-   (void)uConvertTypes;
-   (void)pdValue;
-   return QCBOR_ERR_HW_FLOAT_DISABLED;
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
-
 }
 
-
-/*
- * Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
-                                const uint32_t      uConvertTypes,
-                                double             *pdValue)
-{
-
-   QCBORItem Item;
-
-   QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
-                                                             uConvertTypes,
-                                                             pdValue);
-}
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
 
 
-/*
- *  Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
-                                      const int64_t       nLabel,
-                                      const uint32_t      uConvertTypes,
-                                      double             *pdValue)
-{
-   QCBORItem Item;
-
-   QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
-                                              nLabel,
-                                              uConvertTypes,
-                                              pdValue,
-                                              &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
-                                                             uConvertTypes,
-                                                             pdValue);
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h file
- */
-void
-QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
-                                       const char         *szLabel,
-                                       const uint32_t      uConvertTypes,
-                                       double             *pdValue)
-{
-   QCBORItem Item;
-   QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
-                                               szLabel,
-                                               uConvertTypes,
-                                               pdValue,
-                                               &Item);
-
-   if(pMe->uLastError == QCBOR_SUCCESS) {
-      // The above conversion succeeded
-      return;
-   }
-
-   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
-      // The above conversion failed in a way that code below can't correct
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
-                                                             uConvertTypes,
-                                                             pdValue);
-}
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
-
-
-
-
-#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
-/**
- * @brief Convert an integer to a big number
+/* Add one to the big number and put the result in a new UsefulBufC
+ * from storage in UsefulBuf.
  *
- * @param[in] uInt  The integer to convert.
- * @param[in] Buffer  The buffer to output the big number to.
+ * Leading zeros must be removed before calling this.
  *
- * @returns The big number or NULLUsefulBufC is the buffer is to small.
- *
- * This always succeeds unless the buffer is too small.
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
  */
 static UsefulBufC
-QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
+QCBORDecode_BigNumberCopyPlusOne(UsefulBufC BigNumber, UsefulBuf BigNumberBuf)
 {
-   while((uInt & 0xff00000000000000UL) == 0) {
-      uInt = uInt << 8;
-   };
+   uint8_t        uCarry;
+   uint8_t        uSourceValue;
+   const uint8_t *pSource;
+   uint8_t       *pDest;
+   ptrdiff_t      uDestBytesLeft;
 
-   UsefulOutBuf UOB;
+   /* Start adding at the LSB */
+   pSource = &((const uint8_t *)BigNumber.ptr)[BigNumber.len-1];
+   pDest   = &((uint8_t *)BigNumberBuf.ptr)[BigNumberBuf.len-1];
 
-   UsefulOutBuf_Init(&UOB, Buffer);
+   uCarry = 1; /* Gets set back to zero if add the next line doesn't wrap */
+   *pDest = *pSource + 1;
+   while(1) {
+      /* Wrap around from 0xff to 0 is a defined operation for
+       * unsigned addition in C.*/
+      if(*pDest != 0) {
+         /*  The add operation didn't wrap so no more carry. This
+          * funciton only adds one, so when there is no more carry,
+          * carrying is over to the end.
+          */
+         uCarry = 0;
+      }
 
-   while(uInt) {
-      UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
-      uInt = uInt << 8;
+      uDestBytesLeft = pDest - (uint8_t *)BigNumberBuf.ptr;
+      if(pSource <= (const uint8_t *)BigNumber.ptr && uCarry == 0) {
+         break; /* Successful exit */
+      }
+      if(pSource > (const uint8_t *)BigNumber.ptr) {
+         uSourceValue = *--pSource;
+      } else {
+         /* All source bytes processed, but not the last carry */
+         uSourceValue = 0;
+      }
+
+      pDest--;
+      if(uDestBytesLeft < 0) {
+         return NULLUsefulBufC; /* Not enough space in destination buffer */
+      }
+
+      *pDest = uSourceValue + uCarry;
    }
 
-   return UsefulOutBuf_OutUBuf(&UOB);
+   return (UsefulBufC){pDest, BigNumberBuf.len - (size_t)uDestBytesLeft};
 }
 
+
+/* This returns 1 when uNum is 0 */
+static size_t
+QCBORDecode_Private_CountNonZeroBytes(uint64_t uNum)
+{
+   size_t uCount = 0;
+   do {
+      uCount++;
+      uNum >>= 8;
+   } while(uNum);
+
+   return uCount;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+QCBORError
+QCBORDecode_ProcessBigNumberNoPreferred(const QCBORItem Item,
+                                        const UsefulBuf BigNumberBuf,
+                                        UsefulBufC     *pBigNumber,
+                                        bool           *pbIsNegative)
+{
+   size_t      uLen;
+   UsefulBufC  BigNumber;
+   int         uType;
+
+   uType = Item.uDataType;
+   if(uType == QCBOR_TYPE_BYTE_STRING) {
+      uType = *pbIsNegative ? QCBOR_TYPE_NEGBIGNUM : QCBOR_TYPE_POSBIGNUM;
+   }
+
+   static const uint8_t Zero[] = {0x00};
+   BigNumber = UsefulBuf_SkipLeading(Item.val.bigNum, 0);
+   if(BigNumber.len == 0) {
+      BigNumber = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(Zero);
+   }
+
+   /* Compute required length so it can be returned if buffer is too small */
+   switch(uType) {
+
+      case QCBOR_TYPE_POSBIGNUM:
+         uLen = BigNumber.len;
+         break;
+
+      case QCBOR_TYPE_NEGBIGNUM:
+         uLen = BigNumber.len;
+         if(UsefulBuf_IsValue(UsefulBuf_SkipLeading(BigNumber, 0), 0xff) == SIZE_MAX) {
+            uLen++;
+         }
+         break;
+
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   *pBigNumber = (UsefulBufC){NULL, uLen};
+
+   if(BigNumberBuf.len < uLen || uLen == 0 || BigNumberBuf.ptr == NULL) {
+      return BigNumberBuf.ptr == NULL ? QCBOR_SUCCESS : QCBOR_ERR_BUFFER_TOO_SMALL;
+      /* Buffer is too short or type is wrong */
+   }
+
+
+   if(uType == QCBOR_TYPE_POSBIGNUM) {
+      *pBigNumber = UsefulBuf_Copy(BigNumberBuf, BigNumber);
+      *pbIsNegative = false;
+   } else if(uType == QCBOR_TYPE_NEGBIGNUM) {
+      /* The messy one. Take the stuff in the buffer and copy it to
+       * the new buffer, adding one to it. This might be one byte
+       * bigger than the original because of the carry from adding
+       * one.*/
+      *pbIsNegative = true;
+      *pBigNumber = QCBORDecode_BigNumberCopyPlusOne(BigNumber, BigNumberBuf);
+   }
+
+   return QCBOR_SUCCESS;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+QCBORError
+QCBORDecode_ProcessBigNumber(const QCBORItem Item,
+                             UsefulBuf       BigNumberBuf,
+                             UsefulBufC     *pBigNumber,
+                             bool           *pbIsNegative)
+{
+   QCBORError  uResult;
+   size_t      uLen;
+   int         uType;
+
+   uType = Item.uDataType;
+
+   switch(uType) {
+      case QCBOR_TYPE_POSBIGNUM:
+      case QCBOR_TYPE_NEGBIGNUM:
+      case QCBOR_TYPE_BYTE_STRING:
+         return QCBORDecode_ProcessBigNumberNoPreferred(Item, BigNumberBuf, pBigNumber, pbIsNegative);
+         break;
+
+      case QCBOR_TYPE_INT64:
+         uLen = QCBORDecode_Private_CountNonZeroBytes((uint64_t)ABSOLUTE_VALUE(Item.val.int64));
+         break;
+
+      case QCBOR_TYPE_UINT64:
+         uLen = QCBORDecode_Private_CountNonZeroBytes(Item.val.uint64);
+         break;
+
+      case QCBOR_TYPE_65BIT_NEG_INT:
+         uLen = Item.val.uint64 == UINT64_MAX ? 9 : QCBORDecode_Private_CountNonZeroBytes(Item.val.uint64);
+         break;
+
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+
+   *pBigNumber = (UsefulBufC){NULL, uLen};
+
+   if(BigNumberBuf.len < uLen || uLen == 0 || BigNumberBuf.ptr == NULL) {
+      return BigNumberBuf.ptr == NULL ? QCBOR_SUCCESS : QCBOR_ERR_BUFFER_TOO_SMALL;
+      /* Buffer is too short or type is wrong */
+   }
+
+   uResult = QCBOR_SUCCESS;
+
+   if(uType == QCBOR_TYPE_UINT64) {
+      *pBigNumber = QCBORDecode_Private_UIntToBigNumber(Item.val.uint64, BigNumberBuf);
+      *pbIsNegative = false;
+   } else if(uType == QCBOR_TYPE_INT64) {
+      /* Offset of 1 for negative numbers already performed */
+      *pbIsNegative = Item.val.int64 < 0;
+      *pBigNumber = QCBORDecode_Private_UIntToBigNumber((uint64_t)(*pbIsNegative ? -Item.val.int64 : Item.val.int64), BigNumberBuf);
+   } else if(uType == QCBOR_TYPE_65BIT_NEG_INT) {
+      /* Offset of 1 for negative numbers NOT already performed */
+      *pbIsNegative = true;
+      if(Item.val.uint64 == UINT64_MAX) {
+         /* The one value that can't be done with a computation
+          * because it would overflow a uint64_t */
+         static const uint8_t TwoToThe64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+         *pBigNumber = UsefulBuf_Copy(BigNumberBuf, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(TwoToThe64));
+      } else {
+         /* +1 because negative big numbers are encoded one less than actual */
+         *pBigNumber = QCBORDecode_Private_UIntToBigNumber(Item.val.uint64 + 1, BigNumberBuf);
+      }
+   }
+
+   return uResult;
+}
+
+
+
+static const uint64_t QCBORDecode_Private_BigNumberTagNumbers[] = {
+   CBOR_TAG_POS_BIGNUM,
+   CBOR_TAG_NEG_BIGNUM,
+   CBOR_TAG_INVALID64};
+
+static const uint8_t QCBORDecode_Private_BigNumberTypes[] = {
+   QCBOR_TYPE_INT64,
+   QCBOR_TYPE_UINT64,
+   QCBOR_TYPE_65BIT_NEG_INT,
+   QCBOR_TYPE_POSBIGNUM,
+   QCBOR_TYPE_NEGBIGNUM,
+   QCBOR_TYPE_NONE};
+
+#define QCBORDecode_Private_BigNumberTypesNoPreferred &QCBORDecode_Private_BigNumberTypes[3]
+
+/**
+ * @brief Common processing for a big number tag.
+ *
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[in] pItem            The item with the date.
+ * @param[out] pBignumber          The returned big number
+ * @param[out] pbIsNegative  The returned sign of the big number.
+ *
+ * Common processing for the big number tag. Mostly make sure
+ * the tag content is correct and copy forward any further other tag
+ * numbers.
+ */
+static void
+QCBORDecode_Private_BigNumberRawMain(QCBORDecodeContext *pMe,
+                                     const uint8_t       uTagRequirement,
+                                     QCBORItem          *pItem,
+                                     UsefulBufC         *pBignumber,
+                                     bool               *pbIsNegative,
+                                     size_t              uOffset)
+{
+   QCBORDecode_Private_ProcessTagItemMulti(pMe,
+                                           pItem,
+                                           uTagRequirement,
+                                           QCBORDecode_Private_BigNumberTypesNoPreferred,
+                                           QCBORDecode_Private_BigNumberTagNumbers,
+                                           QCBORDecode_StringsTagCB,
+                                           uOffset);
+   if(pMe->uLastError) {
+      return;
+   }
+
+   if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
+      *pbIsNegative = false;
+   } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
+      *pbIsNegative = true;
+   }
+   *pBignumber = pItem->val.bigNum;
+}
+
+
+static void
+QCBORDecode_Private_BigNumberNoPreferredMain(QCBORDecodeContext *pMe,
+                                             const uint8_t       uTagRequirement,
+                                             QCBORItem          *pItem,
+                                             const size_t        uOffset,
+                                             UsefulBuf           BigNumberBuf,
+                                             UsefulBufC         *pBigNumber,
+                                             bool               *pbIsNegative)
+{
+   QCBORDecode_Private_ProcessTagItemMulti(pMe,
+                                           pItem,
+                                           uTagRequirement,
+                                           QCBORDecode_Private_BigNumberTypesNoPreferred,
+                                           QCBORDecode_Private_BigNumberTagNumbers,
+                                           QCBORDecode_StringsTagCB,
+                                           uOffset);
+   if(pMe->uLastError) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBORDecode_ProcessBigNumberNoPreferred(*pItem, BigNumberBuf, pBigNumber, pbIsNegative);
+}
+
+
+static void
+QCBORDecode_Private_BigNumberMain(QCBORDecodeContext *pMe,
+                                  const uint8_t       uTagRequirement,
+                                  QCBORItem          *pItem,
+                                  const size_t        uOffset,
+                                  UsefulBuf           BigNumberBuf,
+                                  UsefulBufC         *pBigNumber,
+                                  bool               *pbIsNegative)
+{
+   QCBORDecode_Private_ProcessTagItemMulti(pMe,
+                                           pItem,
+                                           uTagRequirement,
+                                           QCBORDecode_Private_BigNumberTypes,
+                                           QCBORDecode_Private_BigNumberTagNumbers,
+                                           QCBORDecode_StringsTagCB,
+                                           uOffset);
+   if(pMe->uLastError) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBORDecode_ProcessBigNumber(*pItem, BigNumberBuf, pBigNumber, pbIsNegative);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetTBigNumber(QCBORDecodeContext *pMe,
+                          const uint8_t       uTagRequirement,
+                          UsefulBuf           BigNumberBuf,
+                          UsefulBufC         *pBigNumber,
+                          bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetTBigNumberInMapN(QCBORDecodeContext *pMe,
+                                const int64_t       nLabel,
+                                const uint8_t       uTagRequirement,
+                                UsefulBuf           BigNumberBuf,
+                                UsefulBufC         *pBigNumber,
+                                bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberMain(pMe,
+                                     uTagRequirement,
+                                    &Item,
+                                     uOffset,
+                                     BigNumberBuf,
+                                     pBigNumber,
+                                     pbIsNegative);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetTBigNumberInMapSZ(QCBORDecodeContext *pMe,
+                                 const char         *szLabel,
+                                 const uint8_t       uTagRequirement,
+                                 UsefulBuf           BigNumberBuf,
+                                 UsefulBufC         *pBigNumber,
+                                 bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberMain(pMe,
+                                     uTagRequirement,
+                                    &Item,
+                                     uOffset,
+                                     BigNumberBuf,
+                                     pBigNumber,
+                                     pbIsNegative);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetTBigNumberNoPreferred(QCBORDecodeContext *pMe,
+                                     const uint8_t       uTagRequirement,
+                                     UsefulBuf           BigNumberBuf,
+                                     UsefulBufC         *pBigNumber,
+                                     bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetTBigNumberNoPreferredInMapN(QCBORDecodeContext *pMe,
+                                           const int64_t       nLabel,
+                                           const uint8_t       uTagRequirement,
+                                           UsefulBuf           BigNumberBuf,
+                                           UsefulBufC         *pBigNumber,
+                                           bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
+
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetTBigNumberNoPreferredInMapSZ(QCBORDecodeContext *pMe,
+                                            const char         *szLabel,
+                                            const uint8_t       uTagRequirement,
+                                            UsefulBuf           BigNumberBuf,
+                                            UsefulBufC         *pBigNumber,
+                                            bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
+}
+
+
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h
+ */
+void
+QCBORDecode_GetTBigNumberRaw(QCBORDecodeContext *pMe,
+                             const uint8_t       uTagRequirement,
+                             UsefulBufC         *pBignumber,
+                             bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberRawMain(pMe,
+                                        uTagRequirement,
+                                       &Item,
+                                        pBignumber,
+                                        pbIsNegative,
+                                        uOffset);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h
+ */
+void
+QCBORDecode_GetTBigNumberRawInMapN(QCBORDecodeContext *pMe,
+                                   const int64_t       nLabel,
+                                   const uint8_t       uTagRequirement,
+                                   UsefulBufC         *pBigNumber,
+                                   bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberRawMain(pMe,
+                                        uTagRequirement,
+                                       &Item,
+                                        pBigNumber,
+                                        pbIsNegative,
+                                        uOffset);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h
+ */
+void
+QCBORDecode_GetTBigNumberRawInMapSZ(QCBORDecodeContext *pMe,
+                                    const char         *szLabel,
+                                    const uint8_t       uTagRequirement,
+                                    UsefulBufC         *pBigNumber,
+                                    bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   size_t     uOffset;
+
+   QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
+   QCBORDecode_Private_BigNumberRawMain(pMe,
+                                        uTagRequirement,
+                                       &Item,
+                                        pBigNumber,
+                                        pbIsNegative,
+                                        uOffset);
+}
+
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+
+
+// TODO: relocate these notes?
 /* Some notes from the work to disable tags.
  * Some are out of date since tag refactoring.
  *
@@ -7137,13 +6525,13 @@
       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
       case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
          *pnExponent = pItem->val.expAndMantissa.nExponent;
-         uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
+         uErr = QCBORDecode_Private_PositiveBigNumberToInt(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
          break;
 
       case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
       case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
          *pnExponent = pItem->val.expAndMantissa.nExponent;
-         uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
+         uErr = QCBORDecode_Private_NegativeBigNumberToInt(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
          break;
 #endif /* QCBOR_DISABLE_TAGS */
 
@@ -7222,7 +6610,7 @@
           * big number arithmetic. This is a bug fix for QCBOR v1.5.
           */
          uMantissa--;
-         *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa, BufferForMantissa);
+         *pMantissa = QCBORDecode_Private_UIntToBigNumber(uMantissa, BufferForMantissa);
          *pnExponent = pItem->val.expAndMantissa.nExponent;
          break;
 
@@ -7745,6 +7133,9 @@
 }
 
 
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
 void
 QCBORDecode_GetTBigFloatBigMantissaRaw(QCBORDecodeContext *pMe,
                                        const uint8_t       uTagRequirement,
@@ -7768,9 +7159,6 @@
                                              pnExponent);
 }
 
-
-
-
 /*
  * Public function, see header qcbor/qcbor_decode.h file
  */
@@ -7826,529 +7214,1108 @@
                                              pnExponent);
 }
 
-
 #endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
-#if !defined(USEFULBUF_DISABLE_ALL_FLOAT) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
-/*
- * Public function, see header qcbor/qcbor_spiffy_decode.h file
+
+
+/**
+ * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetInt64Convert().
  */
 void
-QCBORDecode_GetNumberConvertPrecisely(QCBORDecodeContext *pMe,
-                                      QCBORItem          *pNumber)
+QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
+                                    uint32_t            uConvertTypes,
+                                    int64_t            *pnValue,
+                                    QCBORItem          *pItem)
 {
-   QCBORItem            Item;
-   struct IEEE754_ToInt ToInt;
-   double               dNum;
-   QCBORError           uError;
+   QCBORDecode_VGetNext(pMe, pItem);
+   if(pMe->uLastError) {
+      return;
+   }
 
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
+                                                         uConvertTypes,
+                                                         pnValue);
+}
+
+/**
+ * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] nLabel         Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetInt64ConvertInMapN().
+ */
+void
+QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
+                                          int64_t             nLabel,
+                                          uint32_t            uConvertTypes,
+                                          int64_t            *pnValue,
+                                          QCBORItem          *pItem)
+{
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
    if(pMe->uLastError != QCBOR_SUCCESS) {
       return;
    }
 
-   // TODO:VGetNext?
-   uError = QCBORDecode_GetNext(pMe, &Item);
-   if(uError != QCBOR_SUCCESS) {
-      *pNumber = Item;
-      pMe->uLastError = (uint8_t)uError;
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
+                                                         uConvertTypes,
+                                                         pnValue);
+}
+
+/**
+ * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] szLabel        Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetInt64ConvertInMapSZ().
+ */
+void
+QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
+                                           const char *         szLabel,
+                                           uint32_t             uConvertTypes,
+                                           int64_t             *pnValue,
+                                           QCBORItem           *pItem)
+{
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
       return;
    }
 
-   switch(Item.uDataType) {
-      case QCBOR_TYPE_INT64:
-      case QCBOR_TYPE_UINT64:
-         *pNumber = Item;
-         break;
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
+                                                         uConvertTypes,
+                                                         pnValue);
+}
 
-      case QCBOR_TYPE_DOUBLE:
-         ToInt = IEEE754_DoubleToInt(Item.val.dfnum);
-         if(ToInt.type == IEEE754_ToInt_IS_INT) {
-            pNumber->uDataType = QCBOR_TYPE_INT64;
-            pNumber->val.int64 = ToInt.integer.is_signed;
-         } else if(ToInt.type == IEEE754_ToInt_IS_UINT) {
-            if(ToInt.integer.un_signed <= INT64_MAX) {
-               /* Do the same as base QCBOR integer decoding */
-               pNumber->uDataType = QCBOR_TYPE_INT64;
-               pNumber->val.int64 = (int64_t)ToInt.integer.un_signed;
-            } else {
-               pNumber->uDataType = QCBOR_TYPE_UINT64;
-               pNumber->val.uint64 = ToInt.integer.un_signed;
-            }
+
+/**
+ * @brief Convert many number types to an int64_t.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
+                              const uint32_t   uConvertTypes,
+                              int64_t         *pnValue)
+{
+   switch(pItem->uDataType) {
+
+      case QCBOR_TYPE_POSBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            return QCBORDecode_Private_PositiveBigNumberToInt(pItem->val.bigNum, pnValue);
          } else {
-            *pNumber = Item;
+            return QCBOR_ERR_UNEXPECTED_TYPE;
          }
          break;
 
+      case QCBOR_TYPE_NEGBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            return QCBORDecode_Private_NegativeBigNumberToInt(pItem->val.bigNum, pnValue);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                 &QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+            return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            int64_t    nMantissa;
+            QCBORError uErr;
+            uErr = QCBORDecode_Private_PositiveBigNumberToInt(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
+            if(uErr) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentiateNN(nMantissa,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            int64_t    nMantissa;
+            QCBORError uErr;
+            uErr = QCBORDecode_Private_NegativeBigNumberToInt(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
+            if(uErr) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentiateNN(nMantissa,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            int64_t    nMantissa;
+            QCBORError uErr;
+            uErr = QCBORDecode_Private_PositiveBigNumberToInt(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
+            if(uErr) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentiateNN(nMantissa,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            int64_t    nMantissa;
+            QCBORError uErr;
+            uErr = QCBORDecode_Private_NegativeBigNumberToInt(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
+            if(uErr) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentiateNN(nMantissa,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;   }
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
+                               const uint32_t      uConvertTypes,
+                               int64_t            *pnValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
+                                                            uConvertTypes,
+                                                            pnValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
+                                     const int64_t       nLabel,
+                                     const uint32_t      uConvertTypes,
+                                     int64_t            *pnValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
+                                             nLabel,
+                                             uConvertTypes,
+                                             pnValue,
+                                             &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
+                                                            uConvertTypes,
+                                                            pnValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
+                                      const char         *szLabel,
+                                      const uint32_t      uConvertTypes,
+                                      int64_t            *pnValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
+                                              szLabel,
+                                              uConvertTypes,
+                                              pnValue,
+                                              &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
+                                                            uConvertTypes,
+                                                            pnValue);
+}
+
+
+/**
+ * @brief Convert many number types to an uint64_t.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
+                            const uint32_t   uConvertTypes,
+                            uint64_t        *puValue)
+{
+   switch(pItem->uDataType) {
+      case QCBOR_TYPE_DOUBLE:
       case QCBOR_TYPE_FLOAT:
-         ToInt = IEEE754_SingleToInt(Item.val.fnum);
-         if(ToInt.type == IEEE754_ToInt_IS_INT) {
-            pNumber->uDataType = QCBOR_TYPE_INT64;
-            pNumber->val.int64 = ToInt.integer.is_signed;
-         } else if(ToInt.type == IEEE754_ToInt_IS_UINT) {
-            if(ToInt.integer.un_signed <= INT64_MAX) {
-               /* Do the same as base QCBOR integer decoding */
-               pNumber->uDataType = QCBOR_TYPE_INT64;
-               pNumber->val.int64 = (int64_t)ToInt.integer.un_signed;
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+            // Can't use llround here because it will not convert values
+            // greater than INT64_MAX and less than UINT64_MAX that
+            // need to be converted so it is more complicated.
+            feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
+            if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
+               if(isnan(pItem->val.dfnum)) {
+                  return QCBOR_ERR_FLOAT_EXCEPTION;
+               } else if(pItem->val.dfnum < 0) {
+                  return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+               } else {
+                  double dRounded = round(pItem->val.dfnum);
+                  // See discussion in DecodeDateEpoch() for
+                  // explanation of - 0x7ff
+                  if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
+                     return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+                  }
+                  *puValue = (uint64_t)dRounded;
+               }
             } else {
-               pNumber->uDataType = QCBOR_TYPE_UINT64;
-               pNumber->val.uint64 = ToInt.integer.un_signed;
+               if(isnan(pItem->val.fnum)) {
+                  return QCBOR_ERR_FLOAT_EXCEPTION;
+               } else if(pItem->val.fnum < 0) {
+                  return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+               } else {
+                  float fRounded = roundf(pItem->val.fnum);
+                  // See discussion in DecodeDateEpoch() for
+                  // explanation of - 0x7ff
+                  if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
+                     return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+                  }
+                  *puValue = (uint64_t)fRounded;
+               }
+            }
+            if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
+               // round() and roundf() shouldn't result in exceptions here, but
+               // catch them to be robust and thorough. Don't try to
+               // distinguish between the various exceptions because it seems
+               // they vary by CPU, compiler and OS.
+               return QCBOR_ERR_FLOAT_EXCEPTION;
+            }
+
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+         break;
+
+      case QCBOR_TYPE_INT64:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            if(pItem->val.int64 >= 0) {
+               *puValue = (uint64_t)pItem->val.int64;
+            } else {
+               return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
             }
          } else {
-            *pNumber = Item;
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_UINT64:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            *puValue = pItem->val.uint64;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
          }
          break;
 
       case QCBOR_TYPE_65BIT_NEG_INT:
-         if(Item.val.uint64 == UINT64_MAX) {
-            /* The value -18446744073709551616 is encoded as an
-             * unsigned 18446744073709551615. It's a whole number that
-             * needs to be returned as a double. It can't be handled
-             * by IEEE754_UintToDouble because 18446744073709551616
-             * doesn't fit into a uint64_t. You can't get it by adding
-             * 1 to 18446744073709551615.
-             */
-            pNumber->val.dfnum = -18446744073709551616.0;
-            pNumber->uDataType = QCBOR_TYPE_DOUBLE;
-         } else {
-            dNum = IEEE754_UintToDouble(Item.val.uint64 + 1, 1);
-            if(dNum == IEEE754_UINT_TO_DOUBLE_OOB) {
-               *pNumber = Item;
-            } else {
-               pNumber->val.dfnum = dNum;
-               pNumber->uDataType = QCBOR_TYPE_DOUBLE;
-            }
-         }
-         break;
-
-      default:
-         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
-         pNumber->uDataType = QCBOR_TYPE_NONE;
-         break;
-   }
-}
-
-#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
-
-
-
-
-static UsefulBufC
-QCBORDecode_IntToBigNumber(uint64_t         uNum,
-                           const UsefulBuf  BigNumberBuf)
-{
-   UsefulOutBuf OB;
-
-   /* With a UsefulOutBuf, there's no pointer math here. */
-   UsefulOutBuf_Init(&OB, BigNumberBuf);
-
-   /* Must copy one byte even if zero.  The loop, mask and shift
-    * algorithm provides endian conversion.
-    */
-   do {
-      UsefulOutBuf_InsertByte(&OB, uNum & 0xff, 0);
-      uNum >>= 8;
-   } while(uNum);
-
-   return UsefulOutBuf_OutUBuf(&OB);
-}
-
-
-/* Add one to the big number and put the result in a new UsefulBufC
- * from storage in UsefulBuf.
- *
- * Leading zeros must be removed before calling this.
- *
- * Code Reviewers: THIS FUNCTION DOES POINTER MATH
- */
-static UsefulBufC
-QCBORDecode_BigNumberCopyPlusOne(UsefulBufC BigNumber,
-                                 UsefulBuf  BigNumberBuf)
-{
-   uint8_t        uCarry;
-   uint8_t        uSourceValue;
-   const uint8_t *pSource;
-   uint8_t       *pDest;
-   ptrdiff_t      uDestBytesLeft;
-
-   /* Start adding at the LSB */
-   pSource = &((const uint8_t *)BigNumber.ptr)[BigNumber.len-1];
-   pDest   = &((uint8_t *)BigNumberBuf.ptr)[BigNumberBuf.len-1];
-
-   uCarry = 1; /* Gets set back to zero if add the next line doesn't wrap */
-   *pDest = *pSource + 1;
-   while(1) {
-      /* Wrap around from 0xff to 0 is a defined operation for
-       * unsigned addition in C.*/
-      if(*pDest != 0) {
-         /*  The add operation didn't wrap so no more carry. This
-          * funciton only adds one, so when there is no more carry,
-          * carrying is over to the end.
-          */
-         uCarry = 0;
-      }
-
-      uDestBytesLeft = pDest - (uint8_t *)BigNumberBuf.ptr;
-      if(pSource <= (const uint8_t *)BigNumber.ptr && uCarry == 0) {
-         break; /* Successful exit */
-      }
-      if(pSource > (const uint8_t *)BigNumber.ptr) {
-         uSourceValue = *--pSource;
-      } else {
-         /* All source bytes processed, but not the last carry */
-         uSourceValue = 0;
-      }
-
-      pDest--;
-      if(uDestBytesLeft < 0) {
-         return NULLUsefulBufC; /* Not enough space in destination buffer */
-      }
-
-      *pDest = uSourceValue + uCarry;
-   }
-
-   return (UsefulBufC){pDest, BigNumberBuf.len - (size_t)uDestBytesLeft};
-}
-
-
-/* This returns 1 when uNum is 0 */
-static size_t
-QCBORDecode_Private_CountNonZeroBytes(uint64_t uNum)
-{
-   size_t uCount = 0;
-   do {
-      uCount++;
-      uNum >>= 8;
-   } while(uNum);
-
-   return uCount;
-}
-
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h
- */
-QCBORError
-QCBORDecode_ProcessBigNumberNoPreferred(const QCBORItem Item,
-                                        const UsefulBuf BigNumberBuf,
-                                        UsefulBufC     *pBigNumber,
-                                        bool           *pbIsNegative)
-{
-   size_t      uLen;
-   UsefulBufC  BigNumber;
-   int         uType;
-
-   uType = Item.uDataType;
-   if(uType == QCBOR_TYPE_BYTE_STRING) {
-      uType = *pbIsNegative ? QCBOR_TYPE_NEGBIGNUM : QCBOR_TYPE_POSBIGNUM;
-   }
-
-   static const uint8_t Zero[] = {0x00};
-   BigNumber = UsefulBuf_SkipLeading(Item.val.bigNum, 0);
-   if(BigNumber.len == 0) {
-      BigNumber = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(Zero);
-   }
-
-   /* Compute required length so it can be returned if buffer is too small */
-   switch(uType) {
-
-      case QCBOR_TYPE_POSBIGNUM:
-         uLen = BigNumber.len;
-         break;
-
-      case QCBOR_TYPE_NEGBIGNUM:
-         uLen = BigNumber.len;
-         if(UsefulBuf_IsValue(UsefulBuf_SkipLeading(BigNumber, 0), 0xff) == SIZE_MAX) {
-            uLen++;
-         }
-         break;
+         return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
 
       default:
          return QCBOR_ERR_UNEXPECTED_TYPE;
    }
 
-   *pBigNumber = (UsefulBufC){NULL, uLen};
-
-   if(BigNumberBuf.len < uLen || uLen == 0 || BigNumberBuf.ptr == NULL) {
-      return BigNumberBuf.ptr == NULL ? QCBOR_SUCCESS : QCBOR_ERR_BUFFER_TOO_SMALL;
-      /* Buffer is too short or type is wrong */
-   }
-
-
-   if(uType == QCBOR_TYPE_POSBIGNUM) {
-      *pBigNumber = UsefulBuf_Copy(BigNumberBuf, BigNumber);
-      *pbIsNegative = false;
-   } else if(uType == QCBOR_TYPE_NEGBIGNUM) {
-      /* The messy one. Take the stuff in the buffer and copy it to
-       * the new buffer, adding one to it. This might be one byte
-       * bigger than the original because of the carry from adding
-       * one.*/
-      *pbIsNegative = true;
-      *pBigNumber = QCBORDecode_BigNumberCopyPlusOne(BigNumber, BigNumberBuf);
-   }
-
    return QCBOR_SUCCESS;
 }
 
 
-/*
- * Public function, see header qcbor/qcbor_decode.h
+/**
+ * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetUInt64Convert().
  */
-QCBORError
-QCBORDecode_ProcessBigNumber(const QCBORItem Item,
-                             UsefulBuf       BigNumberBuf,
-                             UsefulBufC     *pBigNumber,
-                             bool           *pbIsNegative)
+void
+QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
+                                     const uint32_t      uConvertTypes,
+                                     uint64_t           *puValue,
+                                     QCBORItem          *pItem)
 {
-   QCBORError  uResult;
-   size_t      uLen;
-   int         uType;
+   QCBORDecode_VGetNext(pMe, pItem);
+   if(pMe->uLastError) {
+      return;
+   }
 
-   uType = Item.uDataType;
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
+                                                          uConvertTypes,
+                                                          puValue);
+}
 
-   switch(uType) {
+
+/**
+ * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] nLabel         Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetUInt64ConvertInMapN().
+ */
+void
+QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
+                                           const int64_t       nLabel,
+                                           const uint32_t      uConvertTypes,
+                                           uint64_t            *puValue,
+                                           QCBORItem          *pItem)
+{
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
+                                                          uConvertTypes,
+                                                          puValue);
+}
+
+
+/**
+ * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] szLabel         Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetUInt64ConvertInMapSZ().
+ */
+void
+QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
+                                            const char         *szLabel,
+                                            const uint32_t      uConvertTypes,
+                                            uint64_t           *puValue,
+                                            QCBORItem          *pItem)
+{
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
+                                                          uConvertTypes,
+                                                          puValue);
+}
+
+
+/**
+ * @brief Convert many number types to an unt64_t.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
+                               const uint32_t   uConvertTypes,
+                               uint64_t        *puValue)
+{
+   switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
+
       case QCBOR_TYPE_POSBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            return QCBORDecode_Private_PositiveBigNumberToUInt(pItem->val.bigNum, puValue);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
       case QCBOR_TYPE_NEGBIGNUM:
-      case QCBOR_TYPE_BYTE_STRING:
-         return QCBORDecode_ProcessBigNumberNoPreferred(Item, BigNumberBuf, pBigNumber, pbIsNegative);
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
+                                   pItem->val.expAndMantissa.nExponent,
+                                   puValue,
+                                   QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+            return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
+                                   pItem->val.expAndMantissa.nExponent,
+                                   puValue,
+                                   QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            uint64_t   uMantissa;
+            QCBORError uErr;
+            uErr = QCBORDecode_Private_PositiveBigNumberToUInt(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
+            if(uErr != QCBOR_SUCCESS) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentitateUU(uMantissa,
+                                                 pItem->val.expAndMantissa.nExponent,
+                                                 puValue,
+                                                 QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            uint64_t   uMantissa;
+            QCBORError uErr;
+            uErr = QCBORDecode_Private_PositiveBigNumberToUInt(pItem->val.expAndMantissa.Mantissa.bigNum,
+                                                                 &uMantissa);
+            if(uErr != QCBOR_SUCCESS) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentitateUU(uMantissa,
+                                                 pItem->val.expAndMantissa.nExponent,
+                                                 puValue,
+                                                 QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
+                                const uint32_t      uConvertTypes,
+                                uint64_t           *puValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             puValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
+                                      const int64_t       nLabel,
+                                      const uint32_t      uConvertTypes,
+                                      uint64_t           *puValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
+                                              nLabel,
+                                              uConvertTypes,
+                                              puValue,
+                                              &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             puValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
+                                       const char         *szLabel,
+                                       const uint32_t      uConvertTypes,
+                                       uint64_t           *puValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
+                                               szLabel,
+                                               uConvertTypes,
+                                               puValue,
+                                               &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             puValue);
+}
+
+
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/**
+ * @brief Basic conversions to a double.
+ *
+ * @param[in] pItem          The item to convert
+ * @param[in] uConvertTypes  Bit flags indicating source types for conversion
+ * @param[out] pdValue       The value converted to a double
+ *
+ * This does the conversions that don't need much object code,
+ * the conversions from int, uint and float to double.
+ *
+ * See QCBOR_Private_DoubleConvertAll() for the full set
+ * of conversions.
+ */
+static QCBORError
+QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
+                            const uint32_t   uConvertTypes,
+                            double          *pdValue)
+{
+   switch(pItem->uDataType) {
+      case QCBOR_TYPE_FLOAT:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+            if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+               // Simple cast does the job.
+               *pdValue = (double)pItem->val.fnum;
+            } else {
+               return QCBOR_ERR_UNEXPECTED_TYPE;
+            }
+         }
+#else /* QCBOR_DISABLE_FLOAT_HW_USE */
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+         break;
+
+      case QCBOR_TYPE_DOUBLE:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+            if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+               *pdValue = pItem->val.dfnum;
+            } else {
+               return QCBOR_ERR_UNEXPECTED_TYPE;
+            }
+         }
          break;
 
       case QCBOR_TYPE_INT64:
-         uLen = QCBORDecode_Private_CountNonZeroBytes((uint64_t)ABSOLUTE_VALUE(Item.val.int64));
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            // A simple cast seems to do the job with no worry of exceptions.
+            // There will be precision loss for some values.
+            *pdValue = (double)pItem->val.int64;
+
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
          break;
 
       case QCBOR_TYPE_UINT64:
-         uLen = QCBORDecode_Private_CountNonZeroBytes(Item.val.uint64);
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            // A simple cast seems to do the job with no worry of exceptions.
+            // There will be precision loss for some values.
+            *pdValue = (double)pItem->val.uint64;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
          break;
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
 
       case QCBOR_TYPE_65BIT_NEG_INT:
-         uLen = Item.val.uint64 == UINT64_MAX ? 9 : QCBORDecode_Private_CountNonZeroBytes(Item.val.uint64);
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         // TODO: don't use float HW. We have the function to do it.
+         *pdValue = -(double)pItem->val.uint64 - 1;
          break;
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
 
       default:
          return QCBOR_ERR_UNEXPECTED_TYPE;
    }
 
-
-   *pBigNumber = (UsefulBufC){NULL, uLen};
-
-   if(BigNumberBuf.len < uLen || uLen == 0 || BigNumberBuf.ptr == NULL) {
-      return BigNumberBuf.ptr == NULL ? QCBOR_SUCCESS : QCBOR_ERR_BUFFER_TOO_SMALL;
-      /* Buffer is too short or type is wrong */
-   }
-
-   uResult = QCBOR_SUCCESS;
-
-   if(uType == QCBOR_TYPE_UINT64) {
-      *pBigNumber = QCBORDecode_IntToBigNumber(Item.val.uint64, BigNumberBuf);
-      *pbIsNegative = false;
-   } else if(uType == QCBOR_TYPE_INT64) {
-      /* Offset of 1 for negative numbers already performed */
-      *pbIsNegative = Item.val.int64 < 0;
-      *pBigNumber = QCBORDecode_IntToBigNumber((uint64_t)(*pbIsNegative ? -Item.val.int64 : Item.val.int64), BigNumberBuf);
-   } else if(uType == QCBOR_TYPE_65BIT_NEG_INT) {
-      /* Offset of 1 for negative numbers NOT already performed */
-      *pbIsNegative = true;
-      if(Item.val.uint64 == UINT64_MAX) {
-         /* The one value that can't be done with a computation
-          * because it would overflow a uint64_t */
-         static const uint8_t TwoToThe64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-         *pBigNumber = UsefulBuf_Copy(BigNumberBuf, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(TwoToThe64));
-      } else {
-         // TODO: why + 1; test it; document it
-         *pBigNumber = QCBORDecode_IntToBigNumber(Item.val.uint64 + 1, BigNumberBuf);
-      }
-   }
-
-   return uResult;
+   return QCBOR_SUCCESS;
 }
 
 
-static const uint64_t QCBORDecode_Private_BigNumberTagNumbers[] = {
-   CBOR_TAG_POS_BIGNUM,
-   CBOR_TAG_NEG_BIGNUM,
-   CBOR_TAG_INVALID64};
-
-static const uint8_t QCBORDecode_Private_BigNumberTypes[] = {
-   QCBOR_TYPE_INT64,
-   QCBOR_TYPE_UINT64,
-   QCBOR_TYPE_65BIT_NEG_INT,
-   QCBOR_TYPE_POSBIGNUM,
-   QCBOR_TYPE_NEGBIGNUM,
-   QCBOR_TYPE_NONE};
-
-#define QCBORDecode_Private_BigNumberTypesNoPreferred &QCBORDecode_Private_BigNumberTypes[3]
-
-
-static void
-QCBORDecode_Private_BigNumberNoPreferredMain(QCBORDecodeContext *pMe,
-                                             const uint8_t       uTagRequirement,
-                                             QCBORItem          *pItem,
-                                             const size_t        uOffset,
-                                             UsefulBuf           BigNumberBuf,
-                                             UsefulBufC         *pBigNumber,
-                                             bool               *pbIsNegative)
+/**
+ * @brief  Almost-public method to decode a number and convert to double (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] uConvertTypes  Bit mask list of conversion options
+ * @param[out] pdValue       The output of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetDoubleConvert().
+ */
+void
+QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
+                                     const uint32_t      uConvertTypes,
+                                     double             *pdValue,
+                                     QCBORItem          *pItem)
 {
-   QCBORDecode_Private_ProcessTagItemMulti(pMe,
-                                           pItem,
-                                           uTagRequirement,
-                                           QCBORDecode_Private_BigNumberTypesNoPreferred,
-                                           QCBORDecode_Private_BigNumberTagNumbers,
-                                           QCBORDecode_StringsTagCB,
-                                           uOffset);
+   QCBORDecode_VGetNext(pMe, pItem);
    if(pMe->uLastError) {
       return;
    }
 
-   pMe->uLastError = (uint8_t)QCBORDecode_ProcessBigNumberNoPreferred(*pItem, BigNumberBuf, pBigNumber, pbIsNegative);
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
+                                                          uConvertTypes,
+                                                          pdValue);
 }
 
 
-static void
-QCBORDecode_Private_BigNumberMain(QCBORDecodeContext *pMe,
-                                  const uint8_t       uTagRequirement,
-                                  QCBORItem          *pItem,
-                                  const size_t        uOffset,
-                                  UsefulBuf           BigNumberBuf,
-                                  UsefulBufC         *pBigNumber,
-                                  bool               *pbIsNegative)
-{
-   QCBORDecode_Private_ProcessTagItemMulti(pMe,
-                                           pItem,
-                                           uTagRequirement,
-                                           QCBORDecode_Private_BigNumberTypes,
-                                           QCBORDecode_Private_BigNumberTagNumbers,
-                                           QCBORDecode_StringsTagCB,
-                                           uOffset);
-   if(pMe->uLastError) {
-      return;
-   }
-
-   pMe->uLastError = (uint8_t)QCBORDecode_ProcessBigNumber(*pItem, BigNumberBuf, pBigNumber, pbIsNegative);
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h
+/**
+ * @brief  Almost-public method to decode a number and convert to double (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] nLabel         Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options
+ * @param[out] pdValue       The output of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetDoubleConvertInMapN().
  */
 void
-QCBORDecode_GetTBigNumber(QCBORDecodeContext *pMe,
-                          const uint8_t       uTagRequirement,
-                          UsefulBuf           BigNumberBuf,
-                          UsefulBufC         *pBigNumber,
-                          bool               *pbIsNegative)
-{
-   QCBORItem  Item;
-   size_t     uOffset;
-
-   QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
-}
-
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h
- */
-void
-QCBORDecode_GetTBigNumberInMapN(QCBORDecodeContext *pMe,
-                                const int64_t       nLabel,
-                                const uint8_t       uTagRequirement,
-                                UsefulBuf           BigNumberBuf,
-                                UsefulBufC         *pBigNumber,
-                                bool               *pbIsNegative)
-{
-   QCBORItem  Item;
-   size_t     uOffset;
-
-   QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberMain(pMe,
-                                     uTagRequirement,
-                                    &Item,
-                                     uOffset,
-                                     BigNumberBuf,
-                                     pBigNumber,
-                                     pbIsNegative);
-}
-
-/*
- * Public function, see header qcbor/qcbor_decode.h
- */
-void
-QCBORDecode_GetTBigNumberInMapSZ(QCBORDecodeContext *pMe,
-                                 const char         *szLabel,
-                                 const uint8_t       uTagRequirement,
-                                 UsefulBuf           BigNumberBuf,
-                                 UsefulBufC         *pBigNumber,
-                                 bool               *pbIsNegative)
-{
-   QCBORItem  Item;
-   size_t     uOffset;
-
-   QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberMain(pMe,
-                                     uTagRequirement,
-                                    &Item,
-                                     uOffset,
-                                     BigNumberBuf,
-                                     pBigNumber,
-                                     pbIsNegative);
-}
-
-
-/*
- * Public function, see header qcbor/qcbor_decode.h
- */
-void
-QCBORDecode_GetTBigNumberNoPreferred(QCBORDecodeContext *pMe,
-                                     const uint8_t       uTagRequirement,
-                                     UsefulBuf           BigNumberBuf,
-                                     UsefulBufC         *pBigNumber,
-                                     bool               *pbIsNegative)
-{
-   QCBORItem  Item;
-   size_t     uOffset;
-
-   QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
-}
-
-/*
- * Public function, see header qcbor/qcbor_decode.h
- */
-void
-QCBORDecode_GetTBigNumberNoPreferredInMapN(QCBORDecodeContext *pMe,
+QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
                                            const int64_t       nLabel,
-                                           const uint8_t       uTagRequirement,
-                                           UsefulBuf           BigNumberBuf,
-                                           UsefulBufC         *pBigNumber,
-                                           bool               *pbIsNegative)
+                                           const uint32_t      uConvertTypes,
+                                           double             *pdValue,
+                                           QCBORItem          *pItem)
 {
-   QCBORItem  Item;
-   size_t     uOffset;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
 
-   QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
-
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
+                                                          uConvertTypes,
+                                                          pdValue);
 }
 
-/*
- * Public function, see header qcbor/qcbor_decode.h
+
+/**
+ * @brief  Almost-public method to decode a number and convert to double (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] szLabel        Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options
+ * @param[out] pdValue       The output of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetDoubleConvertInMapSZ().
  */
 void
-QCBORDecode_GetTBigNumberNoPreferredInMapSZ(QCBORDecodeContext *pMe,
+QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
                                             const char         *szLabel,
-                                            const uint8_t       uTagRequirement,
-                                            UsefulBuf           BigNumberBuf,
-                                            UsefulBufC         *pBigNumber,
-                                            bool               *pbIsNegative)
+                                            const uint32_t      uConvertTypes,
+                                            double             *pdValue,
+                                            QCBORItem          *pItem)
 {
-   QCBORItem  Item;
-   size_t     uOffset;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
 
-   QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
-   QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
+                                                          uConvertTypes,
+                                                          pdValue);
 }
 
+
+/**
+ * @brief Convert many number types to a double.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pdValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
+                               const uint32_t   uConvertTypes,
+                               double          *pdValue)
+{
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+   /*
+    * What Every Computer Scientist Should Know About Floating-Point Arithmetic
+    * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
+    */
+   switch(pItem->uDataType) {
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            // Underflow gives 0, overflow gives infinity
+            *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
+                        pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
+            // Underflow gives 0, overflow gives infinity
+            *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
+                              exp2((double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+      case QCBOR_TYPE_POSBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            *pdValue = QCBORDecode_Private_BigNumberToDouble(pItem->val.bigNum);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_NEGBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            *pdValue = -1-QCBORDecode_Private_BigNumberToDouble(pItem->val.bigNum);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            double dMantissa = QCBORDecode_Private_BigNumberToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
+            *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            /* Must subtract 1 for CBOR negative integer offset */
+            double dMantissa = -1-QCBORDecode_Private_BigNumberToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
+            *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+            double dMantissa = QCBORDecode_Private_BigNumberToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
+            *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+            double dMantissa = -1-QCBORDecode_Private_BigNumberToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
+            *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   return QCBOR_SUCCESS;
+
+#else
+   (void)pItem;
+   (void)uConvertTypes;
+   (void)pdValue;
+   return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
+                                const uint32_t      uConvertTypes,
+                                double             *pdValue)
+{
+
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             pdValue);
+}
+
+
+/*
+ *  Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
+                                      const int64_t       nLabel,
+                                      const uint32_t      uConvertTypes,
+                                      double             *pdValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
+                                              nLabel,
+                                              uConvertTypes,
+                                              pdValue,
+                                              &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             pdValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
+                                       const char         *szLabel,
+                                       const uint32_t      uConvertTypes,
+                                       double             *pdValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
+                                               szLabel,
+                                               uConvertTypes,
+                                               pdValue,
+                                               &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             pdValue);
+}
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
 // TODO: re order above functions in tag number order
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 47208a8..a8f01fe 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -795,8 +795,8 @@
  *
  * @return If there is a carry, \c true.
  *
- * If this returns @c true, then @c BigNumber - 1 is
- * one byte shorter than @c BigNumber.
+ * If this returns @c true, then @c BigNumber - 1 is one byte shorter
+ * than @c BigNumber.
  **/
 static bool
 QCBOREncode_Private_BigNumberCarry(const UsefulBufC BigNumber)
@@ -821,7 +821,7 @@
 }
 
 
-/*
+/**
  * @brief Output negative bignum bytes with subtraction of 1.
  *
  * @param[in] pMe              The decode context.
@@ -864,7 +864,7 @@
    if(bCarry && BigNumber.len > 1 && UsefulBufC_NTH_BYTE(BigNumber, 0) >= 1) {
       uLen--;
    }
-   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uLen, 0);
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uLen,0);
 
    SubString = BigNumber;
    bCopiedSomething = false;
@@ -887,61 +887,19 @@
 
 
 /**
- * @brief Convert a negative big number to unsigned int if possible.
- *
- * @param[in] BigNumber  The negative big number.
- * @param[out] puInt     The converted negative big number.
- *
- * @return If conversion was possible, returns @c true.
- *
- * The parameters here are unsigned integers, but they always
- * represent negative numbers.
- *
- * Conversion is possible if the big number is greater than -(2^64).
- * Conversion include offset of 1 for encoding CBOR negative numbers.
- */
-static bool
-QCBOREncode_Private_NegativeBigNumberToUInt(const UsefulBufC BigNumber, uint64_t *puInt)
-{
-   bool bIs2exp64;
-
-   static const uint8_t twoExp64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-   bIs2exp64 = ! UsefulBuf_Compare(BigNumber, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(twoExp64));
-
-   if(BigNumber.len > 8 && !bIs2exp64) {
-      return false;
-   }
-
-   /* Must convert to CBOR type 1, a negative integer */
-   if(bIs2exp64) {
-      /* 2^64 is a 9 byte big number. Since negative numbers are offset
-       * by one in CBOR, it can be encoded as a type 1 negative. The
-       * conversion below won't work because the uInt will overflow
-       * before the subtraction of 1.
-       */
-      *puInt = UINT64_MAX;
-   } else {
-      *puInt = QCBOREncode_Private_BigNumberToUInt(BigNumber);
-      (*puInt)--; /* CBOR's negative offset of 1 */
-   }
-   return true;
-}
-
-
-/**
  * @brief Remove leading zeros.
  *
- * @param[in] BigNumber  The negative big number.
+ * @param[in] BigNumber  The big number.
  *
  * @return Big number with no leading zeros.
  *
- * If the big number is all zeros, this returns a big number
- * that is one zero rather than the empty string.
+ * If the big number is all zeros, this returns a big number that is
+ * one zero rather than the empty string.
  *
- * 3.4.3 does not explicitly decoders MUST handle the empty string,
- * but does say decoders MUST handle leading zeros. So Postel's Law
- * is applied here and 0 is not encoded as an empty string.
+ * RFC 8949 3.4.3 does not explicitly decoders MUST handle the empty
+ * string, but does say decoders MUST handle leading zeros. So
+ * Postel's Law is applied here and 0 is not encoded as an empty
+ * string.
  */
 static UsefulBufC
 QCBOREncode_Private_SkipLeadingZeros(const UsefulBufC BigNumber)
@@ -950,63 +908,82 @@
    NLZ = UsefulBuf_SkipLeading(BigNumber, 0x00);
 
    /* An all-zero string reduces to one 0, not an empty string. */
-   if(NLZ.len == 0 && BigNumber.len > 0 && UsefulBufC_NTH_BYTE(BigNumber, 0) == 0x00) {
-      NLZ.len++;
+   if(NLZ.len == 0 &&
+      BigNumber.len > 0 &&
+      UsefulBufC_NTH_BYTE(BigNumber, 0) == 0x00) {
+      NLZ.len = 1;
    }
 
    return NLZ;
 }
 
 
-/*
- * Public functions for adding a big number. See qcbor/qcbor_encode.h
+/**
+ * @brief Output a big number, preferred or not, with negative offset
+ *
+ * @param[in] pMe              The decode context.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] bPreferred       Uses preferred serialization if true
+ * @param[in] bNegative        Indicates big number is negative or postive.
+ * @param[in] BigNumber        The big number.
+ *
+ * Regardless of whether preferred serialization is used, if the big
+ * number is negative, one is subtracted before is output per CBOR
+ * convetion for big numbers. This requires a little big number
+ * arithmetic and adds some object code.
+ *
+ * If preferred serialization is used, then if the number is smaller
+ * than UINT64_MAX and postive it is output as type 0 and if it is
+ * equal to or smaller than UINT64_MAX it is output as a type 1
+ * integer minus one.
+ *
+ * See QCBOREncode_AddTBigNumberRaw() for simple copy through.
  */
 void
-QCBOREncode_AddTBigNumber(QCBOREncodeContext *pMe,
-                          const uint8_t       uTagRequirement,
-                          const bool          bNegative,
-                          const UsefulBufC    BigNumber)
+QCBOREncode_Private_AddTBigNumberMain(QCBOREncodeContext *pMe,
+                                      const uint8_t       uTagRequirement,
+                                      const bool          bPreferred,
+                                      const bool          bNegative,
+                                      const UsefulBufC    BigNumber)
 {
-   uint64_t uInt;
+   uint64_t   uInt;
+   bool       bIs2exp64;
+   uint8_t    uMajorType;
+   UsefulBufC BigNumberNLZ;
 
-   const UsefulBufC BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
+   BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
 
-   /* Preferred serialization requires reduction to type 0 and 1 integers */
-   if(bNegative) {
-      if(QCBOREncode_Private_NegativeBigNumberToUInt(BigNumberNLZ, &uInt)) {
-         /* Might be a 65-bit negative; use special add method for such */
-         QCBOREncode_AddNegativeUInt64(pMe, uInt);
+   static const uint8_t twoExp64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+   bIs2exp64 = ! UsefulBuf_Compare(BigNumber, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(twoExp64));
+
+   if(bPreferred && (BigNumberNLZ.len <= 8 || (bNegative && bIs2exp64))) {
+      if(bIs2exp64) {
+         /* 2^64 is a 9 byte big number. Since negative numbers are offset
+          * by one in CBOR, it can be encoded as a type 1 negative. The
+          * conversion below won't work because the uInt will overflow
+          * before the subtraction of 1.
+          */
+         uInt = UINT64_MAX;
       } else {
+         uInt = QCBOREncode_Private_BigNumberToUInt(BigNumberNLZ);
+         if(bNegative) {
+            uInt--;
+         }
+      }
+      uMajorType = bNegative ? CBOR_MAJOR_TYPE_NEGATIVE_INT :
+                               CBOR_MAJOR_TYPE_POSITIVE_INT;
+      QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uInt, 0);
+   } else {
+      if(bNegative) {
          QCBOREncode_Private_AddTNegativeBigNumber(pMe, uTagRequirement, BigNumberNLZ);
-      }
-
-   } else {
-      if(BigNumberNLZ.len <= sizeof(uint64_t)) {
-         QCBOREncode_AddUInt64(pMe, QCBOREncode_Private_BigNumberToUInt(BigNumberNLZ));
       } else {
-         QCBOREncode_AddTBigNumberRaw(pMe, bNegative, uTagRequirement, BigNumberNLZ);
+         QCBOREncode_AddTBigNumberRaw(pMe, false, uTagRequirement, BigNumberNLZ);
       }
    }
 }
 
 
-/*
- * Public functions for adding a big number. See qcbor/qcbor_encode.h
- */
-void
-QCBOREncode_AddTBigNumberNoPreferred(QCBOREncodeContext *pMe,
-                                     const uint8_t       uTagRequirement,
-                                     const bool          bNegative,
-                                     const UsefulBufC    BigNumber)
-{
-   const UsefulBufC BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
-
-   if(bNegative) {
-      QCBOREncode_Private_AddTNegativeBigNumber(pMe, uTagRequirement, BigNumberNLZ);
-   } else {
-      QCBOREncode_AddTBigNumberRaw(pMe, false, uTagRequirement, BigNumberNLZ);
-   }
-}
 
 
 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
@@ -1078,7 +1055,7 @@
     * that has no effect on the code here.
     */
    if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
-      QCBOREncode_AddTag(pMe, uTagNumber);
+      QCBOREncode_AddTagNumber(pMe, uTagNumber);
    }
    QCBOREncode_OpenArray(pMe);
    QCBOREncode_AddInt64(pMe, nExponent);
@@ -1107,7 +1084,7 @@
     * for CBOR negative numbers.
     */
    if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
-      QCBOREncode_AddTag(pMe, uTagNumber);
+      QCBOREncode_AddTagNumber(pMe, uTagNumber);
    }
    QCBOREncode_OpenArray(pMe);
    QCBOREncode_AddInt64(pMe, nExponent);