Merge floating-point disabling into spiffy decode
diff --git a/test/float_tests.c b/test/float_tests.c
index e7696d1..5aefaea 100644
--- a/test/float_tests.c
+++ b/test/float_tests.c
@@ -10,56 +10,81 @@
  Created on 9/19/18
  =============================================================================*/
 
+
 #include "float_tests.h"
 #include "qcbor/qcbor_encode.h"
 #include "qcbor/qcbor_decode.h"
-#include "half_to_double_from_rfc7049.h"
 #include <math.h> // For INFINITY and NAN and isnan()
 
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+
+#include "half_to_double_from_rfc7049.h"
 
 
+/*
+ Half-precision values that are input to test half-precision decoding
+
+ As decoded by http://cbor.me
+ {"zero": 0.0,
+ "infinitity": Infinity,
+ "negative infinitity": -Infinity,
+ "NaN": NaN,
+ "one": 1.0,
+ "one third": 0.333251953125,
+ "largest half-precision": 65504.0,
+ "too-large half-precision": Infinity,
+ "smallest subnormal": 5.960464477539063e-8,
+ "smallest normal": 0.00006097555160522461,
+ "biggest subnormal": 0.00006103515625,
+ "subnormal single": 0.0,
+ 3: -2.0,
+ 4: NaN,
+ 5: NaN,
+ 6: NaN,
+ 7: NaN}
+ */
 static const uint8_t spExpectedHalf[] = {
     0xB1,
         0x64,
             0x7A, 0x65, 0x72, 0x6F,
-        0xF9, 0x00, 0x00,   // 0.000
+        0xF9, 0x00, 0x00, // half-precision 0.000
         0x6A,
             0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
-        0xF9, 0x7C, 0x00,   // Infinity
+        0xF9, 0x7C, 0x00, // Infinity
         0x73,
             0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E,
             0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
-        0xF9, 0xFC, 0x00,   // -Inifinity
+        0xF9, 0xFC, 0x00, // -Inifinity
         0x63,
             0x4E, 0x61, 0x4E,
-        0xF9, 0x7E, 0x00,   // NaN
+        0xF9, 0x7E, 0x00, // NaN
         0x63,
             0x6F, 0x6E, 0x65,
-        0xF9, 0x3C, 0x00,   // 1.0
+        0xF9, 0x3C, 0x00, // 1.0
         0x69,
             0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
-        0xF9, 0x35, 0x55,   // 0.333251953125
+        0xF9, 0x35, 0x55, // half-precsion one third 0.333251953125
         0x76,
             0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C,
             0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
-        0xF9, 0x7B, 0xFF,   // 65504.0
+        0xF9, 0x7B, 0xFF, // largest half-precision 65504.0
         0x78, 0x18,
             0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68,
             0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
             0x6F, 0x6E,
-        0xF9, 0x7C, 0x00,   // Infinity
+        0xF9, 0x7C, 0x00, // Infinity
         0x72,
             0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75,
             0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
-        0xF9, 0x00, 0x01,   // 0.000000059604
-        0x6F,
-            0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
-            0x72, 0x6D, 0x61, 0x6C,
-        0xF9, 0x03, 0xFF,   // 0.0000609755516
+        0xF9, 0x00, 0x01, // Smallest half-precision subnormal 0.000000059604645
         0x71,
             0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62,
             0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
-        0xF9, 0x04, 0x00,   // 0.000061988
+        0xF9, 0x03, 0xFF, // Largest half-precision subnormal 0.0000609755516
+        0x6F,
+            0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
+            0x72, 0x6D, 0x61, 0x6C,
+        0xF9, 0x04, 0x00,  // Smallest half-precision normal 0.000061988
         0x70,
             0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x73,
             0x69, 0x6E, 0x67, 0x6C, 0x65,
@@ -74,118 +99,130 @@
         0xF9, 0x7E, 0x0F,    // qNaN with payload 0x0f
         0x07,
         0xF9, 0x7C, 0x0F,    // sNaN with payload 0x0f
-
 };
 
 
+inline static bool CheckDouble(double d, uint64_t u)
+{
+   return UsefulBufUtil_CopyDoubleToUint64(d) != u;
+}
+
+
 int32_t HalfPrecisionDecodeBasicTests()
 {
-    UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
+   UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
 
-    QCBORDecodeContext DC;
-    QCBORDecode_Init(&DC, HalfPrecision, 0);
+   QCBORDecodeContext DC;
+   QCBORDecode_Init(&DC, HalfPrecision, 0);
 
-    QCBORItem Item;
+   QCBORItem Item;
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_MAP) {
-        return -1;
-    }
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_MAP) {
+      return -1;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0F) {
-        return -2;
-    }
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0) {
+      return -2;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
-        return -3;
-    }
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
+      return -3;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -INFINITY) {
-        return -4;
-    }
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -INFINITY) {
+      return -4;
+   }
 
