blob: 98ebc3d38ec6ea20fadb3de8c0a611f24c682546 [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 *
Laurence Lundbladee8f58162024-08-22 10:30:08 -07009 * See BSD-3-Clause license in file named "LICENSE"
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070010 *
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 Lundbladeeb3cdef2024-02-17 20:38:55 -080044struct FloatTestCase {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070045 double dNumber;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080046 float fNumber;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070047 UsefulBufC Preferred;
48 UsefulBufC NotPreferred;
49 UsefulBufC CDE;
50 UsefulBufC DCBOR;
51};
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -070052
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080053/* Boundaries for destination conversions:
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070054 *
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 *
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080065 * Boundaries for origin conversions:
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070066 * 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 Lundbladeeb3cdef2024-02-17 20:38:55 -080070 *
71 * Boundaries for double conversion to 64-bit integer:
72 * exponent 51, 52 significand bits set 4503599627370495
73 * exponent 52, 52 significand bits set 9007199254740991
74 * exponent 53, 52 bits set in significand 18014398509481982
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070075 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070076
77/* Always four lines per test case so shell scripts can process into
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080078 * other formats. CDE and DCBOR standards are not complete yet,
79 * encodings are what is expected. C string literals are used because they
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070080 * are the shortest notation. They are used __with a length__ . Null
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080081 * termination doesn't work because there are zero bytes.
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070082 */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080083static const struct FloatTestCase FloatTestCases[] = {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070084 /* Zero */
85 {0.0, 0.0f,
86 {"\xF9\x00\x00", 3}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080087 {"\xF9\x00\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070088
89 /* Negative Zero */
90 {-0.0, -0.0f,
91 {"\xF9\x80\x00", 3}, {"\xFB\x80\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080092 {"\xF9\x80\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070093
94 /* NaN */
95 {NAN, NAN,
96 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
97 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
98
99 /* Infinity */
100 {INFINITY, INFINITY,
101 {"\xF9\x7C\x00", 3}, {"\xFB\x7F\xF0\x00\x00\x00\x00\x00\x00", 9},
102 {"\xF9\x7C\x00", 3}, {"\xF9\x7C\x00", 3}},
103
104 /* Negative Infinity */
105 {-INFINITY, -INFINITY,
106 {"\xF9\xFC\x00", 3}, {"\xFB\xFF\xF0\x00\x00\x00\x00\x00\x00", 9},
107 {"\xF9\xFC\x00", 3}, {"\xF9\xFC\x00", 3}},
108
109 /* 1.0 */
110 {1.0, 1.0f,
111 {"\xF9\x3C\x00", 3}, {"\xFB\x3F\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800112 {"\xF9\x3C\x00", 3}, {"\x01", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700113
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800114 /* -2.0 -- a negative */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700115 {-2.0, -2.0f,
116 {"\xF9\xC0\x00", 3}, {"\xFB\xC0\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800117 {"\xF9\xC0\x00", 3}, {"\x21", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700118
119 /* 1/3 */
120 {0.333251953125, 0.333251953125f,
121 {"\xF9\x35\x55", 3}, {"\xFB\x3F\xD5\x54\x00\x00\x00\x00\x00", 9},
122 {"\xF9\x35\x55", 3}, {"\xF9\x35\x55", 3}},
123
124 /* 5.9604644775390625E-8 -- smallest half-precision subnormal */
125 {5.9604644775390625E-8, 0.0f,
126 {"\xF9\x00\x01", 3}, {"\xFB\x3E\x70\x00\x00\x00\x00\x00\x00", 9},
127 {"\xF9\x00\x01", 3}, {"\xF9\x00\x01", 3}},
128
129 /* 3.0517578125E-5 -- a half-precision subnormal */
130 {3.0517578125E-5, 0.0f,
131 {"\xF9\x02\x00", 3}, {"\xFB\x3F\x00\x00\x00\x00\x00\x00\x00", 9},
132 {"\xF9\x02\x00", 3}, {"\xF9\x02\x00", 3}},
133
134 /* 6.097555160522461E-5 -- largest half-precision subnormal */
135 {6.097555160522461E-5, 0.0f,
136 {"\xF9\x03\xFF", 3}, {"\xFB\x3F\x0F\xF8\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800137 {"\xF9\x03\xFF", 3}, {"\xF9\x03\xFF", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700138
139 /* 6.1035156249999993E-5 -- slightly smaller than smallest half-precision normal */
140 {6.1035156249999993E-5, 0.0f,
141 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
142 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
143
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800144 /* 6.103515625E-5 -- smallest half-precision normal */
145 {6.103515625E-5, 0.0f,
146 {"\xF9\04\00", 3}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x00", 9},
147 {"\xF9\04\00", 3}, {"\xF9\04\00", 3}},
148
149 /* 6.1035156250000014E-5 -- slightly larger than smallest half-precision normal */
150 {6.1035156250000014E-5, 0.0f,
151 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9},
152 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}},
153
154 /* 65504.0 -- largest half-precision */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700155 {65504.0, 0.0f,
156 {"\xF9\x7B\xFF", 3}, {"\xFB\x40\xEF\xFC\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800157 {"\xF9\x7B\xFF", 3}, {"\x19\xFF\xE0", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700158
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800159 /* 65504.1 -- exponent too large and too much precision to convert to half */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700160 {65504.1, 0.0f,
161 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9},
162 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}},
163
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800164 /* 65536.0 -- exponent too large for half but not too much precision for single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700165 {65536.0, 65536.0f,
166 {"\xFA\x47\x80\x00\x00", 5}, {"\xFB\x40\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800167 {"\xFA\x47\x80\x00\x00", 5}, {"\x1A\x00\x01\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700168
169 /* 1.401298464324817e-45 -- smallest single subnormal */
170 {1.401298464324817e-45, 1.40129846E-45f,
171 {"\xFA\x00\x00\x00\x01", 5}, {"\xFB\x36\xA0\x00\x00\x00\x00\x00\x00", 9},
172 {"\xFA\x00\x00\x00\x01", 5}, {"\xFA\x00\x00\x00\x01", 5}},
173
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800174 /* 5.8774717541114375E-39 -- slightly smaller than the smallest single normal */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700175 {5.8774717541114375E-39, 5.87747175E-39f,
176 {"\xFA\x00\x40\x00\x00", 5}, {"\xFB\x38\x00\x00\x00\x00\x00\x00\x00", 9},
177 {"\xFA\x00\x40\x00\x00", 5}, {"\xFA\x00\x40\x00\x00", 5}},
178
179 /* 1.1754942106924411e-38 -- largest single subnormal */
180 {1.1754942106924411E-38, 1.17549421E-38f,
181 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFB\x38\x0f\xff\xff\xC0\x00\x00\x00", 9},
182 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFA\x00\x7f\xff\xff", 5} },
183
184 /* 1.1754943508222874E-38 -- slightly bigger than smallest single normal */
185 {1.1754943508222874E-38, 0.0f,
186 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9},
187 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}},
188
189 /* 1.1754943508222875e-38 -- smallest single normal */
190 {1.1754943508222875e-38, 1.17549435E-38f,
191 {"\xFA\x00\x80\x00\x00", 5}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x00", 9},
192 {"\xFA\x00\x80\x00\x00", 5}, {"\xFA\x00\x80\x00\x00", 5}},
193
194 /* 1.1754943508222875e-38 -- slightly bigger than smallest single normal */
195 {1.1754943508222878e-38, 0.0f,
196 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9},
197 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}},
198
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800199 /* 8388607 -- exponent 22 to test single exponent boundary */
200 {8388607, 8388607.0f,
201 {"\xFA\x4A\xFF\xFF\xFE", 5}, {"\xFB\x41\x5F\xFF\xFF\xC0\x00\x00\x00", 9},
202 {"\xFA\x4A\xFF\xFF\xFE", 5}, {"\x1A\x00\x7F\xFF\xFF", 5}},
203
204 /* 16777215 -- exponent 23 to test single exponent boundary */
205 {16777215, 16777215.0f,
206 {"\xFA\x4B\x7F\xFF\xFF", 5}, {"\xFB\x41\x6F\xFF\xFF\xE0\x00\x00\x00", 9},
207 {"\xFA\x4B\x7F\xFF\xFF", 5}, {"\x1A\x00\xFF\xFF\xFF", 5}},
208
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700209 /* 16777216 -- converts to single without loss */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800210 {16777216, 16777216.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700211 {"\xFA\x4B\x80\x00\x00", 5}, {"\xFB\x41\x70\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800212 {"\xFA\x4B\x80\x00\x00", 5}, {"\x1A\x01\x00\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700213
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800214 /* 16777217 -- one more than above and fails conversion to single because of precision */
215 {16777217, 0.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700216 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800217 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\x1A\x01\x00\x00\x01", 5}},
218
219 /* 33554430 -- exponent 24 to test single exponent boundary */
220 {33554430, 33554430.0f,
221 {"\xFA\x4B\xFF\xFF\xFF", 5}, {"\xFB\x41\x7F\xFF\xFF\xE0\x00\x00\x00", 9},
222 {"\xFA\x4B\xFF\xFF\xFF", 5}, {"\x1A\x01\xFF\xFF\xFE", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700223
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800224 /* 4294967295 -- 2^^32 - 1 UINT32_MAX */
225 {4294967295, 0,
226 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
227 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x1A\xFF\xFF\xFF\xFF", 5}},
228
229 /* 4294967296 -- 2^^32, UINT32_MAX + 1 */
230 {4294967296, 4294967296.0f,
231 {"\xFA\x4F\x80\x00\x00", 5}, {"\xFB\x41\xF0\x00\x00\x00\x00\x00\x00", 9},
232 {"\xFA\x4F\x80\x00\x00", 5}, {"\x1B\x00\x00\x00\x01\x00\x00\x00\x00", 9}},
233
234 /* 2251799813685248 -- exponent 51, 0 significand bits set, to test double exponent boundary */
235 {2251799813685248, 2251799813685248.0f,
236 {"\xFA\x59\x00\x00\x00", 5}, {"\xFB\x43\x20\x00\x00\x00\x00\x00\x00", 9},
237 {"\xFA\x59\x00\x00\x00", 5}, {"\x1B\x00\x08\x00\x00\x00\x00\x00\x00", 9}},
238
239 /* 4503599627370495 -- exponent 51, 52 significand bits set to test double exponent boundary*/
240 {4503599627370495, 0,
241 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9},
242 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\x1B\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
243
244 /* 9007199254740991 -- exponent 52, 52 significand bits set to test double exponent boundary */
245 {9007199254740991, 0,
246 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
247 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x1F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
248
249 /* 18014398509481982 -- exponent 53, 52 bits set in significand (double lacks precision to represent 18014398509481983) */
250 {18014398509481982, 0,
251 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
252 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x3F\xFF\xFF\xFF\xFF\xFF\xFE", 9}},
253
254 /* 18014398509481984 -- next largest possible double above 18014398509481982 */
255 {18014398509481984, 18014398509481984.0f,
256 {"\xFA\x5A\x80\x00\x00", 5}, {"\xFB\x43\x50\x00\x00\x00\x00\x00\x00", 9},
257 {"\xFA\x5A\x80\x00\x00", 5}, {"\x1B\x00\x40\x00\x00\x00\x00\x00\x00", 9}},
258
259 /* 18446742974197924000.0.0 -- largest single that can convert to uint64 */
260 {18446742974197924000.0, 18446742974197924000.0f,
261 {"\xFA\x5F\x7F\xFF\xFF", 5}, {"\xFB\x43\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
262 {"\xFA\x5F\x7F\xFF\xFF", 5}, {"\x1B\xFF\xFF\xFF\x00\x00\x00\x00\x00", 9}},
263
264 /* 18446744073709550000.0 -- largest double that can convert to uint64, almost UINT64_MAX (18446744073709551615) */
265 {18446744073709550000.0, 0,
266 {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
267 {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\xFF\xFF\xFF\xFF\xFF\xFF\xF8\x00", 9}},
268
269 /* 18446744073709552000.0 -- just too large to convert to uint64, but converts to a single, just over UINT64_MAX */
270 {18446744073709552000.0, 18446744073709552000.0f,
271 {"\xFA\x5F\x80\x00\x00", 5}, {"\xFB\x43\xF0\x00\x00\x00\x00\x00\x00", 9},
272 {"\xFA\x5F\x80\x00\x00", 5}, {"\xFA\x5F\x80\x00\x00", 5}},
273
274 /* -4294967295 -- negative UINT32_MAX */
275 {-4294967295.0, 0,
276 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
277 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x3A\xFF\xFF\xFF\xFE", 5}},
278
279 /* -9223372036854774784.0 -- most negative double that converts to int64 */
280 {-9223372036854774784.0, 0,
281 {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
282 {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x3B\x7F\xFF\xFF\xFF\xFF\xFF\xFB\xFF", 9}},
283
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700284 /* -18446742974197923840.0 -- large negative that converts to float, but too large for int64 */
285 {-18446742974197923840.0, -18446742974197923840.0f,
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800286 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\xFB\xC3\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700287 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\x3B\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF", 9}},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800288
289 /* 3.4028234663852886E+38 -- largest possible single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700290 {3.4028234663852886E+38, 3.40282347E+38f,
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800291 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
292 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFA\x7F\x7F\xFF\xFF", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700293
294 /* 3.402823466385289E+38 -- slightly larger than largest possible single */
295 {3.402823466385289E+38, 0.0f,
296 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9},
297 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}},
298
299 /* 3.402823669209385e+38 -- exponent larger by one than largest possible single */
300 {3.402823669209385e+38, 0.0f,
301 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9},
302 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}},
303
304 /* 5.0e-324 -- smallest double subnormal normal */
305 {5.0e-324, 0.0f,
306 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9},
307 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}},
308
309 /* 2.2250738585072009E−308 -- largest double subnormal */
310 {2.2250738585072009e-308, 0.0f,
311 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
312 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
313
314 /* 2.2250738585072014e-308 -- smallest double normal */
315 {2.2250738585072014e-308, 0.0f,
316 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9},
317 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}},
318
319 /* 1.7976931348623157E308 -- largest double normal */
320 {1.7976931348623157e308, 0.0f,
321 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
322 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
323
324 /* List terminator */
325 {0.0, 0.0f, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700326};
327
328
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800329/* Can't use types double and float here because there's no way in C to
330 * construct arbitrary payloads for those types.
331 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700332struct NaNTestCase {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800333 uint64_t uDouble; /* Converted to double in test */
334 uint32_t uSingle; /* Converted to single in test */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700335 UsefulBufC Preferred;
336 UsefulBufC NotPreferred;
337 UsefulBufC CDE;
338 UsefulBufC DCBOR;
339};
340
341/* Always four lines per test case so shell scripts can process into
342 * other formats. CDE and DCBOR standards are not complete yet,
343 * encodings are a guess. C string literals are used because they
344 * are the shortest notation. They are used __with a length__ . Null
345 * termination doesn't work because there are zero bytes.
346 */
347static const struct NaNTestCase NaNTestCases[] = {
348
349 /* Payload with most significant bit set, a qNaN by most implementations */
350 {0x7ff8000000000000, 0x00000000,
351 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
352 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
353
354 /* Payload with single rightmost set */
355 {0x7ff8000000000001, 0x00000000,
356 {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9},
357 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
358
359 /* Payload with 10 leftmost bits set -- converts to half */
360 {0x7ffffc0000000000, 0x00000000,
361 {"\xF9\x7F\xFF", 3}, {"\xFB\x7F\xFF\xFC\x00\x00\x00\x00\x00", 9},
362 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
363
364 /* Payload with 10 rightmost bits set -- cannot convert to half */
365 {0x7ff80000000003ff, 0x00000000,
366 {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9},
367 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
368
369 /* Payload with 23 leftmost bits set -- converts to a single */
370 {0x7ffFFFFFE0000000, 0x7fffffff,
371 {"\xFA\x7F\xFF\xFF\xFF", 5}, {"\xFB\x7F\xFF\xFF\xFF\xE0\x00\x00\x00", 9},
372 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
373
374 /* Payload with 24 leftmost bits set -- fails to convert to a single */
375 {0x7ffFFFFFF0000000, 0x00000000,
376 {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9}, {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9},
377 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
378
379 /* Payload with all bits set */
380 {0x7fffffffffffffff, 0x00000000,
381 {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800382 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700383
384 /* List terminator */
385 {0, 0, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
386};
387
388
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700389/* Public function. See float_tests.h
390 *
391 * This is the main test of floating-point encoding / decoding. It is
392 * data-driven by the above tables. It works better than tests below that
393 * it mostly replaces because it tests one number at a time, rather than
394 * putting them all in a map. It is much easier to debug test failures
395 * and to add new tests. */
396int32_t
397FloatValuesTests(void)
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700398{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700399 unsigned int uTestIndex;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800400 const struct FloatTestCase *pTestCase;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700401 const struct NaNTestCase *pNaNTestCase;
402 MakeUsefulBufOnStack( TestOutBuffer, 20);
403 UsefulBufC TestOutput;
404 QCBOREncodeContext EnCtx;
405 QCBORError uErr;
406 QCBORDecodeContext DCtx;
407 QCBORItem Item;
408 uint64_t uDecoded;
409#ifdef QCBOR_DISABLE_FLOAT_HW_USE
410 uint32_t uDecoded2;
411#endif
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700412
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700413 /* Test a variety of doubles */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800414 for(uTestIndex = 0; FloatTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
415 pTestCase = &FloatTestCases[uTestIndex];
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700416
Laurence Lundblade82634b62024-11-20 22:37:45 -0800417 if(uTestIndex == 2) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800418 uDecoded = 1;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700419 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800420
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700421 /* Number Encode of Preferred */
422 QCBOREncode_Init(&EnCtx, TestOutBuffer);
423 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
424 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800425
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700426 if(uErr != QCBOR_SUCCESS) {
427 return MakeTestResultCode(uTestIndex, 1, uErr);;
428 }
429 if(UsefulBuf_Compare(TestOutput, pTestCase->Preferred)) {
430 return MakeTestResultCode(uTestIndex, 1, 200);
431 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700432
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700433 /* Number Encode of Not Preferred */
434 QCBOREncode_Init(&EnCtx, TestOutBuffer);
435 QCBOREncode_AddDoubleNoPreferred(&EnCtx, pTestCase->dNumber);
436 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade68a13352018-09-23 02:19:54 -0700437
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700438 if(uErr != QCBOR_SUCCESS) {
439 return MakeTestResultCode(uTestIndex, 2, uErr);;
440 }
441 if(UsefulBuf_Compare(TestOutput, pTestCase->NotPreferred)) {
442 return MakeTestResultCode(uTestIndex, 2, 200);
443 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800444
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800445 /* Number Encode of CDE */
446 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800447 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_CDE);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800448 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
449 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
450
451 if(uErr != QCBOR_SUCCESS) {
452 return MakeTestResultCode(uTestIndex, 20, uErr);;
453 }
454 if(UsefulBuf_Compare(TestOutput, pTestCase->CDE)) {
455 return MakeTestResultCode(uTestIndex, 21, 200);
456 }
457
458 /* Number Encode of dCBOR */
459 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800460 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800461 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
462 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
463
464 if(uErr != QCBOR_SUCCESS) {
465 return MakeTestResultCode(uTestIndex, 22, uErr);;
466 }
467 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
468 return MakeTestResultCode(uTestIndex, 23, 200);
469 }
470
471 if(pTestCase->fNumber != 0) {
472 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800473 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800474 QCBOREncode_AddFloat(&EnCtx, pTestCase->fNumber);
475 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
476
477 if(uErr != QCBOR_SUCCESS) {
478 return MakeTestResultCode(uTestIndex, 24, uErr);;
479 }
480 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
481 return MakeTestResultCode(uTestIndex, 25, 200);
482 }
483 }
484
485
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700486 /* Number Decode of Preferred */
487 QCBORDecode_Init(&DCtx, pTestCase->Preferred, 0);
488 uErr = QCBORDecode_GetNext(&DCtx, &Item);
489 if(uErr != QCBOR_SUCCESS) {
490 return MakeTestResultCode(uTestIndex, 3, uErr);;
491 }
492#ifndef QCBOR_DISABLE_FLOAT_HW_USE
493 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
494 return MakeTestResultCode(uTestIndex, 4, 0);
495 }
496 if(isnan(pTestCase->dNumber)) {
497 if(!isnan(Item.val.dfnum)) {
498 return MakeTestResultCode(uTestIndex, 5, 0);
499 }
500 } else {
501 if(Item.val.dfnum != pTestCase->dNumber) {
502 return MakeTestResultCode(uTestIndex, 6, 0);
503 }
504 }
505#else /* QCBOR_DISABLE_FLOAT_HW_USE */
506 /* When QCBOR_DISABLE_FLOAT_HW_USE is set, single-precision is not
507 * converted to double when decoding, so test differently. len == 5
508 * indicates single-precision in the encoded CBOR. */
509 if(pTestCase->Preferred.len == 5) {
510 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800511 return MakeTestResultCode(uTestIndex, 41, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700512 }
513 if(isnan(pTestCase->dNumber)) {
514 if(!isnan(Item.val.fnum)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800515 return MakeTestResultCode(uTestIndex, 51, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700516 }
517 } else {
518 if(Item.val.fnum != pTestCase->fNumber) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800519 return MakeTestResultCode(uTestIndex, 61, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700520 }
521 }
522 } else {
523 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800524 return MakeTestResultCode(uTestIndex, 42, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700525 }
526 if(isnan(pTestCase->dNumber)) {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700527 if(!isnan(Item.val.dfnum)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800528 return MakeTestResultCode(uTestIndex, 52, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700529 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700530 } else {
531 if(Item.val.dfnum != pTestCase->dNumber) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800532 return MakeTestResultCode(uTestIndex, 62, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700533 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700534 }
535 }
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800536#endif /* ! QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700537
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700538 /* Number Decode of Not Preferred */
539 QCBORDecode_Init(&DCtx, pTestCase->NotPreferred, 0);
540 uErr = QCBORDecode_GetNext(&DCtx, &Item);
541 if(uErr != QCBOR_SUCCESS) {
542 return MakeTestResultCode(uTestIndex, 7, uErr);;
543 }
544 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
545 return MakeTestResultCode(uTestIndex, 8, 0);
546 }
547 if(isnan(pTestCase->dNumber)) {
548 if(!isnan(Item.val.dfnum)) {
549 return MakeTestResultCode(uTestIndex, 9, 0);
550 }
551 } else {
552 if(Item.val.dfnum != pTestCase->dNumber) {
553 return MakeTestResultCode(uTestIndex, 10, 0);
554 }
555 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700556
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700557 }
558
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700559 /* Test a variety of NaNs with payloads */
560 for(uTestIndex = 0; NaNTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
561 pNaNTestCase = &NaNTestCases[uTestIndex];
562
563
564 if(uTestIndex == 4) {
565 uErr = 99; /* For setting break points for particular tests */
566 }
567
568 /* NaN Encode of Preferred */
569 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800570 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700571 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
572 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
573 if(uErr != QCBOR_SUCCESS) {
574 return MakeTestResultCode(uTestIndex+100, 10, uErr);;
575 }
576 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->Preferred)) {
577 return MakeTestResultCode(uTestIndex+100, 10, 200);
578 }
579
580#ifdef QCBOR_COMPARE_TO_HW_NAN_CONVERSION
581 {
582 /* This test is off by default. It's purpose is to check
583 * QCBOR's mask-n-shift implementation against the HW/CPU
584 * instructions that do conversion between double and single.
585 * It is off because it is only used on occasion to verify
586 * QCBOR and because it is suspected that some HW/CPU does
587 * implement this correctly. NaN payloads are an obscure
588 * feature. */
589 float f;
590 double d, d2;
591
592 d = UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uNumber);
593
594 /* Cast the double to a single and then back to a double and
595 * see if they are equal. If so, then the NaN payload doesn't
596 * have any bits that are lost when converting to single and
597 * it can be safely converted.
598 *
599 * This test can't be done for half-precision because it is
600 * not widely supported.
601 */
602 f = (float)d;
603 d2 = (double)f;
604
605 /* The length of encoded doubles is 9, singles 5 and halves
606 * 3. If there are NaN payload bits that can't be converted,
607 * then the length must be 9.
608 */
609 if((uint64_t)d != (uint64_t)d2 && pNaNTestCase->Preferred.len != 9) {
610 /* QCBOR conversion not the same as HW conversion */
611 return MakeTestResultCode(uTestIndex, 9, 200);
612 }
613 }
614#endif /* QCBOR_COMPARE_TO_HW_NAN_CONVERSION */
615
616
617 /* NaN Encode of Not Preferred */
618 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800619 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700620 QCBOREncode_AddDoubleNoPreferred(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
621 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
622 if(uErr != QCBOR_SUCCESS) {
623 return MakeTestResultCode(uTestIndex+100, 11, uErr);;
624 }
625 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->NotPreferred)) {
626 return MakeTestResultCode(uTestIndex+100, 11, 200);
627 }
628
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800629 /* NaN Decode of Not Preferred */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700630 QCBORDecode_Init(&DCtx, pNaNTestCase->Preferred, 0);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800631 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700632 uErr = QCBORDecode_GetNext(&DCtx, &Item);
633 if(uErr != QCBOR_SUCCESS) {
634 return MakeTestResultCode(uTestIndex+100, 12, uErr);
635 }
636
637#ifndef QCBOR_DISABLE_FLOAT_HW_USE
638
639 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
640 if(uDecoded != pNaNTestCase->uDouble) {
641 return MakeTestResultCode(uTestIndex+100, 12, 200);
642 }
643#else /* QCBOR_DISABLE_FLOAT_HW_USE */
644 if(pNaNTestCase->Preferred.len == 5) {
645 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
646 return MakeTestResultCode(uTestIndex, 4, 0);
647 }
648
649 uDecoded2 = UsefulBufUtil_CopyFloatToUint32(Item.val.fnum);
650
651 if(uDecoded2 != pNaNTestCase->uSingle) {
652 return MakeTestResultCode(uTestIndex, 4, 0);
653 }
654 } else {
655 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
656 return MakeTestResultCode(uTestIndex, 4, 0);
657 }
658 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
659 if(uDecoded != pNaNTestCase->uDouble) {
660 return MakeTestResultCode(uTestIndex+100, 12, 200);
661 }
662 }
663#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
664
665 /* NaN Decode of Not Preferred */
666 QCBORDecode_Init(&DCtx, pNaNTestCase->NotPreferred, 0);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800667 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700668 uErr = QCBORDecode_GetNext(&DCtx, &Item);
669 if(uErr != QCBOR_SUCCESS) {
670 return MakeTestResultCode(uTestIndex+100, 13, uErr);
671 }
672 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
673 if(uDecoded != pNaNTestCase->uDouble) {
674 return MakeTestResultCode(uTestIndex+100, 13, 200);
675 }
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800676
677
678 /* NaN Encode of DCBOR */
679 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800680 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR | QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800681 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
682 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
683 if(uErr != QCBOR_SUCCESS) {
684 return MakeTestResultCode(uTestIndex+100, 14, uErr);;
685 }
686 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->DCBOR)) {
687 return MakeTestResultCode(uTestIndex+100, 14, 200);
688 }
689
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700690 }
691
692 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800693}
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700694
695
696
697/* Public function. See float_tests.h */
698int32_t
699HalfPrecisionAgainstRFCCodeTest(void)
700{
701 QCBORItem Item;
702 QCBORDecodeContext DC;
703 unsigned char pbHalfBytes[2];
704 uint8_t uHalfPrecInitialByte;
705 double d;
706 UsefulBuf_MAKE_STACK_UB(EncodedBytes, 3);
707 UsefulOutBuf UOB;
708 uint32_t uHalfP;
709
710
711 for(uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
712 pbHalfBytes[1] = (uint8_t)(uHalfP & 0xff);
713 pbHalfBytes[0] = (uint8_t)(uHalfP >> 8); /* uHalfP is always less than 0xffff */
714 d = decode_half(pbHalfBytes);
715
716 /* Construct the CBOR for the half-precision float by hand */
717 UsefulOutBuf_Init(&UOB, EncodedBytes);
718
719 uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); /* 0xf9 */
720 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); /* initial byte */
721 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP); /* argument */
722
723 /* Now parse the hand-constructed CBOR. This will invoke the
724 * conversion to a float
725 */
726 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
727 QCBORDecode_GetNext(&DC, &Item);
728 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
729 return -1;
730 }
731
732 if(isnan(d)) {
733 /* The RFC code uses the native instructions which may or may not
734 * handle sNaN, qNaN and NaN payloads correctly. This test just
735 * makes sure it is a NaN and doesn't worry about the type of NaN
736 */
737 if(!isnan(Item.val.dfnum)) {
738 return -3;
739 }
740 } else {
741 if(Item.val.dfnum != d) {
742 return -2;
743 }
744 }
745 }
746 return 0;
747}
748
Laurence Lundblade585127a2020-07-15 03:25:24 -0700749#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700750
751
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700752/*
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700753 * Some encoded floating point numbers that are used for both
754 * encode and decode tests.
755 *
756 * [0.0, // Half
757 * 3.14, // Double
758 * 0.0, // Double
759 * NaN, // Double
760 * Infinity, // Double
761 * 0.0, // Half (Duplicate because of use in encode tests)
762 * 3.140000104904175, // Single
763 * 0.0, // Single
764 * NaN, // Single
765 * Infinity, // Single
766 * {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
767 * 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700768 */
769static const uint8_t spExpectedFloats[] = {
770 0x8B,
771 0xF9, 0x00, 0x00,
772 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
773 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0xF9, 0x00, 0x00,
777 0xFA, 0x40, 0x48, 0xF5, 0xC3,
778 0xFA, 0x00, 0x00, 0x00, 0x00,
779 0xFA, 0x7F, 0xC0, 0x00, 0x00,
780 0xFA, 0x7F, 0x80, 0x00, 0x00,
781 0xA8,
782 0x18, 0x64,
783 0xF9, 0x00, 0x00,
784 0x18, 0x65,
785 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
786 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
787 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
788 0x18, 0x69,
789 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790 0x18, 0x66,
791 0xF9, 0x00, 0x00,
792 0x18, 0x67,
793 0xFA, 0x40, 0x49, 0x0F, 0xDA,
794 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
795 0xFA, 0x40, 0x2D, 0xF8, 0x54,
796 0x18, 0x6A,
797 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700798
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200799#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700800static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700801 0x8B,
802 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
804 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
805 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0xFA, 0x00, 0x00, 0x00, 0x00,
808 0xFA, 0x40, 0x48, 0xF5, 0xC3,
809 0xFA, 0x00, 0x00, 0x00, 0x00,
810 0xFA, 0x7F, 0xC0, 0x00, 0x00,
811 0xFA, 0x7F, 0x80, 0x00, 0x00,
812 0xA8,
813 0x18, 0x64,
814 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815 0x18, 0x65,
816 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
817 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
818 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
819 0x18, 0x69,
820 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821 0x18, 0x66,
822 0xFA, 0x00, 0x00, 0x00, 0x00,
823 0x18, 0x67,
824 0xFA, 0x40, 0x49, 0x0F, 0xDA,
825 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
826 0xFA, 0x40, 0x2D, 0xF8, 0x54,
827 0x18, 0x6A,
828 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700829
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700830
831/* Public function. See float_tests.h */
832int32_t
833GeneralFloatEncodeTests(void)
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700834{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700835 /* See FloatNumberTests() for tests that really cover lots of float values.
836 * Add new tests for new values or decode modes there.
837 * This test is primarily to cover all the float encode methods. */
838
839 UsefulBufC Encoded;
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700840 UsefulBufC ExpectedFloats;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700841 QCBORError uErr;
842
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700843#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700844 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700845 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700846 (void)spExpectedFloatsNoHalf; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700847#else
848 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700849 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700850 (void)spExpectedFloats; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700851#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700852
853 QCBOREncodeContext EC;
854 QCBOREncode_Init(&EC, OutBuffer);
855 QCBOREncode_OpenArray(&EC);
856
857 QCBOREncode_AddDouble(&EC, 0.0);
858 QCBOREncode_AddDouble(&EC, 3.14);
859 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
860 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
861 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
862
863 QCBOREncode_AddFloat(&EC, 0.0);
864 QCBOREncode_AddFloat(&EC, 3.14f);
865 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
866 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
867 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
868
869 QCBOREncode_OpenMap(&EC);
870
871 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
872 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
873 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
874 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
875
876 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
877 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
878 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
879 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
880
881 QCBOREncode_CloseMap(&EC);
882 QCBOREncode_CloseArray(&EC);
883
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700884 uErr = QCBOREncode_Finish(&EC, &Encoded);
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700885 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700886 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700887 }
888
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700889 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700890 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700891 }
892
893 return 0;
894}
895
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200896#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700897
898
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700899/* Public function. See float_tests.h */
900int32_t
901GeneralFloatDecodeTests(void)
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700902{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700903 /* See FloatNumberTests() for tests that really cover lots of float values */
904
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700905 QCBORItem Item;
906 QCBORError uErr;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700907 QCBORDecodeContext DC;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700908
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700909 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
910 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700911
912 QCBORDecode_GetNext(&DC, &Item);
913 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700914 return MakeTestResultCode(0, 1, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700915 }
916
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700917 /* 0.0 half-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_HALF_PREC(QCBOR_SUCCESS)
920#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
921 || Item.uDataType != QCBOR_TYPE_DOUBLE
922 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700923#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
924 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200925#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
926 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700927 return MakeTestResultCode(0, 2, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700928 }
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700929
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700930 /* 3.14 double-precision */
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_FLOAT(QCBOR_SUCCESS)
933#ifndef USEFULBUF_DISABLE_ALL_FLOAT
934 || Item.uDataType != QCBOR_TYPE_DOUBLE
935 || Item.val.dfnum != 3.14
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 /* USEFULBUF_DISABLE_ALL_FLOAT */
939 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700940 return MakeTestResultCode(0, 3, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700941 }
942
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700943 /* 0.0 double-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
947 || Item.uDataType != QCBOR_TYPE_DOUBLE
948 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700949#else /* USEFULBUF_DISABLE_ALL_FLOAT */
950 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200951#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
952 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700953 return MakeTestResultCode(0, 4, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700954 }
955
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700956 /* NaN double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700957 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200958 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
959#ifndef USEFULBUF_DISABLE_ALL_FLOAT
960 || Item.uDataType != QCBOR_TYPE_DOUBLE
961 || !isnan(Item.val.dfnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700962#else /* USEFULBUF_DISABLE_ALL_FLOAT */
963 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200964#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
965 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700966 return MakeTestResultCode(0, 5, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700967 }
968
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700969 /* Infinity double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700970 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200971 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
972#ifndef USEFULBUF_DISABLE_ALL_FLOAT
973 || Item.uDataType != QCBOR_TYPE_DOUBLE
974 || Item.val.dfnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700975#else /* USEFULBUF_DISABLE_ALL_FLOAT */
976 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200977#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
978 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700979 return MakeTestResultCode(0, 6, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700980 }
981
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700982 /* 0.0 half-precision (again) */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700983 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200984 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
985#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
986 || Item.uDataType != QCBOR_TYPE_DOUBLE
987 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700988#else /* USEFULBUF_DISABLE_ALL_FLOAT */
989 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200990#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
991 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700992 return MakeTestResultCode(0, 7, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700993 }
994
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700995 /* 3.140000104904175 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700996 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200997 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
998#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700999#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001000 || Item.uDataType != QCBOR_TYPE_DOUBLE
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001001 || 3.1400001049041748 != Item.val.dfnum
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001002#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001003 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001004 || 3.140000f != Item.val.fnum
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001005#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1006#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1007 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001008#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1009 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001010 return MakeTestResultCode(0, 8, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001011 }
1012
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001013 /* 0.0 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001014 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001015 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1016#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001017#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1018 || Item.uDataType != QCBOR_TYPE_DOUBLE
1019 || Item.val.dfnum != 0.0
1020#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001021 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001022 || Item.val.fnum != 0.0f
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001023#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1024#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1025 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001026#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1027 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001028 return MakeTestResultCode(0, 9, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001029 }
1030
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001031 /* NaN single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001032 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001033 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1034#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001035#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1036 || Item.uDataType != QCBOR_TYPE_DOUBLE
1037 || !isnan(Item.val.dfnum)
1038#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001039 || Item.uDataType != QCBOR_TYPE_FLOAT
1040 || !isnan(Item.val.fnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001041#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1042#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1043 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001044#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1045 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001046 return MakeTestResultCode(0, 10, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001047 }
1048
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001049 /* Infinity single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001050 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001051 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1052#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001053#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1054 || Item.uDataType != QCBOR_TYPE_DOUBLE
1055 || Item.val.dfnum != INFINITY
1056#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001057 || Item.uDataType != QCBOR_TYPE_FLOAT
1058 || Item.val.fnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001059#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1060#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1061 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001062#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1063 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001064 return MakeTestResultCode(0, 11, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001065 }
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001066 /* Sufficent test coverage. Don't need to decode the rest. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001067
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001068
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001069#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001070 /* Now tests for spiffy decode main function */
1071 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001072 double d;
1073 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07001074 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001075
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001076 /* 0.0 half-precision */
1077 QCBORDecode_GetDouble(&DC, &d);
1078 uErr = QCBORDecode_GetAndResetError(&DC);
1079 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001080#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001081 || d != 0.0
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001082#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001083 ) {
1084 return MakeTestResultCode(1, 1, uErr);
1085 }
1086
1087 /* 3.14 double-precision */
1088 QCBORDecode_GetDouble(&DC, &d);
1089 uErr = QCBORDecode_GetAndResetError(&DC);
1090 if(uErr != QCBOR_SUCCESS || d != 3.14) {
1091 return MakeTestResultCode(1, 2, uErr);
1092 }
1093
1094 /* 0.0 double-precision */
1095 QCBORDecode_GetDouble(&DC, &d);
1096 uErr = QCBORDecode_GetAndResetError(&DC);
1097 if(uErr != QCBOR_SUCCESS || d != 0.0) {
1098 return MakeTestResultCode(1, 3, uErr);
1099 }
1100
1101 /* NaN double-precision */
1102 QCBORDecode_GetDouble(&DC, &d);
1103 uErr = QCBORDecode_GetAndResetError(&DC);
1104 if(uErr != QCBOR_SUCCESS || !isnan(d)) {
1105 return MakeTestResultCode(1, 4, uErr);
1106 }
1107
1108 /* Infinity double-precision */
1109 QCBORDecode_GetDouble(&DC, &d);
1110 uErr = QCBORDecode_GetAndResetError(&DC);
1111 if(uErr != QCBOR_SUCCESS || d != INFINITY) {
1112 return MakeTestResultCode(1, 5, uErr);
1113 }
1114
1115 /* 0.0 half-precision */
1116 QCBORDecode_GetDouble(&DC, &d);
1117 uErr = QCBORDecode_GetAndResetError(&DC);
1118 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
1119#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
1120 || d != 0.0
1121#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
1122 ) {
1123 return MakeTestResultCode(1, 6, uErr);
1124 }
1125
1126 /* 3.140000104904175 single-precision */
1127 QCBORDecode_GetDouble(&DC, &d);
1128 uErr = QCBORDecode_GetAndResetError(&DC);
1129 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1130#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1131 || d != 3.140000104904175
1132#endif
1133 ) {
1134 return MakeTestResultCode(1, 7, uErr);
1135 }
1136
1137 /* 0.0 single-precision */
1138 QCBORDecode_GetDouble(&DC, &d);
1139 uErr = QCBORDecode_GetAndResetError(&DC);
1140 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1141#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1142 || d != 0.0
1143#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1144 ) {
1145 return MakeTestResultCode(1, 8, uErr);
1146 }
1147
1148 /* NaN single-precision */
1149 QCBORDecode_GetDouble(&DC, &d);
1150 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1151#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1152 || !isnan(d)
1153#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1154 ) {
1155 return MakeTestResultCode(1, 9, uErr);
1156 }
1157
1158 /* Infinity single-precision */
1159 QCBORDecode_GetDouble(&DC, &d);
1160 uErr = QCBORDecode_GetAndResetError(&DC);
1161 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1162#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1163 || d != INFINITY
1164#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1165 ) {
1166 return MakeTestResultCode(1, 10, uErr);
1167 }
1168
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001169#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001170
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001171 return 0;
1172}
1173
1174
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001175
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001176#ifdef NAN_EXPERIMENT
1177/*
1178 Code for checking what the double to float cast does with
1179 NaNs. Not run as part of tests. Keep it around to
1180 be able to check various platforms and CPUs.
1181 */
1182
1183#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1184#define DOUBLE_NUM_EXPONENT_BITS (11)
1185#define DOUBLE_NUM_SIGN_BITS (1)
1186
1187#define DOUBLE_SIGNIFICAND_SHIFT (0)
1188#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1189#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1190
1191#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1192#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1193#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1194#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1195
1196
1197static int NaNExperiments() {
1198 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1199 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1200 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001201
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001202 float f1 = (float)dqNaN;
1203 float f2 = (float)dsNaN;
1204 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001205
1206
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001207 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1208 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1209 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001210
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001211 // Result of this on x86 is that every NaN is a qNaN. The intel
1212 // CVTSD2SS instruction ignores the NaN payload and even converts
1213 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001214
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001215 return 0;
1216}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001217#endif /* NAN_EXPERIMENT */