From 2fdc7a128b52bb14dc23aa2af8793a9e01951cee Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Wed, 6 Mar 2024 12:08:43 +0100 Subject: [PATCH] Fix #10, mantissa overflow (#11) - **warning: breaking changes!** - Fix #10, mantissa overflow - Fix convert to subnormal numbers ( < 0.000061035...) - Fix printing subnormal numbers - update unit tests with **test_all** - update GitHub/actions to version 4 - remove DATE from examples as it has no added value. - minor edits --- .github/workflows/arduino-lint.yml | 2 +- .github/workflows/arduino_test_runner.yml | 2 +- .github/workflows/jsoncheck.yml | 2 +- CHANGELOG.md | 13 +- LICENSE | 2 +- README.md | 32 ++++- examples/float16_test0/float16_test0.ino | 5 +- examples/float16_test1/float16_test1.ino | 4 +- .../float16_test_all/float16_test_all.ino | 56 +++++++-- .../float16_test_all_2/float16_test_all_2.ino | 113 ++++++++++++++++++ .../float16_test_array/float16_test_array.ino | 13 +- .../float16_test_negative.ino | 5 +- .../float16_test_performance.ino | 5 +- .../performance_0.2.0.txt | 53 ++++++++ .../float16_test_powers2.ino | 2 - .../float16_test_special.ino | 8 +- float16.cpp | 75 +++++++----- float16.h | 36 +++--- library.json | 2 +- library.properties | 2 +- test/unit_test_001.cpp | 35 +++++- 21 files changed, 372 insertions(+), 95 deletions(-) create mode 100644 examples/float16_test_all_2/float16_test_all_2.ino create mode 100644 examples/float16_test_performance/performance_0.2.0.txt diff --git a/.github/workflows/arduino-lint.yml b/.github/workflows/arduino-lint.yml index 8a26f14..870a176 100644 --- a/.github/workflows/arduino-lint.yml +++ b/.github/workflows/arduino-lint.yml @@ -6,7 +6,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: arduino/arduino-lint-action@v1 with: library-manager: update diff --git a/.github/workflows/arduino_test_runner.yml b/.github/workflows/arduino_test_runner.yml index fadfa90..5506eb6 100644 --- a/.github/workflows/arduino_test_runner.yml +++ b/.github/workflows/arduino_test_runner.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: 2.6 diff --git a/.github/workflows/jsoncheck.yml b/.github/workflows/jsoncheck.yml index 37a1129..beb8829 100644 --- a/.github/workflows/jsoncheck.yml +++ b/.github/workflows/jsoncheck.yml @@ -10,7 +10,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: json-syntax-check uses: limitusus/json-syntax-check@v1 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 97fd2b3..374d001 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,23 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.2.0] - 2024-03-05 +- **warning: breaking changes!** +- Fix #10, mantissa overflow +- Fix convert to subnormal numbers ( < 0.000061035...) +- Fix printing subnormal numbers +- update unit tests with **test_all** +- update GitHub/actions to version 4 +- remove DATE from examples as it has no added value. +- minor edits + +---- + ## [0.1.8] - 2023-11-02 - update readme.md - add **isNan()** (experimental). - minor edits. - ## [0.1.7] - 2022-11-07 - add changelog.md - add rp2040 to build-CI diff --git a/LICENSE b/LICENSE index 18c804e..3b61d73 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2015-2023 Rob Tillaart +Copyright (c) 2015-2024 Rob Tillaart Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8037a68..9b6350e 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,21 @@ a floating point number. As it uses only 2 bytes where float and double have typ 4 and 8 bytes, gains can be made at the price of range and precision. +#### Breaking change 0.2.0 + +Version 0.2.0 has a breaking change as a conversion bug has been found. +See for details in issue #10. +For some specific values the mantissa overflowed when the float 16 was +assigned a value to. This overflow was not detected / corrected. + +During the analysis of this bug it became clear that the sub-normal numbers +were also implemented correctly. This is fixed too in 0.2.0. + +There is still an issue 0 versus -0 + +**This makes all pre-0.2.0 version obsolete.** + + ## Specifications @@ -34,14 +49,16 @@ a floating point number. As it uses only 2 bytes where float and double have typ | size | 2 bytes | layout s eeeee mmmmmmmmmm (1,5,10) | sign | 1 bit | | exponent | 5 bit | -| mantissa | 11 bit | ~ 3 digits +| mantissa | 10 bit | ~ 3 digits | minimum | 5.96046 Eāˆ’8 | smallest positive number. -| | 1.0009765625 | 1 + 2^āˆ’10 = smallest nr larger than 1. +| | 1.0009765625 | 1 + 2^āˆ’10 = smallest number larger than 1. | maximum | 65504 | | | | -#### example values +#### Example values + +Source: https://en.wikipedia.org/wiki/Half-precision_floating-point_format ```cpp /* @@ -151,9 +168,18 @@ negation operator. #### Should - unit tests of the above. +- how to handle 0 == -0 (0x0000 == 0x8000) +- investigate ARM alternative half-precision +_ARM processors support (via a floating point control register bit) +an "alternative half-precision" format, which does away with the +special case for an exponent value of 31 (111112).[10] It is almost +identical to the IEEE format, but there is no encoding for infinity or NaNs; +instead, an exponent of 31 encodes normalized numbers in the range 65536 to 131008._ + #### Could +- copy constructor? - update documentation. - error handling. - divide by zero errors. diff --git a/examples/float16_test0/float16_test0.ino b/examples/float16_test0/float16_test0.ino index a0d9c9d..1582554 100644 --- a/examples/float16_test0/float16_test0.ino +++ b/examples/float16_test0/float16_test0.ino @@ -2,9 +2,8 @@ // FILE: float16_test0.ino // AUTHOR: Rob Tillaart // PURPOSE: test float16 -// DATE: 2015-03-11 // URL: https://github.com/RobTillaart/float16 -// + /* SIGN EXP MANTISSA @@ -152,4 +151,4 @@ void test_numbers() } -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/examples/float16_test1/float16_test1.ino b/examples/float16_test1/float16_test1.ino index b60752d..ee2a638 100644 --- a/examples/float16_test1/float16_test1.ino +++ b/examples/float16_test1/float16_test1.ino @@ -2,9 +2,7 @@ // FILE: float16_test1.ino // AUTHOR: Rob Tillaart // PURPOSE: test float16 -// DATE: 2015-03-11 // URL: https://github.com/RobTillaart/float16 -// #include "float16.h" @@ -40,6 +38,6 @@ void loop() } -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/examples/float16_test_all/float16_test_all.ino b/examples/float16_test_all/float16_test_all.ino index 9ef4aa8..4ab2b54 100644 --- a/examples/float16_test_all/float16_test_all.ino +++ b/examples/float16_test_all/float16_test_all.ino @@ -2,14 +2,13 @@ // FILE: float16_test_all.ino // AUTHOR: Rob Tillaart // PURPOSE: test float16 -// DATE: 2021-11-27 // URL: https://github.com/RobTillaart/float16 -// - -// test all values except the NAN -// test_1 takes ~ 2 minutes on UNO @ 115200baud -// https://github.com/RobTillaart/float16/issues/2 +// test all values except the NAN +// test_1 takes ~ 2 minutes on UNO @ 115200baud +// https://github.com/RobTillaart/float16/issues/2 +// +// test_3 is related to issue #10 #include "float16.h" @@ -34,6 +33,7 @@ void setup() test_1(); test_2(); + test_3(); } @@ -42,8 +42,41 @@ void loop() } +// test for issue #10 +void test_3() +{ + Serial.println(__FUNCTION__); + uint16_t y = 0; + uint16_t last = 0; + + start = millis(); + for (int32_t x = 1; x < 65535; x++) // test positive integers. + // for (int32_t x = -1; x > -65535; x--) // test negative integers. + { + last = y; + f16 = x; + y = f16.getBinary(); + if (y < last) + { + Serial.print("| "); + Serial.print(x); + Serial.print(" | "); + Serial.print(y, HEX); + Serial.print(" | "); + Serial.print(last, HEX); + Serial.println(" |"); + } + } + stop = millis(); + Serial.println(); + Serial.print(" TIME: "); + Serial.println(stop - start); +} + + void test_2() { + Serial.println(__FUNCTION__); start = millis(); for (uint32_t x = 0x0001; x < 0x7C01; x++) { @@ -64,7 +97,8 @@ void test_2() void test_1() { - // POSITIVE NUMBERS + Serial.println(__FUNCTION__); + // POSITIVE NUMBERS prev = 0; errors = 0; start = millis(); @@ -76,7 +110,7 @@ void test_1() Serial.print('\t'); float current = f16.toDouble(); Serial.print(current, 8); - if (prev > current) // numbers should be increasing. + if (prev > current) // numbers should be increasing. { Serial.print("\t\tERROR"); errors++; @@ -94,7 +128,7 @@ void test_1() Serial.println(); - // NEGATIVE NUMBERS + // NEGATIVE NUMBERS prev = 0; errors = 0; start = millis(); @@ -106,7 +140,7 @@ void test_1() Serial.print('\t'); float current = f16.toDouble(); Serial.print(current, 8); - if (prev < current) // negative numbers should be decreasing. + if (prev < current) // negative numbers should be decreasing. { Serial.print("\t\tERROR"); errors++; @@ -129,4 +163,4 @@ void test_1() -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/examples/float16_test_all_2/float16_test_all_2.ino b/examples/float16_test_all_2/float16_test_all_2.ino new file mode 100644 index 0000000..b40c13d --- /dev/null +++ b/examples/float16_test_all_2/float16_test_all_2.ino @@ -0,0 +1,113 @@ +// +// FILE: float16_test_all_2.ino +// AUTHOR: alecelular, Rob Tillaart +// PURPOSE: test float16 +// URL: https://github.com/RobTillaart/float16 +// URL: https://github.com/RobTillaart/float16/issues/10 + + +#include "float16.h" + +// issue 10 detected an Error -> 32760 / 32767 + +float16 f16; + + +void setup() +{ + delay(500); + Serial.begin(115200); + while (!Serial) delay(1); + + Serial.println(); + Serial.println(__FILE__); + Serial.print("FLOAT16_LIB_VERSION: "); + Serial.println(FLOAT16_LIB_VERSION); + + f16.setDecimals(6); + + test_all(); + + Serial.println("\ndone"); +} + + +void loop() +{ +} + + +void test_all() +{ + Serial.println(__FUNCTION__); + + // test all possible positive patterns + // test both the conversion to and from float. + for (uint32_t x = 0x0000; x < 0x7C01; x++) + { + f16.setBinary(x); + float16 f17 = f16.toDouble(); + + // internal format should be equal. Except for -0 and 0. + if (x - f17.getBinary() != 0) + { + Serial.print(f16.toDouble(), 10); + Serial.print("\t"); + Serial.print(f16.getBinary(), HEX); + Serial.print("\t"); + Serial.print(f17.getBinary(), HEX); + Serial.print("\t"); + Serial.print(x - f17.getBinary(), HEX); + Serial.println(); + } + } + Serial.println(); + + + // test all possible negative patterns + for (uint32_t x = 0x8000; x < 0xFC01; x++) + { + f16.setBinary(x); + float16 f17 = f16.toDouble(); + + if (x - f17.getBinary() != 0) + { + Serial.print(f16.toDouble(), 10); + Serial.print("\t"); + Serial.print(f16.getBinary(), HEX); + Serial.print("\t"); + Serial.print(f17.getBinary(), HEX); + Serial.print("\t"); + Serial.print(x - f17.getBinary(), HEX); + Serial.println(); + } + } + Serial.println(); + +} + + +void test_0() +{ + Serial.println(__FUNCTION__); + for (uint32_t x = 32750; x < 32770; x++) + // for (uint32_t x = 8175; x < 8205; x++) + { + f16 = x; + Serial.print(x); + Serial.print("\t"); + Serial.print(f16); + Serial.print("\t"); + Serial.print(f16.toDouble(), 2); + Serial.print("\t"); + Serial.println(); + yield(); + } + + f16.setBinary(0x7800); + Serial.print(f16.toDouble(), 2); + Serial.println(); +} + + +// -- END OF FILE -- diff --git a/examples/float16_test_array/float16_test_array.ino b/examples/float16_test_array/float16_test_array.ino index ca5e4c5..11b9a7d 100644 --- a/examples/float16_test_array/float16_test_array.ino +++ b/examples/float16_test_array/float16_test_array.ino @@ -2,16 +2,15 @@ // FILE: float16_test_array.ino // AUTHOR: Rob Tillaart // PURPOSE: test float16 -// DATE: 2015-03-11 // URL: https://github.com/RobTillaart/float16 -// -// show different storage needs + +// show different storage needs #include "float16.h" -float16 temperature[10]; // pointers + object are stored. -uint16_t temp2[10]; // only raw data is stored. +float16 temperature[10]; // pointers + object are stored. +uint16_t temp2[10]; // only raw data is stored. void setup() @@ -24,7 +23,7 @@ void setup() Serial.println(); - // simulate temperature sensor with random numbers + // simulate temperature sensor with random numbers for (uint32_t n = 0; n < 10; n++) { temperature[n] = (random(1000) - 300) * 0.01; @@ -77,4 +76,4 @@ void loop() } -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/examples/float16_test_negative/float16_test_negative.ino b/examples/float16_test_negative/float16_test_negative.ino index 86718d2..e931305 100644 --- a/examples/float16_test_negative/float16_test_negative.ino +++ b/examples/float16_test_negative/float16_test_negative.ino @@ -2,9 +2,8 @@ // FILE: float16_test_negative.ino // AUTHOR: Rob Tillaart // PURPOSE: test float16 -// DATE: 2021-11-26 // URL: https://github.com/RobTillaart/float16 -// + #include "float16.h" @@ -36,4 +35,4 @@ void loop() } -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/examples/float16_test_performance/float16_test_performance.ino b/examples/float16_test_performance/float16_test_performance.ino index 8677f5a..2719221 100644 --- a/examples/float16_test_performance/float16_test_performance.ino +++ b/examples/float16_test_performance/float16_test_performance.ino @@ -2,11 +2,8 @@ // FILE: float16_test_performance.ino // AUTHOR: Rob Tillaart // PURPOSE: test float16 -// DATE: 2021-11-26 // URL: https://github.com/RobTillaart/float16 -// -// TO ELABORATE #include "float16.h" @@ -187,4 +184,4 @@ void loop() } -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/examples/float16_test_performance/performance_0.2.0.txt b/examples/float16_test_performance/performance_0.2.0.txt new file mode 100644 index 0000000..f0a6944 --- /dev/null +++ b/examples/float16_test_performance/performance_0.2.0.txt @@ -0,0 +1,53 @@ + +// +// test: UNO +// IDE: 1.8.19 +// + +FLOAT16_LIB_VERSION: 0.2.0 + +CONSTRUCTORS +Constructor: 28 +a = b: 8 + +CONVERSION +toDouble(): 360 + +COMPARE +compare == : 4 +compare != : 4 +compare < : 4 +compare <= : 4 +compare >= : 4 +compare > : 4 + +MATH I +math + : 752 +math - : 692 +math * : 692 +math / : 684 + +MATH II +math += : 760 +math -= : 692 +math *= : 692 +math /= : 708 + +17.8125 +MATH III - negation +negation : 4 + +-17.8125 + +done + + +------------------------------------------ + +// +// test: RP2040 +// IDE: 1.8.13 +// + + +------------------------------------------- \ No newline at end of file diff --git a/examples/float16_test_powers2/float16_test_powers2.ino b/examples/float16_test_powers2/float16_test_powers2.ino index 7b2c407..c35925a 100644 --- a/examples/float16_test_powers2/float16_test_powers2.ino +++ b/examples/float16_test_powers2/float16_test_powers2.ino @@ -2,9 +2,7 @@ // FILE: float16_test_powers2.ino // AUTHOR: Rob Tillaart // PURPOSE: test float16 -// DATE: 2015-03-11 // URL: https://github.com/RobTillaart/float16 -// #include "float16.h" diff --git a/examples/float16_test_special/float16_test_special.ino b/examples/float16_test_special/float16_test_special.ino index 872777f..4344a2e 100644 --- a/examples/float16_test_special/float16_test_special.ino +++ b/examples/float16_test_special/float16_test_special.ino @@ -2,11 +2,10 @@ // FILE: float16_test_special.ino // AUTHOR: Rob Tillaart // PURPOSE: test float16 -// DATE: 2021-11-26 // URL: https://github.com/RobTillaart/float16 -// test special values ... -// https://github.com/RobTillaart/float16/issues/2 +// test special values ... +// https://github.com/RobTillaart/float16/issues/2 #include "float16.h" @@ -20,6 +19,7 @@ uint16_t value[32] = 0x4400, 0x4C00, 0x5400, 0x5C00, 0x6400, 0x6C00, 0x7400, 0x7C00 }; + float16 f16; @@ -68,4 +68,4 @@ void loop() } -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/float16.cpp b/float16.cpp index 4dd8da5..b5f1473 100644 --- a/float16.cpp +++ b/float16.cpp @@ -1,7 +1,7 @@ // // FILE: float16.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.8 +// VERSION: 0.2.0 // PURPOSE: library for Float16s for Arduino // URL: http://en.wikipedia.org/wiki/Half-precision_floating-point_format @@ -191,24 +191,19 @@ float float16::f16tof32(uint16_t _value) const else return NAN; } - // SUBNORMAL/NORMAL - if (exp == 0) f = 0; - else f = 1; - - // PROCESS MANTISSE - for (int i = 9; i >= 0; i--) - { - f *= 2; - if (man & (1 << i)) f = f + 1; - } - f = f * pow(2.0, exp - 25); - if (exp == 0) + // NORMAL + if (exp > 0) { - f = f * pow(2.0, -13); // 5.96046447754e-8; + f = pow(2.0, exp - 15) * (1 + man * 0.0009765625); + return sgn ? -f : f; } + // SUBNORMAL + // exp == 0; + f = pow(2.0, -24) * man; return sgn ? -f : f; } + uint16_t float16::f32tof16(float f) const { uint32_t t = *(uint32_t *) &f; @@ -217,50 +212,76 @@ uint16_t float16::f32tof16(float f) const int16_t exp = (t & 0x7F800000) >> 23; bool sgn = (t & 0x80000000); +// Serial.print("BEFOR:\t "); +// Serial.print(sgn, HEX); +// Serial.print(" "); +// Serial.print(man, HEX); +// Serial.print(" "); +// Serial.println(exp, HEX); + // handle 0 if ((t & 0x7FFFFFFF) == 0) { return sgn ? 0x8000 : 0x0000; } + // denormalized float32 does not fit in float16 if (exp == 0x00) { return sgn ? 0x8000 : 0x0000; } - // handle infinity & NAN + + // handle INF and NAN == infinity and not a number if (exp == 0x00FF) { if (man) return 0xFE00; // NAN return sgn ? 0xFC00 : 0x7C00; // -INF : INF } - // normal numbers + // rescale exponent exp = exp - 127 + 15; - // overflow does not fit => INF + + // overflow does not fit => INF (infinity) if (exp > 30) { return sgn ? 0xFC00 : 0x7C00; // -INF : INF } - // subnormal numbers - if (exp < -38) + + // subnormal numbers out of range => 0. + if (exp < -9) { return sgn ? 0x8000 : 0x0000; // -0 or 0 ? just 0 ? } - if (exp <= 0) // subnormal + + // subnormal numbers + if (exp <= 0) { - man >>= (exp + 14); - // rounding - man++; - man >>= 1; + exp = 0; + man = abs(f) * 16777216; // pow(2.0, 24); if (sgn) return 0x8000 | man; return man; } - // normal - // TODO rounding - exp <<= 10; + + // normal numbers + // rounding man++; man >>= 1; + // correction mantissa overflow issue #10 + if (man == 0x0400) + { + exp++; + man = 0; + } + exp <<= 10; + +// Serial.print("AFTER:\t "); +// Serial.print(sgn, HEX); +// Serial.print(" "); +// Serial.print(man, HEX); +// Serial.print(" "); +// Serial.println(exp, HEX); + if (sgn) return 0x8000 | exp | man; return exp | man; } diff --git a/float16.h b/float16.h index fd30b52..ae87a53 100644 --- a/float16.h +++ b/float16.h @@ -2,7 +2,7 @@ // // FILE: float16.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.8 +// VERSION: 0.2.0 // PURPOSE: Arduino library to implement float16 data type. // half-precision floating point format, // used for efficient storage and transport. @@ -11,7 +11,7 @@ #include "Arduino.h" -#define FLOAT16_LIB_VERSION (F("0.1.8")) +#define FLOAT16_LIB_VERSION (F("0.2.0")) class float16: public Printable @@ -34,22 +34,22 @@ class float16: public Printable uint8_t getDecimals() { return _decimals; }; // equalities - bool operator == (const float16& f); - bool operator != (const float16& f); + bool operator == (const float16& f); + bool operator != (const float16& f); - bool operator > (const float16& f); - bool operator >= (const float16& f); - bool operator < (const float16& f); - bool operator <= (const float16& f); + bool operator > (const float16& f); + bool operator >= (const float16& f); + bool operator < (const float16& f); + bool operator <= (const float16& f); // negation - float16 operator - (); + float16 operator - (); // basic math - float16 operator + (const float16& f); - float16 operator - (const float16& f); - float16 operator * (const float16& f); - float16 operator / (const float16& f); + float16 operator + (const float16& f); + float16 operator - (const float16& f); + float16 operator * (const float16& f); + float16 operator / (const float16& f); float16& operator += (const float16& f); float16& operator -= (const float16& f); @@ -57,14 +57,14 @@ class float16: public Printable float16& operator /= (const float16& f); // math helper functions - int sign(); // 1 = positive 0 = zero -1 = negative. - bool isZero(); - bool isNaN(); - bool isInf(); + int sign(); // 1 = positive 0 = zero -1 = negative. + bool isZero(); + bool isNaN(); + bool isInf(); // CORE CONVERSION - // should be private but for testing... + // should be private, needed for testing. float f16tof32(uint16_t) const; uint16_t f32tof16(float) const; diff --git a/library.json b/library.json index 1e17842..576e9fd 100644 --- a/library.json +++ b/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/float16.git" }, - "version": "0.1.8", + "version": "0.2.0", "license": "MIT", "frameworks": "*", "platforms": "*", diff --git a/library.properties b/library.properties index ff3eee0..1d4615f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=float16 -version=0.1.8 +version=0.2.0 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library to implement float16 data type. diff --git a/test/unit_test_001.cpp b/test/unit_test_001.cpp index 22dad87..1387bb4 100644 --- a/test/unit_test_001.cpp +++ b/test/unit_test_001.cpp @@ -32,7 +32,6 @@ #include -#include "Arduino.h" #include "float16.h" @@ -106,7 +105,7 @@ unittest(test_compare_equal) } -unittest(test_compare_1nequal) +unittest(test_compare_inequal) { float16 a(1); float16 b(1); @@ -170,7 +169,37 @@ unittest(test_printable) } +unittest(test_all_values) +{ + float16 a; + float16 b; + + // test both the conversion to and from float. + // internal format should be equal. Except for -0 and 0. + + fprintf(stderr, "test all positive patterns\n"); + for (uint32_t x = 0x0000; x < 0x7C01; x++) + { + a.setBinary(x); + b = a.toDouble(); + if (x != b.getBinary()) // assert would give 65K lines output! + { + fprintf(stderr, "fail at %d\n", x); + } + } + fprintf(stderr, "test all negative patterns\n"); + for (uint32_t x = 0x8000; x < 0xFC01; x++) + { + a.setBinary(x); + b = a.toDouble(); + if (x != b.getBinary()) + { + fprintf(stderr, "fail at %d\n", x); + } + } +} + unittest_main() -// -- END OF FILE -- +// -- END OF FILE --