mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare] Remove characteristicXHalfRange
Method characteristicXHalfRange was used to compute the range on which to display cartesian function in Graph. With the new zoom algorithm, this method is deprecated. Change-Id: Ic681fab8d58d0f5628a94302a7b49dacaaa1a6a3
This commit is contained in:
committed by
Émilie Feral
parent
8104caea50
commit
0ed0cc56e9
@@ -21,7 +21,6 @@ public:
|
||||
|
||||
// Properties
|
||||
Type type() const override { return Type::Cosine; }
|
||||
float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const override;
|
||||
|
||||
template<typename T> static Complex<T> computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian);
|
||||
|
||||
|
||||
@@ -170,15 +170,6 @@ public:
|
||||
static bool IsRandom(const Expression e, Context * context);
|
||||
static bool IsMatrix(const Expression e, Context * context);
|
||||
static bool IsInfinity(const Expression e, Context * context);
|
||||
/* 'characteristicXRange' tries to assess the range on x where the expression
|
||||
* (considered as a function on x) has an interesting evolution. For example,
|
||||
* the period of the function on 'x' if it is periodic. If
|
||||
* the function is x-independent, the return value is 0.0f (because any
|
||||
* x-range is equivalent). If the function does not have an interesting range,
|
||||
* the return value is NAN.
|
||||
* NB: so far, we consider that the only way of building a periodic function
|
||||
* is to use sin/tan/cos(f(x)) with f a linear function. */
|
||||
float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const { return node()->characteristicXRange(context, angleUnit); }
|
||||
/* polynomialDegree returns:
|
||||
* - (-1) if the expression is not a polynome
|
||||
* - the degree of the polynome otherwise */
|
||||
|
||||
@@ -200,7 +200,6 @@ public:
|
||||
/*!*/ virtual Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly, int parameteredAncestorsCount);
|
||||
typedef bool (*isVariableTest)(const char * c, Poincare::Context * context);
|
||||
virtual int getVariables(Context * context, isVariableTest isVariable, char * variables, int maxSizeVariable, int nextVariableIndex) const;
|
||||
virtual float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const;
|
||||
bool isOfType(Type * types, int length) const;
|
||||
|
||||
virtual Expression removeUnit(Expression * unit); // Only reduced nodes should answer
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
int polynomialDegree(Context * context, const char * symbolName) const override;
|
||||
int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const override;
|
||||
int getVariables(Context * context, isVariableTest isVariable, char * variables, int maxSizeVariable, int nextVariableIndex) const override;
|
||||
float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const override;
|
||||
|
||||
private:
|
||||
char m_name[0]; // MUST be the last member variable
|
||||
|
||||
@@ -21,7 +21,6 @@ public:
|
||||
|
||||
// Properties
|
||||
Type type() const override { return Type::Sine; }
|
||||
float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const override;
|
||||
|
||||
template<typename T> static Complex<T> computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian);
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ public:
|
||||
int polynomialDegree(Context * context, const char * symbolName) const override;
|
||||
int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const override;
|
||||
int getVariables(Context * context, isVariableTest isVariable, char * variables, int maxSizeVariable, int nextVariableIndex) const override;
|
||||
float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const override;
|
||||
/* getUnit returns Undefined, because the symbol would have
|
||||
* already been replaced if it should have been.*/
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ public:
|
||||
|
||||
// Properties
|
||||
Type type() const override { return Type::Tangent; }
|
||||
float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const override;
|
||||
|
||||
private:
|
||||
// Layout
|
||||
|
||||
@@ -13,7 +13,6 @@ public:
|
||||
Sine = 1,
|
||||
};
|
||||
static double PiInAngleUnit(Preferences::AngleUnit angleUnit);
|
||||
static float characteristicXRange(const Expression & e, Context * context, Preferences::AngleUnit angleUnit);
|
||||
static bool isDirectTrigonometryFunction(const Expression & e);
|
||||
static bool isInverseTrigonometryFunction(const Expression & e);
|
||||
static bool AreInverseFunctions(const Expression & directFunction, const Expression & inverseFunction);
|
||||
|
||||
@@ -15,10 +15,6 @@ constexpr Expression::FunctionHelper Cosine::s_functionHelper;
|
||||
|
||||
int CosineNode::numberOfChildren() const { return Cosine::s_functionHelper.numberOfChildren(); }
|
||||
|
||||
float CosineNode::characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const {
|
||||
return Trigonometry::characteristicXRange(Cosine(this), context, angleUnit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Complex<T> CosineNode::computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) {
|
||||
std::complex<T> angleInput = Trigonometry::ConvertToRadian(c, angleUnit);
|
||||
|
||||
@@ -51,22 +51,6 @@ int ExpressionNode::getVariables(Context * context, isVariableTest isVariable, c
|
||||
return nextVariableIndex;
|
||||
}
|
||||
|
||||
float ExpressionNode::characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const {
|
||||
/* A expression has a characteristic range if at least one of its childAtIndex has
|
||||
* one and the other are x-independant. We keep the biggest interesting range
|
||||
* among the childAtIndex interesting ranges. */
|
||||
float range = 0.0f;
|
||||
for (ExpressionNode * c : children()) {
|
||||
float opRange = c->characteristicXRange(context, angleUnit);
|
||||
if (std::isnan(opRange)) {
|
||||
return NAN;
|
||||
} else if (range < opRange) {
|
||||
range = opRange;
|
||||
}
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
int ExpressionNode::SimplificationOrder(const ExpressionNode * e1, const ExpressionNode * e2, bool ascending, bool canBeInterrupted, bool ignoreParentheses) {
|
||||
// Depending on ignoreParentheses, check if e1 or e2 are parenthesis
|
||||
ExpressionNode::Type type1 = e1->type();
|
||||
|
||||
@@ -44,15 +44,6 @@ int FunctionNode::getVariables(Context * context, isVariableTest isVariable, cha
|
||||
return e.node()->getVariables(context, isVariable, variables, maxSizeVariable, nextVariableIndex);
|
||||
}
|
||||
|
||||
float FunctionNode::characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const {
|
||||
Function f(this);
|
||||
Expression e = SymbolAbstract::Expand(f,context, true);
|
||||
if (e.isUninitialized()) {
|
||||
return 0.0f;
|
||||
}
|
||||
return e.characteristicXRange(context, angleUnit);
|
||||
}
|
||||
|
||||
Layout FunctionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
return LayoutHelper::Prefix(Function(this), floatDisplayMode, numberOfSignificantDigits, name());
|
||||
}
|
||||
|
||||
@@ -13,10 +13,6 @@ constexpr Expression::FunctionHelper Sine::s_functionHelper;
|
||||
|
||||
int SineNode::numberOfChildren() const { return Sine::s_functionHelper.numberOfChildren(); }
|
||||
|
||||
float SineNode::characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const {
|
||||
return Trigonometry::characteristicXRange(Sine(this), context, angleUnit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Complex<T> SineNode::computeOnComplex(const std::complex<T> c, Preferences::ComplexFormat, Preferences::AngleUnit angleUnit) {
|
||||
std::complex<T> angleInput = Trigonometry::ConvertToRadian(c, angleUnit);
|
||||
|
||||
@@ -64,10 +64,6 @@ int SymbolNode::getVariables(Context * context, isVariableTest isVariable, char
|
||||
return nextVariableIndex;
|
||||
}
|
||||
|
||||
float SymbolNode::characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const {
|
||||
return isUnknown() ? NAN : 0.0f;
|
||||
}
|
||||
|
||||
Layout SymbolNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
assert(!isUnknown());
|
||||
// TODO return Parse(m_name).createLayout() ?
|
||||
|
||||
@@ -17,10 +17,6 @@ constexpr Expression::FunctionHelper Tangent::s_functionHelper;
|
||||
|
||||
int TangentNode::numberOfChildren() const { return Tangent::s_functionHelper.numberOfChildren(); }
|
||||
|
||||
float TangentNode::characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const {
|
||||
return Trigonometry::characteristicXRange(Tangent(this), context, angleUnit);
|
||||
}
|
||||
|
||||
Layout TangentNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
return LayoutHelper::Prefix(Tangent(this), floatDisplayMode, numberOfSignificantDigits, Tangent::s_functionHelper.name());
|
||||
}
|
||||
|
||||
@@ -55,32 +55,6 @@ double Trigonometry::PiInAngleUnit(Preferences::AngleUnit angleUnit) {
|
||||
return 200.0;
|
||||
}
|
||||
|
||||
float Trigonometry::characteristicXRange(const Expression & e, Context * context, Preferences::AngleUnit angleUnit) {
|
||||
assert(e.numberOfChildren() == 1);
|
||||
|
||||
constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1;
|
||||
char x[bufferSize];
|
||||
SerializationHelper::CodePoint(x, bufferSize, UCodePointUnknown);
|
||||
|
||||
int d = e.childAtIndex(0).polynomialDegree(context, x);
|
||||
if (d < 0 || d > 1) {
|
||||
// child(0) is not linear so we cannot easily find an interesting range
|
||||
return e.childAtIndex(0).characteristicXRange(context, angleUnit);
|
||||
}
|
||||
// The expression e is x-independent
|
||||
if (d == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
// e has the form cos/sin/tan(ax+b) so it is periodic of period 2*π/a
|
||||
assert(d == 1);
|
||||
/* To compute a, the slope of the expression child(0), we compute the
|
||||
* derivative of child(0) for any x value. */
|
||||
Poincare::Derivative derivative = Poincare::Derivative::Builder(e.childAtIndex(0).clone(), Symbol::Builder(x, 1), Float<float>::Builder(1.0f));
|
||||
double a = derivative.node()->approximate(double(), context, Preferences::ComplexFormat::Real, angleUnit).toScalar();
|
||||
double pi = PiInAngleUnit(angleUnit);
|
||||
return std::fabs(a) < Expression::Epsilon<double>() ? NAN : 2.0*pi/std::fabs(a);
|
||||
}
|
||||
|
||||
bool Trigonometry::isDirectTrigonometryFunction(const Expression & e) {
|
||||
return e.type() == ExpressionNode::Type::Cosine
|
||||
|| e.type() == ExpressionNode::Type::Sine
|
||||
|
||||
@@ -240,45 +240,6 @@ QUIZ_CASE(poincare_properties_polynomial_degree) {
|
||||
Ion::Storage::sharedStorage()->recordNamed("f.func").destroy();
|
||||
}
|
||||
|
||||
void assert_reduced_expression_has_characteristic_range(Expression e, float range, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Degree, Preferences::UnitFormat unitFormat = Metric) {
|
||||
Shared::GlobalContext globalContext;
|
||||
e = e.reduce(ExpressionNode::ReductionContext(&globalContext, Preferences::ComplexFormat::Cartesian, angleUnit, unitFormat, ExpressionNode::ReductionTarget::SystemForApproximation));
|
||||
if (std::isnan(range)) {
|
||||
quiz_assert(std::isnan(e.characteristicXRange(&globalContext, angleUnit)));
|
||||
} else {
|
||||
quiz_assert(std::fabs(e.characteristicXRange(&globalContext, angleUnit) - range) < 0.0000001f);
|
||||
}
|
||||
}
|
||||
|
||||
QUIZ_CASE(poincare_properties_characteristic_range) {
|
||||
// cos(x), degree
|
||||
assert_reduced_expression_has_characteristic_range(Cosine::Builder(Symbol::Builder(UCodePointUnknown)), 360.0f);
|
||||
// cos(-x), degree
|
||||
assert_reduced_expression_has_characteristic_range(Cosine::Builder(Opposite::Builder(Symbol::Builder(UCodePointUnknown))), 360.0f);
|
||||
// cos(x), radian
|
||||
assert_reduced_expression_has_characteristic_range(Cosine::Builder(Symbol::Builder(UCodePointUnknown)), 2.0f*M_PI, Preferences::AngleUnit::Radian);
|
||||
// cos(-x), radian
|
||||
assert_reduced_expression_has_characteristic_range(Cosine::Builder(Opposite::Builder(Symbol::Builder(UCodePointUnknown))), 2.0f*M_PI, Preferences::AngleUnit::Radian);
|
||||
// sin(9x+10), degree
|
||||
assert_reduced_expression_has_characteristic_range(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational::Builder(9),Symbol::Builder(UCodePointUnknown)),Rational::Builder(10))), 40.0f);
|
||||
// sin(9x+10)+cos(x/2), degree
|
||||
assert_reduced_expression_has_characteristic_range(Addition::Builder(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational::Builder(9),Symbol::Builder(UCodePointUnknown)),Rational::Builder(10))),Cosine::Builder(Division::Builder(Symbol::Builder(UCodePointUnknown),Rational::Builder(2)))), 720.0f);
|
||||
// sin(9x+10)+cos(x/2), radian
|
||||
assert_reduced_expression_has_characteristic_range(Addition::Builder(Sine::Builder(Addition::Builder(Multiplication::Builder(Rational::Builder(9),Symbol::Builder(UCodePointUnknown)),Rational::Builder(10))),Cosine::Builder(Division::Builder(Symbol::Builder(UCodePointUnknown),Rational::Builder(2)))), 4.0f*M_PI, Preferences::AngleUnit::Radian);
|
||||
// x, degree
|
||||
assert_reduced_expression_has_characteristic_range(Symbol::Builder(UCodePointUnknown), NAN);
|
||||
// cos(3)+2, degree
|
||||
assert_reduced_expression_has_characteristic_range(Addition::Builder(Cosine::Builder(Rational::Builder(3)),Rational::Builder(2)), 0.0f);
|
||||
// log(cos(40x), degree
|
||||
assert_reduced_expression_has_characteristic_range(CommonLogarithm::Builder(Cosine::Builder(Multiplication::Builder(Rational::Builder(40),Symbol::Builder(UCodePointUnknown)))), 9.0f);
|
||||
// cos(cos(x)), degree
|
||||
assert_reduced_expression_has_characteristic_range(Cosine::Builder((Expression)Cosine::Builder(Symbol::Builder(UCodePointUnknown))), 360.0f);
|
||||
// f(x) with f : x --> cos(x), degree
|
||||
assert_reduce("cos(x)→f(x)");
|
||||
assert_reduced_expression_has_characteristic_range(Function::Builder("f",1,Symbol::Builder(UCodePointUnknown)), 360.0f);
|
||||
Ion::Storage::sharedStorage()->recordNamed("f.func").destroy();
|
||||
}
|
||||
|
||||
void assert_expression_has_variables(const char * expression, const char * variables[], int trueNumberOfVariables) {
|
||||
Shared::GlobalContext globalContext;
|
||||
Expression e = parse_expression(expression, &globalContext, false);
|
||||
|
||||
Reference in New Issue
Block a user