-    // TODO, is this really converting right? It is carrying payload, but
-    // this confuses things.
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || !isnan(Item.val.dfnum)) {
-        return -5;
-    }
+   // TODO: NAN-related is this really converting right? It is carrying
+   // payload, but this confuses things.
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || !isnan(Item.val.dfnum)) {
+      return -5;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 1.0F) {
-        return -6;
-    }
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 1.0) {
+      return -6;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.333251953125F) {
-        return -7;
-    }
+   // Approximately 1/3
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.333251953125) {
+      return -7;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 65504.0F) {
-        return -8;
-    }
+   // Largest half-precision
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 65504.0) {
+      return -8;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
-        return -9;
-    }
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
+      return -9;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item); // TODO: check this
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000000596046448F) {
-        return -10;
-    }
+   // Smallest half-precision subnormal
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00000005960464477539063) {
+      return -10;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item); // TODO: check this
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000609755516F) {
-        return -11;
-    }
+   // Largest half-precision subnormal
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00006097555160522461) {
+      return -11;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item); // TODO check this
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000610351563F) {
-        return -12;
-    }
+   // Smallest half-precision normal
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00006103515625) {
+      return -12;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0) {
-        return -13;
-    }
+   // half-precision zero
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0) {
+      return -13;
+   }
 
-    QCBORDecode_GetNext(&DC, &Item);
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -2.0F) {
-        return -14;
-    }
+   // negative 2
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -2.0) {
+      return -14;
+   }
 
-    // TODO: double check these four tests
-    QCBORDecode_GetNext(&DC, &Item); // qNaN
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
-       UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff8000000000000ULL) {
-        return -15;
-    }
-    QCBORDecode_GetNext(&DC, &Item); // sNaN
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
-       UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff0000000000001ULL) {
-        return -16;
-    }
-    QCBORDecode_GetNext(&DC, &Item); // qNaN with payload 0x0f
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
-       UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff800000000000fULL) {
-        return -17;
-    }
-    QCBORDecode_GetNext(&DC, &Item); // sNaN with payload 0x0f
-    if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
-       UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff000000000000fULL) {
-        return -18;
-    }
+   // TODO: NAN-related double check these four tests
+   QCBORDecode_GetNext(&DC, &Item); // qNaN
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      CheckDouble(Item.val.dfnum, 0x7ff8000000000000ULL)) {
+      return -15;
+   }
+   QCBORDecode_GetNext(&DC, &Item); // sNaN
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      CheckDouble(Item.val.dfnum, 0x7ff0000000000001ULL)) {
+      return -16;
+   }
+   QCBORDecode_GetNext(&DC, &Item); // qNaN with payload 0x0f
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      CheckDouble(Item.val.dfnum, 0x7ff800000000000fULL)) {
+      return -17;
+   }
+   QCBORDecode_GetNext(&DC, &Item); // sNaN with payload 0x0f
+   if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      CheckDouble(Item.val.dfnum, 0x7ff000000000000fULL)) {
+      return -18;
+   }
 
-    if(QCBORDecode_Finish(&DC)) {
-        return -19;
-    }
+   if(QCBORDecode_Finish(&DC)) {
+      return -19;
+   }
 
-    return 0;
+   return 0;
 }
 
 
