blob: ce078d462812468981615057341e4462899c3403 [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 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
284 /* -18446742974197924000.0.0 -- large negative that converts to float, but too large for int64 */
285 {-18446742974197924000.0, -18446742974197924000.0f,
286 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\xFB\xC3\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
287 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\xFA\xDF\x7F\xFF\xFF", 5}},
288
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 Lundbladeeb3cdef2024-02-17 20:38:55 -0800417 if(uTestIndex == 34) {
418 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);
447 QCBOREncode_SerializationCDE(&EnCtx);
448 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);
460 QCBOREncode_SerializationdCBOR(&EnCtx);
461 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);
473 QCBOREncode_SerializationdCBOR(&EnCtx);
474 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 Lundbladeeb3cdef2024-02-17 20:38:55 -0800570 QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_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 Lundbladeeb3cdef2024-02-17 20:38:55 -0800619 QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_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 Lundbladeeb3cdef2024-02-17 20:38:55 -0800631 QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_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 Lundbladeeb3cdef2024-02-17 20:38:55 -0800667 QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_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);
680 QCBOREncode_Allow(&EnCtx, QCBOR_ENCODE_ALLOW_NAN_PAYLOAD);
681 QCBOREncode_SerializationdCBOR(&EnCtx);
682 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
683 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
684 if(uErr != QCBOR_SUCCESS) {
685 return MakeTestResultCode(uTestIndex+100, 14, uErr);;
686 }
687 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->DCBOR)) {
688 return MakeTestResultCode(uTestIndex+100, 14, 200);
689 }
690
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700691 }
692
693 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800694}
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700695
696
697
698/* Public function. See float_tests.h */
699int32_t
700HalfPrecisionAgainstRFCCodeTest(void)
701{
702 QCBORItem Item;
703 QCBORDecodeContext DC;
704 unsigned char pbHalfBytes[2];
705 uint8_t uHalfPrecInitialByte;
706 double d;
707 UsefulBuf_MAKE_STACK_UB(EncodedBytes, 3);
708 UsefulOutBuf UOB;
709 uint32_t uHalfP;
710
711
712 for(uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
713 pbHalfBytes[1] = (uint8_t)(uHalfP & 0xff);
714 pbHalfBytes[0] = (uint8_t)(uHalfP >> 8); /* uHalfP is always less than 0xffff */
715 d = decode_half(pbHalfBytes);
716
717 /* Construct the CBOR for the half-precision float by hand */
718 UsefulOutBuf_Init(&UOB, EncodedBytes);
719
720 uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); /* 0xf9 */
721 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); /* initial byte */
722 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP); /* argument */
723
724 /* Now parse the hand-constructed CBOR. This will invoke the
725 * conversion to a float
726 */
727 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
728 QCBORDecode_GetNext(&DC, &Item);
729 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
730 return -1;
731 }
732
733 if(isnan(d)) {
734 /* The RFC code uses the native instructions which may or may not
735 * handle sNaN, qNaN and NaN payloads correctly. This test just
736 * makes sure it is a NaN and doesn't worry about the type of NaN
737 */
738 if(!isnan(Item.val.dfnum)) {
739 return -3;
740 }
741 } else {
742 if(Item.val.dfnum != d) {
743 return -2;
744 }
745 }
746 }
747 return 0;
748}
749
Laurence Lundblade585127a2020-07-15 03:25:24 -0700750#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700751
752
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700753/*
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700754 * Some encoded floating point numbers that are used for both
755 * encode and decode tests.
756 *
757 * [0.0, // Half
758 * 3.14, // Double
759 * 0.0, // Double
760 * NaN, // Double
761 * Infinity, // Double
762 * 0.0, // Half (Duplicate because of use in encode tests)
763 * 3.140000104904175, // Single
764 * 0.0, // Single
765 * NaN, // Single
766 * Infinity, // Single
767 * {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
768 * 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700769 */
770static const uint8_t spExpectedFloats[] = {
771 0x8B,
772 0xF9, 0x00, 0x00,
773 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
774 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0xF9, 0x00, 0x00,
778 0xFA, 0x40, 0x48, 0xF5, 0xC3,
779 0xFA, 0x00, 0x00, 0x00, 0x00,
780 0xFA, 0x7F, 0xC0, 0x00, 0x00,
781 0xFA, 0x7F, 0x80, 0x00, 0x00,
782 0xA8,
783 0x18, 0x64,
784 0xF9, 0x00, 0x00,
785 0x18, 0x65,
786 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
787 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
788 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
789 0x18, 0x69,
790 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791 0x18, 0x66,
792 0xF9, 0x00, 0x00,
793 0x18, 0x67,
794 0xFA, 0x40, 0x49, 0x0F, 0xDA,
795 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
796 0xFA, 0x40, 0x2D, 0xF8, 0x54,
797 0x18, 0x6A,
798 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700799
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200800#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700801static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700802 0x8B,
803 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
804 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
805 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0xFA, 0x00, 0x00, 0x00, 0x00,
809 0xFA, 0x40, 0x48, 0xF5, 0xC3,
810 0xFA, 0x00, 0x00, 0x00, 0x00,
811 0xFA, 0x7F, 0xC0, 0x00, 0x00,
812 0xFA, 0x7F, 0x80, 0x00, 0x00,
813 0xA8,
814 0x18, 0x64,
815 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x18, 0x65,
817 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
818 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
819 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
820 0x18, 0x69,
821 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822 0x18, 0x66,
823 0xFA, 0x00, 0x00, 0x00, 0x00,
824 0x18, 0x67,
825 0xFA, 0x40, 0x49, 0x0F, 0xDA,
826 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
827 0xFA, 0x40, 0x2D, 0xF8, 0x54,
828 0x18, 0x6A,
829 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700830
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700831
832/* Public function. See float_tests.h */
833int32_t
834GeneralFloatEncodeTests(void)
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700835{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700836 /* See FloatNumberTests() for tests that really cover lots of float values.
837 * Add new tests for new values or decode modes there.
838 * This test is primarily to cover all the float encode methods. */
839
840 UsefulBufC Encoded;
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700841 UsefulBufC ExpectedFloats;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700842 QCBORError uErr;
843
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700844#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700845 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700846 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700847 (void)spExpectedFloatsNoHalf; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700848#else
849 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700850 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700851 (void)spExpectedFloats; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700852#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700853
854 QCBOREncodeContext EC;
855 QCBOREncode_Init(&EC, OutBuffer);
856 QCBOREncode_OpenArray(&EC);
857
858 QCBOREncode_AddDouble(&EC, 0.0);
859 QCBOREncode_AddDouble(&EC, 3.14);
860 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
861 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
862 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
863
864 QCBOREncode_AddFloat(&EC, 0.0);
865 QCBOREncode_AddFloat(&EC, 3.14f);
866 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
867 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
868 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
869
870 QCBOREncode_OpenMap(&EC);
871
872 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
873 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
874 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
875 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
876
877 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
878 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
879 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
880 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
881
882 QCBOREncode_CloseMap(&EC);
883 QCBOREncode_CloseArray(&EC);
884
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700885 uErr = QCBOREncode_Finish(&EC, &Encoded);
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700886 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700887 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700888 }
889
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700890 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700891 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700892 }
893
894 return 0;
895}
896
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200897#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700898
899
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700900/* Public function. See float_tests.h */
901int32_t
902GeneralFloatDecodeTests(void)
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700903{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700904 /* See FloatNumberTests() for tests that really cover lots of float values */
905
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700906 QCBORItem Item;
907 QCBORError uErr;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700908 QCBORDecodeContext DC;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700909
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700910 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
911 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700912
913 QCBORDecode_GetNext(&DC, &Item);
914 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700915 return MakeTestResultCode(0, 1, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700916 }
917
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700918 /* 0.0 half-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700919 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200920 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
921#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
922 || Item.uDataType != QCBOR_TYPE_DOUBLE
923 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700924#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
925 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200926#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
927 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700928 return MakeTestResultCode(0, 2, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700929 }
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700930
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700931 /* 3.14 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700932 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200933 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
934#ifndef USEFULBUF_DISABLE_ALL_FLOAT
935 || Item.uDataType != QCBOR_TYPE_DOUBLE
936 || Item.val.dfnum != 3.14
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700937#else /* USEFULBUF_DISABLE_ALL_FLOAT */
938 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200939#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
940 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700941 return MakeTestResultCode(0, 3, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700942 }
943
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700944 /* 0.0 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700945 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200946 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
947#ifndef USEFULBUF_DISABLE_ALL_FLOAT
948 || Item.uDataType != QCBOR_TYPE_DOUBLE
949 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700950#else /* USEFULBUF_DISABLE_ALL_FLOAT */
951 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200952#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
953 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700954 return MakeTestResultCode(0, 4, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700955 }
956
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700957 /* NaN double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700958 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200959 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
960#ifndef USEFULBUF_DISABLE_ALL_FLOAT
961 || Item.uDataType != QCBOR_TYPE_DOUBLE
962 || !isnan(Item.val.dfnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700963#else /* USEFULBUF_DISABLE_ALL_FLOAT */
964 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200965#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
966 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700967 return MakeTestResultCode(0, 5, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700968 }
969
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700970 /* Infinity double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700971 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200972 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
973#ifndef USEFULBUF_DISABLE_ALL_FLOAT
974 || Item.uDataType != QCBOR_TYPE_DOUBLE
975 || Item.val.dfnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700976#else /* USEFULBUF_DISABLE_ALL_FLOAT */
977 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200978#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
979 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700980 return MakeTestResultCode(0, 6, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700981 }
982
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700983 /* 0.0 half-precision (again) */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700984 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200985 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
986#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
987 || Item.uDataType != QCBOR_TYPE_DOUBLE
988 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700989#else /* USEFULBUF_DISABLE_ALL_FLOAT */
990 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200991#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
992 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700993 return MakeTestResultCode(0, 7, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700994 }
995
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700996 /* 3.140000104904175 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700997 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200998 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
999#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001000#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001001 || Item.uDataType != QCBOR_TYPE_DOUBLE
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001002 || 3.1400001049041748 != Item.val.dfnum
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001003#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001004 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001005 || 3.140000f != Item.val.fnum
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001006#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1007#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1008 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001009#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1010 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001011 return MakeTestResultCode(0, 8, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001012 }
1013
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001014 /* 0.0 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001015 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001016 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1017#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001018#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1019 || Item.uDataType != QCBOR_TYPE_DOUBLE
1020 || Item.val.dfnum != 0.0
1021#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001022 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001023 || Item.val.fnum != 0.0f
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001024#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1025#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1026 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001027#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1028 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001029 return MakeTestResultCode(0, 9, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001030 }
1031
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001032 /* NaN single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001033 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001034 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1035#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001036#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1037 || Item.uDataType != QCBOR_TYPE_DOUBLE
1038 || !isnan(Item.val.dfnum)
1039#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001040 || Item.uDataType != QCBOR_TYPE_FLOAT
1041 || !isnan(Item.val.fnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001042#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1043#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1044 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001045#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1046 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001047 return MakeTestResultCode(0, 10, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001048 }
1049
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001050 /* Infinity single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001051 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001052 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1053#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001054#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1055 || Item.uDataType != QCBOR_TYPE_DOUBLE
1056 || Item.val.dfnum != INFINITY
1057#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001058 || Item.uDataType != QCBOR_TYPE_FLOAT
1059 || Item.val.fnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001060#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1061#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1062 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001063#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1064 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001065 return MakeTestResultCode(0, 11, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001066 }
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001067 /* Sufficent test coverage. Don't need to decode the rest. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001068
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001069
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001070#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001071 /* Now tests for spiffy decode main function */
1072 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001073 double d;
1074 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07001075 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001076
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001077 /* 0.0 half-precision */
1078 QCBORDecode_GetDouble(&DC, &d);
1079 uErr = QCBORDecode_GetAndResetError(&DC);
1080 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001081#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001082 || d != 0.0
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001083#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001084 ) {
1085 return MakeTestResultCode(1, 1, uErr);
1086 }
1087
1088 /* 3.14 double-precision */
1089 QCBORDecode_GetDouble(&DC, &d);
1090 uErr = QCBORDecode_GetAndResetError(&DC);
1091 if(uErr != QCBOR_SUCCESS || d != 3.14) {
1092 return MakeTestResultCode(1, 2, uErr);
1093 }
1094
1095 /* 0.0 double-precision */
1096 QCBORDecode_GetDouble(&DC, &d);
1097 uErr = QCBORDecode_GetAndResetError(&DC);
1098 if(uErr != QCBOR_SUCCESS || d != 0.0) {
1099 return MakeTestResultCode(1, 3, uErr);
1100 }
1101
1102 /* NaN double-precision */
1103 QCBORDecode_GetDouble(&DC, &d);
1104 uErr = QCBORDecode_GetAndResetError(&DC);
1105 if(uErr != QCBOR_SUCCESS || !isnan(d)) {
1106 return MakeTestResultCode(1, 4, uErr);
1107 }
1108
1109 /* Infinity double-precision */
1110 QCBORDecode_GetDouble(&DC, &d);
1111 uErr = QCBORDecode_GetAndResetError(&DC);
1112 if(uErr != QCBOR_SUCCESS || d != INFINITY) {
1113 return MakeTestResultCode(1, 5, uErr);
1114 }
1115
1116 /* 0.0 half-precision */
1117 QCBORDecode_GetDouble(&DC, &d);
1118 uErr = QCBORDecode_GetAndResetError(&DC);
1119 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
1120#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
1121 || d != 0.0
1122#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
1123 ) {
1124 return MakeTestResultCode(1, 6, uErr);
1125 }
1126
1127 /* 3.140000104904175 single-precision */
1128 QCBORDecode_GetDouble(&DC, &d);
1129 uErr = QCBORDecode_GetAndResetError(&DC);
1130 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1131#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1132 || d != 3.140000104904175
1133#endif
1134 ) {
1135 return MakeTestResultCode(1, 7, uErr);
1136 }
1137
1138 /* 0.0 single-precision */
1139 QCBORDecode_GetDouble(&DC, &d);
1140 uErr = QCBORDecode_GetAndResetError(&DC);
1141 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1142#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1143 || d != 0.0
1144#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1145 ) {
1146 return MakeTestResultCode(1, 8, uErr);
1147 }
1148
1149 /* NaN single-precision */
1150 QCBORDecode_GetDouble(&DC, &d);
1151 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1152#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1153 || !isnan(d)
1154#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1155 ) {
1156 return MakeTestResultCode(1, 9, uErr);
1157 }
1158
1159 /* Infinity single-precision */
1160 QCBORDecode_GetDouble(&DC, &d);
1161 uErr = QCBORDecode_GetAndResetError(&DC);
1162 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1163#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1164 || d != INFINITY
1165#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1166 ) {
1167 return MakeTestResultCode(1, 10, uErr);
1168 }
1169
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001170#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001171
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001172 return 0;
1173}
1174
1175
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001176
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001177#ifdef NAN_EXPERIMENT
1178/*
1179 Code for checking what the double to float cast does with
1180 NaNs. Not run as part of tests. Keep it around to
1181 be able to check various platforms and CPUs.
1182 */
1183
1184#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1185#define DOUBLE_NUM_EXPONENT_BITS (11)
1186#define DOUBLE_NUM_SIGN_BITS (1)
1187
1188#define DOUBLE_SIGNIFICAND_SHIFT (0)
1189#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1190#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1191
1192#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1193#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1194#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1195#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1196
1197
1198static int NaNExperiments() {
1199 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1200 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1201 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001202
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001203 float f1 = (float)dqNaN;
1204 float f2 = (float)dsNaN;
1205 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001206
1207
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001208 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1209 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1210 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001211
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001212 // Result of this on x86 is that every NaN is a qNaN. The intel
1213 // CVTSD2SS instruction ignores the NaN payload and even converts
1214 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001215
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001216 return 0;
1217}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001218#endif /* NAN_EXPERIMENT */