[poincare] Integer: fix approximate, round instead of truncate integers

to closest float
This commit is contained in:
Émilie Feral
2018-02-14 16:00:44 +01:00
committed by EmilieNumworks
parent 97df52d0c5
commit d9150d4faa
3 changed files with 42 additions and 13 deletions

View File

@@ -34,6 +34,12 @@ public:
u.ui |= ((uint64_t)sign << (size()-k_signNbBits));
u.ui |= ((uint64_t)exponent << k_mantissaNbBits);
u.ui |= ((uint64_t)mantissa >> (size()-k_mantissaNbBits-1) & oneOnMantissaBits);
/* So far, we just cast the Integer in float. To round it to the closest
* float, we increment the mantissa (and sometimes the exponent if the
* mantissa was full of 1) if the next mantissa bit is 1. */
if (((uint64_t)mantissa >> (size()-k_mantissaNbBits-2)) & 1) {
u.ui += 1;
}
return u.f;
}
static int exponent(T f) {

View File

@@ -531,11 +531,6 @@ T Integer::approximate() const {
}
digitIndex++;
}
// TODO: Here, we just cast the Integer in float(double). We should round it
// to the closest float(double). To do so, we should keep a additional bit
// at the end of the mantissa and add it to the mantissa; do not forget to
// shift the mantissa if the rounding increase the length in bits of the
// mantissa.
T result = IEEE754<T>::buildFloat(sign, exponent, mantissa);

View File

@@ -115,15 +115,43 @@ QUIZ_CASE(poincare_integer_divide) {
}
template<typename T>
void assert_integer_evals_to(int i, T result) {
assert(Integer(i).approximate<T>() == result);
void assert_integer_evals_to(const char * i, bool negative, T result) {
assert(Integer(i, negative).approximate<T>() == result);
}
QUIZ_CASE(poincare_integer_evaluate) {
assert_integer_evals_to(1, 1.0f);
assert_integer_evals_to(12345678, 12345678.0);
assert_integer_evals_to(0, 0.0f);
assert_integer_evals_to(-0, 0.0);
assert_integer_evals_to(-1, -1.0f);
assert_integer_evals_to(12345678, 12345678.0);
assert_integer_evals_to("1", false, 1.0f);
assert_integer_evals_to("1", false, 1.0);
assert_integer_evals_to("12345678", false, 12345678.0f);
assert_integer_evals_to("12345678", false, 12345678.0);
assert_integer_evals_to("0", false, 0.0f);
assert_integer_evals_to("0", false, 0.0);
assert_integer_evals_to("0", true, 0.0f);
assert_integer_evals_to("0", true, 0.0);
assert_integer_evals_to("1", true, -1.0f);
assert_integer_evals_to("1", true, -1.0);
assert_integer_evals_to("12345678", false, 12345678.0f);
assert_integer_evals_to("12345678", false, 12345678.0);
assert_integer_evals_to("4294967295", false, 4294967295.0f);
assert_integer_evals_to("4294967295", false, 4294967295.0);
assert_integer_evals_to("4294967296", true, -4294967296.0f);
assert_integer_evals_to("4294967296", true, -4294967296.0);
assert_integer_evals_to("2147483648", false, 2147483648.0f);
assert_integer_evals_to("2147483648", false, 2147483648.0);
assert_integer_evals_to("18446744073709551615", true, -18446744073709551615.0f);
assert_integer_evals_to("18446744073709551615", true, -18446744073709551615.0);
assert_integer_evals_to("18446744073709551616", true, -18446744073709551616.0f);
assert_integer_evals_to("18446744073709551616", true, -18446744073709551616.0);
assert_integer_evals_to("92233720372036854775808", false, 92233720372036854775808.0f);
assert_integer_evals_to("92233720372036854775808", false, 92233720372036854775808.0);
assert_integer_evals_to("134217720", false, 134217720.0f);
assert_integer_evals_to("134217720", false, 134217720.0);
assert_integer_evals_to("67108864", false, 67108864.0f);
assert_integer_evals_to("67108864", false, 67108864.0);
assert_integer_evals_to("33554432", false, 33554432.0f);
assert_integer_evals_to("33554432", false, 33554432.0);
assert_integer_evals_to("2", false, 2.0f);
assert_integer_evals_to("2", false, 2.0);
assert_integer_evals_to("4", false, 4.0f);
assert_integer_evals_to("4", false, 4.0);
}