1 | // float_test.cc - Printing floats
|
2 |
|
3 | #include <inttypes.h>
|
4 | // #include <limits.h> // HOST_NAME_MAX
|
5 | // #include <unistd.h> // gethostname()
|
6 |
|
7 | //#include <new> // placement new
|
8 |
|
9 | // #include "mycpp/runtime.h"
|
10 | // #include "mycpp/common.h"
|
11 | // #include "mycpp/gc_obj.h" // ObjHeader
|
12 | #include "vendor/greatest.h"
|
13 |
|
14 | // https://randomascii.wordpress.com/2012/01/11/tricks-with-the-floating-point-format/
|
15 |
|
16 | union Float_t {
|
17 | Float_t(float num = 0.0f) : f(num) {
|
18 | }
|
19 | // Portable extraction of components.
|
20 | bool Negative() const {
|
21 | return (i >> 31) != 0;
|
22 | }
|
23 | int32_t RawMantissa() const {
|
24 | return i & ((1 << 23) - 1);
|
25 | }
|
26 | int32_t RawExponent() const {
|
27 | return (i >> 23) & 0xFF;
|
28 | }
|
29 |
|
30 | int32_t i;
|
31 | float f;
|
32 | #if 1
|
33 | struct { // Bitfields for exploration. Do not use in production code.
|
34 | uint32_t mantissa : 23;
|
35 | uint32_t exponent : 8;
|
36 | uint32_t sign : 1;
|
37 | } parts;
|
38 | #endif
|
39 | };
|
40 |
|
41 | void PrintFloat(Float_t num) {
|
42 | // printf("Float value, representation, sign, exponent, mantissa\n");
|
43 | printf("%1.8e 0x%08X sign %d, exponent %d, mantissa 0x%06X\n", num.f,
|
44 | num.i, num.parts.sign, num.parts.exponent, num.parts.mantissa);
|
45 | }
|
46 |
|
47 | TEST print_float_test() {
|
48 | Float_t num(1.0f);
|
49 | for (int i = 0; i < 10; ++i) {
|
50 | PrintFloat(num);
|
51 | num.i -= 1;
|
52 | }
|
53 |
|
54 | PASS();
|
55 | }
|
56 |
|
57 | typedef float (*Transform)(float);
|
58 |
|
59 | // https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-floatsso-test-them-all/
|
60 |
|
61 | // Pass in a uint32_t range of float representations to test.
|
62 | // start and stop are inclusive. Pass in 0, 0xFFFFFFFF to scan all
|
63 | // floats. The floats are iterated through by incrementing
|
64 | // their integer representation.
|
65 | bool ExhaustiveTest(uint32_t start, uint32_t stop, Transform TestFunc,
|
66 | Transform RefFunc, const char* desc) {
|
67 | printf("Testing %s from %u to %u (inclusive).\n", desc, start, stop);
|
68 | // Use long long to let us loop over all positive integers.
|
69 | long long i = start;
|
70 | bool passed = true;
|
71 | while (i <= stop) {
|
72 | Float_t input;
|
73 | input.i = (int32_t)i;
|
74 | Float_t testValue = TestFunc(input.f);
|
75 | Float_t refValue = RefFunc(input.f);
|
76 | // If the results don’t match then report an error.
|
77 | if (testValue.f != refValue.f &&
|
78 | // If both results are NaNs then we treat that as a match.
|
79 | (testValue.f == testValue.f || refValue.f == refValue.f)) {
|
80 | printf("Input %.9g, expected %.9g, got %1.9g \n", input.f,
|
81 | refValue.f, testValue.f);
|
82 | passed = false;
|
83 | }
|
84 |
|
85 | ++i;
|
86 | }
|
87 | return passed;
|
88 | }
|
89 |
|
90 | float half(float f) {
|
91 | return f / 2;
|
92 | }
|
93 |
|
94 | float half2(float f) {
|
95 | #if 0
|
96 | if (f == 4242.00) {
|
97 | return f + 1; // see if exhasutive test finds this number
|
98 | }
|
99 | #endif
|
100 | return f / 2;
|
101 | }
|
102 |
|
103 | TEST round_trip_test() {
|
104 | // This is the biggest number that can be represented in
|
105 | // both float and int32_t. It’s 2^31-128.
|
106 | Float_t maxfloatasint(2147483520.0f);
|
107 |
|
108 | // const uint32_t signBit = 0x80000000;
|
109 |
|
110 | // Takes 3.5 seconds in opt
|
111 | ASSERT(ExhaustiveTest(0, (uint32_t)maxfloatasint.i, half, half2,
|
112 | "exhaustive half"));
|
113 |
|
114 | PASS();
|
115 | }
|
116 |
|
117 | GREATEST_MAIN_DEFS();
|
118 |
|
119 | int main(int argc, char** argv) {
|
120 | // gHeap.Init();
|
121 |
|
122 | GREATEST_MAIN_BEGIN();
|
123 |
|
124 | RUN_TEST(print_float_test);
|
125 | RUN_TEST(round_trip_test);
|
126 |
|
127 | // gHeap.CleanProcessExit();
|
128 |
|
129 | GREATEST_MAIN_END();
|
130 | return 0;
|
131 | }
|