| 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 | }
|