@@ -241,210 +278,601 @@
 
 
 /*
- {"zero": 0.0,
-  "negative zero": -0.0,
-  "infinitity": Infinity,
-  "negative infinitity": -Infinity,
-  "NaN": NaN,
-  "one": 1.0,
-  "one third": 0.333251953125,
-  "largest half-precision": 65504.0,
-  "largest half-precision point one": 65504.1,
-  "too-large half-precision": 65536.0,
-  "smallest subnormal": 5.96046448e-8,
-  "smallest normal": 0.00006103515261202119,
-  "biggest subnormal": 0.00006103515625,
-  "subnormal single": 4.00000646641519e-40,
-  3: -2.0,
-  "large single exp": 2.5521177519070385e+38,
-  "too-large single exp": 5.104235503814077e+38,
-  "biggest single with prec": 16777216.0,
-  "first single with prec loss": 16777217.0,
-  1: "fin"}
+ Expected output from preferred serialization of some of floating-point numbers
+{"zero": 0.0,
+ "negative zero": -0.0,
+ "infinitity": Infinity,
+ "negative infinitity": -Infinity,
+ "NaN": NaN,
+ "one": 1.0,
+ "one third": 0.333251953125,
+ "largest half-precision": 65504.0,
+ "largest half-precision point one": 65504.1,
+ "too-large half-precision": 65536.0,
+ "smallest half subnormal": 5.960464477539063e-8,
+ "smallest half normal": 0.00006103515625,
+ "smallest half normal plus": 0.00006103515625000001,
+ "smallest normal minus": 0.000030517578125,
+ "largest single": 3.4028234663852886e+38,
+ "largest single plus": 6.805646932770577e+38,
+ "smallest single": 1.1754943508222875e-38,
+ "smallest single plus": 1.1754943508222878e-38,
+ "smallest single minus": 1.1754943508222874e-38,
+ "smallest single minus more": 5.877471754111438e-39,
+ 3: -2.0, "single precision": 16777216.0,
+ "single with precision loss": 16777217.0,
+ 1: "fin"}
  */
 static const uint8_t spExpectedSmallest[] = {
-    0xB4, 0x64, 0x7A, 0x65, 0x72, 0x6F, 0xF9, 0x00, 0x00, 0x6D,
-    0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A,
-    0x65, 0x72, 0x6F, 0xF9, 0x80, 0x00, 0x6A, 0x69, 0x6E, 0x66,
-    0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, 0xF9, 0x7C, 0x00,
-    0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20,
-    0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
-    0xF9, 0xFC, 0x00, 0x63, 0x4E, 0x61, 0x4E, 0xF9, 0x7E, 0x00,
-    0x63, 0x6F, 0x6E, 0x65, 0xF9, 0x3C, 0x00, 0x69, 0x6F, 0x6E,
-    0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0xF9, 0x35, 0x55,
-    0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68,
-    0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73,
-    0x69, 0x6F, 0x6E, 0xF9, 0x7B, 0xFF, 0x78, 0x20, 0x6C, 0x61,
-    0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66,
-    0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
-    0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x65,
-    0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33, 0x78,
-    0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65,
-    0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63,
-    0x69, 0x73, 0x69, 0x6F, 0x6E, 0xFA, 0x47, 0x80, 0x00, 0x00,
-    0x72, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
-    0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xFB,
-    0x3E, 0x70, 0x00, 0x00, 0x00, 0x1C, 0x5F, 0x68, 0x6F, 0x73,
-    0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
-    0x72, 0x6D, 0x61, 0x6C, 0xFA, 0x38, 0x7F, 0xFF, 0xFF, 0x71,
-    0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75,
-    0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xF9, 0x04, 0x00,
-    0x70, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
-    0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0xFB, 0x37, 0xC1,
-    0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF9, 0xC0, 0x00,
-    0x70, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E,
-    0x67, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x70, 0xFA, 0x7F, 0x40,
-    0x00, 0x00, 0x74, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72,
-    0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20,
-    0x65, 0x78, 0x70, 0xFB, 0x47, 0xF8, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x78, 0x18, 0x62, 0x69, 0x67, 0x67, 0x65, 0x73,
-    0x74, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77,
-    0x69, 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0xFA, 0x4B,
-    0x80, 0x00, 0x00, 0x78, 0x1B, 0x66, 0x69, 0x72, 0x73, 0x74,
-    0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69,
-    0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x20, 0x6C, 0x6F,
-    0x73, 0x73, 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00,
-    0x00, 0x01, 0x63, 0x66, 0x69, 0x6E
+   0xB8, 0x1A,
+      0x64, 0x7A, 0x65, 0x72, 0x6F,
+      0xF9, 0x00, 0x00,
+
+      0x6D, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A,
+         0x65, 0x72, 0x6F,
+      0xF9, 0x80, 0x00,
+
+      0x6A, 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
+      0xF9, 0x7C, 0x00,
+
+      0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69,
+         0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
+      0xF9, 0xFC, 0x00,
+
+      0x63, 0x4E, 0x61, 0x4E,
+      0xF9, 0x7E, 0x00,
+
+      0x63, 0x6F, 0x6E, 0x65,
+      0xF9, 0x3C, 0x00,
+
+      0x69, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
+      0xF9, 0x35, 0x55,
+
+      0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61,
+         0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
+         0x6F, 0x6E,
+      0xF9, 0x7B, 0xFF,
+
+      0x78, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68,
+         0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73,
+         0x69, 0x6F, 0x6E, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20,
+         0x6F, 0x6E, 0x65,
+      0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33,
+
+      0x78, 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65,
+         0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63,
+         0x69, 0x73, 0x69, 0x6F, 0x6E,
+      0xFA, 0x47, 0x80, 0x00, 0x00,
+
+      0x77, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74,
+         0x20, 0x68, 0x61, 0x6C, 0x66, 0x20, 0x73, 0x75, 0x62, 0x6E,
+         0x6F, 0x72, 0x6D, 0x61, 0x6C,
+      0xFA, 0x33, 0x80, 0x00, 0x00,
+
+      0x74, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x68,
+         0x61, 0x6C, 0x66, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
+      0xF9, 0x04, 0x00,
+
+      0x78, 0x19, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
+         0x68, 0x61, 0x6C, 0x66, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61,
+         0x6C, 0x20, 0x70, 0x6C, 0x75, 0x73,
+      0xFB, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+
+      0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E,
+         0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6E,
+         0x75, 0x73,
+      0xFB, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+
+      0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E,
+         0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6E, 0x75,
+         0x73,
+      0xFA, 0x38, 0x00, 0x00, 0x00,
+
+      0x6E, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
+         0x6E, 0x67, 0x6C, 0x65,
+      0xFA, 0x7F, 0x7F, 0xFF, 0xFF,
+
+      0x73, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
+         0x6E,0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
+      0xFB, 0x47, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01,
+
+      0x73, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
+         0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
+      0xFB, 0x47, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
+
+      0x6F, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
+         0x69, 0x6E, 0x67, 0x6C, 0x65,
+      0xFA, 0x00, 0x80, 0x00, 0x00,
+
+      0x74, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
+         0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
+      0xFB, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+
+      0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
+         0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x6D, 0x69, 0x6E, 0x75,
+         0x73,
+      0xFB, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+
+      0x78, 0x1A, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
+         0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x6D, 0x69, 0x6E,
+         0x75, 0x73, 0x20, 0x6D, 0x6F, 0x72, 0x65,
+      0xFB, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+      0x03,
+      0xF9, 0xC0, 0x00,
+
+      0x70, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x72, 0x65,
+         0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
+      0xFA, 0x4B, 0x80, 0x00, 0x00,
+
+      0x78, 0x1A, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69,
+         0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
+         0x6F, 0x6E, 0x20, 0x6C, 0x6F, 0x73, 0x73,
+      0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+
+      0x01,
+      0x63, 0x66, 0x69, 0x6E
 };
 
 
