mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare] Rational: make a method 'isInteger'
This commit is contained in:
@@ -16,6 +16,7 @@ public:
|
||||
Integer denominator() const;
|
||||
bool isNegative() const { return m_negative; }
|
||||
void setNegative(bool negative) { m_negative = negative; }
|
||||
bool isInteger() const { return denominator().isOne(); }
|
||||
|
||||
// TreeNode
|
||||
size_t size() const override;
|
||||
@@ -43,11 +44,11 @@ public:
|
||||
|
||||
// Basic test
|
||||
bool isZero() const { return unsignedNumerator().isZero(); }
|
||||
bool isOne() const { return signedNumerator().isOne() && denominator().isOne(); }
|
||||
bool isMinusOne() const { return signedNumerator().isMinusOne() && denominator().isOne(); }
|
||||
bool isOne() const { return signedNumerator().isOne() && isInteger(); }
|
||||
bool isMinusOne() const { return signedNumerator().isMinusOne() && isInteger(); }
|
||||
bool isHalf() const { return signedNumerator().isOne() && denominator().isTwo(); }
|
||||
bool isMinusHalf() const { return signedNumerator().isMinusOne() && denominator().isTwo(); }
|
||||
bool isTen() const { return signedNumerator().isTen() && denominator().isOne(); }
|
||||
bool isTen() const { return signedNumerator().isTen() && isInteger(); }
|
||||
|
||||
static int NaturalOrder(const RationalNode * i, const RationalNode * j);
|
||||
private:
|
||||
@@ -92,6 +93,7 @@ public:
|
||||
bool isMinusHalf() const { return node()->isMinusHalf(); }
|
||||
bool isTen() const { return node()->isTen(); }
|
||||
bool numeratorOrDenominatorIsInfinity() const;
|
||||
bool isInteger() const { return node()->isInteger(); }
|
||||
|
||||
// Arithmetic
|
||||
/* Warning: when using this function, always assert that the result does not
|
||||
|
||||
@@ -70,13 +70,13 @@ Expression BinomialCoefficient::shallowReduce(Context * context) {
|
||||
|
||||
if (c0.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r0 = static_cast<Rational&>(c0);
|
||||
if (!r0.integerDenominator().isOne() || r0.isNegative()) {
|
||||
if (!r0.isInteger() || r0.isNegative()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
if (c1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational&>(c1);
|
||||
if (!r1.integerDenominator().isOne() || r1.isNegative()) {
|
||||
if (!r1.isInteger() || r1.isNegative()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ Expression ConfidenceInterval::shallowReduce(ExpressionNode::ReductionContext re
|
||||
}
|
||||
if (c1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational&>(c1);
|
||||
if (!r1.integerDenominator().isOne() || r1.signedIntegerNumerator().isNegative()) {
|
||||
if (!r1.isInteger() || r1.signedIntegerNumerator().isNegative()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ bool DivisionNode::childNeedsSystemParenthesesAtSerialization(const TreeNode * c
|
||||
if (static_cast<const ExpressionNode *>(child)->isNumber() && Number(static_cast<const NumberNode *>(child)).sign() == Sign::Negative) {
|
||||
return true;
|
||||
}
|
||||
if (static_cast<const ExpressionNode *>(child)->type() == Type::Rational && !static_cast<const RationalNode *>(child)->denominator().isOne()) {
|
||||
if (static_cast<const ExpressionNode *>(child)->type() == Type::Rational && !static_cast<const RationalNode *>(child)->isInteger()) {
|
||||
return true;
|
||||
}
|
||||
Type types[] = {Type::Subtraction, Type::Opposite, Type::MultiplicationExplicite, Type::Division, Type::Addition};
|
||||
|
||||
@@ -50,13 +50,13 @@ Expression DivisionQuotient::shallowReduce(Context * context) {
|
||||
}
|
||||
if (c0.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r0 = static_cast<Rational &>(c0);
|
||||
if (!r0.integerDenominator().isOne()) {
|
||||
if (!r0.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
if (c1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational &>(c1);
|
||||
if (!r1.integerDenominator().isOne()) {
|
||||
if (!r1.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,13 +51,13 @@ Expression DivisionRemainder::shallowReduce(Context * context) {
|
||||
}
|
||||
if (c0.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r0 = static_cast<Rational &>(c0);
|
||||
if (!r0.integerDenominator().isOne()) {
|
||||
if (!r0.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
if (c1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational &>(c1);
|
||||
if (!r1.integerDenominator().isOne()) {
|
||||
if (!r1.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ Expression Factor::shallowBeautify(ExpressionNode::ReductionContext reductionCon
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
Expression result = numeratorDecomp.squashUnaryHierarchyInPlace();
|
||||
if (!r.integerDenominator().isOne()) {
|
||||
if (!r.isInteger()) {
|
||||
MultiplicationExplicite denominatorDecomp = createMultiplicationOfIntegerPrimeDecomposition(r.integerDenominator(), reductionContext.context(), reductionContext.complexFormat(), reductionContext.angleUnit());
|
||||
if (denominatorDecomp.numberOfChildren() == 0) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
|
||||
@@ -35,7 +35,7 @@ bool FactorialNode::childNeedsSystemParenthesesAtSerialization(const TreeNode *
|
||||
* --- ! ---> [2/3]!
|
||||
* 3
|
||||
*/
|
||||
if (static_cast<const ExpressionNode *>(child)->type() == Type::Rational && !static_cast<const RationalNode *>(child)->denominator().isOne()) {
|
||||
if (static_cast<const ExpressionNode *>(child)->type() == Type::Rational && !static_cast<const RationalNode *>(child)->isInteger()) {
|
||||
return true;
|
||||
}
|
||||
Type types[] = {Type::Division, Type::Power};
|
||||
@@ -100,7 +100,7 @@ Expression Factorial::shallowReduce(ExpressionNode::ReductionContext reductionCo
|
||||
}
|
||||
if (c.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r = c.convert<Rational>();
|
||||
if (!r.integerDenominator().isOne() || r.sign() == ExpressionNode::Sign::Negative) {
|
||||
if (!r.isInteger() || r.sign() == ExpressionNode::Sign::Negative) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
if (Integer(k_maxOperandValue).isLowerThan(r.unsignedIntegerNumerator())) {
|
||||
|
||||
@@ -64,13 +64,13 @@ Expression GreatCommonDivisor::shallowReduce(Context * context) {
|
||||
}
|
||||
if (c0.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r0 = static_cast<Rational &>(c0);
|
||||
if (!r0.integerDenominator().isOne()) {
|
||||
if (!r0.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
if (c1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational&>(c1);
|
||||
if (!r1.integerDenominator().isOne()) {
|
||||
if (!r1.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,13 +68,13 @@ Expression LeastCommonMultiple::shallowReduce(Context * context) {
|
||||
}
|
||||
if (c0.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r0 = static_cast<Rational &>(c0);
|
||||
if (!r0.integerDenominator().isOne()) {
|
||||
if (!r0.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
if (c1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational &>(c1);
|
||||
if (!r1.integerDenominator().isOne()) {
|
||||
if (!r1.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ Expression Logarithm::shallowReduce(ExpressionNode::ReductionContext reductionCo
|
||||
Rational r = static_cast<Rational &>(c);
|
||||
Addition a = Addition::Builder();
|
||||
// if the log base is Integer: log_b(r) = c + log_b(r') with r = b^c*r'
|
||||
if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert<Rational>().integerDenominator().isOne()) {
|
||||
if (childAtIndex(1).type() == ExpressionNode::Type::Rational && childAtIndex(1).convert<Rational>().isInteger()) {
|
||||
Integer b = childAtIndex(1).convert<Rational>().signedIntegerNumerator();
|
||||
Integer newNumerator = simplifyLogarithmIntegerBaseInteger(r.signedIntegerNumerator(), b, a, false);
|
||||
Integer newDenomitor = simplifyLogarithmIntegerBaseInteger(r.integerDenominator(), b, a, true);
|
||||
|
||||
@@ -537,8 +537,8 @@ void MultiplicationExplicite::addMissingFactors(Expression factor, Context * con
|
||||
* child, we replace it by its LCM with factor ; otherwise, we simply add
|
||||
* factor as a child. */
|
||||
if (numberOfChildren() > 0 && childAtIndex(0).type() == ExpressionNode::Type::Rational && factor.type() == ExpressionNode::Type::Rational) {
|
||||
assert(static_cast<Rational &>(factor).integerDenominator().isOne());
|
||||
assert(childAtIndex(0).convert<Rational>().integerDenominator().isOne());
|
||||
assert(static_cast<Rational &>(factor).isInteger());
|
||||
assert(childAtIndex(0).convert<Rational>().isInteger());
|
||||
Integer lcm = Arithmetic::LCM(static_cast<Rational &>(factor).unsignedIntegerNumerator(), childAtIndex(0).convert<Rational>().unsignedIntegerNumerator());
|
||||
if (lcm.isOverflow()) {
|
||||
addChildAtIndexInPlace(Rational::Builder(static_cast<Rational &>(factor).unsignedIntegerNumerator()), 1, numberOfChildren());
|
||||
@@ -669,7 +669,7 @@ Expression MultiplicationExplicite::mergeNegativePower(Context * context, Prefer
|
||||
* for instance, a^(-1)*b^(-c)*c = c*(a*b^c)^(-1) */
|
||||
MultiplicationExplicite m = MultiplicationExplicite::Builder();
|
||||
// Special case for rational p/q: if q != 1, q should be at denominator
|
||||
if (childAtIndex(0).type() == ExpressionNode::Type::Rational && !childAtIndex(0).convert<Rational>().integerDenominator().isOne()) {
|
||||
if (childAtIndex(0).type() == ExpressionNode::Type::Rational && !childAtIndex(0).convert<Rational>().isInteger()) {
|
||||
Rational r = childAtIndex(0).convert<Rational>();
|
||||
m.addChildAtIndexInPlace(Rational::Builder(r.integerDenominator()), 0, m.numberOfChildren());
|
||||
if (r.signedIntegerNumerator().isOne()) {
|
||||
|
||||
@@ -26,7 +26,7 @@ bool MultiplicationImpliciteNode::childNeedsSystemParenthesesAtSerialization(con
|
||||
* ---i --> [2/3]i
|
||||
* 3
|
||||
*/
|
||||
if (static_cast<const ExpressionNode *>(child)->type() == Type::Rational && !static_cast<const RationalNode *>(child)->denominator().isOne()) {
|
||||
if (static_cast<const ExpressionNode *>(child)->type() == Type::Rational && !static_cast<const RationalNode *>(child)->isInteger()) {
|
||||
return true;
|
||||
}
|
||||
// 2^{3}i --> [2^3]i
|
||||
|
||||
@@ -110,7 +110,7 @@ Number Number::Power(const Number & i, const Number & j) {
|
||||
return BinaryOperation(i, j,
|
||||
// Special case for Rational^Rational: we escape to Float if the index is not an Integer
|
||||
[](const Rational & i, const Rational & j) {
|
||||
if (!j.integerDenominator().isOne()) {
|
||||
if (!j.isInteger()) {
|
||||
// We return an overflown result to reach the escape case Float+Float
|
||||
return Rational::Builder(Integer::Overflow(false));
|
||||
}
|
||||
|
||||
@@ -64,13 +64,13 @@ Expression PermuteCoefficient::shallowReduce(Context * context) {
|
||||
}
|
||||
if (c0.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r0 = static_cast<Rational &>(c0);
|
||||
if (!r0.integerDenominator().isOne() || r0.sign() == ExpressionNode::Sign::Negative) {
|
||||
if (!r0.isInteger() || r0.sign() == ExpressionNode::Sign::Negative) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
if (c1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational &>(c1);
|
||||
if (!r1.integerDenominator().isOne() || r1.sign() == ExpressionNode::Sign::Negative) {
|
||||
if (!r1.isInteger() || r1.sign() == ExpressionNode::Sign::Negative) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ ExpressionNode::Sign PowerNode::sign(Context * context) const {
|
||||
}
|
||||
if (childAtIndex(0)->sign(context) == Sign::Negative && childAtIndex(1)->type() == ExpressionNode::Type::Rational) {
|
||||
RationalNode * r = static_cast<RationalNode *>(childAtIndex(1));
|
||||
if (r->denominator().isOne()) {
|
||||
if (r->isInteger()) {
|
||||
assert(!Integer::Division(r->signedNumerator(), Integer(2)).remainder.isOverflow());
|
||||
if (Integer::Division(r->signedNumerator(), Integer(2)).remainder.isZero()) {
|
||||
return Sign::Positive;
|
||||
@@ -67,7 +67,7 @@ int PowerNode::polynomialDegree(Context * context, const char * symbolName) cons
|
||||
}
|
||||
if (childAtIndex(1)->type() == ExpressionNode::Type::Rational) {
|
||||
RationalNode * r = static_cast<RationalNode *>(childAtIndex(1));
|
||||
if (!r->denominator().isOne() || Number(r).sign() == Sign::Negative) {
|
||||
if (!r->isInteger() || Number(r).sign() == Sign::Negative) {
|
||||
return -1;
|
||||
}
|
||||
Integer numeratorInt = r->signedNumerator();
|
||||
@@ -93,7 +93,7 @@ bool PowerNode::isReal(Context * context) const {
|
||||
if (base->isReal(context) &&
|
||||
index->isReal(context) &&
|
||||
(base->sign(context) == Sign::Positive ||
|
||||
(index->type() == ExpressionNode::Type::Rational && static_cast<RationalNode *>(index)->denominator().isOne()))) {
|
||||
(index->type() == ExpressionNode::Type::Rational && static_cast<RationalNode *>(index)->isInteger()))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -105,7 +105,7 @@ bool PowerNode::childNeedsUserParentheses(const Expression & child) const {
|
||||
* ^(2/3, 4) --> (2/3)^{4}
|
||||
*/
|
||||
if ((child.isNumber() && static_cast<const Number &>(child).sign() == Sign::Negative)
|
||||
|| (child.type() == Type::Rational && !static_cast<const Rational &>(child).integerDenominator().isOne())) {
|
||||
|| (child.type() == Type::Rational && !static_cast<const Rational &>(child).isInteger())) {
|
||||
return true;
|
||||
}
|
||||
// ^(2+3,4) --> (2+3)^{4}
|
||||
@@ -166,7 +166,7 @@ bool PowerNode::childNeedsSystemParenthesesAtSerialization(const TreeNode * chil
|
||||
if (static_cast<const ExpressionNode *>(child)->isNumber() && Number(static_cast<const NumberNode *>(child)).sign() == Sign::Negative) {
|
||||
return true;
|
||||
}
|
||||
if (static_cast<const ExpressionNode *>(child)->type() == Type::Rational && !static_cast<const RationalNode *>(child)->denominator().isOne()) {
|
||||
if (static_cast<const ExpressionNode *>(child)->type() == Type::Rational && !static_cast<const RationalNode *>(child)->isInteger()) {
|
||||
return true;
|
||||
}
|
||||
Type types[] = {Type::Power, Type::Subtraction, Type::Opposite, Type::MultiplicationExplicite, Type::MultiplicationImplicite, Type::Division, Type::Addition};
|
||||
@@ -271,7 +271,7 @@ int Power::getPolynomialCoefficients(Context * context, const char * symbolName,
|
||||
&& childAtIndex(1).type() == ExpressionNode::Type::Rational)
|
||||
{
|
||||
Rational r = childAtIndex(1).convert<Rational>();
|
||||
if (!r.integerDenominator().isOne() || r.sign() == ExpressionNode::Sign::Negative) {
|
||||
if (!r.isInteger() || r.sign() == ExpressionNode::Sign::Negative) {
|
||||
return -1;
|
||||
}
|
||||
Integer num = r.unsignedIntegerNumerator();
|
||||
@@ -309,7 +309,7 @@ Expression Power::shallowReduce(ExpressionNode::ReductionContext reductionContex
|
||||
ExpressionNode::Type baseType = base.type();
|
||||
ExpressionNode::Type indexType = index.type();
|
||||
if (SortedIsMatrix(base, reductionContext.context())) {
|
||||
if (indexType != ExpressionNode::Type::Rational || !static_cast<Rational &>(index).integerDenominator().isOne()) {
|
||||
if (indexType != ExpressionNode::Type::Rational || !static_cast<Rational &>(index).isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
if (baseType != ExpressionNode::Type::Matrix) {
|
||||
@@ -449,7 +449,7 @@ Expression Power::shallowReduce(ExpressionNode::ReductionContext reductionContex
|
||||
} else if (r.isMinusHalf()) {
|
||||
// (x+iy)^(-1/2)
|
||||
result = complexBase.squareRoot(reductionContext).inverse(reductionContext);
|
||||
} else if (r.integerDenominator().isOne() && r.unsignedIntegerNumerator().isLowerThan(Integer(10))) {
|
||||
} else if (r.isInteger() && r.unsignedIntegerNumerator().isLowerThan(Integer(10))) {
|
||||
if (r.sign() == ExpressionNode::Sign::Positive) {
|
||||
// (x+iy)^n, n integer positive n < 10
|
||||
result = complexBase.powerInteger(r.unsignedIntegerNumerator().extractedInt(), reductionContext);
|
||||
@@ -627,7 +627,7 @@ Expression Power::shallowReduce(ExpressionNode::ReductionContext reductionContex
|
||||
Power powerBase = static_cast<Power &>(base);
|
||||
// Check if a > 0 or c is Integer
|
||||
if (powerBase.childAtIndex(0).sign(reductionContext.context()) == ExpressionNode::Sign::Positive // a > 0
|
||||
|| (indexType == ExpressionNode::Type::Rational && static_cast<Rational &>(index).integerDenominator().isOne())) // c integr
|
||||
|| (indexType == ExpressionNode::Type::Rational && static_cast<Rational &>(index).isInteger())) // c integr
|
||||
{
|
||||
/* If the complexFormat is real, we check that the inner power is defined
|
||||
* before applying the rule (a^b)^c -> a^(b*c). Otherwise, we return
|
||||
@@ -646,7 +646,7 @@ Expression Power::shallowReduce(ExpressionNode::ReductionContext reductionContex
|
||||
if (!letPowerAtRoot && baseType == ExpressionNode::Type::MultiplicationExplicite) {
|
||||
MultiplicationExplicite multiplicationBase = static_cast<MultiplicationExplicite &>(base);
|
||||
// Case 1: (a*b*c*...)^n = a^n*b^n*c^n*... if n integer
|
||||
if (indexType == ExpressionNode::Type::Rational && static_cast<Rational &>(index).integerDenominator().isOne()) {
|
||||
if (indexType == ExpressionNode::Type::Rational && static_cast<Rational &>(index).isInteger()) {
|
||||
return simplifyPowerMultiplication(reductionContext);
|
||||
}
|
||||
// Case 2: (a*b*...)^r -> |a|^r*(sign(a)*b*...)^r if a not -1
|
||||
@@ -695,7 +695,7 @@ Expression Power::shallowReduce(ExpressionNode::ReductionContext reductionContex
|
||||
Expression additionIndexChild0 = additionIndex.childAtIndex(0);
|
||||
if (additionIndexChild0.type() == ExpressionNode::Type::Rational) {
|
||||
const Rational rationalIndex = static_cast<Rational &>(additionIndexChild0);
|
||||
if (rationalIndex.unsignedIntegerNumerator().isOne() && !rationalIndex.integerDenominator().isOne()) {
|
||||
if (rationalIndex.unsignedIntegerNumerator().isOne() && !rationalIndex.isInteger()) {
|
||||
/* Do not reduce a^(1/q+c+...) to avoid potential infinite loop:
|
||||
* a^(1/q+c+...) --> a^(1/q)*a^(c+...) --> a^(1/q+c+...)*/
|
||||
/* TODO: do something more sensible here:
|
||||
@@ -731,7 +731,7 @@ Expression Power::shallowReduce(ExpressionNode::ReductionContext reductionContex
|
||||
if (!letPowerAtRoot
|
||||
&& indexType == ExpressionNode::Type::Rational
|
||||
&& !static_cast<Rational &>(index).signedIntegerNumerator().isZero()
|
||||
&& static_cast<Rational &>(index).integerDenominator().isOne()
|
||||
&& static_cast<Rational &>(index).isInteger()
|
||||
&& baseType == ExpressionNode::Type::Addition)
|
||||
{
|
||||
// Exponent n
|
||||
@@ -793,7 +793,7 @@ Expression Power::shallowReduce(ExpressionNode::ReductionContext reductionContex
|
||||
/* We could use the Newton formula instead which is quicker but not immediate
|
||||
* to implement in the general case (Newton multinome). */
|
||||
// (a+b)^n with n integer -> a^n+?a^(n-1)*b+?a^(n-2)*b^2+...+b^n (Newton)
|
||||
if (!letPowerAtRoot && childAtIndex(1)->type() == ExpressionNode::Type::Rational && static_cast<const Rational *>(childAtIndex(1))->denominator().isOne() && childAtIndex(0)->type() == ExpressionNode::Type::Addition && childAtIndex(0)->numberOfChildren() == 2) {
|
||||
if (!letPowerAtRoot && childAtIndex(1)->type() == ExpressionNode::Type::Rational && static_cast<const Rational *>(childAtIndex(1))->isInteger() && childAtIndex(0)->type() == ExpressionNode::Type::Addition && childAtIndex(0)->numberOfChildren() == 2) {
|
||||
Rational * nr = static_cast<Rational *>(childAtIndex(1));
|
||||
Integer n = nr->numerator();
|
||||
n.setNegative(false);
|
||||
@@ -920,7 +920,7 @@ Expression Power::simplifyRationalRationalPower(ExpressionNode::ReductionContext
|
||||
// this is a^b with a, b rationals
|
||||
Rational a = childAtIndex(0).convert<Rational>();
|
||||
Rational b = childAtIndex(1).convert<Rational>();
|
||||
if (b.integerDenominator().isOne()) {
|
||||
if (b.isInteger()) {
|
||||
Rational r = Rational::IntegerPower(a, b.signedIntegerNumerator());
|
||||
if (r.numeratorOrDenominatorIsInfinity()) {
|
||||
return Power::Builder(a, b);
|
||||
|
||||
@@ -67,7 +67,7 @@ Expression PredictionInterval::shallowReduce(ExpressionNode::ReductionContext re
|
||||
}
|
||||
if (c1.type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = static_cast<Rational &>(c1);
|
||||
if (!r1.integerDenominator().isOne() || r1.sign() == ExpressionNode::Sign::Negative) {
|
||||
if (!r1.isInteger() || r1.sign() == ExpressionNode::Sign::Negative) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ Expression PredictionInterval::shallowReduce(ExpressionNode::ReductionContext re
|
||||
}
|
||||
Rational r0 = static_cast<Rational &>(c0);
|
||||
Rational r1 = static_cast<Rational &>(c1);
|
||||
if (!r1.integerDenominator().isOne() || r1.sign() == ExpressionNode::Sign::Negative || r0.sign() == ExpressionNode::Sign::Negative || Integer::NaturalOrder(r0.unsignedIntegerNumerator(), r0.integerDenominator()) > 0) {
|
||||
if (!r1.isInteger() || r1.sign() == ExpressionNode::Sign::Negative || r0.sign() == ExpressionNode::Sign::Negative || Integer::NaturalOrder(r0.unsignedIntegerNumerator(), r0.integerDenominator()) > 0) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
/* [r0-1.96*sqrt(r0*(1-r0)/r1), r0+1.96*sqrt(r0*(1-r0)/r1)]*/
|
||||
|
||||
@@ -72,7 +72,7 @@ int RationalNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo
|
||||
}
|
||||
buffer[bufferSize-1] = 0;
|
||||
int numberOfChar = signedNumerator().serialize(buffer, bufferSize);
|
||||
if (denominator().isOne()) {
|
||||
if (isInteger()) {
|
||||
return numberOfChar;
|
||||
}
|
||||
if (numberOfChar >= bufferSize-1) {
|
||||
@@ -97,7 +97,7 @@ Expression RationalNode::setSign(Sign s, ReductionContext reductionContext) {
|
||||
|
||||
Layout RationalNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
Layout numeratorLayout = signedNumerator().createLayout();
|
||||
if (denominator().isOne()) {
|
||||
if (isInteger()) {
|
||||
return numeratorLayout;
|
||||
}
|
||||
Layout denominatorLayout = denominator().createLayout();
|
||||
|
||||
@@ -56,7 +56,7 @@ Expression Round::shallowReduce(ExpressionNode::ReductionContext reductionContex
|
||||
if (childAtIndex(0).type() == ExpressionNode::Type::Rational && childAtIndex(1).type() == ExpressionNode::Type::Rational) {
|
||||
Rational r1 = childAtIndex(0).convert<Rational>();
|
||||
Rational r2 = childAtIndex(1).convert<Rational>();
|
||||
if (!r2.integerDenominator().isOne()) {
|
||||
if (!r2.isInteger()) {
|
||||
return replaceWithUndefinedInPlace();
|
||||
}
|
||||
const Rational ten = Rational::Builder(10);
|
||||
|
||||
@@ -60,6 +60,11 @@ QUIZ_CASE(poincare_rational_properties) {
|
||||
quiz_assert(!Rational::Builder(3,2).isMinusHalf());
|
||||
quiz_assert(Rational::Builder(10).isTen());
|
||||
quiz_assert(!Rational::Builder(-1).isTen());
|
||||
quiz_assert(Rational::Builder(-1).isInteger());
|
||||
quiz_assert(Rational::Builder(9).isInteger());
|
||||
quiz_assert(Rational::Builder(9,3).isInteger());
|
||||
quiz_assert(Rational::Builder(-9,3).isInteger());
|
||||
quiz_assert(!Rational::Builder(9,10).isInteger());
|
||||
}
|
||||
|
||||
static inline void assert_add_to(const Rational i, const Rational j, const Rational k) {
|
||||
|
||||
Reference in New Issue
Block a user