mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-22 15:20:39 +01:00
[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:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user