Merge from master
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index e43bf04..34bdfc7 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -178,6 +178,7 @@
 		E78C91DF240C90C100F4CECE /* qcbor_common.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_common.h; path = inc/qcbor/qcbor_common.h; sourceTree = "<group>"; tabWidth = 3; };
 		E78C91E0240C90C100F4CECE /* qcbor_private.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_private.h; path = inc/qcbor/qcbor_private.h; sourceTree = "<group>"; tabWidth = 3; };
 		E78C91E1240C90C100F4CECE /* qcbor_encode.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_encode.h; path = inc/qcbor/qcbor_encode.h; sourceTree = "<group>"; tabWidth = 3; };
+		E7A7B60E2B76FB62009102C2 /* Serialization.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = Serialization.md; path = doc/Serialization.md; sourceTree = "<group>"; };
 		E7C960B72800A09E00FB537C /* ub-example.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ub-example.h"; sourceTree = "<group>"; };
 		E7C960B82800A09E00FB537C /* ub-example.c */ = {isa = PBXFileReference; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = "ub-example.c"; sourceTree = "<group>"; tabWidth = 3; };
 		E7FDBF16256C969D007138A8 /* QCBOR_Disable_Indef */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Indef; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -246,6 +247,7 @@
 			children = (
 				E776E161214EE19C00E67947 /* README.md */,
 				E743D132251014E60017899F /* Tagging.md */,
+				E7A7B60E2B76FB62009102C2 /* Serialization.md */,
 				E776E096214AE0C700E67947 /* cmd_line_main.c */,
 				E776E092214AE07C00E67947 /* inc */,
 				E776E08B214AE06600E67947 /* src */,
@@ -274,8 +276,8 @@
 				E776E08C214AE07400E67947 /* qcbor_encode.c */,
 				E776E08E214AE07500E67947 /* qcbor_decode.c */,
 				E776E08D214AE07500E67947 /* UsefulBuf.c */,
-				E73B57582161CA690080D658 /* ieee754.c */,
 				E73B57572161CA680080D658 /* ieee754.h */,
+				E73B57582161CA690080D658 /* ieee754.c */,
 				E7864765252CE63100A0C11B /* qcbor_err_to_str.c */,
 			);
 			name = src;
diff --git a/README.md b/README.md
index 5160cb9..9adfefe 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,18 @@
+This is the QCBOR 2.0 branch. It is under development and not ready for use.
+
+The plan for QCBOR 2 is a few larger features:
+  - Map sorting
+  - Full canonical encoding support (CDE)
+  - Improved support for tag handling
+  - Perhaps other features like OID support
+  - Perhaps dCBOR support
+  - Improved test and verification
+  - Improved documentation
+  - Better presence in GitHub
+
+The improved tag handling is one of the largest work items and may change
+backwards compatibility.
+
 ![QCBOR Logo](https://github.com/laurencelundblade/qdv/blob/master/logo.png?raw=true)
 
 **QCBOR** is a powerful, commercial-quality CBOR encoder-decoder that
@@ -323,23 +338,23 @@
 defining this is to remove dependency on floating point hardware and
 libraries.
 
+
 #### #define QCBOR_DISABLE_PREFERRED_FLOAT
 
-This eliminates support for half-precision
-and CBOR preferred serialization by disabling
-QCBOR's shift and mask based implementation of
-half-precision floating-point.
+This eliminates support of:
+- encode/decode of half-precision
+- shortest-form encoding of floats
+- QCBORDecode_GetNumberConvertPrecisely()
 
-With this defined, single and double-precision floating-point
-numbers can still be encoded and decoded. Conversion
-of floating-point to and from integers, big numbers and
-such is also supported. Floating-point dates are still
-supported.
+This saves about 1KB of object code, though much of this can be saved
+by not calling any functions to encode doubles or floats or
+QCBORDecode_GetNumberConvertPrecisely
 
-The primary reason to define this is to save object code.
-Roughly 900 bytes are saved, though about half of this
-can be saved just by not calling any functions that
-encode floating-point numbers.
+With this defined, single and double-precision floating-point numbers
+can still be encoded and decoded. Some conversion of floating-point to
+and from integers, big numbers and such is also supported. Floating-point
+dates are still supported.
+
 
 #### #define USEFULBUF_DISABLE_ALL_FLOAT
 
@@ -485,7 +500,7 @@
 
 QCBOR_DISABLE_NON_INTEGER_LABELS causes any label that doesn't
 fit in an int64_t to result in a QCBOR_ERR_MAP_LABEL_TYPE error.
-This also disables QCBOR_DECODE_MODE_MAP_AS_ARRAY and 
+This also disables QCBOR_DECODE_MODE_MAP_AS_ARRAY and
 QCBOR_DECODE_MODE_MAP_STRINGS_ONLY. It is fairly common for CBOR-based
 protocols to use only small integers as labels.
 
diff --git a/doc/Serialization.md b/doc/Serialization.md
new file mode 100644
index 0000000..8637e47
--- /dev/null
+++ b/doc/Serialization.md
@@ -0,0 +1,8 @@
+@file Serialization.md
+
+@anchor Serialization
+
+# Serialization and Determinism
+
+To be filled in...
+
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index 3b7afd7..218d269 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -44,6 +44,10 @@
  when         who             what, where, why
  --------     ----            --------------------------------------------------
  10/05/2024   llundblade      Add Xxx_OffsetToPointer.
+ 28/02/2024   llundblade      Rearrange UsefulOutBuf_Compare().
+ 19/11/2023   llundblade      Add UsefulOutBuf_GetOutput().
+ 19/11/2023   llundblade      Add UsefulOutBuf_Swap().
+ 19/11/2023   llundblade      Add UsefulOutBuf_Compare().
  19/12/2022   llundblade      Document that adding empty data is allowed.
  4/11/2022    llundblade      Add GetOutPlace and Advance to UsefulOutBuf.
  9/21/2021    llundbla        Clarify UsefulOutBuf size calculation mode
@@ -866,7 +870,7 @@
 
 
 /**
- * @brief Initialize and supply the actual output buffer.
+ * @brief Initialize and supply the output buffer.
  *
  * @param[out] pUOutBuf  The @ref UsefulOutBuf to initialize.
  * @param[in] Storage    Buffer to output into.
@@ -1348,7 +1352,7 @@
 
 
 /**
- *  @brief Returns the resulting valid data in a UsefulOutBuf
+ *  @brief Returns the data put into a UsefulOutBuf.
  *
  *  @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
  *
@@ -1366,7 +1370,7 @@
 
 
 /**
- * @brief Copies the valid data into a supplied buffer
+ * @brief Copy out the data put into a UsefulOutBuf.
  *
  * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
  * @param[out] Dest     The destination buffer to copy into.
@@ -1376,11 +1380,105 @@
  *         state was entered.
  *
  * This is the same as UsefulOutBuf_OutUBuf() except it copies the
- * data to @c Dest.
+ * data to @c Dest rather than returning a pointer.
  */
 UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
 
 
+/**
+ * @brief Returns data starting at an offset that was put into a UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] uOffset    Offset to bytes to return.
+ *
+ * @return NULLUsefulBufC or the bytes at the offset.
+ *
+ * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
+ * maybe specified. It returns the bytes starting at @c uOffset to the
+ * end of what was encoded so far. Calling this with @c uOffset 0 is
+ * equivalent to UsefulOutBuf_OutUBuf().
+ *
+ * If there's nothing at @c uOffset or it is past the in the output
+ * buffer, a \ref NULLUsefulBufC is returned.
+ *
+ * This is typically not needed in typical use. It is used by QCBOR
+ * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
+ * sorting CBOR maps.
+ */
+UsefulBufC
+UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
+
+
+/**
+ * @brief Compare bytes at offsets.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] uStart1   Offset of first bytes to compare.
+ * @param[in] uLen1     Length of first bytes to compare.
+ * @param[in] uStart2   Offset of second bytes to compare.
+ * @param[in] uLen2     Length of second bytes to compare.
+ *
+ * @return  0 for equality, positive if uStart1 is lexographically larger,
+ *          negative if uStart2 is lexographically larger.
+ * 
+ * This looks into bytes that have been output at the offsets @c start1
+ * and @c start2. It compares bytes at those two starting points until
+ * they are not equal or @c uLen1 or @c uLen2 is reached. If the
+ * length of the string given is off the end of the output data, the
+ * string will be effectively concated to the data in the output
+ * buffer for the comparison.
+ *
+ * This returns positive when @c uStart1 lexographically sorts ahead
+ * of @c uStart2 and vice versa.  Zero is returned if the strings
+ * compare equally.
+ *
+ * If lengths are unequal and the first bytes are an exact subset of
+ * the second string, then a positve value will be returned and vice
+ * versa.
+ *
+ * If either start is past the end of data in the output buffer, 0
+ * will be returned. It is the caller's responsibility to make sure
+ * the offsets are not off the end so that a comparison is actually
+ * being made. No data will ever be read off the end of the buffer so
+ * this safe no matter what offsets are passed.
+ *
+ * This is a relatively odd function in that it works on data in the
+ * output buffer. It is employed by QCBOR to sort CBOR-encoded maps
+ * that are in the output buffer.
+ */
+int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf,
+                         size_t uStart1, size_t uLen1,
+                         size_t uStart2, size_t uLen2);
+
+/**
+ * @brief Swap two regions of output bytes.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] uStartOffset   Offset to start of bytes to be swapped.
+ * @param[in] uPivotOffset   Offset to pivot around which bytes are swapped.
+ * @param[in] uEndOffset       Offset to end of region to be swappe.
+ *
+ * This reaches into bytes that have been output and swaps two
+ * adjacent regions.
+ *
+ * If any of the offsets are outside the range of valid data, no
+ * swapping will be performed. If the start is not the smallest and
+ * the pivot is not in the middle no swapping will be performed.
+ *
+ * The byte at @c uStartOffset will participate in the swapping.  The
+ * byte at @c uEndOffset will not participate in the swapping, only
+ * the byte before it.
+ *
+ * This is a relatively odd function in that it works on data in the
+ * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
+ * maps.
+ */
+void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
+                       size_t        uStartOffset,
+                       size_t        uPivotOffset,
+                       size_t        uEndOffset);
+
+
 
 
 /**
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 20643ab..d64e973 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -44,6 +44,7 @@
 #endif
 
 
+
 /**
  * @file qcbor_common.h
  *
@@ -60,8 +61,8 @@
  *   - QCBOR 1.1 is indicated by the #define QCBOR_1_1
  *   - QCBOR 1.0 is indicated by the absence of all the above
  */
-#define QCBOR_VERSION_MAJOR 1
-#define QCBOR_VERSION_MINOR 3
+#define QCBOR_VERSION_MAJOR 2
+#define QCBOR_VERSION_MINOR 0
 #define QCBOR_VERSION_PATCH 0
 
 
@@ -407,7 +408,7 @@
     *  this error is returned. This error is unrecoverable because the
     *  built-in tag decoding doesn't try to consume the unexpected
     *  type. In previous versions of QCBOR this was considered a
-    *  recoverable error hence @ref QCBOR_ERR_BAD_TAG_CONTENT. Going
+    *  recoverable error hence QCBOR_ERR_BAD_TAG_CONTENT. Going
     *  back further, RFC 7049 use the name "optional tags". That name
     *  is no longer used because "optional" was causing confusion. See
     *  also @ref QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT. */
@@ -523,10 +524,21 @@
     * (to save object code). */
    QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT = 78,
 
+   /** Attempt to output non-preferred, non-CDE or non-dCBOR when not
+    * allowed by mode. See QCBOREncode_SerializationPreferred(),
+    * QCBOREncode_SerializationCDE(),
+    * QCBOREncode_SerializationdCBOR().
+    */
+   QCBOR_ERR_NOT_PREFERRED = 79,
+
+   /* Trying to encode something that is discouraged (e.g., 65-bit
+    * negative integer) without allowing it by calling
+    * QCBOREncode_Allow() */
+   QCBOR_ERR_NOT_ALLOWED = 80,
    /** QCBORDecode_EnterBstrWrapped() cannot be used on
     * indefinite-length strings because they exist in memory pool for
     * a @ref QCBORStringAllocate. */
-   QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING = 79,
+   QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING = 81,
 
    /** A range of error codes that can be made use of by the
     * caller. QCBOR internally does nothing with these except notice
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 918d162..c1f37cf 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -316,6 +316,16 @@
 /** Type for a double floating-point number. Data is in @c val.dfnum. */
 #define QCBOR_TYPE_DOUBLE        27
 
+/** Special type for integers between -2^63 - 1 to -2^64 that
+ * can't be returned as @ref QCBOR_TYPE_INT64 because they don't fit
+ * in an int64_t. The value is returned in @c val.uint64, but this
+ * isn't the number transmitted. Do this arithmatic (carefully to
+ * avoid over/underflow) to get the value transmitted: - val.uint64 - 1.
+ * See QCBOREncode_AddNegativeUInt64() for a longer explanation
+ * and warning. */
+#define QCBOR_TYPE_65BIT_NEG_INT 28
+
+
 #define QCBOR_TYPE_BREAK         31 /* Used internally; never returned */
 
 /** For @ref QCBOR_DECODE_MODE_MAP_AS_ARRAY decode mode, a map that is
@@ -463,9 +473,7 @@
       /** The value for @c uDataType @ref QCBOR_TYPE_DAYS_EPOCH -- the
        *  number of days before or after Jan 1, 1970. */
       int64_t     epochDays;
-      /** No longer used. Was the value for @ref QCBOR_TYPE_DATE_STRING,
-       * but now that value is in @c string. This will be removed in QCBOR 2.0. */
-      UsefulBufC  dateString;
+
       /** The value for @c uDataType @ref QCBOR_TYPE_POSBIGNUM and
        * @ref QCBOR_TYPE_NEGBIGNUM.  */
       UsefulBufC  bigNum;
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 83c167e..c72f4d9 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -437,7 +437,7 @@
  * is too small, encoding will go into an error state and not write
  * anything further.
  *
- * If allocating on the stack the convenience macro
+ * If allocating on the stack, the convenience macro
  * UsefulBuf_MAKE_STACK_UB() can be used, but its use is not required.
  *
  * Since there is no reallocation or such, the output buffer must be
@@ -471,6 +471,144 @@
 
 
 /**
+ * @brief Select preferred serialization mode.
+ *
+ * @param[in] pCtx   The encoding context for mode set.
+ *
+ * Setting this mode will cause QCBOR to return an error if an attempt
+ * is made to use one of the methods that produce non-preferred
+ * serialization. It doesn't change anything else as QCBOR produces
+ * preferred serialization by default.
+ *
+ * The non-preferred methods are: QCBOREncode_AddFloatNoPreferred(),
+ * QCBOREncode_AddDoubleNoPreferred(),
+ * QCBOREncode_OpenArrayIndefiniteLength(),
+ * QCBOREncode_CloseArrayIndefiniteLength(),
+ * QCBOREncode_OpenMapIndefiniteLength(),
+ * QCBOREncode_CloseMapIndefiniteLength(), plus those derived from the
+ * above listed.
+ *
+ * This mode is just a user guard to prevent accidentally calling
+ * something that produces non-preferred serialization. It doesn't do
+ * anything but causes errors to occur on attempts to call the above
+ * listed functions. This does nothing if the library is compiled
+ * QCBOR_DISABLE_ENCODE_USAGE_GUARDS.
+ *
+ * See @ref Serialization. It is usually not necessary to set this
+ * mode, but there is usually no disadvantage to setting it.  Preferred
+ * Serialization is defined in RFC 8949, section 4.1.
+ */
+static void
+QCBOREncode_SerializationPreferred(QCBOREncodeContext *pCtx);
+
+
+/**
+ * @brief Select CBOR deterministic encoding mode.
+ *
+ * @param[in] pCtx   The encoding context for mode set.
+
+ * This causes QCBOR to produce CBOR Deterministic Encoding (CDE).
+ * With CDE, two distant unrelated CBOR encoders will produce exactly
+ * the same encoded CBOR for a given input.
+ *
+ * In addition to doing everything
+ * QCBOREncode_SerializationPreferred() does (including exclusion of
+ * indefinite lengths), this causes maps to be sorted. The map is
+ * sorted automatically when QCBOREncode_CloseMap() is called.
+ * QCBOREncode_CloseMap() becomes equivalent to
+ * QCBOREncode_CloseAndSortMap().
+ *
+ * Note that linking this function causese about 30% more code from
+ * the QCBOR library to be linked. Also, QCBOREncode_CloseMap() runs
+ * slower, but this is probably only of consequence in very
+ * constrained environments.
+ *
+ * See @ref Serialization. It is usually not necessary to set this
+ * mode as determinism is very rarely needed. However it will
+ * usually work with most protocols. CDE is defined in
+ * draft-ietf-cbor-cde.
+ */
+static void
+QCBOREncode_SerializationCDE(QCBOREncodeContext *pCtx);
+
+
+/**
+ * @brief Select "dCBOR" encoding mode.
+ *
+ * @param[in] pCtx   The encoding context for mode set.
+ *
+ * This is a superset of CDE. This function does everything
+ * QCBOREncode_SerializationCDE() does. Also it is a super set of
+ * preferred serialization and does everything
+ * QCBOREncode_SerializationPreferred() does.
+ *
+ * The main feature of dCBOR is that there is only one way to serialize a
+ * particular numeric value. This changes the behavior of functions
+ * that add floating-point numbers.  If the floating-point number is
+ * whole, it will be encoded as an integer, not a floating-point number.
+ * 0.000 will be encoded as 0x00. Precision is never lost in this
+ * conversion.
+ *
+ * dCBOR also disallows NaN payloads. QCBOR will allow NaN payloads if
+ * you pass a NaN to one of the floating-point encoding functions.
+ * This mode forces all NaNs to the half-precision queit NaN. Also see
+ * QCBOREncode_Allow().
+ *
+ * dCBOR also disallows 65-bit negative integers.
+ *
+ * dCBOR disallows use of any simple type other than true, false and
+ * NULL. In particular it disallows use of "undef" produced by
+ * QCBOREncode_AddUndef().
+ *
+ * See @ref Serialization. Set this mode only if the protocol you are
+ * implementing requires dCBOR. This mode is usually not compatible
+ * with protocols that don't use dCBOR. dCBOR is defined in
+ * draft-mcnally-deterministic-cbor.
+ */
+static void
+QCBOREncode_SerializationdCBOR(QCBOREncodeContext *pCtx);
+
+
+
+
+/** Bit flag to be passed to QCBOREncode_Allow() to allow NaN payloads
+ *  to be output by QCBOREncode_AddDouble(),
+ *  QCBOREncode_AddDoubleNoPreferred(), QCBORENcode_AddFloat() and
+ *  QCBOREncode_AddSingleleNoPreferred. */
+#define QCBOR_ENCODE_ALLOW_NAN_PAYLOAD 0x01
+
+/** Bit flag to be passed to QCBOREncode_Allow() to allow use of
+ *  QCBOREncode_AddNegativeUInt64(). */
+#define QCBOR_ENCODE_ALLOW_65_BIG_NEG  0x02
+
+/** Bit flag to be passed to QCBOREncode_Allow() output of less
+ *  interoperable values. See @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD, and
+ *  @ref QCBOR_ENCODE_ALLOW_65_BIG_NEG. */
+#define QCBOR_ENCODE_ALLOW_ALL         0xFF
+
+
+/**
+ * @brief Allow encoding of less-interoperable values.
+ *
+ * @param[in] pCtx    The encoding context.
+ * @param[in] uAllow  Bit flags indicating what to allow.
+ *
+ * There are a few things in the CBOR standard that are often not
+ * supported and are thus not very interoperable.  By default QCBOR
+ * will error if you attempt to output them. This disables that
+ * error.
+ *
+ * See @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD and 
+ * @ref QCBOR_ENCODE_ALLOW_65_BIG_NEG.
+ *
+ * This does nothing if the library is compiled
+ * QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+static void
+QCBOREncode_Allow(QCBOREncodeContext *pCtx, uint8_t uAllow);
+
+
+
+/**
  * @brief  Add a signed 64-bit integer to the encoded output.
  *
  * @param[in] pCtx   The encoding context to add the integer to.
@@ -546,6 +684,55 @@
 
 
 /**
+ * @brief Add a negative 64-bit integer to encoded output
+ *
+ * @param[in] pCtx  The encoding context to add the integer to.
+ * @param[in] uNum  The integer to add.
+ *
+ * QCBOREncode_AddInt64() is much better to encode negative integers
+ * than this.  What this can do is add integers with one more
+ * significant bit than an int64_t (a "65-bit" integer if you count
+ * the sign as a bit) which is possible because CBOR happens to
+ * support such integers.
+ *
+ * Because use of this is discouraged. It must be explicitly allowed
+ * by passing @ref QCBOR_ENCODE_ALLOW_65_BIG_NEG to a call to
+ * QCBOREncode_Allow().
+ *
+ * The actual value encoded is -uNum - 1. That is, give 0 for uNum to
+ * transmit -1, give 1 to transmit -2 and give UINT64_MAX to transmit
+ * -UINT64_MAX-1 (18446744073709551616). The interface is odd like
+ * this so all negative values CBOR can represent can be encoded by
+ * QCBOR (making this a complete CBOR implementation).
+ *
+ * The most negative value QCBOREncode_AddInt64() can encode is
+ * -9223372036854775808 which is -2^63 or negative 0x800000000000.
+ * This can encode from -9223372036854775809 to -18446744073709551616
+ * or -2^63 - 1 to -2^64. Note that it is not possible to represent
+ * positive or negative 18446744073709551616 in any standard C data
+ * type.
+ *
+ * Negative integers are normally decoded in QCBOR with type
+ * @ref QCBOR_TYPE_INT64.  Integers in the range of -9223372036854775809
+ * to -18446744073709551616 are returned as @ref QCBOR_TYPE_65BIT_NEG_INT.
+ *
+ * WARNING: some CBOR decoders will be unable to decode -2^63 - 1 to
+ * -2^64.  Also, most CPUs do not have registers that can represent
+ * this range.  If you need 65-bit negative integers, you likely need
+ * negative 66, 67 and 68-bit negative integers so it is likely better
+ * to use CBOR big numbers where you can have any number of bits. See
+ * QCBOREncode_AddTNegativeBignum() and @ref Serialization.
+ */
+void
+QCBOREncode_AddNegativeUInt64(QCBOREncodeContext *pCtx, uint64_t uNum);
+
+static void
+QCBOREncode_AddNegativeUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum);
+
+static void
+QCBOREncode_AddNegativeUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum);
+
+/**
  * @brief  Add a UTF-8 text string to the encoded output.
  *
  * @param[in] pCtx   The encoding context to add the text to.
@@ -648,6 +835,9 @@
  *
  * See also QCBOREncode_AddDoubleNoPreferred(), QCBOREncode_AddFloat()
  * and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
+ *
+ * By default, this will error out on an attempt to encode a NaN with
+ * a payload. See QCBOREncode_Allow() and @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD.
  */
 static void
 QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum);
