From b5c06fd22bf8fdbbf6ac515844ebf27ca81c786e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 16:17:06 +0200 Subject: [PATCH] [poincare] Implement Integer::Division in Z (relative integers) Change-Id: I72ccd4afd8188b0389b1f32863ecb1af59581c04 --- poincare/include/poincare/integer.h | 1 + poincare/src/integer.cpp | 59 ++++++++++++++++++++++------- poincare/test/integer.cpp | 6 +++ 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 20e2c235e..025c93e8a 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -59,6 +59,7 @@ private: static int8_t ucmp(const Integer & a, const Integer & b); // -1, 0, or 1 static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative); static Integer addition(const Integer & a, const Integer & b, bool inverseBNegative); + static IntegerDivision udiv(const Integer & a, const Integer & b); ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index f49009459..4b04114bd 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -277,22 +277,35 @@ Integer Integer::Multiplication(const Integer & a, const Integer & b) { } IntegerDivision Integer::Division(const Integer & numerator, const Integer & denominator) { - // FIXME: First, test if denominator is zero. - - if (numerator.isLowerThan(denominator)) { - IntegerDivision div = {.quotient = 0, .remainder = Integer::Addition(numerator, Integer(0))}; - // FIXME: This is a ugly way to bypass creating a copy constructor! - return div; + if (!numerator.isNegative() && !denominator.isNegative()) { + return udiv(numerator, denominator); } - - // Recursive case - IntegerDivision div = Division(numerator, Integer::Addition(denominator, denominator)); - div.quotient = Integer::Addition(div.quotient, div.quotient); - if (!(div.remainder.isLowerThan(denominator))) { - div.remainder = Integer::Subtraction(div.remainder, denominator); - div.quotient = Integer::Addition(div.quotient, Integer(1)); + Integer absNumerator = numerator; + absNumerator.setNegative(false); + Integer absDenominator = denominator; + absDenominator.setNegative(false); + IntegerDivision usignedDiv = udiv(absNumerator, absDenominator); + if (usignedDiv.remainder.isEqualTo(Integer(0))) { + if (!numerator.isNegative() || !denominator.isNegative()) { + usignedDiv.quotient.setNegative(true); + } + return usignedDiv; } - return div; + if (numerator.isNegative()) { + if (denominator.isNegative()) { + usignedDiv.remainder.setNegative(true); + usignedDiv.quotient = Addition(usignedDiv.quotient, Integer(1)); + usignedDiv.remainder = Integer::Subtraction(usignedDiv.remainder, denominator); + } else { + usignedDiv.quotient.setNegative(true); + usignedDiv.quotient = Subtraction(usignedDiv.quotient, Integer(1)); + usignedDiv.remainder = Integer::Subtraction(denominator, usignedDiv.remainder); + } + } else { + assert(denominator.isNegative()); + usignedDiv.quotient.setNegative(true); + } + return usignedDiv; } // Private methods @@ -379,6 +392,24 @@ Integer Integer::addition(const Integer & a, const Integer & b, bool inverseBNeg } } +IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denominator) { + assert(!numerator.isNegative() && !denominator.isNegative()); + // FIXME: First, test if denominator is zero. + if (numerator.isLowerThan(denominator)) { + IntegerDivision div = {.quotient = 0, .remainder = numerator}; + return div; + } + + // Recursive case + IntegerDivision div = Division(numerator, Integer::Addition(denominator, denominator)); + div.quotient = Integer::Addition(div.quotient, div.quotient); + if (!(div.remainder.isLowerThan(denominator))) { + div.remainder = Integer::Subtraction(div.remainder, denominator); + div.quotient = Integer::Addition(div.quotient, Integer(1)); + } + return div; +} + int Integer::identifier() const { assert(m_numberOfDigits > 0); int sign = m_negative ? -1 : 1; diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index af4265fd8..2ebe2a7b8 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -52,6 +52,12 @@ QUIZ_CASE(poincare_integer_divide) { assert(Integer::Division(Integer(8), Integer(4)).quotient.isEqualTo(Integer(2)) && Integer::Division(Integer(8), Integer(4)).remainder.isEqualTo(Integer(0))); assert(Integer::Division(Integer("3293920983030066"), Integer(38928)).quotient.isEqualTo(Integer("84615726033")) && Integer::Division(Integer("3293920983030066"), Integer(38928)).remainder.isEqualTo(Integer(17442))); assert(Integer::Division(Integer("3293920983030066"), Integer("389282362616")).quotient.isEqualTo(Integer(8461)) && Integer::Division(Integer("3293920983030066"), Integer("389282362616")).remainder.isEqualTo(Integer("202912936090"))); + assert(Integer::Division(Integer("-18940566"), Integer("499030")).quotient.isEqualTo(Integer(-38)) && Integer::Division(Integer("-18940566"), Integer("499030")).remainder.isEqualTo(Integer("22574"))); + assert(Integer::Division(Integer("234567909876"), Integer("-234567898")).quotient.isEqualTo(Integer(-1000)) && Integer::Division(Integer("234567909876"), Integer("-234567898")).remainder.isEqualTo(Integer("11876"))); + assert(Integer::Division(Integer("-567"), Integer("-12")).quotient.isEqualTo(Integer(48)) && Integer::Division(Integer("-567"), Integer("-12")).remainder.isEqualTo(Integer("9"))); + assert(Integer::Division(Integer("-576"), Integer("-12")).quotient.isEqualTo(Integer(48)) && Integer::Division(Integer("-576"), Integer("-12")).remainder.isEqualTo(Integer("0"))); + assert(Integer::Division(Integer("576"), Integer("-12")).quotient.isEqualTo(Integer(-48)) && Integer::Division(Integer("576"), Integer("-12")).remainder.isEqualTo(Integer("0"))); + assert(Integer::Division(Integer("-576"), Integer("12")).quotient.isEqualTo(Integer(-48)) && Integer::Division(Integer("-576"), Integer("12")).remainder.isEqualTo(Integer("0"))); } template