+/*
+ Makes a double from a uint64_t by copying the bits, not
+ by converting the value.
+ */
+#define MAKE_DOUBLE(x) UsefulBufUtil_CopyUint64ToDouble(x)
+
+
 int32_t DoubleAsSmallestTest()
 {
-    UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, 420);
+   UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, sizeof(spExpectedSmallest));
 
-#define QCBOREncode_AddDoubleAsSmallestToMap QCBOREncode_AddDoubleToMap
-#define QCBOREncode_AddDoubleAsSmallestToMapN QCBOREncode_AddDoubleToMapN
+   QCBOREncodeContext EC;
+   QCBOREncode_Init(&EC, EncodedHalfsMem);
+   QCBOREncode_OpenMap(&EC);
+
+   // Many of these are from
+   // https://en.wikipedia.org/wiki/Half-precision_floating-point_format
+   // and
+   // https://en.wikipedia.org/wiki/Single-precision_floating-point_format
+
+   // F9 0000                              # primitive(0)
+   QCBOREncode_AddDoubleToMap(&EC, "zero", 0.00);
+
+   // F9 8000                              # primitive(0)
+   QCBOREncode_AddDoubleToMap(&EC, "negative zero", -0.00);
+
+   // F9 7C00                              # primitive(31744)
+   QCBOREncode_AddDoubleToMap(&EC, "infinitity", INFINITY);
+
+   // F9 FC00                              # primitive(64512)
+   QCBOREncode_AddDoubleToMap(&EC, "negative infinitity", -INFINITY);
+
+   // F9 7E00                              # primitive(32256)
+   QCBOREncode_AddDoubleToMap(&EC, "NaN", NAN);
+
+   // TODO: test a few NaN variants
+
+   // F9 3C00                              # primitive(15360)
+   QCBOREncode_AddDoubleToMap(&EC, "one", 1.0);
+
+   // F9 3555                              # primitive(13653)
+   QCBOREncode_AddDoubleToMap(&EC, "one third", 0.333251953125);
+
+   // 65504.0, converts to the large possible half-precision.
+   // 0xF9, 0x7B, 0xFF,
+   QCBOREncode_AddDoubleToMap(&EC, "largest half-precision", 65504.0);
+
+   // 65504.1, the double that has both to large an exponent and too
+   // much precision, so no conversion.
+   // 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33,
+   QCBOREncode_AddDoubleToMap(&EC, "largest half-precision point one", 65504.1);
+
+   // 65536.0 has an exponent of 16, which is larger than 15, the
+   // largest half-precision exponent. It is the exponent, not
+   // precision loss that prevents conversion to half. It does convert
+   // to single precision.
+   // 0xFA, 0x47, 0x80, 0x00, 0x00,
+   QCBOREncode_AddDoubleToMap(&EC, "too-large half-precision", 65536.0);
+
+   // 5.9604644775390625E-8, the smallest possible half-precision
+   // subnormal, digitis are lost converting to half, but not
+   // when converting to a single
+   // 0xFA, 0x33, 0x80, 0x00, 0x00,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest half subnormal",
+                              MAKE_DOUBLE(0x3e70000000000000));
+
+   // 0.00006103515625, the double value that converts to the smallest
+   // possible half-precision normal.  which is what should appear in
+   // the output.
+   // 0xF9, 0x04, 0x00,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest half normal",
+                              MAKE_DOUBLE(0x3f10000000000000));
+
+   // 0.000061035156250000014 ,the double value that is a tiny bit
+   // greater than smallest possible half-precision normal. It will be
+   // output as a double because converting it will reduce precision.
+   // 0xFB, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest half normal plus",
+                              MAKE_DOUBLE(0x3f10000000000001));
+
+   // 0.000061035156249999993, the double value that is a tiny bit
+   // smaller than the smallest half-precision normal. This will fail
+   // to convert to a half-precision because both the exponent is too
+   // small and the precision is too large for a half-precision.
+   // 0xFB, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest normal minus",
+                              MAKE_DOUBLE(0x3f0fffffffffffff));
+
+   // 0.000030517578125, the double value that is too small to fit
+   // into a half-precision because the exponent won't fit, not
+   // because precision would be lost. (This would fit into a
+   // half-precision subnormal, but there is no converstion to
+   // that). This ends up encoded as a single-precision.
+   // 0xFA, 0x38, 0x00, 0x00, 0x00,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest normal minus",
+                              MAKE_DOUBLE(0x3f00000000000000));
+
+   // 3.4028234664e38, the value that converts to the largest possible
+   // single-precision.
+   // 0xFA, 0x7F, 0x7F, 0xFF, 0xFF,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "largest single",
+                              MAKE_DOUBLE(0x47efffffe0000000));
+
+   // 3.402823466385289E38, sightly larger than the largest possible
+   // possible precision.  Conversion fails because precision would be
+   // lost.
+   // 0xFB, 0x47, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "largest single plus",
+                              MAKE_DOUBLE(0x47efffffe0000001));
+
+   // 6.8056469327705772E38, slightly more larger than the largers
+   // possible single precision.  Conversion fails because exponent is
+   // too large.
+   // 0xFB, 0x47, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "largest single plus",
+                              MAKE_DOUBLE(0x47ffffffe0000000));
+
+   // 1.1754943508222875E-38, The double value that converts to the
+   // smallest possible single-precision normal
+   // 0xFA, 0x00, 0x80, 0x00, 0x00,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest single",
+                              MAKE_DOUBLE(0x3810000000000000));
+
+   // 1.1754943508222878E-38, double value that is slightly larger
+   // than the smallest single-precision normal. Conversion fails
+   // because of precision
+   // 0xFB, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest single plus",
+                              MAKE_DOUBLE(0x3810000000000001));
+
+   // 1.1754943508222874E-38, slightly smaller than the smallest
+   // single-precision normal.  Conversion fails because of precision
+   // 0xFB, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest single minus",
+                              MAKE_DOUBLE(0x380fffffffffffff));
+
+   // 5.8774717541114375E-39, slightly smaller than the smallest
+   // single-precision normal.  Conversion fails because the exponent
+   // is too small.
+   // 0xFB, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   QCBOREncode_AddDoubleToMap(&EC,
+                              "smallest single minus more",
+                              MAKE_DOUBLE(0x3800000000000000));
+
+   // Just -2, which converts to a negative half-precision
+   // F9 C000                              # primitive(49152)
+   QCBOREncode_AddDoubleToMapN(&EC, 3, -2.0);
+
+   // 16777216, No precision loss converting to single
+   // FA 4B800000                          # primitive(1266679808)
+   QCBOREncode_AddDoubleToMap(&EC, "single precision", 16777216);
+
+   // 16777217, One more than above. Too much precision for a single
+   // so no conversion.
+   // 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+   QCBOREncode_AddDoubleToMap(&EC, "single with precision loss", 16777217);
+
+   // Just a convenient marker when cutting and pasting encoded CBOR
+   QCBOREncode_AddSZStringToMapN(&EC, 1, "fin");
+
+   QCBOREncode_CloseMap(&EC);
+
+   UsefulBufC EncodedHalfs;
+   QCBORError uErr = QCBOREncode_Finish(&EC, &EncodedHalfs);
+   if(uErr) {
+      return -1;
+   }
+
+   if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) {
+      return -3;
+   }
+
+   return 0;
+}
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
 
 
-    QCBOREncodeContext EC;
-    QCBOREncode_Init(&EC, EncodedHalfsMem);
-    // These are mostly from https://en.wikipedia.org/wiki/Half-precision_floating-point_format
-    QCBOREncode_OpenMap(&EC);
-    // 64                                   # text(4)
-    //    7A65726F                          # "zero"
-    // F9 0000                              # primitive(0)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "zero", 0.00);
+/*
+[0.0, 3.14, 0.0, NaN, Infinity, 0.0, 3.140000104904175, 0.0, NaN, Infinity,
+ {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
+  102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
+ */
+static const uint8_t spExpectedFloats[] = {
+   0x8B,
+      0xF9, 0x00, 0x00,
+      0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
+      0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0xF9, 0x00, 0x00,
+      0xFA, 0x40, 0x48, 0xF5, 0xC3,
+      0xFA, 0x00, 0x00, 0x00, 0x00,
+      0xFA, 0x7F, 0xC0, 0x00, 0x00,
+      0xFA, 0x7F, 0x80, 0x00, 0x00,
+      0xA8,
+         0x18, 0x64,
+          0xF9, 0x00, 0x00,
+         0x18, 0x65,
+          0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
+         0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
+          0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
+         0x18, 0x69,
+          0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x18, 0x66,
+          0xF9, 0x00, 0x00,
+         0x18, 0x67,
+          0xFA, 0x40, 0x49, 0x0F, 0xDA,
+         0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
+          0xFA, 0x40, 0x2D, 0xF8, 0x54,
+         0x18, 0x6A,
+          0xFA, 0x00, 0x00, 0x00, 0x00};
 
