blob: 914cfbd12140cc37db81883593491e054790d0ea [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 Lundblade83dbf5c2024-01-07 19:17:52 -070053/* Boundaries for all destination conversions to test at.
54 *
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 *
65 * Boundaries for origin conversions
66 * 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 *
71 * Boundaries for conversion to 64-bit integer
Laurence Lundblade6d3f6ec2020-07-18 17:28:26 -070072 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070073
74/* Always four lines per test case so shell scripts can process into
75 * other formats. CDE and DCBOR standards are not complete yet,
76 * encodings are a guess. C string literals are used because they
77 * are the shortest notation. They are used __with a length__ . Null
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -070078 * termination doesn't work because there are zero bytes.
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070079 */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -070080static const struct FloatTestCase FloatTestCases[] = {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070081 /* Zero */
82 {0.0, 0.0f,
83 {"\xF9\x00\x00", 3}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -070084 {"\xF9\x00\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070085
86 /* Negative Zero */
87 {-0.0, -0.0f,
88 {"\xF9\x80\x00", 3}, {"\xFB\x80\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -070089 {"\xF9\x80\x00", 3}, {"\x00", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -070090
91 /* NaN */
92 {NAN, NAN,
93 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
94 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
95
96 /* Infinity */
97 {INFINITY, INFINITY,
98 {"\xF9\x7C\x00", 3}, {"\xFB\x7F\xF0\x00\x00\x00\x00\x00\x00", 9},
99 {"\xF9\x7C\x00", 3}, {"\xF9\x7C\x00", 3}},
100
101 /* Negative Infinity */
102 {-INFINITY, -INFINITY,
103 {"\xF9\xFC\x00", 3}, {"\xFB\xFF\xF0\x00\x00\x00\x00\x00\x00", 9},
104 {"\xF9\xFC\x00", 3}, {"\xF9\xFC\x00", 3}},
105
106 /* 1.0 */
107 {1.0, 1.0f,
108 {"\xF9\x3C\x00", 3}, {"\xFB\x3F\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700109 {"\xF9\x3C\x00", 3}, {"\x01", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700110
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700111 /* -2.0 -- a negative */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700112 {-2.0, -2.0f,
113 {"\xF9\xC0\x00", 3}, {"\xFB\xC0\x00\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700114 {"\xF9\xC0\x00", 3}, {"\x21", 1}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700115
116 /* 1/3 */
117 {0.333251953125, 0.333251953125f,
118 {"\xF9\x35\x55", 3}, {"\xFB\x3F\xD5\x54\x00\x00\x00\x00\x00", 9},
119 {"\xF9\x35\x55", 3}, {"\xF9\x35\x55", 3}},
120
121 /* 5.9604644775390625E-8 -- smallest half-precision subnormal */
122 {5.9604644775390625E-8, 0.0f,
123 {"\xF9\x00\x01", 3}, {"\xFB\x3E\x70\x00\x00\x00\x00\x00\x00", 9},
124 {"\xF9\x00\x01", 3}, {"\xF9\x00\x01", 3}},
125
126 /* 3.0517578125E-5 -- a half-precision subnormal */
127 {3.0517578125E-5, 0.0f,
128 {"\xF9\x02\x00", 3}, {"\xFB\x3F\x00\x00\x00\x00\x00\x00\x00", 9},
129 {"\xF9\x02\x00", 3}, {"\xF9\x02\x00", 3}},
130
131 /* 6.097555160522461E-5 -- largest half-precision subnormal */
132 {6.097555160522461E-5, 0.0f,
133 {"\xF9\x03\xFF", 3}, {"\xFB\x3F\x0F\xF8\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700134 {"\xF9\x03\xFF", 3}, {"\xF9\x03\xFF", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700135
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700136 /* 6.1035156249999993E-5 -- slightly smaller than smallest half-precision normal */
137 {6.1035156249999993E-5, 0.0f,
138 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
139 {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x3F\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
140
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700141 /* 6.103515625E-5 -- smallest possible half-precision normal */
142 {6.103515625E-5, 0.0f,
143 {"\xF9\04\00", 3}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x00", 9},
144 {"\xF9\04\00", 3}, {"\xF9\04\00", 3}},
145
146 /* 6.1035156250000014E-5 -- slightly larger than smallest half-precision normal */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700147 {6.1035156250000014E-5, 0.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700148 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9},
149 {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x3F\x10\x00\x00\x00\x00\x00\x01", 9}},
150
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700151 /* 65504.0 -- largest possible half-precision */
152 {65504.0, 0.0f,
153 {"\xF9\x7B\xFF", 3}, {"\xFB\x40\xEF\xFC\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700154 {"\xF9\x7B\xFF", 3}, {"\x19\xFF\xE0", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700155
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700156 /* 65504.1 -- exponent too large and too much precision to convert to half */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700157 {65504.1, 0.0f,
158 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9},
159 {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}, {"\xFB\x40\xEF\xFC\x03\x33\x33\x33\x33", 9}},
160
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700161 /* 65536.0 -- exponent too large for half but not too much precision for single */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700162 {65536.0, 65536.0f,
163 {"\xFA\x47\x80\x00\x00", 5}, {"\xFB\x40\xF0\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700164 {"\xFA\x47\x80\x00\x00", 5}, {"\x1A\x00\x01\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700165
166 /* 1.401298464324817e-45 -- smallest single subnormal */
167 {1.401298464324817e-45, 1.40129846E-45f,
168 {"\xFA\x00\x00\x00\x01", 5}, {"\xFB\x36\xA0\x00\x00\x00\x00\x00\x00", 9},
169 {"\xFA\x00\x00\x00\x01", 5}, {"\xFA\x00\x00\x00\x01", 5}},
170
Laurence Lundblade240ca822024-01-16 11:11:00 -0700171 /* 5.8774717541114375E-39 -- slightly smaller than the smallest single normal */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700172 {5.8774717541114375E-39, 5.87747175E-39f,
173 {"\xFA\x00\x40\x00\x00", 5}, {"\xFB\x38\x00\x00\x00\x00\x00\x00\x00", 9},
174 {"\xFA\x00\x40\x00\x00", 5}, {"\xFA\x00\x40\x00\x00", 5}},
175
176 /* 1.1754942106924411e-38 -- largest single subnormal */
177 {1.1754942106924411E-38, 1.17549421E-38f,
178 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFB\x38\x0f\xff\xff\xC0\x00\x00\x00", 9},
179 {"\xFA\x00\x7f\xff\xff", 5}, {"\xFA\x00\x7f\xff\xff", 5} },
180
181 /* 1.1754943508222874E-38 -- slightly bigger than smallest single normal */
182 {1.1754943508222874E-38, 0.0f,
183 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9},
184 {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}, {"\xFB\x38\x0f\xff\xff\xff\xff\xff\xff", 9}},
185
186 /* 1.1754943508222875e-38 -- smallest single normal */
187 {1.1754943508222875e-38, 1.17549435E-38f,
188 {"\xFA\x00\x80\x00\x00", 5}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x00", 9},
189 {"\xFA\x00\x80\x00\x00", 5}, {"\xFA\x00\x80\x00\x00", 5}},
190
191 /* 1.1754943508222875e-38 -- slightly bigger than smallest single normal */
192 {1.1754943508222878e-38, 0.0f,
193 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9},
194 {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x38\x10\x00\x00\x00\x00\x00\x01", 9}},
195
196 /* 16777216 -- converts to single without loss */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700197 {16777216, 16777216.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700198 {"\xFA\x4B\x80\x00\x00", 5}, {"\xFB\x41\x70\x00\x00\x00\x00\x00\x00", 9},
Laurence Lundblade240ca822024-01-16 11:11:00 -0700199 {"\xFA\x4B\x80\x00\x00", 5}, {"\x1A\x01\x00\x00\x00", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700200
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700201 /* 16777217 -- one more than above and fails conversion to single because of precision */
202 {16777217, 0.0f,
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700203 {"\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 -0700204 {"\xFB\x41\x70\x00\x00\x10\x00\x00\x00", 9}, {"\x1A\x01\x00\x00\x01", 5}},
205
206 /* 4294967295 -- UINT32_MAX */
207 {4294967295, 0,
208 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
209 {"\xFB\x41\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x1A\xFF\xFF\xFF\xFF", 5}},
210
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700211 /* 4294967296 -- 2^^32, UINT32_MAX + 1 */
212 {4294967296, 0,
213 {"\xFA\x4F\x80\x00\x00", 5}, {"\xFB\x41\xF0\x00\x00\x00\x00\x00\x00", 9},
214 {"\xFA\x4F\x80\x00\x00", 5}, {"\x1B\x00\x00\x00\x01\x00\x00\x00\x00", 9}},
215
216 /* 2251799813685248 -- exponent 51, 0 significand bits set */
217 {2251799813685248, 0,
218 {"\xFA\x59\x00\x00\x00", 5}, {"\xFB\x43\x20\x00\x00\x00\x00\x00\x00", 9},
219 {"\xFA\x59\x00\x00\x00", 5}, {"\x1B\x00\x08\x00\x00\x00\x00\x00\x00", 9}},
220
221 /* 4503599627370495 -- exponent 51, 52 significand bits set */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700222 {4503599627370495, 0,
223 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9},
224 {"\xFB\x43\x2F\xFF\xFF\xFF\xFF\xFF\xFE", 9}, {"\x1B\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
225
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700226 /* 9007199254740991 -- exponent 52, 52 significand bits set */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700227 {9007199254740991, 0,
228 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
229 {"\xFB\x43\x3F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x1F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
230
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700231 /* 18014398509481982 -- exponent 53, 52 bits set in significand (double lacks precision to represent 18014398509481983) */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700232 {18014398509481982, 0,
233 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
234 {"\xFB\x43\x4F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\x1B\x00\x3F\xFF\xFF\xFF\xFF\xFF\xFE", 9}},
235
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700236 /* 18014398509481984 -- next largest possible double above 18014398509481982 */
Laurence Lundblade240ca822024-01-16 11:11:00 -0700237 {18014398509481984, 0,
238 {"\xFA\x5A\x80\x00\x00", 5}, {"\xFB\x43\x50\x00\x00\x00\x00\x00\x00", 9},
239 {"\xFA\x5A\x80\x00\x00", 5}, {"\x1B\x00\x40\x00\x00\x00\x00\x00\x00", 9}},
240
241 /* -4294967295 -- Negative UINT32_MAX */
242 {-4294967295, 0,
243 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9},
244 {"\xFB\xC1\xEF\xFF\xFF\xFF\xE0\x00\x00", 9}, {"\x3A\xFF\xFF\xFF\xFE", 5}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700245
246 /* 3.4028234663852886E+38 -- largest possible single normal */
247 {3.4028234663852886E+38, 3.40282347E+38f,
248 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x00", 9},
249 {"\xFA\x7F\x7F\xFF\xFF", 5}, {"\xFA\x7F\x7F\xFF\xFF", 5}},
250
251 /* 3.402823466385289E+38 -- slightly larger than largest possible single */
252 {3.402823466385289E+38, 0.0f,
253 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9},
254 {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}, {"\xFB\x47\xEF\xFF\xFF\xE0\x00\x00\x01", 9}},
255
256 /* 3.402823669209385e+38 -- exponent larger by one than largest possible single */
257 {3.402823669209385e+38, 0.0f,
258 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9},
259 {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x47\xF0\x00\x00\x00\x00\x00\x00", 9}},
260
261 /* 5.0e-324 -- smallest double subnormal normal */
262 {5.0e-324, 0.0f,
263 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9},
264 {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x00\x00\x00\x00\x00\x00\x00\x01", 9}},
265
266 /* 2.2250738585072009E−308 -- largest double subnormal */
267 {2.2250738585072009e-308, 0.0f,
268 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9},
269 {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x00\x0F\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
270
271 /* 2.2250738585072014e-308 -- smallest double normal */
272 {2.2250738585072014e-308, 0.0f,
273 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9},
274 {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}, {"\xFB\x00\x10\x00\x00\x00\x00\x00\x00", 9}},
275
276 /* 1.7976931348623157E308 -- largest double normal */
277 {1.7976931348623157e308, 0.0f,
278 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9},
279 {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}, {"\xFB\x7F\xEF\xFF\xFF\xFF\xFF\xFF\xFF", 9}},
280
281 /* List terminator */
282 {0.0, 0.0f, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700283};
284
285
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700286/* Can't use types double and float here because there's no way in C to
287 * construct arbitrary payloads for those types.
288 */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700289struct NaNTestCase {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700290 uint64_t uDouble; /* Converted to double in test */
291 uint32_t uSingle; /* Converted to single in test */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700292 UsefulBufC Preferred;
293 UsefulBufC NotPreferred;
294 UsefulBufC CDE;
295 UsefulBufC DCBOR;
296};
297
298/* Always four lines per test case so shell scripts can process into
299 * other formats. CDE and DCBOR standards are not complete yet,
300 * encodings are a guess. C string literals are used because they
301 * are the shortest notation. They are used __with a length__ . Null
302 * termination doesn't work because there are zero bytes.
303 */
304static const struct NaNTestCase NaNTestCases[] = {
305
306 /* Payload with most significant bit set, a qNaN by most implementations */
307 {0x7ff8000000000000, 0x00000000,
308 {"\xF9\x7E\x00", 3}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x00", 9},
309 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
310
311 /* Payload with single rightmost set */
312 {0x7ff8000000000001, 0x00000000,
313 {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x00\x01", 9},
314 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
315
316 /* Payload with 10 leftmost bits set -- converts to half */
317 {0x7ffffc0000000000, 0x00000000,
318 {"\xF9\x7F\xFF", 3}, {"\xFB\x7F\xFF\xFC\x00\x00\x00\x00\x00", 9},
319 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
320
321 /* Payload with 10 rightmost bits set -- cannot convert to half */
322 {0x7ff80000000003ff, 0x00000000,
323 {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9}, {"\xFB\x7F\xF8\x00\x00\x00\x00\x03\xFF", 9},
324 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
325
326 /* Payload with 23 leftmost bits set -- converts to a single */
327 {0x7ffFFFFFE0000000, 0x7fffffff,
328 {"\xFA\x7F\xFF\xFF\xFF", 5}, {"\xFB\x7F\xFF\xFF\xFF\xE0\x00\x00\x00", 9},
329 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
330
331 /* Payload with 24 leftmost bits set -- fails to convert to a single */
332 {0x7ffFFFFFF0000000, 0x00000000,
333 {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9}, {"\xFB\x7F\xFF\xFF\xFF\xF0\x00\x00\x00", 9},
334 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
335
336 /* Payload with all bits set */
337 {0x7fffffffffffffff, 0x00000000,
338 {"\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 -0700339 {"\xF9\x7E\x00", 3}, {"\xF9\x7E\x00", 3}},
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700340
341 /* List terminator */
342 {0, 0, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} }
343};
344
345
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700346/* Public function. See float_tests.h
347 *
348 * This is the main test of floating-point encoding / decoding. It is
349 * data-driven by the above tables. It works better than tests below that
350 * it mostly replaces because it tests one number at a time, rather than
351 * putting them all in a map. It is much easier to debug test failures
352 * and to add new tests. */
353int32_t
354FloatValuesTests(void)
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700355{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700356 unsigned int uTestIndex;
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700357 const struct FloatTestCase *pTestCase;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700358 const struct NaNTestCase *pNaNTestCase;
359 MakeUsefulBufOnStack( TestOutBuffer, 20);
360 UsefulBufC TestOutput;
361 QCBOREncodeContext EnCtx;
362 QCBORError uErr;
363 QCBORDecodeContext DCtx;
364 QCBORItem Item;
365 uint64_t uDecoded;
366#ifdef QCBOR_DISABLE_FLOAT_HW_USE
367 uint32_t uDecoded2;
368#endif
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700369
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700370 /* Test a variety of doubles */
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700371 for(uTestIndex = 0; FloatTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
372 pTestCase = &FloatTestCases[uTestIndex];
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700373
Laurence Lundblade240ca822024-01-16 11:11:00 -0700374 //if(pTestCase->dNumber == -16325548649218046.0) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700375 if(uTestIndex == 24) {
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700376 uErr = 99; /* For setting break points for particular tests */
377 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800378
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700379 /* Number Encode of Preferred */
380 QCBOREncode_Init(&EnCtx, TestOutBuffer);
381 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
382 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800383
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700384 if(uErr != QCBOR_SUCCESS) {
385 return MakeTestResultCode(uTestIndex, 1, uErr);;
386 }
387 if(UsefulBuf_Compare(TestOutput, pTestCase->Preferred)) {
388 return MakeTestResultCode(uTestIndex, 1, 200);
389 }
Laurence Lundblade68a13352018-09-23 02:19:54 -0700390
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700391 /* Number Encode of Not Preferred */
392 QCBOREncode_Init(&EnCtx, TestOutBuffer);
393 QCBOREncode_AddDoubleNoPreferred(&EnCtx, pTestCase->dNumber);
394 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
Laurence Lundblade68a13352018-09-23 02:19:54 -0700395
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700396 if(uErr != QCBOR_SUCCESS) {
397 return MakeTestResultCode(uTestIndex, 2, uErr);;
398 }
399 if(UsefulBuf_Compare(TestOutput, pTestCase->NotPreferred)) {
400 return MakeTestResultCode(uTestIndex, 2, 200);
401 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800402
Laurence Lundblade240ca822024-01-16 11:11:00 -0700403 /* Number Encode of CDE */
404 QCBOREncode_Init(&EnCtx, TestOutBuffer);
405 QCBOREncode_SerializationCDE(&EnCtx);
406 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
407 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
408
409 if(uErr != QCBOR_SUCCESS) {
410 return MakeTestResultCode(uTestIndex, 20, uErr);;
411 }
412 if(UsefulBuf_Compare(TestOutput, pTestCase->CDE)) {
413 return MakeTestResultCode(uTestIndex, 21, 200);
414 }
415
416 /* Number Encode of dCBOR */
417 QCBOREncode_Init(&EnCtx, TestOutBuffer);
418 QCBOREncode_SerializationdCBOR(&EnCtx);
419 QCBOREncode_AddDouble(&EnCtx, pTestCase->dNumber);
420 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
421
422 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700423 return MakeTestResultCode(uTestIndex, 22, uErr);;
Laurence Lundblade240ca822024-01-16 11:11:00 -0700424 }
425 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700426 return MakeTestResultCode(uTestIndex, 23, 200);
427 }
428
429 if(pTestCase->fNumber != 0) {
430 QCBOREncode_Init(&EnCtx, TestOutBuffer);
431 QCBOREncode_SerializationdCBOR(&EnCtx);
432 QCBOREncode_AddFloat(&EnCtx, pTestCase->fNumber);
433 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
434
435 if(uErr != QCBOR_SUCCESS) {
436 return MakeTestResultCode(uTestIndex, 24, uErr);;
437 }
438 if(UsefulBuf_Compare(TestOutput, pTestCase->DCBOR)) {
439 return MakeTestResultCode(uTestIndex, 25, 200);
440 }
Laurence Lundblade240ca822024-01-16 11:11:00 -0700441 }
442
443
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700444 /* Number Decode of Preferred */
445 QCBORDecode_Init(&DCtx, pTestCase->Preferred, 0);
446 uErr = QCBORDecode_GetNext(&DCtx, &Item);
447 if(uErr != QCBOR_SUCCESS) {
448 return MakeTestResultCode(uTestIndex, 3, uErr);;
449 }
450#ifndef QCBOR_DISABLE_FLOAT_HW_USE
451 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
452 return MakeTestResultCode(uTestIndex, 4, 0);
453 }
454 if(isnan(pTestCase->dNumber)) {
455 if(!isnan(Item.val.dfnum)) {
456 return MakeTestResultCode(uTestIndex, 5, 0);
457 }
458 } else {
459 if(Item.val.dfnum != pTestCase->dNumber) {
460 return MakeTestResultCode(uTestIndex, 6, 0);
461 }
462 }
463#else /* QCBOR_DISABLE_FLOAT_HW_USE */
464 /* When QCBOR_DISABLE_FLOAT_HW_USE is set, single-precision is not
465 * converted to double when decoding, so test differently. len == 5
466 * indicates single-precision in the encoded CBOR. */
467 if(pTestCase->Preferred.len == 5) {
468 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700469 return MakeTestResultCode(uTestIndex, 41, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700470 }
471 if(isnan(pTestCase->dNumber)) {
472 if(!isnan(Item.val.fnum)) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700473 return MakeTestResultCode(uTestIndex, 51, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700474 }
475 } else {
476 if(Item.val.fnum != pTestCase->fNumber) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700477 return MakeTestResultCode(uTestIndex, 61, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700478 }
479 }
480 } else {
481 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700482 return MakeTestResultCode(uTestIndex, 42, 0);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700483 }
484 if(isnan(pTestCase->dNumber)) {
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700485 if(!isnan(Item.val.dfnum)) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700486 return MakeTestResultCode(uTestIndex, 52, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700487 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700488 } else {
489 if(Item.val.dfnum != pTestCase->dNumber) {
Laurence Lundbladebf8e1cf2024-01-17 11:58:24 -0700490 return MakeTestResultCode(uTestIndex, 62, 0);
Laurence Lundblade7d40d812018-09-30 02:44:01 -0700491 }
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700492 }
493 }
494#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700495
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700496 /* Number Decode of Not Preferred */
497 QCBORDecode_Init(&DCtx, pTestCase->NotPreferred, 0);
498 uErr = QCBORDecode_GetNext(&DCtx, &Item);
499 if(uErr != QCBOR_SUCCESS) {
500 return MakeTestResultCode(uTestIndex, 7, uErr);;
501 }
502 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
503 return MakeTestResultCode(uTestIndex, 8, 0);
504 }
505 if(isnan(pTestCase->dNumber)) {
506 if(!isnan(Item.val.dfnum)) {
507 return MakeTestResultCode(uTestIndex, 9, 0);
508 }
509 } else {
510 if(Item.val.dfnum != pTestCase->dNumber) {
511 return MakeTestResultCode(uTestIndex, 10, 0);
512 }
513 }
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700514
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700515 }
516
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700517 /* Test a variety of NaNs with payloads */
518 for(uTestIndex = 0; NaNTestCases[uTestIndex].Preferred.len != 0; uTestIndex++) {
519 pNaNTestCase = &NaNTestCases[uTestIndex];
520
521
522 if(uTestIndex == 4) {
523 uErr = 99; /* For setting break points for particular tests */
524 }
525
526 /* NaN Encode of Preferred */
527 QCBOREncode_Init(&EnCtx, TestOutBuffer);
528 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
529 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
530 if(uErr != QCBOR_SUCCESS) {
531 return MakeTestResultCode(uTestIndex+100, 10, uErr);;
532 }
533 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->Preferred)) {
534 return MakeTestResultCode(uTestIndex+100, 10, 200);
535 }
536
537#ifdef QCBOR_COMPARE_TO_HW_NAN_CONVERSION
538 {
539 /* This test is off by default. It's purpose is to check
540 * QCBOR's mask-n-shift implementation against the HW/CPU
541 * instructions that do conversion between double and single.
542 * It is off because it is only used on occasion to verify
543 * QCBOR and because it is suspected that some HW/CPU does
544 * implement this correctly. NaN payloads are an obscure
545 * feature. */
546 float f;
547 double d, d2;
548
549 d = UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uNumber);
550
551 /* Cast the double to a single and then back to a double and
552 * see if they are equal. If so, then the NaN payload doesn't
553 * have any bits that are lost when converting to single and
554 * it can be safely converted.
555 *
556 * This test can't be done for half-precision because it is
557 * not widely supported.
558 */
559 f = (float)d;
560 d2 = (double)f;
561
562 /* The length of encoded doubles is 9, singles 5 and halves
563 * 3. If there are NaN payload bits that can't be converted,
564 * then the length must be 9.
565 */
566 if((uint64_t)d != (uint64_t)d2 && pNaNTestCase->Preferred.len != 9) {
567 /* QCBOR conversion not the same as HW conversion */
568 return MakeTestResultCode(uTestIndex, 9, 200);
569 }
570 }
571#endif /* QCBOR_COMPARE_TO_HW_NAN_CONVERSION */
572
573
574 /* NaN Encode of Not Preferred */
575 QCBOREncode_Init(&EnCtx, TestOutBuffer);
576 QCBOREncode_AddDoubleNoPreferred(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
577 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
578 if(uErr != QCBOR_SUCCESS) {
579 return MakeTestResultCode(uTestIndex+100, 11, uErr);;
580 }
581 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->NotPreferred)) {
582 return MakeTestResultCode(uTestIndex+100, 11, 200);
583 }
584
Laurence Lundblade240ca822024-01-16 11:11:00 -0700585 /* NaN Decode of Not Preferred */
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700586 QCBORDecode_Init(&DCtx, pNaNTestCase->Preferred, 0);
587 uErr = QCBORDecode_GetNext(&DCtx, &Item);
588 if(uErr != QCBOR_SUCCESS) {
589 return MakeTestResultCode(uTestIndex+100, 12, uErr);
590 }
591
592#ifndef QCBOR_DISABLE_FLOAT_HW_USE
593
594 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
595 if(uDecoded != pNaNTestCase->uDouble) {
596 return MakeTestResultCode(uTestIndex+100, 12, 200);
597 }
598#else /* QCBOR_DISABLE_FLOAT_HW_USE */
599 if(pNaNTestCase->Preferred.len == 5) {
600 if(Item.uDataType != QCBOR_TYPE_FLOAT) {
601 return MakeTestResultCode(uTestIndex, 4, 0);
602 }
603
604 uDecoded2 = UsefulBufUtil_CopyFloatToUint32(Item.val.fnum);
605
606 if(uDecoded2 != pNaNTestCase->uSingle) {
607 return MakeTestResultCode(uTestIndex, 4, 0);
608 }
609 } else {
610 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
611 return MakeTestResultCode(uTestIndex, 4, 0);
612 }
613 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
614 if(uDecoded != pNaNTestCase->uDouble) {
615 return MakeTestResultCode(uTestIndex+100, 12, 200);
616 }
617 }
618#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
619
620 /* NaN Decode of Not Preferred */
621 QCBORDecode_Init(&DCtx, pNaNTestCase->NotPreferred, 0);
622 uErr = QCBORDecode_GetNext(&DCtx, &Item);
623 if(uErr != QCBOR_SUCCESS) {
624 return MakeTestResultCode(uTestIndex+100, 13, uErr);
625 }
626 uDecoded = UsefulBufUtil_CopyDoubleToUint64(Item.val.dfnum);
627 if(uDecoded != pNaNTestCase->uDouble) {
628 return MakeTestResultCode(uTestIndex+100, 13, 200);
629 }
Laurence Lundblade240ca822024-01-16 11:11:00 -0700630
631
632 /* NaN Encode of DCBOR */
633 QCBOREncode_Init(&EnCtx, TestOutBuffer);
634 QCBOREncode_SerializationdCBOR(&EnCtx);
635 QCBOREncode_AddDouble(&EnCtx, UsefulBufUtil_CopyUint64ToDouble(pNaNTestCase->uDouble));
636 uErr = QCBOREncode_Finish(&EnCtx, &TestOutput);
637 if(uErr != QCBOR_SUCCESS) {
638 return MakeTestResultCode(uTestIndex+100, 11, uErr);;
639 }
640 if(UsefulBuf_Compare(TestOutput, pNaNTestCase->DCBOR)) {
641 return MakeTestResultCode(uTestIndex+100, 11, 200);
642 }
643
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700644 }
645
646 return 0;
Laurence Lundblade570fab52018-10-13 18:28:27 +0800647}
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700648
649
650
651/* Public function. See float_tests.h */
652int32_t
653HalfPrecisionAgainstRFCCodeTest(void)
654{
655 QCBORItem Item;
656 QCBORDecodeContext DC;
657 unsigned char pbHalfBytes[2];
658 uint8_t uHalfPrecInitialByte;
659 double d;
660 UsefulBuf_MAKE_STACK_UB(EncodedBytes, 3);
661 UsefulOutBuf UOB;
662 uint32_t uHalfP;
663
664
665 for(uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
666 pbHalfBytes[1] = (uint8_t)(uHalfP & 0xff);
667 pbHalfBytes[0] = (uint8_t)(uHalfP >> 8); /* uHalfP is always less than 0xffff */
668 d = decode_half(pbHalfBytes);
669
670 /* Construct the CBOR for the half-precision float by hand */
671 UsefulOutBuf_Init(&UOB, EncodedBytes);
672
673 uHalfPrecInitialByte = (uint8_t)(HALF_PREC_FLOAT + (CBOR_MAJOR_TYPE_SIMPLE << 5)); /* 0xf9 */
674 UsefulOutBuf_AppendByte(&UOB, uHalfPrecInitialByte); /* initial byte */
675 UsefulOutBuf_AppendUint16(&UOB, (uint16_t)uHalfP); /* argument */
676
677 /* Now parse the hand-constructed CBOR. This will invoke the
678 * conversion to a float
679 */
680 QCBORDecode_Init(&DC, UsefulOutBuf_OutUBuf(&UOB), 0);
681 QCBORDecode_GetNext(&DC, &Item);
682 if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
683 return -1;
684 }
685
686 if(isnan(d)) {
687 /* The RFC code uses the native instructions which may or may not
688 * handle sNaN, qNaN and NaN payloads correctly. This test just
689 * makes sure it is a NaN and doesn't worry about the type of NaN
690 */
691 if(!isnan(Item.val.dfnum)) {
692 return -3;
693 }
694 } else {
695 if(Item.val.dfnum != d) {
696 return -2;
697 }
698 }
699 }
700 return 0;
701}
702
Laurence Lundblade585127a2020-07-15 03:25:24 -0700703#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladed711fb22018-09-26 14:35:22 -0700704
705
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700706/*
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700707 * Some encoded floating point numbers that are used for both
708 * encode and decode tests.
709 *
710 * [0.0, // Half
711 * 3.14, // Double
712 * 0.0, // Double
713 * NaN, // Double
714 * Infinity, // Double
715 * 0.0, // Half (Duplicate because of use in encode tests)
716 * 3.140000104904175, // Single
717 * 0.0, // Single
718 * NaN, // Single
719 * Infinity, // Single
720 * {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
721 * 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700722 */
723static const uint8_t spExpectedFloats[] = {
724 0x8B,
725 0xF9, 0x00, 0x00,
726 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
727 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730 0xF9, 0x00, 0x00,
731 0xFA, 0x40, 0x48, 0xF5, 0xC3,
732 0xFA, 0x00, 0x00, 0x00, 0x00,
733 0xFA, 0x7F, 0xC0, 0x00, 0x00,
734 0xFA, 0x7F, 0x80, 0x00, 0x00,
735 0xA8,
736 0x18, 0x64,
737 0xF9, 0x00, 0x00,
738 0x18, 0x65,
739 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
740 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
741 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
742 0x18, 0x69,
743 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
744 0x18, 0x66,
745 0xF9, 0x00, 0x00,
746 0x18, 0x67,
747 0xFA, 0x40, 0x49, 0x0F, 0xDA,
748 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
749 0xFA, 0x40, 0x2D, 0xF8, 0x54,
750 0x18, 0x6A,
751 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700752
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200753#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700754static const uint8_t spExpectedFloatsNoHalf[] = {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700755 0x8B,
756 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
757 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
758 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
759 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0xFA, 0x00, 0x00, 0x00, 0x00,
762 0xFA, 0x40, 0x48, 0xF5, 0xC3,
763 0xFA, 0x00, 0x00, 0x00, 0x00,
764 0xFA, 0x7F, 0xC0, 0x00, 0x00,
765 0xFA, 0x7F, 0x80, 0x00, 0x00,
766 0xA8,
767 0x18, 0x64,
768 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x18, 0x65,
770 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
771 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
772 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
773 0x18, 0x69,
774 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775 0x18, 0x66,
776 0xFA, 0x00, 0x00, 0x00, 0x00,
777 0x18, 0x67,
778 0xFA, 0x40, 0x49, 0x0F, 0xDA,
779 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
780 0xFA, 0x40, 0x2D, 0xF8, 0x54,
781 0x18, 0x6A,
782 0xFA, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700783
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700784
785/* Public function. See float_tests.h */
786int32_t
787GeneralFloatEncodeTests(void)
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700788{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700789 /* See FloatNumberTests() for tests that really cover lots of float values.
790 * Add new tests for new values or decode modes there.
791 * This test is primarily to cover all the float encode methods. */
792
793 UsefulBufC Encoded;
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700794 UsefulBufC ExpectedFloats;
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700795 QCBORError uErr;
796
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700797#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700798 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700799 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700800 (void)spExpectedFloatsNoHalf; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700801#else
802 UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloatsNoHalf));
Laurence Lundbladeb992fdb2020-07-20 22:44:11 -0700803 ExpectedFloats = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloatsNoHalf);
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700804 (void)spExpectedFloats; /* Avoid unused variable error */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700805#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700806
807 QCBOREncodeContext EC;
808 QCBOREncode_Init(&EC, OutBuffer);
809 QCBOREncode_OpenArray(&EC);
810
811 QCBOREncode_AddDouble(&EC, 0.0);
812 QCBOREncode_AddDouble(&EC, 3.14);
813 QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
814 QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
815 QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
816
817 QCBOREncode_AddFloat(&EC, 0.0);
818 QCBOREncode_AddFloat(&EC, 3.14f);
819 QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
820 QCBOREncode_AddFloatNoPreferred(&EC, NAN);
821 QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
822
823 QCBOREncode_OpenMap(&EC);
824
825 QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
826 QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
827 QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
828 QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
829
830 QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
831 QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
832 QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
833 QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
834
835 QCBOREncode_CloseMap(&EC);
836 QCBOREncode_CloseArray(&EC);
837
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700838 uErr = QCBOREncode_Finish(&EC, &Encoded);
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700839 if(uErr) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700840 return -1;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700841 }
842
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700843 if(UsefulBuf_Compare(Encoded, ExpectedFloats)) {
Laurence Lundblade585127a2020-07-15 03:25:24 -0700844 return -3;
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700845 }
846
847 return 0;
848}
849
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200850#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700851
852
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700853/* Public function. See float_tests.h */
854int32_t
855GeneralFloatDecodeTests(void)
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700856{
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700857 /* See FloatNumberTests() for tests that really cover lots of float values */
858
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700859 QCBORItem Item;
860 QCBORError uErr;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700861 QCBORDecodeContext DC;
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700862
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700863 UsefulBufC TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
864 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700865
866 QCBORDecode_GetNext(&DC, &Item);
867 if(Item.uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700868 return MakeTestResultCode(0, 1, 0);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700869 }
870
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700871 /* 0.0 half-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700872 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200873 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
874#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
875 || Item.uDataType != QCBOR_TYPE_DOUBLE
876 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700877#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
878 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200879#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
880 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700881 return MakeTestResultCode(0, 2, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700882 }
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700883
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700884 /* 3.14 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700885 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200886 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
887#ifndef USEFULBUF_DISABLE_ALL_FLOAT
888 || Item.uDataType != QCBOR_TYPE_DOUBLE
889 || Item.val.dfnum != 3.14
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700890#else /* USEFULBUF_DISABLE_ALL_FLOAT */
891 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200892#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
893 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700894 return MakeTestResultCode(0, 3, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700895 }
896
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700897 /* 0.0 double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700898 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200899 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
900#ifndef USEFULBUF_DISABLE_ALL_FLOAT
901 || Item.uDataType != QCBOR_TYPE_DOUBLE
902 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700903#else /* USEFULBUF_DISABLE_ALL_FLOAT */
904 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200905#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
906 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700907 return MakeTestResultCode(0, 4, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700908 }
909
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700910 /* NaN double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700911 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200912 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
913#ifndef USEFULBUF_DISABLE_ALL_FLOAT
914 || Item.uDataType != QCBOR_TYPE_DOUBLE
915 || !isnan(Item.val.dfnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700916#else /* USEFULBUF_DISABLE_ALL_FLOAT */
917 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200918#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
919 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700920 return MakeTestResultCode(0, 5, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700921 }
922
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700923 /* Infinity double-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700924 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200925 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
926#ifndef USEFULBUF_DISABLE_ALL_FLOAT
927 || Item.uDataType != QCBOR_TYPE_DOUBLE
928 || Item.val.dfnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700929#else /* USEFULBUF_DISABLE_ALL_FLOAT */
930 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200931#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
932 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700933 return MakeTestResultCode(0, 6, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700934 }
935
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700936 /* 0.0 half-precision (again) */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700937 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200938 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
939#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
940 || Item.uDataType != QCBOR_TYPE_DOUBLE
941 || Item.val.dfnum != 0.0
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700942#else /* USEFULBUF_DISABLE_ALL_FLOAT */
943 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200944#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
945 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700946 return MakeTestResultCode(0, 7, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700947 }
948
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700949 /* 3.140000104904175 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700950 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200951 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
952#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700953#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200954 || Item.uDataType != QCBOR_TYPE_DOUBLE
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700955 || 3.1400001049041748 != Item.val.dfnum
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700956#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200957 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700958 || 3.140000f != Item.val.fnum
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700959#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
960#else /* USEFULBUF_DISABLE_ALL_FLOAT */
961 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200962#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
963 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700964 return MakeTestResultCode(0, 8, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700965 }
966
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700967 /* 0.0 single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700968 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200969 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
970#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700971#ifndef QCBOR_DISABLE_FLOAT_HW_USE
972 || Item.uDataType != QCBOR_TYPE_DOUBLE
973 || Item.val.dfnum != 0.0
974#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200975 || Item.uDataType != QCBOR_TYPE_FLOAT
Laurence Lundblade83dbf5c2024-01-07 19:17:52 -0700976 || Item.val.fnum != 0.0f
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700977#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
978#else /* USEFULBUF_DISABLE_ALL_FLOAT */
979 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200980#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
981 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700982 return MakeTestResultCode(0, 9, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700983 }
984
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700985 /* NaN single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700986 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200987 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
988#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700989#ifndef QCBOR_DISABLE_FLOAT_HW_USE
990 || Item.uDataType != QCBOR_TYPE_DOUBLE
991 || !isnan(Item.val.dfnum)
992#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200993 || Item.uDataType != QCBOR_TYPE_FLOAT
994 || !isnan(Item.val.fnum)
Laurence Lundblade16a207a2021-09-18 17:22:46 -0700995#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
996#else /* USEFULBUF_DISABLE_ALL_FLOAT */
997 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200998#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
999 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001000 return MakeTestResultCode(0, 10, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001001 }
1002
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001003 /* Infinity single-precision */
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001004 uErr = QCBORDecode_GetNext(&DC, &Item);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001005 if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
1006#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001007#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1008 || Item.uDataType != QCBOR_TYPE_DOUBLE
1009 || Item.val.dfnum != INFINITY
1010#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001011 || Item.uDataType != QCBOR_TYPE_FLOAT
1012 || Item.val.fnum != INFINITY
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001013#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1014#else /* USEFULBUF_DISABLE_ALL_FLOAT */
1015 || Item.uDataType != QCBOR_TYPE_NONE
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001016#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1017 ) {
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001018 return MakeTestResultCode(0, 11, uErr);
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001019 }
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001020 /* Sufficent test coverage. Don't need to decode the rest. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001021
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001022
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001023#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001024 /* Now tests for spiffy decode main function */
1025 TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001026 double d;
1027 QCBORDecode_Init(&DC, TestData, 0);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07001028 QCBORDecode_EnterArray(&DC, NULL);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001029
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001030 /* 0.0 half-precision */
1031 QCBORDecode_GetDouble(&DC, &d);
1032 uErr = QCBORDecode_GetAndResetError(&DC);
1033 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001034#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001035 || d != 0.0
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001036#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001037 ) {
1038 return MakeTestResultCode(1, 1, uErr);
1039 }
1040
1041 /* 3.14 double-precision */
1042 QCBORDecode_GetDouble(&DC, &d);
1043 uErr = QCBORDecode_GetAndResetError(&DC);
1044 if(uErr != QCBOR_SUCCESS || d != 3.14) {
1045 return MakeTestResultCode(1, 2, uErr);
1046 }
1047
1048 /* 0.0 double-precision */
1049 QCBORDecode_GetDouble(&DC, &d);
1050 uErr = QCBORDecode_GetAndResetError(&DC);
1051 if(uErr != QCBOR_SUCCESS || d != 0.0) {
1052 return MakeTestResultCode(1, 3, uErr);
1053 }
1054
1055 /* NaN double-precision */
1056 QCBORDecode_GetDouble(&DC, &d);
1057 uErr = QCBORDecode_GetAndResetError(&DC);
1058 if(uErr != QCBOR_SUCCESS || !isnan(d)) {
1059 return MakeTestResultCode(1, 4, uErr);
1060 }
1061
1062 /* Infinity double-precision */
1063 QCBORDecode_GetDouble(&DC, &d);
1064 uErr = QCBORDecode_GetAndResetError(&DC);
1065 if(uErr != QCBOR_SUCCESS || d != INFINITY) {
1066 return MakeTestResultCode(1, 5, uErr);
1067 }
1068
1069 /* 0.0 half-precision */
1070 QCBORDecode_GetDouble(&DC, &d);
1071 uErr = QCBORDecode_GetAndResetError(&DC);
1072 if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
1073#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
1074 || d != 0.0
1075#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
1076 ) {
1077 return MakeTestResultCode(1, 6, uErr);
1078 }
1079
1080 /* 3.140000104904175 single-precision */
1081 QCBORDecode_GetDouble(&DC, &d);
1082 uErr = QCBORDecode_GetAndResetError(&DC);
1083 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1084#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1085 || d != 3.140000104904175
1086#endif
1087 ) {
1088 return MakeTestResultCode(1, 7, uErr);
1089 }
1090
1091 /* 0.0 single-precision */
1092 QCBORDecode_GetDouble(&DC, &d);
1093 uErr = QCBORDecode_GetAndResetError(&DC);
1094 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1095#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1096 || d != 0.0
1097#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1098 ) {
1099 return MakeTestResultCode(1, 8, uErr);
1100 }
1101
1102 /* NaN single-precision */
1103 QCBORDecode_GetDouble(&DC, &d);
1104 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1105#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1106 || !isnan(d)
1107#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1108 ) {
1109 return MakeTestResultCode(1, 9, uErr);
1110 }
1111
1112 /* Infinity single-precision */
1113 QCBORDecode_GetDouble(&DC, &d);
1114 uErr = QCBORDecode_GetAndResetError(&DC);
1115 if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)
1116#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1117 || d != INFINITY
1118#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
1119 ) {
1120 return MakeTestResultCode(1, 10, uErr);
1121 }
1122
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001123#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001124
Laurence Lundblade02fcf312020-07-17 02:49:46 -07001125 return 0;
1126}
1127
1128
Laurence Lundbladed711fb22018-09-26 14:35:22 -07001129
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001130#ifdef NAN_EXPERIMENT
1131/*
1132 Code for checking what the double to float cast does with
1133 NaNs. Not run as part of tests. Keep it around to
1134 be able to check various platforms and CPUs.
1135 */
1136
1137#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
1138#define DOUBLE_NUM_EXPONENT_BITS (11)
1139#define DOUBLE_NUM_SIGN_BITS (1)
1140
1141#define DOUBLE_SIGNIFICAND_SHIFT (0)
1142#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
1143#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
1144
1145#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
1146#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
1147#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
1148#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
1149
1150
1151static int NaNExperiments() {
1152 double dqNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT);
1153 double dsNaN = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | 0x01);
1154 double dqNaNPayload = UsefulBufUtil_CopyUint64ToDouble(DOUBLE_EXPONENT_MASK | DOUBLE_QUIET_NAN_BIT | 0xf00f);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001155
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001156 float f1 = (float)dqNaN;
1157 float f2 = (float)dsNaN;
1158 float f3 = (float)dqNaNPayload;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001159
1160
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001161 uint32_t uqNaN = UsefulBufUtil_CopyFloatToUint32((float)dqNaN);
1162 uint32_t usNaN = UsefulBufUtil_CopyFloatToUint32((float)dsNaN);
1163 uint32_t uqNaNPayload = UsefulBufUtil_CopyFloatToUint32((float)dqNaNPayload);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001164
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001165 // Result of this on x86 is that every NaN is a qNaN. The intel
1166 // CVTSD2SS instruction ignores the NaN payload and even converts
1167 // a sNaN to a qNaN.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001168
Laurence Lundblade7d40d812018-09-30 02:44:01 -07001169 return 0;
1170}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001171#endif /* NAN_EXPERIMENT */