FastLED 3.10.6
Loading...
Searching...
No Matches
AutoResearchIeee754.h
Go to the documentation of this file.
1
3
4#pragma once
5
7#include "fl/stl/int.h"
8#include "fl/stl/string.h"
9#include "fl/stl/cstring.h"
10#include "fl/stl/singleton.h"
11
12namespace autoresearch {
13namespace ieee754_check {
14
15struct Result {
16 bool success;
17 fl::u32 tests_run;
18 fl::u32 tests_failed;
19 const char* first_failure;
21 fl::u32 actual_bits;
22};
23
24struct ParseCase {
25 const char* text;
27 bool exact;
28};
29
30struct FormatCase {
31 fl::u32 bits;
33 const char* expected_text;
34};
35
39 fl::u32 round_trip_bits[10];
40
42 : parse_cases{{"0", 0x00000000u, true},
43 {"-0", 0x80000000u, true},
44 {"1", 0x3F800000u, true},
45 {"-1", 0xBF800000u, true},
46 {"0.5", 0x3F000000u, true},
47 {"2.5", 0x40200000u, true},
48 {"3.14159", 0x40490FD0u, false},
49 {"2.71828", 0x402DF84Du, false},
50 {"100", 0x42C80000u, true},
51 {"1000", 0x447A0000u, true},
52 {"1e30", 0x7149F2CAu, false},
53 {"1e-30", 0x0DA24260u, false},
54 {"1e-40", 0x00000000u, true},
55 {"1e40", 0x7F800000u, true},
56 {"-1e40", 0xFF800000u, true}},
57 format_cases{{0x00000000u, 6, "0.000000"},
58 {0x80000000u, 6, "-0.000000"},
59 {0x3F800000u, 6, "1.000000"},
60 {0xBF800000u, 6, "-1.000000"},
61 {0x3F000000u, 6, "0.500000"},
62 {0x41200000u, 2, "10.00"},
63 {0x7F800000u, 6, "inf"},
64 {0xFF800000u, 6, "-inf"},
65 {0x7FC00000u, 6, "nan"}},
66 round_trip_bits{0x00000000u, 0x80000000u, 0x3F800000u, 0xBF800000u,
67 0x3F000000u, 0x40200000u, 0x40490FDBu, 0x40B00000u,
68 0x42C80000u, 0x447A0000u} {}
69};
70
74
75inline fl::u32 absDiff(fl::u32 a, fl::u32 b) FL_NO_EXCEPT {
76 return a > b ? a - b : b - a;
77}
78
79inline bool withinOneUlp(fl::u32 actual, fl::u32 expected) FL_NO_EXCEPT {
80 if (actual == expected) {
81 return true;
82 }
83 if ((actual & 0x80000000u) != (expected & 0x80000000u)) {
84 return false;
85 }
86 return absDiff(actual, expected) <= 1u;
87}
88
89inline void recordCheck(Result& r, const char* name, bool passed,
90 fl::u32 expected = 0, fl::u32 actual = 0) FL_NO_EXCEPT {
91 ++r.tests_run;
92 if (passed) {
93 return;
94 }
95 ++r.tests_failed;
96 if (r.first_failure == nullptr) {
97 r.first_failure = name;
98 r.expected_bits = expected;
99 r.actual_bits = actual;
100 }
101}
102
103inline Result run() {
104 Result r{};
105 r.success = true;
106 r.first_failure = nullptr;
107
109
110 for (fl::size i = 0; i < sizeof(state.parse_cases) / sizeof(state.parse_cases[0]); ++i) {
111 const ParseCase& c = state.parse_cases[i];
112 fl::size consumed = 0;
113 const fl::u32 actual =
115 const bool value_ok = c.exact
116 ? actual == c.expected_bits
117 : withinOneUlp(actual, c.expected_bits);
118 recordCheck(r, c.text, value_ok && consumed == fl::strlen(c.text),
119 c.expected_bits, actual);
120 }
121
122 for (fl::size i = 0; i < sizeof(state.format_cases) / sizeof(state.format_cases[0]); ++i) {
123 const FormatCase& c = state.format_cases[i];
125 recordCheck(r, c.expected_text, actual == c.expected_text,
126 c.bits, c.bits);
127 }
128
129 for (fl::size i = 0; i < sizeof(state.round_trip_bits) / sizeof(state.round_trip_bits[0]); ++i) {
130 const fl::u32 expected = state.round_trip_bits[i];
131 const fl::string text = fl::ieee754_format_decimal(expected, 9);
132 const fl::u32 actual =
133 fl::ieee754_parse_decimal(text.c_str(), text.size());
134 recordCheck(r, "roundtrip", withinOneUlp(actual, expected),
135 expected, actual);
136 }
137
138 fl::size consumed = 123u;
139 (void)fl::ieee754_parse_decimal("nan", 3, &consumed);
140 recordCheck(r, "nan-reject", consumed == 0u, 0u, static_cast<fl::u32>(consumed));
141
142 r.success = r.tests_failed == 0u;
143 return r;
144}
145
146} // namespace ieee754_check
147} // namespace autoresearch
TestState state
static T & instance() FL_NO_EXCEPT
Definition singleton.h:81
const char * c_str() const FL_NO_EXCEPT
fl::size size() const FL_NO_EXCEPT
Ieee754CaseState & ieee754CaseState()
void recordCheck(Result &r, const char *name, bool passed, fl::u32 expected=0, fl::u32 actual=0) FL_NO_EXCEPT
bool withinOneUlp(fl::u32 actual, fl::u32 expected) FL_NO_EXCEPT
fl::u32 absDiff(fl::u32 a, fl::u32 b) FL_NO_EXCEPT
u32 ieee754_parse_decimal(const char *s, fl::size len, fl::size *consumed) FL_NO_EXCEPT
Parse a decimal floating-point number into IEEE 754 single-precision bits.
size_t strlen(const char *s) FL_NO_EXCEPT
fl::string ieee754_format_decimal(u32 bits, int precision) FL_NO_EXCEPT
Format IEEE 754 single-precision bits as decimal text.
#define FL_NO_EXCEPT