[poincare] Fatorize code of Complex::complexToExpression in

Expression::CreateComplexExpression that create the expression a+i*b or
r*e^(i*th) from 2 expressions representing a & b or r & th.
This commit is contained in:
Émilie Feral
2018-11-28 15:14:06 +01:00
committed by Léa Saviot
parent 476a79565f
commit f452d8fced
4 changed files with 92 additions and 58 deletions

View File

@@ -86,6 +86,8 @@ private:
class Decimal final : public Number {
friend class Number;
friend class DecimalNode;
template<typename T>
friend class ComplexNode;
public:
static int Exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentIsNegative = false);
Decimal(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, int exponent);

View File

@@ -26,6 +26,8 @@ class Expression : public TreeHandle {
friend class BinomialCoefficient;
friend class Ceiling;
friend class CommonLogarithm;
template<typename T>
friend class ComplexNode;
friend class ComplexArgument;
friend class ComplexHelper;
friend class ConfidenceInterval;
@@ -288,6 +290,10 @@ private:
Expression defaultReplaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression expression);
int defaultGetPolynomialCoefficients(Context & context, const char * symbol, Expression expression[]) const;
/* Builder */
typedef Expression (*TransformExpression)(Expression e);
static Expression CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeTb, TransformExpression inverse);
/* Expression roots/extrema solver*/
constexpr static double k_solverPrecision = 1.0E-5;
constexpr static double k_sqrtEps = 1.4901161193847656E-8; // sqrt(DBL_EPSILON)

View File

@@ -42,67 +42,24 @@ T ComplexNode<T>::toScalar() const {
template<typename T>
Expression ComplexNode<T>::complexToExpression(Preferences::ComplexFormat complexFormat) const {
if (std::isnan(this->real()) || std::isnan(this->imag())) {
return Undefined();
}
T ra, tb;
if (complexFormat == Preferences::ComplexFormat::Cartesian) {
Expression real;
Expression imag;
if (this->real() != 0 || this->imag() == 0) {
real = Number::DecimalNumber<T>(this->real());
}
if (this->imag() != 0) {
if (this->imag() == 1.0 || this->imag() == -1) {
imag = Constant(Ion::Charset::IComplex);
} else if (this->imag() > 0) {
imag = Multiplication(Number::DecimalNumber(this->imag()), Constant(Ion::Charset::IComplex));
} else {
imag = Multiplication(Number::DecimalNumber(-this->imag()), Constant(Ion::Charset::IComplex));
}
}
if (imag.isUninitialized()) {
return real;
} else if (real.isUninitialized()) {
if (this->imag() > 0) {
return imag;
} else {
return Opposite(imag);
}
return imag;
} else if (this->imag() > 0) {
return Addition(real, imag);
} else {
return Subtraction(real, imag);
}
}
assert(complexFormat == Preferences::ComplexFormat::Polar);
Expression norm;
Expression exp;
T r = std::abs(*this);
T th = std::arg(*this);
if (r != 1 || th == 0) {
norm = Number::DecimalNumber(r);
}
if (r != 0 && th != 0) {
Expression arg;
if (th == 1.0) {
arg = Constant(Ion::Charset::IComplex);
} else if (th == -1.0) {
arg = Opposite(Constant(Ion::Charset::IComplex));
} else if (th > 0) {
arg = Multiplication(Number::DecimalNumber(th), Constant(Ion::Charset::IComplex));
} else {
arg = Opposite(Multiplication(Number::DecimalNumber(-th), Constant(Ion::Charset::IComplex)));
}
exp = Power(Constant(Ion::Charset::Exponential), arg);
}
if (exp.isUninitialized()) {
return norm;
} else if (norm.isUninitialized()) {
return exp;
ra = this->real();
tb = this->imag();
} else {
return Multiplication(norm, exp);
ra = std::abs(*this);
tb = std::arg(*this);
}
return Expression::CreateComplexExpression(
Number::DecimalNumber<T>(ra),
Number::DecimalNumber<T>(tb),
complexFormat,
(std::isnan(this->real()) || std::isnan(this->imag())),
ra == 0.0, ra == 1.0, tb == 0.0, tb == 1.0, tb == -1.0, tb < 0.0,
[](Expression e) {
assert(e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Rational || e.type() == ExpressionNode::Type::Float || e.type() == ExpressionNode::Type::Decimal || e.type() == ExpressionNode::Type::Infinity);
return Expression(static_cast<Number &>(e).setSign(ExpressionNode::Sign::Positive)); }
);
}
template <typename T>

View File

@@ -455,6 +455,75 @@ U Expression::epsilon() {
return epsilon;
}
/* Builder */
Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Preferences::ComplexFormat complexFormat, bool undefined, bool isZeroRa, bool isOneRa, bool isZeroTb, bool isOneTb, bool isMinusOneTb, bool isNegativeTb, TransformExpression inverse) {
if (undefined) {
return Undefined();
}
switch (complexFormat) {
case Preferences::ComplexFormat::Cartesian:
{
Expression real;
Expression imag;
if (!isZeroRa || isZeroTb) {
real = ra;
}
if (!isZeroTb) {
if (isOneTb || isMinusOneTb) {
imag = Constant(Ion::Charset::IComplex);
} else if (isNegativeTb) {
imag = Multiplication(inverse(tb), Constant(Ion::Charset::IComplex));
} else {
imag = Multiplication(tb , Constant(Ion::Charset::IComplex));
}
}
if (imag.isUninitialized()) {
return real;
} else if (real.isUninitialized()) {
if (isNegativeTb) {
return Opposite(imag);
} else {
return imag;
}
} else if (isNegativeTb) {
return Subtraction(real, imag);
} else {
return Addition(real, imag);
}
}
default:
{
assert(complexFormat == Preferences::ComplexFormat::Polar);
Expression norm;
Expression exp;
if (!isOneRa || isZeroTb) {
norm = ra;
}
if (!isZeroRa && !isZeroTb) {
Expression arg;
if (isOneTb) {
arg = Constant(Ion::Charset::IComplex);
} else if (isMinusOneTb) {
arg = Opposite(Constant(Ion::Charset::IComplex));
} else if (isNegativeTb) {
arg = Opposite(Multiplication(inverse(tb), Constant(Ion::Charset::IComplex)));
} else {
arg = Multiplication(tb, Constant(Ion::Charset::IComplex));
}
exp = Power(Constant(Ion::Charset::Exponential), arg);
}
if (exp.isUninitialized()) {
return norm;
} else if (norm.isUninitialized()) {
return exp;
} else {
return Multiplication(norm, exp);
}
}
}
}
/* Expression roots/extrema solver*/
typename Expression::Coordinate2D Expression::nextMinimum(const char * symbol, double start, double step, double max, Context & context, Preferences::AngleUnit angleUnit) const {