blob: 40ab80ae6048095def0db268ccaa9ea1b4423a51 [file] [log] [blame]
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001/* ==========================================================================
2 * float_tests.c -- tests for float and conversion to/from half-precision
3 *
4 * Copyright (c) 2018-2024, Laurence Lundblade. All rights reserved.
5 * Copyright (c) 2021, Arm Limited. All rights reserved.
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * See BSD-3-Clause license in README.md
10 *
11 * Created on 9/19/18
12 * ========================================================================= */
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 Lundblade83dbf5c2024-01-07 19:17:52 -070019#include <math.h> /* For INFINITY and NAN and isnan() */
Laurence Lundblade585127a2020-07-15 03:25:24 -070020
Laurence Lundblade16a207a2021-09-18 17:22:46 -070021
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070022
23/* Make a test results code that includes three components. Return code
24 * is xxxyyyzzz where zz is the error code, yy is the test number and
25 * zz is check being performed
Laurence Lundblade16a207a2021-09-18 17:22:46 -070026 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070027static inline int32_t
28MakeTestResultCode(uint32_t uTestCase,
29 uint32_t uTestNumber,
30 QCBORError uErrorCode)
Laurence Lundblade16a207a2021-09-18 17:22:46 -070031{
32 uint32_t uCode = (uTestCase * 1000000) +
33 (uTestNumber * 1000) +
34 (uint32_t)uErrorCode;
35 return (int32_t)uCode;
36}
37
38
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -070039#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -070040
Laurence Lundbladed711fb22018-09-26 14:35:22 -070041#include "half_to_double_from_rfc7049.h"
Laurence Lundblade68a13352018-09-23 02:19:54 -070042
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080043
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070044struct DoubleTestCase {
45 double dNumber;
46 double fNumber;
47 UsefulBufC Preferred;
48 UsefulBufC NotPreferred;
49 UsefulBufC CDE;
50 UsefulBufC DCBOR;
51};
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -070052
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070053/* Boundaries for all destination conversions to test at.
54 *
55 * smallest subnormal single 1.401298464324817e-45 2^^-149
56 * largest subnormal single 1.1754942106924411e-38 2^^-126
57 * smallest normal single 1.1754943508222875e-38
58 * largest single 3.4028234663852886E+38
59 *
60 * smallest subnormal half 5.9604644775390625E-8
61 * largest subnormal half 6.097555160522461E-5
62 * smallest normal half 6.103515625E-5
63 * largest half 65504.0
64 *
65 * Boundaries for origin conversions
66 * smallest subnormal double 5.0e-324 2^^-1074
67 * largest subnormal double
68 * smallest normal double 2.2250738585072014e-308 2^^-1022
69 * largest normal double 1.7976931348623157e308 2^^-1023
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070070 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070071
72/* Always four lines per test case so shell scripts can process into
73 * other formats. CDE and DCBOR standards are not complete yet,
74 * encodings are a guess. C string literals are used because they
75 * are the shortest notation. They are used __with a length__ . Null
76 * termination doesn't work because * there are zero bytes.
77 */
78static const struct DoubleTestCase DoubleTestCases[] = {
79 /* Zero */
80 {0.0, 0.0f,
81 {"\xF9\x00\x00", 3}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -070082 {"\xF9\x00\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070083
84 /* Negative Zero */
85 {-0.0, -0.0f,
86 {"\xF9\x80\x00", 3}, {"\xFB\x80\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -070087 {"\xF9\x80\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070088
89 /* NaN */
90 {NAN, NAN,
91 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
92 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
93
94 /* Infinity */
95 {INFINITY, INFINITY,
96 {"\xF9\x7C\x00", 3}, {"\xFB\x7F\xF0\x00\x00\x00\x00\x00\x00", 9},
97 {"\xF9\x7C\x00", 3}, {"\xF9\x7C\x00", 3}},
98
99 /* Negative Infinity */
100 {-INFINITY, -INFINITY,
101 {"\xF9\xFC\x00", 3}, {"\xFB\xFF\xF0\x00\x00\x00\x00\x00\x00", 9},
102 {"\xF9\xFC\x00", 3}, {"\xF9\xFC\x00", 3}},
103
104 /* 1.0 */
105 {1.0, 1.0f,
106 {"\xF9\x3C\x00", 3}, {"\xFB\x3F\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700107 {"\xF9\x3C\x00", 3}, {"\x01", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700108
109 /* -2.0 -- a negative number that is not zero */
110 {-2.0, -2.0f,
111 {"\xF9\xC0\x00", 3}, {"\xFB\xC0\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700112 {"\xF9\xC0\x00", 3}, {"\x21", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700113
114 /* 1/3 */
115 {0.333251953125, 0.333251953125f,
116 {"\xF9\x35\x55", 3}, {"\xFB\x3F\xD5\x54\x00\x00\x00\x00\x00", 9},
117 {"\xF9\x35\x55", 3}, {"\xF9\x35\x55", 3}},
118
119 /* 5.9604644775390625E-8 -- smallest half-precision subnormal */
120 {5.9604644775390625E-8, 0.0f,
121 {"\xF9\x00\x01", 3}, {"\xFB\x3E\x70\x00\x00\x00\x00\x00\x00", 9},
122 {"\xF9\x00\x01", 3}, {"\xF9\x00\x01", 3}},
123
124 /* 3.0517578125E-5 -- a half-precision subnormal */
125 {3.0517578125E-5, 0.0f,
126 {"\xF9\x02\x00", 3}, {"\xFB\x3F\x00\x00\x00\x00\x00\x00\x00", 9},
127 {"\xF9\x02\x00", 3}, {"\xF9\x02\x00", 3}},
128
129 /* 6.097555160522461E-5 -- largest half-precision subnormal */
130 {6.097555160522461E-5, 0.0f,
131 {"\xF9\x03\xFF", 3}, {"\xFB\x3F\x0F\xF8\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700132 {"\xF9\x03\xFF", 3}, {"\xF9\x03\xFF", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700133
134 /* 6.103515625E-5 -- smallest possible half-precision normal */
135 {6.103515625E-5, 0.0f,
136 {"\xF9\04\00", 3}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x00", 9},
137 {"\xF9\04\00", 3}, {"\xF9\04\00", 3}},
138
139 /* 6.1035156250000014E-5 -- slightly larger than smallest half-precision normal */
140 {6.1035156250000014E-5, 6.1035156250000014E-5f,
141 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9},
142 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}},
143
144 /* 6.1035156249999993E-5 -- slightly smaller than smallest half-precision normal */
145 {6.1035156249999993E-5, 0.0f,
146 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
147 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
148
149 /* 65504.0 -- largest possible half-precision */
150 {65504.0, 0.0f,
151 {"\xF9\x7B\xFF", 3}, {"\xFB\x40\xEF\xFC\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700152 {"\xF9\x7B\xFF", 3}, {"\x19\xFF\xE0", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700153
154 /* 65504.1 -- exponent too large and too much precision to convert */
155 {65504.1, 0.0f,
156 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9},
157 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}},
158
159 /* 65536.0 -- exponent too large but not too much precision for single */
160 {65536.0, 65536.0f,
161 {"\xFA\x47\x80\x00\x00", 5}, {"\xFB\x40\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700162 {"\xFA\x47\x80\x00\x00", 5}, {"\x1A\x00\x01\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700163
164 /* 1.401298464324817e-45 -- smallest single subnormal */
165 {1.401298464324817e-45, 1.40129846E-45f,
166 {"\xFA\x00\x00\x00\x01", 5}, {"\xFB\x36\xA0\x00\x00\x00\x00\x00\x00", 9},
167 {"\xFA\x00\x00\x00\x01", 5}, {"\xFA\x00\x00\x00\x01", 5}},
168
Laurence Lundblade240ca822024-01-16 11:11:00 -0700169 /* 5.8774717541114375E-39 -- slightly smaller than the smallest single normal */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700170 {5.8774717541114375E-39, 5.87747175E-39f,
171 {"\xFA\x00\x40\x00\x00", 5}, {"\xFB\x38\x00\x00\x00\x00\x00\x00\x00", 9},
172 {"\xFA\x00\x40\x00\x00", 5}, {"\xFA\x00\x40\x00\x00", 5}},
173
174 /* 1.1754942106924411e-38 -- largest single subnormal */
175 {1.1754942106924411E-38, 1.17549421E-38f,
176 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFB\x38\x0f\xff\xff\xC0\x00\x00\x00", 9},
177 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFA\x00\x7f\xff\xff", 5} },
178
179 /* 1.1754943508222874E-38 -- slightly bigger than smallest single normal */
180 {1.1754943508222874E-38, 0.0f,
181 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9},
182 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}},
183
184 /* 1.1754943508222875e-38 -- smallest single normal */
185 {1.1754943508222875e-38, 1.17549435E-38f,
186 {"\xFA\x00\x80\x00\x00", 5}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x00", 9},
187 {"\xFA\x00\x80\x00\x00", 5}, {"\xFA\x00\x80\x00\x00", 5}},
188
189 /* 1.1754943508222875e-38 -- slightly bigger than smallest single normal */
190 {1.1754943508222878e-38, 0.0f,
191 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9},
192 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}},
193
194 /* 16777216 -- converts to single without loss */
195 {16777216, 16777216,
196 {"\xFA\x4B\x80\x00\x00", 5}, {"\xFB\x41\x70\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700197 {"\xFA\x4B\x80\x00\x00", 5}, {"\x1A\x01\x00\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700198
199 /* 16777217 -- one more than above and fails conversion to single */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700200 {16777217, 16777217,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700201 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700202 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\x1A\x01\x00\x00\x01", 5}},
203
204 /* 4294967295 -- UINT32_MAX */
205 {4294967295, 0,
206 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
207 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x1A\xFF\xFF\xFF\xFF", 5}},
208
209 /* exponent 51 */
210 {4503599627370495, 0,
211 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9},
212 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\x1B\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
213
214 /* exponent 52 */
215 {9007199254740991, 0,
216 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
217 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x1F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
218
219 /* 18014398509481982 -- 52 bits set in double; 18014398509481983 not representable as a double */
220 {18014398509481982, 0,
221 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
222 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x3F\xFF\xFF\xFF\xFF\xFF\xFE", 9}},
223
224 /* 18014398509481984 -- exponent is 54 */
225 {18014398509481984, 0,
226 {"\xFA\x5A\x80\x00\x00", 5}, {"\xFB\x43\x50\x00\x00\x00\x00\x00\x00", 9},
227 {"\xFA\x5A\x80\x00\x00", 5}, {"\x1B\x00\x40\x00\x00\x00\x00\x00\x00", 9}},
228
229 /* -4294967295 -- Negative UINT32_MAX */
230 {-4294967295, 0,
231 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
232 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x3A\xFF\xFF\xFF\xFE", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700233
234 /* 3.4028234663852886E+38 -- largest possible single normal */
235 {3.4028234663852886E+38, 3.40282347E+38f,
236 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
237 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFA\x7F\x7F\xFF\xFF", 5}},
238
239 /* 3.402823466385289E+38 -- slightly larger than largest possible single */
240 {3.402823466385289E+38, 0.0f,
241 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9},
242 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}},
243
244 /* 3.402823669209385e+38 -- exponent larger by one than largest possible single */
245 {3.402823669209385e+38, 0.0f,
246 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9},
247 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}},
248
249 /* 5.0e-324 -- smallest double subnormal normal */
250 {5.0e-324, 0.0f,
251 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9},
252 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}},
253
254 /* 2.2250738585072009E−308 -- largest double subnormal */
255 {2.2250738585072009e-308, 0.0f,
256 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
257 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
258
259 /* 2.2250738585072014e-308 -- smallest double normal */
260 {2.2250738585072014e-308, 0.0f,
261 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9},
262 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}},
263
264 /* 1.7976931348623157E308 -- largest double normal */
265 {1.7976931348623157e308, 0.0f,
266 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
267 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
268
269 /* List terminator */
270 {0.0, 0.0f, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700271};
272
273
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700274struct NaNTestCase {
275 uint64_t uDouble;
276 uint32_t uSingle;
277 UsefulBufC Preferred;
278 UsefulBufC NotPreferred;
279 UsefulBufC CDE;
280 UsefulBufC DCBOR;
281};
282
283/* Always four lines per test case so shell scripts can process into
284 * other formats. CDE and DCBOR standards are not complete yet,
285 * encodings are a guess. C string literals are used because they
286 * are the shortest notation. They are used __with a length__ . Null
287 * termination doesn't work because there are zero bytes.
288 */
289static const struct NaNTestCase NaNTestCases[] = {
290
291 /* Payload with most significant bit set, a qNaN by most implementations */
292 {0x7ff8000000000000, 0x00000000,
293 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
294 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
295
296 /* Payload with single rightmost set */
297 {0x7ff8000000000001, 0x00000000,
298 {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9},
299 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
300
301 /* Payload with 10 leftmost bits set -- converts to half */
302 {0x7ffffc0000000000, 0x00000000,
303 {"\xF9\x7F\xFF", 3}, {"\xFB\x7F\xFF\xFC\x00\x00\x00\x00\x00", 9},
304 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
305
306 /* Payload with 10 rightmost bits set -- cannot convert to half */
307 {0x7ff80000000003ff, 0x00000000,
308 {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9},
309 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
310
311 /* Payload with 23 leftmost bits set -- converts to a single */
312 {0x7ffFFFFFE0000000, 0x7fffffff,
313 {"\xFA\x7F\xFF\xFF\xFF", 5}, {"\xFB\x7F\xFF\xFF\xFF\xE0\x00\x00\x00", 9},
314 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
315
316 /* Payload with 24 leftmost bits set -- fails to convert to a single */
317 {0x7ffFFFFFF0000000, 0x00000000,
318 {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9}, {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9},
319 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
320
321 /* Payload with all bits set */
322 {0x7fffffffffffffff, 0x00000000,
323 {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700324 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700325
326 /* List terminator */
327 {0, 0, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
328};
329
330
331
Laurence Lundblade240ca822024-01-16 11:11:00 -0700332#include <stdio.h>
333extern void foooo(void);
334
335
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700336/* Public function. See float_tests.h
337 *
338 * This is the main test of floating-point encoding / decoding. It is
339 * data-driven by the above tables. It works better than tests below that
340 * it mostly replaces because it tests one number at a time, rather than
341 * putting them all in a map. It is much easier to debug test failures
342 * and to add new tests. */
343int32_t
344FloatValuesTests(void)
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700345{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700346 unsigned int uTestIndex;
347 const struct DoubleTestCase *pTestCase;
348 const struct NaNTestCase *pNaNTestCase;
349 MakeUsefulBufOnStack( TestOutBuffer, 20);
350 UsefulBufC TestOutput;
351 QCBOREncodeContext EnCtx;
352 QCBORError uErr;
353 QCBORDecodeContext DCtx;
354 QCBORItem Item;
355 uint64_t uDecoded;
356#ifdef QCBOR_DISABLE_FLOAT_HW_USE
357 uint32_t uDecoded2;
358#endif
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700359
Laurence Lundblade240ca822024-01-16 11:11:00 -0700360 foooo();
361
362 {
363 uint64_t xxx = 0x4350000000000000 - 2;
364
365 for(uint64_t i = 0; i < 5; i++) {
366
367 uint64_t yyy = xxx + i;
368
369 double d = UsefulBufUtil_CopyUint64ToDouble(yyy);
370
371 printf("%llx %f\n", yyy, d);
372 }
373
374
375
376 }
377
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700378 /* Test a variety of doubles */
379 for(uTestIndex = 0; DoubleTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
380 pTestCase = &DoubleTestCases[uTestIndex];
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700381
Laurence Lundblade240ca822024-01-16 11:11:00 -0700382 //if(pTestCase->dNumber == -16325548649218046.0) {
383 if(uTestIndex == 26) {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700384 uErr = 99; /* For setting break points for particular tests */
385 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800386
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700387 /* Number Encode of Preferred */
388 QCBOREncode_Init(&EnCtx, TestOutBuffer);
389 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
390 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800391
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700392 if(uErr != QCBOR_SUCCESS) {
393 return MakeTestResultCode(uTestIndex, 1, uErr);;
394 }
395 if(UsefulBuf_Compare(TestOutput, pTestCase->Preferred)) {
396 return MakeTestResultCode(uTestIndex, 1, 200);
397 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700398
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700399 /* Number Encode of Not Preferred */
400 QCBOREncode_Init(&EnCtx, TestOutBuffer);
401 QCBOREncode_AddDoubleNoPreferred(&EnCtx, pTestCase->dNumber);
402 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade68a13352018-09-23 02:19:54 -0700403
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700404 if(uErr != QCBOR_SUCCESS) {
405 return MakeTestResultCode(uTestIndex, 2, uErr);;
406 }
407 if(UsefulBuf_Compare(TestOutput, pTestCase->NotPreferred)) {
408 return MakeTestResultCode(uTestIndex, 2, 200);
409 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800410
Laurence Lundblade240ca822024-01-16 11:11:00 -0700411 /* Number Encode of CDE */
412 QCBOREncode_Init(&EnCtx, TestOutBuffer);
413 QCBOREncode_SerializationCDE(&EnCtx);
414 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
415 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
416
417 if(uErr != QCBOR_SUCCESS) {
418 return MakeTestResultCode(uTestIndex, 20, uErr);;
419 }
420 if(UsefulBuf_Compare(TestOutput, pTestCase->CDE)) {
421 return MakeTestResultCode(uTestIndex, 21, 200);
422 }
423
424 /* Number Encode of dCBOR */
425 QCBOREncode_Init(&EnCtx, TestOutBuffer);
426 QCBOREncode_SerializationdCBOR(&EnCtx);
427 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
428 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
429
430 if(uErr != QCBOR_SUCCESS) {
431 return MakeTestResultCode(uTestIndex, 20, uErr);;
432 }
433 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
434 return MakeTestResultCode(uTestIndex, 21, 200);
435 }
436
437
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700438 /* Number Decode of Preferred */
439 QCBORDecode_Init(&DCtx, pTestCase->Preferred, 0);
440 uErr = QCBORDecode_GetNext(&DCtx, &Item);
441 if(uErr != QCBOR_SUCCESS) {
442 return MakeTestResultCode(uTestIndex, 3, uErr);;
443 }
444#ifndef QCBOR_DISABLE_FLOAT_HW_USE
445 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
446 return MakeTestResultCode(uTestIndex, 4, 0);
447 }
448 if(isnan(pTestCase->dNumber)) {
449 if(!isnan(Item.val.dfnum)) {
450 return MakeTestResultCode(uTestIndex, 5, 0);
451 }
452 } else {
453 if(Item.val.dfnum != pTestCase->dNumber) {
454 return MakeTestResultCode(uTestIndex, 6, 0);
455 }
456 }
457#else /* QCBOR_DISABLE_FLOAT_HW_USE */
458 /* When QCBOR_DISABLE_FLOAT_HW_USE is set, single-precision is not
459 * converted to double when decoding, so test differently. len == 5
460 * indicates single-precision in the encoded CBOR. */
461 if(pTestCase->Preferred.len == 5) {
462 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
463 return MakeTestResultCode(uTestIndex, 4, 0);
464 }
465 if(isnan(pTestCase->dNumber)) {
466 if(!isnan(Item.val.fnum)) {
467 return MakeTestResultCode(uTestIndex, 5, 0);
468 }
469 } else {
470 if(Item.val.fnum != pTestCase->fNumber) {
471 return MakeTestResultCode(uTestIndex, 6, 0);
472 }
473 }
474 } else {
475 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
476 return MakeTestResultCode(uTestIndex, 4, 0);
477 }
478 if(isnan(pTestCase->dNumber)) {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700479 if(!isnan(Item.val.dfnum)) {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700480 return MakeTestResultCode(uTestIndex, 5, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700481 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700482 } else {
483 if(Item.val.dfnum != pTestCase->dNumber) {
484 return MakeTestResultCode(uTestIndex, 6, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700485 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700486 }
487 }
488#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700489
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700490 /* Number Decode of Not Preferred */
491 QCBORDecode_Init(&DCtx, pTestCase->NotPreferred, 0);
492 uErr = QCBORDecode_GetNext(&DCtx, &Item);
493 if(uErr != QCBOR_SUCCESS) {
494 return MakeTestResultCode(uTestIndex, 7, uErr);;
495 }
496 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
497 return MakeTestResultCode(uTestIndex, 8, 0);
498 }
499 if(isnan(pTestCase->dNumber)) {
500 if(!isnan(Item.val.dfnum)) {
501 return MakeTestResultCode(uTestIndex, 9, 0);
502 }
503 } else {
504 if(Item.val.dfnum != pTestCase->dNumber) {
505 return MakeTestResultCode(uTestIndex, 10, 0);
506 }
507 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700508
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700509 }
510
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700511 /* Test a variety of NaNs with payloads */
512 for(uTestIndex = 0; NaNTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
513 pNaNTestCase = &NaNTestCases[uTestIndex];
514
515
516 if(uTestIndex == 4) {
517 uErr = 99; /* For setting break points for particular tests */
518 }
519
520 /* NaN Encode of Preferred */
521 QCBOREncode_Init(&EnCtx, TestOutBuffer);
522 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
523 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
524 if(uErr != QCBOR_SUCCESS) {
525 return MakeTestResultCode(uTestIndex+100, 10, uErr);;
526 }
527 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->Preferred)) {
528 return MakeTestResultCode(uTestIndex+100, 10, 200);
529 }
530
531#ifdef QCBOR_COMPARE_TO_HW_NAN_CONVERSION
532 {
533 /* This test is off by default. It's purpose is to check
534 * QCBOR's mask-n-shift implementation against the HW/CPU
535 * instructions that do conversion between double and single.
536 * It is off because it is only used on occasion to verify
537 * QCBOR and because it is suspected that some HW/CPU does
538 * implement this correctly. NaN payloads are an obscure
539 * feature. */
540 float f;
541 double d, d2;
542
543 d = UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uNumber);
544
545 /* Cast the double to a single and then back to a double and
546 * see if they are equal. If so, then the NaN payload doesn't
547 * have any bits that are lost when converting to single and
548 * it can be safely converted.
549 *
550 * This test can't be done for half-precision because it is
551 * not widely supported.
552 */
553 f = (float)d;
554 d2 = (double)f;
555
556 /* The length of encoded doubles is 9, singles 5 and halves
557 * 3. If there are NaN payload bits that can't be converted,
558 * then the length must be 9.
559 */
560 if((uint64_t)d != (uint64_t)d2 && pNaNTestCase->Preferred.len != 9) {
561 /* QCBOR conversion not the same as HW conversion */
562 return MakeTestResultCode(uTestIndex, 9, 200);
563 }
564 }
565#endif /* QCBOR_COMPARE_TO_HW_NAN_CONVERSION */
566
567
568 /* NaN Encode of Not Preferred */
569 QCBOREncode_Init(&EnCtx, TestOutBuffer);
570 QCBOREncode_AddDoubleNoPreferred(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
571 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
572 if(uErr != QCBOR_SUCCESS) {
573 return MakeTestResultCode(uTestIndex+100, 11, uErr);;
574 }
575 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->NotPreferred)) {
576 return MakeTestResultCode(uTestIndex+100, 11, 200);
577 }
578
Laurence Lundblade240ca822024-01-16 11:11:00 -0700579 /* NaN Decode of Not Preferred */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700580 QCBORDecode_Init(&DCtx, pNaNTestCase->Preferred, 0);
581 uErr = QCBORDecode_GetNext(&DCtx, &Item);
582 if(uErr != QCBOR_SUCCESS) {
583 return MakeTestResultCode(uTestIndex+100, 12, uErr);
584 }
585
586#ifndef QCBOR_DISABLE_FLOAT_HW_USE
587
588 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
589 if(uDecoded != pNaNTestCase->uDouble) {
590 return MakeTestResultCode(uTestIndex+100, 12, 200);
591 }
592#else /* QCBOR_DISABLE_FLOAT_HW_USE */
593 if(pNaNTestCase->Preferred.len == 5) {
594 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
595 return MakeTestResultCode(uTestIndex, 4, 0);
596 }
597
598 uDecoded2 = UsefulBufUtil_CopyFloatToUint32(Item.val.fnum);
599
600 if(uDecoded2 != pNaNTestCase->uSingle) {
601 return MakeTestResultCode(uTestIndex, 4, 0);
602 }
603 } else {
604 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
605 return MakeTestResultCode(uTestIndex, 4, 0);
606 }
607 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
608 if(uDecoded != pNaNTestCase->uDouble) {
609 return MakeTestResultCode(uTestIndex+100, 12, 200);
610 }
611 }
612#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
613
614 /* NaN Decode of Not Preferred */
615 QCBORDecode_Init(&DCtx, pNaNTestCase->NotPreferred, 0);
616 uErr = QCBORDecode_GetNext(&DCtx, &Item);
617 if(uErr != QCBOR_SUCCESS) {
618 return MakeTestResultCode(uTestIndex+100, 13, uErr);
619 }
620 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
621 if(uDecoded != pNaNTestCase->uDouble) {
622 return MakeTestResultCode(uTestIndex+100, 13, 200);
623 }
Laurence Lundblade240ca822024-01-16 11:11:00 -0700624
625
626 /* NaN Encode of DCBOR */
627 QCBOREncode_Init(&EnCtx, TestOutBuffer);
628 QCBOREncode_SerializationdCBOR(&EnCtx);
629 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
630 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
631 if(uErr != QCBOR_SUCCESS) {
632 return MakeTestResultCode(uTestIndex+100, 11, uErr);;
633 }
634 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->DCBOR)) {
635 return MakeTestResultCode(uTestIndex+100, 11, 200);
636 }
637
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700638 }
639
640 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800641}
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700642
643
644
645/* Public function. See float_tests.h */
646int32_t
647HalfPrecisionAgainstRFCCodeTest(void)
648{
649 QCBORItem Item;
650 QCBORDecodeContext DC;
651 unsigned char pbHalfBytes[2];
652 uint8_t uHalfPrecInitialByte;
653 double d;
654 UsefulBuf_MAKE_STACK_UB(EncodedBytes, 3);
655 UsefulOutBuf UOB;
656 uint32_t uHalfP;
657
658
659 for(uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
660 pbHalfBytes[1] = (uint8_t)(uHalfP & 0xff);
661 pbHalfBytes[0] = (uint8_t)(uHalfP >> 8); /* uHalfP is always less than 0xffff */
662 d = decode_half(pbHalfBytes);
663
664 /* Construct the CBOR for the half-precision float by hand */
665 UsefulOutBuf_Init(&UOB, EncodedBytes);
666
667 uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); /* 0xf9 */
668 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); /* initial byte */
669 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP); /* argument */
670
671 /* Now parse the hand-constructed CBOR. This will invoke the
672 * conversion to a float
673 */
674 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
675 QCBORDecode_GetNext(&DC, &Item);
676 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
677 return -1;
678 }
679
680 if(isnan(d)) {
681 /* The RFC code uses the native instructions which may or may not
682 * handle sNaN, qNaN and NaN payloads correctly. This test just
683 * makes sure it is a NaN and doesn't worry about the type of NaN
684 */
685 if(!isnan(Item.val.dfnum)) {
686 return -3;
687 }
688 } else {
689 if(Item.val.dfnum != d) {
690 return -2;
691 }
692 }
693 }
694 return 0;
695}
696
Laurence Lundblade585127a2020-07-15 03:25:24 -0700697#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700698
699
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700700/*
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700701 * Some encoded floating point numbers that are used for both
702 * encode and decode tests.
703 *
704 * [0.0, // Half
705 * 3.14, // Double
706 * 0.0, // Double
707 * NaN, // Double
708 * Infinity, // Double
709 * 0.0, // Half (Duplicate because of use in encode tests)
710 * 3.140000104904175, // Single
711 * 0.0, // Single
712 * NaN, // Single
713 * Infinity, // Single
714 * {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
715 * 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700716 */
717static const uint8_t spExpectedFloats[] = {
718 0x8B,
719 0xF9, 0x00, 0x00,
720 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
721 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0xF9, 0x00, 0x00,
725 0xFA, 0x40, 0x48, 0xF5, 0xC3,
726 0xFA, 0x00, 0x00, 0x00, 0x00,
727 0xFA, 0x7F, 0xC0, 0x00, 0x00,
728 0xFA, 0x7F, 0x80, 0x00, 0x00,
729 0xA8,
730 0x18, 0x64,
731 0xF9, 0x00, 0x00,
732 0x18, 0x65,
733 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
734 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
735 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
736 0x18, 0x69,
737 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
738 0x18, 0x66,
739 0xF9, 0x00, 0x00,
740 0x18, 0x67,
741 0xFA, 0x40, 0x49, 0x0F, 0xDA,
742 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
743 0xFA, 0x40, 0x2D, 0xF8, 0x54,
744 0x18, 0x6A,
745 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700746
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200747#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700748static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700749 0x8B,
750 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
751 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
752 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
753 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
755 0xFA, 0x00, 0x00, 0x00, 0x00,
756 0xFA, 0x40, 0x48, 0xF5, 0xC3,
757 0xFA, 0x00, 0x00, 0x00, 0x00,
758 0xFA, 0x7F, 0xC0, 0x00, 0x00,
759 0xFA, 0x7F, 0x80, 0x00, 0x00,
760 0xA8,
761 0x18, 0x64,
762 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 0x18, 0x65,
764 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
765 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
766 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
767 0x18, 0x69,
768 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x18, 0x66,
770 0xFA, 0x00, 0x00, 0x00, 0x00,
771 0x18, 0x67,
772 0xFA, 0x40, 0x49, 0x0F, 0xDA,
773 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
774 0xFA, 0x40, 0x2D, 0xF8, 0x54,
775 0x18, 0x6A,
776 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700777
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700778
779/* Public function. See float_tests.h */
780int32_t
781GeneralFloatEncodeTests(void)
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700782{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700783 /* See FloatNumberTests() for tests that really cover lots of float values.
784 * Add new tests for new values or decode modes there.
785 * This test is primarily to cover all the float encode methods. */
786
787 UsefulBufC Encoded;
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700788 UsefulBufC ExpectedFloats;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700789 QCBORError uErr;
790
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700791#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700792 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700793 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700794 (void)spExpectedFloatsNoHalf; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700795#else
796 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700797 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700798 (void)spExpectedFloats; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700799#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700800
801 QCBOREncodeContext EC;
802 QCBOREncode_Init(&EC, OutBuffer);
803 QCBOREncode_OpenArray(&EC);
804
805 QCBOREncode_AddDouble(&EC, 0.0);
806 QCBOREncode_AddDouble(&EC, 3.14);
807 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
808 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
809 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
810
811 QCBOREncode_AddFloat(&EC, 0.0);
812 QCBOREncode_AddFloat(&EC, 3.14f);
813 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
814 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
815 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
816
817 QCBOREncode_OpenMap(&EC);
818
819 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
820 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
821 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
822 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
823
824 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
825 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
826 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
827 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
828
829 QCBOREncode_CloseMap(&EC);
830 QCBOREncode_CloseArray(&EC);
831
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700832 uErr = QCBOREncode_Finish(&EC, &Encoded);
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700833 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700834 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700835 }
836
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700837 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700838 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700839 }
840
841 return 0;
842}
843
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200844#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700845
846
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700847/* Public function. See float_tests.h */
848int32_t
849GeneralFloatDecodeTests(void)
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700850{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700851 /* See FloatNumberTests() for tests that really cover lots of float values */
852
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700853 QCBORItem Item;
854 QCBORError uErr;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700855 QCBORDecodeContext DC;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700856
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700857 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
858 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700859
860 QCBORDecode_GetNext(&DC, &Item);
861 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700862 return MakeTestResultCode(0, 1, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700863 }
864
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700865 /* 0.0 half-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700866 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200867 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
868#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
869 || Item.uDataType != QCBOR_TYPE_DOUBLE
870 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700871#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
872 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200873#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
874 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700875 return MakeTestResultCode(0, 2, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700876 }
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700877
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700878 /* 3.14 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700879 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200880 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
881#ifndef USEFULBUF_DISABLE_ALL_FLOAT
882 || Item.uDataType != QCBOR_TYPE_DOUBLE
883 || Item.val.dfnum != 3.14
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700884#else /* USEFULBUF_DISABLE_ALL_FLOAT */
885 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200886#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
887 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700888 return MakeTestResultCode(0, 3, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700889 }
890
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700891 /* 0.0 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700892 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200893 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
894#ifndef USEFULBUF_DISABLE_ALL_FLOAT
895 || Item.uDataType != QCBOR_TYPE_DOUBLE
896 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700897#else /* USEFULBUF_DISABLE_ALL_FLOAT */
898 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200899#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
900 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700901 return MakeTestResultCode(0, 4, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700902 }
903
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700904 /* NaN double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700905 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200906 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
907#ifndef USEFULBUF_DISABLE_ALL_FLOAT
908 || Item.uDataType != QCBOR_TYPE_DOUBLE
909 || !isnan(Item.val.dfnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700910#else /* USEFULBUF_DISABLE_ALL_FLOAT */
911 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200912#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
913 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700914 return MakeTestResultCode(0, 5, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700915 }
916
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700917 /* Infinity double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700918 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200919 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
920#ifndef USEFULBUF_DISABLE_ALL_FLOAT
921 || Item.uDataType != QCBOR_TYPE_DOUBLE
922 || Item.val.dfnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700923#else /* USEFULBUF_DISABLE_ALL_FLOAT */
924 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200925#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
926 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700927 return MakeTestResultCode(0, 6, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700928 }
929
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700930 /* 0.0 half-precision (again) */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700931 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200932 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
933#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
934 || Item.uDataType != QCBOR_TYPE_DOUBLE
935 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700936#else /* USEFULBUF_DISABLE_ALL_FLOAT */
937 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200938#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
939 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700940 return MakeTestResultCode(0, 7, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700941 }
942
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700943 /* 3.140000104904175 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700944 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200945 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
946#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700947#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200948 || Item.uDataType != QCBOR_TYPE_DOUBLE
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700949 || 3.1400001049041748 != Item.val.dfnum
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700950#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200951 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700952 || 3.140000f != Item.val.fnum
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700953#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
954#else /* USEFULBUF_DISABLE_ALL_FLOAT */
955 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200956#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
957 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700958 return MakeTestResultCode(0, 8, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700959 }
960
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700961 /* 0.0 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700962 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200963 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
964#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700965#ifndef QCBOR_DISABLE_FLOAT_HW_USE
966 || Item.uDataType != QCBOR_TYPE_DOUBLE
967 || Item.val.dfnum != 0.0
968#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200969 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700970 || Item.val.fnum != 0.0f
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700971#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
972#else /* USEFULBUF_DISABLE_ALL_FLOAT */
973 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200974#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
975 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700976 return MakeTestResultCode(0, 9, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700977 }
978
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700979 /* NaN single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700980 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200981 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
982#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700983#ifndef QCBOR_DISABLE_FLOAT_HW_USE
984 || Item.uDataType != QCBOR_TYPE_DOUBLE
985 || !isnan(Item.val.dfnum)
986#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200987 || Item.uDataType != QCBOR_TYPE_FLOAT
988 || !isnan(Item.val.fnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700989#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
990#else /* USEFULBUF_DISABLE_ALL_FLOAT */
991 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200992#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
993 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700994 return MakeTestResultCode(0, 10, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700995 }
996
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700997 /* Infinity single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700998 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200999 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1000#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001001#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1002 || Item.uDataType != QCBOR_TYPE_DOUBLE
1003 || Item.val.dfnum != INFINITY
1004#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001005 || Item.uDataType != QCBOR_TYPE_FLOAT
1006 || Item.val.fnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001007#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1008#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1009 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001010#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1011 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001012 return MakeTestResultCode(0, 11, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001013 }
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001014 /* Sufficent test coverage. Don't need to decode the rest. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001015
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001016
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001017#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001018 /* Now tests for spiffy decode main function */
1019 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001020 double d;
1021 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07001022 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001023
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001024 /* 0.0 half-precision */
1025 QCBORDecode_GetDouble(&DC, &d);
1026 uErr = QCBORDecode_GetAndResetError(&DC);
1027 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001028#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001029 || d != 0.0
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001030#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001031 ) {
1032 return MakeTestResultCode(1, 1, uErr);
1033 }
1034
1035 /* 3.14 double-precision */
1036 QCBORDecode_GetDouble(&DC, &d);
1037 uErr = QCBORDecode_GetAndResetError(&DC);
1038 if(uErr != QCBOR_SUCCESS || d != 3.14) {
1039 return MakeTestResultCode(1, 2, uErr);
1040 }
1041
1042 /* 0.0 double-precision */
1043 QCBORDecode_GetDouble(&DC, &d);
1044 uErr = QCBORDecode_GetAndResetError(&DC);
1045 if(uErr != QCBOR_SUCCESS || d != 0.0) {
1046 return MakeTestResultCode(1, 3, uErr);
1047 }
1048
1049 /* NaN double-precision */
1050 QCBORDecode_GetDouble(&DC, &d);
1051 uErr = QCBORDecode_GetAndResetError(&DC);
1052 if(uErr != QCBOR_SUCCESS || !isnan(d)) {
1053 return MakeTestResultCode(1, 4, uErr);
1054 }
1055
1056 /* Infinity double-precision */
1057 QCBORDecode_GetDouble(&DC, &d);
1058 uErr = QCBORDecode_GetAndResetError(&DC);
1059 if(uErr != QCBOR_SUCCESS || d != INFINITY) {
1060 return MakeTestResultCode(1, 5, uErr);
1061 }
1062
1063 /* 0.0 half-precision */
1064 QCBORDecode_GetDouble(&DC, &d);
1065 uErr = QCBORDecode_GetAndResetError(&DC);
1066 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
1067#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
1068 || d != 0.0
1069#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
1070 ) {
1071 return MakeTestResultCode(1, 6, uErr);
1072 }
1073
1074 /* 3.140000104904175 single-precision */
1075 QCBORDecode_GetDouble(&DC, &d);
1076 uErr = QCBORDecode_GetAndResetError(&DC);
1077 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1078#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1079 || d != 3.140000104904175
1080#endif
1081 ) {
1082 return MakeTestResultCode(1, 7, uErr);
1083 }
1084
1085 /* 0.0 single-precision */
1086 QCBORDecode_GetDouble(&DC, &d);
1087 uErr = QCBORDecode_GetAndResetError(&DC);
1088 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1089#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1090 || d != 0.0
1091#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1092 ) {
1093 return MakeTestResultCode(1, 8, uErr);
1094 }
1095
1096 /* NaN single-precision */
1097 QCBORDecode_GetDouble(&DC, &d);
1098 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1099#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1100 || !isnan(d)
1101#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1102 ) {
1103 return MakeTestResultCode(1, 9, uErr);
1104 }
1105
1106 /* Infinity single-precision */
1107 QCBORDecode_GetDouble(&DC, &d);
1108 uErr = QCBORDecode_GetAndResetError(&DC);
1109 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1110#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1111 || d != INFINITY
1112#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1113 ) {
1114 return MakeTestResultCode(1, 10, uErr);
1115 }
1116
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001117#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001118
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001119 return 0;
1120}
1121
1122
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001123
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001124#ifdef NAN_EXPERIMENT
1125/*
1126 Code for checking what the double to float cast does with
1127 NaNs. Not run as part of tests. Keep it around to
1128 be able to check various platforms and CPUs.
1129 */
1130
1131#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1132#define DOUBLE_NUM_EXPONENT_BITS (11)
1133#define DOUBLE_NUM_SIGN_BITS (1)
1134
1135#define DOUBLE_SIGNIFICAND_SHIFT (0)
1136#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1137#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1138
1139#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1140#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1141#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1142#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1143
1144
1145static int NaNExperiments() {
1146 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1147 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1148 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001149
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001150 float f1 = (float)dqNaN;
1151 float f2 = (float)dsNaN;
1152 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001153
1154
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001155 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1156 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1157 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001158
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001159 // Result of this on x86 is that every NaN is a qNaN. The intel
1160 // CVTSD2SS instruction ignores the NaN payload and even converts
1161 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001162
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001163 return 0;
1164}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001165#endif /* NAN_EXPERIMENT */