[poincare] Complex parts getters (realPart, imaginaryPart,

complexNorm...) simplify while building the complex part
This commit is contained in:
Émilie Feral
2018-11-28 17:25:22 +01:00
committed by Léa Saviot
parent 79e7fb2183
commit 5dae60bc7e
14 changed files with 118 additions and 36 deletions

View File

@@ -14,7 +14,7 @@ public:
return cartesianPartOfComplexFunction(e, context, angleUnit, false);
}
static Expression realPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) {
return Expression(e).clone();
return Expression(e).clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation);
}
static Expression imaginaryPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit);
// static Expression realPartMatrix(const Expression e, Context & context, Preferences::AngleUnit angleUnit);

View File

@@ -185,8 +185,8 @@ public:
Expression simplify(Context & context, Preferences::AngleUnit angleUnit);
Expression reduce(Context & context, Preferences::AngleUnit angleUnit);
static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context);
Expression radianToDegree();
Expression degreeToRadian();
Expression radianToDegree(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target);
Expression degreeToRadian(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target);
/* Approximation Helper */
template<typename U> static U epsilon();

View File

@@ -40,7 +40,7 @@ Expression AdditionNode::complexPart(Context & context, Preferences::AngleUnit a
}
result.addChildAtIndexInPlace(part, result.numberOfChildren(), result.numberOfChildren());
}
return result;
return result.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
// Layout

View File

@@ -13,9 +13,7 @@ Expression ComplexHelper::cartesianPartOfComplexFunction(const ExpressionNode *
return Expression();
}
if (real) {
Expression result = e.clone();
result.replaceChildAtIndexInPlace(0, e.childAtIndex(0).realPart(context, angleUnit));
return result;
return e.clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation);
}
return Rational(0);
}
@@ -31,14 +29,14 @@ Expression ComplexHelper::complexCartesianPartFromPolarParts(const ExpressionNod
if (r.isUninitialized() || th.isUninitialized()) {
return Expression();
}
Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree();
Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation);
Expression trigo;
if (isReal) {
trigo = Cosine::Builder(argument);
} else {
trigo = Sine::Builder(argument);
}
return Multiplication(r, trigo);
return Multiplication(r, trigo.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation);
}
}

View File