@@ -687,8 +877,8 @@
  * @param[in] pCtx  The encoding context to add the double to.
  * @param[in] dNum  The double-precision number to add.
  *
- * This always outputs the number as a 64-bit double-precision.
- * Preferred serialization is not used.
+ * Output a double-precision float straight-through with no checking or
+ * processing for preferred serializtion, dCBOR or other.
  *
  * Error handling is the same as QCBOREncode_AddInt64().
  *
@@ -711,8 +901,8 @@
  * @param[in] pCtx  The encoding context to add the double to.
  * @param[in] fNum  The single-precision number to add.
  *
- * This always outputs the number as a 32-bit single-precision.
- * Preferred serialization is not used.
+ * Output a single-precision float straight-through with no checking or
+ * processing for preferred serializtion, dCBOR or other.
  *
  * Error handling is the same as QCBOREncode_AddInt64().
  *
@@ -2025,10 +2215,35 @@
  * This is the same as QCBOREncode_CloseMap(), but the open map that
  * is being close must be of indefinite length.
  */
-static  void
+static void
 QCBOREncode_CloseMapIndefiniteLength(QCBOREncodeContext *pCtx);
 
 
+/**
+ * @brief Close and sort an open map.
+ *
+ * @param[in] pCtx The encoding context to close the map in .
+ *
+ * This is the same as QCBOREncode_CloseMap() except it sorts the map
+ * per RFC 8949 Section 4.2.1 and checks for duplicate map keys. This
+ * sort is lexicographic of the CBOR-encoded map labels.
+ *
+ * This is more expensive than most things in the encoder. It uses
+ * bubble sort which runs in n-squared time where @c n is the number
+ * of map items. Sorting large maps on slow CPUs might be slow. This
+ * is also increases the object code size of the encoder by about 30%
+ * (500-1000 bytes).
+ *
+ * Bubble sort was selected so as to not need require configuration of
+ * a buffer to track map item offsets. Bubble sort works well even
+ * though map items are not all the same size because it always swaps
+ * adjacent items.
+ */
+void 
+QCBOREncode_CloseAndSortMap(QCBOREncodeContext *pCtx);
+
+void 
+QCBOREncode_CloseAndSortMapIndef(QCBOREncodeContext *pCtx);
 
 
 /**
@@ -2390,6 +2605,7 @@
                                    int64_t             nExponent);
 
 
+
 /**
  * @brief  Semi-private method to add simple items and floating-point.
  *
@@ -2414,50 +2630,48 @@
 }
 
 
-/**
- * @brief Semi-private method to add only the type and length of a byte string.
- *
- * @param[in] pCtx    The context to initialize.
- * @param[in] Bytes   Pointer and length of the input data.
- *
- * This will be removed in QCBOR 2.0. It was never a public function.
- *
- * This is the same as QCBOREncode_AddBytes() except it only adds the
- * CBOR encoding for the type and the length. It doesn't actually add
- * the bytes. You can't actually produce correct CBOR with this and
- * the rest of this API. It is only used for a special case where the
- * valid CBOR is created manually by putting this type and length in
- * and then adding the actual bytes. In particular, when only a hash
- * of the encoded CBOR is needed, where the type and header are hashed
- * separately and then the bytes is hashed. This makes it possible to
- * implement COSE Sign1 with only one copy of the payload in the
- * output buffer, rather than two, roughly cutting memory use in half.
- *
- * This is only used for this odd case, but this is a supported
- * tested function for QCBOR 1.0.
- *
- * See also QCBOREncode_EncodeHead().
- */
-static void
-QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx,
-                            UsefulBufC          Bytes);
-
-static void
-QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx,
-                                 const char         *szLabel,
-                                 UsefulBufC          Bytes);
-
-static void
-QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx,
-                                 int64_t              nLabel,
-                                 UsefulBufC           Bytes);
-
-
 /* Forward declaration */
 static void
 QCBOREncode_AddSZString(QCBOREncodeContext *pMe, const char *szString);
 
 
+static inline void
+QCBOREncode_SerializationCDE(QCBOREncodeContext *pMe)
+{
+   /* The use of a function pointer here is a little trick to reduce
+    * code linked for the common use cases that don't sort.  If this
+    * function is never linked, then QCBOREncode_CloseAndSortMap() is
+    * never linked and the amount of code pulled in is small. If the
+    * mode switch between sorting and not sorting were an if
+    * statement, then QCBOREncode_CloseAndSortMap() would always be
+    * linked even when not used. */
+   pMe->pfnCloseMap = QCBOREncode_CloseAndSortMap;
+   pMe->uMode = QCBOR_ENCODE_MODE_CDE;
+}
+
+static inline void
+QCBOREncode_SerializationdCBOR(QCBOREncodeContext *pMe)
+{
+   pMe->pfnCloseMap = QCBOREncode_CloseAndSortMap;
+   pMe->uMode = QCBOR_ENCODE_MODE_DCBOR;
+}
+
+static inline void
+QCBOREncode_SerializationPreferred(QCBOREncodeContext *pMe)
+{
+   pMe->uMode = QCBOR_ENCODE_MODE_PREFERRED;
+}
+
+static inline void
+QCBOREncode_Allow(QCBOREncodeContext *pMe, const uint8_t uAllow)
+{
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   pMe->uAllow = uAllow;
+#else
+   (void)uAllow;
+   (void)pMe;
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+}
 
 
 static inline void
@@ -2506,6 +2720,24 @@
 
 
 static inline void
+QCBOREncode_AddNegativeUInt64ToMap(QCBOREncodeContext *pMe, const char *szLabel, uint64_t uNum)
+{
+   /* Use _AddBuffer() because _AddSZString() is defined below, not above */
+   QCBOREncode_Private_AddBuffer(pMe,
+                                 CBOR_MAJOR_TYPE_TEXT_STRING,
+                                 UsefulBuf_FromSZ(szLabel));
+   QCBOREncode_AddNegativeUInt64(pMe, uNum);
+}
+
+static inline void
+QCBOREncode_AddNegativeUInt64ToMapN(QCBOREncodeContext *pMe, int64_t nLabel, uint64_t uNum)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddNegativeUInt64(pMe, uNum);
+}
+
+
+static inline void
 QCBOREncode_AddText(QCBOREncodeContext *pMe, const UsefulBufC Text)
 {
    QCBOREncode_Private_AddBuffer(pMe, CBOR_MAJOR_TYPE_TEXT_STRING, Text);
@@ -2817,35 +3049,6 @@
 }
 
 
-/*
- * Public functions for adding only a byte string length. See qcbor/qcbor_encode.h
- */
-static inline void
-QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
-{
-   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes.len, 0);
-}
-
-
-static inline void
-QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pMe,
-                                 const char         *szLabel,
-                                 const UsefulBufC    Bytes)
-{
-    QCBOREncode_AddSZString(pMe, szLabel);
-    QCBOREncode_AddBytesLenOnly(pMe, Bytes);
-}
-
-static inline void
-QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pMe,
-                                  const int64_t       nLabel,
-                                  const UsefulBufC    Bytes)
-{
-    QCBOREncode_AddInt64(pMe, nLabel);
-    QCBOREncode_AddBytesLenOnly(pMe, Bytes);
-}
-
-
 static inline void
 QCBOREncode_AddTBinaryUUID(QCBOREncodeContext *pMe,
                            const uint8_t       uTagRequirement,
@@ -3758,8 +3961,15 @@
 static inline void
 QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint8_t uNum)
 {
-   /* This check often is optimized out because uNum is known at compile time. */
 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(pMe->uMode >= QCBOR_ENCODE_MODE_DCBOR) {
+      if(uNum < CBOR_SIMPLEV_FALSE ||
+         uNum > CBOR_SIMPLEV_NULL) {
+         pMe->uError = QCBOR_ERR_NOT_PREFERRED;
+         return;
+      }
+   }
+   /* This check often is optimized out because uNum is known at compile time. */
    if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
       pMe->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
       return;
@@ -3875,6 +4085,7 @@
    QCBOREncode_OpenArray(pMe);
 }
 
+
 static inline void
 QCBOREncode_CloseArray(QCBOREncodeContext *pMe)
 {
@@ -3905,7 +4116,7 @@
 static inline void
 QCBOREncode_CloseMap(QCBOREncodeContext *pMe)
 {
-   QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
+   (pMe->pfnCloseMap)(pMe);
 }
 
 static inline void
diff --git a/inc/qcbor/qcbor_private.h b/inc/qcbor/qcbor_private.h
index a061809..04d0d11 100644
--- a/inc/qcbor/qcbor_private.h
+++ b/inc/qcbor/qcbor_private.h
@@ -92,9 +92,9 @@
  *                                should return 'x'.
  *  FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) Can be used when either disabled
  *                                             preferred float or disabling
- *                                             hardware floating point results in
- *                                             error, and all other cases should
- *                                             return 'x'.
+ *                                             hardware floating point results
+ *                                             in error, and all other cases
+ *                                             should return 'x'.
  */
 #ifdef USEFULBUF_DISABLE_ALL_FLOAT
    #define FLOAT_ERR_CODE_NO_FLOAT(x)                 QCBOR_ERR_ALL_FLOAT_DISABLED
@@ -165,6 +165,8 @@
  * a uin32_t.
  *
  * This will cause trouble on a machine where size_t is less than 32-bits.
+ *
+ * TODO: make this public?
  */
 #define QCBOR_MAX_ARRAY_OFFSET  (UINT32_MAX - 100)
 
@@ -215,14 +217,29 @@
  * functions to form a public "object" that does the job of encdoing.
  *
  * Size approximation (varies with CPU/compiler):
- *   64-bit machine: 27 + 1 (+ 4 padding) + 136 = 32 + 136 = 168 bytes
+ *  64-bit machine: 27 + 1 (+ 4 padding) + 136 = 32 + 136 = 168 bytes
  *  32-bit machine: 15 + 1 + 132 = 148 bytes
  */
+typedef struct _QCBOREncodeContext QCBORPrivateEncodeContext;
+
+
+/* These are in order of increasing strictness. Order is relied upon in
+ * implementation. */
+#define QCBOR_ENCODE_MODE_ANY       0
+#define QCBOR_ENCODE_MODE_PREFERRED 1
+#define QCBOR_ENCODE_MODE_CDE       2
+#define QCBOR_ENCODE_MODE_DCBOR     3
+
+
 struct _QCBOREncodeContext {
    /* PRIVATE DATA STRUCTURE */
    UsefulOutBuf      OutBuf;  /* Pointer to output buffer, its length and
                                * position in it. */
    uint8_t           uError;  /* Error state, always from QCBORError enum */
+   uint8_t           uMode;   /* @ref QCBOR_ENCODE_MODE_PREFERRED or related */
+   uint8_t           uAllow;  /* @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD, ... */
+   void            (*pfnCloseMap)(QCBORPrivateEncodeContext *); /* Use of function
+                               * pointer explained in QCBOREncode_SerializationCDE() */
    QCBORTrackNesting nesting; /* Keep track of array and map nesting */
 };
 
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 9e0cd07..d1e5d20 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -297,6 +297,54 @@
                                    int64_t            *pnValue);
 
 
+#if !defined(USEFULBUF_DISABLE_ALL_FLOAT) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
+/**
+ * @brief Decode next as a number with precision-preserving conversions.
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[out] pNumber       The returned 64-bit signed integer.
+ *
+ * This will get the next item as a number and return it as a C
+ * data type such that no precision is lost.
+ *
+ * The CBOR input can be integers (major type 0 or 1) or floats (major type 7).
+ * If not these \ref QCBOR_ERR_UNEXPECTED_TYPE will be set.
+ *
+ * The conversion is as follows.
+ *
+ * Whole numbers between \c INT64_MIN and \c INT64_MAX will
+ * be returned as \ref QCBOR_TYPE_INT64. This includes
+ * conversion of float-point values that are whole numbers.
+ *
+ * Whole numbers between \c INT64_MAX and \c UINT64_MAX will
+ * be returned as \ref QCBOR_TYPE_UINT64, again including
+ * conversion of floating-point values that are whole numbers.
+ *
+ * The whole numbers called "65-bit negative" in CBOR (-2^63 - 1 to -2^64) are a
+ * special case. Some of them can be converted to a double without
+ * loss of precision and some can't (uint64_t has 64 bits of precision; a double
+ * has only 52). If they can't be converted to a double, they are returned
+ * as \ref QCBOR_TYPE_65BIT_NEG_INT.
+ * In many cases, it will be reasonable to error out if the
+ * number type returned here is \ref QCBOR_TYPE_65BIT_NEG_INT
+ * on the assumption that many protocols will never uses these.
+ * See also QCBOREncode_AddNegativeUInt64() for more discussion.
+ *
+ * All others are returned as a double.
+ *
+ * This is useful for dCBOR which essentially combines floats
+ * and integers into one number space.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See also QCBORDecode_GetNumberConvertPreciselyBig().
+ */
+void
+QCBORDecode_GetNumberConvertPrecisely(QCBORDecodeContext *pCtx,
+                                      QCBORItem          *pNumber);
+
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
+
 /**
  * @brief Decode next item into a signed 64-bit integer with conversions.
  *
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index f90790b..91ffda1 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -1,4 +1,4 @@
-/* ==========================================================================
+/*==============================================================================
  * Copyright (c) 2016-2018, The Linux Foundation.
  * Copyright (c) 2018-2024, Laurence Lundblade.
  * All rights reserved.
@@ -45,6 +45,10 @@
  when        who          what, where, why
  --------    ----         ---------------------------------------------------
  21/05/2024  llundblade   Comment formatting and some code tidiness.
+ 28/02/2022  llundblade   Rearrange UsefulOutBuf_Compare().
+ 19/11/2023  llundblade   Add UsefulOutBuf_GetOutput().
+ 19/11/2023  llundblade   Add UsefulOutBuf_Swap().
+ 19/11/2023  llundblade   Add UsefulOutBuf_Compare().
  19/12/2022  llundblade   Don't pass NULL to memmove when adding empty data.
  4/11/2022   llundblade   Add GetOutPlace and Advance to UsefulOutBuf
  3/6/2021    mcr/llundblade  Fix warnings related to --Wcast-qual
@@ -441,3 +445,123 @@
    pMe->cursor += uAmount;
    return result;
 }
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ */
+int UsefulOutBuf_Compare(UsefulOutBuf *pMe,
+                         const size_t uStart1, const size_t uLen1,
+                         const size_t uStart2, const size_t uLen2)
+{
+   const uint8_t *pBase;
+   const uint8_t *pEnd;
+   const uint8_t *p1;
+   const uint8_t *p2;
+   const uint8_t *p1End;
+   const uint8_t *p2End;
+   int            uComparison;
+
+   pBase = pMe->UB.ptr;
+   pEnd = (const uint8_t *)pBase + pMe->data_len;
+   p1   = pBase + uStart1;
+   p2   = pBase + uStart2;
+   p1End = p1 + uLen1;
+   p2End = p2 + uLen2;
+
+   uComparison = 0;
+   while(p1 < pEnd && p2 < pEnd && p1 < p1End && p2 < p2End) {
+      uComparison = *p2 - *p1;
+      if(uComparison != 0) {
+         break;;
+      }
+      p1++;
+      p2++;
+   }
+
+   if(uComparison == 0 && p1 != p1End && p2 != p2End) {
+      if(uLen1 > uLen2) {
+         uComparison = 1;
+      } else if(uLen2 < uLen1){
+         uComparison = -1;
+      } else  {
+         return 0;
+      }
+   }
+
+   return uComparison;
+}
+
+
+
+/**
+ * @brief Reverse order of bytes in a buffer.
+ *
+ * This reverses bytes starting at pStart, up to, but not including
+ * the byte at pEnd
+ */
+static void
+UsefulOutBuf_Private_ReverseBytes(uint8_t *pStart, uint8_t *pEnd)
+{
+   uint8_t uTmp;
+
+   while(pStart < pEnd) {
+      pEnd--;
+      uTmp    = *pStart;
+      *pStart = *pEnd;
+      *pEnd   = uTmp;
+      pStart++;
+   }
+}
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ */
+void UsefulOutBuf_Swap(UsefulOutBuf *pMe, size_t uStartOffset, size_t uPivotOffset, size_t uEndOffset)
+{
+   uint8_t *pBase;
+
+   if(uStartOffset > pMe->data_len || uPivotOffset > pMe->data_len || uEndOffset > pMe->data_len) {
+      return;
+   }
+
+   if(uStartOffset > uPivotOffset || uStartOffset > uEndOffset || uPivotOffset > uEndOffset) {
+      return;
+   }
+
+   /* This is the "reverse" algorithm to swap two memory regions */
+   pBase = pMe->UB.ptr;
+   UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uPivotOffset);
+   UsefulOutBuf_Private_ReverseBytes(pBase + uPivotOffset, pBase + uEndOffset);
+   UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uEndOffset);
+}
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ */
+UsefulBufC
+UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pMe, size_t uOffset)
+{
+   UsefulBufC ReturnValue;
+
+   ReturnValue = UsefulOutBuf_OutUBuf(pMe);
+
+   if(UsefulBuf_IsNULLC(ReturnValue)) {
+      return NULLUsefulBufC;
+   }
+
+   if(uOffset >= ReturnValue.len) {
+      return NULLUsefulBufC;
+   }
+
+   ReturnValue.ptr = (const uint8_t *)ReturnValue.ptr + uOffset;
+   ReturnValue.len -= uOffset;
+
+   return ReturnValue;
+}
diff --git a/src/ieee754.c b/src/ieee754.c
index 2d98159..69bf113 100644
--- a/src/ieee754.c
+++ b/src/ieee754.c
@@ -1,5 +1,5 @@
 /* ==========================================================================
- * ieee754.c -- floating-point conversion between half, double & single-precision
+ * ieee754.c -- floating-point conversion for half, double & single-precision
  *
  * Copyright (c) 2018-2024, Laurence Lundblade. All rights reserved.
  * Copyright (c) 2021, Arm Limited. All rights reserved.
@@ -11,20 +11,14 @@
  * Created on 7/23/18
  * ========================================================================== */
 
