From d9150d4faab758093428dc15c7569c2b401bd975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 14 Feb 2018 16:00:44 +0100 Subject: [PATCH] [poincare] Integer: fix approximate, round instead of truncate integers to closest float --- poincare/include/poincare/ieee754.h | 6 ++++ poincare/src/integer.cpp | 5 ---- poincare/test/integer.cpp | 44 +++++++++++++++++++++++------ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/poincare/include/poincare/ieee754.h b/poincare/include/poincare/ieee754.h index 6c909f5fb..275d9c0c3 100644 --- a/poincare/include/poincare/ieee754.h +++ b/poincare/include/poincare/ieee754.h @@ -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) { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 8e8d47493..5046e7f79 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -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::buildFloat(sign, exponent, mantissa); diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index dc5e64360..2382ca25a 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -115,15 +115,43 @@ QUIZ_CASE(poincare_integer_divide) { } template -void assert_integer_evals_to(int i, T result) { - assert(Integer(i).approximate() == result); +void assert_integer_evals_to(const char * i, bool negative, T result) { + assert(Integer(i, negative).approximate() == 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); }