Floating point tests and fixes related to #ifdefs
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index b5140c1..280a99a 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -797,25 +797,43 @@
 
       case HALF_PREC_FLOAT:
 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+         // Half-precision is returned as a double.
          // The cast to uint16_t is safe because the encoded value
          // was 16 bits. It was widened to 64 bits to be passed in here.
          pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
          pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
 #else
-         nReturn = QCBOR_ERR_HALF_PRECISION_UNSUPPORTED;
+         nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
 #endif
          break;
       case SINGLE_PREC_FLOAT:
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+         // Single precision is normally returned as a double
+         // since double is widely supported, there is no loss of
+         // precision, it makes it easy for the caller in
+         // most cases and it can be converted back to single
+         // with no loss of precision
+         //
          // The cast to uint32_t is safe because the encoded value
          // was 32 bits. It was widened to 64 bits to be passed in here.
-         pDecodedItem->val.dfnum = IEEE754_FloatToDouble((uint32_t)uNumber);
-         pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
+         {
+            const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+            // In the normal case, use HW to convert float to double.
+            pDecodedItem->val.dfnum = (double)f;
+            pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
 #else
-         pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
-         pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
+            // Use of float HW is disabled, return as a float.
+            pDecodedItem->val.fnum = f;
+            pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
+
+            // IEEE754_FloatToDouble() could be used here to return
+            // as a double, but it adds object code and most likely
+            // anyone disabling FLOAT HW use doesn't care about
+            // floats and wants to save object code.
 #endif
+         }
          break;
+
       case DOUBLE_PREC_FLOAT:
          pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
          pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
@@ -1591,7 +1609,7 @@
           requires floating point conversion to integers and
           comparison which requires either floating point HW
           or a SW library. */
-         nReturn = QCBOR_ERR_FLOAT_DATE_UNSUPPORTED;
+         nReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
          break;
 
@@ -3445,7 +3463,7 @@
    uint64_t uResult;
 
    // Take the absolute value of the mantissa and convert to unsigned.
-   // TODO: this should be possible in one intruction
+   // Improvement: this should be possible in one instruction
    uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
 
    // Do the exponentiation of the positive mantissa
@@ -3557,25 +3575,7 @@
 }
 
 
-static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
-{
-   while((uInt & 0xff00000000000000UL) == 0) {
-      uInt = uInt << 8;
-   };
 
-   UsefulOutBuf UOB;
-
-   UsefulOutBuf_Init(&UOB, Buffer);
-
-   while(uInt) {
-      const uint64_t xx = uInt & 0xff00000000000000UL;
-      UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
-      uInt = uInt << 8;
-      (void)xx;
-   }
-
-   return UsefulOutBuf_OutUBuf(&UOB);
-}
 
 #include "fenv.h"
 
