mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-28 01:59:59 +01:00
[poincare] SignFunction: improve shallowReduce: sign(-x) = -sign(x)
This commit is contained in:
@@ -51,7 +51,7 @@ public:
|
||||
static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); }
|
||||
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("sign", 1, &UntypedBuilder);
|
||||
|
||||
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit);
|
||||
Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target);
|
||||
private:
|
||||
explicit SignFunction(Expression child) : Expression(TreePool::sharedPool()->createTreeNode<SignFunctionNode>()) {
|
||||
replaceChildAtIndexInPlace(0, child);
|
||||
|
||||
@@ -94,7 +94,7 @@ Expression ComplexCartesian::argument(Context & context, Preferences::AngleUnit
|
||||
return sub;
|
||||
} else {
|
||||
// if b == 0, argument = (1-sign(a))*Pi/2
|
||||
Expression signa = SignFunction::Builder(a).shallowReduce(context, angleUnit);
|
||||
Expression signa = SignFunction::Builder(a).shallowReduce(context, angleUnit, target);
|
||||
Subtraction sub(Rational(1), signa);
|
||||
signa.shallowReduce(context, angleUnit, target);
|
||||
Multiplication mul(Rational(1,2), Constant(Ion::Charset::SmallPi), sub);
|
||||
|
||||
@@ -96,7 +96,7 @@ ComplexPolar ComplexHelper::complexPolarFromComplexCartesian(const ExpressionNod
|
||||
// Then, compute sign(b) * Pi/2 - arctan(a/b)
|
||||
argument = Subtraction(
|
||||
Multiplication(
|
||||
SignFunction::Builder(b).shallowReduce(context, angleUnit),
|
||||
SignFunction::Builder(b).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation),
|
||||
Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)
|
||||
).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation),
|
||||
arcTangent
|
||||
@@ -106,7 +106,7 @@ ComplexPolar ComplexHelper::complexPolarFromComplexCartesian(const ExpressionNod
|
||||
argument = Multiplication(
|
||||
Subtraction(
|
||||
Rational(1),
|
||||
SignFunction::Builder(a).shallowReduce(context, angleUnit)
|
||||
SignFunction::Builder(a).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)
|
||||
).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation),
|
||||
Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)
|
||||
).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation);
|
||||
|
||||
@@ -32,7 +32,7 @@ int SignFunctionNode::serialize(char * buffer, int bufferSize, Preferences::Prin
|
||||
}
|
||||
|
||||
Expression SignFunctionNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) {
|
||||
return SignFunction(this).shallowReduce(context, angleUnit);
|
||||
return SignFunction(this).shallowReduce(context, angleUnit, target);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -46,7 +46,7 @@ Complex<T> SignFunctionNode::computeOnComplex(const std::complex<T> c, Preferenc
|
||||
return Complex<T>(1.0);
|
||||
}
|
||||
|
||||
Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) {
|
||||
Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) {
|
||||
{
|
||||
Expression e = Expression::defaultShallowReduce(context, angleUnit);
|
||||
if (e.isUndefined()) {
|
||||
@@ -59,16 +59,30 @@ Expression SignFunction::shallowReduce(Context & context, Preferences::AngleUnit
|
||||
}
|
||||
#endif
|
||||
Rational one(1);
|
||||
if (childAtIndex(0).sign(&context, angleUnit) != ExpressionNode::Sign::Unknown) {
|
||||
if (childAtIndex(0).sign(&context, angleUnit) == ExpressionNode::Sign::Negative) {
|
||||
Expression child = childAtIndex(0);
|
||||
ExpressionNode::Sign s = child.sign(&context, angleUnit);
|
||||
if (s != ExpressionNode::Sign::Unknown) {
|
||||
if (s == ExpressionNode::Sign::Negative) {
|
||||
one = Rational(-1);
|
||||
}
|
||||
} else {
|
||||
Evaluation<float> childApproximated = childAtIndex(0).node()->approximate(1.0f, context, angleUnit);
|
||||
Evaluation<float> childApproximated = child.node()->approximate(1.0f, context, angleUnit);
|
||||
assert(childApproximated.type() == EvaluationNode<float>::Type::Complex);
|
||||
Complex<float> c = static_cast<Complex<float>&>(childApproximated);
|
||||
// c has no sign (c is complex or NAN)
|
||||
if (std::isnan(c.imag()) || std::isnan(c.real()) || c.imag() != 0) {
|
||||
return *this;
|
||||
// sign(-x) = sign(x)
|
||||
Expression oppChild = child.makePositiveAnyNegativeNumeralFactor(context, angleUnit);
|
||||
if (oppChild.isUninitialized()) {
|
||||
return *this;
|
||||
} else {
|
||||
Expression sign = *this;
|
||||
Multiplication m(Rational(-1));
|
||||
replaceWithInPlace(m);
|
||||
m.addChildAtIndexInPlace(sign, 1, 1);
|
||||
sign.shallowReduce(context, angleUnit, target);
|
||||
return m.shallowReduce(context, angleUnit, target);
|
||||
}
|
||||
}
|
||||
if (c.real() < 0) {
|
||||
one = Rational(-1);
|
||||
|
||||
@@ -62,7 +62,7 @@ ComplexCartesian SquareRootNode::complexCartesian(Context & context, Preferences
|
||||
// a = sqrt(x^2+y^2)+x
|
||||
Multiplication real = complexCartesianHelper(Addition(norm.clone(), x.clone()), context, angleUnit);
|
||||
Multiplication imag = complexCartesianHelper(Subtraction(norm, x), context, angleUnit);
|
||||
imag.addChildAtIndexInPlace(SignFunction::Builder(y).shallowReduce(context, angleUnit), imag.numberOfChildren(), imag.numberOfChildren());
|
||||
imag.addChildAtIndexInPlace(SignFunction::Builder(y).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation), imag.numberOfChildren(), imag.numberOfChildren());
|
||||
return ComplexCartesian::Builder(
|
||||
real.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation),
|
||||
imag.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)
|
||||
|
||||
Reference in New Issue
Block a user