-/*
- * Include before QCBOR_DISABLE_PREFERRED_FLOAT is checked as
- * QCBOR_DISABLE_PREFERRED_FLOAT might be defined in qcbor/qcbor_common.h
- */
 #include "qcbor/qcbor_common.h"
 
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
-
 #include "ieee754.h"
 #include <string.h> /* For memcpy() */
 
 
 /*
- * This code has long lines and is easier to read because of
+ * This has long lines and is easier to read because of
  * them. Some coding guidelines prefer 80 column lines (can they not
  * afford big displays?).
  *
@@ -164,6 +158,10 @@
    return u64;
 }
 
+
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+
+
 static inline double
 CopyUint64ToDouble(uint64_t u64)
 {
@@ -184,7 +182,7 @@
 
 
 /**
- * @brief Assemble sign, significand and exponent into single precision float.
+ * @brief Assemble sign, significand and exponent into double precision float.
  *
  * @param[in] uDoubleSign              0 if positive, 1 if negative
  * @pararm[in] uDoubleSignificand      Bits of the significand
@@ -193,6 +191,7 @@
  * This returns the bits for a single-precision float, a binary64
  * as specified in IEEE754.
  */
+// TODO: make the sign and exponent type int?
 static double
 IEEE754_AssembleDouble(uint64_t uDoubleSign,
                        uint64_t uDoubleSignificand,
@@ -208,6 +207,7 @@
 }
 
 
+/* Public function; see ieee754.h */
 double
 IEEE754_HalfToDouble(uint16_t uHalfPrecision)
 {
@@ -315,7 +315,7 @@
 
 /*  Public function; see ieee754.h */
 IEEE754_union
-IEEE754_SingleToHalf(float f)
+IEEE754_SingleToHalf(const float f, const int bNoNaNPayload)
 {
    IEEE754_union result;
    uint32_t      uDroppedBits;
@@ -357,28 +357,36 @@
          result.uSize  = IEEE754_UNION_IS_HALF;
          result.uValue = IEEE754_AssembleHalf(uSingleSign, 0, HALF_EXPONENT_INF_OR_NAN);
       } else {
-         /* The NaN can only be converted if no payload bits are lost
-          * per RFC 8949 section 4.1 that defines Preferred
-          * Serializaton. Note that Deterministically Encode CBOR in
-          * section 4.2 allows for some variation of this rule, but at
-          * the moment this implementation is of Preferred
-          * Serialization, not CDE. As of December 2023, we are also
-          * expecting an update to CDE. This code may need to be
-          * updated for CDE.
-          */
-         uDroppedBits = uSingleSignificand & (SINGLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS);
-         if(uDroppedBits == 0) {
-            /* --- IS CONVERTABLE NAN --- */
-            uHalfSignificand = uSingleSignificand >> (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
+         if(bNoNaNPayload) {
+            /* --- REQUIRE CANNONICAL NAN --- */
             result.uSize  = IEEE754_UNION_IS_HALF;
             result.uValue = IEEE754_AssembleHalf(uSingleSign,
-                                                 uHalfSignificand,
+                                                 HALF_QUIET_NAN_BIT,
                                                  HALF_EXPONENT_INF_OR_NAN);
-
          } else {
-            /* --- IS UNCONVERTABLE NAN --- */
-            result.uSize   = IEEE754_UNION_IS_SINGLE;
-            result.uValue  = uSingle;
+            /* The NaN can only be converted if no payload bits are lost
+             * per RFC 8949 section 4.1 that defines Preferred
+             * Serializaton. Note that Deterministically Encode CBOR in
+             * section 4.2 allows for some variation of this rule, but at
+             * the moment this implementation is of Preferred
+             * Serialization, not CDE. As of December 2023, we are also
+             * expecting an update to CDE. This code may need to be
+             * updated for CDE.
+             */
+            uDroppedBits = uSingleSignificand & (SINGLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS);
+            if(uDroppedBits == 0) {
+               /* --- IS CONVERTABLE NAN --- */
+               uHalfSignificand = uSingleSignificand >> (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
+               result.uSize  = IEEE754_UNION_IS_HALF;
+               result.uValue = IEEE754_AssembleHalf(uSingleSign,
+                                                    uHalfSignificand,
+                                                    HALF_EXPONENT_INF_OR_NAN);
+
+            } else {
+               /* --- IS UNCONVERTABLE NAN --- */
+               result.uSize   = IEEE754_UNION_IS_SINGLE;
+               result.uValue  = uSingle;
+            }
          }
       }
    } else {
@@ -495,7 +503,7 @@
  * This handles all subnormals and NaN payloads.
  */
 static IEEE754_union
-IEEE754_DoubleToSingle(double d)
+IEEE754_DoubleToSingle(const double d)
 {
    IEEE754_union Result;
    int64_t       nExponentDifference;
@@ -514,7 +522,6 @@
    const uint64_t uDoubleSign             = (uDouble & DOUBLE_SIGN_MASK) >> DOUBLE_SIGN_SHIFT;
    const uint64_t uDoubleSignificand      = uDouble & DOUBLE_SIGNIFICAND_MASK;
 
-
     if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_ZERO) {
         if(uDoubleSignificand == 0) {
             /* --- IS ZERO --- */
@@ -619,7 +626,9 @@
 
 /* Public function; see ieee754.h */
 IEEE754_union
-IEEE754_DoubleToSmaller(double d, int bAllowHalfPrecision)
+IEEE754_DoubleToSmaller(const double d,
+                        const int    bAllowHalfPrecision,
+                        const int    bNoNanPayload)
 {
    IEEE754_union result;
 
@@ -629,15 +638,276 @@
       /* Cast to uint32_t is OK, because value was just successfully
        * converted to single. */
       float uSingle = CopyUint32ToSingle((uint32_t)result.uValue);
-      result = IEEE754_SingleToHalf(uSingle);
+      result = IEEE754_SingleToHalf(uSingle, bNoNanPayload);
    }
 
    return result;
 }
 
 
-#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
 
-int ieee754_dummy_place_holder;
+/* This returns 64 minus the number of zero bits on the right. It is
+ * is the amount of precision in the 64-bit significand passed in.
+ * When used for 52 and 23-bit significands, subtract 12 and 41
+ * to get their precision.
+ *
+ * The value returned is for a *normalized* number like the
+ * significand of a double. When used for precision for a non-normalized
+ * number like a uint64_t, further computation is required.
+ *
+ * If the significand is 0, then 0 is returned as the precision.*/
+static int
+IEEE754_Private_CountPrecisionBits(uint64_t uSignigicand)
+{
+   int      nNonZeroBitsCount;
+   uint64_t uMask;
+
+   for(nNonZeroBitsCount = 64; nNonZeroBitsCount > 0; nNonZeroBitsCount--) {
+      uMask = 0x01UL << (64 - nNonZeroBitsCount);
+      if(uMask & uSignigicand) {
+         break;
+      }
+   }
+
+   return nNonZeroBitsCount;
+}
+
+
+
+/* Public function; see ieee754.h */
+struct IEEE754_ToInt
+IEEE754_DoubleToInt(const double d)
+{
+   int64_t              nPrecisionBits;
+   struct IEEE754_ToInt Result;
+   uint64_t             uInteger;
+
+   /* Pull the three parts out of the double-precision float. Most
+    * work is done with uint64_t which helps avoid integer promotions
+    * and static analyzer complaints.
+    */
+   const uint64_t uDouble                 = CopyDoubleToUint64(d);
+   const uint64_t uDoubleBiasedExponent   = (uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT;
+   /* Cast safe because of mask above; exponents < DOUBLE_EXPONENT_MAX */
+   const int64_t  nDoubleUnbiasedExponent = (int64_t)uDoubleBiasedExponent - DOUBLE_EXPONENT_BIAS;
+   const uint64_t uDoubleSignificand      = uDouble & DOUBLE_SIGNIFICAND_MASK;
+
+   if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_ZERO) {
+      if(uDoubleSignificand == 0) {
+         /* --- POSITIVE AND NEGATIVE ZERO --- */
+         Result.integer.un_signed = 0;
+         Result.type              = IEEE754_ToInt_IS_UINT;
+      } else {
+         /* --- SUBNORMAL --- */
+         Result.type = IEEE754_ToInt_NO_CONVERSION;
+      }
+   } else if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_INF_OR_NAN) {
+      if(uDoubleSignificand != 0) {
+         /* --- NAN --- */
+         Result.type = IEEE754_ToInt_NaN; /* dCBOR doesn't care about payload */
+      } else  {
+         /* --- INIFINITY --- */
+         Result.type = IEEE754_ToInt_NO_CONVERSION;
+      }
+   } else if(nDoubleUnbiasedExponent < 0 ||
+             (nDoubleUnbiasedExponent >= ((uDouble & DOUBLE_SIGN_MASK) ? 63 : 64))) {
+      /* --- Exponent out of range --- */
+      Result.type = IEEE754_ToInt_NO_CONVERSION;
+   } else {
+      /* Conversion only fails when the input is too large or is not a
+       * whole number, never because of lack of precision because
+       * 64-bit integers always have more precision than the 52-bits
+       * of a double.
+       */
+      nPrecisionBits = IEEE754_Private_CountPrecisionBits(uDoubleSignificand) -
+                               (64-DOUBLE_NUM_SIGNIFICAND_BITS);
+
+      if(nPrecisionBits && nPrecisionBits > nDoubleUnbiasedExponent) {
+         /* --- Not a whole number --- */
+         Result.type = IEEE754_ToInt_NO_CONVERSION;
+      } else {
+         /* --- CONVERTABLE WHOLE NUMBER --- */
+         /* Add in the one that is implied in normal floats */
+         uInteger = uDoubleSignificand + (1ULL << DOUBLE_NUM_SIGNIFICAND_BITS);
+         /* Factor in the exponent */
+         if(nDoubleUnbiasedExponent < DOUBLE_NUM_SIGNIFICAND_BITS) {
+            /* Numbers less than 2^52 with up to 52 significant bits */
+            uInteger >>= DOUBLE_NUM_SIGNIFICAND_BITS - nDoubleUnbiasedExponent;
+         } else {
+            /* Numbers greater than 2^52 with at most 52 significant bits */
+            uInteger <<= nDoubleUnbiasedExponent - DOUBLE_NUM_SIGNIFICAND_BITS;
+         }
+         if(uDouble & DOUBLE_SIGN_MASK) {
+            /* Cast safe because exponent range check above */
+            Result.integer.is_signed = -((int64_t)uInteger);
+            Result.type              = IEEE754_ToInt_IS_INT;
+         } else {
+            Result.integer.un_signed = uInteger;
+            Result.type              = IEEE754_ToInt_IS_UINT;
+         }
+      }
+   }
+
+   return Result;
+}
+
+
+/* Public function; see ieee754.h */
+struct IEEE754_ToInt
+IEEE754_SingleToInt(const float f)
+{
+   int32_t              nPrecisionBits;
+   struct IEEE754_ToInt Result;
+   uint64_t             uInteger;
+
+   /* Pull the three parts out of the single-precision float. Most
+    * work is done with uint32_t which helps avoid integer promotions
+    * and static analyzer complaints.
+    */
+   const uint32_t uSingle                 = CopyFloatToUint32(f);
+   const uint32_t uSingleBiasedExponent   = (uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT;
+   /* Cast safe because of mask above; exponents < SINGLE_EXPONENT_MAX */
+   const int32_t  nSingleUnbiasedExponent = (int32_t)uSingleBiasedExponent - SINGLE_EXPONENT_BIAS;
+   const uint32_t uSingleleSignificand    = uSingle & SINGLE_SIGNIFICAND_MASK;
+
+   if(nSingleUnbiasedExponent == SINGLE_EXPONENT_ZERO) {
+      if(uSingleleSignificand == 0 && !(uSingle & SINGLE_SIGN_MASK)) {
+         /* --- POSITIVE AND NEGATIVE ZERO --- */
+         Result.integer.un_signed = 0;
+         Result.type              = IEEE754_ToInt_IS_UINT;
+      } else {
+         /* --- Subnormal --- */
+         Result.type = IEEE754_ToInt_NO_CONVERSION;
+      }
+   } else if(nSingleUnbiasedExponent == SINGLE_EXPONENT_INF_OR_NAN) {
+      /* --- NAN or INFINITY --- */
+      if(uSingleleSignificand != 0) {
+         Result.type = IEEE754_ToInt_NaN; /* dCBOR doesn't care about payload */
+      } else  {
+         Result.type = IEEE754_ToInt_NO_CONVERSION;
+      }
+   } else if(nSingleUnbiasedExponent < 0 ||
+             (nSingleUnbiasedExponent >= ((uSingle & SINGLE_SIGN_MASK) ? 63 : 64))) {
+      /* --- Exponent out of range --- */
+       Result.type = IEEE754_ToInt_NO_CONVERSION;
+    } else {
+      /* Conversion only fails when the input is too large or is not a
+       * whole number, never because of lack of precision because
+       * 64-bit integers always have more precision than the 23 bits
+       * of a single.
+       */
+       nPrecisionBits = IEEE754_Private_CountPrecisionBits(uSingleleSignificand) -
+                           (64 - SINGLE_NUM_SIGNIFICAND_BITS);
+
+      if(nPrecisionBits && nPrecisionBits > nSingleUnbiasedExponent) {
+         /* --- Not a whole number --- */
+         Result.type = IEEE754_ToInt_NO_CONVERSION;
+      } else {
+         /* --- CONVERTABLE WHOLE NUMBER --- */
+         /* Add in the one that is implied in normal floats */
+         uInteger = uSingleleSignificand + (1ULL << SINGLE_NUM_SIGNIFICAND_BITS);
+         /* Factor in the exponent */
+         if(nSingleUnbiasedExponent < SINGLE_NUM_SIGNIFICAND_BITS) {
+            /* Numbers less than 2^23 with up to 23 significant bits */
+            uInteger >>= SINGLE_NUM_SIGNIFICAND_BITS - nSingleUnbiasedExponent;
+         } else {
+            /* Numbers greater than 2^23 with at most 23 significant bits*/
+            uInteger <<= nSingleUnbiasedExponent - SINGLE_NUM_SIGNIFICAND_BITS;
+         }
+         if(uSingle & SINGLE_SIGN_MASK) {
+            Result.integer.is_signed = -((int64_t)uInteger);
+            Result.type              = IEEE754_ToInt_IS_INT;
+         } else {
+            Result.integer.un_signed = uInteger;
+            Result.type              = IEEE754_ToInt_IS_UINT;
+         }
+      }
+   }
+
+   return Result;
+}
+
+
+
+/* Public function; see ieee754.h */
+double
+IEEE754_UintToDouble(const uint64_t uInt, const int uIsNegative)
+{
+   int      nDoubleUnbiasedExponent;
+   uint64_t uDoubleSignificand;
+   int      nPrecisionBits;
+
+   /* Figure out the exponent and normalize the significand. This is
+    * done by shifting out all leading zero bits and counting them. If
+    * none are shifted out, the exponent is 63. */
+   uDoubleSignificand = uInt;
+   nDoubleUnbiasedExponent = 63;
+   while(1) {
+      if(uDoubleSignificand & 0x8000000000000000UL) {
+         break;
+      }
+      uDoubleSignificand <<= 1;
+      nDoubleUnbiasedExponent--;
+   };
+
+   /* Position significand correctly for a double. Only shift 63 bits
+    * because of the 1 that is present by implication in IEEE 754.*/
+   uDoubleSignificand >>= 63 - DOUBLE_NUM_SIGNIFICAND_BITS;
+
+   /* Subtract 1 which is present by implication in IEEE 754 */
+   uDoubleSignificand -= 1ULL << (DOUBLE_NUM_SIGNIFICAND_BITS);
+
+   nPrecisionBits = IEEE754_Private_CountPrecisionBits(uInt) - (64 - nDoubleUnbiasedExponent);
+
+   if(nPrecisionBits > DOUBLE_NUM_SIGNIFICAND_BITS) {
+      /* Will lose precision if converted */
+      return IEEE754_UINT_TO_DOUBLE_OOB;
+   }
+
+   return IEEE754_AssembleDouble((uint64_t)uIsNegative,
+                                 uDoubleSignificand,
+                                 nDoubleUnbiasedExponent);
+}
 
 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+
+
+
+/* Public function; see ieee754.h */
+int
+IEEE754_IsNotStandardDoubleNaN(const double d)
+{
+   const uint64_t uDouble                 = CopyDoubleToUint64(d);
+   const uint64_t uDoubleBiasedExponent   = (uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT;
+   /* Cast safe because of mask above; exponents < DOUBLE_EXPONENT_MAX */
+   const int64_t  nDoubleUnbiasedExponent = (int64_t)uDoubleBiasedExponent - DOUBLE_EXPONENT_BIAS;
+   const uint64_t uDoubleSignificand      = uDouble & DOUBLE_SIGNIFICAND_MASK;
+
+   if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_INF_OR_NAN &&
+      uDoubleSignificand != 0 &&
+      uDoubleSignificand != DOUBLE_QUIET_NAN_BIT) {
+      return 1;
+   } else {
+      return 0;
+   }
+}
+
+
+/* Public function; see ieee754.h */
+int
+IEEE754_IsNotStandardSingleNaN(const float f)
+{
+   const uint32_t uSingle                 = CopyFloatToUint32(f);
+   const uint32_t uSingleBiasedExponent   = (uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT;
+   /* Cast safe because of mask above; exponents < SINGLE_EXPONENT_MAX */
+   const int32_t  nSingleUnbiasedExponent = (int32_t)uSingleBiasedExponent - SINGLE_EXPONENT_BIAS;
+   const uint32_t uSingleleSignificand    = uSingle & SINGLE_SIGNIFICAND_MASK;
+
+   if(nSingleUnbiasedExponent == SINGLE_EXPONENT_INF_OR_NAN &&
+      uSingleleSignificand != 0 &&
+      uSingleleSignificand != SINGLE_QUIET_NAN_BIT) {
+      return 1;
+   } else {
+      return 0;
+   }
+}
diff --git a/src/ieee754.h b/src/ieee754.h
index 863019b..c893e6f 100644
--- a/src/ieee754.h
+++ b/src/ieee754.h
@@ -10,11 +10,11 @@
  * Created on 7/23/18
  * ========================================================================== */
 
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
 
 #ifndef ieee754_h
 #define ieee754_h
 
+
 #include <stdint.h>
 
 
@@ -25,6 +25,9 @@
  * smaller representation (e.g., double to single) that does not lose
  * precision for CBOR preferred serialization.
  *
+ * This also implements conversion of floats to whole numbers as
+ * is required for dCBOR.
+ *
  * This implementation works entirely with shifts and masks and does
  * not require any floating-point HW or library.
  *
@@ -51,6 +54,7 @@
  * conversion. This version is reduced to what is needed for CBOR.
  */
 
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
 
 /**
  * @brief Convert half-precision float to double-precision float.
@@ -87,6 +91,22 @@
 } IEEE754_union;
 
 
+/** Holds result of an attempt to convert a floating-point
+ * number to an int64_t or uint64_t.
+ */
+struct IEEE754_ToInt {
+   enum {IEEE754_ToInt_IS_INT,
+         IEEE754_ToInt_IS_UINT,
+         IEEE754_ToInt_NO_CONVERSION,
+         IEEE754_ToInt_NaN
+   } type;
+   union {
+      uint64_t un_signed;
+      int64_t  is_signed;
+   } integer;
+};
+
+
 /**
  * @brief Convert a double to either single or half-precision.
  *
@@ -102,7 +122,7 @@
  * This handles all subnormals and NaN payloads.
  */
 IEEE754_union
-IEEE754_DoubleToSmaller(double d, int bAllowHalfPrecision);
+IEEE754_DoubleToSmaller(double d, int bAllowHalfPrecision, int bNoNaNPayload);
 
 
 /**
@@ -118,9 +138,108 @@
  * This handles all subnormals and NaN payloads.
  */
 IEEE754_union
-IEEE754_SingleToHalf(float f);
+IEEE754_SingleToHalf(float f, int bNoNanPayloads);
+
+
+/**
+ * @brief Convert a double-precision float to integer if whole number
+ *
+ * @param[in] d  The value to convert.
+ *
+ * @returns Either converted number or conversion status.
+ *
+ * If the value is a whole number that will fit either in a uint64_t
+ * or an int64_t, it is converted. If it is a NaN, then there is no
+ * conversion and and the fact that it is a NaN is indicated in the
+ * returned structure.  If it can't be converted, then that is
+ * indicated in the returned structure.
+ *
+ * This always returns postive numbers as a uint64_t even if they will
+ * fit in an int64_t.
+ *
+ * This never fails becaue of precision, but may fail because of range.
+ */
+struct IEEE754_ToInt
+IEEE754_DoubleToInt(double d);
+
+
+/**
+ * @brief Convert a single-precision float to integer if whole number
+ *
+ * @param[in] f  The value to convert.
+ *
+ * @returns Either converted number or conversion status.
+ *
+ * If the value is a whole number that will fit either in a uint64_t
+ * or an int64_t, it is converted. If it is a NaN, then there is no
+ * conversion and and the fact that it is a NaN is indicated in the
+ * returned structure.  If it can't be converted, then that is
+ * indicated in the returned structure.
+ *
+ * This always returns postive numbers as a uint64_t even if they will
+ * fit in an int64_t.
+ *
+ * This never fails becaue of precision, but may fail because of range.
+ */
+struct IEEE754_ToInt
+IEEE754_SingleToInt(float f);
+
+
+/**
+ * @brief Convert an unsigned integer to a double with no precision loss.
+ *
+ * @param[in] uInt  The value to convert.
+ * @param[in] uIsNegative   0 if postive, 1 if negative.
+ *
+ * @returns Either the converted number or 0.5 if no conversion.
+ *
+ * The conversion will fail if the input can not be represented in the
+ * 52 bits or precision that a double has. 0.5 is returned to indicate
+ * no conversion. It is out-of-band from non-error results, because
+ * all non-error results are whole integers.
+ */
+#define IEEE754_UINT_TO_DOUBLE_OOB 0.5
+double
+IEEE754_UintToDouble(uint64_t uInt, int uIsNegative);
+
+
+#endif /* ! QCBOR_DISABLE_PREFERRED_FLOAT */
+
+
+/**
+ * @brief Tests whether NaN is "quiet" vs having a payload.
+ *
+ * @param[in] dNum   Double number to test.
+ *
+ * @returns 0 if a quiet NaN, 1 if it has a payload.
+ *
+ * A quiet NaN is usually represented as 0x7ff8000000000000. That is
+ * the significand bits are 0x8000000000000. If the significand bits
+ * are other than 0x8000000000000 it is considered to have a NaN
+ * payload.
+ *
+ * Note that 0x7ff8000000000000 is not specified in a standard, but it
+ * is commonly implemented and chosen by CBOR as the best way to
+ * represent a NaN.
+ */
+int
+IEEE754_IsNotStandardDoubleNaN(double dNum);
+
+
+
+/**
+ * @brief Tests whether NaN is "quiet" vs having a payload.
+ *
+ * @param[in] fNum   Float number to test.
+ *
+ * @returns 0 if a quiet NaN, 1 if it has a payload.
+ *
+ * See IEEE754_IsNotStandardDoubleNaN(). A single precision quiet NaN
+ * is 0x7fc00000.
+ */
+int
+IEEE754_IsNotStandardSingleNaN(float fNum);
 
 
 #endif /* ieee754_h */
 
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 3ed4d0f..13a728d 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -904,10 +904,8 @@
          pDecodedItem->uDataType = QCBOR_TYPE_INT64;
 
       } else {
-         /* C can't represent a negative integer in this range so it
-          * is an error.
-          */
-         uReturn = QCBOR_ERR_INT_OVERFLOW;
+         pDecodedItem->val.uint64 = uArgument;
+         pDecodedItem->uDataType  = QCBOR_TYPE_65BIT_NEG_INT;
       }
    }
 
@@ -5555,6 +5553,12 @@
          }
          break;
 
+      case QCBOR_TYPE_65BIT_NEG_INT:
+         /* This type occurs if the value won't fit into int64_t
+          * so this is always an error. */
+         return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+         break;
+
       default:
          return  QCBOR_ERR_UNEXPECTED_TYPE;
    }
@@ -5963,12 +5967,15 @@
 
       case QCBOR_TYPE_UINT64:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
-            *puValue =  pItem->val.uint64;
+            *puValue = pItem->val.uint64;
          } else {
             return QCBOR_ERR_UNEXPECTED_TYPE;
          }
          break;
 
+      case QCBOR_TYPE_65BIT_NEG_INT:
+         return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+
       default:
          return QCBOR_ERR_UNEXPECTED_TYPE;
    }
