mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Implement Integer::Division in Z (relative integers)
Change-Id: I72ccd4afd8188b0389b1f32863ecb1af59581c04
This commit is contained in:
@@ -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<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override;
|
||||
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<typename T>
|
||||
|
||||
Reference in New Issue
Block a user