blob: 754eb4fb6e9c2bad0531a9ff9016b50fe9ace2c2 [file] [log] [blame]
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001/* ==========================================================================
2 * float_tests.c -- tests for float and conversion to/from half-precision
3 *
4 * Copyright (c) 2018-2024, Laurence Lundblade. All rights reserved.
5 * Copyright (c) 2021, Arm Limited. All rights reserved.
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * See BSD-3-Clause license in README.md
10 *
11 * Created on 9/19/18
12 * ========================================================================= */
Laurence Lundblade68a13352018-09-23 02:19:54 -070013
Laurence Lundblade2aa0b572020-07-16 19:48:42 -070014
15#include "float_tests.h"
Laurence Lundblade585127a2020-07-15 03:25:24 -070016#include "qcbor/qcbor_encode.h"
Laurence Lundblade02fcf312020-07-17 02:49:46 -070017#include "qcbor/qcbor_decode.h"
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -070018#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070019#include <math.h> /* For INFINITY and NAN and isnan() */
Laurence Lundblade585127a2020-07-15 03:25:24 -070020
Laurence Lundblade16a207a2021-09-18 17:22:46 -070021
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070022
23/* Make a test results code that includes three components. Return code
24 * is xxxyyyzzz where zz is the error code, yy is the test number and
25 * zz is check being performed
Laurence Lundblade16a207a2021-09-18 17:22:46 -070026 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070027static inline int32_t
28MakeTestResultCode(uint32_t uTestCase,
29 uint32_t uTestNumber,
30 QCBORError uErrorCode)
Laurence Lundblade16a207a2021-09-18 17:22:46 -070031{
32 uint32_t uCode = (uTestCase * 1000000) +
33 (uTestNumber * 1000) +
34 (uint32_t)uErrorCode;
35 return (int32_t)uCode;
36}
37
38
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -070039#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade9682a532020-06-06 18:33:04 -070040
Laurence Lundbladed711fb22018-09-26 14:35:22 -070041#include "half_to_double_from_rfc7049.h"
Laurence Lundblade68a13352018-09-23 02:19:54 -070042
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080043
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -070044struct FloatTestCase {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070045 double dNumber;
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -070046 float fNumber;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070047 UsefulBufC Preferred;
48 UsefulBufC NotPreferred;
49 UsefulBufC CDE;
50 UsefulBufC DCBOR;
51};
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -070052
Laurence Lundbladee026f4f2024-01-18 13:48:34 -070053/* Boundaries for destination conversions:
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070054 *
55 * smallest subnormal single 1.401298464324817e-45 2^^-149
56 * largest subnormal single 1.1754942106924411e-38 2^^-126
57 * smallest normal single 1.1754943508222875e-38
58 * largest single 3.4028234663852886E+38
59 *
60 * smallest subnormal half 5.9604644775390625E-8
61 * largest subnormal half 6.097555160522461E-5
62 * smallest normal half 6.103515625E-5
63 * largest half 65504.0
64 *
Laurence Lundbladee026f4f2024-01-18 13:48:34 -070065 * Boundaries for origin conversions:
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070066 * smallest subnormal double 5.0e-324 2^^-1074
67 * largest subnormal double
68 * smallest normal double 2.2250738585072014e-308 2^^-1022
69 * largest normal double 1.7976931348623157e308 2^^-1023
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -070070 *
Laurence Lundbladee026f4f2024-01-18 13:48:34 -070071 * Boundaries for double conversion to 64-bit integer:
72 * exponent 51, 52 significand bits set 4503599627370495
73 * exponent 52, 52 significand bits set 9007199254740991
74 * exponent 53, 52 bits set in significand 18014398509481982
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070075 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070076
77/* Always four lines per test case so shell scripts can process into
Laurence Lundbladee026f4f2024-01-18 13:48:34 -070078 * other formats. CDE and DCBOR standards are not complete yet,
79 * encodings are what is expected. C string literals are used because they
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070080 * are the shortest notation. They are used __with a length__ . Null
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -070081 * termination doesn't work because there are zero bytes.
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070082 */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -070083static const struct FloatTestCase FloatTestCases[] = {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070084 /* Zero */
85 {0.0, 0.0f,
86 {"\xF9\x00\x00", 3}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -070087 {"\xF9\x00\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070088
89 /* Negative Zero */
90 {-0.0, -0.0f,
91 {"\xF9\x80\x00", 3}, {"\xFB\x80\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -070092 {"\xF9\x80\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070093
94 /* NaN */
95 {NAN, NAN,
96 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
97 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
98
99 /* Infinity */
100 {INFINITY, INFINITY,
101 {"\xF9\x7C\x00", 3}, {"\xFB\x7F\xF0\x00\x00\x00\x00\x00\x00", 9},
102 {"\xF9\x7C\x00", 3}, {"\xF9\x7C\x00", 3}},
103
104 /* Negative Infinity */
105 {-INFINITY, -INFINITY,
106 {"\xF9\xFC\x00", 3}, {"\xFB\xFF\xF0\x00\x00\x00\x00\x00\x00", 9},
107 {"\xF9\xFC\x00", 3}, {"\xF9\xFC\x00", 3}},
108
109 /* 1.0 */
110 {1.0, 1.0f,
111 {"\xF9\x3C\x00", 3}, {"\xFB\x3F\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700112 {"\xF9\x3C\x00", 3}, {"\x01", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700113
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700114 /* -2.0 -- a negative */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700115 {-2.0, -2.0f,
116 {"\xF9\xC0\x00", 3}, {"\xFB\xC0\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700117 {"\xF9\xC0\x00", 3}, {"\x21", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700118
119 /* 1/3 */
120 {0.333251953125, 0.333251953125f,
121 {"\xF9\x35\x55", 3}, {"\xFB\x3F\xD5\x54\x00\x00\x00\x00\x00", 9},
122 {"\xF9\x35\x55", 3}, {"\xF9\x35\x55", 3}},
123
124 /* 5.9604644775390625E-8 -- smallest half-precision subnormal */
125 {5.9604644775390625E-8, 0.0f,
126 {"\xF9\x00\x01", 3}, {"\xFB\x3E\x70\x00\x00\x00\x00\x00\x00", 9},
127 {"\xF9\x00\x01", 3}, {"\xF9\x00\x01", 3}},
128
129 /* 3.0517578125E-5 -- a half-precision subnormal */
130 {3.0517578125E-5, 0.0f,
131 {"\xF9\x02\x00", 3}, {"\xFB\x3F\x00\x00\x00\x00\x00\x00\x00", 9},
132 {"\xF9\x02\x00", 3}, {"\xF9\x02\x00", 3}},
133
134 /* 6.097555160522461E-5 -- largest half-precision subnormal */
135 {6.097555160522461E-5, 0.0f,
136 {"\xF9\x03\xFF", 3}, {"\xFB\x3F\x0F\xF8\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700137 {"\xF9\x03\xFF", 3}, {"\xF9\x03\xFF", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700138
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700139 /* 6.1035156249999993E-5 -- slightly smaller than smallest half-precision normal */
140 {6.1035156249999993E-5, 0.0f,
141 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
142 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
143
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700144 /* 6.103515625E-5 -- smallest half-precision normal */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700145 {6.103515625E-5, 0.0f,
146 {"\xF9\04\00", 3}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x00", 9},
147 {"\xF9\04\00", 3}, {"\xF9\04\00", 3}},
148
149 /* 6.1035156250000014E-5 -- slightly larger than smallest half-precision normal */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700150 {6.1035156250000014E-5, 0.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700151 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9},
152 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}},
153
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700154 /* 65504.0 -- largest half-precision */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700155 {65504.0, 0.0f,
156 {"\xF9\x7B\xFF", 3}, {"\xFB\x40\xEF\xFC\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700157 {"\xF9\x7B\xFF", 3}, {"\x19\xFF\xE0", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700158
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700159 /* 65504.1 -- exponent too large and too much precision to convert to half */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700160 {65504.1, 0.0f,
161 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9},
162 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}},
163
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700164 /* 65536.0 -- exponent too large for half but not too much precision for single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700165 {65536.0, 65536.0f,
166 {"\xFA\x47\x80\x00\x00", 5}, {"\xFB\x40\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700167 {"\xFA\x47\x80\x00\x00", 5}, {"\x1A\x00\x01\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700168
169 /* 1.401298464324817e-45 -- smallest single subnormal */
170 {1.401298464324817e-45, 1.40129846E-45f,
171 {"\xFA\x00\x00\x00\x01", 5}, {"\xFB\x36\xA0\x00\x00\x00\x00\x00\x00", 9},
172 {"\xFA\x00\x00\x00\x01", 5}, {"\xFA\x00\x00\x00\x01", 5}},
173
Laurence Lundblade240ca822024-01-16 11:11:00 -0700174 /* 5.8774717541114375E-39 -- slightly smaller than the smallest single normal */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700175 {5.8774717541114375E-39, 5.87747175E-39f,
176 {"\xFA\x00\x40\x00\x00", 5}, {"\xFB\x38\x00\x00\x00\x00\x00\x00\x00", 9},
177 {"\xFA\x00\x40\x00\x00", 5}, {"\xFA\x00\x40\x00\x00", 5}},
178
179 /* 1.1754942106924411e-38 -- largest single subnormal */
180 {1.1754942106924411E-38, 1.17549421E-38f,
181 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFB\x38\x0f\xff\xff\xC0\x00\x00\x00", 9},
182 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFA\x00\x7f\xff\xff", 5} },
183
184 /* 1.1754943508222874E-38 -- slightly bigger than smallest single normal */
185 {1.1754943508222874E-38, 0.0f,
186 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9},
187 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}},
188
189 /* 1.1754943508222875e-38 -- smallest single normal */
190 {1.1754943508222875e-38, 1.17549435E-38f,
191 {"\xFA\x00\x80\x00\x00", 5}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x00", 9},
192 {"\xFA\x00\x80\x00\x00", 5}, {"\xFA\x00\x80\x00\x00", 5}},
193
194 /* 1.1754943508222875e-38 -- slightly bigger than smallest single normal */
195 {1.1754943508222878e-38, 0.0f,
196 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9},
197 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}},
198
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700199 /* 8388607 -- exponent 22 to test single exponent boundary */
200 {8388607, 8388607.0f,
201 {"\xFA\x4A\xFF\xFF\xFE", 5}, {"\xFB\x41\x5F\xFF\xFF\xC0\x00\x00\x00", 9},
202 {"\xFA\x4A\xFF\xFF\xFE", 5}, {"\x1A\x00\x7F\xFF\xFF", 5}},
203
204 /* 16777215 -- exponent 23 to test single exponent boundary */
205 {16777215, 16777215.0f,
206 {"\xFA\x4B\x7F\xFF\xFF", 5}, {"\xFB\x41\x6F\xFF\xFF\xE0\x00\x00\x00", 9},
207 {"\xFA\x4B\x7F\xFF\xFF", 5}, {"\x1A\x00\xFF\xFF\xFF", 5}},
208
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700209 /* 16777216 -- converts to single without loss */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700210 {16777216, 16777216.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700211 {"\xFA\x4B\x80\x00\x00", 5}, {"\xFB\x41\x70\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700212 {"\xFA\x4B\x80\x00\x00", 5}, {"\x1A\x01\x00\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700213
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700214 /* 16777217 -- one more than above and fails conversion to single because of precision */
215 {16777217, 0.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700216 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700217 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\x1A\x01\x00\x00\x01", 5}},
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700218
219 /* 33554430 -- exponent 24 to test single exponent boundary */
220 {33554430, 33554430.0f,
221 {"\xFA\x4B\xFF\xFF\xFF", 5}, {"\xFB\x41\x7F\xFF\xFF\xE0\x00\x00\x00", 9},
222 {"\xFA\x4B\xFF\xFF\xFF", 5}, {"\x1A\x01\xFF\xFF\xFE", 5}},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700223
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700224 /* 4294967295 -- 2^^32 - 1 UINT32_MAX */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700225 {4294967295, 0,
226 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700227 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x1A\xFF\xFF\xFF\xFF", 5}},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700228
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700229 /* 4294967296 -- 2^^32, UINT32_MAX + 1 */
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700230 {4294967296, 4294967296.0f,
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700231 {"\xFA\x4F\x80\x00\x00", 5}, {"\xFB\x41\xF0\x00\x00\x00\x00\x00\x00", 9},
232 {"\xFA\x4F\x80\x00\x00", 5}, {"\x1B\x00\x00\x00\x01\x00\x00\x00\x00", 9}},
233
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700234 /* 2251799813685248 -- exponent 51, 0 significand bits set, to test double exponent boundary */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700235 {2251799813685248, 0,
236 {"\xFA\x59\x00\x00\x00", 5}, {"\xFB\x43\x20\x00\x00\x00\x00\x00\x00", 9},
237 {"\xFA\x59\x00\x00\x00", 5}, {"\x1B\x00\x08\x00\x00\x00\x00\x00\x00", 9}},
238
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700239 /* 4503599627370495 -- exponent 51, 52 significand bits set to test double exponent boundary*/
Laurence Lundblade240ca822024-01-16 11:11:00 -0700240 {4503599627370495, 0,
241 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9},
242 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\x1B\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
243
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700244 /* 9007199254740991 -- exponent 52, 52 significand bits set to test double exponent boundary */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700245 {9007199254740991, 0,
246 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
247 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x1F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
248
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700249 /* 18014398509481982 -- exponent 53, 52 bits set in significand (double lacks precision to represent 18014398509481983) */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700250 {18014398509481982, 0,
251 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
252 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x3F\xFF\xFF\xFF\xFF\xFF\xFE", 9}},
253
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700254 /* 18014398509481984 -- next largest possible double above 18014398509481982 */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700255 {18014398509481984, 0,
256 {"\xFA\x5A\x80\x00\x00", 5}, {"\xFB\x43\x50\x00\x00\x00\x00\x00\x00", 9},
257 {"\xFA\x5A\x80\x00\x00", 5}, {"\x1B\x00\x40\x00\x00\x00\x00\x00\x00", 9}},
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700258
259 /* 18446742974197924000.0.0 -- largest single that can convert to uint64 */
260 {18446742974197924000.0, 18446742974197924000.0f,
261 {"\xFA\x5F\x7F\xFF\xFF", 5}, {"\xFB\x43\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
262 {"\xFA\x5F\x7F\xFF\xFF", 5}, {"\x1B\xFF\xFF\xFF\x00\x00\x00\x00\x00", 9}},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700263
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700264 /* 18446744073709550000.0 -- largest double that can convert to uint64, almost UINT64_MAX (18446744073709551615) */
265 {18446744073709550000.0, 0,
266 {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
267 {"\xFB\x43\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\xFF\xFF\xFF\xFF\xFF\xFF\xF8\x00", 9}},
268
269 /* 18446744073709552000.0 -- just too large to convert to uint64, but converts to a single, just over UINT64_MAX */
270 {18446744073709552000.0, 18446744073709552000.0f,
271 {"\xFA\x5F\x80\x00\x00", 5}, {"\xFB\x43\xF0\x00\x00\x00\x00\x00\x00", 9},
272 {"\xFA\x5F\x80\x00\x00", 5}, {"\xFA\x5F\x80\x00\x00", 5}},
273
274 /* -4294967295 -- negative UINT32_MAX */
275 {-4294967295.0, 0,
Laurence Lundblade240ca822024-01-16 11:11:00 -0700276 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
277 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x3A\xFF\xFF\xFF\xFE", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700278
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700279 /* -9223372036854774784.0 -- most negative double that converts to int64 */
280 {-9223372036854774784.0, 0,
281 {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
282 {"\xFB\xC3\xDF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x3B\x7F\xFF\xFF\xFF\xFF\xFF\xFB\xFF", 9}},
283
284 /* -18446742974197924000.0.0 -- large negative that converts to float, but too large for int64 */
285 {-18446742974197924000.0, -18446742974197924000.0f,
286 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\xFB\xC3\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
287 {"\xFA\xDF\x7F\xFF\xFF", 5}, {"\xFA\xDF\x7F\xFF\xFF", 5}},
288
289 /* 3.4028234663852886E+38 -- largest possible single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700290 {3.4028234663852886E+38, 3.40282347E+38f,
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700291 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
292 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFA\x7F\x7F\xFF\xFF", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700293
294 /* 3.402823466385289E+38 -- slightly larger than largest possible single */
295 {3.402823466385289E+38, 0.0f,
296 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9},
297 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}},
298
299 /* 3.402823669209385e+38 -- exponent larger by one than largest possible single */
300 {3.402823669209385e+38, 0.0f,
301 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9},
302 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}},
303
304 /* 5.0e-324 -- smallest double subnormal normal */
305 {5.0e-324, 0.0f,
306 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9},
307 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}},
308
309 /* 2.2250738585072009E−308 -- largest double subnormal */
310 {2.2250738585072009e-308, 0.0f,
311 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
312 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
313
314 /* 2.2250738585072014e-308 -- smallest double normal */
315 {2.2250738585072014e-308, 0.0f,
316 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9},
317 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}},
318
319 /* 1.7976931348623157E308 -- largest double normal */
320 {1.7976931348623157e308, 0.0f,
321 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
322 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
323
324 /* List terminator */
325 {0.0, 0.0f, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700326};
327
328
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700329/* Can't use types double and float here because there's no way in C to
330 * construct arbitrary payloads for those types.
331 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700332struct NaNTestCase {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700333 uint64_t uDouble; /* Converted to double in test */
334 uint32_t uSingle; /* Converted to single in test */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700335 UsefulBufC Preferred;
336 UsefulBufC NotPreferred;
337 UsefulBufC CDE;
338 UsefulBufC DCBOR;
339};
340
341/* Always four lines per test case so shell scripts can process into
342 * other formats. CDE and DCBOR standards are not complete yet,
343 * encodings are a guess. C string literals are used because they
344 * are the shortest notation. They are used __with a length__ . Null
345 * termination doesn't work because there are zero bytes.
346 */
347static const struct NaNTestCase NaNTestCases[] = {
348
349 /* Payload with most significant bit set, a qNaN by most implementations */
350 {0x7ff8000000000000, 0x00000000,
351 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
352 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
353
354 /* Payload with single rightmost set */
355 {0x7ff8000000000001, 0x00000000,
356 {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9},
357 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
358
359 /* Payload with 10 leftmost bits set -- converts to half */
360 {0x7ffffc0000000000, 0x00000000,
361 {"\xF9\x7F\xFF", 3}, {"\xFB\x7F\xFF\xFC\x00\x00\x00\x00\x00", 9},
362 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
363
364 /* Payload with 10 rightmost bits set -- cannot convert to half */
365 {0x7ff80000000003ff, 0x00000000,
366 {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9},
367 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
368
369 /* Payload with 23 leftmost bits set -- converts to a single */
370 {0x7ffFFFFFE0000000, 0x7fffffff,
371 {"\xFA\x7F\xFF\xFF\xFF", 5}, {"\xFB\x7F\xFF\xFF\xFF\xE0\x00\x00\x00", 9},
372 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
373
374 /* Payload with 24 leftmost bits set -- fails to convert to a single */
375 {0x7ffFFFFFF0000000, 0x00000000,
376 {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9}, {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9},
377 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
378
379 /* Payload with all bits set */
380 {0x7fffffffffffffff, 0x00000000,
381 {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700382 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700383
384 /* List terminator */
385 {0, 0, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
386};
387
388
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700389/* Public function. See float_tests.h
390 *
391 * This is the main test of floating-point encoding / decoding. It is
392 * data-driven by the above tables. It works better than tests below that
393 * it mostly replaces because it tests one number at a time, rather than
394 * putting them all in a map. It is much easier to debug test failures
395 * and to add new tests. */
396int32_t
397FloatValuesTests(void)
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700398{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700399 unsigned int uTestIndex;
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700400 const struct FloatTestCase *pTestCase;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700401 const struct NaNTestCase *pNaNTestCase;
402 MakeUsefulBufOnStack( TestOutBuffer, 20);
403 UsefulBufC TestOutput;
404 QCBOREncodeContext EnCtx;
405 QCBORError uErr;
406 QCBORDecodeContext DCtx;
407 QCBORItem Item;
408 uint64_t uDecoded;
409#ifdef QCBOR_DISABLE_FLOAT_HW_USE
410 uint32_t uDecoded2;
411#endif
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700412
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700413 /* Test a variety of doubles */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700414 for(uTestIndex = 0; FloatTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
415 pTestCase = &FloatTestCases[uTestIndex];
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700416
Laurence Lundbladee026f4f2024-01-18 13:48:34 -0700417
418 // 9223372036854774784
419 if(pTestCase->dNumber == 1.7976931348623157e308 ||
420 uTestIndex == 77) {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700421 uErr = 99; /* For setting break points for particular tests */
422 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800423
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700424 /* Number Encode of Preferred */
425 QCBOREncode_Init(&EnCtx, TestOutBuffer);
426 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
427 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800428
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700429 if(uErr != QCBOR_SUCCESS) {
430 return MakeTestResultCode(uTestIndex, 1, uErr);;
431 }
432 if(UsefulBuf_Compare(TestOutput, pTestCase->Preferred)) {
433 return MakeTestResultCode(uTestIndex, 1, 200);
434 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700435
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700436 /* Number Encode of Not Preferred */
437 QCBOREncode_Init(&EnCtx, TestOutBuffer);
438 QCBOREncode_AddDoubleNoPreferred(&EnCtx, pTestCase->dNumber);
439 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade68a13352018-09-23 02:19:54 -0700440
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700441 if(uErr != QCBOR_SUCCESS) {
442 return MakeTestResultCode(uTestIndex, 2, uErr);;
443 }
444 if(UsefulBuf_Compare(TestOutput, pTestCase->NotPreferred)) {
445 return MakeTestResultCode(uTestIndex, 2, 200);
446 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800447
Laurence Lundblade240ca822024-01-16 11:11:00 -0700448 /* Number Encode of CDE */
449 QCBOREncode_Init(&EnCtx, TestOutBuffer);
450 QCBOREncode_SerializationCDE(&EnCtx);
451 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
452 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
453
454 if(uErr != QCBOR_SUCCESS) {
455 return MakeTestResultCode(uTestIndex, 20, uErr);;
456 }
457 if(UsefulBuf_Compare(TestOutput, pTestCase->CDE)) {
458 return MakeTestResultCode(uTestIndex, 21, 200);
459 }
460
461 /* Number Encode of dCBOR */
462 QCBOREncode_Init(&EnCtx, TestOutBuffer);
463 QCBOREncode_SerializationdCBOR(&EnCtx);
464 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
465 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
466
467 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700468 return MakeTestResultCode(uTestIndex, 22, uErr);;
Laurence Lundblade240ca822024-01-16 11:11:00 -0700469 }
470 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700471 return MakeTestResultCode(uTestIndex, 23, 200);
472 }
473
474 if(pTestCase->fNumber != 0) {
475 QCBOREncode_Init(&EnCtx, TestOutBuffer);
476 QCBOREncode_SerializationdCBOR(&EnCtx);
477 QCBOREncode_AddFloat(&EnCtx, pTestCase->fNumber);
478 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
479
480 if(uErr != QCBOR_SUCCESS) {
481 return MakeTestResultCode(uTestIndex, 24, uErr);;
482 }
483 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
484 return MakeTestResultCode(uTestIndex, 25, 200);
485 }
Laurence Lundblade240ca822024-01-16 11:11:00 -0700486 }
487
488
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700489 /* Number Decode of Preferred */
490 QCBORDecode_Init(&DCtx, pTestCase->Preferred, 0);
491 uErr = QCBORDecode_GetNext(&DCtx, &Item);
492 if(uErr != QCBOR_SUCCESS) {
493 return MakeTestResultCode(uTestIndex, 3, uErr);;
494 }
495#ifndef QCBOR_DISABLE_FLOAT_HW_USE
496 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
497 return MakeTestResultCode(uTestIndex, 4, 0);
498 }
499 if(isnan(pTestCase->dNumber)) {
500 if(!isnan(Item.val.dfnum)) {
501 return MakeTestResultCode(uTestIndex, 5, 0);
502 }
503 } else {
504 if(Item.val.dfnum != pTestCase->dNumber) {
505 return MakeTestResultCode(uTestIndex, 6, 0);
506 }
507 }
508#else /* QCBOR_DISABLE_FLOAT_HW_USE */
509 /* When QCBOR_DISABLE_FLOAT_HW_USE is set, single-precision is not
510 * converted to double when decoding, so test differently. len == 5
511 * indicates single-precision in the encoded CBOR. */
512 if(pTestCase->Preferred.len == 5) {
513 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700514 return MakeTestResultCode(uTestIndex, 41, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700515 }
516 if(isnan(pTestCase->dNumber)) {
517 if(!isnan(Item.val.fnum)) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700518 return MakeTestResultCode(uTestIndex, 51, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700519 }
520 } else {
521 if(Item.val.fnum != pTestCase->fNumber) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700522 return MakeTestResultCode(uTestIndex, 61, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700523 }
524 }
525 } else {
526 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700527 return MakeTestResultCode(uTestIndex, 42, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700528 }
529 if(isnan(pTestCase->dNumber)) {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700530 if(!isnan(Item.val.dfnum)) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700531 return MakeTestResultCode(uTestIndex, 52, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700532 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700533 } else {
534 if(Item.val.dfnum != pTestCase->dNumber) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700535 return MakeTestResultCode(uTestIndex, 62, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700536 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700537 }
538 }
539#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700540
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700541 /* Number Decode of Not Preferred */
542 QCBORDecode_Init(&DCtx, pTestCase->NotPreferred, 0);
543 uErr = QCBORDecode_GetNext(&DCtx, &Item);
544 if(uErr != QCBOR_SUCCESS) {
545 return MakeTestResultCode(uTestIndex, 7, uErr);;
546 }
547 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
548 return MakeTestResultCode(uTestIndex, 8, 0);
549 }
550 if(isnan(pTestCase->dNumber)) {
551 if(!isnan(Item.val.dfnum)) {
552 return MakeTestResultCode(uTestIndex, 9, 0);
553 }
554 } else {
555 if(Item.val.dfnum != pTestCase->dNumber) {
556 return MakeTestResultCode(uTestIndex, 10, 0);
557 }
558 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700559
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700560 }
561
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700562 /* Test a variety of NaNs with payloads */
563 for(uTestIndex = 0; NaNTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
564 pNaNTestCase = &NaNTestCases[uTestIndex];
565
566
567 if(uTestIndex == 4) {
568 uErr = 99; /* For setting break points for particular tests */
569 }
570
571 /* NaN Encode of Preferred */
572 QCBOREncode_Init(&EnCtx, TestOutBuffer);
573 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);
621 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 Lundblade240ca822024-01-16 11:11:00 -0700630 /* NaN Decode of Not Preferred */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700631 QCBORDecode_Init(&DCtx, pNaNTestCase->Preferred, 0);
632 uErr = QCBORDecode_GetNext(&DCtx, &Item);
633 if(uErr != QCBOR_SUCCESS) {
634 return MakeTestResultCode(uTestIndex+100, 12, uErr);
635 }
636
637#ifndef QCBOR_DISABLE_FLOAT_HW_USE
638
639 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
640 if(uDecoded != pNaNTestCase->uDouble) {
641 return MakeTestResultCode(uTestIndex+100, 12, 200);
642 }
643#else /* QCBOR_DISABLE_FLOAT_HW_USE */
644 if(pNaNTestCase->Preferred.len == 5) {
645 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
646 return MakeTestResultCode(uTestIndex, 4, 0);
647 }
648
649 uDecoded2 = UsefulBufUtil_CopyFloatToUint32(Item.val.fnum);
650
651 if(uDecoded2 != pNaNTestCase->uSingle) {
652 return MakeTestResultCode(uTestIndex, 4, 0);
653 }
654 } else {
655 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
656 return MakeTestResultCode(uTestIndex, 4, 0);
657 }
658 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
659 if(uDecoded != pNaNTestCase->uDouble) {
660 return MakeTestResultCode(uTestIndex+100, 12, 200);
661 }
662 }
663#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
664
665 /* NaN Decode of Not Preferred */
666 QCBORDecode_Init(&DCtx, pNaNTestCase->NotPreferred, 0);
667 uErr = QCBORDecode_GetNext(&DCtx, &Item);
668 if(uErr != QCBOR_SUCCESS) {
669 return MakeTestResultCode(uTestIndex+100, 13, uErr);
670 }
671 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
672 if(uDecoded != pNaNTestCase->uDouble) {
673 return MakeTestResultCode(uTestIndex+100, 13, 200);
674 }
Laurence Lundblade240ca822024-01-16 11:11:00 -0700675
676
677 /* NaN Encode of DCBOR */
678 QCBOREncode_Init(&EnCtx, TestOutBuffer);
679 QCBOREncode_SerializationdCBOR(&EnCtx);
680 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
681 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
682 if(uErr != QCBOR_SUCCESS) {
683 return MakeTestResultCode(uTestIndex+100, 11, uErr);;
684 }
685 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->DCBOR)) {
686 return MakeTestResultCode(uTestIndex+100, 11, 200);
687 }
688
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700689 }
690
691 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800692}
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700693
694
695
696/* Public function. See float_tests.h */
697int32_t
698HalfPrecisionAgainstRFCCodeTest(void)
699{
700 QCBORItem Item;
701 QCBORDecodeContext DC;
702 unsigned char pbHalfBytes[2];
703 uint8_t uHalfPrecInitialByte;
704 double d;
705 UsefulBuf_MAKE_STACK_UB(EncodedBytes, 3);
706 UsefulOutBuf UOB;
707 uint32_t uHalfP;
708
709
710 for(uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
711 pbHalfBytes[1] = (uint8_t)(uHalfP & 0xff);
712 pbHalfBytes[0] = (uint8_t)(uHalfP >> 8); /* uHalfP is always less than 0xffff */
713 d = decode_half(pbHalfBytes);
714
715 /* Construct the CBOR for the half-precision float by hand */
716 UsefulOutBuf_Init(&UOB, EncodedBytes);
717
718 uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); /* 0xf9 */
719 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); /* initial byte */
720 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP); /* argument */
721
722 /* Now parse the hand-constructed CBOR. This will invoke the
723 * conversion to a float
724 */
725 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
726 QCBORDecode_GetNext(&DC, &Item);
727 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
728 return -1;
729 }
730
731 if(isnan(d)) {
732 /* The RFC code uses the native instructions which may or may not
733 * handle sNaN, qNaN and NaN payloads correctly. This test just
734 * makes sure it is a NaN and doesn't worry about the type of NaN
735 */
736 if(!isnan(Item.val.dfnum)) {
737 return -3;
738 }
739 } else {
740 if(Item.val.dfnum != d) {
741 return -2;
742 }
743 }
744 }
745 return 0;
746}
747
Laurence Lundblade585127a2020-07-15 03:25:24 -0700748#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700749
750
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700751/*
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700752 * Some encoded floating point numbers that are used for both
753 * encode and decode tests.
754 *
755 * [0.0, // Half
756 * 3.14, // Double
757 * 0.0, // Double
758 * NaN, // Double
759 * Infinity, // Double
760 * 0.0, // Half (Duplicate because of use in encode tests)
761 * 3.140000104904175, // Single
762 * 0.0, // Single
763 * NaN, // Single
764 * Infinity, // Single
765 * {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
766 * 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700767 */
768static const uint8_t spExpectedFloats[] = {
769 0x8B,
770 0xF9, 0x00, 0x00,
771 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
772 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0xF9, 0x00, 0x00,
776 0xFA, 0x40, 0x48, 0xF5, 0xC3,
777 0xFA, 0x00, 0x00, 0x00, 0x00,
778 0xFA, 0x7F, 0xC0, 0x00, 0x00,
779 0xFA, 0x7F, 0x80, 0x00, 0x00,
780 0xA8,
781 0x18, 0x64,
782 0xF9, 0x00, 0x00,
783 0x18, 0x65,
784 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
785 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
786 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
787 0x18, 0x69,
788 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789 0x18, 0x66,
790 0xF9, 0x00, 0x00,
791 0x18, 0x67,
792 0xFA, 0x40, 0x49, 0x0F, 0xDA,
793 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
794 0xFA, 0x40, 0x2D, 0xF8, 0x54,
795 0x18, 0x6A,
796 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700797
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200798#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700799static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700800 0x8B,
801 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
802 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
803 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
804 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
805 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0xFA, 0x00, 0x00, 0x00, 0x00,
807 0xFA, 0x40, 0x48, 0xF5, 0xC3,
808 0xFA, 0x00, 0x00, 0x00, 0x00,
809 0xFA, 0x7F, 0xC0, 0x00, 0x00,
810 0xFA, 0x7F, 0x80, 0x00, 0x00,
811 0xA8,
812 0x18, 0x64,
813 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x18, 0x65,
815 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
816 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
817 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
818 0x18, 0x69,
819 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820 0x18, 0x66,
821 0xFA, 0x00, 0x00, 0x00, 0x00,
822 0x18, 0x67,
823 0xFA, 0x40, 0x49, 0x0F, 0xDA,
824 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
825 0xFA, 0x40, 0x2D, 0xF8, 0x54,
826 0x18, 0x6A,
827 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700828
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700829
830/* Public function. See float_tests.h */
831int32_t
832GeneralFloatEncodeTests(void)
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700833{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700834 /* See FloatNumberTests() for tests that really cover lots of float values.
835 * Add new tests for new values or decode modes there.
836 * This test is primarily to cover all the float encode methods. */
837
838 UsefulBufC Encoded;
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700839 UsefulBufC ExpectedFloats;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700840 QCBORError uErr;
841
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700842#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700843 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700844 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700845 (void)spExpectedFloatsNoHalf; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700846#else
847 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700848 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700849 (void)spExpectedFloats; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700850#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700851
852 QCBOREncodeContext EC;
853 QCBOREncode_Init(&EC, OutBuffer);
854 QCBOREncode_OpenArray(&EC);
855
856 QCBOREncode_AddDouble(&EC, 0.0);
857 QCBOREncode_AddDouble(&EC, 3.14);
858 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
859 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
860 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
861
862 QCBOREncode_AddFloat(&EC, 0.0);
863 QCBOREncode_AddFloat(&EC, 3.14f);
864 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
865 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
866 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
867
868 QCBOREncode_OpenMap(&EC);
869
870 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
871 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
872 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
873 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
874
875 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
876 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
877 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
878 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
879
880 QCBOREncode_CloseMap(&EC);
881 QCBOREncode_CloseArray(&EC);
882
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700883 uErr = QCBOREncode_Finish(&EC, &Encoded);
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700884 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700885 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700886 }
887
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700888 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700889 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700890 }
891
892 return 0;
893}
894
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200895#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700896
897
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700898/* Public function. See float_tests.h */
899int32_t
900GeneralFloatDecodeTests(void)
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700901{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700902 /* See FloatNumberTests() for tests that really cover lots of float values */
903
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700904 QCBORItem Item;
905 QCBORError uErr;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700906 QCBORDecodeContext DC;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700907
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700908 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
909 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700910
911 QCBORDecode_GetNext(&DC, &Item);
912 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700913 return MakeTestResultCode(0, 1, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700914 }
915
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700916 /* 0.0 half-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700917 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200918 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
919#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
920 || Item.uDataType != QCBOR_TYPE_DOUBLE
921 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700922#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
923 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200924#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
925 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700926 return MakeTestResultCode(0, 2, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700927 }
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700928
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700929 /* 3.14 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700930 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200931 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
932#ifndef USEFULBUF_DISABLE_ALL_FLOAT
933 || Item.uDataType != QCBOR_TYPE_DOUBLE
934 || Item.val.dfnum != 3.14
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700935#else /* USEFULBUF_DISABLE_ALL_FLOAT */
936 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200937#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
938 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700939 return MakeTestResultCode(0, 3, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700940 }
941
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700942 /* 0.0 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700943 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200944 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
945#ifndef USEFULBUF_DISABLE_ALL_FLOAT
946 || Item.uDataType != QCBOR_TYPE_DOUBLE
947 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700948#else /* USEFULBUF_DISABLE_ALL_FLOAT */
949 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200950#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
951 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700952 return MakeTestResultCode(0, 4, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700953 }
954
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700955 /* NaN double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700956 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200957 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
958#ifndef USEFULBUF_DISABLE_ALL_FLOAT
959 || Item.uDataType != QCBOR_TYPE_DOUBLE
960 || !isnan(Item.val.dfnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700961#else /* USEFULBUF_DISABLE_ALL_FLOAT */
962 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200963#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
964 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700965 return MakeTestResultCode(0, 5, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700966 }
967
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700968 /* Infinity double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700969 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200970 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
971#ifndef USEFULBUF_DISABLE_ALL_FLOAT
972 || Item.uDataType != QCBOR_TYPE_DOUBLE
973 || Item.val.dfnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700974#else /* USEFULBUF_DISABLE_ALL_FLOAT */
975 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200976#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
977 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700978 return MakeTestResultCode(0, 6, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700979 }
980
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700981 /* 0.0 half-precision (again) */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700982 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200983 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
984#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
985 || Item.uDataType != QCBOR_TYPE_DOUBLE
986 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700987#else /* USEFULBUF_DISABLE_ALL_FLOAT */
988 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200989#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
990 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700991 return MakeTestResultCode(0, 7, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700992 }
993
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700994 /* 3.140000104904175 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700995 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200996 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
997#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700998#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200999 || Item.uDataType != QCBOR_TYPE_DOUBLE
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001000 || 3.1400001049041748 != Item.val.dfnum
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001001#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001002 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001003 || 3.140000f != Item.val.fnum
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001004#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1005#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1006 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001007#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1008 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001009 return MakeTestResultCode(0, 8, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001010 }
1011
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001012 /* 0.0 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001013 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001014 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1015#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001016#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1017 || Item.uDataType != QCBOR_TYPE_DOUBLE
1018 || Item.val.dfnum != 0.0
1019#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001020 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -07001021 || Item.val.fnum != 0.0f
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001022#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1023#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1024 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001025#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1026 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001027 return MakeTestResultCode(0, 9, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001028 }
1029
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001030 /* NaN single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001031 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001032 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1033#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001034#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1035 || Item.uDataType != QCBOR_TYPE_DOUBLE
1036 || !isnan(Item.val.dfnum)
1037#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001038 || Item.uDataType != QCBOR_TYPE_FLOAT
1039 || !isnan(Item.val.fnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001040#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1041#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1042 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001043#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1044 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001045 return MakeTestResultCode(0, 10, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001046 }
1047
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001048 /* Infinity single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001049 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001050 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1051#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001052#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1053 || Item.uDataType != QCBOR_TYPE_DOUBLE
1054 || Item.val.dfnum != INFINITY
1055#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001056 || Item.uDataType != QCBOR_TYPE_FLOAT
1057 || Item.val.fnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001058#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1059#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1060 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001061#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1062 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001063 return MakeTestResultCode(0, 11, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001064 }
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001065 /* Sufficent test coverage. Don't need to decode the rest. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001066
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001067
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001068#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001069 /* Now tests for spiffy decode main function */
1070 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001071 double d;
1072 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07001073 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001074
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001075 /* 0.0 half-precision */
1076 QCBORDecode_GetDouble(&DC, &d);
1077 uErr = QCBORDecode_GetAndResetError(&DC);
1078 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001079#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001080 || d != 0.0
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001081#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001082 ) {
1083 return MakeTestResultCode(1, 1, uErr);
1084 }
1085
1086 /* 3.14 double-precision */
1087 QCBORDecode_GetDouble(&DC, &d);
1088 uErr = QCBORDecode_GetAndResetError(&DC);
1089 if(uErr != QCBOR_SUCCESS || d != 3.14) {
1090 return MakeTestResultCode(1, 2, uErr);
1091 }
1092
1093 /* 0.0 double-precision */
1094 QCBORDecode_GetDouble(&DC, &d);
1095 uErr = QCBORDecode_GetAndResetError(&DC);
1096 if(uErr != QCBOR_SUCCESS || d != 0.0) {
1097 return MakeTestResultCode(1, 3, uErr);
1098 }
1099
1100 /* NaN double-precision */
1101 QCBORDecode_GetDouble(&DC, &d);
1102 uErr = QCBORDecode_GetAndResetError(&DC);
1103 if(uErr != QCBOR_SUCCESS || !isnan(d)) {
1104 return MakeTestResultCode(1, 4, uErr);
1105 }
1106
1107 /* Infinity double-precision */
1108 QCBORDecode_GetDouble(&DC, &d);
1109 uErr = QCBORDecode_GetAndResetError(&DC);
1110 if(uErr != QCBOR_SUCCESS || d != INFINITY) {
1111 return MakeTestResultCode(1, 5, uErr);
1112 }
1113
1114 /* 0.0 half-precision */
1115 QCBORDecode_GetDouble(&DC, &d);
1116 uErr = QCBORDecode_GetAndResetError(&DC);
1117 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
1118#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
1119 || d != 0.0
1120#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
1121 ) {
1122 return MakeTestResultCode(1, 6, uErr);
1123 }
1124
1125 /* 3.140000104904175 single-precision */
1126 QCBORDecode_GetDouble(&DC, &d);
1127 uErr = QCBORDecode_GetAndResetError(&DC);
1128 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1129#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1130 || d != 3.140000104904175
1131#endif
1132 ) {
1133 return MakeTestResultCode(1, 7, uErr);
1134 }
1135
1136 /* 0.0 single-precision */
1137 QCBORDecode_GetDouble(&DC, &d);
1138 uErr = QCBORDecode_GetAndResetError(&DC);
1139 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1140#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1141 || d != 0.0
1142#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1143 ) {
1144 return MakeTestResultCode(1, 8, uErr);
1145 }
1146
1147 /* NaN single-precision */
1148 QCBORDecode_GetDouble(&DC, &d);
1149 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1150#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1151 || !isnan(d)
1152#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1153 ) {
1154 return MakeTestResultCode(1, 9, uErr);
1155 }
1156
1157 /* Infinity single-precision */
1158 QCBORDecode_GetDouble(&DC, &d);
1159 uErr = QCBORDecode_GetAndResetError(&DC);
1160 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1161#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1162 || d != INFINITY
1163#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1164 ) {
1165 return MakeTestResultCode(1, 10, uErr);
1166 }
1167
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001168#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001169
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001170 return 0;
1171}
1172
1173
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001174
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001175#ifdef NAN_EXPERIMENT
1176/*
1177 Code for checking what the double to float cast does with
1178 NaNs. Not run as part of tests. Keep it around to
1179 be able to check various platforms and CPUs.
1180 */
1181
1182#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1183#define DOUBLE_NUM_EXPONENT_BITS (11)
1184#define DOUBLE_NUM_SIGN_BITS (1)
1185
1186#define DOUBLE_SIGNIFICAND_SHIFT (0)
1187#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1188#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1189
1190#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1191#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1192#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1193#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1194
1195
1196static int NaNExperiments() {
1197 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1198 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1199 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001200
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001201 float f1 = (float)dqNaN;
1202 float f2 = (float)dsNaN;
1203 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001204
1205
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001206 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1207 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1208 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001209
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001210 // Result of this on x86 is that every NaN is a qNaN. The intel
1211 // CVTSD2SS instruction ignores the NaN payload and even converts
1212 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001213
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001214 return 0;
1215}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001216#endif /* NAN_EXPERIMENT */