@@ -6363,6 +6370,14 @@
          return QCBOR_ERR_HW_FLOAT_DISABLED;
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
 
+      case QCBOR_TYPE_65BIT_NEG_INT:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         *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;
    }
@@ -7433,3 +7448,92 @@
 }
 
 #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
+ */
+void
+QCBORDecode_GetNumberConvertPrecisely(QCBORDecodeContext *pMe,
+                                      QCBORItem          *pNumber)
+{
+   QCBORItem            Item;
+   struct IEEE754_ToInt ToInt;
+   double               d;
+   QCBORError           uError;
+
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   uError = QCBORDecode_GetNext(pMe, &Item);
+   if(uError != QCBOR_SUCCESS) {
+      pMe->uLastError = (uint8_t)uError;
+      return;
+   }
+
+   switch(Item.uDataType) {
+      case QCBOR_TYPE_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 {
+               pNumber->uDataType = QCBOR_TYPE_UINT64;
+               pNumber->val.uint64 = ToInt.integer.un_signed;
+            }
+         } else {
+            *pNumber = Item;
+         }
+         break;
+
+      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 {
+            *pNumber = Item;
+         }
+         break;
+
+
+      case QCBOR_TYPE_65BIT_NEG_INT:
+         d = IEEE754_UintToDouble(Item.val.uint64, 1);
+         if(d == IEEE754_UINT_TO_DOUBLE_OOB) {
+            *pNumber = Item;
+         } else {
+            pNumber->uDataType = QCBOR_TYPE_DOUBLE;
+            /* -1 is because of CBOR offset of negative numbers */
+            pNumber->val.dfnum = d - 1;
+         }
+         break;
+
+      default:
+         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+         pNumber->uDataType = QCBOR_TYPE_NONE;
+         break;
+   }
+}
+
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 2a99110..d196149 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -35,6 +35,10 @@
 #include "qcbor/qcbor_encode.h"
 #include "ieee754.h"
 
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+#include <math.h> /* Only for NAN definition */
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
 
 /**
  * @file qcbor_encode.c
@@ -248,6 +252,11 @@
  */
 
 
+/* Forward declaration for reference in QCBOREncode_Init() */
+static void
+QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe);
+
+
 /*
  * Public function for initialization. See qcbor/qcbor_encode.h
  */
@@ -257,6 +266,7 @@
    memset(pMe, 0, sizeof(QCBOREncodeContext));
    UsefulOutBuf_Init(&(pMe->OutBuf), Storage);
    Nesting_Init(&(pMe->nesting));
+   pMe->pfnCloseMap = QCBOREncode_Private_CloseMapUnsorted;
 }
 
 
@@ -529,7 +539,7 @@
  * @param pMe         Encoder context.
  * @param uMajorType  Major type to insert.
  * @param uArgument   The argument (an integer value or a length).
- * @param uMinLen     The minimum number of bytes for encoding the CBOR argument.
+ * @param uMinLen     Minimum number of bytes for encoding the CBOR argument.
  *
  * This formats the CBOR "head" and appends it to the output.
  *
@@ -570,6 +580,29 @@
 
 
 /*
+ * Public functions for adding negative integers. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_AddNegativeUInt64(QCBOREncodeContext *pMe, const uint64_t uValue)
+{
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(pMe->uMode >= QCBOR_ENCODE_MODE_DCBOR) {
+      /* Never allowed in dCBOR */
+      pMe->uError = QCBOR_ERR_NOT_PREFERRED;
+      return;
+   }
+
+   if(!(pMe->uAllow & QCBOR_ENCODE_ALLOW_65_BIG_NEG)) {
+      pMe->uError = QCBOR_ERR_NOT_ALLOWED;
+      return;
+   }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_NEGATIVE_INT, uValue, 0);
+}
+
+
+/*
  * Public functions for adding signed integers. See qcbor/qcbor_encode.h
  */
 void
@@ -581,9 +614,9 @@
    if(nNum < 0) {
       /* In CBOR -1 encodes as 0x00 with major type negative int.
        * First add one as a signed integer because that will not
-       * overflow. Then change the sign as needed for encoding.  (The
+       * overflow. Then change the sign as needed for encoding (the
        * opposite order, changing the sign and subtracting, can cause
-       * an overflow when encoding INT64_MIN. */
+       * an overflow when encoding INT64_MIN). */
       int64_t nTmp = nNum + 1;
       uValue = (uint64_t)-nTmp;
       uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
@@ -641,10 +674,42 @@
  * without a loss of precision. See QCBOREncode_AddDouble().
  */
 void
-QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, const double dNum)
+QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, double dNum)
 {
-   const IEEE754_union uNum = IEEE754_DoubleToSmaller(dNum, true);
-   QCBOREncode_Private_AddType7(pMe, (uint8_t)uNum.uSize, uNum.uValue);
+   IEEE754_union        FloatResult;
+   bool                 bNoNaNPayload;
+   struct IEEE754_ToInt IntResult;
+
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(IEEE754_IsNotStandardDoubleNaN(dNum) && !(pMe->uAllow & QCBOR_ENCODE_ALLOW_NAN_PAYLOAD)) {
+      pMe->uError = QCBOR_ERR_NOT_ALLOWED;
+      return;
+   }
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
+      IntResult = IEEE754_DoubleToInt(dNum);
+      switch(IntResult.type) {
+         case IEEE754_ToInt_IS_INT:
+            QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
+            return;
+         case IEEE754_ToInt_IS_UINT:
+            QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
+            return;
+         case IEEE754_ToInt_NaN:
+            dNum = NAN;
+            bNoNaNPayload = true;
+            break;
+         case IEEE754_ToInt_NO_CONVERSION:
+            bNoNaNPayload = true;
+      }
+   } else  {
+      bNoNaNPayload = false;
+   }
+
+   FloatResult = IEEE754_DoubleToSmaller(dNum, true, bNoNaNPayload);
+
+   QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
 }
 
 
@@ -658,14 +723,47 @@
  * without a loss of precision. See QCBOREncode_AddFloat().
  */
 void
-QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, const float fNum)
+QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, float fNum)
 {
-   const IEEE754_union uNum = IEEE754_SingleToHalf(fNum);
-   QCBOREncode_Private_AddType7(pMe, (uint8_t)uNum.uSize, uNum.uValue);
+   IEEE754_union        FloatResult;
+   bool                 bNoNaNPayload;
+   struct IEEE754_ToInt IntResult;
+
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(IEEE754_IsNotStandardSingleNaN(fNum) && !(pMe->uAllow & QCBOR_ENCODE_ALLOW_NAN_PAYLOAD)) {
+      pMe->uError = QCBOR_ERR_NOT_ALLOWED;
+      return;
+   }
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
+      IntResult = IEEE754_SingleToInt(fNum);
+      switch(IntResult.type) {
+         case IEEE754_ToInt_IS_INT:
+            QCBOREncode_AddInt64(pMe, IntResult.integer.is_signed);
+            return;
+         case IEEE754_ToInt_IS_UINT:
+            QCBOREncode_AddUInt64(pMe, IntResult.integer.un_signed);
+            return;
+         case IEEE754_ToInt_NaN:
+            fNum = NAN;
+            bNoNaNPayload = true;
+            break;
+         case IEEE754_ToInt_NO_CONVERSION:
+            bNoNaNPayload = true;
+      }
+   } else  {
+      bNoNaNPayload = false;
+   }
+
+   FloatResult = IEEE754_SingleToHalf(fNum, bNoNaNPayload);
+
+   QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
 }
 #endif /* !QCBOR_DISABLE_PREFERRED_FLOAT */
 
 
+
 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /**
  * @brief  Semi-private method to add bigfloats and decimal fractions.
@@ -788,6 +886,12 @@
 QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
                                                    const uint8_t       uMajorType)
 {
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
+      pMe->uError = QCBOR_ERR_NOT_PREFERRED;
+      return;
+   }
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
    /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
    QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, 0, 0);
 
@@ -895,12 +999,10 @@
 
 
 /**
- * @brief Semi-private method to close a map, array or bstr wrapped CBOR
+ * @brief Semi-private method to close a map, array or bstr wrapped CBOR.
  *
  * @param[in] pMe           The context to add to.
  * @param[in] uMajorType     The major CBOR type to close.
- *
- * Call QCBOREncode_CloseArray() or QCBOREncode_CloseMap() instead of this.
  */
 void
 QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pMe,
@@ -910,6 +1012,339 @@
 }
 
 
+/**
+ * @brief Private method to close a map without sorting.
+ *
+ * @param[in] pMe     The encode context with map to close.
+ *
+ * See QCBOREncode_SerializationCDE() implemention for explantion for why
+ * this exists in this form.
+ */
+static void
+QCBOREncode_Private_CloseMapUnsorted(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
+}
+
+
+/**
+ * @brief Decode a CBOR item head.
+ *
+ * @param[in]   pUInBuf           UsefulInputBuf to read from.
+ * @param[out]  pnMajorType       Major type of decoded head.
+ * @param[out]  puArgument        Argument of decoded head.
+ * @param[out]  pnAdditionalInfo  Additional info from decoded head.
+ *
+ * @return SUCCESS if a head was decoded
+ *         HIT_END if there were not enough bytes to decode a head
+ *         UNSUPPORTED if the decoded item is not one that is supported
+ *
+ * This is copied from qcbor_decode.c rather than referenced.  This
+ * makes the core decoder 60 bytes smaller because it gets inlined.
+ * It would not get inlined if it was referenced. It is important to
+ * make the core decoder as small as possible. The copy here does make
+ * map sorting 200 bytes bigger, but map sorting is rarely used in
+ * environments that need small object code. It would also make
+ * qcbor_encode.c depend on qcbor_decode.c
+ *
+ * This is also super stable and tested. It implements the very
+ * well-defined part of CBOR that will never change.  So this won't
+ * change.
+ */
+static QCBORError
+QCBOREncodePriv_DecodeHead(UsefulInputBuf *pUInBuf,
+                           int            *pnMajorType,
+                           uint64_t       *puArgument,
+                           int            *pnAdditionalInfo)
+{
+   QCBORError uReturn;
+
+   /* Get the initial byte that every CBOR data item has and break it
+    * down. */
+   const int nInitialByte    = (int)UsefulInputBuf_GetByte(pUInBuf);
+   const int nTmpMajorType   = nInitialByte >> 5;
+   const int nAdditionalInfo = nInitialByte & 0x1f;
+
+   /* Where the argument accumulates */
+   uint64_t uArgument;
+
+   if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
+      /* Need to get 1,2,4 or 8 additional argument bytes. Map
+       * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
+       */
+      static const uint8_t aIterate[] = {1,2,4,8};
+
+      /* Loop getting all the bytes in the argument */
+      uArgument = 0;
+      for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
+         /* This shift and add gives the endian conversion. */
+         uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
+      }
+   } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
+      /* The reserved and thus-far unused additional info values */
+      uReturn = QCBOR_ERR_UNSUPPORTED;
+      goto Done;
+   } else {
+      /* Less than 24, additional info is argument or 31, an
+       * indefinite-length.  No more bytes to get.
+       */
+      uArgument = (uint64_t)nAdditionalInfo;
+   }
+
+   if(UsefulInputBuf_GetError(pUInBuf)) {
+      uReturn = QCBOR_ERR_HIT_END;
+      goto Done;
+   }
+
+   /* All successful if arrived here. */
+   uReturn           = QCBOR_SUCCESS;
+   *pnMajorType      = nTmpMajorType;
+   *puArgument       = uArgument;
+   *pnAdditionalInfo = nAdditionalInfo;
+
+Done:
+   return uReturn;
+}
+
+
+/**
+ * @brief Consume the next item from a UsefulInputBuf.
+ *
+ * @param[in] pInBuf  UsefulInputBuf from which to consume item.
+ *
+ * Recursive, but stack usage is light and encoding depth limit
+ */
+static QCBORError
+QCBOR_Private_ConsumeNext(UsefulInputBuf *pInBuf)
+{
+   int      nMajor;
+   uint64_t uArgument;
+   int      nAdditional;
+   uint16_t uItemCount;
+   uint16_t uMul;
+   uint16_t i;
+   QCBORError uCBORError;
+
+   uCBORError = QCBOREncodePriv_DecodeHead(pInBuf, &nMajor, &uArgument, &nAdditional);
+   if(uCBORError != QCBOR_SUCCESS) {
+      return uCBORError;
+   }
+
+   uMul = 1;
+
+   switch(nMajor) {
+      case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
+      case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
+         break;
+
+      case CBOR_MAJOR_TYPE_SIMPLE:
+         return uArgument == CBOR_SIMPLE_BREAK ? 1 : 0;
+         break;
+
+      case CBOR_MAJOR_TYPE_BYTE_STRING:
+      case CBOR_MAJOR_TYPE_TEXT_STRING:
+         if(nAdditional == LEN_IS_INDEFINITE) {
+            /* Segments of indefinite length */
+            while(QCBOR_Private_ConsumeNext(pInBuf) == 0);
+         }
+         (void)UsefulInputBuf_GetBytes(pInBuf, uArgument);
+         break;
+
+      case CBOR_MAJOR_TYPE_TAG:
+         QCBOR_Private_ConsumeNext(pInBuf);
+         break;
+
+      case CBOR_MAJOR_TYPE_MAP:
+         uMul = 2;
+         /* Fallthrough */
+      case CBOR_MAJOR_TYPE_ARRAY:
+         uItemCount = (uint16_t)uArgument * uMul;
+         if(nAdditional == LEN_IS_INDEFINITE) {
+            uItemCount = UINT16_MAX;
+         }
+         for(i = uItemCount; i > 0; i--) {
+            if(QCBOR_Private_ConsumeNext(pInBuf)) {
+               /* End of indefinite length */
+               break;
+            }
+         }
+         break;
+   }
+
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief  Decoded next item to get its lengths.
+ *
+ * Decode the next item in map no matter what type it is. It works
+ * recursively when an item is a map or array It returns offset just
+ * past the item decoded or zero there are no more items in the output
+ * buffer.
+ *
+ * This doesn't distinguish between end of the input and an error
+ * because it is used to decode stuff we encoded into a buffer, not
+ * stuff that came in from outside. We still want a check for safety
+ * in case of bugs here, but it is OK to report end of input on error.
+ */
+struct ItemLens {
+   uint32_t  uLabelLen;
+   uint32_t  uItemLen;
+};
+
+static struct ItemLens
+QCBOREncode_Private_DecodeNextInMap(QCBOREncodeContext *pMe, uint32_t uStart)
+{
+   UsefulInputBuf  InBuf;
+   UsefulBufC      EncodedMapBytes;
+   QCBORError      uCBORError;
+   struct ItemLens Result;
+
+   Result.uLabelLen = 0;
+   Result.uItemLen  = 0;
+
+   EncodedMapBytes = UsefulOutBuf_OutUBufOffset(&(pMe->OutBuf), uStart);
+   if(UsefulBuf_IsNULLC(EncodedMapBytes)) {
+      return Result;
+   }
+
+   UsefulInputBuf_Init(&InBuf, EncodedMapBytes);
+
+   /* This is always used on maps, so consume two, the label and the value */
+   uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
+   if(uCBORError) {
+      return Result;
+   }
+
+   /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
+   Result.uLabelLen = (uint32_t)UsefulInputBuf_Tell(&InBuf);
+
+   uCBORError = QCBOR_Private_ConsumeNext(&InBuf);
+   if(uCBORError) {
+      Result.uLabelLen = 0;
+      return Result;
+   }
+
+   Result.uItemLen = (uint32_t)UsefulInputBuf_Tell(&InBuf);
+
+   /* Cast is safe because this is QCBOR which limits sizes to UINT32_MAX */
+   return Result;
+}
+
+
+/**
+ * @brief Sort items lexographically by encoded labels.
+ *
+ * @param[in] pMe     Encoding context.
+ * @param[in] uStart  Offset in outbuf of first item for sorting.
+ *
+ * This reaches into the UsefulOutBuf in the encoding context and
+ * sorts encoded CBOR items. The byte offset start of the items is at
+ * @c uStart and it goes to the end of valid bytes in the
+ * UsefulOutBuf.
+ */
+static void
+QCBOREncode_Private_SortMap(QCBOREncodeContext *pMe, uint32_t uStart)
+{
+   bool            bSwapped;
+   int             nComparison;
+   uint32_t        uStart1;
+   uint32_t        uStart2;
+   struct ItemLens Lens1;
+   struct ItemLens Lens2;
+
+
+   if(pMe->uError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   /* Bubble sort because the sizes of all the items are not the
+    * same. It works with adjacent pairs so the swap is not too
+    * difficult even though sizes are different.
+    *
+    * While bubble sort is n-squared, it seems OK here because n will
+    * usually be small and the comparison and swap functions aren't
+    * too CPU intensive.
+    *
+    * Another approach would be to have an array of offsets to the
+    * items. However this requires memory allocation and the swap
+    * operation for quick sort or such is complicated because the item
+    * sizes are not the same and overlap may occur in the bytes being
+    * swapped.
+    */
+   do { /* Loop until nothing was swapped */
+      Lens1 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart);
+      if(Lens1.uLabelLen == 0) {
+         /* It's an empty map. Nothing to do. */
+         break;
+      }
+      uStart1 = uStart;
+      uStart2 = uStart1 + Lens1.uItemLen;
+      bSwapped = false;
+
+      while(1) {
+         Lens2 = QCBOREncode_Private_DecodeNextInMap(pMe, uStart2);
+         if(Lens2.uLabelLen == 0) {
+            break;
+         }
+
+         nComparison = UsefulOutBuf_Compare(&(pMe->OutBuf),
+                                            uStart1, Lens1.uLabelLen,
+                                            uStart2, Lens2.uLabelLen);
+         if(nComparison < 0) {
+            UsefulOutBuf_Swap(&(pMe->OutBuf), uStart1, uStart2, uStart2 + Lens2.uItemLen);
+            uStart1 = uStart1 + Lens2.uItemLen; /* item 2 now in position of item 1 */
+            /* Lens1 is still valid as Lens1 for the next loop */
+            bSwapped = true;
+         } else if(nComparison > 0) {
+            uStart1 = uStart2;
+            Lens1   = Lens2;
+         } else /* nComparison == 0 */ {
+            pMe->uError = QCBOR_ERR_DUPLICATE_LABEL;
+            return;
+         }
+         uStart2 = uStart2 + Lens2.uItemLen;
+      }
+   } while(bSwapped);
+}
+
+
+/*
+ * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
+ */
+void 
+QCBOREncode_CloseAndSortMap(QCBOREncodeContext *pMe)
+{
+   uint32_t uStart;
+
+   /* The Header for the map we are about to sort hasn't been
+    * inserted yet, so uStart is the position of the first item
+    * and the end out the UsefulOutBuf data is the end of the
+    * items we are about to sort.
+    */
+   uStart = Nesting_GetStartPos(&(pMe->nesting));
+   QCBOREncode_Private_SortMap(pMe, uStart);
+
+   QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_MAP, Nesting_GetCount(&(pMe->nesting)));
+}
+
+
+/*
+ * Public functions for closing sorted maps. See qcbor/qcbor_encode.h
+ */
+void 
+QCBOREncode_CloseAndSortMapIndef(QCBOREncodeContext *pMe)
+{
+   uint32_t uStart;
+
+   uStart = Nesting_GetStartPos(&(pMe->nesting));
+   QCBOREncode_Private_SortMap(pMe, uStart);
+
+   QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
+}
+
+
 /*
  * Public functions for closing bstr wrapping. See qcbor/qcbor_encode.h
  */
