mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[poincare] IEEE754: add methods to find the next and the previous
IEEE754 exactly representable float/double
This commit is contained in:
@@ -165,6 +165,7 @@ tests_src += $(addprefix poincare/test/,\
|
||||
function_solver.cpp\
|
||||
helper.cpp\
|
||||
helpers.cpp\
|
||||
ieee754.cpp\
|
||||
integer.cpp\
|
||||
layout.cpp\
|
||||
layout_cursor.cpp\
|
||||
|
||||
@@ -28,7 +28,6 @@ public:
|
||||
assert(k_totalNumberOfBits == 8*sizeof(T));
|
||||
return k_totalNumberOfBits;
|
||||
}
|
||||
|
||||
static T buildFloat(bool sign, uint16_t exponent, uint64_t mantissa) {
|
||||
static uint64_t oneOnMantissaBits = ((uint64_t)1 << k_mantissaNbBits)-1;
|
||||
uint_float u;
|
||||
@@ -74,11 +73,41 @@ public:
|
||||
}
|
||||
return exponentBase10;
|
||||
}
|
||||
static T next(T f) {
|
||||
return nextOrPrevious(f, true);
|
||||
}
|
||||
|
||||
static T previous(T f) {
|
||||
return nextOrPrevious(f, false);
|
||||
}
|
||||
|
||||
private:
|
||||
union uint_float {
|
||||
uint64_t ui;
|
||||
T f;
|
||||
};
|
||||
static T nextOrPrevious(T f, bool isNext) {
|
||||
if (std::isinf(f) || std::isnan(f)) {
|
||||
return f;
|
||||
}
|
||||
uint_float u;
|
||||
u.ui = 0;
|
||||
u.f = f;
|
||||
uint64_t oneBitOnSignBit = (uint64_t)1 << (k_exponentNbBits + k_mantissaNbBits);
|
||||
if ((isNext && (u.ui & oneBitOnSignBit) > 0) // next: Negative float
|
||||
|| (!isNext && (u.ui & oneBitOnSignBit) == 0)) { // previous: Positive float
|
||||
if ((isNext && u.ui == oneBitOnSignBit) // next: -0.0
|
||||
|| (!isNext && u.ui == 0.0)) { // previous: 0.0
|
||||
u.ui = isNext ? 0 : oneBitOnSignBit;
|
||||
} else {
|
||||
u.ui -= 1;
|
||||
}
|
||||
} else { // next: Positive float, previous: Negative float
|
||||
u.ui += 1;
|
||||
}
|
||||
return u.f;
|
||||
}
|
||||
|
||||
constexpr static size_t k_signNbBits = 1;
|
||||
constexpr static size_t k_exponentNbBits = sizeof(T) == sizeof(float) ? 8 : 11;
|
||||
constexpr static size_t k_mantissaNbBits = sizeof(T) == sizeof(float) ? 23 : 52;
|
||||
|
||||
43
poincare/test/ieee754.cpp
Normal file
43
poincare/test/ieee754.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include <quiz.h>
|
||||
#include <poincare/ieee754.h>
|
||||
#include <string.h>
|
||||
#include <ion.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include "helper.h"
|
||||
|
||||
using namespace Poincare;
|
||||
|
||||
template<typename T>
|
||||
void assert_next_and_previous_IEEE754_is(T a, T b) {
|
||||
T next = IEEE754<T>::next(a);
|
||||
T previous = IEEE754<T>::previous(b);
|
||||
assert((std::isnan(next) && std::isnan(b)) || next == b);
|
||||
assert((std::isnan(previous) && std::isnan(a)) || previous == a);
|
||||
}
|
||||
|
||||
QUIZ_CASE(ieee754_next_and_previous) {
|
||||
assert_next_and_previous_IEEE754_is<float>(0.0f, 1.4E-45f);
|
||||
assert_next_and_previous_IEEE754_is<float>(INFINITY, INFINITY);
|
||||
assert_next_and_previous_IEEE754_is<float>(NAN, NAN);
|
||||
assert_next_and_previous_IEEE754_is<float>(2.2566837E-10f, 2.2566839E-10f);
|
||||
assert_next_and_previous_IEEE754_is<float>(-INFINITY, -INFINITY);
|
||||
assert_next_and_previous_IEEE754_is<float>(-0.0f, 0.0f);
|
||||
assert_next_and_previous_IEEE754_is<float>(-1.4E-45f, -0.0f);
|
||||
assert_next_and_previous_IEEE754_is<float>(-3.4359738E10f, -3.43597363E10f);
|
||||
assert(IEEE754<float>::next(3.4028235E38f) == INFINITY);
|
||||
assert(IEEE754<float>::previous(-3.4028235E38f) == -INFINITY);
|
||||
|
||||
assert_next_and_previous_IEEE754_is<double>(0.0f, 4.94065645841246544176568792868E-324);
|
||||
assert_next_and_previous_IEEE754_is<double>(INFINITY, INFINITY);
|
||||
assert_next_and_previous_IEEE754_is<double>(NAN, NAN);
|
||||
assert_next_and_previous_IEEE754_is<double>(1.936766735060658315512927142E-282, 1.93676673506065869777770528092E-282);
|
||||
assert_next_and_previous_IEEE754_is<double>(-INFINITY, -INFINITY);
|
||||
assert_next_and_previous_IEEE754_is<double>(-0.0, 0.0);
|
||||
assert_next_and_previous_IEEE754_is<double>(-4.94065645841246544176568792868E-324, -0.0);
|
||||
assert_next_and_previous_IEEE754_is<double>(-1.38737906372912431085182213247E201, -1.38737906372912403890916981028E201);
|
||||
assert(IEEE754<double>::next(1.79769313486231570814527423732E308) == INFINITY);
|
||||
assert(IEEE754<double>::previous(-1.79769313486231570814527423732E308) == -INFINITY);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user