-    // 64                                   # text(4)
-    //    7A65726F                          # "negative zero"
-    // F9 8000                              # primitive(0)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "negative zero", -0.00);
+static const uint8_t spExpectedFloatsNoHalf[] = {
+   0x8B,
+      0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
+      0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0xFA, 0x00, 0x00, 0x00, 0x00,
+      0xFA, 0x40, 0x48, 0xF5, 0xC3,
+      0xFA, 0x00, 0x00, 0x00, 0x00,
+      0xFA, 0x7F, 0xC0, 0x00, 0x00,
+      0xFA, 0x7F, 0x80, 0x00, 0x00,
+      0xA8,
+         0x18, 0x64,
+          0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x18, 0x65,
+          0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
+         0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
+          0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
+         0x18, 0x69,
+          0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x18, 0x66,
+          0xFA, 0x00, 0x00, 0x00, 0x00,
+         0x18, 0x67,
+          0xFA, 0x40, 0x49, 0x0F, 0xDA,
+         0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
+          0xFA, 0x40, 0x2D, 0xF8, 0x54,
+         0x18, 0x6A,
+          0xFA, 0x00, 0x00, 0x00, 0x00};
 
-    // 6A                                   # text(10)
-    //    696E66696E6974697479              # "infinitity"
-    // F9 7C00                              # primitive(31744)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "infinitity", INFINITY);
+int32_t GeneralFloatEncodeTests()
+{
+   UsefulBufC ExpectedFloats;
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
+   ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
+   (void)spExpectedFloatsNoHalf; // Avoid unused variable error
+#else
+   UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
+   ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
+   (void)spExpectedFloats; // Avoid unused variable error
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
 
-    // 73                                   # text(19)
-    //    6E6567617469766520696E66696E6974697479 # "negative infinitity"
-    // F9 FC00                              # primitive(64512)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "negative infinitity", -INFINITY);
+   QCBOREncodeContext EC;
+   QCBOREncode_Init(&EC, OutBuffer);
+   QCBOREncode_OpenArray(&EC);
 
-    // 63                                   # text(3)
-    //    4E614E                            # "NaN"
-    // F9 7E00                              # primitive(32256)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "NaN", NAN);
+   QCBOREncode_AddDouble(&EC, 0.0);
+   QCBOREncode_AddDouble(&EC, 3.14);
+   QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
+   QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
+   QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
 
-    // TODO: test a few NaN variants
+   QCBOREncode_AddFloat(&EC, 0.0);
+   QCBOREncode_AddFloat(&EC, 3.14f);
+   QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
+   QCBOREncode_AddFloatNoPreferred(&EC, NAN);
+   QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
 
-    // 63                                   # text(3)
-    //    6F6E65                            # "one"
-    // F9 3C00                              # primitive(15360)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "one", 1.0);
+   QCBOREncode_OpenMap(&EC);
 
-    // 69                                   # text(9)
-    //    6F6E65207468697264                # "one third"
-    // F9 3555                              # primitive(13653)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "one third", 0.333251953125);
+   QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
+   QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
+   QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
+   QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
 
-    // 76                                   # text(22)
-    //   6C6172676573742068616C662D707265636973696F6E # "largest half-precision"
-    // F9 7BFF                              # primitive(31743)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "largest half-precision",65504.0);
+   QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
+   QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
+   QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
+   QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
 
-    // 76                                   # text(22)
-    //   6C6172676573742068616C662D707265636973696F6E # "largest half-precision"
-    // F9 7BFF                              # primitive(31743)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "largest half-precision point one",65504.1);
+   QCBOREncode_CloseMap(&EC);
+   QCBOREncode_CloseArray(&EC);
 
-    // Float 65536.0F is 0x47800000 in hex. It has an exponent of 16, which
-    // is larger than 15, the largest half-precision exponent
-    // 78 18                                # text(24)
-    //    746F6F2D6C617267652068616C662D707265636973696F6E # "too-large half-precision"
-    // FA 47800000                          # primitive(31743)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "too-large half-precision", 65536.0);
+   UsefulBufC Encoded;
+   QCBORError uErr = QCBOREncode_Finish(&EC, &Encoded);
+   if(uErr) {
+      return -1;
+   }
 
-    // The smallest possible half-precision subnormal, but digitis are lost converting
-    // to half, so this turns into a double
-    // 72                                   # text(18)
-    //    736D616C6C657374207375626E6F726D616C # "smallest subnormal"
-    // FB 3E700000001C5F68                  # primitive(4499096027744984936)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "smallest subnormal", 0.0000000596046448);
+   if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
+      return -3;
+   }
 
