blob: 2bf5fad311b7aae6c4ea3c8b07fa1515bae8038e [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.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005 Copyright (c) 2021, Arm Limited. All rights reserved.
Laurence Lundblade035bd782019-01-21 17:01:31 -08006
Laurence Lundbladea3fd49f2019-01-21 10:16:22 -08007 SPDX-License-Identifier: BSD-3-Clause
Laurence Lundblade035bd782019-01-21 17:01:31 -08008
Laurence Lundbladea3fd49f2019-01-21 10:16:22 -08009 See BSD-3-Clause license in README.md
Laurence Lundblade035bd782019-01-21 17:01:31 -080010
Laurence Lundbladea3fd49f2019-01-21 10:16:22 -080011 Created on 9/19/18
Laurence Lundbladeee851742020-01-08 08:37:05 -080012 =============================================================================*/
Laurence Lundblade68a13352018-09-23 02:19:54 -070013
Laurence Lundblade2aa0b572020-07-16 19:48:42 -070014
15#include "float_tests.h"
Laurence Lundblade585127a2020-07-15 03:25:24 -070016#include "qcbor/qcbor_encode.h"
Laurence Lundblade02fcf312020-07-17 02:49:46 -070017#include "qcbor/qcbor_decode.h"
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -070018#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade585127a2020-07-15 03:25:24 -070019#include <math.h> // For INFINITY and NAN and isnan()
20
Laurence Lundblade16a207a2021-09-18 17:22:46 -070021
22/* Make a test results code that includes three components
23 * Return code is
24 * xxxyyyzzz where zz is the error code, yy is the test number and zz is
25 * check being performed
26 */
27static inline int32_t MakeTestResultCode(uint32_t uTestCase,
28 uint32_t uTestNumber,
29 QCBORError uErrorCode)
30{
31 uint32_t uCode = (uTestCase * 1000000) +
32 (uTestNumber * 1000) +
33 (uint32_t)uErrorCode;
34 return (int32_t)uCode;
35}
36
37
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -070038#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -070039
Laurence Lundbladed711fb22018-09-26 14:35:22 -070040#include "half_to_double_from_rfc7049.h"
Laurence Lundblade68a13352018-09-23 02:19:54 -070041
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080042
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070043/*
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -070044 Half-precision values that are input to test half-precision decoding
45
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070046 As decoded by http://cbor.me
47 {"zero": 0.0,
48 "infinitity": Infinity,
49 "negative infinitity": -Infinity,
50 "NaN": NaN,
51 "one": 1.0,
52 "one third": 0.333251953125,
53 "largest half-precision": 65504.0,
54 "too-large half-precision": Infinity,
55 "smallest subnormal": 5.960464477539063e-8,
56 "smallest normal": 0.00006097555160522461,
57 "biggest subnormal": 0.00006103515625,
58 "subnormal single": 0.0,
59 3: -2.0,
60 4: NaN,
61 5: NaN,
62 6: NaN,
63 7: NaN}
64 */
Laurence Lundbladebb474be2018-10-22 11:53:21 +053065static const uint8_t spExpectedHalf[] = {
Laurence Lundblade7d40d812018-09-30 02:44:01 -070066 0xB1,
Laurence Lundblade68a13352018-09-23 02:19:54 -070067 0x64,
68 0x7A, 0x65, 0x72, 0x6F,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070069 0xF9, 0x00, 0x00, // half-precision 0.000
Laurence Lundblade68a13352018-09-23 02:19:54 -070070 0x6A,
71 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070072 0xF9, 0x7C, 0x00, // Infinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070073 0x73,
Laurence Lundbladeee851742020-01-08 08:37:05 -080074 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E,
75 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070076 0xF9, 0xFC, 0x00, // -Inifinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070077 0x63,
78 0x4E, 0x61, 0x4E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070079 0xF9, 0x7E, 0x00, // NaN
Laurence Lundblade68a13352018-09-23 02:19:54 -070080 0x63,
81 0x6F, 0x6E, 0x65,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070082 0xF9, 0x3C, 0x00, // 1.0
Laurence Lundblade68a13352018-09-23 02:19:54 -070083 0x69,
84 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070085 0xF9, 0x35, 0x55, // half-precsion one third 0.333251953125
Laurence Lundblade68a13352018-09-23 02:19:54 -070086 0x76,
Laurence Lundbladeee851742020-01-08 08:37:05 -080087 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C,
88 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070089 0xF9, 0x7B, 0xFF, // largest half-precision 65504.0
Laurence Lundbladeee851742020-01-08 08:37:05 -080090 0x78, 0x18,
91 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68,
92 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
93 0x6F, 0x6E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070094 0xF9, 0x7C, 0x00, // Infinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070095 0x72,
Laurence Lundbladeee851742020-01-08 08:37:05 -080096 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75,
97 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070098 0xF9, 0x00, 0x01, // Smallest half-precision subnormal 0.000000059604645
Laurence Lundblade68a13352018-09-23 02:19:54 -070099 0x71,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800100 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62,
101 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700102 0xF9, 0x03, 0xFF, // Largest half-precision subnormal 0.0000609755516
103 0x6F,
104 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
105 0x72, 0x6D, 0x61, 0x6C,
106 0xF9, 0x04, 0x00, // Smallest half-precision normal 0.000061988
Laurence Lundblade68a13352018-09-23 02:19:54 -0700107 0x70,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800108 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x73,
109 0x69, 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade68a13352018-09-23 02:19:54 -0700110 0xF9, 0x00, 0x00,
111 0x03,
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700112 0xF9, 0xC0, 0x00, // -2
113 0x04,
114 0xF9, 0x7E, 0x00, // qNaN
115 0x05,
116 0xF9, 0x7C, 0x01, // sNaN
117 0x06,
118 0xF9, 0x7E, 0x0F, // qNaN with payload 0x0f
119 0x07,
120 0xF9, 0x7C, 0x0F, // sNaN with payload 0x0f
Laurence Lundblade68a13352018-09-23 02:19:54 -0700121};
122
123
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700124inline static bool CheckDouble(double d, uint64_t u)
125{
126 return UsefulBufUtil_CopyDoubleToUint64(d) != u;
127}
128
129
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300130int32_t HalfPrecisionDecodeBasicTests(void)
Laurence Lundblade68a13352018-09-23 02:19:54 -0700131{
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700132 UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800133
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700134 QCBORDecodeContext DC;
135 QCBORDecode_Init(&DC, HalfPrecision, 0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800136
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700137 QCBORItem Item;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700138
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700139 QCBORDecode_GetNext(&DC, &Item);
140 if(Item.uDataType != QCBOR_TYPE_MAP) {
141 return -1;
142 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700143
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700144 QCBORDecode_GetNext(&DC, &Item);
145 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0) {
146 return -2;
147 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800148
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700149 QCBORDecode_GetNext(&DC, &Item);
150 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
151 return -3;
152 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700153
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700154 QCBORDecode_GetNext(&DC, &Item);
155 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -INFINITY) {
156 return -4;
157 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700158
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700159 // TODO: NAN-related is this really converting right? It is carrying
160 // payload, but this confuses things.
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700161 QCBORDecode_GetNext(&DC, &Item);
162 if(Item.uDataType != QCBOR_TYPE_DOUBLE || !isnan(Item.val.dfnum)) {
163 return -5;
164 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700165
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700166 QCBORDecode_GetNext(&DC, &Item);
167 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 1.0) {
168 return -6;
169 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800170
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700171 // Approximately 1/3
172 QCBORDecode_GetNext(&DC, &Item);
173 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.333251953125) {
174 return -7;
175 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700176
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700177 // Largest half-precision
178 QCBORDecode_GetNext(&DC, &Item);
179 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 65504.0) {
180 return -8;
181 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700182
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700183 QCBORDecode_GetNext(&DC, &Item);
184 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
185 return -9;
186 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800187
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700188 // Smallest half-precision subnormal
189 QCBORDecode_GetNext(&DC, &Item);
190 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00000005960464477539063) {
191 return -10;
192 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700193
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700194 // Largest half-precision subnormal
195 QCBORDecode_GetNext(&DC, &Item);
196 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00006097555160522461) {
197 return -11;
198 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700199
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700200 // Smallest half-precision normal
201 QCBORDecode_GetNext(&DC, &Item);
202 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00006103515625) {
203 return -12;
204 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800205
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700206 // half-precision zero
207 QCBORDecode_GetNext(&DC, &Item);
208 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0) {
209 return -13;
210 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800211
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700212 // negative 2
213 QCBORDecode_GetNext(&DC, &Item);
214 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -2.0) {
215 return -14;
216 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800217
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700218 // TODO: NAN-related double check these four tests
219 QCBORDecode_GetNext(&DC, &Item); // qNaN
220 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700221 CheckDouble(Item.val.dfnum, 0x7ff8000000000000ULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700222 return -15;
223 }
224 QCBORDecode_GetNext(&DC, &Item); // sNaN
225 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700226 CheckDouble(Item.val.dfnum, 0x7ff0000000000001ULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700227 return -16;
228 }
229 QCBORDecode_GetNext(&DC, &Item); // qNaN with payload 0x0f
230 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700231 CheckDouble(Item.val.dfnum, 0x7ff800000000000fULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700232 return -17;
233 }
234 QCBORDecode_GetNext(&DC, &Item); // sNaN with payload 0x0f
235 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700236 CheckDouble(Item.val.dfnum, 0x7ff000000000000fULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700237 return -18;
238 }
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700239
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700240 if(QCBORDecode_Finish(&DC)) {
241 return -19;
242 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800243
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700244 return 0;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700245}
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700246
247
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700248
249
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300250int32_t HalfPrecisionAgainstRFCCodeTest(void)
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700251{
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700252 for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700253 unsigned char x[2];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800254 x[1] = (uint8_t)(uHalfP & 0xff);
255 x[0] = (uint8_t)(uHalfP >> 8); // uHalfP is always less than 0xffff
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700256 double d = decode_half(x);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800257
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700258 // Contruct the CBOR for the half-precision float by hand
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530259 UsefulBuf_MAKE_STACK_UB(__xx, 3);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700260 UsefulOutBuf UOB;
261 UsefulOutBuf_Init(&UOB, __xx);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800262
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800263 const uint8_t uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); // 0xf9
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700264 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); // The initial byte for a half-precision float
265 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP);
266
Laurence Lundbladeee851742020-01-08 08:37:05 -0800267 // Now parse the hand-constructed CBOR. This will invoke the
268 // conversion to a float
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700269 QCBORDecodeContext DC;
270 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800271
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700272 QCBORItem Item;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800273
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700274 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700275 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700276 return -1;
277 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800278
Laurence Lundbladeee851742020-01-08 08:37:05 -0800279 //printf("%04x QCBOR:%15.15f RFC: %15.15f (%8x)\n",
280 // uHalfP, Item.val.fnum, d , UsefulBufUtil_CopyFloatToUint32(d));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800281
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700282 if(isnan(d)) {
283 // The RFC code uses the native instructions which may or may not
284 // handle sNaN, qNaN and NaN payloads correctly. This test just
285 // makes sure it is a NaN and doesn't worry about the type of NaN
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700286 if(!isnan(Item.val.dfnum)) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700287 return -3;
288 }
289 } else {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700290 if(Item.val.dfnum != d) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700291 return -2;
292 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700293 }
294 }
295 return 0;
296}
297
298
299/*
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700300 Expected output from preferred serialization of some of floating-point numbers
301{"zero": 0.0,
302 "negative zero": -0.0,
303 "infinitity": Infinity,
304 "negative infinitity": -Infinity,
305 "NaN": NaN,
306 "one": 1.0,
307 "one third": 0.333251953125,
308 "largest half-precision": 65504.0,
309 "largest half-precision point one": 65504.1,
310 "too-large half-precision": 65536.0,
311 "smallest half subnormal": 5.960464477539063e-8,
312 "smallest half normal": 0.00006103515625,
313 "smallest half normal plus": 0.00006103515625000001,
314 "smallest normal minus": 0.000030517578125,
315 "largest single": 3.4028234663852886e+38,
316 "largest single plus": 6.805646932770577e+38,
317 "smallest single": 1.1754943508222875e-38,
318 "smallest single plus": 1.1754943508222878e-38,
319 "smallest single minus": 1.1754943508222874e-38,
320 "smallest single minus more": 5.877471754111438e-39,
321 3: -2.0, "single precision": 16777216.0,
322 "single with precision loss": 16777217.0,
323 1: "fin"}
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700324 */
Laurence Lundbladebb474be2018-10-22 11:53:21 +0530325static const uint8_t spExpectedSmallest[] = {
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700326 0xB8, 0x1A,
327 0x64, 0x7A, 0x65, 0x72, 0x6F,
328 0xF9, 0x00, 0x00,
329
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700330 0x6D, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A,
331 0x65, 0x72, 0x6F,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700332 0xF9, 0x80, 0x00,
333
334 0x6A, 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
335 0xF9, 0x7C, 0x00,
336
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700337 0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69,
338 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700339 0xF9, 0xFC, 0x00,
340
341 0x63, 0x4E, 0x61, 0x4E,
342 0xF9, 0x7E, 0x00,
343
344 0x63, 0x6F, 0x6E, 0x65,
345 0xF9, 0x3C, 0x00,
346
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700347 0x69, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700348 0xF9, 0x35, 0x55,
349
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700350 0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61,
351 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
352 0x6F, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700353 0xF9, 0x7B, 0xFF,
354
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700355 0x78, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68,
356 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73,
357 0x69, 0x6F, 0x6E, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20,
358 0x6F, 0x6E, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700359 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33,
360
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700361 0x78, 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65,
362 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63,
363 0x69, 0x73, 0x69, 0x6F, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700364 0xFA, 0x47, 0x80, 0x00, 0x00,
365
366 0x77, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74,
367 0x20, 0x68, 0x61, 0x6C, 0x66, 0x20, 0x73, 0x75, 0x62, 0x6E,
368 0x6F, 0x72, 0x6D, 0x61, 0x6C,
369 0xFA, 0x33, 0x80, 0x00, 0x00,
370
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700371 0x74, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x68,
372 0x61, 0x6C, 0x66, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700373 0xF9, 0x04, 0x00,
374
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700375 0x78, 0x19, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
376 0x68, 0x61, 0x6C, 0x66, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61,
377 0x6C, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700378 0xFB, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
379
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700380 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E,
381 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700382 0x75, 0x73,
383 0xFB, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
384
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700385 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E,
386 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6E, 0x75,
387 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700388 0xFA, 0x38, 0x00, 0x00, 0x00,
389
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700390 0x6E, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
391 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700392 0xFA, 0x7F, 0x7F, 0xFF, 0xFF,
393
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700394 0x73, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
395 0x6E,0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700396 0xFB, 0x47, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01,
397
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700398 0x73, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
399 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700400 0xFB, 0x47, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
401
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700402 0x6F, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
403 0x69, 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700404 0xFA, 0x00, 0x80, 0x00, 0x00,
405
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700406 0x74, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
407 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700408 0xFB, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
409
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700410 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
411 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x6D, 0x69, 0x6E, 0x75,
412 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700413 0xFB, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
414
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700415 0x78, 0x1A, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
416 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x6D, 0x69, 0x6E,
417 0x75, 0x73, 0x20, 0x6D, 0x6F, 0x72, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700418 0xFB, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419
420 0x03,
421 0xF9, 0xC0, 0x00,
422
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700423 0x70, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x72, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700424 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
425 0xFA, 0x4B, 0x80, 0x00, 0x00,
426
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700427 0x78, 0x1A, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69,
428 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
429 0x6F, 0x6E, 0x20, 0x6C, 0x6F, 0x73, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700430 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
431
432 0x01,
433 0x63, 0x66, 0x69, 0x6E
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700434};
435
436
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700437/*
438 Makes a double from a uint64_t by copying the bits, not
439 by converting the value.
440 */
441#define MAKE_DOUBLE(x) UsefulBufUtil_CopyUint64ToDouble(x)
442
443
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300444int32_t DoubleAsSmallestTest(void)
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700445{
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700446 UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, sizeof(spExpectedSmallest));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800447
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700448 QCBOREncodeContext EC;
449 QCBOREncode_Init(&EC, EncodedHalfsMem);
450 QCBOREncode_OpenMap(&EC);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800451
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700452 // Many of these are from
453 // https://en.wikipedia.org/wiki/Half-precision_floating-point_format
454 // and
455 // https://en.wikipedia.org/wiki/Single-precision_floating-point_format
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800456
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700457 // F9 0000 # primitive(0)
458 QCBOREncode_AddDoubleToMap(&EC, "zero", 0.00);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700459
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700460 // F9 8000 # primitive(0)
461 QCBOREncode_AddDoubleToMap(&EC, "negative zero", -0.00);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800462
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700463 // F9 7C00 # primitive(31744)
464 QCBOREncode_AddDoubleToMap(&EC, "infinitity", INFINITY);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800465
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700466 // F9 FC00 # primitive(64512)
467 QCBOREncode_AddDoubleToMap(&EC, "negative infinitity", -INFINITY);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800468
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700469 // F9 7E00 # primitive(32256)
470 QCBOREncode_AddDoubleToMap(&EC, "NaN", NAN);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800471
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700472 // TODO: test a few NaN variants
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800473
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700474 // F9 3C00 # primitive(15360)
475 QCBOREncode_AddDoubleToMap(&EC, "one", 1.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800476
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700477 // F9 3555 # primitive(13653)
478 QCBOREncode_AddDoubleToMap(&EC, "one third", 0.333251953125);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800479
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700480 // 65504.0, converts to the large possible half-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700481 // 0xF9, 0x7B, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700482 QCBOREncode_AddDoubleToMap(&EC, "largest half-precision", 65504.0);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700483
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700484 // 65504.1, the double that has both to large an exponent and too
485 // much precision, so no conversion.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700486 // 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700487 QCBOREncode_AddDoubleToMap(&EC, "largest half-precision point one", 65504.1);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800488
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700489 // 65536.0 has an exponent of 16, which is larger than 15, the
490 // largest half-precision exponent. It is the exponent, not
491 // precision loss that prevents conversion to half. It does convert
492 // to single precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700493 // 0xFA, 0x47, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700494 QCBOREncode_AddDoubleToMap(&EC, "too-large half-precision", 65536.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800495
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700496 // 5.9604644775390625E-8, the smallest possible half-precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700497 // subnormal, digitis are lost converting to half, but not
498 // when converting to a single
499 // 0xFA, 0x33, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700500 QCBOREncode_AddDoubleToMap(&EC,
501 "smallest half subnormal",
502 MAKE_DOUBLE(0x3e70000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800503
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700504 // 0.00006103515625, the double value that converts to the smallest
505 // possible half-precision normal. which is what should appear in
506 // the output.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700507 // 0xF9, 0x04, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700508 QCBOREncode_AddDoubleToMap(&EC,
509 "smallest half normal",
510 MAKE_DOUBLE(0x3f10000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800511
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700512 // 0.000061035156250000014 ,the double value that is a tiny bit
513 // greater than smallest possible half-precision normal. It will be
514 // output as a double because converting it will reduce precision.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700515 // 0xFB, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700516 QCBOREncode_AddDoubleToMap(&EC,
517 "smallest half normal plus",
518 MAKE_DOUBLE(0x3f10000000000001));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800519
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700520 // 0.000061035156249999993, the double value that is a tiny bit
521 // smaller than the smallest half-precision normal. This will fail
522 // to convert to a half-precision because both the exponent is too
523 // small and the precision is too large for a half-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700524 // 0xFB, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700525 QCBOREncode_AddDoubleToMap(&EC,
526 "smallest normal minus",
527 MAKE_DOUBLE(0x3f0fffffffffffff));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800528
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700529 // 0.000030517578125, the double value that is too small to fit
530 // into a half-precision because the exponent won't fit, not
531 // because precision would be lost. (This would fit into a
532 // half-precision subnormal, but there is no converstion to
533 // that). This ends up encoded as a single-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700534 // 0xFA, 0x38, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700535 QCBOREncode_AddDoubleToMap(&EC,
536 "smallest normal minus",
537 MAKE_DOUBLE(0x3f00000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800538
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700539 // 3.4028234664e38, the value that converts to the largest possible
540 // single-precision.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700541 // 0xFA, 0x7F, 0x7F, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700542 QCBOREncode_AddDoubleToMap(&EC,
543 "largest single",
544 MAKE_DOUBLE(0x47efffffe0000000));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700545
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700546 // 3.402823466385289E38, sightly larger than the largest possible
547 // possible precision. Conversion fails because precision would be
548 // lost.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700549 // 0xFB, 0x47, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700550 QCBOREncode_AddDoubleToMap(&EC,
551 "largest single plus",
552 MAKE_DOUBLE(0x47efffffe0000001));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700553
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700554 // 6.8056469327705772E38, slightly more larger than the largers
555 // possible single precision. Conversion fails because exponent is
556 // too large.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700557 // 0xFB, 0x47, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700558 QCBOREncode_AddDoubleToMap(&EC,
559 "largest single plus",
560 MAKE_DOUBLE(0x47ffffffe0000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800561
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700562 // 1.1754943508222875E-38, The double value that converts to the
563 // smallest possible single-precision normal
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700564 // 0xFA, 0x00, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700565 QCBOREncode_AddDoubleToMap(&EC,
566 "smallest single",
567 MAKE_DOUBLE(0x3810000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800568
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700569 // 1.1754943508222878E-38, double value that is slightly larger
570 // than the smallest single-precision normal. Conversion fails
571 // because of precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700572 // 0xFB, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700573 QCBOREncode_AddDoubleToMap(&EC,
574 "smallest single plus",
575 MAKE_DOUBLE(0x3810000000000001));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700576
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700577 // 1.1754943508222874E-38, slightly smaller than the smallest
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700578 // single-precision normal. Conversion fails because of precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700579 // 0xFB, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700580 QCBOREncode_AddDoubleToMap(&EC,
581 "smallest single minus",
582 MAKE_DOUBLE(0x380fffffffffffff));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800583
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700584 // 5.8774717541114375E-39, slightly smaller than the smallest
585 // single-precision normal. Conversion fails because the exponent
586 // is too small.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700587 // 0xFB, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700588 QCBOREncode_AddDoubleToMap(&EC,
589 "smallest single minus more",
590 MAKE_DOUBLE(0x3800000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800591
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700592 // Just -2, which converts to a negative half-precision
593 // F9 C000 # primitive(49152)
594 QCBOREncode_AddDoubleToMapN(&EC, 3, -2.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800595
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700596 // 16777216, No precision loss converting to single
597 // FA 4B800000 # primitive(1266679808)
598 QCBOREncode_AddDoubleToMap(&EC, "single precision", 16777216);
599
600 // 16777217, One more than above. Too much precision for a single
601 // so no conversion.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700602 // 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700603 QCBOREncode_AddDoubleToMap(&EC, "single with precision loss", 16777217);
604
605 // Just a convenient marker when cutting and pasting encoded CBOR
606 QCBOREncode_AddSZStringToMapN(&EC, 1, "fin");
607
608 QCBOREncode_CloseMap(&EC);
609
610 UsefulBufC EncodedHalfs;
611 QCBORError uErr = QCBOREncode_Finish(&EC, &EncodedHalfs);
612 if(uErr) {
613 return -1;
614 }
615
616 if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) {
617 return -3;
618 }
619
620 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800621}
Laurence Lundblade585127a2020-07-15 03:25:24 -0700622#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700623
624
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700625/*
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700626 * Some encoded floating point numbers that are used for both
627 * encode and decode tests.
628 *
629 * [0.0, // Half
630 * 3.14, // Double
631 * 0.0, // Double
632 * NaN, // Double
633 * Infinity, // Double
634 * 0.0, // Half (Duplicate because of use in encode tests)
635 * 3.140000104904175, // Single
636 * 0.0, // Single
637 * NaN, // Single
638 * Infinity, // Single
639 * {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
640 * 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700641 */
642static const uint8_t spExpectedFloats[] = {
643 0x8B,
644 0xF9, 0x00, 0x00,
645 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
646 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0xF9, 0x00, 0x00,
650 0xFA, 0x40, 0x48, 0xF5, 0xC3,
651 0xFA, 0x00, 0x00, 0x00, 0x00,
652 0xFA, 0x7F, 0xC0, 0x00, 0x00,
653 0xFA, 0x7F, 0x80, 0x00, 0x00,
654 0xA8,
655 0x18, 0x64,
656 0xF9, 0x00, 0x00,
657 0x18, 0x65,
658 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
659 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
660 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
661 0x18, 0x69,
662 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
663 0x18, 0x66,
664 0xF9, 0x00, 0x00,
665 0x18, 0x67,
666 0xFA, 0x40, 0x49, 0x0F, 0xDA,
667 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
668 0xFA, 0x40, 0x2D, 0xF8, 0x54,
669 0x18, 0x6A,
670 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700671
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200672#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700673static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700674 0x8B,
675 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
677 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0xFA, 0x00, 0x00, 0x00, 0x00,
681 0xFA, 0x40, 0x48, 0xF5, 0xC3,
682 0xFA, 0x00, 0x00, 0x00, 0x00,
683 0xFA, 0x7F, 0xC0, 0x00, 0x00,
684 0xFA, 0x7F, 0x80, 0x00, 0x00,
685 0xA8,
686 0x18, 0x64,
687 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688 0x18, 0x65,
689 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
690 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
691 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
692 0x18, 0x69,
693 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x18, 0x66,
695 0xFA, 0x00, 0x00, 0x00, 0x00,
696 0x18, 0x67,
697 0xFA, 0x40, 0x49, 0x0F, 0xDA,
698 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
699 0xFA, 0x40, 0x2D, 0xF8, 0x54,
700 0x18, 0x6A,
701 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700702
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300703int32_t GeneralFloatEncodeTests(void)
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700704{
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700705 UsefulBufC ExpectedFloats;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700706#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700707 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700708 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700709 (void)spExpectedFloatsNoHalf; // Avoid unused variable error
710#else
711 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700712 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700713 (void)spExpectedFloats; // Avoid unused variable error
714#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700715
716 QCBOREncodeContext EC;
717 QCBOREncode_Init(&EC, OutBuffer);
718 QCBOREncode_OpenArray(&EC);
719
720 QCBOREncode_AddDouble(&EC, 0.0);
721 QCBOREncode_AddDouble(&EC, 3.14);
722 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
723 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
724 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
725
726 QCBOREncode_AddFloat(&EC, 0.0);
727 QCBOREncode_AddFloat(&EC, 3.14f);
728 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
729 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
730 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
731
732 QCBOREncode_OpenMap(&EC);
733
734 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
735 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
736 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
737 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
738
739 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
740 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
741 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
742 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
743
744 QCBOREncode_CloseMap(&EC);
745 QCBOREncode_CloseArray(&EC);
746
747 UsefulBufC Encoded;
748 QCBORError uErr = QCBOREncode_Finish(&EC, &Encoded);
749 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700750 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700751 }
752
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700753 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700754 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700755 }
756
757 return 0;
758}
759
760
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700761/* returns 0 if equivalent, non-zero if not equivalent */
762static int CHECK_EXPECTED_DOUBLE(double val, double expected)
763{
764 double diff = val - expected;
765
766 diff = fabs(diff);
767
768 if(diff > 0.000001) {
769 return 1;
770 } else {
771 return 0;
772 }
773}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200774#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700775
776
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300777int32_t GeneralFloatDecodeTests(void)
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700778{
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700779 QCBORItem Item;
780 QCBORError uErr;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700781 QCBORDecodeContext DC;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700782
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700783 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
784 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700785
786 QCBORDecode_GetNext(&DC, &Item);
787 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700788 return MakeTestResultCode(0, 1, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700789 }
790
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700791 /* 0.0 half-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700792 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200793 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
794#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
795 || Item.uDataType != QCBOR_TYPE_DOUBLE
796 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700797#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
798 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200799#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
800 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700801 return MakeTestResultCode(0, 2, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700802 }
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700803
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700804 /* 3.14 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700805 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200806 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
807#ifndef USEFULBUF_DISABLE_ALL_FLOAT
808 || Item.uDataType != QCBOR_TYPE_DOUBLE
809 || Item.val.dfnum != 3.14
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700810#else /* USEFULBUF_DISABLE_ALL_FLOAT */
811 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200812#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
813 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700814 return MakeTestResultCode(0, 3, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700815 }
816
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700817 /* 0.0 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700818 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200819 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
820#ifndef USEFULBUF_DISABLE_ALL_FLOAT
821 || Item.uDataType != QCBOR_TYPE_DOUBLE
822 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700823#else /* USEFULBUF_DISABLE_ALL_FLOAT */
824 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200825#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
826 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700827 return MakeTestResultCode(0, 4, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700828 }
829
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700830 /* NaN double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700831 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200832 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
833#ifndef USEFULBUF_DISABLE_ALL_FLOAT
834 || Item.uDataType != QCBOR_TYPE_DOUBLE
835 || !isnan(Item.val.dfnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700836#else /* USEFULBUF_DISABLE_ALL_FLOAT */
837 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200838#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
839 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700840 return MakeTestResultCode(0, 5, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700841 }
842
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700843 /* Infinity double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700844 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200845 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
846#ifndef USEFULBUF_DISABLE_ALL_FLOAT
847 || Item.uDataType != QCBOR_TYPE_DOUBLE
848 || Item.val.dfnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700849#else /* USEFULBUF_DISABLE_ALL_FLOAT */
850 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200851#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
852 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700853 return MakeTestResultCode(0, 6, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700854 }
855
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700856 /* 0.0 half-precision (again) */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700857 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200858 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
859#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
860 || Item.uDataType != QCBOR_TYPE_DOUBLE
861 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700862#else /* USEFULBUF_DISABLE_ALL_FLOAT */
863 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200864#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
865 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700866 return MakeTestResultCode(0, 7, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700867 }
868
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700869 /* 3.140000104904175 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700870 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200871 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
872#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700873#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200874 || Item.uDataType != QCBOR_TYPE_DOUBLE
875 || CHECK_EXPECTED_DOUBLE(3.14, Item.val.dfnum)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700876#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200877 || Item.uDataType != QCBOR_TYPE_FLOAT
878 || CHECK_EXPECTED_DOUBLE(3.14, Item.val.fnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700879#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
880#else /* USEFULBUF_DISABLE_ALL_FLOAT */
881 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200882#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
883 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700884 return MakeTestResultCode(0, 8, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700885 }
886
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700887 /* 0.0 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700888 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200889 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
890#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700891#ifndef QCBOR_DISABLE_FLOAT_HW_USE
892 || Item.uDataType != QCBOR_TYPE_DOUBLE
893 || Item.val.dfnum != 0.0
894#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200895 || Item.uDataType != QCBOR_TYPE_FLOAT
896 || Item.val.fnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700897#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
898#else /* USEFULBUF_DISABLE_ALL_FLOAT */
899 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200900#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
901 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700902 return MakeTestResultCode(0, 9, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700903 }
904
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700905 /* NaN single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700906 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200907 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
908#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700909#ifndef QCBOR_DISABLE_FLOAT_HW_USE
910 || Item.uDataType != QCBOR_TYPE_DOUBLE
911 || !isnan(Item.val.dfnum)
912#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200913 || Item.uDataType != QCBOR_TYPE_FLOAT
914 || !isnan(Item.val.fnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700915#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
916#else /* USEFULBUF_DISABLE_ALL_FLOAT */
917 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200918#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
919 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700920 return MakeTestResultCode(0, 10, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700921 }
922
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700923 /* Infinity single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700924 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200925 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
926#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700927#ifndef QCBOR_DISABLE_FLOAT_HW_USE
928 || Item.uDataType != QCBOR_TYPE_DOUBLE
929 || Item.val.dfnum != INFINITY
930#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200931 || Item.uDataType != QCBOR_TYPE_FLOAT
932 || Item.val.fnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700933#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
934#else /* USEFULBUF_DISABLE_ALL_FLOAT */
935 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200936#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
937 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700938 return MakeTestResultCode(0, 11, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700939 }
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700940 /* Sufficent test coverage. Don't need to decode the rest. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700941
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200942
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200943#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700944 /* Now tests for spiffy decode main function */
945 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700946 double d;
947 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -0700948 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700949
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700950 /* 0.0 half-precision */
951 QCBORDecode_GetDouble(&DC, &d);
952 uErr = QCBORDecode_GetAndResetError(&DC);
953 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700954#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700955 || d != 0.0
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700956#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700957 ) {
958 return MakeTestResultCode(1, 1, uErr);
959 }
960
961 /* 3.14 double-precision */
962 QCBORDecode_GetDouble(&DC, &d);
963 uErr = QCBORDecode_GetAndResetError(&DC);
964 if(uErr != QCBOR_SUCCESS || d != 3.14) {
965 return MakeTestResultCode(1, 2, uErr);
966 }
967
968 /* 0.0 double-precision */
969 QCBORDecode_GetDouble(&DC, &d);
970 uErr = QCBORDecode_GetAndResetError(&DC);
971 if(uErr != QCBOR_SUCCESS || d != 0.0) {
972 return MakeTestResultCode(1, 3, uErr);
973 }
974
975 /* NaN double-precision */
976 QCBORDecode_GetDouble(&DC, &d);
977 uErr = QCBORDecode_GetAndResetError(&DC);
978 if(uErr != QCBOR_SUCCESS || !isnan(d)) {
979 return MakeTestResultCode(1, 4, uErr);
980 }
981
982 /* Infinity double-precision */
983 QCBORDecode_GetDouble(&DC, &d);
984 uErr = QCBORDecode_GetAndResetError(&DC);
985 if(uErr != QCBOR_SUCCESS || d != INFINITY) {
986 return MakeTestResultCode(1, 5, uErr);
987 }
988
989 /* 0.0 half-precision */
990 QCBORDecode_GetDouble(&DC, &d);
991 uErr = QCBORDecode_GetAndResetError(&DC);
992 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
993#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
994 || d != 0.0
995#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
996 ) {
997 return MakeTestResultCode(1, 6, uErr);
998 }
999
1000 /* 3.140000104904175 single-precision */
1001 QCBORDecode_GetDouble(&DC, &d);
1002 uErr = QCBORDecode_GetAndResetError(&DC);
1003 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1004#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1005 || d != 3.140000104904175
1006#endif
1007 ) {
1008 return MakeTestResultCode(1, 7, uErr);
1009 }
1010
1011 /* 0.0 single-precision */
1012 QCBORDecode_GetDouble(&DC, &d);
1013 uErr = QCBORDecode_GetAndResetError(&DC);
1014 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1015#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1016 || d != 0.0
1017#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1018 ) {
1019 return MakeTestResultCode(1, 8, uErr);
1020 }
1021
1022 /* NaN single-precision */
1023 QCBORDecode_GetDouble(&DC, &d);
1024 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1025#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1026 || !isnan(d)
1027#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1028 ) {
1029 return MakeTestResultCode(1, 9, uErr);
1030 }
1031
1032 /* Infinity single-precision */
1033 QCBORDecode_GetDouble(&DC, &d);
1034 uErr = QCBORDecode_GetAndResetError(&DC);
1035 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1036#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1037 || d != INFINITY
1038#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1039 ) {
1040 return MakeTestResultCode(1, 10, uErr);
1041 }
1042
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001043#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001044
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001045 return 0;
1046}
1047
1048
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001049
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001050#ifdef NAN_EXPERIMENT
1051/*
1052 Code for checking what the double to float cast does with
1053 NaNs. Not run as part of tests. Keep it around to
1054 be able to check various platforms and CPUs.
1055 */
1056
1057#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1058#define DOUBLE_NUM_EXPONENT_BITS (11)
1059#define DOUBLE_NUM_SIGN_BITS (1)
1060
1061#define DOUBLE_SIGNIFICAND_SHIFT (0)
1062#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1063#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1064
1065#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1066#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1067#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1068#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1069
1070
1071static int NaNExperiments() {
1072 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1073 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1074 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001076 float f1 = (float)dqNaN;
1077 float f2 = (float)dsNaN;
1078 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001079
1080
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001081 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1082 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1083 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001084
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001085 // Result of this on x86 is that every NaN is a qNaN. The intel
1086 // CVTSD2SS instruction ignores the NaN payload and even converts
1087 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001088
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001089 return 0;
1090}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001091#endif /* NAN_EXPERIMENT */