blob: 294be55bab642b8d96ab9ac3a8d7cae32a5d491d [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 Lundblade33ed26f2024-11-24 10:26:43 -080019#include "qcbor/qcbor_number_decode.h"
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070020#include <math.h> /* For INFINITY and NAN and isnan() */
Laurence Lundblade585127a2020-07-15 03:25:24 -070021
Laurence Lundblade16a207a2021-09-18 17:22:46 -070022
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070023
24/* Make a test results code that includes three components. Return code
25 * is xxxyyyzzz where zz is the error code, yy is the test number and
26 * zz is check being performed
Laurence Lundblade16a207a2021-09-18 17:22:46 -070027 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070028static inline int32_t
29MakeTestResultCode(uint32_t uTestCase,
30 uint32_t uTestNumber,
31 QCBORError uErrorCode)
Laurence Lundblade16a207a2021-09-18 17:22:46 -070032{
33 uint32_t uCode = (uTestCase * 1000000) +
34 (uTestNumber * 1000) +
35 (uint32_t)uErrorCode;
36 return (int32_t)uCode;
37}
38
39
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -070040#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -070041
Laurence Lundbladed711fb22018-09-26 14:35:22 -070042#include "half_to_double_from_rfc7049.h"
Laurence Lundblade68a13352018-09-23 02:19:54 -070043
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080044
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080045struct FloatTestCase {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070046 double dNumber;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080047 float fNumber;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070048 UsefulBufC Preferred;
49 UsefulBufC NotPreferred;
50 UsefulBufC CDE;
51 UsefulBufC DCBOR;
52};
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -070053
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080054/* Boundaries for destination conversions:
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070055 *
56 * smallest subnormal single 1.401298464324817e-45 2^^-149
57 * largest subnormal single 1.1754942106924411e-38 2^^-126
58 * smallest normal single 1.1754943508222875e-38
59 * largest single 3.4028234663852886E+38
60 *
61 * smallest subnormal half 5.9604644775390625E-8
62 * largest subnormal half 6.097555160522461E-5
63 * smallest normal half 6.103515625E-5
64 * largest half 65504.0
65 *
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080066 * Boundaries for origin conversions:
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070067 * smallest subnormal double 5.0e-324 2^^-1074
68 * largest subnormal double
69 * smallest normal double 2.2250738585072014e-308 2^^-1022
70 * largest normal double 1.7976931348623157e308 2^^-1023
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080071 *
72 * Boundaries for double conversion to 64-bit integer:
73 * exponent 51, 52 significand bits set 4503599627370495
74 * exponent 52, 52 significand bits set 9007199254740991
75 * exponent 53, 52 bits set in significand 18014398509481982
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070076 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070077
78/* Always four lines per test case so shell scripts can process into
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080079 * other formats. CDE and DCBOR standards are not complete yet,
80 * encodings are what is expected. C string literals are used because they
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070081 * are the shortest notation. They are used __with a length__ . Null
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080082 * termination doesn't work because there are zero bytes.
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070083 */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080084static const struct FloatTestCase FloatTestCases[] = {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070085 /* Zero */
86 {0.0, 0.0f,
87 {"\xF9\x00\x00", 3}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080088 {"\xF9\x00\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070089
90 /* Negative Zero */
91 {-0.0, -0.0f,
92 {"\xF9\x80\x00", 3}, {"\xFB\x80\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080093 {"\xF9\x80\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070094
95 /* NaN */
96 {NAN, NAN,
97 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
98 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
99
100 /* Infinity */
101 {INFINITY, INFINITY,
102 {"\xF9\x7C\x00", 3}, {"\xFB\x7F\xF0\x00\x00\x00\x00\x00\x00", 9},
103 {"\xF9\x7C\x00", 3}, {"\xF9\x7C\x00", 3}},
104
105 /* Negative Infinity */
106 {-INFINITY, -INFINITY,
107 {"\xF9\xFC\x00", 3}, {"\xFB\xFF\xF0\x00\x00\x00\x00\x00\x00", 9},
108 {"\xF9\xFC\x00", 3}, {"\xF9\xFC\x00", 3}},
109
110 /* 1.0 */
111 {1.0, 1.0f,
112 {"\xF9\x3C\x00", 3}, {"\xFB\x3F\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800113 {"\xF9\x3C\x00", 3}, {"\x01", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700114
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800115 /* -2.0 -- a negative */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700116 {-2.0, -2.0f,
117 {"\xF9\xC0\x00", 3}, {"\xFB\xC0\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800118 {"\xF9\xC0\x00", 3}, {"\x21", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700119
120 /* 1/3 */
121 {0.333251953125, 0.333251953125f,
122 {"\xF9\x35\x55", 3}, {"\xFB\x3F\xD5\x54\x00\x00\x00\x00\x00", 9},
123 {"\xF9\x35\x55", 3}, {"\xF9\x35\x55", 3}},
124
125 /* 5.9604644775390625E-8 -- smallest half-precision subnormal */
126 {5.9604644775390625E-8, 0.0f,
127 {"\xF9\x00\x01", 3}, {"\xFB\x3E\x70\x00\x00\x00\x00\x00\x00", 9},
128 {"\xF9\x00\x01", 3}, {"\xF9\x00\x01", 3}},
129
130 /* 3.0517578125E-5 -- a half-precision subnormal */
131 {3.0517578125E-5, 0.0f,
132 {"\xF9\x02\x00", 3}, {"\xFB\x3F\x00\x00\x00\x00\x00\x00\x00", 9},
133 {"\xF9\x02\x00", 3}, {"\xF9\x02\x00", 3}},
134
135 /* 6.097555160522461E-5 -- largest half-precision subnormal */
136 {6.097555160522461E-5, 0.0f,
137 {"\xF9\x03\xFF", 3}, {"\xFB\x3F\x0F\xF8\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800138 {"\xF9\x03\xFF", 3}, {"\xF9\x03\xFF", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700139
140 /* 6.1035156249999993E-5 -- slightly smaller than smallest half-precision normal */
141 {6.1035156249999993E-5, 0.0f,
142 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
143 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
144
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800145 /* 6.103515625E-5 -- smallest half-precision normal */
146 {6.103515625E-5, 0.0f,
147 {"\xF9\04\00", 3}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x00", 9},
148 {"\xF9\04\00", 3}, {"\xF9\04\00", 3}},
149
150 /* 6.1035156250000014E-5 -- slightly larger than smallest half-precision normal */
151 {6.1035156250000014E-5, 0.0f,
152 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9},
153 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}},
154
155 /* 65504.0 -- largest half-precision */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700156 {65504.0, 0.0f,
157 {"\xF9\x7B\xFF", 3}, {"\xFB\x40\xEF\xFC\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800158 {"\xF9\x7B\xFF", 3}, {"\x19\xFF\xE0", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700159
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800160 /* 65504.1 -- exponent too large and too much precision to convert to half */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700161 {65504.1, 0.0f,
162 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9},
163 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}},
164
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800165 /* 65536.0 -- exponent too large for half but not too much precision for single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700166 {65536.0, 65536.0f,
167 {"\xFA\x47\x80\x00\x00", 5}, {"\xFB\x40\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800168 {"\xFA\x47\x80\x00\x00", 5}, {"\x1A\x00\x01\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700169
170 /* 1.401298464324817e-45 -- smallest single subnormal */
171 {1.401298464324817e-45, 1.40129846E-45f,
172 {"\xFA\x00\x00\x00\x01", 5}, {"\xFB\x36\xA0\x00\x00\x00\x00\x00\x00", 9},
173 {"\xFA\x00\x00\x00\x01", 5}, {"\xFA\x00\x00\x00\x01", 5}},
174
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800175 /* 5.8774717541114375E-39 -- slightly smaller than the smallest single normal */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700176 {5.8774717541114375E-39, 5.87747175E-39f,
177 {"\xFA\x00\x40\x00\x00", 5}, {"\xFB\x38\x00\x00\x00\x00\x00\x00\x00", 9},
178 {"\xFA\x00\x40\x00\x00", 5}, {"\xFA\x00\x40\x00\x00", 5}},
179
180 /* 1.1754942106924411e-38 -- largest single subnormal */
181 {1.1754942106924411E-38, 1.17549421E-38f,
182 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFB\x38\x0f\xff\xff\xC0\x00\x00\x00", 9},
183 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFA\x00\x7f\xff\xff", 5} },
184
185 /* 1.1754943508222874E-38 -- slightly bigger than smallest single normal */
186 {1.1754943508222874E-38, 0.0f,
187 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9},
188 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}},
189
190 /* 1.1754943508222875e-38 -- smallest single normal */
191 {1.1754943508222875e-38, 1.17549435E-38f,
192 {"\xFA\x00\x80\x00\x00", 5}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x00", 9},
193 {"\xFA\x00\x80\x00\x00", 5}, {"\xFA\x00\x80\x00\x00", 5}},
194
195 /* 1.1754943508222875e-38 -- slightly bigger than smallest single normal */
196 {1.1754943508222878e-38, 0.0f,
197 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9},
198 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}},
199
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800200 /* 8388607 -- exponent 22 to test single exponent boundary */
201 {8388607, 8388607.0f,
202 {"\xFA\x4A\xFF\xFF\xFE", 5}, {"\xFB\x41\x5F\xFF\xFF\xC0\x00\x00\x00", 9},
203 {"\xFA\x4A\xFF\xFF\xFE", 5}, {"\x1A\x00\x7F\xFF\xFF", 5}},
204
205 /* 16777215 -- exponent 23 to test single exponent boundary */
206 {16777215, 16777215.0f,
207 {"\xFA\x4B\x7F\xFF\xFF", 5}, {"\xFB\x41\x6F\xFF\xFF\xE0\x00\x00\x00", 9},
208 {"\xFA\x4B\x7F\xFF\xFF", 5}, {"\x1A\x00\xFF\xFF\xFF", 5}},
209
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700210 /* 16777216 -- converts to single without loss */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800211 {16777216, 16777216.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700212 {"\xFA\x4B\x80\x00\x00", 5}, {"\xFB\x41\x70\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800213 {"\xFA\x4B\x80\x00\x00", 5}, {"\x1A\x01\x00\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700214
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800215 /* 16777217 -- one more than above and fails conversion to single because of precision */
216 {16777217, 0.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700217 {"\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 -0800218 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\x1A\x01\x00\x00\x01", 5}},
219
220 /* 33554430 -- exponent 24 to test single exponent boundary */
221 {33554430, 33554430.0f,
222 {"\xFA\x4B\xFF\xFF\xFF", 5}, {"\xFB\x41\x7F\xFF\xFF\xE0\x00\x00\x00", 9},
223 {"\xFA\x4B\xFF\xFF\xFF", 5}, {"\x1A\x01\xFF\xFF\xFE", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700224
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800225 /* 4294967295 -- 2^^32 - 1 UINT32_MAX */
226 {4294967295, 0,
227 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
228 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x1A\xFF\xFF\xFF\xFF", 5}},
229
230 /* 4294967296 -- 2^^32, UINT32_MAX + 1 */
231 {4294967296, 4294967296.0f,
232 {"\xFA\x4F\x80\x00\x00", 5}, {"\xFB\x41\xF0\x00\x00\x00\x00\x00\x00", 9},
233 {"\xFA\x4F\x80\x00\x00", 5}, {"\x1B\x00\x00\x00\x01\x00\x00\x00\x00", 9}},
234
235 /* 2251799813685248 -- exponent 51, 0 significand bits set, to test double exponent boundary */
236 {2251799813685248, 2251799813685248.0f,
237 {"\xFA\x59\x00\x00\x00", 5}, {"\xFB\x43\x20\x00\x00\x00\x00\x00\x00", 9},
238 {"\xFA\x59\x00\x00\x00", 5}, {"\x1B\x00\x08\x00\x00\x00\x00\x00\x00", 9}},
239
240 /* 4503599627370495 -- exponent 51, 52 significand bits set to test double exponent boundary*/
241 {4503599627370495, 0,
242 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9},
243 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\x1B\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
244
245 /* 9007199254740991 -- exponent 52, 52 significand bits set to test double exponent boundary */
246 {9007199254740991, 0,
247 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
248 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x1F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
249
250 /* 18014398509481982 -- exponent 53, 52 bits set in significand (double lacks precision to represent 18014398509481983) */
251 {18014398509481982, 0,
252 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
253 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x3F\xFF\xFF\xFF\xFF\xFF\xFE", 9}},
254
255 /* 18014398509481984 -- next largest possible double above 18014398509481982 */
256 {18014398509481984, 18014398509481984.0f,
257 {"\xFA\x5A\x80\x00\x00", 5}, {"\xFB\x43\x50\x00\x00\x00\x00\x00\x00", 9},
258 {"\xFA\x5A\x80\x00\x00", 5}, {"\x1B\x00\x40\x00\x00\x00\x00\x00\x00", 9}},
259
260 /* 18446742974197924000.0.0 -- largest single that can convert to uint64 */
261 {18446742974197924000.0, 18446742974197924000.0f,
262 {"\xFA\x5F\x7F\xFF\xFF", 5}, {"\xFB\x43\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
263 {"\xFA\x5F\x7F\xFF\xFF", 5}, {"\x1B\xFF\xFF\xFF\x00\x00\x00\x00\x00", 9}},
264
265 /* 18446744073709550000.0 -- largest double that can convert to uint64, almost UINT64_MAX (18446744073709551615) */
266 {18446744073709550000.0, 0,
267 {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
268 {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\xFF\xFF\xFF\xFF\xFF\xFF\xF8\x00", 9}},
269
270 /* 18446744073709552000.0 -- just too large to convert to uint64, but converts to a single, just over UINT64_MAX */
271 {18446744073709552000.0, 18446744073709552000.0f,
272 {"\xFA\x5F\x80\x00\x00", 5}, {"\xFB\x43\xF0\x00\x00\x00\x00\x00\x00", 9},
273 {"\xFA\x5F\x80\x00\x00", 5}, {"\xFA\x5F\x80\x00\x00", 5}},
274
275 /* -4294967295 -- negative UINT32_MAX */
276 {-4294967295.0, 0,
277 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
278 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x3A\xFF\xFF\xFF\xFE", 5}},
279
280 /* -9223372036854774784.0 -- most negative double that converts to int64 */
281 {-9223372036854774784.0, 0,
282 {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
283 {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x3B\x7F\xFF\xFF\xFF\xFF\xFF\xFB\xFF", 9}},
284
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700285 /* -18446742974197923840.0 -- large negative that converts to float, but too large for int64 */
286 {-18446742974197923840.0, -18446742974197923840.0f,
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800287 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\xFB\xC3\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700288 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\x3B\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF", 9}},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800289
290 /* 3.4028234663852886E+38 -- largest possible single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700291 {3.4028234663852886E+38, 3.40282347E+38f,
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800292 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
293 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFA\x7F\x7F\xFF\xFF", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700294
295 /* 3.402823466385289E+38 -- slightly larger than largest possible single */
296 {3.402823466385289E+38, 0.0f,
297 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9},
298 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}},
299
300 /* 3.402823669209385e+38 -- exponent larger by one than largest possible single */
301 {3.402823669209385e+38, 0.0f,
302 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9},
303 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}},
304
305 /* 5.0e-324 -- smallest double subnormal normal */
306 {5.0e-324, 0.0f,
307 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9},
308 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}},
309
310 /* 2.2250738585072009E−308 -- largest double subnormal */
311 {2.2250738585072009e-308, 0.0f,
312 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
313 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
314
315 /* 2.2250738585072014e-308 -- smallest double normal */
316 {2.2250738585072014e-308, 0.0f,
317 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9},
318 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}},
319
320 /* 1.7976931348623157E308 -- largest double normal */
321 {1.7976931348623157e308, 0.0f,
322 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
323 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
324
325 /* List terminator */
326 {0.0, 0.0f, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700327};
328
329
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800330/* Can't use types double and float here because there's no way in C to
331 * construct arbitrary payloads for those types.
332 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700333struct NaNTestCase {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800334 uint64_t uDouble; /* Converted to double in test */
335 uint32_t uSingle; /* Converted to single in test */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700336 UsefulBufC Preferred;
337 UsefulBufC NotPreferred;
338 UsefulBufC CDE;
339 UsefulBufC DCBOR;
340};
341
342/* Always four lines per test case so shell scripts can process into
343 * other formats. CDE and DCBOR standards are not complete yet,
344 * encodings are a guess. C string literals are used because they
345 * are the shortest notation. They are used __with a length__ . Null
346 * termination doesn't work because there are zero bytes.
347 */
348static const struct NaNTestCase NaNTestCases[] = {
349
350 /* Payload with most significant bit set, a qNaN by most implementations */
351 {0x7ff8000000000000, 0x00000000,
352 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
353 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
354
355 /* Payload with single rightmost set */
356 {0x7ff8000000000001, 0x00000000,
357 {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9},
358 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
359
360 /* Payload with 10 leftmost bits set -- converts to half */
361 {0x7ffffc0000000000, 0x00000000,
362 {"\xF9\x7F\xFF", 3}, {"\xFB\x7F\xFF\xFC\x00\x00\x00\x00\x00", 9},
363 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
364
365 /* Payload with 10 rightmost bits set -- cannot convert to half */
366 {0x7ff80000000003ff, 0x00000000,
367 {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9},
368 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
369
370 /* Payload with 23 leftmost bits set -- converts to a single */
371 {0x7ffFFFFFE0000000, 0x7fffffff,
372 {"\xFA\x7F\xFF\xFF\xFF", 5}, {"\xFB\x7F\xFF\xFF\xFF\xE0\x00\x00\x00", 9},
373 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
374
375 /* Payload with 24 leftmost bits set -- fails to convert to a single */
376 {0x7ffFFFFFF0000000, 0x00000000,
377 {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9}, {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9},
378 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
379
380 /* Payload with all bits set */
381 {0x7fffffffffffffff, 0x00000000,
382 {"\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 -0800383 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700384
385 /* List terminator */
386 {0, 0, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
387};
388
389
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700390/* Public function. See float_tests.h
391 *
392 * This is the main test of floating-point encoding / decoding. It is
393 * data-driven by the above tables. It works better than tests below that
394 * it mostly replaces because it tests one number at a time, rather than
395 * putting them all in a map. It is much easier to debug test failures
396 * and to add new tests. */
397int32_t
398FloatValuesTests(void)
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700399{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700400 unsigned int uTestIndex;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800401 const struct FloatTestCase *pTestCase;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700402 const struct NaNTestCase *pNaNTestCase;
403 MakeUsefulBufOnStack( TestOutBuffer, 20);
404 UsefulBufC TestOutput;
405 QCBOREncodeContext EnCtx;
406 QCBORError uErr;
407 QCBORDecodeContext DCtx;
408 QCBORItem Item;
409 uint64_t uDecoded;
410#ifdef QCBOR_DISABLE_FLOAT_HW_USE
411 uint32_t uDecoded2;
412#endif
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700413
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700414 /* Test a variety of doubles */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800415 for(uTestIndex = 0; FloatTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
416 pTestCase = &FloatTestCases[uTestIndex];
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700417
Laurence Lundblade82634b62024-11-20 22:37:45 -0800418 if(uTestIndex == 2) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800419 uDecoded = 1;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700420 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800421
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700422 /* Number Encode of Preferred */
423 QCBOREncode_Init(&EnCtx, TestOutBuffer);
424 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
425 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800426
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700427 if(uErr != QCBOR_SUCCESS) {
428 return MakeTestResultCode(uTestIndex, 1, uErr);;
429 }
430 if(UsefulBuf_Compare(TestOutput, pTestCase->Preferred)) {
431 return MakeTestResultCode(uTestIndex, 1, 200);
432 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700433
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700434 /* Number Encode of Not Preferred */
435 QCBOREncode_Init(&EnCtx, TestOutBuffer);
436 QCBOREncode_AddDoubleNoPreferred(&EnCtx, pTestCase->dNumber);
437 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade68a13352018-09-23 02:19:54 -0700438
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700439 if(uErr != QCBOR_SUCCESS) {
440 return MakeTestResultCode(uTestIndex, 2, uErr);;
441 }
442 if(UsefulBuf_Compare(TestOutput, pTestCase->NotPreferred)) {
443 return MakeTestResultCode(uTestIndex, 2, 200);
444 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800445
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800446 /* Number Encode of CDE */
447 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800448 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_CDE);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800449 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
450 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
451
452 if(uErr != QCBOR_SUCCESS) {
453 return MakeTestResultCode(uTestIndex, 20, uErr);;
454 }
455 if(UsefulBuf_Compare(TestOutput, pTestCase->CDE)) {
456 return MakeTestResultCode(uTestIndex, 21, 200);
457 }
458
459 /* Number Encode of dCBOR */
460 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800461 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800462 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
463 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
464
465 if(uErr != QCBOR_SUCCESS) {
466 return MakeTestResultCode(uTestIndex, 22, uErr);;
467 }
468 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
469 return MakeTestResultCode(uTestIndex, 23, 200);
470 }
471
472 if(pTestCase->fNumber != 0) {
473 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800474 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800475 QCBOREncode_AddFloat(&EnCtx, pTestCase->fNumber);
476 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
477
478 if(uErr != QCBOR_SUCCESS) {
479 return MakeTestResultCode(uTestIndex, 24, uErr);;
480 }
481 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
482 return MakeTestResultCode(uTestIndex, 25, 200);
483 }
484 }
485
486
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700487 /* Number Decode of Preferred */
488 QCBORDecode_Init(&DCtx, pTestCase->Preferred, 0);
489 uErr = QCBORDecode_GetNext(&DCtx, &Item);
490 if(uErr != QCBOR_SUCCESS) {
491 return MakeTestResultCode(uTestIndex, 3, uErr);;
492 }
493#ifndef QCBOR_DISABLE_FLOAT_HW_USE
494 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
495 return MakeTestResultCode(uTestIndex, 4, 0);
496 }
497 if(isnan(pTestCase->dNumber)) {
498 if(!isnan(Item.val.dfnum)) {
499 return MakeTestResultCode(uTestIndex, 5, 0);
500 }
501 } else {
502 if(Item.val.dfnum != pTestCase->dNumber) {
503 return MakeTestResultCode(uTestIndex, 6, 0);
504 }
505 }
506#else /* QCBOR_DISABLE_FLOAT_HW_USE */
507 /* When QCBOR_DISABLE_FLOAT_HW_USE is set, single-precision is not
508 * converted to double when decoding, so test differently. len == 5
509 * indicates single-precision in the encoded CBOR. */
510 if(pTestCase->Preferred.len == 5) {
511 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800512 return MakeTestResultCode(uTestIndex, 41, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700513 }
514 if(isnan(pTestCase->dNumber)) {
515 if(!isnan(Item.val.fnum)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800516 return MakeTestResultCode(uTestIndex, 51, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700517 }
518 } else {
519 if(Item.val.fnum != pTestCase->fNumber) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800520 return MakeTestResultCode(uTestIndex, 61, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700521 }
522 }
523 } else {
524 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800525 return MakeTestResultCode(uTestIndex, 42, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700526 }
527 if(isnan(pTestCase->dNumber)) {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700528 if(!isnan(Item.val.dfnum)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800529 return MakeTestResultCode(uTestIndex, 52, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700530 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700531 } else {
532 if(Item.val.dfnum != pTestCase->dNumber) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800533 return MakeTestResultCode(uTestIndex, 62, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700534 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700535 }
536 }
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800537#endif /* ! QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700538
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700539 /* Number Decode of Not Preferred */
540 QCBORDecode_Init(&DCtx, pTestCase->NotPreferred, 0);
541 uErr = QCBORDecode_GetNext(&DCtx, &Item);
542 if(uErr != QCBOR_SUCCESS) {
543 return MakeTestResultCode(uTestIndex, 7, uErr);;
544 }
545 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
546 return MakeTestResultCode(uTestIndex, 8, 0);
547 }
548 if(isnan(pTestCase->dNumber)) {
549 if(!isnan(Item.val.dfnum)) {
550 return MakeTestResultCode(uTestIndex, 9, 0);
551 }
552 } else {
553 if(Item.val.dfnum != pTestCase->dNumber) {
554 return MakeTestResultCode(uTestIndex, 10, 0);
555 }
556 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700557
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700558 }
559
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700560 /* Test a variety of NaNs with payloads */
561 for(uTestIndex = 0; NaNTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
562 pNaNTestCase = &NaNTestCases[uTestIndex];
563
564
565 if(uTestIndex == 4) {
566 uErr = 99; /* For setting break points for particular tests */
567 }
568
569 /* NaN Encode of Preferred */
570 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800571 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700572 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
573 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
574 if(uErr != QCBOR_SUCCESS) {
575 return MakeTestResultCode(uTestIndex+100, 10, uErr);;
576 }
577 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->Preferred)) {
578 return MakeTestResultCode(uTestIndex+100, 10, 200);
579 }
580
581#ifdef QCBOR_COMPARE_TO_HW_NAN_CONVERSION
582 {
583 /* This test is off by default. It's purpose is to check
584 * QCBOR's mask-n-shift implementation against the HW/CPU
585 * instructions that do conversion between double and single.
586 * It is off because it is only used on occasion to verify
587 * QCBOR and because it is suspected that some HW/CPU does
588 * implement this correctly. NaN payloads are an obscure
589 * feature. */
590 float f;
591 double d, d2;
592
593 d = UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uNumber);
594
595 /* Cast the double to a single and then back to a double and
596 * see if they are equal. If so, then the NaN payload doesn't
597 * have any bits that are lost when converting to single and
598 * it can be safely converted.
599 *
600 * This test can't be done for half-precision because it is
601 * not widely supported.
602 */
603 f = (float)d;
604 d2 = (double)f;
605
606 /* The length of encoded doubles is 9, singles 5 and halves
607 * 3. If there are NaN payload bits that can't be converted,
608 * then the length must be 9.
609 */
610 if((uint64_t)d != (uint64_t)d2 && pNaNTestCase->Preferred.len != 9) {
611 /* QCBOR conversion not the same as HW conversion */
612 return MakeTestResultCode(uTestIndex, 9, 200);
613 }
614 }
615#endif /* QCBOR_COMPARE_TO_HW_NAN_CONVERSION */
616
617
618 /* NaN Encode of Not Preferred */
619 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800620 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700621 QCBOREncode_AddDoubleNoPreferred(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
622 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
623 if(uErr != QCBOR_SUCCESS) {
624 return MakeTestResultCode(uTestIndex+100, 11, uErr);;
625 }
626 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->NotPreferred)) {
627 return MakeTestResultCode(uTestIndex+100, 11, 200);
628 }
629
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800630 /* NaN Decode of Not Preferred */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700631 QCBORDecode_Init(&DCtx, pNaNTestCase->Preferred, 0);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800632 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700633 uErr = QCBORDecode_GetNext(&DCtx, &Item);
634 if(uErr != QCBOR_SUCCESS) {
635 return MakeTestResultCode(uTestIndex+100, 12, uErr);
636 }
637
638#ifndef QCBOR_DISABLE_FLOAT_HW_USE
639
640 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
641 if(uDecoded != pNaNTestCase->uDouble) {
642 return MakeTestResultCode(uTestIndex+100, 12, 200);
643 }
644#else /* QCBOR_DISABLE_FLOAT_HW_USE */
645 if(pNaNTestCase->Preferred.len == 5) {
646 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
647 return MakeTestResultCode(uTestIndex, 4, 0);
648 }
649
650 uDecoded2 = UsefulBufUtil_CopyFloatToUint32(Item.val.fnum);
651
652 if(uDecoded2 != pNaNTestCase->uSingle) {
653 return MakeTestResultCode(uTestIndex, 4, 0);
654 }
655 } else {
656 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
657 return MakeTestResultCode(uTestIndex, 4, 0);
658 }
659 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
660 if(uDecoded != pNaNTestCase->uDouble) {
661 return MakeTestResultCode(uTestIndex+100, 12, 200);
662 }
663 }
664#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
665
666 /* NaN Decode of Not Preferred */
667 QCBORDecode_Init(&DCtx, pNaNTestCase->NotPreferred, 0);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800668 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700669 uErr = QCBORDecode_GetNext(&DCtx, &Item);
670 if(uErr != QCBOR_SUCCESS) {
671 return MakeTestResultCode(uTestIndex+100, 13, uErr);
672 }
673 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
674 if(uDecoded != pNaNTestCase->uDouble) {
675 return MakeTestResultCode(uTestIndex+100, 13, 200);
676 }
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800677
678
679 /* NaN Encode of DCBOR */
680 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800681 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR | QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800682 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 */