diff --git a/test/UsefulBuf_Tests.c b/test/UsefulBuf_Tests.c
index 6d2b5a4..0235466 100644
--- a/test/UsefulBuf_Tests.c
+++ b/test/UsefulBuf_Tests.c
@@ -989,3 +989,205 @@
 
    return NULL;
 }
+
+
+const char * UOBExtraTests(void)
+{
+   #define COMPARE_TEST_SIZE 10
+   UsefulOutBuf_MakeOnStack( UOB, COMPARE_TEST_SIZE);
+   int                       nCompare;
+   UsefulBufC                Out;
+
+   /* Test UsefulOutBuf_Compare() */
+   UsefulOutBuf_AppendString(&UOB, "abcabdefab");
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 2, 8, 2);
+   if(nCompare != 0) {
+      return "ab should compare equal";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 3, 3, 3);
+   if(nCompare != 'd' - 'c') {
+      return "abc should not equal abd";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 3, 2, 8, 2);
+   if(nCompare != 0) {
+       return "ab should compare equal";
+    }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 2, 4, 5, 4);
+   if(nCompare != 'd' - 'c') {
+      return "ca should not equal de";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 5, 1, 2, 1);
+   if(nCompare != 'c' - 'd') {
+      return "de should not equal ca";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 7, 2, 8, 2);
+   if(nCompare !=  'a' - 'f') {
+      return "fa should not equal ab";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 10, 0, 10);
+   if(nCompare != 0) {
+      return "comparison to self failed";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 9, 1, 9, 1);
+   if(nCompare != 0) {
+      return "b should compare equal to b";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 10, 1, 10, 1);
+   if(nCompare != 0) {
+      return "Comparison off the end is equal";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 1, 100, 1);
+   if(nCompare != 0) {
+      return "Comparison off the end is equal";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 100, 1, 0, 1);
+   if(nCompare != 0) {
+      return "Comparison off the end is equal";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 3, 3, 2);
+   if(nCompare > 0) {
+      return "Comparison of unequal lengths incorrect";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 8, 2, 0, 3);
+   if(nCompare < 0) {
+      return "Comparison of unequal lengths incorrect 2";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 2, 2, 3);
+   if(nCompare != 'c' - 'a') {
+      return "Inequal lengths, but inequal strings";
+   }
+
+   nCompare = UsefulOutBuf_Compare(&UOB, 1, 3, 4, 2);
+   if(nCompare != 'd' - 'c') {
+      return "Inequal lengths, but inequal strings";
+   }
+
+   /* Test UsefulOutBuf_Swap() */
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 0, 4, 8);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("efghabcd"))) {
+      return "swap fail 1";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 0, 1, 2);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("bacdefgh"))) {
+      return "swap fail 2";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 0, 1, 8);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("bcdefgha"))) {
+      return "swap fail 3";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 0, 3, 4);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("dabcefgh"))) {
+      return "swap fail 4";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 9, 10, 11);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("abcdefgh"))) {
+      return "swap fail 5";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 0, 4, 11);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("abcdefgh"))) {
+      return "swap fail 6";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 9, 0, 0);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("abcdefgh"))) {
+      return "swap fail 7";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 0, 0, 0);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("abcdefgh"))) {
+      return "swap fail 8";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 8, 4, 0);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("abcdefgh"))) {
+      return "swap fail 9";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abcdefgh");
+   UsefulOutBuf_Swap(&UOB, 0, 8, 4);
+   Out = UsefulOutBuf_OutUBuf(&UOB);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("abcdefgh"))) {
+      return "swap fail 10";
+   }
+
+
+   /* Test for UsefulOutBuf_GetOutput() */
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_AppendString(&UOB, "abc");
+   UsefulOutBuf_AppendString(&UOB, "xyz");
+
+   Out = UsefulOutBuf_OutUBufOffset(&UOB, 0);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("abcxyz"))) {
+      return "GetOutput fail 1";
+   }
+
+   Out = UsefulOutBuf_OutUBufOffset(&UOB, 5);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("z"))) {
+      return "GetOutput fail 2";
+   }
+
+   Out = UsefulOutBuf_OutUBufOffset(&UOB, 1);
+   if(UsefulBuf_Compare(Out, UsefulBuf_FROM_SZ_LITERAL("bcxyz"))) {
+      return "GetOutput fail 3";
+   }
+
+   Out = UsefulOutBuf_OutUBufOffset(&UOB, 6);
+   if(!UsefulBuf_IsNULLC(Out)) {
+      return "GetOutput fail 4";
+   }
+
+   Out = UsefulOutBuf_OutUBufOffset(&UOB, 7);
+   if(!UsefulBuf_IsNULLC(Out)) {
+      return "GetOutput fail 5";
+   }
+
+   return NULL;
+}
diff --git a/test/UsefulBuf_Tests.h b/test/UsefulBuf_Tests.h
index 828f3f4..c0317e8 100644
--- a/test/UsefulBuf_Tests.h
+++ b/test/UsefulBuf_Tests.h
@@ -52,4 +52,6 @@
 
 const char * UBAdvanceTest(void);
 
+const char * UOBExtraTests(void);
+
 #endif
diff --git a/test/float_tests.c b/test/float_tests.c
index 97f92bf..ce078d4 100644
--- a/test/float_tests.c
+++ b/test/float_tests.c
@@ -41,16 +41,16 @@
 #include "half_to_double_from_rfc7049.h"
 
 
