Precision-preserving number decode
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 090eb38..bf97722 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -7037,11 +7037,29 @@
 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
+static double
+NegToD(uint64_t uNegInt)
+{
+   double d;
+   /* Improvement: do this with shifts and masks so it doesn't get disabled when float does */
+
+   /* Subtraction must be after the cast to avoid overflow. */
+   d = (double)uNegInt - 1.0;
+   if(d + 1 == (double)uNegInt) { /* Make sure it is a whole number */
+      return -d;
+   }
+
+   return NAN;
+}
+
+
 void
 QCBORDecode_GetNumberConvertPrecisely(QCBORDecodeContext *pMe,
                                       QCBORItem          *pNumber)
 {
    QCBORItem Item;
+   struct IEEE754_ToInt ToInt;
+   double d;
 
    if(pMe->uLastError != QCBOR_SUCCESS) {
       return;
@@ -7054,53 +7072,50 @@
    }
 
    switch(Item.uDataType) {
-
       case QCBOR_TYPE_INT64:
       case QCBOR_TYPE_UINT64:
          *pNumber = Item;
          break;
 
       case QCBOR_TYPE_DOUBLE:
-         /* TODO: Try to convert to int */
+         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) {
+            pNumber->uDataType = QCBOR_TYPE_UINT64;
+            pNumber->val.uint64 = ToInt.integer.un_signed;
+         } else {
+            *pNumber = Item;
+         }
          break;
 
       case QCBOR_TYPE_65BIT_NEG_INT:
-         /* TODO: Try to convert to double without precision loss */
+         d = NegToD(Item.val.uint64);
+         if(d == NAN) {
+            *pNumber = Item;
+         } else {
+            pNumber->uDataType = QCBOR_TYPE_DOUBLE;
+            pNumber->val.dfnum = d;
+         }
+         break;
 
       default:
          pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+         pNumber->uDataType = QCBOR_TYPE_NONE;
          break;
-
-
    }
-
-
 }
 
 
 #if 0
-/*
-
-
- case QCBOR_TYPE_65BIT_NEG_INT:
-
- case QCBOR_TYPE_NEGBIGNUM:
- case QCBOR_TYPE_POSBIGNUM:
-    /* TODO: convert to int, uint, double??? */
-
- case QCBOR_TYPE_BIGFLOAT:
-
- case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
- case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
- */
-#endif
 
 
 
 void
-Int_To_BigNum(int64_t     n,
+Int_To_BigNum(uint64_t     u,
               UsefulBuf   B,
-              UsefulBufC pBigNum)
+              UsefulBufC  *pBigNum)
 {
    /* This is just a memcpy, though watch out for endianess */
    /* Have to check size */
@@ -7109,10 +7124,11 @@
 }
 
 
+// TODO: error conditions
 void
-Double_To_BigNum(int64_t     n,
+Double_To_BigNum(double     d,
               UsefulBuf   B,
-              UsefulBufC pBigNum)
+              UsefulBufC *pBigNum)
 {
    /* Have to do shift thing to figure out if it is whole number */
    /* Then kind of a copy and shift, possibly with a lot of zeros */
@@ -7123,7 +7139,8 @@
 void
 QCBORDecode_GetNumberConvertBigNum(QCBORDecodeContext *pMe,
                                    UsefulBuf B,
-                                   UsefulBufC pBigNum)
+                                   UsefulBufC *pBigNum,
+                                   bool       *pbIsNegative)
 {
    QCBORItem Item;
 
@@ -7140,23 +7157,106 @@
    switch(Item.uDataType) {
 
       case QCBOR_TYPE_INT64:
+         if(Item.val.int64 < 0) {
+            *pbIsNegative = true;
+            Item.val.uint64 = (uint64_t)(-Item.val.int64);
+         } else {
+            Item.val.uint64 =  (uint64_t)Item.val.int64;
+         }
+         /* FALLTHROUGH */
+
       case QCBOR_TYPE_UINT64:
-         *pNumber = Item;
+         Int_To_BigNum(Item.val.uint64, B, pBigNum);
          break;
 
       case QCBOR_TYPE_DOUBLE:
-         /* TODO: Try to convert to int */
+         Double_To_BigNum(Item.val.dfnum, B, pBigNum);
+         /* TODO: sometimes this will fail */
          break;
 
       case QCBOR_TYPE_65BIT_NEG_INT:
          /* TODO: Try to convert to double without precision loss */
 
+      case QCBOR_TYPE_NEGBIGNUM:
+      case QCBOR_TYPE_POSBIGNUM:
+         *pBigNum = UsefulBuf_Copy(B, Item.val.bigNum);
+         break;
+         // TODO: sign
+
+      case QCBOR_TYPE_BIGFLOAT:
+         // TODO: lots of work
+         // This will fail sometimes
+
+
       default:
          pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
          break;
 
 
    }
-
-
 }
+
+
+/* This can represent a very large range of values! */
+void
+QCBORDecode_GetNumberConvertBigFloat(QCBORDecodeContext *pMe,
+                                   UsefulBuf B,
+                                   UsefulBufC *pBigNum,
+                                   bool       *pbIsNegative,
+                                     int64_t   *nExponent)
+{
+   QCBORItem Item;
+
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
+   if(uError) {
+      pMe->uLastError = (uint8_t)uError;
+      return;
+   }
+
+   switch(Item.uDataType) {
+
+      case QCBOR_TYPE_INT64:
+         if(Item.val.int64 < 0) {
+            *pbIsNegative = true;
+            Item.val.uint64 = (uint64_t)(-Item.val.int64);
+         } else {
+            Item.val.uint64 =  (uint64_t)Item.val.int64;
+         }
+         /* FALLTHROUGH */
+
+      case QCBOR_TYPE_UINT64:
+         Int_To_BigNum(Item.val.uint64, B, pBigNum);
+         break;
+
+      case QCBOR_TYPE_DOUBLE:
+         Double_To_BigNum(Item.val.dfnum, B, pBigNum);
+         /* TODO: sometimes this will fail */
+         break;
+
+      case QCBOR_TYPE_65BIT_NEG_INT:
+         /* TODO: Try to convert to double without precision loss */
+
+      case QCBOR_TYPE_NEGBIGNUM:
+      case QCBOR_TYPE_POSBIGNUM:
+         *pBigNum = UsefulBuf_Copy(B, Item.val.bigNum);
+         break;
+         // TODO: sign
+
+      case QCBOR_TYPE_BIGFLOAT:
+         // TODO: lots of work
+         // This will fail sometimes
+
+
+      default:
+         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+         break;
+
+
+   }
+}
+
+#endif