blob: 12f34fd0238d8a304cab246f7d995650bc7839d0 [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 Lundbladef7c0adb2020-08-08 20:20:58 -070017#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade585127a2020-07-15 03:25:24 -070018#include <math.h> // For INFINITY and NAN and isnan()
19
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -070020#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -070021
Laurence Lundbladed711fb22018-09-26 14:35:22 -070022#include "half_to_double_from_rfc7049.h"
Laurence Lundblade68a13352018-09-23 02:19:54 -070023
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080024
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070025/*
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -070026 Half-precision values that are input to test half-precision decoding
27
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070028 As decoded by http://cbor.me
29 {"zero": 0.0,
30 "infinitity": Infinity,
31 "negative infinitity": -Infinity,
32 "NaN": NaN,
33 "one": 1.0,
34 "one third": 0.333251953125,
35 "largest half-precision": 65504.0,
36 "too-large half-precision": Infinity,
37 "smallest subnormal": 5.960464477539063e-8,
38 "smallest normal": 0.00006097555160522461,
39 "biggest subnormal": 0.00006103515625,
40 "subnormal single": 0.0,
41 3: -2.0,
42 4: NaN,
43 5: NaN,
44 6: NaN,
45 7: NaN}
46 */
Laurence Lundbladebb474be2018-10-22 11:53:21 +053047static const uint8_t spExpectedHalf[] = {
Laurence Lundblade7d40d812018-09-30 02:44:01 -070048 0xB1,
Laurence Lundblade68a13352018-09-23 02:19:54 -070049 0x64,
50 0x7A, 0x65, 0x72, 0x6F,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070051 0xF9, 0x00, 0x00, // half-precision 0.000
Laurence Lundblade68a13352018-09-23 02:19:54 -070052 0x6A,
53 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070054 0xF9, 0x7C, 0x00, // Infinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070055 0x73,
Laurence Lundbladeee851742020-01-08 08:37:05 -080056 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E,
57 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070058 0xF9, 0xFC, 0x00, // -Inifinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070059 0x63,
60 0x4E, 0x61, 0x4E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070061 0xF9, 0x7E, 0x00, // NaN
Laurence Lundblade68a13352018-09-23 02:19:54 -070062 0x63,
63 0x6F, 0x6E, 0x65,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070064 0xF9, 0x3C, 0x00, // 1.0
Laurence Lundblade68a13352018-09-23 02:19:54 -070065 0x69,
66 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070067 0xF9, 0x35, 0x55, // half-precsion one third 0.333251953125
Laurence Lundblade68a13352018-09-23 02:19:54 -070068 0x76,
Laurence Lundbladeee851742020-01-08 08:37:05 -080069 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C,
70 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070071 0xF9, 0x7B, 0xFF, // largest half-precision 65504.0
Laurence Lundbladeee851742020-01-08 08:37:05 -080072 0x78, 0x18,
73 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68,
74 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
75 0x6F, 0x6E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070076 0xF9, 0x7C, 0x00, // Infinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070077 0x72,
Laurence Lundbladeee851742020-01-08 08:37:05 -080078 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75,
79 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070080 0xF9, 0x00, 0x01, // Smallest half-precision subnormal 0.000000059604645
Laurence Lundblade68a13352018-09-23 02:19:54 -070081 0x71,
Laurence Lundbladeee851742020-01-08 08:37:05 -080082 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62,
83 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070084 0xF9, 0x03, 0xFF, // Largest half-precision subnormal 0.0000609755516
85 0x6F,
86 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
87 0x72, 0x6D, 0x61, 0x6C,
88 0xF9, 0x04, 0x00, // Smallest half-precision normal 0.000061988
Laurence Lundblade68a13352018-09-23 02:19:54 -070089 0x70,
Laurence Lundbladeee851742020-01-08 08:37:05 -080090 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x73,
91 0x69, 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade68a13352018-09-23 02:19:54 -070092 0xF9, 0x00, 0x00,
93 0x03,
Laurence Lundblade7d40d812018-09-30 02:44:01 -070094 0xF9, 0xC0, 0x00, // -2
95 0x04,
96 0xF9, 0x7E, 0x00, // qNaN
97 0x05,
98 0xF9, 0x7C, 0x01, // sNaN
99 0x06,
100 0xF9, 0x7E, 0x0F, // qNaN with payload 0x0f
101 0x07,
102 0xF9, 0x7C, 0x0F, // sNaN with payload 0x0f
Laurence Lundblade68a13352018-09-23 02:19:54 -0700103};
104
105
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700106inline static bool CheckDouble(double d, uint64_t u)
107{
108 return UsefulBufUtil_CopyDoubleToUint64(d) != u;
109}
110
111
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800112int32_t HalfPrecisionDecodeBasicTests()
Laurence Lundblade68a13352018-09-23 02:19:54 -0700113{
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700114 UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800115
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700116 QCBORDecodeContext DC;
117 QCBORDecode_Init(&DC, HalfPrecision, 0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800118
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700119 QCBORItem Item;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700120
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700121 QCBORDecode_GetNext(&DC, &Item);
122 if(Item.uDataType != QCBOR_TYPE_MAP) {
123 return -1;
124 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700125
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700126 QCBORDecode_GetNext(&DC, &Item);
127 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0) {
128 return -2;
129 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800130
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700131 QCBORDecode_GetNext(&DC, &Item);
132 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
133 return -3;
134 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700135
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700136 QCBORDecode_GetNext(&DC, &Item);
137 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -INFINITY) {
138 return -4;
139 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700140
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700141 // TODO: NAN-related is this really converting right? It is carrying
142 // payload, but this confuses things.
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700143 QCBORDecode_GetNext(&DC, &Item);
144 if(Item.uDataType != QCBOR_TYPE_DOUBLE || !isnan(Item.val.dfnum)) {
145 return -5;
146 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700147
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700148 QCBORDecode_GetNext(&DC, &Item);
149 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 1.0) {
150 return -6;
151 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800152
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700153 // Approximately 1/3
154 QCBORDecode_GetNext(&DC, &Item);
155 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.333251953125) {
156 return -7;
157 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700158
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700159 // Largest half-precision
160 QCBORDecode_GetNext(&DC, &Item);
161 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 65504.0) {
162 return -8;
163 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700164
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700165 QCBORDecode_GetNext(&DC, &Item);
166 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
167 return -9;
168 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800169
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700170 // Smallest half-precision subnormal
171 QCBORDecode_GetNext(&DC, &Item);
172 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00000005960464477539063) {
173 return -10;
174 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700175
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700176 // Largest half-precision subnormal
177 QCBORDecode_GetNext(&DC, &Item);
178 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00006097555160522461) {
179 return -11;
180 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700181
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700182 // Smallest half-precision normal
183 QCBORDecode_GetNext(&DC, &Item);
184 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00006103515625) {
185 return -12;
186 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800187
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700188 // half-precision zero
189 QCBORDecode_GetNext(&DC, &Item);
190 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0) {
191 return -13;
192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800193
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700194 // negative 2
195 QCBORDecode_GetNext(&DC, &Item);
196 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -2.0) {
197 return -14;
198 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800199
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700200 // TODO: NAN-related double check these four tests
201 QCBORDecode_GetNext(&DC, &Item); // qNaN
202 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700203 CheckDouble(Item.val.dfnum, 0x7ff8000000000000ULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700204 return -15;
205 }
206 QCBORDecode_GetNext(&DC, &Item); // sNaN
207 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700208 CheckDouble(Item.val.dfnum, 0x7ff0000000000001ULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700209 return -16;
210 }
211 QCBORDecode_GetNext(&DC, &Item); // qNaN with payload 0x0f
212 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700213 CheckDouble(Item.val.dfnum, 0x7ff800000000000fULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700214 return -17;
215 }
216 QCBORDecode_GetNext(&DC, &Item); // sNaN with payload 0x0f
217 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700218 CheckDouble(Item.val.dfnum, 0x7ff000000000000fULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700219 return -18;
220 }
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700221
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700222 if(QCBORDecode_Finish(&DC)) {
223 return -19;
224 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800225
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700226 return 0;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700227}
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700228
229
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700230
231
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800232int32_t HalfPrecisionAgainstRFCCodeTest()
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700233{
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700234 for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700235 unsigned char x[2];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800236 x[1] = (uint8_t)(uHalfP & 0xff);
237 x[0] = (uint8_t)(uHalfP >> 8); // uHalfP is always less than 0xffff
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700238 double d = decode_half(x);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800239
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700240 // Contruct the CBOR for the half-precision float by hand
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530241 UsefulBuf_MAKE_STACK_UB(__xx, 3);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700242 UsefulOutBuf UOB;
243 UsefulOutBuf_Init(&UOB, __xx);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800244
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800245 const uint8_t uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); // 0xf9
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700246 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); // The initial byte for a half-precision float
247 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP);
248
Laurence Lundbladeee851742020-01-08 08:37:05 -0800249 // Now parse the hand-constructed CBOR. This will invoke the
250 // conversion to a float
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700251 QCBORDecodeContext DC;
252 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800253
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700254 QCBORItem Item;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800255
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700256 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700257 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700258 return -1;
259 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800260
Laurence Lundbladeee851742020-01-08 08:37:05 -0800261 //printf("%04x QCBOR:%15.15f RFC: %15.15f (%8x)\n",
262 // uHalfP, Item.val.fnum, d , UsefulBufUtil_CopyFloatToUint32(d));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800263
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700264 if(isnan(d)) {
265 // The RFC code uses the native instructions which may or may not
266 // handle sNaN, qNaN and NaN payloads correctly. This test just
267 // makes sure it is a NaN and doesn't worry about the type of NaN
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700268 if(!isnan(Item.val.dfnum)) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700269 return -3;
270 }
271 } else {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700272 if(Item.val.dfnum != d) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700273 return -2;
274 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700275 }
276 }
277 return 0;
278}
279
280
281/*
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700282 Expected output from preferred serialization of some of floating-point numbers
283{"zero": 0.0,
284 "negative zero": -0.0,
285 "infinitity": Infinity,
286 "negative infinitity": -Infinity,
287 "NaN": NaN,
288 "one": 1.0,
289 "one third": 0.333251953125,
290 "largest half-precision": 65504.0,
291 "largest half-precision point one": 65504.1,
292 "too-large half-precision": 65536.0,
293 "smallest half subnormal": 5.960464477539063e-8,
294 "smallest half normal": 0.00006103515625,
295 "smallest half normal plus": 0.00006103515625000001,
296 "smallest normal minus": 0.000030517578125,
297 "largest single": 3.4028234663852886e+38,
298 "largest single plus": 6.805646932770577e+38,
299 "smallest single": 1.1754943508222875e-38,
300 "smallest single plus": 1.1754943508222878e-38,
301 "smallest single minus": 1.1754943508222874e-38,
302 "smallest single minus more": 5.877471754111438e-39,
303 3: -2.0, "single precision": 16777216.0,
304 "single with precision loss": 16777217.0,
305 1: "fin"}
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700306 */
Laurence Lundbladebb474be2018-10-22 11:53:21 +0530307static const uint8_t spExpectedSmallest[] = {
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700308 0xB8, 0x1A,
309 0x64, 0x7A, 0x65, 0x72, 0x6F,
310 0xF9, 0x00, 0x00,
311
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700312 0x6D, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A,
313 0x65, 0x72, 0x6F,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700314 0xF9, 0x80, 0x00,
315
316 0x6A, 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
317 0xF9, 0x7C, 0x00,
318
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700319 0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69,
320 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700321 0xF9, 0xFC, 0x00,
322
323 0x63, 0x4E, 0x61, 0x4E,
324 0xF9, 0x7E, 0x00,
325
326 0x63, 0x6F, 0x6E, 0x65,
327 0xF9, 0x3C, 0x00,
328
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700329 0x69, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700330 0xF9, 0x35, 0x55,
331
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700332 0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61,
333 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
334 0x6F, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700335 0xF9, 0x7B, 0xFF,
336
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700337 0x78, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68,
338 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73,
339 0x69, 0x6F, 0x6E, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20,
340 0x6F, 0x6E, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700341 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33,
342
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700343 0x78, 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65,
344 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63,
345 0x69, 0x73, 0x69, 0x6F, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700346 0xFA, 0x47, 0x80, 0x00, 0x00,
347
348 0x77, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74,
349 0x20, 0x68, 0x61, 0x6C, 0x66, 0x20, 0x73, 0x75, 0x62, 0x6E,
350 0x6F, 0x72, 0x6D, 0x61, 0x6C,
351 0xFA, 0x33, 0x80, 0x00, 0x00,
352
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700353 0x74, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x68,
354 0x61, 0x6C, 0x66, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700355 0xF9, 0x04, 0x00,
356
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700357 0x78, 0x19, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
358 0x68, 0x61, 0x6C, 0x66, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61,
359 0x6C, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700360 0xFB, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
361
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700362 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E,
363 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700364 0x75, 0x73,
365 0xFB, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
366
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700367 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E,
368 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6E, 0x75,
369 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700370 0xFA, 0x38, 0x00, 0x00, 0x00,
371
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700372 0x6E, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
373 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700374 0xFA, 0x7F, 0x7F, 0xFF, 0xFF,
375
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700376 0x73, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
377 0x6E,0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700378 0xFB, 0x47, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01,
379
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700380 0x73, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
381 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700382 0xFB, 0x47, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
383
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700384 0x6F, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
385 0x69, 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700386 0xFA, 0x00, 0x80, 0x00, 0x00,
387
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700388 0x74, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
389 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700390 0xFB, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
391
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700392 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
393 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x6D, 0x69, 0x6E, 0x75,
394 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700395 0xFB, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
396
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700397 0x78, 0x1A, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
398 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x6D, 0x69, 0x6E,
399 0x75, 0x73, 0x20, 0x6D, 0x6F, 0x72, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700400 0xFB, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401
402 0x03,
403 0xF9, 0xC0, 0x00,
404
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700405 0x70, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x72, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700406 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
407 0xFA, 0x4B, 0x80, 0x00, 0x00,
408
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700409 0x78, 0x1A, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69,
410 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
411 0x6F, 0x6E, 0x20, 0x6C, 0x6F, 0x73, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700412 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
413
414 0x01,
415 0x63, 0x66, 0x69, 0x6E
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700416};
417
418
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700419/*
420 Makes a double from a uint64_t by copying the bits, not
421 by converting the value.
422 */
423#define MAKE_DOUBLE(x) UsefulBufUtil_CopyUint64ToDouble(x)
424
425
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800426int32_t DoubleAsSmallestTest()
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700427{
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700428 UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, sizeof(spExpectedSmallest));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800429
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700430 QCBOREncodeContext EC;
431 QCBOREncode_Init(&EC, EncodedHalfsMem);
432 QCBOREncode_OpenMap(&EC);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800433
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700434 // Many of these are from
435 // https://en.wikipedia.org/wiki/Half-precision_floating-point_format
436 // and
437 // https://en.wikipedia.org/wiki/Single-precision_floating-point_format
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800438
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700439 // F9 0000 # primitive(0)
440 QCBOREncode_AddDoubleToMap(&EC, "zero", 0.00);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700441
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700442 // F9 8000 # primitive(0)
443 QCBOREncode_AddDoubleToMap(&EC, "negative zero", -0.00);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800444
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700445 // F9 7C00 # primitive(31744)
446 QCBOREncode_AddDoubleToMap(&EC, "infinitity", INFINITY);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800447
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700448 // F9 FC00 # primitive(64512)
449 QCBOREncode_AddDoubleToMap(&EC, "negative infinitity", -INFINITY);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800450
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700451 // F9 7E00 # primitive(32256)
452 QCBOREncode_AddDoubleToMap(&EC, "NaN", NAN);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800453
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700454 // TODO: test a few NaN variants
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800455
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700456 // F9 3C00 # primitive(15360)
457 QCBOREncode_AddDoubleToMap(&EC, "one", 1.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800458
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700459 // F9 3555 # primitive(13653)
460 QCBOREncode_AddDoubleToMap(&EC, "one third", 0.333251953125);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800461
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700462 // 65504.0, converts to the large possible half-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700463 // 0xF9, 0x7B, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700464 QCBOREncode_AddDoubleToMap(&EC, "largest half-precision", 65504.0);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700465
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700466 // 65504.1, the double that has both to large an exponent and too
467 // much precision, so no conversion.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700468 // 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700469 QCBOREncode_AddDoubleToMap(&EC, "largest half-precision point one", 65504.1);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800470
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700471 // 65536.0 has an exponent of 16, which is larger than 15, the
472 // largest half-precision exponent. It is the exponent, not
473 // precision loss that prevents conversion to half. It does convert
474 // to single precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700475 // 0xFA, 0x47, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700476 QCBOREncode_AddDoubleToMap(&EC, "too-large half-precision", 65536.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800477
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700478 // 5.9604644775390625E-8, the smallest possible half-precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700479 // subnormal, digitis are lost converting to half, but not
480 // when converting to a single
481 // 0xFA, 0x33, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700482 QCBOREncode_AddDoubleToMap(&EC,
483 "smallest half subnormal",
484 MAKE_DOUBLE(0x3e70000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800485
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700486 // 0.00006103515625, the double value that converts to the smallest
487 // possible half-precision normal. which is what should appear in
488 // the output.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700489 // 0xF9, 0x04, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700490 QCBOREncode_AddDoubleToMap(&EC,
491 "smallest half normal",
492 MAKE_DOUBLE(0x3f10000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800493
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700494 // 0.000061035156250000014 ,the double value that is a tiny bit
495 // greater than smallest possible half-precision normal. It will be
496 // output as a double because converting it will reduce precision.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700497 // 0xFB, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700498 QCBOREncode_AddDoubleToMap(&EC,
499 "smallest half normal plus",
500 MAKE_DOUBLE(0x3f10000000000001));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800501
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700502 // 0.000061035156249999993, the double value that is a tiny bit
503 // smaller than the smallest half-precision normal. This will fail
504 // to convert to a half-precision because both the exponent is too
505 // small and the precision is too large for a half-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700506 // 0xFB, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700507 QCBOREncode_AddDoubleToMap(&EC,
508 "smallest normal minus",
509 MAKE_DOUBLE(0x3f0fffffffffffff));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800510
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700511 // 0.000030517578125, the double value that is too small to fit
512 // into a half-precision because the exponent won't fit, not
513 // because precision would be lost. (This would fit into a
514 // half-precision subnormal, but there is no converstion to
515 // that). This ends up encoded as a single-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700516 // 0xFA, 0x38, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700517 QCBOREncode_AddDoubleToMap(&EC,
518 "smallest normal minus",
519 MAKE_DOUBLE(0x3f00000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800520
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700521 // 3.4028234664e38, the value that converts to the largest possible
522 // single-precision.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700523 // 0xFA, 0x7F, 0x7F, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700524 QCBOREncode_AddDoubleToMap(&EC,
525 "largest single",
526 MAKE_DOUBLE(0x47efffffe0000000));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700527
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700528 // 3.402823466385289E38, sightly larger than the largest possible
529 // possible precision. Conversion fails because precision would be
530 // lost.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700531 // 0xFB, 0x47, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700532 QCBOREncode_AddDoubleToMap(&EC,
533 "largest single plus",
534 MAKE_DOUBLE(0x47efffffe0000001));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700535
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700536 // 6.8056469327705772E38, slightly more larger than the largers
537 // possible single precision. Conversion fails because exponent is
538 // too large.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700539 // 0xFB, 0x47, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700540 QCBOREncode_AddDoubleToMap(&EC,
541 "largest single plus",
542 MAKE_DOUBLE(0x47ffffffe0000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800543
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700544 // 1.1754943508222875E-38, The double value that converts to the
545 // smallest possible single-precision normal
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700546 // 0xFA, 0x00, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700547 QCBOREncode_AddDoubleToMap(&EC,
548 "smallest single",
549 MAKE_DOUBLE(0x3810000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800550
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700551 // 1.1754943508222878E-38, double value that is slightly larger
552 // than the smallest single-precision normal. Conversion fails
553 // because of precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700554 // 0xFB, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700555 QCBOREncode_AddDoubleToMap(&EC,
556 "smallest single plus",
557 MAKE_DOUBLE(0x3810000000000001));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700558
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700559 // 1.1754943508222874E-38, slightly smaller than the smallest
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700560 // single-precision normal. Conversion fails because of precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700561 // 0xFB, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700562 QCBOREncode_AddDoubleToMap(&EC,
563 "smallest single minus",
564 MAKE_DOUBLE(0x380fffffffffffff));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800565
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700566 // 5.8774717541114375E-39, slightly smaller than the smallest
567 // single-precision normal. Conversion fails because the exponent
568 // is too small.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700569 // 0xFB, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700570 QCBOREncode_AddDoubleToMap(&EC,
571 "smallest single minus more",
572 MAKE_DOUBLE(0x3800000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800573
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700574 // Just -2, which converts to a negative half-precision
575 // F9 C000 # primitive(49152)
576 QCBOREncode_AddDoubleToMapN(&EC, 3, -2.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800577
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700578 // 16777216, No precision loss converting to single
579 // FA 4B800000 # primitive(1266679808)
580 QCBOREncode_AddDoubleToMap(&EC, "single precision", 16777216);
581
582 // 16777217, One more than above. Too much precision for a single
583 // so no conversion.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700584 // 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700585 QCBOREncode_AddDoubleToMap(&EC, "single with precision loss", 16777217);
586
587 // Just a convenient marker when cutting and pasting encoded CBOR
588 QCBOREncode_AddSZStringToMapN(&EC, 1, "fin");
589
590 QCBOREncode_CloseMap(&EC);
591
592 UsefulBufC EncodedHalfs;
593 QCBORError uErr = QCBOREncode_Finish(&EC, &EncodedHalfs);
594 if(uErr) {
595 return -1;
596 }
597
598 if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) {
599 return -3;
600 }
601
602 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800603}
Laurence Lundblade585127a2020-07-15 03:25:24 -0700604#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700605
606
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700607/*
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700608[0.0, // Half
609 3.14, // Double
610 0.0, // Double
611 NaN, // Double
612 Infinity, // Double
613 0.0, // Half
614 3.140000104904175, // Single
615 0.0, // Single
616 NaN, // Single
617 Infinity, // Single
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700618 {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
619 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
620 */
621static const uint8_t spExpectedFloats[] = {
622 0x8B,
623 0xF9, 0x00, 0x00,
624 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
625 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0xF9, 0x00, 0x00,
629 0xFA, 0x40, 0x48, 0xF5, 0xC3,
630 0xFA, 0x00, 0x00, 0x00, 0x00,
631 0xFA, 0x7F, 0xC0, 0x00, 0x00,
632 0xFA, 0x7F, 0x80, 0x00, 0x00,
633 0xA8,
634 0x18, 0x64,
635 0xF9, 0x00, 0x00,
636 0x18, 0x65,
637 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
638 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
639 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
640 0x18, 0x69,
641 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642 0x18, 0x66,
643 0xF9, 0x00, 0x00,
644 0x18, 0x67,
645 0xFA, 0x40, 0x49, 0x0F, 0xDA,
646 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
647 0xFA, 0x40, 0x2D, 0xF8, 0x54,
648 0x18, 0x6A,
649 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700650
651static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700652 0x8B,
653 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
655 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0xFA, 0x00, 0x00, 0x00, 0x00,
659 0xFA, 0x40, 0x48, 0xF5, 0xC3,
660 0xFA, 0x00, 0x00, 0x00, 0x00,
661 0xFA, 0x7F, 0xC0, 0x00, 0x00,
662 0xFA, 0x7F, 0x80, 0x00, 0x00,
663 0xA8,
664 0x18, 0x64,
665 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x18, 0x65,
667 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
668 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
669 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
670 0x18, 0x69,
671 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 0x18, 0x66,
673 0xFA, 0x00, 0x00, 0x00, 0x00,
674 0x18, 0x67,
675 0xFA, 0x40, 0x49, 0x0F, 0xDA,
676 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
677 0xFA, 0x40, 0x2D, 0xF8, 0x54,
678 0x18, 0x6A,
679 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700680
681int32_t GeneralFloatEncodeTests()
682{
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700683 UsefulBufC ExpectedFloats;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700684#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700685 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700686 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700687 (void)spExpectedFloatsNoHalf; // Avoid unused variable error
688#else
689 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700690 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700691 (void)spExpectedFloats; // Avoid unused variable error
692#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700693
694 QCBOREncodeContext EC;
695 QCBOREncode_Init(&EC, OutBuffer);
696 QCBOREncode_OpenArray(&EC);
697
698 QCBOREncode_AddDouble(&EC, 0.0);
699 QCBOREncode_AddDouble(&EC, 3.14);
700 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
701 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
702 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
703
704 QCBOREncode_AddFloat(&EC, 0.0);
705 QCBOREncode_AddFloat(&EC, 3.14f);
706 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
707 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
708 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
709
710 QCBOREncode_OpenMap(&EC);
711
712 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
713 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
714 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
715 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
716
717 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
718 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
719 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
720 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
721
722 QCBOREncode_CloseMap(&EC);
723 QCBOREncode_CloseArray(&EC);
724
725 UsefulBufC Encoded;
726 QCBORError uErr = QCBOREncode_Finish(&EC, &Encoded);
727 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700728 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700729 }
730
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700731 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700732 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700733 }
734
735 return 0;
736}
737
738
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700739/* returns 0 if equivalent, non-zero if not equivalent */
740static int CHECK_EXPECTED_DOUBLE(double val, double expected)
741{
742 double diff = val - expected;
743
744 diff = fabs(diff);
745
746 if(diff > 0.000001) {
747 return 1;
748 } else {
749 return 0;
750 }
751}
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700752
753
754int32_t GeneralFloatDecodeTests()
755{
756 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
757
758 QCBORDecodeContext DC;
759 QCBORDecode_Init(&DC, TestData, 0);
760
761 QCBORItem Item;
762 QCBORError uErr;
763
764 QCBORDecode_GetNext(&DC, &Item);
765 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
766 return -1;
767 }
768
769#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
770 uErr = QCBORDecode_GetNext(&DC, &Item);
771 if(uErr != QCBOR_SUCCESS ||
772 Item.uDataType != QCBOR_TYPE_DOUBLE ||
773 Item.val.dfnum != 0.0) {
774 return -2;
775 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700776#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700777 uErr = QCBORDecode_GetNext(&DC, &Item);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700778 if(uErr != QCBOR_ERR_HALF_PRECISION_DISABLED) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700779 return -3;
780 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700781#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700782
783 uErr = QCBORDecode_GetNext(&DC, &Item);
784 if(uErr != QCBOR_SUCCESS ||
785 Item.uDataType != QCBOR_TYPE_DOUBLE ||
786 Item.val.dfnum != 3.14) {
787 return -4;
788 }
789
790 uErr = QCBORDecode_GetNext(&DC, &Item);
791 if(uErr != QCBOR_SUCCESS ||
792 Item.uDataType != QCBOR_TYPE_DOUBLE ||
793 Item.val.dfnum != 0.0) {
794 return -5;
795 }
796
797 uErr = QCBORDecode_GetNext(&DC, &Item);
798 if(uErr != QCBOR_SUCCESS ||
799 Item.uDataType != QCBOR_TYPE_DOUBLE ||
800 !isnan(Item.val.dfnum)) {
801 return -6;
802 }
803
804 uErr = QCBORDecode_GetNext(&DC, &Item);
805 if(uErr != QCBOR_SUCCESS ||
806 Item.uDataType != QCBOR_TYPE_DOUBLE ||
807 Item.val.dfnum != INFINITY) {
808 return -7;
809 }
810
811#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700812 // Tests for normal config
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700813 uErr = QCBORDecode_GetNext(&DC, &Item);
814 if(uErr != QCBOR_SUCCESS ||
815 Item.uDataType != QCBOR_TYPE_DOUBLE ||
816 Item.val.dfnum != 0.0) {
817 return -8;
818 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700819#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
820 // Tests for preferred serialization turned off
821 uErr = QCBORDecode_GetNext(&DC, &Item);
822 if(uErr != QCBOR_ERR_HALF_PRECISION_DISABLED) {
823 return -13;
824 }
825#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700826
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700827#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700828 uErr = QCBORDecode_GetNext(&DC, &Item);
829 if(uErr != QCBOR_SUCCESS ||
830 Item.uDataType != QCBOR_TYPE_DOUBLE ||
831 CHECK_EXPECTED_DOUBLE(3.14, Item.val.dfnum)) {
832 return -9;
833 }
834
835 uErr = QCBORDecode_GetNext(&DC, &Item);
836 if(uErr != QCBOR_SUCCESS ||
837 Item.uDataType != QCBOR_TYPE_DOUBLE ||
838 Item.val.dfnum != 0.0) {
839 return -10;
840 }
841
842 uErr = QCBORDecode_GetNext(&DC, &Item);
843 if(uErr != QCBOR_SUCCESS ||
844 Item.uDataType != QCBOR_TYPE_DOUBLE ||
845 !isnan(Item.val.dfnum)) {
846 return -11;
847 }
848
849 uErr = QCBORDecode_GetNext(&DC, &Item);
850 if(uErr != QCBOR_SUCCESS ||
851 Item.uDataType != QCBOR_TYPE_DOUBLE ||
852 Item.val.dfnum != INFINITY) {
853 return -12;
854 }
855
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700856#else /* QCBOR_DISABLE_FLOAT_HW_USE */
857 // Tests for floating point HW use disabled
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700858 uErr = QCBORDecode_GetNext(&DC, &Item);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700859 if(uErr != QCBOR_SUCCESS ||
860 Item.uDataType != QCBOR_TYPE_FLOAT ||
861 CHECK_EXPECTED_DOUBLE(3.14, Item.val.fnum)) {
862 return -9;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700863 }
864
865 uErr = QCBORDecode_GetNext(&DC, &Item);
866 if(uErr != QCBOR_SUCCESS ||
867 Item.uDataType != QCBOR_TYPE_FLOAT ||
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700868 Item.val.fnum != 0.0) {
869 return -10;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700870 }
871
872 uErr = QCBORDecode_GetNext(&DC, &Item);
873 if(uErr != QCBOR_SUCCESS ||
874 Item.uDataType != QCBOR_TYPE_FLOAT ||
875 !isnan(Item.val.fnum)) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700876 return -11;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700877 }
878
879 uErr = QCBORDecode_GetNext(&DC, &Item);
880 if(uErr != QCBOR_SUCCESS ||
881 Item.uDataType != QCBOR_TYPE_FLOAT ||
882 Item.val.fnum != INFINITY) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700883 return -12;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700884 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700885#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
886
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700887 /* Sufficent test coverage. Don't need to decode the rest */
888
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700889
890 // Now tests for spiffy decode
891 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
892 double d;
893 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -0700894 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700895
896#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
897#ifndef QCBOR_DISABLE_FLOAT_HW_USE
898 // Spiffy decode tests for normal full float support
899 QCBORDecode_GetDouble(&DC, &d);
900 uErr = QCBORDecode_GetAndResetError(&DC);
901 if(uErr != QCBOR_SUCCESS ||
902 d != 0.0) {
903 return -100;
904 }
905
906 QCBORDecode_GetDouble(&DC, &d);
907 uErr = QCBORDecode_GetAndResetError(&DC);
908 if(uErr != QCBOR_SUCCESS ||
909 d != 3.14) {
910 return -101;
911 }
912
913 QCBORDecode_GetDouble(&DC, &d);
914 uErr = QCBORDecode_GetAndResetError(&DC);
915 if(uErr != QCBOR_SUCCESS ||
916 d != 0.0) {
917 return -102;
918 }
919
920 QCBORDecode_GetDouble(&DC, &d);
921 uErr = QCBORDecode_GetAndResetError(&DC);
922 if(uErr != QCBOR_SUCCESS ||
923 !isnan(d)) {
924 return -103;
925 }
926
927 QCBORDecode_GetDouble(&DC, &d);
928 uErr = QCBORDecode_GetAndResetError(&DC);
929 if(uErr != QCBOR_SUCCESS ||
930 d != INFINITY) {
931 return -104;
932 }
933
934 QCBORDecode_GetDouble(&DC, &d);
935 uErr = QCBORDecode_GetAndResetError(&DC);
936 if(uErr != QCBOR_SUCCESS ||
937 d != 0.0) {
938 return -105;
939 }
940
941 QCBORDecode_GetDouble(&DC, &d);
942 uErr = QCBORDecode_GetAndResetError(&DC);
943 if(uErr != QCBOR_SUCCESS ||
944 d != 3.140000104904175) {
945 return -106;
946 }
947
948 QCBORDecode_GetDouble(&DC, &d);
949 uErr = QCBORDecode_GetAndResetError(&DC);
950 if(uErr != QCBOR_SUCCESS ||
951 d != 0.0) {
952 return -107;
953 }
954
955 QCBORDecode_GetDouble(&DC, &d);
956 uErr = QCBORDecode_GetAndResetError(&DC);
957 if(uErr != QCBOR_SUCCESS ||
958 !isnan(d)) {
959 return -108;
960 }
961
962 QCBORDecode_GetDouble(&DC, &d);
963 uErr = QCBORDecode_GetAndResetError(&DC);
964 if(uErr != QCBOR_SUCCESS ||
965 d != INFINITY) {
966 return -109;
967 }
968#else /* QCBOR_DISABLE_FLOAT_HW_USE */
969 // Spiffy decode tests for float HW disabled
970 QCBORDecode_GetDouble(&DC, &d);
971 uErr = QCBORDecode_GetAndResetError(&DC);
972 if(uErr != QCBOR_SUCCESS ||
973 d != 0.0) {
974 return -200;
975 }
976
977 QCBORDecode_GetDouble(&DC, &d);
978 uErr = QCBORDecode_GetAndResetError(&DC);
979 if(uErr != QCBOR_SUCCESS ||
980 d != 3.14) {
981 return -201;
982 }
983
984 QCBORDecode_GetDouble(&DC, &d);
985 uErr = QCBORDecode_GetAndResetError(&DC);
986 if(uErr != QCBOR_SUCCESS ||
987 d != 0.0) {
988 return -202;
989 }
990
991 QCBORDecode_GetDouble(&DC, &d);
992 uErr = QCBORDecode_GetAndResetError(&DC);
993 if(uErr != QCBOR_SUCCESS ||
994 !isnan(d)) {
995 return -203;
996 }
997
998 QCBORDecode_GetDouble(&DC, &d);
999 uErr = QCBORDecode_GetAndResetError(&DC);
1000 if(uErr != QCBOR_SUCCESS ||
1001 d != INFINITY) {
1002 return -204;
1003 }
1004
1005 QCBORDecode_GetDouble(&DC, &d);
1006 uErr = QCBORDecode_GetAndResetError(&DC);
1007 if(uErr != QCBOR_SUCCESS ||
1008 d != 0.0) {
1009 return -205;
1010 }
1011
1012 QCBORDecode_GetDouble(&DC, &d);
1013 uErr = QCBORDecode_GetAndResetError(&DC);
1014 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED) {
1015 return -206;
1016 }
1017
1018 QCBORDecode_GetDouble(&DC, &d);
1019 uErr = QCBORDecode_GetAndResetError(&DC);
1020 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED) {
1021 return -207;
1022 }
1023
1024 QCBORDecode_GetDouble(&DC, &d);
1025 uErr = QCBORDecode_GetAndResetError(&DC);
1026 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED ) {
1027 return -208;
1028 }
1029
1030 QCBORDecode_GetDouble(&DC, &d);
1031 uErr = QCBORDecode_GetAndResetError(&DC);
1032 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED ) {
1033 return -209;
1034 }
1035
1036
1037#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1038#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
1039 // Spiffy decode tests for half-precision disabled
1040 QCBORDecode_GetDouble(&DC, &d);
1041 uErr = QCBORDecode_GetAndResetError(&DC);
1042 if(uErr != QCBOR_ERR_HALF_PRECISION_DISABLED) {
1043 return -300;
1044 }
1045
1046 QCBORDecode_GetDouble(&DC, &d);
1047 uErr = QCBORDecode_GetAndResetError(&DC);
1048 if(uErr != QCBOR_SUCCESS ||
1049 d != 3.14) {
1050 return -301;
1051 }
1052
1053 QCBORDecode_GetDouble(&DC, &d);
1054 uErr = QCBORDecode_GetAndResetError(&DC);
1055 if(uErr != QCBOR_SUCCESS ||
1056 d != 0.0) {
1057 return -302;
1058 }
1059
1060 QCBORDecode_GetDouble(&DC, &d);
1061 uErr = QCBORDecode_GetAndResetError(&DC);
1062 if(uErr != QCBOR_SUCCESS ||
1063 !isnan(d)) {
1064 return -303;
1065 }
1066
1067 QCBORDecode_GetDouble(&DC, &d);
1068 uErr = QCBORDecode_GetAndResetError(&DC);
1069 if(uErr != QCBOR_SUCCESS ||
1070 d != INFINITY) {
1071 return -304;
1072 }
1073
1074 QCBORDecode_GetDouble(&DC, &d);
1075 uErr = QCBORDecode_GetAndResetError(&DC);
1076 if(uErr != QCBOR_ERR_HALF_PRECISION_DISABLED) {
1077 return -305;
1078 }
1079
1080 QCBORDecode_GetDouble(&DC, &d);
1081 uErr = QCBORDecode_GetAndResetError(&DC);
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001082#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001083 if(uErr != QCBOR_SUCCESS ||
1084 d != 3.140000104904175) {
1085 return -306;
1086 }
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001087#else
1088 // Disabled use of HW to convert from single to double
1089 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED) {
1090 return -316;
1091 }
1092#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1093
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001094
1095 QCBORDecode_GetDouble(&DC, &d);
1096 uErr = QCBORDecode_GetAndResetError(&DC);
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001097#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001098 if(uErr != QCBOR_SUCCESS ||
1099 d != 0.0) {
1100 return -307;
1101 }
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001102#else
1103 // Disabled use of HW to convert from single to double
1104 if(uErr == QCBOR_SUCCESS) {
1105 return -317;
1106 }
1107#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1108
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001109
1110 QCBORDecode_GetDouble(&DC, &d);
1111 uErr = QCBORDecode_GetAndResetError(&DC);
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001112#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001113 if(uErr != QCBOR_SUCCESS ||
1114 !isnan(d)) {
1115 return -308;
1116 }
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001117#else
1118 // Disabled use of HW to convert from single to double
1119 if(uErr == QCBOR_SUCCESS) {
1120 return -318;
1121 }
1122#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001123
1124 QCBORDecode_GetDouble(&DC, &d);
1125 uErr = QCBORDecode_GetAndResetError(&DC);
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001126#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001127 if(uErr != QCBOR_SUCCESS ||
1128 d != INFINITY) {
1129 return -309;
1130 }
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001131#else
1132 // Disabled use of HW to convert from single to double
1133 if(uErr == QCBOR_SUCCESS) {
1134 return -318;
1135 }
1136#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001137#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
1138
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001139 return 0;
1140}
1141
1142
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001143
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001144#ifdef NAN_EXPERIMENT
1145/*
1146 Code for checking what the double to float cast does with
1147 NaNs. Not run as part of tests. Keep it around to
1148 be able to check various platforms and CPUs.
1149 */
1150
1151#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1152#define DOUBLE_NUM_EXPONENT_BITS (11)
1153#define DOUBLE_NUM_SIGN_BITS (1)
1154
1155#define DOUBLE_SIGNIFICAND_SHIFT (0)
1156#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1157#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1158
1159#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1160#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1161#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1162#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1163
1164
1165static int NaNExperiments() {
1166 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1167 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1168 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001169
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001170 float f1 = (float)dqNaN;
1171 float f2 = (float)dsNaN;
1172 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001173
1174
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001175 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1176 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1177 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001178
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001179 // Result of this on x86 is that every NaN is a qNaN. The intel
1180 // CVTSD2SS instruction ignores the NaN payload and even converts
1181 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001182
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001183 return 0;
1184}
Laurence Lundblade1ddc1f22020-12-06 05:29:05 -08001185#endif /* NAN_EXPERIMENT */