@@ -19,7 +19,7 @@ Expression ConjugateNode::realPart(Context & context, Preferences::AngleUnit ang
Expression ConjugateNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const {
Expression e = childAtIndex(0)->imaginaryPart(context, angleUnit);
if (!e.isUninitialized()) {
return Opposite(e);
return Opposite(e).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
return Expression();
}

View File

@@ -53,7 +53,7 @@ Expression DivisionNode::complexNorm(Context & context, Preferences::AngleUnit a
if (r0.isUninitialized() || r1.isUninitialized()) {
return Expression();
}
return Division(r0,r1);
return Division(r0,r1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const {
@@ -65,11 +65,32 @@ Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit a
if (a.isUninitialized() || b.isUninitialized() || c.isUninitialized() || d.isUninitialized()) {
return Expression();
}
Expression denominator = Addition(Power(c.clone(), Rational(2)), Power(d.clone(), Rational(2)));
Expression denominator =
Addition(
Power(
c.clone(),
Rational(2)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Power(
d.clone(),
Rational(2)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
if (real) {
return Division(Addition(Multiplication(a, c), Multiplication(b, d)), denominator);
return Division(
Addition(
Multiplication(a, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Multiplication(b, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
denominator
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
return Division(Subtraction(Multiplication(b, c), Multiplication(a, d)), denominator);
return Division(
Subtraction(
Multiplication(b, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Multiplication(a, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
denominator).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
template<typename T> Complex<T> DivisionNode::compute(const std::complex<T> c, const std::complex<T> d) {

View File

@@ -424,12 +424,12 @@ Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context)
return e;
}
Expression Expression::radianToDegree() {
return Multiplication(*this, Division(Rational(180), Constant(Ion::Charset::SmallPi)));
Expression Expression::radianToDegree(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) {
return Multiplication(*this, Division(Rational(180), Constant(Ion::Charset::SmallPi)).shallowReduce(context, angleUnit, target)).shallowReduce(context, angleUnit, target);
}
Expression Expression::degreeToRadian( ) {
return Multiplication(*this, Division(Constant(Ion::Charset::SmallPi), Rational(180)));
Expression Expression::degreeToRadian(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) {
return Multiplication(*this, Division(Constant(Ion::Charset::SmallPi), Rational(180)).shallowReduce(context, angleUnit, target)).shallowReduce(context, angleUnit, target);
}
Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUnit) {

View File

@@ -84,7 +84,12 @@ Expression ExpressionNode::complexNorm(Context & context, Preferences::AngleUnit
Expression b = imaginaryPart(context, angleUnit);
if (!a.isUninitialized() && !b.isUninitialized()) {
// sqrt(a^2+b^2)
return SquareRoot::Builder(Addition(Power(a, Rational(2)), Power(b, Rational(2))));
return SquareRoot::Builder(
Addition(
Power(a, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Power(b, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
return Expression();
}
@@ -95,15 +100,27 @@ Expression ExpressionNode::complexArgument(Context & context, Preferences::Angle
if (!a.isUninitialized() && !b.isUninitialized()) {
if (b.type() != Type::Rational || !static_cast<Rational &>(b).isZero()) {
// arctan(a/b) or (180/Pi)*arctan(a/b)
Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()));
Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
if (angleUnit == Preferences::AngleUnit::Degree) {
arcTangent = arcTangent.degreeToRadian();
arcTangent = arcTangent.degreeToRadian(context, angleUnit, ReductionTarget::BottomUpComputation);
}
// sign(b) * Pi/2 - arctan(a/b)
return Subtraction(Multiplication(SignFunction::Builder(b), Division(Constant(Ion::Charset::SmallPi), Rational(2))), arcTangent);
return Subtraction(
Multiplication(
SignFunction::Builder(b).shallowReduce(context, angleUnit),
Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
),
arcTangent
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
} else {
// (1-sign(a))*Pi/2
return Multiplication(Subtraction(Rational(1), SignFunction::Builder(a)), Division(Constant(Ion::Charset::SmallPi), Rational(2)));
return Multiplication(
Subtraction(
Rational(1),
SignFunction::Builder(a).shallowReduce(context, angleUnit)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
}
return Expression();

View File

@@ -43,8 +43,16 @@ Expression MultiplicationNode::complexCartesianPart(Context & context, Preferenc
if (childReal.isUninitialized() || childImag.isUninitialized()) {
return Expression();
}
Expression newReal = Subtraction(Multiplication(real.clone(), childReal.clone()), Multiplication(imag.clone(), childImag.clone()));
Expression newImag = Addition(Multiplication(real, childImag), Multiplication(imag, childReal));
Expression newReal =
Subtraction(
Multiplication(real.clone(), childReal.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Multiplication(imag.clone(), childImag.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
Expression newImag =
Addition(
Multiplication(real, childImag).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Multiplication(imag, childReal).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
real = newReal;
imag = newImag;
}
@@ -61,7 +69,7 @@ Expression MultiplicationNode::complexNorm(Context & context, Preferences::Angle
}
norm.addChildAtIndexInPlace(r, norm.numberOfChildren(), norm.numberOfChildren());
}
return norm;
return norm.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
/*Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const {

View File

@@ -28,15 +28,39 @@ Expression NthRootNode::complexPolarPart(Context & context, Preferences::AngleUn
if (r.isUninitialized() || th.isUninitialized() || c.isUninitialized() || d.isUninitialized()) {
return Expression();
}
Expression denominator = Addition(Power(c.clone(), Rational(2)), Power(d.clone(), Rational(2)));
Expression denominator =
Addition(
Power(c.clone(), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Power(d.clone(), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
if (isNorm) {
// R = e^((c*ln(r)+th*d)/(c^2+d^2))
// R = r^(c/(c^2+d^2))*e^(th*d/(c^2+d^2))
return Multiplication(Power(r, Division(c, denominator.clone())), Power(Constant(Ion::Charset::Exponential), Division(Multiplication(d, th), denominator)));
return Multiplication(
Power(
r,
Division(c, denominator.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Power(
Constant(Ion::Charset::Exponential),
Division(
Multiplication(d, th).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
denominator)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
//return Power(Constant(Ion::Charset::Exponential), Division(Addition(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th)), denominator));
} else {
// TH = (th*c-d*ln(r))/(c^2+d^2)
return Division(Subtraction(Multiplication(th, c), Multiplication(d, NaperianLogarithm::Builder(r))), denominator);
return Division(
Subtraction(
Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Multiplication(
d,
NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
denominator
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
}

View File

@@ -32,7 +32,7 @@ Expression OppositeNode::complexCartesianPart(Context & context, Preferences::An
if (a.isUninitialized()) {
return Expression();
}
return Opposite(a);
return Opposite(a).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
/* Layout */

View File

@@ -94,11 +94,25 @@ Expression PowerNode::complexPolarPart(Context & context, Preferences::AngleUnit
if (norm) {
// R = e^(c*ln(r)-th*d)
// R = r^c*e^(-th*d)
return Multiplication(Power(r, c), Power(Constant(Ion::Charset::Exponential), Opposite(Multiplication(th, d))));
return Multiplication(
Power(r, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Power(
Constant(Ion::Charset::Exponential),
Opposite(
Multiplication(th, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
//return Power(Constant(Ion::Charset::Exponential), Subtraction(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th)));
} else {
// TH = d*ln(r)+c*th
return Addition(Multiplication(th, c), Multiplication(d, NaperianLogarithm::Builder(r)));
return Addition(
Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
Multiplication(
d,
NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
}
@@ -448,7 +462,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU
/* We do not apply some rules to a^b if:
* - the parent node is a logarithm of same base a. In this case there is a
* simplication of form ln(e^(3^(1/2))->3^(1/2).
* - the reduction is being BottomUp. In this case, we do not yet have any
* - the reduction is being BottomUpComputation. In this case, we do not yet have any
* information on the parent which could later be a logarithm of the same
* base.
*/

View File

@@ -21,7 +21,7 @@ Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit
return Expression();
}
// R = sqrt(r)
return SquareRoot::Builder(r);
return SquareRoot::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
Expression SquareRootNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const {
@@ -30,7 +30,7 @@ Expression SquareRootNode::complexArgument(Context & context, Preferences::Angle
return Expression();
}
// TH = th/2
return Division(th, Rational(2));
return Division(th, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
Layout SquareRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {

View File

@@ -30,7 +30,7 @@ Expression SubtractionNode::complexPart(Context & context, Preferences::AngleUni
if (a0.isUninitialized() || a1.isUninitialized()) {
return Expression();
}
return Subtraction(a0, a1);
return Subtraction(a0, a1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation);
}
bool SubtractionNode::childNeedsParenthesis(const TreeNode * child) const {