-    // The smallest possible half-precision snormal, but digitis are lost converting
-    // to half, so this turns into a single TODO: confirm this is right
-    // 6F                                   # text(15)
-    //    736D616C6C657374206E6F726D616C    # "smallest normal"
-    // FA 387FFFFF                          # primitive(947912703)
-    // in hex single is 0x387fffff, exponent -15, significand 7fffff
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "smallest normal",    0.0000610351526F);
+   return 0;
+}
 
-    // 71                                   # text(17)
-    //    62696767657374207375626E6F726D616C # "biggest subnormal"
-    // F9 0400                              # primitive(1024)
-    // in hex single is 0x38800000, exponent -14, significand 0
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "biggest subnormal",  0.0000610351563F);
 
-    // 70                                   # text(16)
-    //    7375626E6F726D616C2073696E676C65  # "subnormal single"
-    // FB 37C16C2800000000                  # primitive(4017611261645684736)
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "subnormal single", 4e-40F);
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+/* returns 0 if equivalent, non-zero if not equivalent */
+static int CHECK_EXPECTED_DOUBLE(double val, double expected)
+{
+   double diff = val - expected;
 
-    // 03                                   # unsigned(3)
-    // F9 C000                              # primitive(49152)
-    QCBOREncode_AddDoubleAsSmallestToMapN(&EC, 3, -2.0);
+   diff = fabs(diff);
 
-    // 70                                   # text(16)
-    //    6C617267652073696E676C6520657870  # "large single exp"
-    // FA 7F400000                          # primitive(2134900736)
-    // (0x01LL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) | ((127LL + DOUBLE_EXPONENT_BIAS) << DOUBLE_EXPONENT_SHIFT);
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "large single exp", 2.5521177519070385E+38); // Exponent fits  single
+   if(diff > 0.000001) {
+      return 1;
+   } else {
+      return 0;
+   }
+}
+#endif
 
