blob: 735a55da6bbb738aa1e72ce7e70287525a2d1c1e [file] [log] [blame]
Laurence Lundblade68a13352018-09-23 02:19:54 -07001/*==============================================================================
Laurence Lundblade2d85ce42018-10-12 14:12:47 +08002 float_tests.c -- tests for float and conversion to/from half-precision
Laurence Lundblade781fd822018-10-01 09:37:52 -07003
Laurence Lundbladeee851742020-01-08 08:37:05 -08004 Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
Laurence Lundblade035bd782019-01-21 17:01:31 -08005
Laurence Lundbladea3fd49f2019-01-21 10:16:22 -08006 SPDX-License-Identifier: BSD-3-Clause
Laurence Lundblade035bd782019-01-21 17:01:31 -08007
Laurence Lundbladea3fd49f2019-01-21 10:16:22 -08008 See BSD-3-Clause license in README.md
Laurence Lundblade035bd782019-01-21 17:01:31 -08009
Laurence Lundbladea3fd49f2019-01-21 10:16:22 -080010 Created on 9/19/18
Laurence Lundbladeee851742020-01-08 08:37:05 -080011 =============================================================================*/
Laurence Lundblade68a13352018-09-23 02:19:54 -070012
Laurence Lundblade2aa0b572020-07-16 19:48:42 -070013
14#include "float_tests.h"
Laurence Lundblade585127a2020-07-15 03:25:24 -070015#include "qcbor/qcbor_encode.h"
Laurence Lundblade02fcf312020-07-17 02:49:46 -070016#include "qcbor/qcbor_decode.h"
Laurence Lundblade585127a2020-07-15 03:25:24 -070017#include <math.h> // For INFINITY and NAN and isnan()
18
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -070019#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -070020
Laurence Lundbladed711fb22018-09-26 14:35:22 -070021#include "half_to_double_from_rfc7049.h"
Laurence Lundblade68a13352018-09-23 02:19:54 -070022
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080023
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080024
Laurence Lundbladebb474be2018-10-22 11:53:21 +053025static const uint8_t spExpectedHalf[] = {
Laurence Lundblade7d40d812018-09-30 02:44:01 -070026 0xB1,
Laurence Lundblade68a13352018-09-23 02:19:54 -070027 0x64,
28 0x7A, 0x65, 0x72, 0x6F,
29 0xF9, 0x00, 0x00, // 0.000
30 0x6A,
31 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
32 0xF9, 0x7C, 0x00, // Infinity
33 0x73,
Laurence Lundbladeee851742020-01-08 08:37:05 -080034 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E,
35 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade68a13352018-09-23 02:19:54 -070036 0xF9, 0xFC, 0x00, // -Inifinity
37 0x63,
38 0x4E, 0x61, 0x4E,
39 0xF9, 0x7E, 0x00, // NaN
40 0x63,
41 0x6F, 0x6E, 0x65,
42 0xF9, 0x3C, 0x00, // 1.0
43 0x69,
44 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
45 0xF9, 0x35, 0x55, // 0.333251953125
46 0x76,
Laurence Lundbladeee851742020-01-08 08:37:05 -080047 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C,
48 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
Laurence Lundblade68a13352018-09-23 02:19:54 -070049 0xF9, 0x7B, 0xFF, // 65504.0
Laurence Lundbladeee851742020-01-08 08:37:05 -080050 0x78, 0x18,
51 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68,
52 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
53 0x6F, 0x6E,
Laurence Lundblade68a13352018-09-23 02:19:54 -070054 0xF9, 0x7C, 0x00, // Infinity
55 0x72,
Laurence Lundbladeee851742020-01-08 08:37:05 -080056 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75,
57 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade68a13352018-09-23 02:19:54 -070058 0xF9, 0x00, 0x01, // 0.000000059604
59 0x6F,
Laurence Lundbladeee851742020-01-08 08:37:05 -080060 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
61 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade68a13352018-09-23 02:19:54 -070062 0xF9, 0x03, 0xFF, // 0.0000609755516
63 0x71,
Laurence Lundbladeee851742020-01-08 08:37:05 -080064 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62,
65 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade68a13352018-09-23 02:19:54 -070066 0xF9, 0x04, 0x00, // 0.000061988
67 0x70,
Laurence Lundbladeee851742020-01-08 08:37:05 -080068 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x73,
69 0x69, 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade68a13352018-09-23 02:19:54 -070070 0xF9, 0x00, 0x00,
71 0x03,
Laurence Lundblade7d40d812018-09-30 02:44:01 -070072 0xF9, 0xC0, 0x00, // -2
73 0x04,
74 0xF9, 0x7E, 0x00, // qNaN
75 0x05,
76 0xF9, 0x7C, 0x01, // sNaN
77 0x06,
78 0xF9, 0x7E, 0x0F, // qNaN with payload 0x0f
79 0x07,
80 0xF9, 0x7C, 0x0F, // sNaN with payload 0x0f
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080081
Laurence Lundblade68a13352018-09-23 02:19:54 -070082};
83
84
Laurence Lundbladec5fef682020-01-25 11:38:45 -080085int32_t HalfPrecisionDecodeBasicTests()
Laurence Lundblade68a13352018-09-23 02:19:54 -070086{
Laurence Lundbladebb474be2018-10-22 11:53:21 +053087 UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080088
Laurence Lundblade68a13352018-09-23 02:19:54 -070089 QCBORDecodeContext DC;
90 QCBORDecode_Init(&DC, HalfPrecision, 0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080091
Laurence Lundblade68a13352018-09-23 02:19:54 -070092 QCBORItem Item;
93
94 QCBORDecode_GetNext(&DC, &Item);
95 if(Item.uDataType != QCBOR_TYPE_MAP) {
96 return -1;
97 }
98
99 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700100 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0F) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700101 return -2;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700102 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800103
Laurence Lundblade68a13352018-09-23 02:19:54 -0700104 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700105 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700106 return -3;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700107 }
108
109 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700110 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -INFINITY) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700111 return -4;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700112 }
113
Laurence Lundbladeee851742020-01-08 08:37:05 -0800114 // TODO, is this really converting right? It is carrying payload, but
115 // this confuses things.
116 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700117 if(Item.uDataType != QCBOR_TYPE_DOUBLE || !isnan(Item.val.dfnum)) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700118 return -5;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700119 }
120
121 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700122 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 1.0F) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700123 return -6;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700124 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800125
Laurence Lundblade68a13352018-09-23 02:19:54 -0700126 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700127 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.333251953125F) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700128 return -7;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700129 }
130
131 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700132 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 65504.0F) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700133 return -8;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700134 }
135
136 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700137 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700138 return -9;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700139 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800140
Laurence Lundblade68a13352018-09-23 02:19:54 -0700141 QCBORDecode_GetNext(&DC, &Item); // TODO: check this
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700142 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000000596046448F) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700143 return -10;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700144 }
145
146 QCBORDecode_GetNext(&DC, &Item); // TODO: check this
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700147 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000609755516F) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700148 return -11;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700149 }
150
151 QCBORDecode_GetNext(&DC, &Item); // TODO check this
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700152 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0000610351563F) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700153 return -12;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700154 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800155
156 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700157 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700158 return -13;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700159 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800160
Laurence Lundblade68a13352018-09-23 02:19:54 -0700161 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700162 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -2.0F) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700163 return -14;
164 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800165
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700166 // TODO: double check these four tests
167 QCBORDecode_GetNext(&DC, &Item); // qNaN
Laurence Lundbladeee851742020-01-08 08:37:05 -0800168 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
169 UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff8000000000000ULL) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700170 return -15;
171 }
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700172 QCBORDecode_GetNext(&DC, &Item); // sNaN
Laurence Lundbladeee851742020-01-08 08:37:05 -0800173 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
174 UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff0000000000001ULL) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700175 return -16;
176 }
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700177 QCBORDecode_GetNext(&DC, &Item); // qNaN with payload 0x0f
Laurence Lundbladeee851742020-01-08 08:37:05 -0800178 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
179 UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff800000000000fULL) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700180 return -17;
181 }
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700182 QCBORDecode_GetNext(&DC, &Item); // sNaN with payload 0x0f
Laurence Lundbladeee851742020-01-08 08:37:05 -0800183 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
184 UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum) != 0x7ff000000000000fULL) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700185 return -18;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700186 }
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700187
Laurence Lundblade68a13352018-09-23 02:19:54 -0700188 if(QCBORDecode_Finish(&DC)) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700189 return -19;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700190 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800191
Laurence Lundblade68a13352018-09-23 02:19:54 -0700192 return 0;
193}
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700194
195
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700196
197
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800198int32_t HalfPrecisionAgainstRFCCodeTest()
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700199{
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700200 for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700201 unsigned char x[2];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800202 x[1] = (uint8_t)(uHalfP & 0xff);
203 x[0] = (uint8_t)(uHalfP >> 8); // uHalfP is always less than 0xffff
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700204 double d = decode_half(x);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800205
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700206 // Contruct the CBOR for the half-precision float by hand
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530207 UsefulBuf_MAKE_STACK_UB(__xx, 3);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700208 UsefulOutBuf UOB;
209 UsefulOutBuf_Init(&UOB, __xx);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800210
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800211 const uint8_t uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); // 0xf9
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700212 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); // The initial byte for a half-precision float
213 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP);
214
Laurence Lundbladeee851742020-01-08 08:37:05 -0800215 // Now parse the hand-constructed CBOR. This will invoke the
216 // conversion to a float
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700217 QCBORDecodeContext DC;
218 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800219
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700220 QCBORItem Item;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800221
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700222 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700223 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700224 return -1;
225 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800226
Laurence Lundbladeee851742020-01-08 08:37:05 -0800227 //printf("%04x QCBOR:%15.15f RFC: %15.15f (%8x)\n",
228 // uHalfP, Item.val.fnum, d , UsefulBufUtil_CopyFloatToUint32(d));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800229
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700230 if(isnan(d)) {
231 // The RFC code uses the native instructions which may or may not
232 // handle sNaN, qNaN and NaN payloads correctly. This test just
233 // makes sure it is a NaN and doesn't worry about the type of NaN
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700234 if(!isnan(Item.val.dfnum)) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700235 return -3;
236 }
237 } else {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700238 if(Item.val.dfnum != d) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700239 return -2;
240 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700241 }
242 }
243 return 0;
244}
245
246
247/*
Laurence Lundbladebb474be2018-10-22 11:53:21 +0530248 {"zero": 0.0,
249 "negative zero": -0.0,
250 "infinitity": Infinity,
251 "negative infinitity": -Infinity,
252 "NaN": NaN,
253 "one": 1.0,
254 "one third": 0.333251953125,
255 "largest half-precision": 65504.0,
256 "largest half-precision point one": 65504.1,
257 "too-large half-precision": 65536.0,
258 "smallest subnormal": 5.96046448e-8,
259 "smallest normal": 0.00006103515261202119,
260 "biggest subnormal": 0.00006103515625,
261 "subnormal single": 4.00000646641519e-40,
262 3: -2.0,
263 "large single exp": 2.5521177519070385e+38,
264 "too-large single exp": 5.104235503814077e+38,
265 "biggest single with prec": 16777216.0,
266 "first single with prec loss": 16777217.0,
267 1: "fin"}
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700268 */
Laurence Lundbladebb474be2018-10-22 11:53:21 +0530269static const uint8_t spExpectedSmallest[] = {
270 0xB4, 0x64, 0x7A, 0x65, 0x72, 0x6F, 0xF9, 0x00, 0x00, 0x6D,
271 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A,
272 0x65, 0x72, 0x6F, 0xF9, 0x80, 0x00, 0x6A, 0x69, 0x6E, 0x66,
273 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, 0xF9, 0x7C, 0x00,
274 0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20,
275 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
276 0xF9, 0xFC, 0x00, 0x63, 0x4E, 0x61, 0x4E, 0xF9, 0x7E, 0x00,
277 0x63, 0x6F, 0x6E, 0x65, 0xF9, 0x3C, 0x00, 0x69, 0x6F, 0x6E,
278 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0xF9, 0x35, 0x55,
279 0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68,
280 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73,
281 0x69, 0x6F, 0x6E, 0xF9, 0x7B, 0xFF, 0x78, 0x20, 0x6C, 0x61,
282 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66,
283 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
284 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x65,
285 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33, 0x78,
286 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65,
287 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63,
288 0x69, 0x73, 0x69, 0x6F, 0x6E, 0xFA, 0x47, 0x80, 0x00, 0x00,
289 0x72, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
290 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xFB,
291 0x3E, 0x70, 0x00, 0x00, 0x00, 0x1C, 0x5F, 0x68, 0x6F, 0x73,
292 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
293 0x72, 0x6D, 0x61, 0x6C, 0xFA, 0x38, 0x7F, 0xFF, 0xFF, 0x71,
294 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75,
295 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xF9, 0x04, 0x00,
296 0x70, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
297 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0xFB, 0x37, 0xC1,
298 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF9, 0xC0, 0x00,
299 0x70, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E,
300 0x67, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x70, 0xFA, 0x7F, 0x40,
301 0x00, 0x00, 0x74, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72,
302 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20,
303 0x65, 0x78, 0x70, 0xFB, 0x47, 0xF8, 0x00, 0x00, 0x00, 0x00,
304 0x00, 0x00, 0x78, 0x18, 0x62, 0x69, 0x67, 0x67, 0x65, 0x73,
305 0x74, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77,
306 0x69, 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0xFA, 0x4B,
307 0x80, 0x00, 0x00, 0x78, 0x1B, 0x66, 0x69, 0x72, 0x73, 0x74,
308 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69,
309 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x20, 0x6C, 0x6F,
310 0x73, 0x73, 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00,
311 0x00, 0x01, 0x63, 0x66, 0x69, 0x6E
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700312};
313
314
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800315int32_t DoubleAsSmallestTest()
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700316{
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530317 UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, 420);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800318
Laurence Lundblade067035b2018-11-28 17:35:25 -0800319#define QCBOREncode_AddDoubleAsSmallestToMap QCBOREncode_AddDoubleToMap
320#define QCBOREncode_AddDoubleAsSmallestToMapN QCBOREncode_AddDoubleToMapN
321
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800322
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700323 QCBOREncodeContext EC;
324 QCBOREncode_Init(&EC, EncodedHalfsMem);
325 // These are mostly from https://en.wikipedia.org/wiki/Half-precision_floating-point_format
326 QCBOREncode_OpenMap(&EC);
327 // 64 # text(4)
328 // 7A65726F # "zero"
329 // F9 0000 # primitive(0)
330 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "zero", 0.00);
331
332 // 64 # text(4)
333 // 7A65726F # "negative zero"
334 // F9 8000 # primitive(0)
335 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "negative zero", -0.00);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800336
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700337 // 6A # text(10)
338 // 696E66696E6974697479 # "infinitity"
339 // F9 7C00 # primitive(31744)
340 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "infinitity", INFINITY);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800341
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700342 // 73 # text(19)
343 // 6E6567617469766520696E66696E6974697479 # "negative infinitity"
344 // F9 FC00 # primitive(64512)
345 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "negative infinitity", -INFINITY);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800346
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700347 // 63 # text(3)
348 // 4E614E # "NaN"
349 // F9 7E00 # primitive(32256)
350 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "NaN", NAN);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800351
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700352 // TODO: test a few NaN variants
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800353
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700354 // 63 # text(3)
355 // 6F6E65 # "one"
356 // F9 3C00 # primitive(15360)
357 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "one", 1.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800358
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700359 // 69 # text(9)
360 // 6F6E65207468697264 # "one third"
361 // F9 3555 # primitive(13653)
362 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "one third", 0.333251953125);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800363
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700364 // 76 # text(22)
Laurence Lundbladeee851742020-01-08 08:37:05 -0800365 // 6C6172676573742068616C662D707265636973696F6E # "largest half-precision"
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700366 // F9 7BFF # primitive(31743)
367 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "largest half-precision",65504.0);
368
369 // 76 # text(22)
Laurence Lundbladeee851742020-01-08 08:37:05 -0800370 // 6C6172676573742068616C662D707265636973696F6E # "largest half-precision"
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700371 // F9 7BFF # primitive(31743)
372 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "largest half-precision point one",65504.1);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800373
Laurence Lundbladeee851742020-01-08 08:37:05 -0800374 // Float 65536.0F is 0x47800000 in hex. It has an exponent of 16, which
375 // is larger than 15, the largest half-precision exponent
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700376 // 78 18 # text(24)
377 // 746F6F2D6C617267652068616C662D707265636973696F6E # "too-large half-precision"
378 // FA 47800000 # primitive(31743)
379 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "too-large half-precision", 65536.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800380
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700381 // The smallest possible half-precision subnormal, but digitis are lost converting
382 // to half, so this turns into a double
383 // 72 # text(18)
384 // 736D616C6C657374207375626E6F726D616C # "smallest subnormal"
385 // FB 3E700000001C5F68 # primitive(4499096027744984936)
386 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "smallest subnormal", 0.0000000596046448);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800387
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700388 // The smallest possible half-precision snormal, but digitis are lost converting
389 // to half, so this turns into a single TODO: confirm this is right
390 // 6F # text(15)
391 // 736D616C6C657374206E6F726D616C # "smallest normal"
392 // FA 387FFFFF # primitive(947912703)
393 // in hex single is 0x387fffff, exponent -15, significand 7fffff
394 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "smallest normal", 0.0000610351526F);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800395
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700396 // 71 # text(17)
397 // 62696767657374207375626E6F726D616C # "biggest subnormal"
398 // F9 0400 # primitive(1024)
399 // in hex single is 0x38800000, exponent -14, significand 0
400 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "biggest subnormal", 0.0000610351563F);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800401
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700402 // 70 # text(16)
403 // 7375626E6F726D616C2073696E676C65 # "subnormal single"
404 // FB 37C16C2800000000 # primitive(4017611261645684736)
405 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "subnormal single", 4e-40F);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800406
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700407 // 03 # unsigned(3)
408 // F9 C000 # primitive(49152)
409 QCBOREncode_AddDoubleAsSmallestToMapN(&EC, 3, -2.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800410
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700411 // 70 # text(16)
412 // 6C617267652073696E676C6520657870 # "large single exp"
413 // FA 7F400000 # primitive(2134900736)
414 // (0x01LL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) | ((127LL + DOUBLE_EXPONENT_BIAS) << DOUBLE_EXPONENT_SHIFT);
415 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "large single exp", 2.5521177519070385E+38); // Exponent fits single
416
417 // 74 # text(20)
418 // 746F6F2D6C617267652073696E676C6520657870 # "too-large single exp"
419 // FB 47F8000000000000 # primitive(5185894970917126144)
420 // (0x01LL << (DOUBLE_NUM_SIGNIFICAND_BITS-1)) | ((128LL + DOUBLE_EXPONENT_BIAS) << DOUBLE_EXPONENT_SHIFT);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800421 // Exponent too large for single
422 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "too-large single exp", 5.104235503814077E+38);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700423
424 // 66 # text(6)
425 // 646664666465 # "dfdfde"
426 // FA 4B800000 # primitive(1266679808)
Laurence Lundbladeee851742020-01-08 08:37:05 -0800427 // Single with no precision loss
428 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "biggest single with prec", 16777216);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800429
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700430 // 78 18 # text(24)
431 // 626967676573742073696E676C6520776974682070726563 # "biggest single with prec"
432 // FA 4B800000 # primitive(1266679808)
Laurence Lundbladeee851742020-01-08 08:37:05 -0800433 // Double becuase of precision loss
434 QCBOREncode_AddDoubleAsSmallestToMap(&EC, "first single with prec loss", 16777217);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800435
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700436 // Just a convenient marker when cutting and pasting encoded CBOR
437 QCBOREncode_AddSZStringToMapN(&EC, 1, "fin");
438
439 QCBOREncode_CloseMap(&EC);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800440
Laurence Lundblade781fd822018-10-01 09:37:52 -0700441 UsefulBufC EncodedHalfs;
Laurence Lundblade29497c02020-07-11 15:44:03 -0700442 QCBORError uErr = QCBOREncode_Finish(&EC, &EncodedHalfs);
443 if(uErr) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700444 return -1;
445 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800446
Laurence Lundbladebb474be2018-10-22 11:53:21 +0530447 if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700448 return -3;
449 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800450
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700451 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800452}
Laurence Lundblade585127a2020-07-15 03:25:24 -0700453#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700454
455
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700456/*
457[0.0, 3.14, 0.0, NaN, Infinity, 0.0, 3.140000104904175, 0.0, NaN, Infinity,
458 {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
459 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
460 */
461static const uint8_t spExpectedFloats[] = {
462 0x8B,
463 0xF9, 0x00, 0x00,
464 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
465 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
467 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468 0xF9, 0x00, 0x00,
469 0xFA, 0x40, 0x48, 0xF5, 0xC3,
470 0xFA, 0x00, 0x00, 0x00, 0x00,
471 0xFA, 0x7F, 0xC0, 0x00, 0x00,
472 0xFA, 0x7F, 0x80, 0x00, 0x00,
473 0xA8,
474 0x18, 0x64,
475 0xF9, 0x00, 0x00,
476 0x18, 0x65,
477 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
478 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
479 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
480 0x18, 0x69,
481 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x18, 0x66,
483 0xF9, 0x00, 0x00,
484 0x18, 0x67,
485 0xFA, 0x40, 0x49, 0x0F, 0xDA,
486 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
487 0xFA, 0x40, 0x2D, 0xF8, 0x54,
488 0x18, 0x6A,
489 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700490
491static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700492 0x8B,
493 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
495 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
496 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0xFA, 0x00, 0x00, 0x00, 0x00,
499 0xFA, 0x40, 0x48, 0xF5, 0xC3,
500 0xFA, 0x00, 0x00, 0x00, 0x00,
501 0xFA, 0x7F, 0xC0, 0x00, 0x00,
502 0xFA, 0x7F, 0x80, 0x00, 0x00,
503 0xA8,
504 0x18, 0x64,
505 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 0x18, 0x65,
507 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
508 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
509 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
510 0x18, 0x69,
511 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
512 0x18, 0x66,
513 0xFA, 0x00, 0x00, 0x00, 0x00,
514 0x18, 0x67,
515 0xFA, 0x40, 0x49, 0x0F, 0xDA,
516 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
517 0xFA, 0x40, 0x2D, 0xF8, 0x54,
518 0x18, 0x6A,
519 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700520
521int32_t GeneralFloatEncodeTests()
522{
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700523#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700524 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700525 UsefulBufC ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
526 (void)spExpectedFloatsNoHalf; // Avoid unused variable error
527#else
528 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
529 UsefulBufC ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
530 (void)spExpectedFloats; // Avoid unused variable error
531#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700532
533 QCBOREncodeContext EC;
534 QCBOREncode_Init(&EC, OutBuffer);
535 QCBOREncode_OpenArray(&EC);
536
537 QCBOREncode_AddDouble(&EC, 0.0);
538 QCBOREncode_AddDouble(&EC, 3.14);
539 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
540 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
541 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
542
543 QCBOREncode_AddFloat(&EC, 0.0);
544 QCBOREncode_AddFloat(&EC, 3.14f);
545 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
546 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
547 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
548
549 QCBOREncode_OpenMap(&EC);
550
551 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
552 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
553 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
554 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
555
556 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
557 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
558 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
559 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
560
561 QCBOREncode_CloseMap(&EC);
562 QCBOREncode_CloseArray(&EC);
563
564 UsefulBufC Encoded;
565 QCBORError uErr = QCBOREncode_Finish(&EC, &Encoded);
566 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700567 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700568 }
569
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700570 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700571 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700572 }
573
574 return 0;
575}
576
577
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700578#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
579/* returns 0 if equivalent, non-zero if not equivalent */
580static int CHECK_EXPECTED_DOUBLE(double val, double expected)
581{
582 double diff = val - expected;
583
584 diff = fabs(diff);
585
586 if(diff > 0.000001) {
587 return 1;
588 } else {
589 return 0;
590 }
591}
592#endif
593
594
595int32_t GeneralFloatDecodeTests()
596{
597 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
598
599 QCBORDecodeContext DC;
600 QCBORDecode_Init(&DC, TestData, 0);
601
602 QCBORItem Item;
603 QCBORError uErr;
604
605 QCBORDecode_GetNext(&DC, &Item);
606 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
607 return -1;
608 }
609
610#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
611 uErr = QCBORDecode_GetNext(&DC, &Item);
612 if(uErr != QCBOR_SUCCESS ||
613 Item.uDataType != QCBOR_TYPE_DOUBLE ||
614 Item.val.dfnum != 0.0) {
615 return -2;
616 }
617#else
618 uErr = QCBORDecode_GetNext(&DC, &Item);
619 if(uErr != QCBOR_ERR_HALF_PRECISION_UNSUPPORTED) {
620 return -3;
621 }
622#endif
623
624 uErr = QCBORDecode_GetNext(&DC, &Item);
625 if(uErr != QCBOR_SUCCESS ||
626 Item.uDataType != QCBOR_TYPE_DOUBLE ||
627 Item.val.dfnum != 3.14) {
628 return -4;
629 }
630
631 uErr = QCBORDecode_GetNext(&DC, &Item);
632 if(uErr != QCBOR_SUCCESS ||
633 Item.uDataType != QCBOR_TYPE_DOUBLE ||
634 Item.val.dfnum != 0.0) {
635 return -5;
636 }
637
638 uErr = QCBORDecode_GetNext(&DC, &Item);
639 if(uErr != QCBOR_SUCCESS ||
640 Item.uDataType != QCBOR_TYPE_DOUBLE ||
641 !isnan(Item.val.dfnum)) {
642 return -6;
643 }
644
645 uErr = QCBORDecode_GetNext(&DC, &Item);
646 if(uErr != QCBOR_SUCCESS ||
647 Item.uDataType != QCBOR_TYPE_DOUBLE ||
648 Item.val.dfnum != INFINITY) {
649 return -7;
650 }
651
652#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
653 uErr = QCBORDecode_GetNext(&DC, &Item);
654 if(uErr != QCBOR_SUCCESS ||
655 Item.uDataType != QCBOR_TYPE_DOUBLE ||
656 Item.val.dfnum != 0.0) {
657 return -8;
658 }
659
660 uErr = QCBORDecode_GetNext(&DC, &Item);
661 if(uErr != QCBOR_SUCCESS ||
662 Item.uDataType != QCBOR_TYPE_DOUBLE ||
663 CHECK_EXPECTED_DOUBLE(3.14, Item.val.dfnum)) {
664 return -9;
665 }
666
667 uErr = QCBORDecode_GetNext(&DC, &Item);
668 if(uErr != QCBOR_SUCCESS ||
669 Item.uDataType != QCBOR_TYPE_DOUBLE ||
670 Item.val.dfnum != 0.0) {
671 return -10;
672 }
673
674 uErr = QCBORDecode_GetNext(&DC, &Item);
675 if(uErr != QCBOR_SUCCESS ||
676 Item.uDataType != QCBOR_TYPE_DOUBLE ||
677 !isnan(Item.val.dfnum)) {
678 return -11;
679 }
680
681 uErr = QCBORDecode_GetNext(&DC, &Item);
682 if(uErr != QCBOR_SUCCESS ||
683 Item.uDataType != QCBOR_TYPE_DOUBLE ||
684 Item.val.dfnum != INFINITY) {
685 return -12;
686 }
687
688#else
689 uErr = QCBORDecode_GetNext(&DC, &Item);
690 if(uErr != QCBOR_ERR_HALF_PRECISION_UNSUPPORTED) {
691 return -13;
692 }
693
694 uErr = QCBORDecode_GetNext(&DC, &Item);
695 if(uErr != QCBOR_SUCCESS ||
696 Item.uDataType != QCBOR_TYPE_FLOAT ||
697 Item.val.fnum != 3.14f) {
698 return -14;
699 }
700
701 uErr = QCBORDecode_GetNext(&DC, &Item);
702 if(uErr != QCBOR_SUCCESS ||
703 Item.uDataType != QCBOR_TYPE_FLOAT ||
704 Item.val.fnum != 0.0f) {
705 return -15;
706 }
707
708 uErr = QCBORDecode_GetNext(&DC, &Item);
709 if(uErr != QCBOR_SUCCESS ||
710 Item.uDataType != QCBOR_TYPE_FLOAT ||
711 !isnan(Item.val.fnum)) {
712 return -16;
713 }
714
715 uErr = QCBORDecode_GetNext(&DC, &Item);
716 if(uErr != QCBOR_SUCCESS ||
717 Item.uDataType != QCBOR_TYPE_FLOAT ||
718 Item.val.fnum != INFINITY) {
719 return -17;
720 }
721#endif
722 /* Sufficent test coverage. Don't need to decode the rest */
723
724 return 0;
725}
726
727
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700728
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700729#ifdef NAN_EXPERIMENT
730/*
731 Code for checking what the double to float cast does with
732 NaNs. Not run as part of tests. Keep it around to
733 be able to check various platforms and CPUs.
734 */
735
736#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
737#define DOUBLE_NUM_EXPONENT_BITS (11)
738#define DOUBLE_NUM_SIGN_BITS (1)
739
740#define DOUBLE_SIGNIFICAND_SHIFT (0)
741#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
742#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
743
744#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
745#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
746#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
747#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
748
749
750static int NaNExperiments() {
751 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
752 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
753 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700755 float f1 = (float)dqNaN;
756 float f2 = (float)dsNaN;
757 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800758
759
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700760 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
761 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
762 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800763
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700764 // Result of this on x86 is that every NaN is a qNaN. The intel
765 // CVTSD2SS instruction ignores the NaN payload and even converts
766 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800767
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700768 return 0;
769}
770#endif
771
772
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700773