-struct DoubleTestCase {
+struct FloatTestCase {
    double      dNumber;
-   double      fNumber;
+   float       fNumber;
    UsefulBufC  Preferred;
    UsefulBufC  NotPreferred;
    UsefulBufC  CDE;
    UsefulBufC  DCBOR;
 };
 
-/* Boundaries for all destination conversions to test at.
+/* Boundaries for destination conversions:
  *
  * smallest subnormal single  1.401298464324817e-45   2^^-149
  * largest subnormal single   1.1754942106924411e-38  2^^-126
@@ -62,29 +62,34 @@
  * smallest normal half      6.103515625E-5
  * largest half              65504.0
  *
- * Boundaries for origin conversions
+ * Boundaries for origin conversions:
  * smallest subnormal double 5.0e-324  2^^-1074
  * largest subnormal double
  * smallest normal double 2.2250738585072014e-308  2^^-1022
  * largest normal double 1.7976931348623157e308 2^^-1023
+ *
+ * Boundaries for double conversion to 64-bit integer:
+ * exponent 51, 52 significand bits set     4503599627370495
+ * exponent 52, 52 significand bits set     9007199254740991
+ * exponent 53, 52 bits set in significand  18014398509481982
  */
 
 /* Always four lines per test case so shell scripts can process into
- * other formats.  CDE and DCBOR standards are not complete yet,
- * encodings are a guess.  C string literals are used because they
+ * other formats. CDE and DCBOR standards are not complete yet,
+ * encodings are what is expected.  C string literals are used because they
  * are the shortest notation. They are used __with a length__ . Null
  * termination doesn't work because there are zero bytes.
  */
-static const struct DoubleTestCase DoubleTestCases[] =  {
+static const struct FloatTestCase FloatTestCases[] =  {
    /* Zero */
    {0.0,                                         0.0f,
     {"\xF9\x00\x00", 3},                         {"\xFB\x00\x00\x00\x00\x00\x00\x00\x00", 9},
-    {"\xF9\x00\x00", 3},                         {"\xF9\x00\x00", 3}},
+    {"\xF9\x00\x00", 3},                         {"\x00", 1}},
 
    /* Negative Zero */
    {-0.0,                                        -0.0f,
     {"\xF9\x80\x00", 3},                         {"\xFB\x80\x00\x00\x00\x00\x00\x00\x00", 9},
-    {"\xF9\x80\x00", 3},                         {"\xF9\x80\x00", 3}},
+    {"\xF9\x80\x00", 3},                         {"\x00", 1}},
 
    /* NaN */
    {NAN,                                         NAN,
@@ -104,12 +109,12 @@
    /* 1.0 */
    {1.0,                                         1.0f,
     {"\xF9\x3C\x00", 3},                         {"\xFB\x3F\xF0\x00\x00\x00\x00\x00\x00", 9},
-    {"\xF9\x3C\x00", 3},                         {"\xF9\x3C\x00", 3}},
+    {"\xF9\x3C\x00", 3},                         {"\x01", 1}},
 
-   /* -2.0 -- a negative number that is not zero */
+   /* -2.0 -- a negative */
    {-2.0,                                        -2.0f,
     {"\xF9\xC0\x00", 3},                         {"\xFB\xC0\x00\x00\x00\x00\x00\x00\x00", 9},
-    {"\xF9\xC0\x00", 3},                         {"\xF9\x3C\x00", 3}},
+    {"\xF9\xC0\x00", 3},                         {"\x21", 1}},
 
    /* 1/3 */
    {0.333251953125,                              0.333251953125f,
@@ -129,45 +134,44 @@
    /* 6.097555160522461E-5 -- largest half-precision subnormal */
    {6.097555160522461E-5,                        0.0f,
     {"\xF9\x03\xFF", 3},                         {"\xFB\x3F\x0F\xF8\x00\x00\x00\x00\x00", 9},
-    {"\xF9\x03\xFF", 3},                         {"\xF9\04\00", 3}},
-
-   /* 6.103515625E-5 -- smallest possible half-precision normal */
-   {6.103515625E-5,                              0.0f,
-    {"\xF9\04\00", 3},                           {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x00", 9},
-    {"\xF9\04\00", 3},                           {"\xF9\04\00", 3}},
-
-   /* 6.1035156250000014E-5 -- slightly larger than smallest half-precision normal */
-   {6.1035156250000014E-5,                       6.1035156250000014E-5f,
-    {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9},
-    {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}},
+    {"\xF9\x03\xFF", 3},                         {"\xF9\x03\xFF", 3}},
 
    /* 6.1035156249999993E-5 -- slightly smaller than smallest half-precision normal */
    {6.1035156249999993E-5,  0.0f,
     {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
     {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
 
-   /* 65504.0 -- largest possible half-precision */
+   /* 6.103515625E-5 -- smallest half-precision normal */
+   {6.103515625E-5,                              0.0f,
+    {"\xF9\04\00", 3},                           {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x00", 9},
+    {"\xF9\04\00", 3},                           {"\xF9\04\00", 3}},
+
+   /* 6.1035156250000014E-5 -- slightly larger than smallest half-precision normal */
+   {6.1035156250000014E-5,                       0.0f,
+    {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9},
+    {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}},
+
+   /* 65504.0 -- largest half-precision */
    {65504.0,                                     0.0f,
     {"\xF9\x7B\xFF", 3},                         {"\xFB\x40\xEF\xFC\x00\x00\x00\x00\x00", 9},
-    {"\xF9\x7B\xFF", 3},                         {"\xF9\x7B\xFF", 3}},
+    {"\xF9\x7B\xFF", 3},                         {"\x19\xFF\xE0", 3}},
 
-   /* 65504.1 -- exponent too large and too much precision to convert */
+   /* 65504.1 -- exponent too large and too much precision to convert to half */
    {65504.1,                                     0.0f,
     {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9},
     {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}},
 
-    /* 65536.0 -- exponent too large but not too much precision for single */
+    /* 65536.0 -- exponent too large for half but not too much precision for single */
    {65536.0,                                     65536.0f,
     {"\xFA\x47\x80\x00\x00", 5},                 {"\xFB\x40\xF0\x00\x00\x00\x00\x00\x00", 9},
-    {"\xFA\x47\x80\x00\x00", 5},                 {"\xFA\x47\x80\x00\x00", 5}},
+    {"\xFA\x47\x80\x00\x00", 5},                 {"\x1A\x00\x01\x00\x00", 5}},
 
    /* 1.401298464324817e-45 -- smallest single subnormal */
    {1.401298464324817e-45,                       1.40129846E-45f,
     {"\xFA\x00\x00\x00\x01", 5},                 {"\xFB\x36\xA0\x00\x00\x00\x00\x00\x00", 9},
     {"\xFA\x00\x00\x00\x01", 5},                 {"\xFA\x00\x00\x00\x01", 5}},
 
-   /* 5.8774717541114375E-39 -- slightly smaller than the smallest
-    // single normal */
+   /* 5.8774717541114375E-39 -- slightly smaller than the smallest single normal */
    {5.8774717541114375E-39,                      5.87747175E-39f,
     {"\xFA\x00\x40\x00\x00", 5},                 {"\xFB\x38\x00\x00\x00\x00\x00\x00\x00", 9},
     {"\xFA\x00\x40\x00\x00", 5},                 {"\xFA\x00\x40\x00\x00", 5}},
@@ -192,20 +196,100 @@
     {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9},
     {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}},
 
+   /* 8388607 -- exponent 22 to test single exponent boundary */
+   {8388607,                                     8388607.0f,
+    {"\xFA\x4A\xFF\xFF\xFE", 5},                 {"\xFB\x41\x5F\xFF\xFF\xC0\x00\x00\x00", 9},
+    {"\xFA\x4A\xFF\xFF\xFE", 5},                 {"\x1A\x00\x7F\xFF\xFF", 5}},
+
+   /* 16777215 -- exponent 23 to test single exponent boundary */
+   {16777215,                                    16777215.0f,
+    {"\xFA\x4B\x7F\xFF\xFF", 5},                 {"\xFB\x41\x6F\xFF\xFF\xE0\x00\x00\x00", 9},
+    {"\xFA\x4B\x7F\xFF\xFF", 5},                 {"\x1A\x00\xFF\xFF\xFF", 5}},
+
    /* 16777216 -- converts to single without loss */
-   {16777216,                                    16777216,
+   {16777216,                                    16777216.0f,
     {"\xFA\x4B\x80\x00\x00", 5},                 {"\xFB\x41\x70\x00\x00\x00\x00\x00\x00", 9},
-    {"\xFA\x4B\x80\x00\x00", 5},                 {"\xFA\x4B\x80\x00\x00", 5}},
+    {"\xFA\x4B\x80\x00\x00", 5},                 {"\x1A\x01\x00\x00\x00", 5}},
 
-   /* 16777217 -- one more than above and fails conversion to single */
-   {16777217,                                    16777216,
+   /* 16777217 -- one more than above and fails conversion to single because of precision */
+   {16777217,                                    0.0f,
     {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9},
-    {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}},
+    {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\x1A\x01\x00\x00\x01", 5}},
+ 
+   /* 33554430 -- exponent 24 to test single exponent boundary */
+   {33554430,                                    33554430.0f,
+    {"\xFA\x4B\xFF\xFF\xFF", 5},                 {"\xFB\x41\x7F\xFF\xFF\xE0\x00\x00\x00", 9},
+    {"\xFA\x4B\xFF\xFF\xFF", 5},                 {"\x1A\x01\xFF\xFF\xFE",                 5}},
 
-   /* 3.4028234663852886E+38 -- largest possible single normal */
+   /* 4294967295 -- 2^^32 - 1 UINT32_MAX */
+   {4294967295,                                  0,
+    {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
+    {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x1A\xFF\xFF\xFF\xFF",                 5}},
+
+   /* 4294967296 -- 2^^32, UINT32_MAX + 1 */
+   {4294967296,                                  4294967296.0f,
+    {"\xFA\x4F\x80\x00\x00",                 5}, {"\xFB\x41\xF0\x00\x00\x00\x00\x00\x00", 9},
+    {"\xFA\x4F\x80\x00\x00",                 5}, {"\x1B\x00\x00\x00\x01\x00\x00\x00\x00", 9}},
+
+   /* 2251799813685248 -- exponent 51, 0 significand bits set, to test double exponent boundary */
+   {2251799813685248,                            2251799813685248.0f,
+    {"\xFA\x59\x00\x00\x00",                 5}, {"\xFB\x43\x20\x00\x00\x00\x00\x00\x00", 9},
+    {"\xFA\x59\x00\x00\x00",                 5}, {"\x1B\x00\x08\x00\x00\x00\x00\x00\x00", 9}},
+
+   /* 4503599627370495 -- exponent 51, 52 significand bits set to test double exponent boundary*/
+   {4503599627370495,                            0,
+    {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9},
+    {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\x1B\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
+
+   /* 9007199254740991 -- exponent 52, 52 significand bits set to test double exponent boundary */
+   {9007199254740991,                            0,
+    {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
+    {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x1F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
+
+   /* 18014398509481982 -- exponent 53, 52 bits set in significand (double lacks precision to represent 18014398509481983) */
+   {18014398509481982,                           0,
+    {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
+    {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x3F\xFF\xFF\xFF\xFF\xFF\xFE", 9}},
+
+   /* 18014398509481984 -- next largest possible double above 18014398509481982  */
+   {18014398509481984,                           18014398509481984.0f,
+    {"\xFA\x5A\x80\x00\x00",                 5}, {"\xFB\x43\x50\x00\x00\x00\x00\x00\x00", 9},
+    {"\xFA\x5A\x80\x00\x00",                 5}, {"\x1B\x00\x40\x00\x00\x00\x00\x00\x00", 9}},
+   
+   /* 18446742974197924000.0.0 -- largest single that can convert to uint64 */
+   {18446742974197924000.0,                      18446742974197924000.0f,
+    {"\xFA\x5F\x7F\xFF\xFF",                 5}, {"\xFB\x43\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
+    {"\xFA\x5F\x7F\xFF\xFF",                 5}, {"\x1B\xFF\xFF\xFF\x00\x00\x00\x00\x00", 9}},
+
+   /* 18446744073709550000.0 -- largest double that can convert to uint64, almost UINT64_MAX (18446744073709551615) */
+   {18446744073709550000.0,                      0,
+    {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
+    {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\xFF\xFF\xFF\xFF\xFF\xFF\xF8\x00", 9}},
+
+   /* 18446744073709552000.0 -- just too large to convert to uint64, but converts to a single, just over UINT64_MAX  */
+   {18446744073709552000.0,                      18446744073709552000.0f,
+    {"\xFA\x5F\x80\x00\x00",                 5}, {"\xFB\x43\xF0\x00\x00\x00\x00\x00\x00", 9},
+    {"\xFA\x5F\x80\x00\x00",                 5}, {"\xFA\x5F\x80\x00\x00",                 5}},
+
+   /* -4294967295 -- negative UINT32_MAX */
+   {-4294967295.0,                               0,
+    {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
+    {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x3A\xFF\xFF\xFF\xFE", 5}},
+
+   /* -9223372036854774784.0 -- most negative double that converts to int64 */
+   {-9223372036854774784.0,                      0,
+    {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
+    {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x3B\x7F\xFF\xFF\xFF\xFF\xFF\xFB\xFF", 9}},
+
+   /* -18446742974197924000.0.0 -- large negative that converts to float, but too large for int64 */
+   {-18446742974197924000.0,                     -18446742974197924000.0f,
+    {"\xFA\xDF\x7F\xFF\xFF",                 5}, {"\xFB\xC3\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
+    {"\xFA\xDF\x7F\xFF\xFF",                 5}, {"\xFA\xDF\x7F\xFF\xFF",                 5}},
+
+   /* 3.4028234663852886E+38 -- largest possible single */
    {3.4028234663852886E+38,                      3.40282347E+38f,
-    {"\xFA\x7F\x7F\xFF\xFF", 5},                 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
-    {"\xFA\x7F\x7F\xFF\xFF", 5},                 {"\xFA\x7F\x7F\xFF\xFF", 5}},
+    {"\xFA\x7F\x7F\xFF\xFF",                 5}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
+    {"\xFA\x7F\x7F\xFF\xFF",                 5}, {"\xFA\x7F\x7F\xFF\xFF",                 5}},
 
    /* 3.402823466385289E+38 -- slightly larger than largest possible single */
    {3.402823466385289E+38,                       0.0f,
@@ -242,9 +326,12 @@
 };
 
 
+/* Can't use types double and float here because there's no way in C to
+ * construct arbitrary payloads for those types.
+ */
 struct NaNTestCase {
-   uint64_t    uDouble;
-   uint32_t    uSingle;
+   uint64_t    uDouble; /* Converted to double in test */
+   uint32_t    uSingle; /* Converted to single in test */
    UsefulBufC  Preferred;
    UsefulBufC  NotPreferred;
    UsefulBufC  CDE;
@@ -292,14 +379,13 @@
    /* Payload with all bits set */
    {0x7fffffffffffffff,                          0x00000000,
     {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
-    {"\xF9\x7E\x00", 3},                         {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
+    {"\xF9\x7E\x00", 3},                         {"\xF9\x7E\x00", 3}},
 
    /* List terminator */
    {0, 0, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
 };
 
 
-
 /* Public function. See float_tests.h
  *
  * This is the main test of floating-point encoding / decoding. It is
@@ -311,7 +397,7 @@
 FloatValuesTests(void)
 {
    unsigned int                 uTestIndex;
-   const struct DoubleTestCase *pTestCase;
+   const struct FloatTestCase  *pTestCase;
    const struct NaNTestCase    *pNaNTestCase;
    MakeUsefulBufOnStack(        TestOutBuffer, 20);
    UsefulBufC                   TestOutput;
@@ -325,12 +411,11 @@
 #endif
 
    /* Test a variety of doubles */
-   for(uTestIndex = 0; DoubleTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
-      pTestCase = &DoubleTestCases[uTestIndex];
+   for(uTestIndex = 0; FloatTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
+      pTestCase = &FloatTestCases[uTestIndex];
 
-     // if(pTestCase->dNumber == 1.1754943508222874E-38) {
-         if(uTestIndex == 19) {
-         uErr = 99; /* For setting break points for particular tests */
+      if(uTestIndex == 34) {
+         uDecoded = 1;
       }
 
       /* Number Encode of Preferred */
@@ -357,6 +442,47 @@
          return MakeTestResultCode(uTestIndex, 2, 200);
       }
 
+      /* Number Encode of CDE */
+      QCBOREncode_Init(&EnCtx, TestOutBuffer);
+      QCBOREncode_SerializationCDE(&EnCtx);
+      QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
+      uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
+
+      if(uErr != QCBOR_SUCCESS) {
+         return MakeTestResultCode(uTestIndex, 20, uErr);;
+      }
+      if(UsefulBuf_Compare(TestOutput, pTestCase->CDE)) {
+         return MakeTestResultCode(uTestIndex, 21, 200);
+      }
+
+      /* Number Encode of dCBOR */
+      QCBOREncode_Init(&EnCtx, TestOutBuffer);
+      QCBOREncode_SerializationdCBOR(&EnCtx);
+      QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
+      uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
+
+      if(uErr != QCBOR_SUCCESS) {
+         return MakeTestResultCode(uTestIndex, 22, uErr);;
+      }
+      if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
+         return MakeTestResultCode(uTestIndex, 23, 200);
+      }
+
+      if(pTestCase->fNumber != 0) {
+         QCBOREncode_Init(&EnCtx, TestOutBuffer);
+         QCBOREncode_SerializationdCBOR(&EnCtx);
+         QCBOREncode_AddFloat(&EnCtx, pTestCase->fNumber);
+         uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
+
+         if(uErr != QCBOR_SUCCESS) {
+            return MakeTestResultCode(uTestIndex, 24, uErr);;
+         }
+         if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
+            return MakeTestResultCode(uTestIndex, 25, 200);
+         }
+      }
+
+
       /* Number Decode of Preferred */
       QCBORDecode_Init(&DCtx, pTestCase->Preferred, 0);
       uErr = QCBORDecode_GetNext(&DCtx, &Item);
@@ -382,32 +508,32 @@
        * indicates single-precision in the encoded CBOR. */
       if(pTestCase->Preferred.len == 5) {
          if(Item.uDataType != QCBOR_TYPE_FLOAT) {
-            return MakeTestResultCode(uTestIndex, 4, 0);
+            return MakeTestResultCode(uTestIndex, 41, 0);
          }
          if(isnan(pTestCase->dNumber)) {
             if(!isnan(Item.val.fnum)) {
-               return MakeTestResultCode(uTestIndex, 5, 0);
+               return MakeTestResultCode(uTestIndex, 51, 0);
             }
          } else {
             if(Item.val.fnum != pTestCase->fNumber) {
-               return MakeTestResultCode(uTestIndex, 6, 0);
+               return MakeTestResultCode(uTestIndex, 61, 0);
             }
          }
       } else {
          if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
-            return MakeTestResultCode(uTestIndex, 4, 0);
+            return MakeTestResultCode(uTestIndex, 42, 0);
          }
          if(isnan(pTestCase->dNumber)) {
             if(!isnan(Item.val.dfnum)) {
-               return MakeTestResultCode(uTestIndex, 5, 0);
+               return MakeTestResultCode(uTestIndex, 52, 0);
             }
          } else {
             if(Item.val.dfnum != pTestCase->dNumber) {
-               return MakeTestResultCode(uTestIndex, 6, 0);
+               return MakeTestResultCode(uTestIndex, 62, 0);
             }
          }
       }
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+#endif /* ! QCBOR_DISABLE_FLOAT_HW_USE */
 
       /* Number Decode of Not Preferred */
       QCBORDecode_Init(&DCtx, pTestCase->NotPreferred, 0);
@@ -441,6 +567,7 @@
 
       /* NaN Encode of Preferred */
       QCBOREncode_Init(&EnCtx, TestOutBuffer);
+      QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_ALLOW_NAN_PAYLOAD);
       QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
       uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
       if(uErr != QCBOR_SUCCESS) {
@@ -489,6 +616,7 @@
 
       /* NaN Encode of Not Preferred */
       QCBOREncode_Init(&EnCtx, TestOutBuffer);
+      QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_ALLOW_NAN_PAYLOAD);
       QCBOREncode_AddDoubleNoPreferred(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
       uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
       if(uErr != QCBOR_SUCCESS) {
@@ -498,8 +626,9 @@
          return MakeTestResultCode(uTestIndex+100, 11, 200);
       }
 
-      /* NaN Decode of Preferred */
+      /* NaN Decode of Not Preferred */
       QCBORDecode_Init(&DCtx, pNaNTestCase->Preferred, 0);
+      QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_ALLOW_NAN_PAYLOAD);
       uErr = QCBORDecode_GetNext(&DCtx, &Item);
       if(uErr != QCBOR_SUCCESS) {
          return MakeTestResultCode(uTestIndex+100, 12, uErr);
@@ -535,6 +664,7 @@
 
       /* NaN Decode of Not Preferred */
       QCBORDecode_Init(&DCtx, pNaNTestCase->NotPreferred, 0);
+      QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_ALLOW_NAN_PAYLOAD);
       uErr = QCBORDecode_GetNext(&DCtx, &Item);
       if(uErr != QCBOR_SUCCESS) {
          return MakeTestResultCode(uTestIndex+100, 13, uErr);
@@ -543,6 +673,21 @@
       if(uDecoded != pNaNTestCase->uDouble) {
          return MakeTestResultCode(uTestIndex+100, 13, 200);
       }
+
+
+      /* NaN Encode of DCBOR */
+      QCBOREncode_Init(&EnCtx, TestOutBuffer);
+      QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_ALLOW_NAN_PAYLOAD);
+      QCBOREncode_SerializationdCBOR(&EnCtx);
+      QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
+      uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
+      if(uErr != QCBOR_SUCCESS) {
+         return MakeTestResultCode(uTestIndex+100, 14, uErr);;
+      }
+      if(UsefulBuf_Compare(TestOutput, pNaNTestCase->DCBOR)) {
+         return MakeTestResultCode(uTestIndex+100, 14, 200);
+      }
+
    }
 
    return 0;
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 0f48613..6b97768 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -132,7 +132,9 @@
  */
 
 static const uint8_t spExpectedEncodedInts[] = {
-   0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff,
+   0x98, 0x31, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x3b, 0xFf, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xfe, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff,
    0xff, 0x3a, 0xff, 0xff, 0xff, 0xfe, 0x3a, 0xff,
@@ -172,6 +174,18 @@
 
    if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
       return (int32_t)nCBORError;
+   if(Item.uDataType != QCBOR_TYPE_65BIT_NEG_INT ||
+      Item.val.uint64 != 18446744073709551615ULL)
+      return -1;
+
+   if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
+      return (int32_t)nCBORError;
+   if(Item.uDataType != QCBOR_TYPE_65BIT_NEG_INT ||
+      Item.val.uint64 != 18446744073709551614ULL)
+      return -1;
+
+   if((nCBORError = QCBORDecode_GetNext(pDCtx, &Item)))
+      return (int32_t)nCBORError;
    if(Item.uDataType != QCBOR_TYPE_INT64 ||
       Item.val.int64 != -9223372036854775807LL - 1)
       return -1;
@@ -487,14 +501,6 @@
 }
 
 
-/* One less than the smallest negative integer allowed in C. Decoding
-   this should fail.
-   -9223372036854775809
- */
-static const uint8_t spTooSmallNegative[] = {
-   0x3b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
 
 /*
    Tests the decoding of lots of different integers sizes
@@ -515,16 +521,6 @@
       return nReturn;
    }
 
-   // The one large negative integer that can be parsed
-   QCBORDecode_Init(&DCtx,
-                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooSmallNegative),
-                    QCBOR_DECODE_MODE_NORMAL);
-
-   QCBORItem item;
-   if(QCBORDecode_GetNext(&DCtx, &item) != QCBOR_ERR_INT_OVERFLOW) {
-      nReturn = -4000;
-   }
-
    return(nReturn);
 }
 
@@ -6637,13 +6633,12 @@
  */
 static const uint8_t spRecoverableMapErrors[] = {
 #ifndef QCBOR_DISABLE_TAGS
-   0xa6,
+   0xa5,
    0x04, 0xc1, 0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c,
    0x01, 0xd8, 0xe0, 0xd8, 0xe1, 0xd8, 0xe2, 0xd8, 0xe3, 0xd8, 0x04, 0x00,
 #else
    0xa4,
 #endif
-   0x03, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0x05, 0x00,
    0x05, 0x00,
    0x08, 0x08,
@@ -7051,12 +7046,6 @@
 #endif
 
 
-   QCBORDecode_GetInt64InMapN(&DCtx, 0x03, &nInt);
-   uErr = QCBORDecode_GetAndResetError(&DCtx);
-   if(uErr != QCBOR_ERR_INT_OVERFLOW) {
-      return 2023;
-   }
-
 #ifndef QCBOR_DISABLE_TAGS
    QCBORDecode_GetEpochDateInMapN(&DCtx, 0x04, QCBOR_TAG_REQUIREMENT_TAG, &nInt);
    uErr = QCBORDecode_GetAndResetError(&DCtx);
@@ -7558,8 +7547,8 @@
       FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
    },
    {
-      "Negative integer -18446744073709551616",
-      {(uint8_t[]){0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 9},
+      "Negative integer -9223372036854775808",
+      {(uint8_t[]){0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 9},
       -9223372036854775807-1, // INT64_MIN
       QCBOR_SUCCESS,
       0ULL,
@@ -7568,6 +7557,16 @@
       FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
    },
    {
+      "Negative integer -18446744073709551616",
+      {(uint8_t[]){0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 9},
+      0ULL,
+      QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
+      0ULL,
+      QCBOR_ERR_NUMBER_SIGN_CONVERSION,
+      -18446744073709551616.0,
+      FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
+   },
+   {
       "Double Floating point value 100.3",
       {(uint8_t[]){0xfb, 0x40, 0x59, 0x13, 0x33, 0x33, 0x33, 0x33, 0x33}, 9},
       100L,
@@ -7630,6 +7629,9 @@
 
 int32_t IntegerConvertTest(void)
 {
+   uint64_t uInt;
+
+
    const int nNumTests = C_ARRAY_COUNT(NumberConversions,
                                        struct NumberConversion);
 
@@ -7660,7 +7662,6 @@
          return (int32_t)(3333+nIndex);
       }
 
-      uint64_t uInt;
       QCBORDecode_GetUInt64ConvertAll(&DCtx, 0xffff, &uInt);
       if(QCBORDecode_GetError(&DCtx) != pF->uErrorUint64) {
          return (int32_t)(4000+nIndex);
@@ -9602,6 +9603,214 @@
 }
 
 
+#if !defined(USEFULBUF_DISABLE_ALL_FLOAT) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
+
+struct PreciseNumberConversion {
+   char       *szDescription;
+   UsefulBufC  CBOR;
+   QCBORError  uError;
+   uint8_t     qcborType;
+   struct {
+      int64_t  int64;
+      uint64_t uint64;
+      double   d;
+   } number;
+};
+
+
+static const struct PreciseNumberConversion PreciseNumberConversions[] = {
+   {
+      "-0.00",
+      {"\xf9\x80\x00", 3},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_INT64,
+      {0, 0, 0}
+   },
+   {
+      "NaN",
+      {"\xf9\x7e\x00", 3},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_DOUBLE,
+      {0, 0, NAN}
+   },
+   {
+      "NaN payload",
+      {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_DOUBLE,
+      {0, 0, NAN}
+   },
+   {
+      "65536.0 single",
+      {"\xFA\x47\x80\x00\x00", 5},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_INT64,
+      {65536, 0, 0}
+   },
+   {
+      "Infinity",
+      {"\xf9\x7c\x00", 3},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_DOUBLE,
+      {0, 0, INFINITY}
+   },
+   {
+      "1.0",
+      {"\xf9\x3c\x00", 3},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_INT64,
+      {1, 0, 0}
+   },
+   {
+      "UINT64_MAX",
+      {"\x1B\xff\xff\xff\xff\xff\xff\xff\xff", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_UINT64,
+      {0, UINT64_MAX, 0}
+   },
+   {
+      "INT64_MIN",
+      {"\x3B\x7f\xff\xff\xff\xff\xff\xff\xff", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_INT64,
+      {INT64_MIN, 0, 0}
+   },
+   {
+      "18446742974197923840",
+      {"\xFB\x43\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_UINT64,
+      {0, 18446742974197923840ULL, 0}
+   },
+   {
+      "65-bit neg, too much precision",
+      {"\x3B\x80\x00\x00\x00\x00\x00\x00\x01", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_65BIT_NEG_INT,
+      {0, 0x8000000000000001, 0}
+   },
+   {
+      "65-bit neg lots of precision",
+      {"\x3B\xff\xff\xff\xff\xff\xff\xf0\x00", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_DOUBLE,
+      {0, 0, -18446744073709547521.0}
+   },
+   {
+      "65-bit neg very precise",
+      {"\x3B\xff\xff\xff\xff\xff\xff\xf8\x00", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_DOUBLE,
+      {0, 0, -18446744073709549569.0}
+   },
+   {
+      "65-bit neg too precise",
+      {"\x3B\xff\xff\xff\xff\xff\xff\xfc\x00", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_65BIT_NEG_INT,
+      {0, 18446744073709550592ULL, 0.0}
+   },
+   {
+      "65-bit neg, power of two",
+      {"\x3B\x80\x00\x00\x00\x00\x00\x00\x00", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_DOUBLE,
+      {0, 0, -9223372036854775809.0}
+   },
+   {
+      "Zero",
+      {"\x00", 1},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_INT64,
+      {0, 0, 0}
+   },
+   {
+      "Pi",
+      {"\xFB\x40\x09\x2A\xDB\x40\x2D\x16\xB9", 9},
+      QCBOR_SUCCESS,
+      QCBOR_TYPE_DOUBLE,
+      {0, 0, 3.145926}
+   },
+   {
+      "String",
+      {"\x60", 1},
+      QCBOR_ERR_UNEXPECTED_TYPE,
+      QCBOR_TYPE_NONE,
+      {0, 0, 0}
+   }
+};
+
+
+int32_t
+PreciseNumbersTest(void)
+{
+   int                i;
+   QCBORError         uErr;
+   QCBORItem          Item;
+   QCBORDecodeContext DCtx;
+   const struct PreciseNumberConversion *pTest;
+
+   const int count = (int)C_ARRAY_COUNT(PreciseNumberConversions, struct PreciseNumberConversion);
+
+   for(i = 0; i < count; i++) {
+      pTest = &PreciseNumberConversions[i];
+
+      if(i == 11) {
+         uErr = 99; // For break point only
+      }
+
+      QCBORDecode_Init(&DCtx, pTest->CBOR, 0);
+
+      QCBORDecode_GetNumberConvertPrecisely(&DCtx, &Item);
+
+      uErr = QCBORDecode_GetError(&DCtx);
+
+      if(uErr != pTest->uError) {
+         return i * 1000 + (int)uErr;
+      }
+
+      if(pTest->qcborType != Item.uDataType) {
+         return i * 1000 + 200;
+      }
+
+      if(pTest->qcborType == QCBOR_TYPE_NONE) {
+         continue;
+      }
+
+      switch(pTest->qcborType) {
+         case QCBOR_TYPE_INT64:
+            if(Item.val.int64 != pTest->number.int64) {
+               return i * 1000 + 300;
+            }
+            break;
+
+         case QCBOR_TYPE_UINT64:
+         case QCBOR_TYPE_65BIT_NEG_INT:
+            if(Item.val.uint64 != pTest->number.uint64) {
+               return i * 1000 + 400;
+            }
+            break;
+
+         case QCBOR_TYPE_DOUBLE:
+            if(isnan(pTest->number.d)) {
+               if(!isnan(Item.val.dfnum)) {
+                  return i * 1000 + 600;
+               }
+            } else {
+               if(Item.val.dfnum != pTest->number.d) {
+                  return i * 1000 + 500;
+               }
+            }
+            break;
+      }
+   }
+   return 0;
+}
+
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
+
+
+
 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
 static const uint8_t spExpectedArray2s[] = {
    0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index a08a3af..4c4c0a6 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -319,6 +319,7 @@
 int32_t CBORTestIssue134(void);
 
 
+int32_t PreciseNumbersTest(void);
 
 int32_t ErrorHandlingTests(void);
 
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index be5548c..1c0902b 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -48,7 +48,7 @@
 
  */
 
-//#define PRINT_FUNCTIONS_FOR_DEBUGGING
+#define PRINT_FUNCTIONS_FOR_DEBUGGING
 
 #ifdef  PRINT_FUNCTIONS_FOR_DEBUGGING
 #include <stdio.h>
@@ -96,13 +96,9 @@
 #endif
 
 
-#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /*
  Returns 0 if UsefulBufs are equal
  Returns 1000000 + offeset if they are not equal.
-
-
-
 */
 struct UBCompareDiagnostic {
    uint8_t uActual;
@@ -130,7 +126,6 @@
    return 0;
 
 }
-#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 // One big buffer that is used by all the tests to encode into
@@ -281,10 +276,10 @@
 
 
 static const uint8_t spExpectedEncodedAll[] = {
- 0x98, 0x23, 0x66, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x32, 0xd8,
+ 0x98, 0x24, 0x66, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x32, 0xd8,
  0x64, 0x1a, 0x05, 0x5d, 0x23, 0x15, 0x65, 0x49, 0x4e, 0x54,
  0x36, 0x34, 0xd8, 0x4c, 0x1b, 0x00, 0x00, 0x00, 0x12, 0x16,
- 0xaf, 0x2b, 0x15, 0x00, 0x38, 0x2b, 0xa4, 0x63, 0x4c, 0x42,
+ 0xaf, 0x2b, 0x15, 0x00, 0x38, 0x2b, 0x20, 0xa4, 0x63, 0x4c, 0x42,
  0x4c, 0x18, 0x4d, 0x23, 0x18, 0x58, 0x78, 0x1a, 0x4e, 0x45,
  0x47, 0x4c, 0x42, 0x4c, 0x54, 0x48, 0x41, 0x54, 0x20, 0x49,
  0x53, 0x20, 0x4b, 0x49, 0x4e, 0x44, 0x20, 0x4f, 0x46, 0x20,
@@ -526,8 +521,9 @@
    QCBOREncode_AddSZString(pECtx, "INT64");
    QCBOREncode_AddTag(pECtx, 76);
    QCBOREncode_AddInt64(pECtx, 77689989909);
-   QCBOREncode_AddUInt64(pECtx,0);
+   QCBOREncode_AddUInt64(pECtx, 0);
    QCBOREncode_AddInt64(pECtx, -44);
+   QCBOREncode_AddNegativeUInt64(pECtx, 0);
 
    /* ints that go in maps */
    QCBOREncode_OpenMap(pECtx);
@@ -696,13 +692,18 @@
    /* Improvement: this test should be broken down into several so it is more
     * managable. Tags and labels could be more sensible */
    QCBOREncodeContext ECtx;
-   int nReturn = 0;
+   UsefulBufC         Enc;
+   size_t             size;
+   int                nReturn;
+   QCBORError         uExpectedErr;
+
+   nReturn = 0;
 
    QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   QCBOREncode_Allow(&ECtx, QCBOR_ENCODE_ALLOW_ALL);
 
-   AddAll (&ECtx);
+   AddAll(&ECtx);
 
-   UsefulBufC Enc;
    if(QCBOREncode_Finish(&ECtx, &Enc)) {
       nReturn = -1;
       goto Done;
@@ -710,15 +711,16 @@
 
    if(CheckResults(Enc, spExpectedEncodedAll)) {
       nReturn = -2;
+      goto Done;
    }
 
 
    /* Also test size calculation */
    QCBOREncode_Init(&ECtx, SizeCalculateUsefulBuf);
+   QCBOREncode_Allow(&ECtx, QCBOR_ENCODE_ALLOW_ALL);
 
-   AddAll (&ECtx);
+   AddAll(&ECtx);
 
-   size_t size;
    if(QCBOREncode_FinishGetSize(&ECtx, &size)) {
       nReturn = -10;
       goto Done;
@@ -726,8 +728,55 @@
 
    if(size != sizeof(spExpectedEncodedAll)) {
       nReturn = -11;
+      goto Done;
    }
 
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   uExpectedErr = QCBOR_ERR_NOT_ALLOWED;
+#else
+   uExpectedErr = QCBOR_SUCCESS;
+#endif
+
+   /* Test the QCBOR_ERR_NOT_ALLOWED error codes */
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   QCBOREncode_AddNegativeUInt64(&ECtx, 1);
+   if(QCBOREncode_Finish(&ECtx, &Enc) != uExpectedErr) {
+      nReturn = -21;
+      goto Done;
+   }
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   /* 0x7ff8000000000001ULL is a NaN with a payload. */
+   QCBOREncode_AddDouble(&ECtx, UsefulBufUtil_CopyUint64ToDouble(0x7ff8000000000001ULL));
+   if(QCBOREncode_Finish(&ECtx, &Enc) != uExpectedErr) {
+      nReturn = -22;
+      goto Done;
+   }
+
+
+   /* 0x7ffc000000000000ULL is a NaN with a payload. */
+   QCBOREncode_AddDouble(&ECtx, UsefulBufUtil_CopyUint64ToDouble(0x7ff8000000000001ULL));
+   if(QCBOREncode_Finish(&ECtx, &Enc) != uExpectedErr) {
+      nReturn = -23;
+      goto Done;
+   }
+
+   /* 0x7ff80001UL is a NaN with a payload. */
+   QCBOREncode_AddFloat(&ECtx, UsefulBufUtil_CopyUint32ToFloat(0x7ff80001UL));
+   if(QCBOREncode_Finish(&ECtx, &Enc) != uExpectedErr) {
+      nReturn = -24;
+      goto Done;
+   }
+
+   /* 0x7ffc0000UL is a NaN with a payload. */
+   QCBOREncode_AddFloat(&ECtx, UsefulBufUtil_CopyUint32ToFloat(0x7ffc0000UL));
+   if(QCBOREncode_Finish(&ECtx, &Enc) != uExpectedErr) {
+      nReturn = -25;
+      goto Done;
+   }
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
+
 Done:
    return nReturn;
 }
@@ -1768,12 +1817,6 @@
 */
 static const uint8_t spExpectedBstrWrap[] = {0x82, 0x19, 0x01, 0xC3, 0x43, 0x19, 0x01, 0xD2};
 
-/*
- 81   #array(1)
- 0x58  0x25  # string of length 37 (length of "This is longer than twenty four bytes")
- */
-static const uint8_t spExpectedTypeAndLen[] = {0x81, 0x58, 0x25};
-
 static const uint8_t spExpectedForBstrWrapCancel[] = {0x82, 0x19, 0x01, 0xC3, 0x18, 0x2A};
 
 /*
@@ -1823,19 +1866,6 @@
       return -5;
    }
 
-   // Third, test QCBOREncode_AddBytesLenOnly() here as it is part of the
-   // bstr wrapping use cases.
-   UsefulBuf_MAKE_STACK_UB(StuffBuf, 50);
-   QCBOREncode_Init(&EC, StuffBuf);
-   QCBOREncode_OpenArray(&EC);
-   QCBOREncode_AddBytesLenOnly(&EC, UsefulBuf_FROM_SZ_LITERAL("This is longer than twenty four bytes"));
-   QCBOREncode_CloseArray(&EC);
-   if(QCBOREncode_Finish(&EC, &Encoded)) {
-      return -6;
-   }
-   if(CheckResults(Encoded, spExpectedTypeAndLen)) {
-      return -7;
-   }
 
    // Fourth test, cancelling a byte string
    QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
@@ -3109,3 +3139,573 @@
 
    return 0;
 }
+
+
+
+int32_t
+SortMapTest(void)
+{
+   UsefulBuf_MAKE_STACK_UB(   TestBuf,  200);
+   QCBOREncodeContext         EC;
+   UsefulBufC                 EncodedAndSorted;
+   QCBORError                 uErr;
+   struct UBCompareDiagnostic CompareDiagnostics;
+
+
+   /* --- Basic sort test case --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMapN(&EC, 3, 3);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_AddInt64ToMapN(&EC, 4, 4);
+   QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 11;
+   }
+
+   static const uint8_t spBasic[] = {
+      0xA4, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04};
+
+   if(UsefulBuf_Compare(EncodedAndSorted, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBasic))) {
+      return 12;
+   }
+
+   /* --- Empty map sort test case --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 21;
+   }
+
+   static const uint8_t spEmpty[] = {0xA0};
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEmpty),
+                                      &CompareDiagnostics)) {
+      return 22;
+   }
+
+   /* --- Several levels of nested sorted maps ---  */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+     QCBOREncode_AddInt64ToMap(&EC, "three", 3);
+     QCBOREncode_OpenMapInMapN(&EC, 428);
+       QCBOREncode_AddNULLToMap(&EC, "null");
+       QCBOREncode_OpenArrayInMap(&EC, "array");
+         QCBOREncode_AddSZString(&EC, "hi");
+         QCBOREncode_AddSZString(&EC, "there");
+         QCBOREncode_CloseArray(&EC);
+       QCBOREncode_OpenMapInMap(&EC, "empty2");
+         QCBOREncode_CloseAndSortMap(&EC);
+       QCBOREncode_OpenMapInMap(&EC, "empty1");
+         QCBOREncode_CloseAndSortMap(&EC);
+       QCBOREncode_CloseAndSortMap(&EC);
+     QCBOREncode_AddDateEpochToMapN(&EC, 88, 888888);
+     QCBOREncode_AddBoolToMap(&EC, "boo", true);
+     QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 31;
+   }
+
+   /* Correctly sorted.
+    * {
+    *   88: 1(888888),
+    *   428: {
+    *     "null": null,
+    *     "array": [
+    *       "hi",
+    *       "there"
+    *     ],
+    *     "empty1": {},
+    *     "empty2": {}
+    *   },
+    *   "boo": true,
+    *   "three": 3
+    *  }
+    */
+   static const uint8_t spSorted[] = {
+      0xA4, 0x18, 0x58, 0xC1, 0x1A, 0x00, 0x0D, 0x90,
+      0x38, 0x19, 0x01, 0xAC, 0xA4, 0x64, 0x6E, 0x75,
+      0x6C, 0x6C, 0xF6, 0x65, 0x61, 0x72, 0x72, 0x61,
+      0x79, 0x82, 0x62, 0x68, 0x69, 0x65, 0x74, 0x68,
+      0x65, 0x72, 0x65, 0x66, 0x65, 0x6D, 0x70, 0x74,
+      0x79, 0x31, 0xA0, 0x66, 0x65, 0x6D, 0x70, 0x74,
+      0x79, 0x32, 0xA0, 0x63, 0x62, 0x6F, 0x6F, 0xF5,
+      0x65, 0x74, 0x68, 0x72, 0x65, 0x65, 0x03};
+
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSorted),
+                                      &CompareDiagnostics)) {
+      return 32;
+   }
+
+
+   /* Same data items, but added in a different order */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+     QCBOREncode_AddInt64ToMap(&EC, "three", 3);
+     QCBOREncode_OpenMapInMapN(&EC, 428);
+       QCBOREncode_OpenMapInMap(&EC, "empty1");
+         QCBOREncode_CloseAndSortMap(&EC);
+       QCBOREncode_OpenArrayInMap(&EC, "array");
+         QCBOREncode_AddSZString(&EC, "hi");
+         QCBOREncode_AddSZString(&EC, "there");
+         QCBOREncode_CloseArray(&EC);
+       QCBOREncode_OpenMapInMap(&EC, "empty2");
+         QCBOREncode_CloseAndSortMap(&EC);
+       QCBOREncode_AddNULLToMap(&EC, "null");
+       QCBOREncode_CloseAndSortMap(&EC);
+     QCBOREncode_AddDateEpochToMapN(&EC, 88, 888888);
+     QCBOREncode_AddBoolToMap(&EC, "boo", true);
+     QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 31;
+   }
+
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSorted),
+                                      &CompareDiagnostics)) {
+      return 32;
+   }
+
+   /* Same data items, but added in a different order */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+     QCBOREncode_AddBoolToMap(&EC, "boo", true);
+     QCBOREncode_OpenMapInMapN(&EC, 428);
+       QCBOREncode_OpenMapInMap(&EC, "empty1");
+         QCBOREncode_CloseAndSortMap(&EC);
+       QCBOREncode_OpenArrayInMap(&EC, "array");
+         QCBOREncode_AddSZString(&EC, "hi");
+         QCBOREncode_AddSZString(&EC, "there");
+         QCBOREncode_CloseArray(&EC);
+       QCBOREncode_OpenMapInMap(&EC, "empty2");
+         QCBOREncode_CloseAndSortMap(&EC);
+       QCBOREncode_AddNULLToMap(&EC, "null");
+       QCBOREncode_CloseAndSortMap(&EC);
+     QCBOREncode_AddDateEpochToMapN(&EC, 88, 888888);
+     QCBOREncode_AddInt64ToMap(&EC, "three", 3);
+     QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 31;
+   }
+
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSorted),
+                                      &CompareDiagnostics)) {
+      return 32;
+   }
+
+
+
+   /* --- Degenerate case of everything in order --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMapN(&EC, 0, 0);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+   QCBOREncode_AddInt64ToMap(&EC, "a", 3);
+   QCBOREncode_AddInt64ToMap(&EC, "b", 4);
+   QCBOREncode_AddInt64ToMap(&EC, "aa", 5);
+   QCBOREncode_AddInt64ToMap(&EC, "aaa", 6);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 41;
+   }
+
+   static const uint8_t sp6Items[] = {
+      0xA7, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x61,
+      0x61, 0x03, 0x61, 0x62, 0x04, 0x62, 0x61, 0x61,
+      0x05, 0x63, 0x61, 0x61, 0x61, 0x06};
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sp6Items),
+                                      &CompareDiagnostics)) {
+      return 42;
+   }
+
+   /* --- Degenerate case -- reverse order --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMap(&EC, "aaa", 6);
+   QCBOREncode_AddInt64ToMap(&EC, "aa", 5);
+   QCBOREncode_AddInt64ToMap(&EC, "b", 4);
+   QCBOREncode_AddInt64ToMap(&EC, "a", 3);
+   QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+   QCBOREncode_AddInt64ToMapN(&EC, 0, 0);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 51;
+   }
+
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sp6Items),
+                                      &CompareDiagnostics)) {
+      return 52;
+   }
+
+   /* --- Same items, randomly out of order --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMap(&EC, "aa", 5);
+   QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+   QCBOREncode_AddInt64ToMapN(&EC, 0, 0);
+   QCBOREncode_AddInt64ToMap(&EC, "b", 4);
+   QCBOREncode_AddInt64ToMap(&EC, "aaa", 6);
+   QCBOREncode_AddInt64ToMap(&EC, "a", 3);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 61;
+   }
+
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sp6Items),
+                                      &CompareDiagnostics)) {
+      return 62;
+   }
+
+   /* --- Stuff in front of and after array to sort --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenArray(&EC);
+   QCBOREncode_AddInt64(&EC, 111);
+   QCBOREncode_AddInt64(&EC, 222);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMapN(&EC, 0, 0);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+   QCBOREncode_CloseAndSortMap(&EC);
+   QCBOREncode_AddInt64(&EC, 888);
+   QCBOREncode_AddInt64(&EC, 999);
+   QCBOREncode_CloseArray(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 71;
+   }
+
+   static const uint8_t spPreItems[] = {
+      0x85, 0x18, 0x6F, 0x18, 0xDE, 0xA3, 0x00, 0x00,
+      0x01, 0x01, 0x02, 0x02, 0x19, 0x03, 0x78, 0x19,
+      0x03, 0xE7};
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spPreItems),
+                                      &CompareDiagnostics)) {
+      return 72;
+   }
+
+   /* --- map with labels of all CBOR major types and in reverse order --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+
+   /* Adding labels directly rather than AddToMap functions */
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+   QCBOREncode_AddDouble(&EC, 8.77);
+   QCBOREncode_AddInt64(&EC, 7);
+#endif /* QCBOR_DISABLE_ALL_FLOAT */
+
+   QCBOREncode_AddBool(&EC, true);
+   QCBOREncode_AddInt64(&EC, 6);
+
+   QCBOREncode_AddDateEpoch(&EC, 88);
+   QCBOREncode_AddInt64(&EC, 5);
+
+   QCBOREncode_AddEncoded(&EC, UsefulBuf_FromSZ("\xa0"));
+   QCBOREncode_AddInt64(&EC, 4);
+
+   QCBOREncode_AddEncoded(&EC, UsefulBuf_FromSZ("\x80"));
+   QCBOREncode_AddInt64(&EC, 7);
+
+   QCBOREncode_AddInt64ToMap(&EC, "text", 3);
+
+   QCBOREncode_AddBytes(&EC, UsefulBuf_FromSZ("xx"));
+   QCBOREncode_AddInt64(&EC, 2);
+
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1); /* Integer */
+   QCBOREncode_CloseAndSortMap(&EC);
+
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 81;
+   }
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+   static const uint8_t spLabelTypes[] = {
+      0xA8, 0x01, 0x01, 0x42, 0x78, 0x78, 0x02, 0x64,
+      0x74, 0x65, 0x78, 0x74, 0x03, 0x80, 0x07, 0xA0,
+      0x04, 0xC1, 0x18, 0x58, 0x05, 0xF5, 0x06, 0xFB,
+      0x40, 0x21, 0x8A, 0x3D, 0x70, 0xA3, 0xD7, 0x0A,
+      0x07};
+#else
+   static const uint8_t spLabelTypes[] = {
+      0xA7, 0x01, 0x01, 0x42, 0x78, 0x78, 0x02, 0x64,
+      0x74, 0x65, 0x78, 0x74, 0x03, 0x80, 0x07, 0xA0,
+      0x04, 0xC1, 0x18, 0x58, 0x05, 0xF5, 0x06};
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLabelTypes),
+                                      &CompareDiagnostics)) {
+      return 82;
+   }
+
+   /* --- labels are indefinitely encoded ---  */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+
+   QCBOREncode_AddInt64ToMap(&EC, "aaaa", 1);
+
+   QCBOREncode_AddInt64ToMap(&EC, "bb", 2);
+
+   QCBOREncode_AddEncoded(&EC, UsefulBuf_FromSZ("\x7f\x61" "a" "\x61" "a" "\xff"));
+   QCBOREncode_AddInt64(&EC, 3);
+
+   QCBOREncode_AddEncoded(&EC, UsefulBuf_FromSZ("\x7f" "\x61" "c" "\xff"));
+   QCBOREncode_AddInt64(&EC, 4);
+
+   QCBOREncode_CloseAndSortMap(&EC);
+
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 91;
+   }
+
+   static const uint8_t spIndefItems[] = {
+      0xA4, 0x62, 0x62, 0x62, 0x02, 0x64, 0x61, 0x61,
+      0x61, 0x61, 0x01, 0x7F, 0x61, 0x61, 0x61, 0x61,
+      0xFF, 0x03, 0x7F, 0x61, 0x63, 0xFF, 0x04};
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                       UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefItems),
+                                       &CompareDiagnostics)) {
+       return 92;
+   }
+
+   /* --- Indefinitely encoded maps --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMapIndefiniteLength(&EC);
+
+   QCBOREncode_OpenMapIndefiniteLengthInMap(&EC, "aa");
+   QCBOREncode_CloseMapIndefiniteLength(&EC);
+
+   QCBOREncode_OpenArrayIndefiniteLengthInMap(&EC, "ff");
+   QCBOREncode_CloseArrayIndefiniteLength(&EC);
+
+   QCBOREncode_OpenMapIndefiniteLengthInMap(&EC, "zz");
+   QCBOREncode_CloseMapIndefiniteLength(&EC);
+
+   QCBOREncode_OpenMapIndefiniteLengthInMap(&EC, "bb");
+   QCBOREncode_CloseMapIndefiniteLength(&EC);
+
+   QCBOREncode_CloseAndSortMapIndef(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr) {
+      return 101;
+   }
+
+   static const uint8_t spIndeMaps[] = {
+      0xBF, 0x62, 0x61, 0x61, 0xBF, 0xFF, 0x62, 0x62,
+      0x62, 0xBF, 0xFF, 0x62, 0x66, 0x66, 0x9F, 0xFF,
+      0x62, 0x7A, 0x7A, 0xBF, 0xFF, 0xFF, 0x06, 0xFB};
+   if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+                                      UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndeMaps),
+                                      &CompareDiagnostics)) {
+      return 102;
+   }
+
+
+   /* --- Duplicate label test  --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMapN(&EC, 3, 3);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr != QCBOR_ERR_DUPLICATE_LABEL) {
+      return 114;
+   }
+
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMapN(&EC, 3, 3);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 2);
+   QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr != QCBOR_ERR_DUPLICATE_LABEL) {
+      return 115;
+   }
+
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMap(&EC, "abc", 3);
+   QCBOREncode_AddInt64ToMap(&EC, "def", 1);
+   QCBOREncode_AddInt64ToMap(&EC, "def", 1);
+   QCBOREncode_AddInt64ToMap(&EC, "def", 2);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr != QCBOR_ERR_DUPLICATE_LABEL) {
+      return 116;
+   }
+
+   return 0;
+}
+
+
+#if !defined(USEFULBUF_DISABLE_ALL_FLOAT) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
+
+#include <math.h> /* For INFINITY and NAN and isnan() */
+
+
+/* Public function. See qcbor_encode_tests.h */
+int32_t CDETest(void)
+{
+   QCBOREncodeContext EC;
+   UsefulBufC         Encoded;
+   QCBORError         uExpectedErr;
+
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+
+   QCBOREncode_SerializationCDE(&EC);
+
+   /* Items added to test sorting and preferred encoding of numbers and floats */
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddFloatToMap(&EC, "k", 1.0f);
+   QCBOREncode_AddInt64ToMap(&EC, "a", 1);
+   QCBOREncode_AddDoubleToMap(&EC, "x", 2.0);
+   QCBOREncode_AddDoubleToMap(&EC, "r", 3.4028234663852886E+38);
+   QCBOREncode_AddDoubleToMap(&EC, "b", NAN);
+   QCBOREncode_AddUndefToMap(&EC, "t"); /* Test because dCBOR disallows */
+
+   QCBOREncode_CloseMap(&EC);
+
+   uExpectedErr = QCBOREncode_Finish(&EC, &Encoded);
+   if(uExpectedErr != QCBOR_SUCCESS) {
+      return 2;
+   }
+
+   static const uint8_t spExpectedCDE[] = {
+      0xA6, 0x61, 0x61, 0x01, 0x61, 0x62, 0xF9, 0x7E,
+      0x00, 0x61, 0x6B, 0xF9, 0x3C, 0x00, 0x61, 0x72,
+      0xFA, 0x7F, 0x7F, 0xFF, 0xFF, 0x61, 0x74, 0xF7,
+      0x61, 0x78, 0xF9, 0x40, 0x00};
+
+   if(UsefulBuf_Compare(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedCDE),
+                        Encoded)) {
+      return 1;
+   }
+
+
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   uExpectedErr = QCBOR_ERR_NOT_PREFERRED;
+#else
+   uExpectedErr = QCBOR_SUCCESS;
+#endif
+
+   /* Next, make sure methods that encode non-CDE error out */
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   QCBOREncode_SerializationCDE(&EC);
+   QCBOREncode_OpenMapIndefiniteLength(&EC);
+   QCBOREncode_CloseMap(&EC);
+   if(QCBOREncode_GetErrorState(&EC) != uExpectedErr) {
+      return 100;
+   }
+
+   return 0;
+}
+
+/* Public function. See qcbor_encode_tests.h */
+int32_t DCBORTest(void)
+{
+   QCBOREncodeContext EC;
+   UsefulBufC         Encoded;
+   QCBORError         uExpectedErr;
+
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+
+   QCBOREncode_SerializationdCBOR(&EC);
+
+   /* Items added to test sorting and preferred encoding of numbers and floats */
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddFloatToMap(&EC, "k", 1.0f);
+   QCBOREncode_AddInt64ToMap(&EC, "a", 1);
+   QCBOREncode_AddDoubleToMap(&EC, "x", 2.0);
+   QCBOREncode_AddDoubleToMap(&EC, "r", 3.4028234663852886E+38);
+   QCBOREncode_AddDoubleToMap(&EC, "b", NAN);
+
+   QCBOREncode_CloseMap(&EC);
+
+   QCBOREncode_Finish(&EC, &Encoded);
+
+   static const uint8_t spExpecteddCBOR[] = {
+      0xA5, 0x61, 0x61, 0x01, 0x61, 0x62, 0xF9, 0x7E,
+      0x00, 0x61, 0x6B, 0x01, 0x61, 0x72, 0xFA, 0x7F,
+      0x7F, 0xFF, 0xFF, 0x61, 0x78, 0x02};
+
+   if(UsefulBuf_Compare(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpecteddCBOR),
+                        Encoded)) {
+      return 1;
+   }
+
+
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   uExpectedErr = QCBOR_ERR_NOT_PREFERRED;
+#else
+   uExpectedErr = QCBOR_SUCCESS;
+#endif
+
+   /* Next, make sure methods that encode of non-CDE error out */
+
+   /* Indefinite-length map */
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   QCBOREncode_SerializationdCBOR(&EC);
+   QCBOREncode_OpenMapIndefiniteLength(&EC);
+   QCBOREncode_CloseMap(&EC);
+   if(QCBOREncode_GetErrorState(&EC) != uExpectedErr) {
+      return 100;
+   }
+
+   /* Indefinite-length array */
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   QCBOREncode_SerializationdCBOR(&EC);
+   QCBOREncode_OpenArrayIndefiniteLength(&EC);
+   QCBOREncode_CloseMap(&EC);
+   if(QCBOREncode_GetErrorState(&EC) != uExpectedErr) {
+      return 101;
+   }
+
+   /* The "undef" special value */
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   QCBOREncode_SerializationdCBOR(&EC);
+   QCBOREncode_AddUndef(&EC);
+   QCBOREncode_CloseMap(&EC);
+   if(QCBOREncode_GetErrorState(&EC) != uExpectedErr) {
+      return 102;
+   }
+
+   /* 65-bit negative integers */
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   QCBOREncode_SerializationdCBOR(&EC);
+   QCBOREncode_AddNegativeUInt64(&EC, 1);
+   if(QCBOREncode_GetErrorState(&EC) != uExpectedErr) {
+      return 103;
+   }
+
+   /* Improvement: when indefinite length string encoding is supported
+    * test it here too. */
+
+   return 0;
+
+}
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
diff --git a/test/qcbor_encode_tests.h b/test/qcbor_encode_tests.h
index 8452009..5e2f978 100644
--- a/test/qcbor_encode_tests.h
+++ b/test/qcbor_encode_tests.h
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2022, Laurence Lundblade.
+ Copyright (c) 2018-2024, Laurence Lundblade.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -191,5 +191,17 @@
 int32_t OpenCloseBytesTest(void);
 
 
+/* Test map sorting */
+int32_t SortMapTest(void);
+
+#if !defined(USEFULBUF_DISABLE_ALL_FLOAT) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
+
+/* Test CBOR Deterministic Encoding */
+int32_t CDETest(void);
+
+/* Test "dCBOR" mode */
+int32_t DCBORTest(void);
+
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
 
 #endif /* defined(__QCBOR__qcbor_encode_tests__) */
diff --git a/test/run_tests.c b/test/run_tests.c
index d1d49ed..e24506a 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -61,108 +61,127 @@
     TEST_ENTRY(UBMacroConversionsTest),
     TEST_ENTRY(UBUtilTests),
     TEST_ENTRY(UIBTest_IntegerFormat),
-    TEST_ENTRY(UBAdvanceTest)
+    TEST_ENTRY(UBAdvanceTest),
+    TEST_ENTRY(UOBExtraTests)
 };
 
 
 static test_entry s_tests[] = {
 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
-    TEST_ENTRY(GetMapAndArrayTest),
-    TEST_ENTRY(TellTests),
-    TEST_ENTRY(ParseMapAsArrayTest),
+   TEST_ENTRY(GetMapAndArrayTest),
+   TEST_ENTRY(TellTests),
+   TEST_ENTRY(ParseMapAsArrayTest),
    TEST_ENTRY(SpiffyDateDecodeTest),
 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
-    TEST_ENTRY(ErrorHandlingTests),
-    TEST_ENTRY(OpenCloseBytesTest),
-    TEST_ENTRY(EnterBstrTest),
-    TEST_ENTRY(IntegerConvertTest),
-    TEST_ENTRY(EnterMapTest),
-    TEST_ENTRY(QCBORHeadTest),
-    TEST_ENTRY(EmptyMapsAndArraysTest),
-    TEST_ENTRY(NotWellFormedTests),
+   TEST_ENTRY(ErrorHandlingTests),
+   TEST_ENTRY(OpenCloseBytesTest),
+   TEST_ENTRY(EnterBstrTest),
+   TEST_ENTRY(IntegerConvertTest),
+   TEST_ENTRY(EnterMapTest),
+   TEST_ENTRY(QCBORHeadTest),
+   TEST_ENTRY(EmptyMapsAndArraysTest),
+   TEST_ENTRY(NotWellFormedTests),
+
 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
-    TEST_ENTRY(IndefiniteLengthNestTest),
-    TEST_ENTRY(IndefiniteLengthArrayMapTest),
-    TEST_ENTRY(NestedMapTestIndefLen),
+   TEST_ENTRY(IndefiniteLengthNestTest),
+   TEST_ENTRY(IndefiniteLengthArrayMapTest),
+   TEST_ENTRY(NestedMapTestIndefLen),
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
-    TEST_ENTRY(SimpleValueDecodeTests),
-    TEST_ENTRY(DecodeFailureTests),
-    TEST_ENTRY(EncodeRawTest),
-    TEST_ENTRY(RTICResultsTest),
-    TEST_ENTRY(MapEncodeTest),
-    TEST_ENTRY(ArrayNestingTest1),
-    TEST_ENTRY(ArrayNestingTest2),
+
+   TEST_ENTRY(SimpleValueDecodeTests),
+   TEST_ENTRY(DecodeFailureTests),
+   TEST_ENTRY(EncodeRawTest),
+   TEST_ENTRY(RTICResultsTest),
+   TEST_ENTRY(MapEncodeTest),
+   TEST_ENTRY(ArrayNestingTest1),
+   TEST_ENTRY(ArrayNestingTest2),
+
 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
-    TEST_ENTRY(ArrayNestingTest3),
+   TEST_ENTRY(ArrayNestingTest3),
 #endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
-    TEST_ENTRY(EncodeDateTest),
-    TEST_ENTRY(SimpleValuesTest1),
-    TEST_ENTRY(IntegerValuesTest1),
-    TEST_ENTRY(AllAddMethodsTest),
-    TEST_ENTRY(ParseTooDeepArrayTest),
-    TEST_ENTRY(ComprehensiveInputTest),
+
+   TEST_ENTRY(EncodeDateTest),
+   TEST_ENTRY(SimpleValuesTest1),
+   TEST_ENTRY(IntegerValuesTest1),
+   TEST_ENTRY(AllAddMethodsTest),
+   TEST_ENTRY(ParseTooDeepArrayTest),
+   TEST_ENTRY(ComprehensiveInputTest),
 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
-    TEST_ENTRY(ParseMapTest),
+   TEST_ENTRY(ParseMapTest),
 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
-    TEST_ENTRY(BasicEncodeTest),
-    TEST_ENTRY(NestedMapTest),
-    TEST_ENTRY(BignumParseTest),
+   TEST_ENTRY(BasicEncodeTest),
+   TEST_ENTRY(NestedMapTest),
+   TEST_ENTRY(BignumParseTest),
+
 #ifndef QCBOR_DISABLE_TAGS
-    TEST_ENTRY(OptTagParseTest),
-    TEST_ENTRY(DateParseTest),
-    TEST_ENTRY(DecodeTaggedTypeTests),
+   TEST_ENTRY(OptTagParseTest),
+   TEST_ENTRY(DateParseTest),
+   TEST_ENTRY(DecodeTaggedTypeTests),
 #endif /* QCBOR_DISABLE_TAGS */
-    TEST_ENTRY(ShortBufferParseTest2),
-    TEST_ENTRY(ShortBufferParseTest),
-    TEST_ENTRY(ParseDeepArrayTest),
-    TEST_ENTRY(SimpleArrayTest),
-    TEST_ENTRY(IntegerValuesParseTest),
+
+   TEST_ENTRY(ShortBufferParseTest2),
+   TEST_ENTRY(ShortBufferParseTest),
+   TEST_ENTRY(ParseDeepArrayTest),
+   TEST_ENTRY(SimpleArrayTest),
+   TEST_ENTRY(IntegerValuesParseTest),
 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
-    TEST_ENTRY(AllocAllStringsTest),
-    TEST_ENTRY(MemPoolTest),
-    TEST_ENTRY(IndefiniteLengthStringTest),
+   TEST_ENTRY(AllocAllStringsTest),
+   TEST_ENTRY(MemPoolTest),
+   TEST_ENTRY(IndefiniteLengthStringTest),
 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
-    TEST_ENTRY(SpiffyIndefiniteLengthStringsTests),
+   TEST_ENTRY(SpiffyIndefiniteLengthStringsTests),
 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
-    TEST_ENTRY(SetUpAllocatorTest),
-    TEST_ENTRY(CBORTestIssue134),
+   TEST_ENTRY(SetUpAllocatorTest),
+   TEST_ENTRY(CBORTestIssue134),
+
 #endif /* #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
    TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest),
    TEST_ENTRY(FloatValuesTests),
+   TEST_ENTRY(PreciseNumbersTest),
 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
-    TEST_ENTRY(GeneralFloatEncodeTests),
-    TEST_ENTRY(GeneralFloatDecodeTests),
+   TEST_ENTRY(GeneralFloatEncodeTests),
+   TEST_ENTRY(GeneralFloatDecodeTests),
 #endif /* USEFULBUF_DISABLE_ALL_FLOAT */
-    TEST_ENTRY(BstrWrapTest),
-    TEST_ENTRY(BstrWrapErrorTest),
-    TEST_ENTRY(BstrWrapNestTest),
-    TEST_ENTRY(CoseSign1TBSTest),
+
+   TEST_ENTRY(BstrWrapTest),
+   TEST_ENTRY(BstrWrapErrorTest),
+   TEST_ENTRY(BstrWrapNestTest),
+   TEST_ENTRY(CoseSign1TBSTest),
 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
-    TEST_ENTRY(StringDecoderModeFailTest),
+   TEST_ENTRY(StringDecoderModeFailTest),
 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
-    TEST_ENTRY_DISABLED(BigComprehensiveInputTest),
-    TEST_ENTRY_DISABLED(TooLargeInputTest),
-    TEST_ENTRY(EncodeErrorTests),
+   TEST_ENTRY_DISABLED(BigComprehensiveInputTest),
+   TEST_ENTRY_DISABLED(TooLargeInputTest),
+   TEST_ENTRY(EncodeErrorTests),
 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
-    TEST_ENTRY(SimpleValuesIndefiniteLengthTest1),
+   TEST_ENTRY(SimpleValuesIndefiniteLengthTest1),
 #endif
-    TEST_ENTRY(EncodeLengthThirtyoneTest),
-    TEST_ENTRY(CBORSequenceDecodeTests),
-    TEST_ENTRY(IntToTests),
+   TEST_ENTRY(EncodeLengthThirtyoneTest),
+   TEST_ENTRY(CBORSequenceDecodeTests),
+   TEST_ENTRY(IntToTests),
 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
-    TEST_ENTRY(PeekAndRewindTest),
+   TEST_ENTRY(PeekAndRewindTest),
 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+
+
 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
-    TEST_ENTRY(ExponentAndMantissaDecodeTests),
+   TEST_ENTRY(ExponentAndMantissaDecodeTests),
 #ifndef QCBOR_DISABLE_TAGS
-    TEST_ENTRY(ExponentAndMantissaDecodeFailTests),
+   TEST_ENTRY(ExponentAndMantissaDecodeFailTests),
 #endif /* QCBOR_DISABLE_TAGS */
-    TEST_ENTRY(ExponentAndMantissaEncodeTests),
+   TEST_ENTRY(ExponentAndMantissaEncodeTests),
 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
-    TEST_ENTRY(ParseEmptyMapInMapTest),
-    TEST_ENTRY(BoolTest)
+   TEST_ENTRY(BoolTest),
+   TEST_ENTRY(SortMapTest),
+#if !defined(USEFULBUF_DISABLE_ALL_FLOAT) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
+   TEST_ENTRY(CDETest),
+   TEST_ENTRY(DCBORTest),
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
+   TEST_ENTRY(ParseEmptyMapInMapTest),
+
 };