-    // 74                                   # text(20)
-    //    746F6F2D6C617267652073696E676C6520657870 # "too-large single exp"
-    // FB 47F8000000000000                  # primitive(5185894970917126144)
-    // (0x01LL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) | ((128LL + DOUBLE_EXPONENT_BIAS) << DOUBLE_EXPONENT_SHIFT);
-    // Exponent too large for single
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "too-large single exp", 5.104235503814077E+38);
 
-    // 66                                   # text(6)
-    //    646664666465                      # "dfdfde"
-    // FA 4B800000                          # primitive(1266679808)
-    // Single with no precision loss
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "biggest single with prec", 16777216);
+int32_t GeneralFloatDecodeTests()
+{
+   UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
 
-    // 78 18                                # text(24)
-    //    626967676573742073696E676C6520776974682070726563 # "biggest single with prec"
-    // FA 4B800000                          # primitive(1266679808)
-    // Double becuase of precision loss
-    QCBOREncode_AddDoubleAsSmallestToMap(&EC, "first single with prec loss", 16777217);
+   QCBORDecodeContext DC;
+   QCBORDecode_Init(&DC, TestData, 0);
 
-    // Just a convenient marker when cutting and pasting encoded CBOR
-    QCBOREncode_AddSZStringToMapN(&EC, 1, "fin");
+   QCBORItem Item;
+   QCBORError uErr;
 
-    QCBOREncode_CloseMap(&EC);
+   QCBORDecode_GetNext(&DC, &Item);
+   if(Item.uDataType != QCBOR_TYPE_ARRAY) {
+      return -1;
+   }
 
-    UsefulBufC EncodedHalfs;
-    QCBORError nReturn = QCBOREncode_Finish(&EC, &EncodedHalfs);
-    if(nReturn != QCBOR_SUCCESS) {
-        return -1;
-    }
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != 0.0) {
+      return -2;
+   }
+#else
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_ERR_HALF_PRECISION_UNSUPPORTED) {
+      return -3;
+   }
+#endif
 
-    if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) {
-        return -3;
-    }
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != 3.14) {
+      return -4;
+   }
 
-    return 0;
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != 0.0) {
+      return -5;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      !isnan(Item.val.dfnum)) {
+      return -6;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != INFINITY) {
+      return -7;
+   }
+
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != 0.0) {
+      return -8;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      CHECK_EXPECTED_DOUBLE(3.14, Item.val.dfnum)) {
+      return -9;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != 0.0) {
+      return -10;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      !isnan(Item.val.dfnum)) {
+      return -11;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != INFINITY) {
+      return -12;
+   }
+
+#else
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_ERR_HALF_PRECISION_UNSUPPORTED) {
+      return -13;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_FLOAT ||
+      Item.val.fnum != 3.14f) {
+      return -14;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_FLOAT ||
+      Item.val.fnum != 0.0f) {
+      return -15;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_FLOAT ||
+      !isnan(Item.val.fnum)) {
+      return -16;
+   }
+
+   uErr = QCBORDecode_GetNext(&DC, &Item);
+   if(uErr != QCBOR_SUCCESS ||
+      Item.uDataType != QCBOR_TYPE_FLOAT ||
+      Item.val.fnum != INFINITY) {
+      return -17;
+   }
+#endif
+   /* Sufficent test coverage. Don't need to decode the rest */
+
+   return 0;
 }
 
 
@@ -491,6 +919,3 @@
     return 0;
 }
 #endif
-
-
-
diff --git a/test/float_tests.h b/test/float_tests.h
index f777156..54daa3f 100644
--- a/test/float_tests.h
+++ b/test/float_tests.h
@@ -15,11 +15,26 @@
 
 #include <stdint.h>
 
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+
 int32_t HalfPrecisionDecodeBasicTests(void);
 
 int32_t DoubleAsSmallestTest(void);
 
 int32_t HalfPrecisionAgainstRFCCodeTest(void);
 
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+
+/*
+ This calls each and every method for encoding
+ floating-point numbers.
+ */
+int32_t GeneralFloatEncodeTests(void);
+
+/*
+ Tests basic float decoding.
+ */
+int32_t GeneralFloatDecodeTests(void);
+
 
 #endif /* float_tests_h */
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index deb4c6c..c3dcc1e 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -372,7 +372,7 @@
       return  -1;
 
 