@@ -3595,13 +3595,18 @@
 static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
 {
    switch(pItem->uDataType) {
-      // TODO: float when ifdefs are set
+      case QCBOR_TYPE_FLOAT:
       case QCBOR_TYPE_DOUBLE:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
          if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
             // TODO: what about under/overflow here?
             // Invokes the floating-point HW and/or compiler-added libraries
             feclearexcept(FE_ALL_EXCEPT);
-            *pnValue = llround(pItem->val.dfnum);
+            if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
+               *pnValue = llround(pItem->val.dfnum);
+            } else {
+               *pnValue = lroundf(pItem->val.fnum);
+            }
             if(fetestexcept(FE_INVALID)) {
                // TODO: better error code
                return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
@@ -3609,6 +3614,9 @@
          } else {
             return  QCBOR_ERR_UNEXPECTED_TYPE;
          }
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
          break;
 
       case QCBOR_TYPE_INT64:
@@ -3707,8 +3715,6 @@
  */
 static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
 {
-   QCBORError uErr;
-
    switch(pItem->uDataType) {
 
       case QCBOR_TYPE_POSBIGNUM:
@@ -3752,7 +3758,8 @@
 
       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            int64_t nMantissa;
+            int64_t    nMantissa;
+            QCBORError uErr;
             uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
             if(uErr) {
                return uErr;
@@ -3768,7 +3775,8 @@
 
       case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            int64_t nMantissa;
+            int64_t    nMantissa;
+            QCBORError uErr;
             uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
             if(uErr) {
                return uErr;
@@ -3784,7 +3792,8 @@
 
       case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            int64_t nMantissa;
+            int64_t    nMantissa;
+            QCBORError uErr;
             uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
             if(uErr) {
                return uErr;
@@ -3800,7 +3809,8 @@
 
       case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
-            int64_t nMantissa;
+            int64_t    nMantissa;
+            QCBORError uErr;
             uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
             if(uErr) {
                return uErr;
@@ -3892,9 +3902,11 @@
 static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
 {
    switch(pItem->uDataType) {
-           // TODO: type flaot
         case QCBOR_TYPE_DOUBLE:
+        case QCBOR_TYPE_FLOAT:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
            if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+              // TODO: this code needs work
               feclearexcept(FE_ALL_EXCEPT);
               double dRounded = round(pItem->val.dfnum);
               // TODO: over/underflow
@@ -3912,6 +3924,9 @@
            } else {
               return QCBOR_ERR_UNEXPECTED_TYPE;
            }
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
            break;
 
         case QCBOR_TYPE_INT64:
@@ -4006,8 +4021,6 @@
 */
 static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
 {
-   QCBORError uErr;
-
    switch(pItem->uDataType) {
 
       case QCBOR_TYPE_POSBIGNUM:
@@ -4053,7 +4066,8 @@
       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
             // TODO: Would be better to convert to unsigned
-            int64_t nMantissa;
+            int64_t    nMantissa;
+            QCBORError uErr;
             uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
             if(uErr != QCBOR_SUCCESS) {
                return uErr;
@@ -4078,7 +4092,8 @@
       case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
             // TODO: Would be better to convert to unsigned
-            int64_t nMantissa;
+            int64_t    nMantissa;
+            QCBORError uErr;
             uErr =  ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
             if(uErr != QCBOR_SUCCESS) {
                return uErr;
@@ -4176,7 +4191,20 @@
 static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
 {
    switch(pItem->uDataType) {
-      // TODO: float when ifdefs are set
+      case QCBOR_TYPE_FLOAT:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+            if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+               *pdValue = (double)pItem->val.fnum;
+            } else {
+               return QCBOR_ERR_UNEXPECTED_TYPE;
+            }
+         }
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif
+         break;
+
       case QCBOR_TYPE_DOUBLE:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
             if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
@@ -4188,6 +4216,7 @@
          break;
 
       case QCBOR_TYPE_INT64:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
          if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
             // TODO: how does this work?
             *pdValue = (double)pItem->val.int64;
@@ -4195,15 +4224,22 @@
          } 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) {
              *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 */
 
       default:
          return QCBOR_ERR_UNEXPECTED_TYPE;
@@ -4272,7 +4308,7 @@
 }
 
 
-
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
 static double ConvertBigNumToDouble(const UsefulBufC BigNum)
 {
    double dResult;
@@ -4289,15 +4325,17 @@
 
    return dResult;
 }
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
 
 static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
 {
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
    /*
    https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
 
    */
    switch(pItem->uDataType) {
-         // TODO: type float
 
 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
       case QCBOR_TYPE_DECIMAL_FRACTION:
@@ -4380,6 +4418,14 @@
    }
 
    return QCBOR_SUCCESS;
+
+#else
+   (void)pItem;
+   (void)uConvertTypes;
+   (void)pdValue;
+   return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
 }
 
 
@@ -4455,6 +4501,27 @@
 
 
 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
+{
+   while((uInt & 0xff00000000000000UL) == 0) {
+      uInt = uInt << 8;
+   };
+
+   UsefulOutBuf UOB;
+
+   UsefulOutBuf_Init(&UOB, Buffer);
+
+   while(uInt) {
+      const uint64_t xx = uInt & 0xff00000000000000UL;
+      UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
+      uInt = uInt << 8;
+      (void)xx;
+   }
+
+   return UsefulOutBuf_OutUBuf(&UOB);
+}
+
+
 static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
                                                  TagSpecification    TagSpec,
                                                  QCBORItem          *pItem)