blob: 99297c05f23725d2053aa39f8a6ec5ab3f31aa28 [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 Lundbladeb275cdc2020-07-12 12:34:38 -070021#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -070022
Laurence Lundbladed711fb22018-09-26 14:35:22 -070023#include "half_to_double_from_rfc7049.h"
Laurence Lundblade68a13352018-09-23 02:19:54 -070024
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080025
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070026/*
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -070027 Half-precision values that are input to test half-precision decoding
28
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070029 As decoded by http://cbor.me
30 {"zero": 0.0,
31 "infinitity": Infinity,
32 "negative infinitity": -Infinity,
33 "NaN": NaN,
34 "one": 1.0,
35 "one third": 0.333251953125,
36 "largest half-precision": 65504.0,
37 "too-large half-precision": Infinity,
38 "smallest subnormal": 5.960464477539063e-8,
39 "smallest normal": 0.00006097555160522461,
40 "biggest subnormal": 0.00006103515625,
41 "subnormal single": 0.0,
42 3: -2.0,
43 4: NaN,
44 5: NaN,
45 6: NaN,
46 7: NaN}
47 */
Laurence Lundbladebb474be2018-10-22 11:53:21 +053048static const uint8_t spExpectedHalf[] = {
Laurence Lundblade7d40d812018-09-30 02:44:01 -070049 0xB1,
Laurence Lundblade68a13352018-09-23 02:19:54 -070050 0x64,
51 0x7A, 0x65, 0x72, 0x6F,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070052 0xF9, 0x00, 0x00, // half-precision 0.000
Laurence Lundblade68a13352018-09-23 02:19:54 -070053 0x6A,
54 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070055 0xF9, 0x7C, 0x00, // Infinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070056 0x73,
Laurence Lundbladeee851742020-01-08 08:37:05 -080057 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E,
58 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070059 0xF9, 0xFC, 0x00, // -Inifinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070060 0x63,
61 0x4E, 0x61, 0x4E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070062 0xF9, 0x7E, 0x00, // NaN
Laurence Lundblade68a13352018-09-23 02:19:54 -070063 0x63,
64 0x6F, 0x6E, 0x65,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070065 0xF9, 0x3C, 0x00, // 1.0
Laurence Lundblade68a13352018-09-23 02:19:54 -070066 0x69,
67 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070068 0xF9, 0x35, 0x55, // half-precsion one third 0.333251953125
Laurence Lundblade68a13352018-09-23 02:19:54 -070069 0x76,
Laurence Lundbladeee851742020-01-08 08:37:05 -080070 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C,
71 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070072 0xF9, 0x7B, 0xFF, // largest half-precision 65504.0
Laurence Lundbladeee851742020-01-08 08:37:05 -080073 0x78, 0x18,
74 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68,
75 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
76 0x6F, 0x6E,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070077 0xF9, 0x7C, 0x00, // Infinity
Laurence Lundblade68a13352018-09-23 02:19:54 -070078 0x72,
Laurence Lundbladeee851742020-01-08 08:37:05 -080079 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75,
80 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070081 0xF9, 0x00, 0x01, // Smallest half-precision subnormal 0.000000059604645
Laurence Lundblade68a13352018-09-23 02:19:54 -070082 0x71,
Laurence Lundbladeee851742020-01-08 08:37:05 -080083 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62,
84 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070085 0xF9, 0x03, 0xFF, // Largest half-precision subnormal 0.0000609755516
86 0x6F,
87 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
88 0x72, 0x6D, 0x61, 0x6C,
89 0xF9, 0x04, 0x00, // Smallest half-precision normal 0.000061988
Laurence Lundblade68a13352018-09-23 02:19:54 -070090 0x70,
Laurence Lundbladeee851742020-01-08 08:37:05 -080091 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x73,
92 0x69, 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade68a13352018-09-23 02:19:54 -070093 0xF9, 0x00, 0x00,
94 0x03,
Laurence Lundblade7d40d812018-09-30 02:44:01 -070095 0xF9, 0xC0, 0x00, // -2
96 0x04,
97 0xF9, 0x7E, 0x00, // qNaN
98 0x05,
99 0xF9, 0x7C, 0x01, // sNaN
100 0x06,
101 0xF9, 0x7E, 0x0F, // qNaN with payload 0x0f
102 0x07,
103 0xF9, 0x7C, 0x0F, // sNaN with payload 0x0f
Laurence Lundblade68a13352018-09-23 02:19:54 -0700104};
105
106
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700107inline static bool CheckDouble(double d, uint64_t u)
108{
109 return UsefulBufUtil_CopyDoubleToUint64(d) != u;
110}
111
112
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800113int32_t HalfPrecisionDecodeBasicTests()
Laurence Lundblade68a13352018-09-23 02:19:54 -0700114{
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700115 UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800116
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700117 QCBORDecodeContext DC;
118 QCBORDecode_Init(&DC, HalfPrecision, 0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800119
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700120 QCBORItem Item;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700121
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700122 QCBORDecode_GetNext(&DC, &Item);
123 if(Item.uDataType != QCBOR_TYPE_MAP) {
124 return -1;
125 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700126
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700127 QCBORDecode_GetNext(&DC, &Item);
128 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0) {
129 return -2;
130 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800131
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700132 QCBORDecode_GetNext(&DC, &Item);
133 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != INFINITY) {
134 return -3;
135 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700136
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700137 QCBORDecode_GetNext(&DC, &Item);
138 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -INFINITY) {
139 return -4;
140 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700141
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700142 // TODO: NAN-related is this really converting right? It is carrying
143 // payload, but this confuses things.
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700144 QCBORDecode_GetNext(&DC, &Item);
145 if(Item.uDataType != QCBOR_TYPE_DOUBLE || !isnan(Item.val.dfnum)) {
146 return -5;
147 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700148
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700149 QCBORDecode_GetNext(&DC, &Item);
150 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 1.0) {
151 return -6;
152 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800153
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700154 // Approximately 1/3
155 QCBORDecode_GetNext(&DC, &Item);
156 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.333251953125) {
157 return -7;
158 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700159
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700160 // Largest half-precision
161 QCBORDecode_GetNext(&DC, &Item);
162 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 65504.0) {
163 return -8;
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 != INFINITY) {
168 return -9;
169 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800170
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700171 // Smallest half-precision subnormal
172 QCBORDecode_GetNext(&DC, &Item);
173 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00000005960464477539063) {
174 return -10;
175 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700176
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700177 // Largest half-precision subnormal
178 QCBORDecode_GetNext(&DC, &Item);
179 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00006097555160522461) {
180 return -11;
181 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700182
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700183 // Smallest half-precision normal
184 QCBORDecode_GetNext(&DC, &Item);
185 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.00006103515625) {
186 return -12;
187 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800188
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700189 // half-precision zero
190 QCBORDecode_GetNext(&DC, &Item);
191 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != 0.0) {
192 return -13;
193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800194
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700195 // negative 2
196 QCBORDecode_GetNext(&DC, &Item);
197 if(Item.uDataType != QCBOR_TYPE_DOUBLE || Item.val.dfnum != -2.0) {
198 return -14;
199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800200
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700201 // TODO: NAN-related double check these four tests
202 QCBORDecode_GetNext(&DC, &Item); // qNaN
203 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700204 CheckDouble(Item.val.dfnum, 0x7ff8000000000000ULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700205 return -15;
206 }
207 QCBORDecode_GetNext(&DC, &Item); // sNaN
208 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700209 CheckDouble(Item.val.dfnum, 0x7ff0000000000001ULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700210 return -16;
211 }
212 QCBORDecode_GetNext(&DC, &Item); // qNaN with payload 0x0f
213 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700214 CheckDouble(Item.val.dfnum, 0x7ff800000000000fULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700215 return -17;
216 }
217 QCBORDecode_GetNext(&DC, &Item); // sNaN with payload 0x0f
218 if(Item.uDataType != QCBOR_TYPE_DOUBLE ||
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700219 CheckDouble(Item.val.dfnum, 0x7ff000000000000fULL)) {
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700220 return -18;
221 }
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700222
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700223 if(QCBORDecode_Finish(&DC)) {
224 return -19;
225 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800226
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -0700227 return 0;
Laurence Lundblade68a13352018-09-23 02:19:54 -0700228}
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700229
230
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700231
232
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800233int32_t HalfPrecisionAgainstRFCCodeTest()
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700234{
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700235 for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700236 unsigned char x[2];
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800237 x[1] = (uint8_t)(uHalfP & 0xff);
238 x[0] = (uint8_t)(uHalfP >> 8); // uHalfP is always less than 0xffff
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700239 double d = decode_half(x);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800240
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700241 // Contruct the CBOR for the half-precision float by hand
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530242 UsefulBuf_MAKE_STACK_UB(__xx, 3);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700243 UsefulOutBuf UOB;
244 UsefulOutBuf_Init(&UOB, __xx);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800245
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800246 const uint8_t uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); // 0xf9
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700247 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); // The initial byte for a half-precision float
248 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP);
249
Laurence Lundbladeee851742020-01-08 08:37:05 -0800250 // Now parse the hand-constructed CBOR. This will invoke the
251 // conversion to a float
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700252 QCBORDecodeContext DC;
253 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800254
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700255 QCBORItem Item;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800256
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700257 QCBORDecode_GetNext(&DC, &Item);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700258 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700259 return -1;
260 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800261
Laurence Lundbladeee851742020-01-08 08:37:05 -0800262 //printf("%04x QCBOR:%15.15f RFC: %15.15f (%8x)\n",
263 // uHalfP, Item.val.fnum, d , UsefulBufUtil_CopyFloatToUint32(d));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800264
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700265 if(isnan(d)) {
266 // The RFC code uses the native instructions which may or may not
267 // handle sNaN, qNaN and NaN payloads correctly. This test just
268 // makes sure it is a NaN and doesn't worry about the type of NaN
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700269 if(!isnan(Item.val.dfnum)) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700270 return -3;
271 }
272 } else {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700273 if(Item.val.dfnum != d) {
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700274 return -2;
275 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700276 }
277 }
278 return 0;
279}
280
281
282/*
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700283 Expected output from preferred serialization of some of floating-point numbers
284{"zero": 0.0,
285 "negative zero": -0.0,
286 "infinitity": Infinity,
287 "negative infinitity": -Infinity,
288 "NaN": NaN,
289 "one": 1.0,
290 "one third": 0.333251953125,
291 "largest half-precision": 65504.0,
292 "largest half-precision point one": 65504.1,
293 "too-large half-precision": 65536.0,
294 "smallest half subnormal": 5.960464477539063e-8,
295 "smallest half normal": 0.00006103515625,
296 "smallest half normal plus": 0.00006103515625000001,
297 "smallest normal minus": 0.000030517578125,
298 "largest single": 3.4028234663852886e+38,
299 "largest single plus": 6.805646932770577e+38,
300 "smallest single": 1.1754943508222875e-38,
301 "smallest single plus": 1.1754943508222878e-38,
302 "smallest single minus": 1.1754943508222874e-38,
303 "smallest single minus more": 5.877471754111438e-39,
304 3: -2.0, "single precision": 16777216.0,
305 "single with precision loss": 16777217.0,
306 1: "fin"}
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700307 */
Laurence Lundbladebb474be2018-10-22 11:53:21 +0530308static const uint8_t spExpectedSmallest[] = {
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700309 0xB8, 0x1A,
310 0x64, 0x7A, 0x65, 0x72, 0x6F,
311 0xF9, 0x00, 0x00,
312
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700313 0x6D, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A,
314 0x65, 0x72, 0x6F,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700315 0xF9, 0x80, 0x00,
316
317 0x6A, 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
318 0xF9, 0x7C, 0x00,
319
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700320 0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69,
321 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700322 0xF9, 0xFC, 0x00,
323
324 0x63, 0x4E, 0x61, 0x4E,
325 0xF9, 0x7E, 0x00,
326
327 0x63, 0x6F, 0x6E, 0x65,
328 0xF9, 0x3C, 0x00,
329
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700330 0x69, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700331 0xF9, 0x35, 0x55,
332
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700333 0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61,
334 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
335 0x6F, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700336 0xF9, 0x7B, 0xFF,
337
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700338 0x78, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68,
339 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73,
340 0x69, 0x6F, 0x6E, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20,
341 0x6F, 0x6E, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700342 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33,
343
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700344 0x78, 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65,
345 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63,
346 0x69, 0x73, 0x69, 0x6F, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700347 0xFA, 0x47, 0x80, 0x00, 0x00,
348
349 0x77, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74,
350 0x20, 0x68, 0x61, 0x6C, 0x66, 0x20, 0x73, 0x75, 0x62, 0x6E,
351 0x6F, 0x72, 0x6D, 0x61, 0x6C,
352 0xFA, 0x33, 0x80, 0x00, 0x00,
353
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700354 0x74, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x68,
355 0x61, 0x6C, 0x66, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700356 0xF9, 0x04, 0x00,
357
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700358 0x78, 0x19, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
359 0x68, 0x61, 0x6C, 0x66, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61,
360 0x6C, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700361 0xFB, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
362
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700363 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E,
364 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6E,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700365 0x75, 0x73,
366 0xFB, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
367
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700368 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E,
369 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x6D, 0x69, 0x6E, 0x75,
370 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700371 0xFA, 0x38, 0x00, 0x00, 0x00,
372
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700373 0x6E, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
374 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700375 0xFA, 0x7F, 0x7F, 0xFF, 0xFF,
376
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700377 0x73, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
378 0x6E,0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700379 0xFB, 0x47, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01,
380
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700381 0x73, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69,
382 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700383 0xFB, 0x47, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
384
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700385 0x6F, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
386 0x69, 0x6E, 0x67, 0x6C, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700387 0xFA, 0x00, 0x80, 0x00, 0x00,
388
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700389 0x74, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
390 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x6C, 0x75, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700391 0xFB, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
392
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700393 0x75, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73,
394 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x6D, 0x69, 0x6E, 0x75,
395 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700396 0xFB, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
397
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700398 0x78, 0x1A, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
399 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x6D, 0x69, 0x6E,
400 0x75, 0x73, 0x20, 0x6D, 0x6F, 0x72, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700401 0xFB, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402
403 0x03,
404 0xF9, 0xC0, 0x00,
405
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700406 0x70, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x70, 0x72, 0x65,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700407 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
408 0xFA, 0x4B, 0x80, 0x00, 0x00,
409
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700410 0x78, 0x1A, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69,
411 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69,
412 0x6F, 0x6E, 0x20, 0x6C, 0x6F, 0x73, 0x73,
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700413 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
414
415 0x01,
416 0x63, 0x66, 0x69, 0x6E
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700417};
418
419
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700420/*
421 Makes a double from a uint64_t by copying the bits, not
422 by converting the value.
423 */
424#define MAKE_DOUBLE(x) UsefulBufUtil_CopyUint64ToDouble(x)
425
426
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800427int32_t DoubleAsSmallestTest()
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700428{
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700429 UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, sizeof(spExpectedSmallest));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800430
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700431 QCBOREncodeContext EC;
432 QCBOREncode_Init(&EC, EncodedHalfsMem);
433 QCBOREncode_OpenMap(&EC);
Laurence Lundblade067035b2018-11-28 17:35:25 -0800434
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700435 // Many of these are from
436 // https://en.wikipedia.org/wiki/Half-precision_floating-point_format
437 // and
438 // https://en.wikipedia.org/wiki/Single-precision_floating-point_format
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800439
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700440 // F9 0000 # primitive(0)
441 QCBOREncode_AddDoubleToMap(&EC, "zero", 0.00);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700442
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700443 // F9 8000 # primitive(0)
444 QCBOREncode_AddDoubleToMap(&EC, "negative zero", -0.00);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800445
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700446 // F9 7C00 # primitive(31744)
447 QCBOREncode_AddDoubleToMap(&EC, "infinitity", INFINITY);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800448
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700449 // F9 FC00 # primitive(64512)
450 QCBOREncode_AddDoubleToMap(&EC, "negative infinitity", -INFINITY);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800451
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700452 // F9 7E00 # primitive(32256)
453 QCBOREncode_AddDoubleToMap(&EC, "NaN", NAN);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800454
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700455 // TODO: test a few NaN variants
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800456
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700457 // F9 3C00 # primitive(15360)
458 QCBOREncode_AddDoubleToMap(&EC, "one", 1.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800459
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700460 // F9 3555 # primitive(13653)
461 QCBOREncode_AddDoubleToMap(&EC, "one third", 0.333251953125);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800462
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700463 // 65504.0, converts to the large possible half-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700464 // 0xF9, 0x7B, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700465 QCBOREncode_AddDoubleToMap(&EC, "largest half-precision", 65504.0);
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700466
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700467 // 65504.1, the double that has both to large an exponent and too
468 // much precision, so no conversion.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700469 // 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700470 QCBOREncode_AddDoubleToMap(&EC, "largest half-precision point one", 65504.1);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800471
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700472 // 65536.0 has an exponent of 16, which is larger than 15, the
473 // largest half-precision exponent. It is the exponent, not
474 // precision loss that prevents conversion to half. It does convert
475 // to single precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700476 // 0xFA, 0x47, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700477 QCBOREncode_AddDoubleToMap(&EC, "too-large half-precision", 65536.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800478
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700479 // 5.9604644775390625E-8, the smallest possible half-precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700480 // subnormal, digitis are lost converting to half, but not
481 // when converting to a single
482 // 0xFA, 0x33, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700483 QCBOREncode_AddDoubleToMap(&EC,
484 "smallest half subnormal",
485 MAKE_DOUBLE(0x3e70000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800486
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700487 // 0.00006103515625, the double value that converts to the smallest
488 // possible half-precision normal. which is what should appear in
489 // the output.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700490 // 0xF9, 0x04, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700491 QCBOREncode_AddDoubleToMap(&EC,
492 "smallest half normal",
493 MAKE_DOUBLE(0x3f10000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800494
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700495 // 0.000061035156250000014 ,the double value that is a tiny bit
496 // greater than smallest possible half-precision normal. It will be
497 // output as a double because converting it will reduce precision.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700498 // 0xFB, 0x3F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700499 QCBOREncode_AddDoubleToMap(&EC,
500 "smallest half normal plus",
501 MAKE_DOUBLE(0x3f10000000000001));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800502
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700503 // 0.000061035156249999993, the double value that is a tiny bit
504 // smaller than the smallest half-precision normal. This will fail
505 // to convert to a half-precision because both the exponent is too
506 // small and the precision is too large for a half-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700507 // 0xFB, 0x3F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700508 QCBOREncode_AddDoubleToMap(&EC,
509 "smallest normal minus",
510 MAKE_DOUBLE(0x3f0fffffffffffff));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800511
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700512 // 0.000030517578125, the double value that is too small to fit
513 // into a half-precision because the exponent won't fit, not
514 // because precision would be lost. (This would fit into a
515 // half-precision subnormal, but there is no converstion to
516 // that). This ends up encoded as a single-precision.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700517 // 0xFA, 0x38, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700518 QCBOREncode_AddDoubleToMap(&EC,
519 "smallest normal minus",
520 MAKE_DOUBLE(0x3f00000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800521
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700522 // 3.4028234664e38, the value that converts to the largest possible
523 // single-precision.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700524 // 0xFA, 0x7F, 0x7F, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700525 QCBOREncode_AddDoubleToMap(&EC,
526 "largest single",
527 MAKE_DOUBLE(0x47efffffe0000000));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700528
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700529 // 3.402823466385289E38, sightly larger than the largest possible
530 // possible precision. Conversion fails because precision would be
531 // lost.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700532 // 0xFB, 0x47, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700533 QCBOREncode_AddDoubleToMap(&EC,
534 "largest single plus",
535 MAKE_DOUBLE(0x47efffffe0000001));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700536
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700537 // 6.8056469327705772E38, slightly more larger than the largers
538 // possible single precision. Conversion fails because exponent is
539 // too large.
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700540 // 0xFB, 0x47, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700541 QCBOREncode_AddDoubleToMap(&EC,
542 "largest single plus",
543 MAKE_DOUBLE(0x47ffffffe0000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800544
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700545 // 1.1754943508222875E-38, The double value that converts to the
546 // smallest possible single-precision normal
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700547 // 0xFA, 0x00, 0x80, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700548 QCBOREncode_AddDoubleToMap(&EC,
549 "smallest single",
550 MAKE_DOUBLE(0x3810000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800551
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700552 // 1.1754943508222878E-38, double value that is slightly larger
553 // than the smallest single-precision normal. Conversion fails
554 // because of precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700555 // 0xFB, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700556 QCBOREncode_AddDoubleToMap(&EC,
557 "smallest single plus",
558 MAKE_DOUBLE(0x3810000000000001));
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700559
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700560 // 1.1754943508222874E-38, slightly smaller than the smallest
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700561 // single-precision normal. Conversion fails because of precision
Laurence Lundblade29ec4642020-07-21 21:11:45 -0700562 // 0xFB, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700563 QCBOREncode_AddDoubleToMap(&EC,
564 "smallest single minus",
565 MAKE_DOUBLE(0x380fffffffffffff));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800566
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700567 // 5.8774717541114375E-39, slightly smaller than the smallest
568 // single-precision normal. Conversion fails because the exponent
569 // is too small.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700570 // 0xFB, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700571 QCBOREncode_AddDoubleToMap(&EC,
572 "smallest single minus more",
573 MAKE_DOUBLE(0x3800000000000000));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800574
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700575 // Just -2, which converts to a negative half-precision
576 // F9 C000 # primitive(49152)
577 QCBOREncode_AddDoubleToMapN(&EC, 3, -2.0);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800578
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700579 // 16777216, No precision loss converting to single
580 // FA 4B800000 # primitive(1266679808)
581 QCBOREncode_AddDoubleToMap(&EC, "single precision", 16777216);
582
583 // 16777217, One more than above. Too much precision for a single
584 // so no conversion.
Laurence Lundblade60f30e72020-07-21 11:16:01 -0700585 // 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700586 QCBOREncode_AddDoubleToMap(&EC, "single with precision loss", 16777217);
587
588 // Just a convenient marker when cutting and pasting encoded CBOR
589 QCBOREncode_AddSZStringToMapN(&EC, 1, "fin");
590
591 QCBOREncode_CloseMap(&EC);
592
593 UsefulBufC EncodedHalfs;
594 QCBORError uErr = QCBOREncode_Finish(&EC, &EncodedHalfs);
595 if(uErr) {
596 return -1;
597 }
598
599 if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) {
600 return -3;
601 }
602
603 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800604}
Laurence Lundblade585127a2020-07-15 03:25:24 -0700605#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700606
607
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700608/*
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700609[0.0, // Half
610 3.14, // Double
611 0.0, // Double
612 NaN, // Double
613 Infinity, // Double
614 0.0, // Half
615 3.140000104904175, // Single
616 0.0, // Single
617 NaN, // Single
618 Infinity, // Single
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700619 {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
620 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
621 */
622static const uint8_t spExpectedFloats[] = {
623 0x8B,
624 0xF9, 0x00, 0x00,
625 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
626 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 0xF9, 0x00, 0x00,
630 0xFA, 0x40, 0x48, 0xF5, 0xC3,
631 0xFA, 0x00, 0x00, 0x00, 0x00,
632 0xFA, 0x7F, 0xC0, 0x00, 0x00,
633 0xFA, 0x7F, 0x80, 0x00, 0x00,
634 0xA8,
635 0x18, 0x64,
636 0xF9, 0x00, 0x00,
637 0x18, 0x65,
638 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
639 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
640 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
641 0x18, 0x69,
642 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x18, 0x66,
644 0xF9, 0x00, 0x00,
645 0x18, 0x67,
646 0xFA, 0x40, 0x49, 0x0F, 0xDA,
647 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
648 0xFA, 0x40, 0x2D, 0xF8, 0x54,
649 0x18, 0x6A,
650 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700651
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200652#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700653static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700654 0x8B,
655 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
657 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0xFA, 0x00, 0x00, 0x00, 0x00,
661 0xFA, 0x40, 0x48, 0xF5, 0xC3,
662 0xFA, 0x00, 0x00, 0x00, 0x00,
663 0xFA, 0x7F, 0xC0, 0x00, 0x00,
664 0xFA, 0x7F, 0x80, 0x00, 0x00,
665 0xA8,
666 0x18, 0x64,
667 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 0x18, 0x65,
669 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
670 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
671 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
672 0x18, 0x69,
673 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x18, 0x66,
675 0xFA, 0x00, 0x00, 0x00, 0x00,
676 0x18, 0x67,
677 0xFA, 0x40, 0x49, 0x0F, 0xDA,
678 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
679 0xFA, 0x40, 0x2D, 0xF8, 0x54,
680 0x18, 0x6A,
681 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700682
683int32_t GeneralFloatEncodeTests()
684{
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700685 UsefulBufC ExpectedFloats;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700686#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700687 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700688 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700689 (void)spExpectedFloatsNoHalf; // Avoid unused variable error
690#else
691 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700692 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700693 (void)spExpectedFloats; // Avoid unused variable error
694#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700695
696 QCBOREncodeContext EC;
697 QCBOREncode_Init(&EC, OutBuffer);
698 QCBOREncode_OpenArray(&EC);
699
700 QCBOREncode_AddDouble(&EC, 0.0);
701 QCBOREncode_AddDouble(&EC, 3.14);
702 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
703 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
704 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
705
706 QCBOREncode_AddFloat(&EC, 0.0);
707 QCBOREncode_AddFloat(&EC, 3.14f);
708 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
709 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
710 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
711
712 QCBOREncode_OpenMap(&EC);
713
714 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
715 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
716 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
717 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
718
719 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
720 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
721 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
722 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
723
724 QCBOREncode_CloseMap(&EC);
725 QCBOREncode_CloseArray(&EC);
726
727 UsefulBufC Encoded;
728 QCBORError uErr = QCBOREncode_Finish(&EC, &Encoded);
729 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700730 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700731 }
732
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700733 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700734 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700735 }
736
737 return 0;
738}
739
740
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700741/* returns 0 if equivalent, non-zero if not equivalent */
742static int CHECK_EXPECTED_DOUBLE(double val, double expected)
743{
744 double diff = val - expected;
745
746 diff = fabs(diff);
747
748 if(diff > 0.000001) {
749 return 1;
750 } else {
751 return 0;
752 }
753}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200754#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700755
756
757int32_t GeneralFloatDecodeTests()
758{
759 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
760
761 QCBORDecodeContext DC;
762 QCBORDecode_Init(&DC, TestData, 0);
763
764 QCBORItem Item;
765 QCBORError uErr;
766
767 QCBORDecode_GetNext(&DC, &Item);
768 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
769 return -1;
770 }
771
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700772 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200773 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
774#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
775 || Item.uDataType != QCBOR_TYPE_DOUBLE
776 || Item.val.dfnum != 0.0
777#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
778 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700779 return -2;
780 }
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700781
782 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200783 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
784#ifndef USEFULBUF_DISABLE_ALL_FLOAT
785 || Item.uDataType != QCBOR_TYPE_DOUBLE
786 || Item.val.dfnum != 3.14
787#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
788 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700789 return -4;
790 }
791
792 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200793 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
794#ifndef USEFULBUF_DISABLE_ALL_FLOAT
795 || Item.uDataType != QCBOR_TYPE_DOUBLE
796 || Item.val.dfnum != 0.0
797#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
798 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700799 return -5;
800 }
801
802 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200803 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
804#ifndef USEFULBUF_DISABLE_ALL_FLOAT
805 || Item.uDataType != QCBOR_TYPE_DOUBLE
806 || !isnan(Item.val.dfnum)
807#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
808 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700809 return -6;
810 }
811
812 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200813 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
814#ifndef USEFULBUF_DISABLE_ALL_FLOAT
815 || Item.uDataType != QCBOR_TYPE_DOUBLE
816 || Item.val.dfnum != INFINITY
817#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
818 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700819 return -7;
820 }
821
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200822// Tests for normal config
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700823 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200824 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
825#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
826 || Item.uDataType != QCBOR_TYPE_DOUBLE
827 || Item.val.dfnum != 0.0
828#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
829 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700830 return -8;
831 }
832
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700833#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700834 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200835 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
836#ifndef USEFULBUF_DISABLE_ALL_FLOAT
837 || Item.uDataType != QCBOR_TYPE_DOUBLE
838 || CHECK_EXPECTED_DOUBLE(3.14, Item.val.dfnum)
839#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
840 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700841 return -9;
842 }
843
844 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 != 0.0
849#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
850 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700851 return -10;
852 }
853
854 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200855 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
856#ifndef USEFULBUF_DISABLE_ALL_FLOAT
857 || Item.uDataType != QCBOR_TYPE_DOUBLE
858 || !isnan(Item.val.dfnum)
859#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
860 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700861 return -11;
862 }
863
864 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200865 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
866#ifndef USEFULBUF_DISABLE_ALL_FLOAT
867 || Item.uDataType != QCBOR_TYPE_DOUBLE
868 || Item.val.dfnum != INFINITY
869#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
870 ) {
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700871 return -12;
872 }
873
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700874#else /* QCBOR_DISABLE_FLOAT_HW_USE */
875 // Tests for floating point HW use disabled
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700876 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200877 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
878#ifndef USEFULBUF_DISABLE_ALL_FLOAT
879 || Item.uDataType != QCBOR_TYPE_FLOAT
880 || CHECK_EXPECTED_DOUBLE(3.14, Item.val.fnum)
881#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
882 ) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700883 return -9;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700884 }
885
886 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200887 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
888#ifndef USEFULBUF_DISABLE_ALL_FLOAT
889 || Item.uDataType != QCBOR_TYPE_FLOAT
890 || Item.val.fnum != 0.0
891#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
892 ) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700893 return -10;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700894 }
895
896 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200897 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
898#ifndef USEFULBUF_DISABLE_ALL_FLOAT
899 || Item.uDataType != QCBOR_TYPE_FLOAT
900 || !isnan(Item.val.fnum)
901#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
902 ) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700903 return -11;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700904 }
905
906 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
909 || Item.uDataType != QCBOR_TYPE_FLOAT
910 || Item.val.fnum != INFINITY
911#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
912 ) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700913 return -12;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700914 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700915#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
916
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200917
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700918 /* Sufficent test coverage. Don't need to decode the rest */
919
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700920
921 // Now tests for spiffy decode
922 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200923#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700924 double d;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200925#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700926 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -0700927 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700928
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200929#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700930#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
931#ifndef QCBOR_DISABLE_FLOAT_HW_USE
932 // Spiffy decode tests for normal full float support
933 QCBORDecode_GetDouble(&DC, &d);
934 uErr = QCBORDecode_GetAndResetError(&DC);
935 if(uErr != QCBOR_SUCCESS ||
936 d != 0.0) {
937 return -100;
938 }
939
940 QCBORDecode_GetDouble(&DC, &d);
941 uErr = QCBORDecode_GetAndResetError(&DC);
942 if(uErr != QCBOR_SUCCESS ||
943 d != 3.14) {
944 return -101;
945 }
946
947 QCBORDecode_GetDouble(&DC, &d);
948 uErr = QCBORDecode_GetAndResetError(&DC);
949 if(uErr != QCBOR_SUCCESS ||
950 d != 0.0) {
951 return -102;
952 }
953
954 QCBORDecode_GetDouble(&DC, &d);
955 uErr = QCBORDecode_GetAndResetError(&DC);
956 if(uErr != QCBOR_SUCCESS ||
957 !isnan(d)) {
958 return -103;
959 }
960
961 QCBORDecode_GetDouble(&DC, &d);
962 uErr = QCBORDecode_GetAndResetError(&DC);
963 if(uErr != QCBOR_SUCCESS ||
964 d != INFINITY) {
965 return -104;
966 }
967
968 QCBORDecode_GetDouble(&DC, &d);
969 uErr = QCBORDecode_GetAndResetError(&DC);
970 if(uErr != QCBOR_SUCCESS ||
971 d != 0.0) {
972 return -105;
973 }
974
975 QCBORDecode_GetDouble(&DC, &d);
976 uErr = QCBORDecode_GetAndResetError(&DC);
977 if(uErr != QCBOR_SUCCESS ||
978 d != 3.140000104904175) {
979 return -106;
980 }
981
982 QCBORDecode_GetDouble(&DC, &d);
983 uErr = QCBORDecode_GetAndResetError(&DC);
984 if(uErr != QCBOR_SUCCESS ||
985 d != 0.0) {
986 return -107;
987 }
988
989 QCBORDecode_GetDouble(&DC, &d);
990 uErr = QCBORDecode_GetAndResetError(&DC);
991 if(uErr != QCBOR_SUCCESS ||
992 !isnan(d)) {
993 return -108;
994 }
995
996 QCBORDecode_GetDouble(&DC, &d);
997 uErr = QCBORDecode_GetAndResetError(&DC);
998 if(uErr != QCBOR_SUCCESS ||
999 d != INFINITY) {
1000 return -109;
1001 }
1002#else /* QCBOR_DISABLE_FLOAT_HW_USE */
1003 // Spiffy decode tests for float HW disabled
1004 QCBORDecode_GetDouble(&DC, &d);
1005 uErr = QCBORDecode_GetAndResetError(&DC);
1006 if(uErr != QCBOR_SUCCESS ||
1007 d != 0.0) {
1008 return -200;
1009 }
1010
1011 QCBORDecode_GetDouble(&DC, &d);
1012 uErr = QCBORDecode_GetAndResetError(&DC);
1013 if(uErr != QCBOR_SUCCESS ||
1014 d != 3.14) {
1015 return -201;
1016 }
1017
1018 QCBORDecode_GetDouble(&DC, &d);
1019 uErr = QCBORDecode_GetAndResetError(&DC);
1020 if(uErr != QCBOR_SUCCESS ||
1021 d != 0.0) {
1022 return -202;
1023 }
1024
1025 QCBORDecode_GetDouble(&DC, &d);
1026 uErr = QCBORDecode_GetAndResetError(&DC);
1027 if(uErr != QCBOR_SUCCESS ||
1028 !isnan(d)) {
1029 return -203;
1030 }
1031
1032 QCBORDecode_GetDouble(&DC, &d);
1033 uErr = QCBORDecode_GetAndResetError(&DC);
1034 if(uErr != QCBOR_SUCCESS ||
1035 d != INFINITY) {
1036 return -204;
1037 }
1038
1039 QCBORDecode_GetDouble(&DC, &d);
1040 uErr = QCBORDecode_GetAndResetError(&DC);
1041 if(uErr != QCBOR_SUCCESS ||
1042 d != 0.0) {
1043 return -205;
1044 }
1045
1046 QCBORDecode_GetDouble(&DC, &d);
1047 uErr = QCBORDecode_GetAndResetError(&DC);
1048 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED) {
1049 return -206;
1050 }
1051
1052 QCBORDecode_GetDouble(&DC, &d);
1053 uErr = QCBORDecode_GetAndResetError(&DC);
1054 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED) {
1055 return -207;
1056 }
1057
1058 QCBORDecode_GetDouble(&DC, &d);
1059 uErr = QCBORDecode_GetAndResetError(&DC);
1060 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED ) {
1061 return -208;
1062 }
1063
1064 QCBORDecode_GetDouble(&DC, &d);
1065 uErr = QCBORDecode_GetAndResetError(&DC);
1066 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED ) {
1067 return -209;
1068 }
1069
1070
1071#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1072#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
1073 // Spiffy decode tests for half-precision disabled
1074 QCBORDecode_GetDouble(&DC, &d);
1075 uErr = QCBORDecode_GetAndResetError(&DC);
1076 if(uErr != QCBOR_ERR_HALF_PRECISION_DISABLED) {
1077 return -300;
1078 }
1079
1080 QCBORDecode_GetDouble(&DC, &d);
1081 uErr = QCBORDecode_GetAndResetError(&DC);
1082 if(uErr != QCBOR_SUCCESS ||
1083 d != 3.14) {
1084 return -301;
1085 }
1086
1087 QCBORDecode_GetDouble(&DC, &d);
1088 uErr = QCBORDecode_GetAndResetError(&DC);
1089 if(uErr != QCBOR_SUCCESS ||
1090 d != 0.0) {
1091 return -302;
1092 }
1093
1094 QCBORDecode_GetDouble(&DC, &d);
1095 uErr = QCBORDecode_GetAndResetError(&DC);
1096 if(uErr != QCBOR_SUCCESS ||
1097 !isnan(d)) {
1098 return -303;
1099 }
1100
1101 QCBORDecode_GetDouble(&DC, &d);
1102 uErr = QCBORDecode_GetAndResetError(&DC);
1103 if(uErr != QCBOR_SUCCESS ||
1104 d != INFINITY) {
1105 return -304;
1106 }
1107
1108 QCBORDecode_GetDouble(&DC, &d);
1109 uErr = QCBORDecode_GetAndResetError(&DC);
1110 if(uErr != QCBOR_ERR_HALF_PRECISION_DISABLED) {
1111 return -305;
1112 }
1113
1114 QCBORDecode_GetDouble(&DC, &d);
1115 uErr = QCBORDecode_GetAndResetError(&DC);
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001116#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001117 if(uErr != QCBOR_SUCCESS ||
1118 d != 3.140000104904175) {
1119 return -306;
1120 }
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001121#else
1122 // Disabled use of HW to convert from single to double
1123 if(uErr != QCBOR_ERR_HW_FLOAT_DISABLED) {
1124 return -316;
1125 }
1126#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1127
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001128
1129 QCBORDecode_GetDouble(&DC, &d);
1130 uErr = QCBORDecode_GetAndResetError(&DC);
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001131#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001132 if(uErr != QCBOR_SUCCESS ||
1133 d != 0.0) {
1134 return -307;
1135 }
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001136#else
1137 // Disabled use of HW to convert from single to double
1138 if(uErr == QCBOR_SUCCESS) {
1139 return -317;
1140 }
1141#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1142
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001143
1144 QCBORDecode_GetDouble(&DC, &d);
1145 uErr = QCBORDecode_GetAndResetError(&DC);
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001146#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001147 if(uErr != QCBOR_SUCCESS ||
1148 !isnan(d)) {
1149 return -308;
1150 }
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001151#else
1152 // Disabled use of HW to convert from single to double
1153 if(uErr == QCBOR_SUCCESS) {
1154 return -318;
1155 }
1156#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001157
1158 QCBORDecode_GetDouble(&DC, &d);
1159 uErr = QCBORDecode_GetAndResetError(&DC);
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001160#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001161 if(uErr != QCBOR_SUCCESS ||
1162 d != INFINITY) {
1163 return -309;
1164 }
Laurence Lundbladeb8e19aa2020-10-07 20:59:11 -07001165#else
1166 // Disabled use of HW to convert from single to double
1167 if(uErr == QCBOR_SUCCESS) {
1168 return -318;
1169 }
1170#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001171#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001172#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001173
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001174 return 0;
1175}
1176
1177
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001178
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001179#ifdef NAN_EXPERIMENT
1180/*
1181 Code for checking what the double to float cast does with
1182 NaNs. Not run as part of tests. Keep it around to
1183 be able to check various platforms and CPUs.
1184 */
1185
1186#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1187#define DOUBLE_NUM_EXPONENT_BITS (11)
1188#define DOUBLE_NUM_SIGN_BITS (1)
1189
1190#define DOUBLE_SIGNIFICAND_SHIFT (0)
1191#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1192#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1193
1194#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1195#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1196#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1197#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1198
1199
1200static int NaNExperiments() {
1201 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1202 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1203 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001204
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001205 float f1 = (float)dqNaN;
1206 float f2 = (float)dsNaN;
1207 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001208
1209
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001210 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1211 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1212 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001213
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001214 // Result of this on x86 is that every NaN is a qNaN. The intel
1215 // CVTSD2SS instruction ignores the NaN payload and even converts
1216 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001217
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001218 return 0;
1219}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001220#endif /* NAN_EXPERIMENT */