blob: f32d181dfce8bcfe84b5b6b3cf838d859c30d646 [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 Lundblade0fd2d502024-12-20 14:27:24 -070016#include "qcbor/qcbor_main_encode.h"
17#include "qcbor/qcbor_number_encode.h"
Laurence Lundblade02fcf312020-07-17 02:49:46 -070018#include "qcbor/qcbor_decode.h"
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -070019#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade33ed26f2024-11-24 10:26:43 -080020#include "qcbor/qcbor_number_decode.h"
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070021#include <math.h> /* For INFINITY and NAN and isnan() */
Laurence Lundblade585127a2020-07-15 03:25:24 -070022
Laurence Lundblade16a207a2021-09-18 17:22:46 -070023
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070024
25/* Make a test results code that includes three components. Return code
26 * is xxxyyyzzz where zz is the error code, yy is the test number and
27 * zz is check being performed
Laurence Lundblade16a207a2021-09-18 17:22:46 -070028 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070029static inline int32_t
30MakeTestResultCode(uint32_t uTestCase,
31 uint32_t uTestNumber,
32 QCBORError uErrorCode)
Laurence Lundblade16a207a2021-09-18 17:22:46 -070033{
34 uint32_t uCode = (uTestCase * 1000000) +
35 (uTestNumber * 1000) +
36 (uint32_t)uErrorCode;
37 return (int32_t)uCode;
38}
39
40
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -070041#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -070042
Laurence Lundbladed711fb22018-09-26 14:35:22 -070043#include "half_to_double_from_rfc7049.h"
Laurence Lundblade68a13352018-09-23 02:19:54 -070044
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080045
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080046struct FloatTestCase {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070047 double dNumber;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080048 float fNumber;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070049 UsefulBufC Preferred;
50 UsefulBufC NotPreferred;
51 UsefulBufC CDE;
52 UsefulBufC DCBOR;
53};
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -070054
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080055/* Boundaries for destination conversions:
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070056 *
57 * smallest subnormal single 1.401298464324817e-45 2^^-149
58 * largest subnormal single 1.1754942106924411e-38 2^^-126
59 * smallest normal single 1.1754943508222875e-38
60 * largest single 3.4028234663852886E+38
61 *
62 * smallest subnormal half 5.9604644775390625E-8
63 * largest subnormal half 6.097555160522461E-5
64 * smallest normal half 6.103515625E-5
65 * largest half 65504.0
66 *
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080067 * Boundaries for origin conversions:
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070068 * smallest subnormal double 5.0e-324 2^^-1074
69 * largest subnormal double
70 * smallest normal double 2.2250738585072014e-308 2^^-1022
71 * largest normal double 1.7976931348623157e308 2^^-1023
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080072 *
73 * Boundaries for double conversion to 64-bit integer:
74 * exponent 51, 52 significand bits set 4503599627370495
75 * exponent 52, 52 significand bits set 9007199254740991
76 * exponent 53, 52 bits set in significand 18014398509481982
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070077 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070078
79/* Always four lines per test case so shell scripts can process into
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080080 * other formats. CDE and DCBOR standards are not complete yet,
81 * encodings are what is expected. C string literals are used because they
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070082 * are the shortest notation. They are used __with a length__ . Null
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080083 * termination doesn't work because there are zero bytes.
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070084 */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080085static const struct FloatTestCase FloatTestCases[] = {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070086 /* Zero */
87 {0.0, 0.0f,
88 {"\xF9\x00\x00", 3}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080089 {"\xF9\x00\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070090
91 /* Negative Zero */
92 {-0.0, -0.0f,
93 {"\xF9\x80\x00", 3}, {"\xFB\x80\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -080094 {"\xF9\x80\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070095
96 /* NaN */
97 {NAN, NAN,
98 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
99 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
100
101 /* Infinity */
102 {INFINITY, INFINITY,
103 {"\xF9\x7C\x00", 3}, {"\xFB\x7F\xF0\x00\x00\x00\x00\x00\x00", 9},
104 {"\xF9\x7C\x00", 3}, {"\xF9\x7C\x00", 3}},
105
106 /* Negative Infinity */
107 {-INFINITY, -INFINITY,
108 {"\xF9\xFC\x00", 3}, {"\xFB\xFF\xF0\x00\x00\x00\x00\x00\x00", 9},
109 {"\xF9\xFC\x00", 3}, {"\xF9\xFC\x00", 3}},
110
111 /* 1.0 */
112 {1.0, 1.0f,
113 {"\xF9\x3C\x00", 3}, {"\xFB\x3F\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800114 {"\xF9\x3C\x00", 3}, {"\x01", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700115
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800116 /* -2.0 -- a negative */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700117 {-2.0, -2.0f,
118 {"\xF9\xC0\x00", 3}, {"\xFB\xC0\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800119 {"\xF9\xC0\x00", 3}, {"\x21", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700120
121 /* 1/3 */
122 {0.333251953125, 0.333251953125f,
123 {"\xF9\x35\x55", 3}, {"\xFB\x3F\xD5\x54\x00\x00\x00\x00\x00", 9},
124 {"\xF9\x35\x55", 3}, {"\xF9\x35\x55", 3}},
125
126 /* 5.9604644775390625E-8 -- smallest half-precision subnormal */
127 {5.9604644775390625E-8, 0.0f,
128 {"\xF9\x00\x01", 3}, {"\xFB\x3E\x70\x00\x00\x00\x00\x00\x00", 9},
129 {"\xF9\x00\x01", 3}, {"\xF9\x00\x01", 3}},
130
131 /* 3.0517578125E-5 -- a half-precision subnormal */
132 {3.0517578125E-5, 0.0f,
133 {"\xF9\x02\x00", 3}, {"\xFB\x3F\x00\x00\x00\x00\x00\x00\x00", 9},
134 {"\xF9\x02\x00", 3}, {"\xF9\x02\x00", 3}},
135
136 /* 6.097555160522461E-5 -- largest half-precision subnormal */
137 {6.097555160522461E-5, 0.0f,
138 {"\xF9\x03\xFF", 3}, {"\xFB\x3F\x0F\xF8\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800139 {"\xF9\x03\xFF", 3}, {"\xF9\x03\xFF", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700140
141 /* 6.1035156249999993E-5 -- slightly smaller than smallest half-precision normal */
142 {6.1035156249999993E-5, 0.0f,
143 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
144 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
145
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800146 /* 6.103515625E-5 -- smallest half-precision normal */
147 {6.103515625E-5, 0.0f,
148 {"\xF9\04\00", 3}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x00", 9},
149 {"\xF9\04\00", 3}, {"\xF9\04\00", 3}},
150
151 /* 6.1035156250000014E-5 -- slightly larger than smallest half-precision normal */
152 {6.1035156250000014E-5, 0.0f,
153 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9},
154 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}},
155
156 /* 65504.0 -- largest half-precision */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700157 {65504.0, 0.0f,
158 {"\xF9\x7B\xFF", 3}, {"\xFB\x40\xEF\xFC\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800159 {"\xF9\x7B\xFF", 3}, {"\x19\xFF\xE0", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700160
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800161 /* 65504.1 -- exponent too large and too much precision to convert to half */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700162 {65504.1, 0.0f,
163 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9},
164 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}},
165
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800166 /* 65536.0 -- exponent too large for half but not too much precision for single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700167 {65536.0, 65536.0f,
168 {"\xFA\x47\x80\x00\x00", 5}, {"\xFB\x40\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800169 {"\xFA\x47\x80\x00\x00", 5}, {"\x1A\x00\x01\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700170
171 /* 1.401298464324817e-45 -- smallest single subnormal */
172 {1.401298464324817e-45, 1.40129846E-45f,
173 {"\xFA\x00\x00\x00\x01", 5}, {"\xFB\x36\xA0\x00\x00\x00\x00\x00\x00", 9},
174 {"\xFA\x00\x00\x00\x01", 5}, {"\xFA\x00\x00\x00\x01", 5}},
175
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800176 /* 5.8774717541114375E-39 -- slightly smaller than the smallest single normal */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700177 {5.8774717541114375E-39, 5.87747175E-39f,
178 {"\xFA\x00\x40\x00\x00", 5}, {"\xFB\x38\x00\x00\x00\x00\x00\x00\x00", 9},
179 {"\xFA\x00\x40\x00\x00", 5}, {"\xFA\x00\x40\x00\x00", 5}},
180
181 /* 1.1754942106924411e-38 -- largest single subnormal */
182 {1.1754942106924411E-38, 1.17549421E-38f,
183 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFB\x38\x0f\xff\xff\xC0\x00\x00\x00", 9},
184 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFA\x00\x7f\xff\xff", 5} },
185
186 /* 1.1754943508222874E-38 -- slightly bigger than smallest single normal */
187 {1.1754943508222874E-38, 0.0f,
188 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9},
189 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}},
190
191 /* 1.1754943508222875e-38 -- smallest single normal */
192 {1.1754943508222875e-38, 1.17549435E-38f,
193 {"\xFA\x00\x80\x00\x00", 5}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x00", 9},
194 {"\xFA\x00\x80\x00\x00", 5}, {"\xFA\x00\x80\x00\x00", 5}},
195
196 /* 1.1754943508222875e-38 -- slightly bigger than smallest single normal */
197 {1.1754943508222878e-38, 0.0f,
198 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9},
199 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}},
200
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800201 /* 8388607 -- exponent 22 to test single exponent boundary */
202 {8388607, 8388607.0f,
203 {"\xFA\x4A\xFF\xFF\xFE", 5}, {"\xFB\x41\x5F\xFF\xFF\xC0\x00\x00\x00", 9},
204 {"\xFA\x4A\xFF\xFF\xFE", 5}, {"\x1A\x00\x7F\xFF\xFF", 5}},
205
206 /* 16777215 -- exponent 23 to test single exponent boundary */
207 {16777215, 16777215.0f,
208 {"\xFA\x4B\x7F\xFF\xFF", 5}, {"\xFB\x41\x6F\xFF\xFF\xE0\x00\x00\x00", 9},
209 {"\xFA\x4B\x7F\xFF\xFF", 5}, {"\x1A\x00\xFF\xFF\xFF", 5}},
210
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700211 /* 16777216 -- converts to single without loss */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800212 {16777216, 16777216.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700213 {"\xFA\x4B\x80\x00\x00", 5}, {"\xFB\x41\x70\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800214 {"\xFA\x4B\x80\x00\x00", 5}, {"\x1A\x01\x00\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700215
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800216 /* 16777217 -- one more than above and fails conversion to single because of precision */
217 {16777217, 0.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700218 {"\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 -0800219 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\x1A\x01\x00\x00\x01", 5}},
220
221 /* 33554430 -- exponent 24 to test single exponent boundary */
222 {33554430, 33554430.0f,
223 {"\xFA\x4B\xFF\xFF\xFF", 5}, {"\xFB\x41\x7F\xFF\xFF\xE0\x00\x00\x00", 9},
224 {"\xFA\x4B\xFF\xFF\xFF", 5}, {"\x1A\x01\xFF\xFF\xFE", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700225
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800226 /* 4294967295 -- 2^^32 - 1 UINT32_MAX */
227 {4294967295, 0,
228 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
229 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x1A\xFF\xFF\xFF\xFF", 5}},
230
231 /* 4294967296 -- 2^^32, UINT32_MAX + 1 */
232 {4294967296, 4294967296.0f,
233 {"\xFA\x4F\x80\x00\x00", 5}, {"\xFB\x41\xF0\x00\x00\x00\x00\x00\x00", 9},
234 {"\xFA\x4F\x80\x00\x00", 5}, {"\x1B\x00\x00\x00\x01\x00\x00\x00\x00", 9}},
235
236 /* 2251799813685248 -- exponent 51, 0 significand bits set, to test double exponent boundary */
237 {2251799813685248, 2251799813685248.0f,
238 {"\xFA\x59\x00\x00\x00", 5}, {"\xFB\x43\x20\x00\x00\x00\x00\x00\x00", 9},
239 {"\xFA\x59\x00\x00\x00", 5}, {"\x1B\x00\x08\x00\x00\x00\x00\x00\x00", 9}},
240
241 /* 4503599627370495 -- exponent 51, 52 significand bits set to test double exponent boundary*/
242 {4503599627370495, 0,
243 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9},
244 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\x1B\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
245
246 /* 9007199254740991 -- exponent 52, 52 significand bits set to test double exponent boundary */
247 {9007199254740991, 0,
248 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
249 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x1F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
250
251 /* 18014398509481982 -- exponent 53, 52 bits set in significand (double lacks precision to represent 18014398509481983) */
252 {18014398509481982, 0,
253 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
254 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x3F\xFF\xFF\xFF\xFF\xFF\xFE", 9}},
255
256 /* 18014398509481984 -- next largest possible double above 18014398509481982 */
257 {18014398509481984, 18014398509481984.0f,
258 {"\xFA\x5A\x80\x00\x00", 5}, {"\xFB\x43\x50\x00\x00\x00\x00\x00\x00", 9},
259 {"\xFA\x5A\x80\x00\x00", 5}, {"\x1B\x00\x40\x00\x00\x00\x00\x00\x00", 9}},
260
261 /* 18446742974197924000.0.0 -- largest single that can convert to uint64 */
262 {18446742974197924000.0, 18446742974197924000.0f,
263 {"\xFA\x5F\x7F\xFF\xFF", 5}, {"\xFB\x43\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
264 {"\xFA\x5F\x7F\xFF\xFF", 5}, {"\x1B\xFF\xFF\xFF\x00\x00\x00\x00\x00", 9}},
265
266 /* 18446744073709550000.0 -- largest double that can convert to uint64, almost UINT64_MAX (18446744073709551615) */
267 {18446744073709550000.0, 0,
268 {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
269 {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\xFF\xFF\xFF\xFF\xFF\xFF\xF8\x00", 9}},
270
271 /* 18446744073709552000.0 -- just too large to convert to uint64, but converts to a single, just over UINT64_MAX */
272 {18446744073709552000.0, 18446744073709552000.0f,
273 {"\xFA\x5F\x80\x00\x00", 5}, {"\xFB\x43\xF0\x00\x00\x00\x00\x00\x00", 9},
274 {"\xFA\x5F\x80\x00\x00", 5}, {"\xFA\x5F\x80\x00\x00", 5}},
275
276 /* -4294967295 -- negative UINT32_MAX */
277 {-4294967295.0, 0,
278 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
279 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x3A\xFF\xFF\xFF\xFE", 5}},
280
281 /* -9223372036854774784.0 -- most negative double that converts to int64 */
282 {-9223372036854774784.0, 0,
283 {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
284 {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x3B\x7F\xFF\xFF\xFF\xFF\xFF\xFB\xFF", 9}},
285
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700286 /* -18446742974197923840.0 -- large negative that converts to float, but too large for int64 */
287 {-18446742974197923840.0, -18446742974197923840.0f,
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800288 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\xFB\xC3\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700289 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\x3B\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF", 9}},
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800290
291 /* 3.4028234663852886E+38 -- largest possible single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700292 {3.4028234663852886E+38, 3.40282347E+38f,
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800293 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
294 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFA\x7F\x7F\xFF\xFF", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700295
296 /* 3.402823466385289E+38 -- slightly larger than largest possible single */
297 {3.402823466385289E+38, 0.0f,
298 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9},
299 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}},
300
301 /* 3.402823669209385e+38 -- exponent larger by one than largest possible single */
302 {3.402823669209385e+38, 0.0f,
303 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9},
304 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}},
305
306 /* 5.0e-324 -- smallest double subnormal normal */
307 {5.0e-324, 0.0f,
308 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9},
309 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}},
310
311 /* 2.2250738585072009E−308 -- largest double subnormal */
312 {2.2250738585072009e-308, 0.0f,
313 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
314 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
315
316 /* 2.2250738585072014e-308 -- smallest double normal */
317 {2.2250738585072014e-308, 0.0f,
318 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9},
319 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}},
320
321 /* 1.7976931348623157E308 -- largest double normal */
322 {1.7976931348623157e308, 0.0f,
323 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
324 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
325
326 /* List terminator */
327 {0.0, 0.0f, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700328};
329
330
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800331/* Can't use types double and float here because there's no way in C to
332 * construct arbitrary payloads for those types.
333 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700334struct NaNTestCase {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800335 uint64_t uDouble; /* Converted to double in test */
336 uint32_t uSingle; /* Converted to single in test */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700337 UsefulBufC Preferred;
338 UsefulBufC NotPreferred;
339 UsefulBufC CDE;
340 UsefulBufC DCBOR;
341};
342
343/* Always four lines per test case so shell scripts can process into
344 * other formats. CDE and DCBOR standards are not complete yet,
345 * encodings are a guess. C string literals are used because they
346 * are the shortest notation. They are used __with a length__ . Null
347 * termination doesn't work because there are zero bytes.
348 */
349static const struct NaNTestCase NaNTestCases[] = {
350
351 /* Payload with most significant bit set, a qNaN by most implementations */
352 {0x7ff8000000000000, 0x00000000,
353 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
354 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
355
356 /* Payload with single rightmost set */
357 {0x7ff8000000000001, 0x00000000,
358 {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9},
359 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
360
361 /* Payload with 10 leftmost bits set -- converts to half */
362 {0x7ffffc0000000000, 0x00000000,
363 {"\xF9\x7F\xFF", 3}, {"\xFB\x7F\xFF\xFC\x00\x00\x00\x00\x00", 9},
364 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
365
366 /* Payload with 10 rightmost bits set -- cannot convert to half */
367 {0x7ff80000000003ff, 0x00000000,
368 {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9},
369 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
370
371 /* Payload with 23 leftmost bits set -- converts to a single */
372 {0x7ffFFFFFE0000000, 0x7fffffff,
373 {"\xFA\x7F\xFF\xFF\xFF", 5}, {"\xFB\x7F\xFF\xFF\xFF\xE0\x00\x00\x00", 9},
374 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
375
376 /* Payload with 24 leftmost bits set -- fails to convert to a single */
377 {0x7ffFFFFFF0000000, 0x00000000,
378 {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9}, {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9},
379 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
380
381 /* Payload with all bits set */
382 {0x7fffffffffffffff, 0x00000000,
383 {"\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 -0800384 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700385
386 /* List terminator */
387 {0, 0, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
388};
389
390
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700391/* Public function. See float_tests.h
392 *
393 * This is the main test of floating-point encoding / decoding. It is
394 * data-driven by the above tables. It works better than tests below that
395 * it mostly replaces because it tests one number at a time, rather than
396 * putting them all in a map. It is much easier to debug test failures
397 * and to add new tests. */
398int32_t
399FloatValuesTests(void)
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700400{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700401 unsigned int uTestIndex;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800402 const struct FloatTestCase *pTestCase;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700403 const struct NaNTestCase *pNaNTestCase;
404 MakeUsefulBufOnStack( TestOutBuffer, 20);
405 UsefulBufC TestOutput;
406 QCBOREncodeContext EnCtx;
407 QCBORError uErr;
408 QCBORDecodeContext DCtx;
409 QCBORItem Item;
410 uint64_t uDecoded;
411#ifdef QCBOR_DISABLE_FLOAT_HW_USE
412 uint32_t uDecoded2;
413#endif
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700414
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700415 /* Test a variety of doubles */
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800416 for(uTestIndex = 0; FloatTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
417 pTestCase = &FloatTestCases[uTestIndex];
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700418
Laurence Lundblade82634b62024-11-20 22:37:45 -0800419 if(uTestIndex == 2) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800420 uDecoded = 1;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700421 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800422
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700423 /* Number Encode of Preferred */
424 QCBOREncode_Init(&EnCtx, TestOutBuffer);
425 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
426 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800427
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700428 if(uErr != QCBOR_SUCCESS) {
429 return MakeTestResultCode(uTestIndex, 1, uErr);;
430 }
431 if(UsefulBuf_Compare(TestOutput, pTestCase->Preferred)) {
432 return MakeTestResultCode(uTestIndex, 1, 200);
433 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700434
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700435 /* Number Encode of Not Preferred */
436 QCBOREncode_Init(&EnCtx, TestOutBuffer);
437 QCBOREncode_AddDoubleNoPreferred(&EnCtx, pTestCase->dNumber);
438 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade68a13352018-09-23 02:19:54 -0700439
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700440 if(uErr != QCBOR_SUCCESS) {
441 return MakeTestResultCode(uTestIndex, 2, uErr);;
442 }
443 if(UsefulBuf_Compare(TestOutput, pTestCase->NotPreferred)) {
444 return MakeTestResultCode(uTestIndex, 2, 200);
445 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800446
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800447 /* Number Encode of CDE */
448 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800449 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_CDE);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800450 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
451 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
452
453 if(uErr != QCBOR_SUCCESS) {
454 return MakeTestResultCode(uTestIndex, 20, uErr);;
455 }
456 if(UsefulBuf_Compare(TestOutput, pTestCase->CDE)) {
457 return MakeTestResultCode(uTestIndex, 21, 200);
458 }
459
460 /* Number Encode of dCBOR */
461 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800462 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800463 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
464 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
465
466 if(uErr != QCBOR_SUCCESS) {
467 return MakeTestResultCode(uTestIndex, 22, uErr);;
468 }
469 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
470 return MakeTestResultCode(uTestIndex, 23, 200);
471 }
472
473 if(pTestCase->fNumber != 0) {
474 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800475 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800476 QCBOREncode_AddFloat(&EnCtx, pTestCase->fNumber);
477 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
478
479 if(uErr != QCBOR_SUCCESS) {
480 return MakeTestResultCode(uTestIndex, 24, uErr);;
481 }
482 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
483 return MakeTestResultCode(uTestIndex, 25, 200);
484 }
485 }
486
487
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700488 /* Number Decode of Preferred */
489 QCBORDecode_Init(&DCtx, pTestCase->Preferred, 0);
490 uErr = QCBORDecode_GetNext(&DCtx, &Item);
491 if(uErr != QCBOR_SUCCESS) {
492 return MakeTestResultCode(uTestIndex, 3, uErr);;
493 }
494#ifndef QCBOR_DISABLE_FLOAT_HW_USE
495 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
496 return MakeTestResultCode(uTestIndex, 4, 0);
497 }
498 if(isnan(pTestCase->dNumber)) {
499 if(!isnan(Item.val.dfnum)) {
500 return MakeTestResultCode(uTestIndex, 5, 0);
501 }
502 } else {
503 if(Item.val.dfnum != pTestCase->dNumber) {
504 return MakeTestResultCode(uTestIndex, 6, 0);
505 }
506 }
507#else /* QCBOR_DISABLE_FLOAT_HW_USE */
508 /* When QCBOR_DISABLE_FLOAT_HW_USE is set, single-precision is not
509 * converted to double when decoding, so test differently. len == 5
510 * indicates single-precision in the encoded CBOR. */
511 if(pTestCase->Preferred.len == 5) {
512 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800513 return MakeTestResultCode(uTestIndex, 41, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700514 }
515 if(isnan(pTestCase->dNumber)) {
516 if(!isnan(Item.val.fnum)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800517 return MakeTestResultCode(uTestIndex, 51, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700518 }
519 } else {
520 if(Item.val.fnum != pTestCase->fNumber) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800521 return MakeTestResultCode(uTestIndex, 61, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700522 }
523 }
524 } else {
525 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800526 return MakeTestResultCode(uTestIndex, 42, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700527 }
528 if(isnan(pTestCase->dNumber)) {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700529 if(!isnan(Item.val.dfnum)) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800530 return MakeTestResultCode(uTestIndex, 52, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700531 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700532 } else {
533 if(Item.val.dfnum != pTestCase->dNumber) {
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800534 return MakeTestResultCode(uTestIndex, 62, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700535 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700536 }
537 }
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800538#endif /* ! QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700539
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700540 /* Number Decode of Not Preferred */
541 QCBORDecode_Init(&DCtx, pTestCase->NotPreferred, 0);
542 uErr = QCBORDecode_GetNext(&DCtx, &Item);
543 if(uErr != QCBOR_SUCCESS) {
544 return MakeTestResultCode(uTestIndex, 7, uErr);;
545 }
546 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
547 return MakeTestResultCode(uTestIndex, 8, 0);
548 }
549 if(isnan(pTestCase->dNumber)) {
550 if(!isnan(Item.val.dfnum)) {
551 return MakeTestResultCode(uTestIndex, 9, 0);
552 }
553 } else {
554 if(Item.val.dfnum != pTestCase->dNumber) {
555 return MakeTestResultCode(uTestIndex, 10, 0);
556 }
557 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700558
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700559 }
560
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700561 /* Test a variety of NaNs with payloads */
562 for(uTestIndex = 0; NaNTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
563 pNaNTestCase = &NaNTestCases[uTestIndex];
564
565
566 if(uTestIndex == 4) {
567 uErr = 99; /* For setting break points for particular tests */
568 }
569
570 /* NaN Encode of Preferred */
571 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800572 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700573 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
574 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
575 if(uErr != QCBOR_SUCCESS) {
576 return MakeTestResultCode(uTestIndex+100, 10, uErr);;
577 }
578 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->Preferred)) {
579 return MakeTestResultCode(uTestIndex+100, 10, 200);
580 }
581
582#ifdef QCBOR_COMPARE_TO_HW_NAN_CONVERSION
583 {
584 /* This test is off by default. It's purpose is to check
585 * QCBOR's mask-n-shift implementation against the HW/CPU
586 * instructions that do conversion between double and single.
587 * It is off because it is only used on occasion to verify
588 * QCBOR and because it is suspected that some HW/CPU does
589 * implement this correctly. NaN payloads are an obscure
590 * feature. */
591 float f;
592 double d, d2;
593
594 d = UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uNumber);
595
596 /* Cast the double to a single and then back to a double and
597 * see if they are equal. If so, then the NaN payload doesn't
598 * have any bits that are lost when converting to single and
599 * it can be safely converted.
600 *
601 * This test can't be done for half-precision because it is
602 * not widely supported.
603 */
604 f = (float)d;
605 d2 = (double)f;
606
607 /* The length of encoded doubles is 9, singles 5 and halves
608 * 3. If there are NaN payload bits that can't be converted,
609 * then the length must be 9.
610 */
611 if((uint64_t)d != (uint64_t)d2 && pNaNTestCase->Preferred.len != 9) {
612 /* QCBOR conversion not the same as HW conversion */
613 return MakeTestResultCode(uTestIndex, 9, 200);
614 }
615 }
616#endif /* QCBOR_COMPARE_TO_HW_NAN_CONVERSION */
617
618
619 /* NaN Encode of Not Preferred */
620 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800621 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700622 QCBOREncode_AddDoubleNoPreferred(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
623 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
624 if(uErr != QCBOR_SUCCESS) {
625 return MakeTestResultCode(uTestIndex+100, 11, uErr);;
626 }
627 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->NotPreferred)) {
628 return MakeTestResultCode(uTestIndex+100, 11, 200);
629 }
630
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800631 /* NaN Decode of Not Preferred */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700632 QCBORDecode_Init(&DCtx, pNaNTestCase->Preferred, 0);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800633 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700634 uErr = QCBORDecode_GetNext(&DCtx, &Item);
635 if(uErr != QCBOR_SUCCESS) {
636 return MakeTestResultCode(uTestIndex+100, 12, uErr);
637 }
638
639#ifndef QCBOR_DISABLE_FLOAT_HW_USE
640
641 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
642 if(uDecoded != pNaNTestCase->uDouble) {
643 return MakeTestResultCode(uTestIndex+100, 12, 200);
644 }
645#else /* QCBOR_DISABLE_FLOAT_HW_USE */
646 if(pNaNTestCase->Preferred.len == 5) {
647 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
648 return MakeTestResultCode(uTestIndex, 4, 0);
649 }
650
651 uDecoded2 = UsefulBufUtil_CopyFloatToUint32(Item.val.fnum);
652
653 if(uDecoded2 != pNaNTestCase->uSingle) {
654 return MakeTestResultCode(uTestIndex, 4, 0);
655 }
656 } else {
657 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
658 return MakeTestResultCode(uTestIndex, 4, 0);
659 }
660 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
661 if(uDecoded != pNaNTestCase->uDouble) {
662 return MakeTestResultCode(uTestIndex+100, 12, 200);
663 }
664 }
665#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
666
667 /* NaN Decode of Not Preferred */
668 QCBORDecode_Init(&DCtx, pNaNTestCase->NotPreferred, 0);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800669 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700670 uErr = QCBORDecode_GetNext(&DCtx, &Item);
671 if(uErr != QCBOR_SUCCESS) {
672 return MakeTestResultCode(uTestIndex+100, 13, uErr);
673 }
674 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
675 if(uDecoded != pNaNTestCase->uDouble) {
676 return MakeTestResultCode(uTestIndex+100, 13, 200);
677 }
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800678
679
680 /* NaN Encode of DCBOR */
681 QCBOREncode_Init(&EnCtx, TestOutBuffer);
Laurence Lundblade82634b62024-11-20 22:37:45 -0800682 QCBOREncode_Config(&EnCtx, QCBOR_ENCODE_CONFIG_DCBOR | QCBOR_ENCODE_CONFIG_ALLOW_NAN_PAYLOAD);
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -0800683 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
684 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
685 if(uErr != QCBOR_SUCCESS) {
686 return MakeTestResultCode(uTestIndex+100, 14, uErr);;
687 }
688 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->DCBOR)) {
689 return MakeTestResultCode(uTestIndex+100, 14, 200);
690 }
691
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700692 }
693
694 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800695}
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700696
697
698
699/* Public function. See float_tests.h */
700int32_t
701HalfPrecisionAgainstRFCCodeTest(void)
702{
703 QCBORItem Item;
704 QCBORDecodeContext DC;
705 unsigned char pbHalfBytes[2];
706 uint8_t uHalfPrecInitialByte;
707 double d;
708 UsefulBuf_MAKE_STACK_UB(EncodedBytes, 3);
709 UsefulOutBuf UOB;
710 uint32_t uHalfP;
711
712
713 for(uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
714 pbHalfBytes[1] = (uint8_t)(uHalfP & 0xff);
715 pbHalfBytes[0] = (uint8_t)(uHalfP >> 8); /* uHalfP is always less than 0xffff */
716 d = decode_half(pbHalfBytes);
717
718 /* Construct the CBOR for the half-precision float by hand */
719 UsefulOutBuf_Init(&UOB, EncodedBytes);
720
721 uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); /* 0xf9 */
722 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); /* initial byte */
723 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP); /* argument */
724
725 /* Now parse the hand-constructed CBOR. This will invoke the
726 * conversion to a float
727 */
728 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
729 QCBORDecode_GetNext(&DC, &Item);
730 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
731 return -1;
732 }
733
734 if(isnan(d)) {
735 /* The RFC code uses the native instructions which may or may not
736 * handle sNaN, qNaN and NaN payloads correctly. This test just
737 * makes sure it is a NaN and doesn't worry about the type of NaN
738 */
739 if(!isnan(Item.val.dfnum)) {
740 return -3;
741 }
742 } else {
743 if(Item.val.dfnum != d) {
744 return -2;
745 }
746 }
747 }
748 return 0;
749}
750
Laurence Lundblade585127a2020-07-15 03:25:24 -0700751#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700752
753
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700754/*
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700755 * Some encoded floating point numbers that are used for both
756 * encode and decode tests.
757 *
758 * [0.0, // Half
759 * 3.14, // Double
760 * 0.0, // Double
761 * NaN, // Double
762 * Infinity, // Double
763 * 0.0, // Half (Duplicate because of use in encode tests)
764 * 3.140000104904175, // Single
765 * 0.0, // Single
766 * NaN, // Single
767 * Infinity, // Single
768 * {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
769 * 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700770 */
771static const uint8_t spExpectedFloats[] = {
772 0x8B,
773 0xF9, 0x00, 0x00,
774 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
775 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778 0xF9, 0x00, 0x00,
779 0xFA, 0x40, 0x48, 0xF5, 0xC3,
780 0xFA, 0x00, 0x00, 0x00, 0x00,
781 0xFA, 0x7F, 0xC0, 0x00, 0x00,
782 0xFA, 0x7F, 0x80, 0x00, 0x00,
783 0xA8,
784 0x18, 0x64,
785 0xF9, 0x00, 0x00,
786 0x18, 0x65,
787 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
788 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
789 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
790 0x18, 0x69,
791 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792 0x18, 0x66,
793 0xF9, 0x00, 0x00,
794 0x18, 0x67,
795 0xFA, 0x40, 0x49, 0x0F, 0xDA,
796 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
797 0xFA, 0x40, 0x2D, 0xF8, 0x54,
798 0x18, 0x6A,
799 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700800
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200801#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700802static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700803 0x8B,
804 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
805 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
806 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
809 0xFA, 0x00, 0x00, 0x00, 0x00,
810 0xFA, 0x40, 0x48, 0xF5, 0xC3,
811 0xFA, 0x00, 0x00, 0x00, 0x00,
812 0xFA, 0x7F, 0xC0, 0x00, 0x00,
813 0xFA, 0x7F, 0x80, 0x00, 0x00,
814 0xA8,
815 0x18, 0x64,
816 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 0x18, 0x65,
818 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
819 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
820 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
821 0x18, 0x69,
822 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823 0x18, 0x66,
824 0xFA, 0x00, 0x00, 0x00, 0x00,
825 0x18, 0x67,
826 0xFA, 0x40, 0x49, 0x0F, 0xDA,
827 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
828 0xFA, 0x40, 0x2D, 0xF8, 0x54,
829 0x18, 0x6A,
830 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700831
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700832
833/* Public function. See float_tests.h */
834int32_t
835GeneralFloatEncodeTests(void)
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700836{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700837 /* See FloatNumberTests() for tests that really cover lots of float values.
838 * Add new tests for new values or decode modes there.
839 * This test is primarily to cover all the float encode methods. */
840
841 UsefulBufC Encoded;
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700842 UsefulBufC ExpectedFloats;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700843 QCBORError uErr;
844
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700845#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700846 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700847 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700848 (void)spExpectedFloatsNoHalf; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700849#else
850 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700851 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700852 (void)spExpectedFloats; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700853#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700854
855 QCBOREncodeContext EC;
856 QCBOREncode_Init(&EC, OutBuffer);
857 QCBOREncode_OpenArray(&EC);
858
859 QCBOREncode_AddDouble(&EC, 0.0);
860 QCBOREncode_AddDouble(&EC, 3.14);
861 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
862 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
863 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
864
865 QCBOREncode_AddFloat(&EC, 0.0);
866 QCBOREncode_AddFloat(&EC, 3.14f);
867 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
868 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
869 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
870
871 QCBOREncode_OpenMap(&EC);
872
873 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
874 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
875 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
876 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
877
878 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
879 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
880 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
881 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
882
883 QCBOREncode_CloseMap(&EC);
884 QCBOREncode_CloseArray(&EC);
885
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700886 uErr = QCBOREncode_Finish(&EC, &Encoded);
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700887 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700888 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700889 }
890
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700891 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700892 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700893 }
894
895 return 0;
896}
897
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200898#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700899
900
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700901/* Public function. See float_tests.h */
902int32_t
903GeneralFloatDecodeTests(void)
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700904{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700905 /* See FloatNumberTests() for tests that really cover lots of float values */
906
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700907 QCBORItem Item;
908 QCBORError uErr;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700909 QCBORDecodeContext DC;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700910
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700911 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
912 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700913
914 QCBORDecode_GetNext(&DC, &Item);
915 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700916 return MakeTestResultCode(0, 1, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700917 }
918
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700919 /* 0.0 half-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700920 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200921 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
922#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
923 || Item.uDataType != QCBOR_TYPE_DOUBLE
924 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700925#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
926 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200927#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
928 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700929 return MakeTestResultCode(0, 2, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700930 }
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700931
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700932 /* 3.14 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700933 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200934 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
935#ifndef USEFULBUF_DISABLE_ALL_FLOAT
936 || Item.uDataType != QCBOR_TYPE_DOUBLE
937 || Item.val.dfnum != 3.14
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700938#else /* USEFULBUF_DISABLE_ALL_FLOAT */
939 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200940#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
941 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700942 return MakeTestResultCode(0, 3, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700943 }
944
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700945 /* 0.0 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700946 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200947 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
948#ifndef USEFULBUF_DISABLE_ALL_FLOAT
949 || Item.uDataType != QCBOR_TYPE_DOUBLE
950 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700951#else /* USEFULBUF_DISABLE_ALL_FLOAT */
952 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200953#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
954 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700955 return MakeTestResultCode(0, 4, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700956 }
957
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700958 /* NaN double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700959 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200960 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
961#ifndef USEFULBUF_DISABLE_ALL_FLOAT
962 || Item.uDataType != QCBOR_TYPE_DOUBLE
963 || !isnan(Item.val.dfnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700964#else /* USEFULBUF_DISABLE_ALL_FLOAT */
965 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200966#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
967 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700968 return MakeTestResultCode(0, 5, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700969 }
970
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700971 /* Infinity double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700972 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200973 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
974#ifndef USEFULBUF_DISABLE_ALL_FLOAT
975 || Item.uDataType != QCBOR_TYPE_DOUBLE
976 || Item.val.dfnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700977#else /* USEFULBUF_DISABLE_ALL_FLOAT */
978 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200979#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
980 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700981 return MakeTestResultCode(0, 6, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700982 }
983
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700984 /* 0.0 half-precision (again) */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700985 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200986 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
987#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
988 || Item.uDataType != QCBOR_TYPE_DOUBLE
989 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700990#else /* USEFULBUF_DISABLE_ALL_FLOAT */
991 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200992#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
993 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700994 return MakeTestResultCode(0, 7, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700995 }
996
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700997 /* 3.140000104904175 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700998 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200999 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1000#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001001#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001002 || Item.uDataType != QCBOR_TYPE_DOUBLE
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001003 || 3.1400001049041748 != Item.val.dfnum
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001004#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001005 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001006 || 3.140000f != Item.val.fnum
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001007#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1008#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1009 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001010#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1011 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001012 return MakeTestResultCode(0, 8, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001013 }
1014
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001015 /* 0.0 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001016 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001017 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1018#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001019#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1020 || Item.uDataType != QCBOR_TYPE_DOUBLE
1021 || Item.val.dfnum != 0.0
1022#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001023 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001024 || Item.val.fnum != 0.0f
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001025#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1026#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1027 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001028#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1029 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001030 return MakeTestResultCode(0, 9, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001031 }
1032
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001033 /* NaN single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001034 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001035 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1036#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001037#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1038 || Item.uDataType != QCBOR_TYPE_DOUBLE
1039 || !isnan(Item.val.dfnum)
1040#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001041 || Item.uDataType != QCBOR_TYPE_FLOAT
1042 || !isnan(Item.val.fnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001043#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1044#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1045 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001046#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1047 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001048 return MakeTestResultCode(0, 10, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001049 }
1050
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001051 /* Infinity single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001052 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001053 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1054#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001055#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1056 || Item.uDataType != QCBOR_TYPE_DOUBLE
1057 || Item.val.dfnum != INFINITY
1058#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001059 || Item.uDataType != QCBOR_TYPE_FLOAT
1060 || Item.val.fnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001061#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1062#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1063 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001064#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1065 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001066 return MakeTestResultCode(0, 11, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001067 }
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001068 /* Sufficent test coverage. Don't need to decode the rest. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001069
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001070
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001071#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001072 /* Now tests for spiffy decode main function */
1073 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001074 double d;
1075 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07001076 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001077
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001078 /* 0.0 half-precision */
1079 QCBORDecode_GetDouble(&DC, &d);
1080 uErr = QCBORDecode_GetAndResetError(&DC);
1081 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001082#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001083 || d != 0.0
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001084#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001085 ) {
1086 return MakeTestResultCode(1, 1, uErr);
1087 }
1088
1089 /* 3.14 double-precision */
1090 QCBORDecode_GetDouble(&DC, &d);
1091 uErr = QCBORDecode_GetAndResetError(&DC);
1092 if(uErr != QCBOR_SUCCESS || d != 3.14) {
1093 return MakeTestResultCode(1, 2, uErr);
1094 }
1095
1096 /* 0.0 double-precision */
1097 QCBORDecode_GetDouble(&DC, &d);
1098 uErr = QCBORDecode_GetAndResetError(&DC);
1099 if(uErr != QCBOR_SUCCESS || d != 0.0) {
1100 return MakeTestResultCode(1, 3, uErr);
1101 }
1102
1103 /* NaN double-precision */
1104 QCBORDecode_GetDouble(&DC, &d);
1105 uErr = QCBORDecode_GetAndResetError(&DC);
1106 if(uErr != QCBOR_SUCCESS || !isnan(d)) {
1107 return MakeTestResultCode(1, 4, uErr);
1108 }
1109
1110 /* Infinity double-precision */
1111 QCBORDecode_GetDouble(&DC, &d);
1112 uErr = QCBORDecode_GetAndResetError(&DC);
1113 if(uErr != QCBOR_SUCCESS || d != INFINITY) {
1114 return MakeTestResultCode(1, 5, uErr);
1115 }
1116
1117 /* 0.0 half-precision */
1118 QCBORDecode_GetDouble(&DC, &d);
1119 uErr = QCBORDecode_GetAndResetError(&DC);
1120 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
1121#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
1122 || d != 0.0
1123#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
1124 ) {
1125 return MakeTestResultCode(1, 6, uErr);
1126 }
1127
1128 /* 3.140000104904175 single-precision */
1129 QCBORDecode_GetDouble(&DC, &d);
1130 uErr = QCBORDecode_GetAndResetError(&DC);
1131 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1132#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1133 || d != 3.140000104904175
1134#endif
1135 ) {
1136 return MakeTestResultCode(1, 7, uErr);
1137 }
1138
1139 /* 0.0 single-precision */
1140 QCBORDecode_GetDouble(&DC, &d);
1141 uErr = QCBORDecode_GetAndResetError(&DC);
1142 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1143#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1144 || d != 0.0
1145#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1146 ) {
1147 return MakeTestResultCode(1, 8, uErr);
1148 }
1149
1150 /* NaN single-precision */
1151 QCBORDecode_GetDouble(&DC, &d);
1152 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1153#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1154 || !isnan(d)
1155#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1156 ) {
1157 return MakeTestResultCode(1, 9, uErr);
1158 }
1159
1160 /* Infinity single-precision */
1161 QCBORDecode_GetDouble(&DC, &d);
1162 uErr = QCBORDecode_GetAndResetError(&DC);
1163 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1164#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1165 || d != INFINITY
1166#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1167 ) {
1168 return MakeTestResultCode(1, 10, uErr);
1169 }
1170
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001171#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001172
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001173 return 0;
1174}
1175
1176
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001177
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001178#ifdef NAN_EXPERIMENT
1179/*
1180 Code for checking what the double to float cast does with
1181 NaNs. Not run as part of tests. Keep it around to
1182 be able to check various platforms and CPUs.
1183 */
1184
1185#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1186#define DOUBLE_NUM_EXPONENT_BITS (11)
1187#define DOUBLE_NUM_SIGN_BITS (1)
1188
1189#define DOUBLE_SIGNIFICAND_SHIFT (0)
1190#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1191#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1192
1193#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1194#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1195#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1196#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1197
1198
1199static int NaNExperiments() {
1200 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1201 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1202 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001204 float f1 = (float)dqNaN;
1205 float f2 = (float)dsNaN;
1206 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001207
1208
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001209 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1210 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1211 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001212
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001213 // Result of this on x86 is that every NaN is a qNaN. The intel
1214 // CVTSD2SS instruction ignores the NaN payload and even converts
1215 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001216
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001217 return 0;
1218}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001219#endif /* NAN_EXPERIMENT */