-   if((  nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
+   if((   nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
       return (int32_t)nCBORError;
    if(Item.uDataType != QCBOR_TYPE_INT64 ||
       Item.val.int64 != 4294967295)
@@ -1276,19 +1276,19 @@
       UsefulBuf_Compare(Item.val.string, UsefulBuf_FromSZ("lies, damn lies and statistics"))) {
       return -17;
    }
-   
-   
+
+
    /*
     Test with map that nearly QCBOR_MAX_ITEMS_IN_ARRAY items in a
     map that when interpreted as an array will be too many. Test
     data just has the start of the map, not all the items in the map.
     */
    static const uint8_t pTooLargeMap[] = {0xb9, 0xff, 0xfd};
-   
+
    QCBORDecode_Init(&DCtx,
                     UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pTooLargeMap),
                     QCBOR_DECODE_MODE_MAP_AS_ARRAY);
-   
+
    if((QCBOR_ERR_ARRAY_TOO_LONG != QCBORDecode_GetNext(&DCtx, &Item))) {
       return -50;
    }
@@ -2105,14 +2105,14 @@
    0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
 
    // CBOR_TAG_B64
-   0xc1, 0xcf, 0xd8, 0x22, // 0xee, // Epoch date with extra tags TODO: fix this test
+   0xc1, 0xcf, 0xd8, 0x22, // 0xee, // Epoch date with extra tags
    0x1a, 0x53, 0x72, 0x4E, 0x01,
 
    0xc1, // tag for epoch date
    0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too large integer
 
    0xc1, // tag for epoch date
-   0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // double with value 1.1
+   0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // single with value 1.1
 
    0xc1, // tag for epoch date
    0xfa, 0x7f, 0x7f, 0xff, 0xff, // 3.4028234663852886e+38 too large
@@ -2127,7 +2127,7 @@
 
 
 // have to check float expected only to within an epsilon
-int CHECK_EXPECTED_DOUBLE(double val, double expected) {
+static int CHECK_EXPECTED_DOUBLE(double val, double expected) {
 
    double diff = val - expected;
 
@@ -2160,7 +2160,7 @@
       return -2;
    }
 
-   // Epoch date
+   // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
       return -3;
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
@@ -2186,6 +2186,7 @@
    }
 
    // Epoch date in float format with fractional seconds
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
       return -8;
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
@@ -2205,12 +2206,28 @@
    }
 
    // Largest double epoch date supported
-   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
-      Item.val.epochDate.nSeconds != 9223372036854773760 ||
-      Item.val.epochDate.nSeconds == 0) {
-      return -12;
+    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_SUCCESS ||
+       Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
+       Item.val.epochDate.nSeconds != 9223372036854773760 ||
+       Item.val.epochDate.nSeconds == 0) {
+       return -12;
+    }
+#else
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED) {
+      return -80;
    }
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED) {
+      return -80;
+   }
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED) {
+      return -80;
+   }
+   if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED) {
+      return -80;
+   }
+#endif
+
+
    // TODO: could use a few more tests with float, double, and half precsion
    // and negative (but coverage is still pretty good)
 
@@ -4096,8 +4113,10 @@
          [],
          []
       ]
-   }
+ }
  */
+
+
 static const uint8_t spMapOfEmpty[] = {
    0xa6, 0x00, 0x80, 0x09, 0x82, 0x80, 0x80, 0x08, 0xa3, 0x01,
    0x80, 0x02, 0xa0, 0x03, 0x80, 0x04, 0xa0, 0x05, 0x9f, 0xff,
@@ -4826,15 +4845,15 @@
    if(uCBORError != QCBOR_SUCCESS) {
       return 5;
    }
-   
-   
+
+
    // --- Sequence with unclosed indefinite length array ---
    static const uint8_t xx[] = {0x01, 0x9f, 0x02};
-   
+
    QCBORDecode_Init(&DCtx,
                     UsefulBuf_FROM_BYTE_ARRAY_LITERAL(xx),
                     QCBOR_DECODE_MODE_NORMAL);
-   
+
    // Get the first item
    uCBORError = QCBORDecode_GetNext(&DCtx, &Item);
    if(uCBORError != QCBOR_SUCCESS) {
@@ -4843,7 +4862,7 @@
    if(Item.uDataType != QCBOR_TYPE_INT64) {
       return 8;
    }
-   
+
    // Get a second item
    uCBORError = QCBORDecode_GetNext(&DCtx, &Item);
    if(uCBORError != QCBOR_SUCCESS) {
@@ -4860,14 +4879,14 @@
       return 11;
    }
 
-   
+
    // --- Sequence with a closed indefinite length array ---
    static const uint8_t yy[] = {0x01, 0x9f, 0xff};
-   
+
    QCBORDecode_Init(&DCtx,
                     UsefulBuf_FROM_BYTE_ARRAY_LITERAL(yy),
                     QCBOR_DECODE_MODE_NORMAL);
-   
+
    // Get the first item
    uCBORError = QCBORDecode_GetNext(&DCtx, &Item);
    if(uCBORError != QCBOR_SUCCESS) {
@@ -4876,7 +4895,7 @@
    if(Item.uDataType != QCBOR_TYPE_INT64) {
       return 13;
    }
-   
+
    // Get a second item
    uCBORError = QCBORDecode_GetNext(&DCtx, &Item);
    if(uCBORError != QCBOR_SUCCESS) {
@@ -4893,7 +4912,7 @@
       return 16;
    }
 
-   
+
    return 0;
 }
 
diff --git a/test/run_tests.c b/test/run_tests.c
index 794c456..0adccd4 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -94,9 +94,13 @@
     TEST_ENTRY(IntegerValuesParseTest),
     TEST_ENTRY(MemPoolTest),
     TEST_ENTRY(IndefiniteLengthStringTest),
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
     TEST_ENTRY(HalfPrecisionDecodeBasicTests),
     TEST_ENTRY(DoubleAsSmallestTest),
     TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest),
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+    TEST_ENTRY(GeneralFloatEncodeTests),
+    TEST_ENTRY(GeneralFloatDecodeTests),
     TEST_ENTRY(BstrWrapTest),
     TEST_ENTRY(BstrWrapErrorTest),
     TEST_ENTRY(BstrWrapNestTest),