mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-27 17:50:04 +01:00
[poincare/Coordinate2D] Template for double or float
This commit is contained in:
@@ -19,7 +19,7 @@ CalculationGraphController::CalculationGraphController(Responder * parentRespond
|
||||
|
||||
void CalculationGraphController::viewWillAppear() {
|
||||
assert(!m_record.isNull());
|
||||
Coordinate2D pointOfInterest = computeNewPointOfInteresetFromAbscissa(m_graphRange->xMin(), 1);
|
||||
Coordinate2D<double> pointOfInterest = computeNewPointOfInteresetFromAbscissa(m_graphRange->xMin(), 1);
|
||||
if (std::isnan(pointOfInterest.abscissa())) {
|
||||
m_isActive = false;
|
||||
m_graphView->setCursorView(nullptr);
|
||||
@@ -44,7 +44,7 @@ void CalculationGraphController::reloadBannerView() {
|
||||
reloadBannerViewForCursorOnFunction(m_cursor, m_record, functionStore());
|
||||
}
|
||||
|
||||
Coordinate2D CalculationGraphController::computeNewPointOfInteresetFromAbscissa(double start, int direction) {
|
||||
Coordinate2D<double> CalculationGraphController::computeNewPointOfInteresetFromAbscissa(double start, int direction) {
|
||||
double step = m_graphRange->xGridUnit()/10.0;
|
||||
step = direction < 0 ? -step : step;
|
||||
double max = direction > 0 ? m_graphRange->xMax() : m_graphRange->xMin();
|
||||
@@ -69,7 +69,7 @@ bool CalculationGraphController::handleEnter() {
|
||||
}
|
||||
|
||||
bool CalculationGraphController::moveCursorHorizontally(int direction) {
|
||||
Coordinate2D newPointOfInterest = computeNewPointOfInteresetFromAbscissa(m_cursor->x(), direction);
|
||||
Coordinate2D<double> newPointOfInterest = computeNewPointOfInteresetFromAbscissa(m_cursor->x(), direction);
|
||||
if (std::isnan(newPointOfInterest.abscissa())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ protected:
|
||||
float cursorBottomMarginRatio() override { return 0.15f; }
|
||||
BannerView * bannerView() override { return m_bannerView; }
|
||||
void reloadBannerView() override;
|
||||
Poincare::Coordinate2D computeNewPointOfInteresetFromAbscissa(double start, int direction);
|
||||
Poincare::Coordinate2D<double> computeNewPointOfInteresetFromAbscissa(double start, int direction);
|
||||
CartesianFunctionStore * functionStore() const;
|
||||
virtual Poincare::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) = 0;
|
||||
virtual Poincare::Coordinate2D<double> computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) = 0;
|
||||
GraphView * m_graphView;
|
||||
BannerView * m_bannerView;
|
||||
Shared::InteractiveCurveViewRange * m_graphRange;
|
||||
|
||||
@@ -15,7 +15,7 @@ const char * MinimumGraphController::title() {
|
||||
return I18n::translate(I18n::Message::Minimum);
|
||||
}
|
||||
|
||||
Coordinate2D MinimumGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
|
||||
Coordinate2D<double> MinimumGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
|
||||
// TODO The following three lines should be factored.
|
||||
constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1;
|
||||
char unknownX[bufferSize];
|
||||
@@ -32,7 +32,7 @@ const char * MaximumGraphController::title() {
|
||||
return I18n::translate(I18n::Message::Maximum);
|
||||
}
|
||||
|
||||
Coordinate2D MaximumGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
|
||||
Coordinate2D<double> MaximumGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
|
||||
// TODO The following three lines should be factored.
|
||||
constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1;
|
||||
char unknownX[bufferSize];
|
||||
|
||||
@@ -10,7 +10,7 @@ public:
|
||||
MinimumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor);
|
||||
const char * title() override;
|
||||
private:
|
||||
Poincare::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
Poincare::Coordinate2D<double> computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
};
|
||||
|
||||
class MaximumGraphController : public CalculationGraphController {
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
MaximumGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor);
|
||||
const char * title() override;
|
||||
private:
|
||||
Poincare::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
Poincare::Coordinate2D<double> computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -40,17 +40,17 @@ void IntersectionGraphController::reloadBannerView() {
|
||||
bannerView()->reload();
|
||||
}
|
||||
|
||||
Poincare::Coordinate2D IntersectionGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
|
||||
Poincare::Coordinate2D<double> IntersectionGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
|
||||
// TODO The following three lines should be factored.
|
||||
constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1;
|
||||
char unknownX[bufferSize];
|
||||
Poincare::SerializationHelper::CodePoint(unknownX, bufferSize, UCodePointUnknownX);
|
||||
Poincare::Coordinate2D result = Poincare::Coordinate2D(NAN, NAN);
|
||||
Poincare::Coordinate2D<double> result = Poincare::Coordinate2D<double>(NAN, NAN);
|
||||
for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) {
|
||||
Ion::Storage::Record record = functionStore()->activeRecordAtIndex(i);
|
||||
if (record != m_record) {
|
||||
Poincare::Expression e = functionStore()->modelForRecord(record)->expressionReduced(context);
|
||||
Poincare::Coordinate2D intersection = Shared::PoincareHelpers::NextIntersection(functionStore()->modelForRecord(m_record)->expressionReduced(context), unknownX, start, step, max, context, e);
|
||||
Poincare::Coordinate2D<double> intersection = Shared::PoincareHelpers::NextIntersection(functionStore()->modelForRecord(m_record)->expressionReduced(context), unknownX, start, step, max, context, e);
|
||||
if ((std::isnan(result.abscissa()) || std::fabs(intersection.abscissa()-start) < std::fabs(result.abscissa()-start)) && !std::isnan(intersection.abscissa())) {
|
||||
m_intersectedRecord = record;
|
||||
result = (std::isnan(result.abscissa()) || std::fabs(intersection.abscissa()-start) < std::fabs(result.abscissa()-start)) ? intersection : result;
|
||||
|
||||
@@ -12,7 +12,7 @@ public:
|
||||
const char * title() override;
|
||||
private:
|
||||
void reloadBannerView() override;
|
||||
Poincare::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
Poincare::Coordinate2D<double> computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
Ion::Storage::Record m_intersectedRecord;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ PreimageGraphController::PreimageGraphController(
|
||||
{
|
||||
}
|
||||
|
||||
Poincare::Coordinate2D PreimageGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
|
||||
Poincare::Coordinate2D<double> PreimageGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) {
|
||||
// TODO The following three lines should be factored.
|
||||
constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1;
|
||||
char unknownX[bufferSize];
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
double image() { return m_image; }
|
||||
void setImage(double value) { m_image = value; }
|
||||
private:
|
||||
Poincare::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
Poincare::Coordinate2D<double> computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
double m_image;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@ const char * RootGraphController::title() {
|
||||
return I18n::translate(I18n::Message::Zeros);
|
||||
}
|
||||
|
||||
Coordinate2D RootGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) {
|
||||
Coordinate2D<double> RootGraphController::computeNewPointOfInterest(double start, double step, double max, Context * context) {
|
||||
// TODO The following three lines should be factored.
|
||||
constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1;
|
||||
char unknownX[bufferSize];
|
||||
Poincare::SerializationHelper::CodePoint(unknownX, bufferSize, UCodePointUnknownX);
|
||||
return Coordinate2D(Shared::PoincareHelpers::NextRoot(functionStore()->modelForRecord(m_record)->expressionReduced(context), unknownX, start, step, max, context), 0.0);
|
||||
return Coordinate2D<double>(Shared::PoincareHelpers::NextRoot(functionStore()->modelForRecord(m_record)->expressionReduced(context), unknownX, start, step, max, context), 0.0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ public:
|
||||
RootGraphController(Responder * parentResponder, GraphView * graphView, BannerView * bannerView, Shared::InteractiveCurveViewRange * curveViewRange, Shared::CurveViewCursor * cursor);
|
||||
const char * title() override;
|
||||
private:
|
||||
Poincare::Coordinate2D computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
Poincare::Coordinate2D<double> computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ double Distribution::cumulativeDistributiveInverseForProbabilityUsingIncreasingF
|
||||
if (*probability <= 0.0) {
|
||||
return -INFINITY;
|
||||
}
|
||||
Poincare::Coordinate2D result = Poincare::Solver::IncreasingFunctionRoot(
|
||||
Poincare::Coordinate2D<double> result = Poincare::Solver::IncreasingFunctionRoot(
|
||||
ax,
|
||||
bx,
|
||||
FLT_EPSILON,
|
||||
|
||||
@@ -69,13 +69,13 @@ inline void ParseAndSimplifyAndApproximate(const char * text, Poincare::Expressi
|
||||
Poincare::Expression::ParseAndSimplifyAndApproximate(text, simplifiedExpression, approximateExpression, context, complexFormat, preferences->angleUnit(), symbolicComputation);
|
||||
}
|
||||
|
||||
inline typename Poincare::Coordinate2D NextMinimum(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context * context) {
|
||||
inline typename Poincare::Coordinate2D<double> NextMinimum(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context * context) {
|
||||
Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences();
|
||||
Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context);
|
||||
return e.nextMinimum(symbol, start, step, max, context, complexFormat, preferences->angleUnit());
|
||||
}
|
||||
|
||||
inline typename Poincare::Coordinate2D NextMaximum(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context * context) {
|
||||
inline typename Poincare::Coordinate2D<double> NextMaximum(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context * context) {
|
||||
Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences();
|
||||
Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context);
|
||||
return e.nextMaximum(symbol, start, step, max, context, complexFormat, preferences->angleUnit());
|
||||
@@ -87,7 +87,7 @@ inline double NextRoot(const Poincare::Expression e, const char * symbol, double
|
||||
return e.nextRoot(symbol, start, step, max, context, complexFormat, preferences->angleUnit());
|
||||
}
|
||||
|
||||
inline typename Poincare::Coordinate2D NextIntersection(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context * context, const Poincare::Expression expression) {
|
||||
inline typename Poincare::Coordinate2D<double> NextIntersection(const Poincare::Expression e, const char * symbol, double start, double step, double max, Poincare::Context * context, const Poincare::Expression expression) {
|
||||
Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences();
|
||||
Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, context);
|
||||
complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(complexFormat, expression, context);
|
||||
|
||||
@@ -5,16 +5,17 @@
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
template <typename T>
|
||||
class Coordinate2D final {
|
||||
public:
|
||||
Coordinate2D (double abscissa = NAN, double value = NAN) : m_abscissa(abscissa), m_value(value) {}
|
||||
double abscissa() const { return m_abscissa; }
|
||||
double value() const { return m_value; }
|
||||
void setAbscissa(double a) { m_abscissa = a; }
|
||||
void setValue(double v) { m_value = v; }
|
||||
Coordinate2D(T abscissa = NAN, T value = NAN) : m_abscissa(abscissa), m_value(value) {}
|
||||
T abscissa() const { return m_abscissa; }
|
||||
T value() const { return m_value; }
|
||||
void setAbscissa(T a) { m_abscissa = a; }
|
||||
void setValue(T v) { m_value = v; }
|
||||
private:
|
||||
double m_abscissa;
|
||||
double m_value;
|
||||
T m_abscissa;
|
||||
T m_value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -241,10 +241,10 @@ public:
|
||||
template<typename U> static U ApproximateToScalar(const char * text, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, bool symbolicComputation = true);
|
||||
template<typename U> U approximateWithValueForSymbol(const char * symbol, U x, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
|
||||
/* Expression roots/extrema solver */
|
||||
Coordinate2D nextMinimum(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
|
||||
Coordinate2D nextMaximum(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
|
||||
Coordinate2D<double> nextMinimum(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
|
||||
Coordinate2D<double> nextMaximum(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
|
||||
double nextRoot(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
|
||||
Coordinate2D nextIntersection(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const;
|
||||
Coordinate2D<double> nextIntersection(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const;
|
||||
|
||||
/* This class is meant to contain data about named functions (e.g. sin, tan...)
|
||||
* in one place: their name, their number of children and a pointer to a builder.
|
||||
@@ -391,9 +391,9 @@ private:
|
||||
/* Expression roots/extrema solver*/
|
||||
constexpr static double k_solverPrecision = 1.0E-5;
|
||||
constexpr static double k_maxFloat = 1e100;
|
||||
Coordinate2D nextMinimumOfExpression(const char * symbol, double start, double step, double max, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression(), bool lookForRootMinimum = false) const;
|
||||
Coordinate2D<double> nextMinimumOfExpression(const char * symbol, double start, double step, double max, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression(), bool lookForRootMinimum = false) const;
|
||||
void bracketMinimum(const char * symbol, double start, double step, double max, double result[3], Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const;
|
||||
Coordinate2D brentMinimum(const char * symbol, double ax, double bx, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const;
|
||||
Coordinate2D<double> brentMinimum(const char * symbol, double ax, double bx, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression = Expression()) const;
|
||||
double nextIntersectionWithExpression(const char * symbol, double start, double step, double max, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const;
|
||||
void bracketRoot(const char * symbol, double start, double step, double max, double result[2], Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const;
|
||||
double brentRoot(const char * symbol, double ax, double bx, double precision, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const;
|
||||
|
||||
@@ -11,11 +11,11 @@ class Solver {
|
||||
public:
|
||||
// Minimum
|
||||
typedef double (*ValueAtAbscissa)(double abscissa, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3);
|
||||
static Coordinate2D BrentMinimum(double ax, double bx, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1 = nullptr, const void * context2 = nullptr, const void * context3 = nullptr);
|
||||
static Coordinate2D<double> BrentMinimum(double ax, double bx, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1 = nullptr, const void * context2 = nullptr, const void * context3 = nullptr);
|
||||
|
||||
// Root
|
||||
static double BrentRoot(double ax, double bx, double precision, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1 = nullptr, const void * context2 = nullptr, const void * context3 = nullptr);
|
||||
static Coordinate2D IncreasingFunctionRoot(double ax, double bx, double precision, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1 = nullptr, const void * context2 = nullptr, const void * context3 = nullptr);
|
||||
static Coordinate2D<double> IncreasingFunctionRoot(double ax, double bx, double precision, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1 = nullptr, const void * context2 = nullptr, const void * context3 = nullptr);
|
||||
|
||||
// Proba
|
||||
|
||||
|
||||
@@ -873,7 +873,7 @@ Expression Expression::CreateComplexExpression(Expression ra, Expression tb, Pre
|
||||
|
||||
/* Expression roots/extrema solver*/
|
||||
|
||||
Coordinate2D Expression::nextMinimum(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||
Coordinate2D<double> Expression::nextMinimum(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||
return nextMinimumOfExpression(symbol, start, step, max,
|
||||
[](double x, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
const Expression * expression0 = reinterpret_cast<const Expression *>(context1);
|
||||
@@ -882,14 +882,14 @@ Coordinate2D Expression::nextMinimum(const char * symbol, double start, double s
|
||||
}, context, complexFormat, angleUnit);
|
||||
}
|
||||
|
||||
Coordinate2D Expression::nextMaximum(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||
Coordinate2D minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max,
|
||||
Coordinate2D<double> Expression::nextMaximum(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||
Coordinate2D<double> minimumOfOpposite = nextMinimumOfExpression(symbol, start, step, max,
|
||||
[](double x, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
const Expression * expression0 = reinterpret_cast<const Expression *>(context1);
|
||||
const char * symbol = reinterpret_cast<const char *>(context2);
|
||||
return -expression0->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit);
|
||||
}, context, complexFormat, angleUnit);
|
||||
return Coordinate2D(minimumOfOpposite.abscissa(), -minimumOfOpposite.value());
|
||||
return Coordinate2D<double>(minimumOfOpposite.abscissa(), -minimumOfOpposite.value());
|
||||
}
|
||||
|
||||
double Expression::nextRoot(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||
@@ -901,7 +901,7 @@ double Expression::nextRoot(const char * symbol, double start, double step, doub
|
||||
}, context, complexFormat, angleUnit, nullptr);
|
||||
}
|
||||
|
||||
Coordinate2D Expression::nextIntersection(const char * symbol, double start, double step, double max, Poincare::Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const {
|
||||
Coordinate2D<double> Expression::nextIntersection(const char * symbol, double start, double step, double max, Poincare::Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const {
|
||||
double resultAbscissa = nextIntersectionWithExpression(symbol, start, step, max,
|
||||
[](double x, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
const Expression * expression0 = reinterpret_cast<const Expression *>(context1);
|
||||
@@ -909,15 +909,15 @@ Coordinate2D Expression::nextIntersection(const char * symbol, double start, dou
|
||||
const Expression * expression1 = reinterpret_cast<const Expression *>(context3);
|
||||
return expression0->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit)-expression1->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit);
|
||||
}, context, complexFormat, angleUnit, expression);
|
||||
Coordinate2D result(resultAbscissa, approximateWithValueForSymbol(symbol, resultAbscissa, context, complexFormat, angleUnit));
|
||||
Coordinate2D<double> result(resultAbscissa, approximateWithValueForSymbol(symbol, resultAbscissa, context, complexFormat, angleUnit));
|
||||
if (std::fabs(result.value()) < step*k_solverPrecision) {
|
||||
result.setValue(0.0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Coordinate2D Expression::nextMinimumOfExpression(const char * symbol, double start, double step, double max, Solver::ValueAtAbscissa evaluate, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression, bool lookForRootMinimum) const {
|
||||
Coordinate2D result;
|
||||
Coordinate2D<double> Expression::nextMinimumOfExpression(const char * symbol, double start, double step, double max, Solver::ValueAtAbscissa evaluate, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression, bool lookForRootMinimum) const {
|
||||
Coordinate2D<double> result;
|
||||
if (start == max || step == 0.0) {
|
||||
return result;
|
||||
}
|
||||
@@ -954,10 +954,10 @@ Coordinate2D Expression::nextMinimumOfExpression(const char * symbol, double sta
|
||||
}
|
||||
|
||||
void Expression::bracketMinimum(const char * symbol, double start, double step, double max, double result[3], Solver::ValueAtAbscissa evaluate, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const {
|
||||
Coordinate2D p[3] = {
|
||||
Coordinate2D(start, evaluate(start, context, complexFormat, angleUnit, this, symbol, &expression)),
|
||||
Coordinate2D(start+step, evaluate(start+step, context, complexFormat, angleUnit, this, symbol, &expression)),
|
||||
Coordinate2D()
|
||||
Coordinate2D<double> p[3] = {
|
||||
Coordinate2D<double>(start, evaluate(start, context, complexFormat, angleUnit, this, symbol, &expression)),
|
||||
Coordinate2D<double>(start+step, evaluate(start+step, context, complexFormat, angleUnit, this, symbol, &expression)),
|
||||
Coordinate2D<double>()
|
||||
};
|
||||
double x = start+2.0*step;
|
||||
while (step > 0.0 ? x <= max : x >= max) {
|
||||
@@ -984,7 +984,7 @@ void Expression::bracketMinimum(const char * symbol, double start, double step,
|
||||
result[2] = NAN;
|
||||
}
|
||||
|
||||
Coordinate2D Expression::brentMinimum(const char * symbol, double ax, double bx, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const {
|
||||
Coordinate2D<double> Expression::brentMinimum(const char * symbol, double ax, double bx, Solver::ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const Expression expression) const {
|
||||
return Solver::BrentMinimum(
|
||||
ax,
|
||||
bx,
|
||||
@@ -1012,7 +1012,7 @@ double Expression::nextIntersectionWithExpression(const char * symbol, double st
|
||||
} while (std::isnan(result) && (step > 0.0 ? x <= max : x >= max));
|
||||
|
||||
double extremumMax = std::isnan(result) ? max : result;
|
||||
Coordinate2D resultExtremum[2] = {
|
||||
Coordinate2D<double> resultExtremum[2] = {
|
||||
nextMinimumOfExpression(symbol, start, step, extremumMax,
|
||||
[](double x, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
const Expression * expression0 = reinterpret_cast<const Expression *>(context1);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
Coordinate2D Solver::BrentMinimum(double ax, double bx, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
Coordinate2D<double> Solver::BrentMinimum(double ax, double bx, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
/* Bibliography: R. P. Brent, Algorithms for finding zeros and extrema of
|
||||
* functions without calculating derivatives */
|
||||
if (ax > bx) {
|
||||
@@ -34,7 +34,7 @@ Coordinate2D Solver::BrentMinimum(double ax, double bx, ValueAtAbscissa evaluati
|
||||
double fa = evaluation(a, context, complexFormat, angleUnit, context1, context2, context3);
|
||||
double fb = evaluation(b, context, complexFormat, angleUnit, context1, context2, context3);
|
||||
if (middleFax-fa <= k_sqrtEps && fx-middleFax <= k_sqrtEps && fx-middleFbx <= k_sqrtEps && middleFbx-fb <= k_sqrtEps) {
|
||||
return Coordinate2D(x, fx);
|
||||
return Coordinate2D<double>(x, fx);
|
||||
}
|
||||
}
|
||||
double p = 0;
|
||||
@@ -94,7 +94,7 @@ Coordinate2D Solver::BrentMinimum(double ax, double bx, ValueAtAbscissa evaluati
|
||||
}
|
||||
}
|
||||
}
|
||||
return Coordinate2D(x, fx);
|
||||
return Coordinate2D<double>(x, fx);
|
||||
}
|
||||
|
||||
double Solver::BrentRoot(double ax, double bx, double precision, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
@@ -174,7 +174,7 @@ double Solver::BrentRoot(double ax, double bx, double precision, ValueAtAbscissa
|
||||
return NAN;
|
||||
}
|
||||
|
||||
Coordinate2D Solver::IncreasingFunctionRoot(double ax, double bx, double precision, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
Coordinate2D<double> Solver::IncreasingFunctionRoot(double ax, double bx, double precision, ValueAtAbscissa evaluation, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, const void * context1, const void * context2, const void * context3) {
|
||||
assert(ax < bx);
|
||||
double min = ax;
|
||||
double max = bx;
|
||||
@@ -183,10 +183,10 @@ Coordinate2D Solver::IncreasingFunctionRoot(double ax, double bx, double precisi
|
||||
if (eval >= 0) {
|
||||
if (eval <= DBL_EPSILON) {
|
||||
// The value on the left bracket is 0, return it.
|
||||
return Coordinate2D(currentAbscissa, eval);
|
||||
return Coordinate2D<double>(currentAbscissa, eval);
|
||||
}
|
||||
// The minimal value is already bigger than 0, return NAN.
|
||||
return Coordinate2D(NAN, NAN);
|
||||
return Coordinate2D<double>(NAN, NAN);
|
||||
}
|
||||
while (max - min > precision) {
|
||||
currentAbscissa = (min + max) / 2.0;
|
||||
@@ -200,9 +200,9 @@ Coordinate2D Solver::IncreasingFunctionRoot(double ax, double bx, double precisi
|
||||
}
|
||||
}
|
||||
if (std::fabs(eval) < precision) {
|
||||
return Coordinate2D(currentAbscissa, eval);
|
||||
return Coordinate2D<double>(currentAbscissa, eval);
|
||||
}
|
||||
return Coordinate2D(NAN, NAN);
|
||||
return Coordinate2D<double>(NAN, NAN);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -24,7 +24,7 @@ bool doubles_are_approximately_equal(double d1, double d2) {
|
||||
void assert_next_extrema_are(
|
||||
ExtremumType extremumType,
|
||||
int numberOfExtrema,
|
||||
Coordinate2D * extrema,
|
||||
Coordinate2D<double> * extrema,
|
||||
Expression e,
|
||||
const char * symbol,
|
||||
Context * context,
|
||||
@@ -37,13 +37,13 @@ void assert_next_extrema_are(
|
||||
double currentStart = start;
|
||||
for (int i = 0; i < numberOfExtrema; i++) {
|
||||
quiz_assert_log_if_failure(!std::isnan(currentStart), e);
|
||||
Coordinate2D nextExtrema;
|
||||
Coordinate2D<double> nextExtrema;
|
||||
if (extremumType == ExtremumType::Maximum) {
|
||||
nextExtrema = e.nextMaximum(symbol, currentStart, step, max, context, complexFormat, angleUnit);
|
||||
} else if (extremumType == ExtremumType::Minimum) {
|
||||
nextExtrema = e.nextMinimum(symbol, currentStart, step, max, context, complexFormat, angleUnit);
|
||||
} else if (extremumType == ExtremumType::Root) {
|
||||
nextExtrema = Coordinate2D(e.nextRoot(symbol, currentStart, step, max, context, complexFormat, angleUnit), 0.0 );
|
||||
nextExtrema = Coordinate2D<double>(e.nextRoot(symbol, currentStart, step, max, context, complexFormat, angleUnit), 0.0 );
|
||||
}
|
||||
currentStart = nextExtrema.abscissa() + step;
|
||||
quiz_assert_log_if_failure(
|
||||
@@ -62,16 +62,16 @@ QUIZ_CASE(poincare_function_extremum) {
|
||||
Expression e = Cosine::Builder(Symbol::Builder(symbol, symbolLength));
|
||||
{
|
||||
constexpr int numberOfMaxima = 3;
|
||||
Coordinate2D maxima[numberOfMaxima] = {
|
||||
Coordinate2D(0.0, 1.0),
|
||||
Coordinate2D(360.0, 1.0),
|
||||
Coordinate2D(NAN, NAN)};
|
||||
Coordinate2D<double> maxima[numberOfMaxima] = {
|
||||
Coordinate2D<double>(0.0, 1.0),
|
||||
Coordinate2D<double>(360.0, 1.0),
|
||||
Coordinate2D<double>(NAN, NAN)};
|
||||
assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, &globalContext, -1.0, 0.1, 500.0);
|
||||
}
|
||||
{
|
||||
constexpr int numberOfMinima = 1;
|
||||
Coordinate2D minima[numberOfMinima] = {
|
||||
Coordinate2D(180.0, -1.0)};
|
||||
Coordinate2D<double> minima[numberOfMinima] = {
|
||||
Coordinate2D<double>(180.0, -1.0)};
|
||||
assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, &globalContext, 0.0, 0.1, 300.0);
|
||||
}
|
||||
}
|
||||
@@ -80,14 +80,14 @@ QUIZ_CASE(poincare_function_extremum) {
|
||||
Expression e = Power::Builder(Symbol::Builder(symbol, symbolLength), Rational::Builder(2));
|
||||
{
|
||||
constexpr int numberOfMaxima = 1;
|
||||
Coordinate2D maxima[numberOfMaxima] = {
|
||||
Coordinate2D(NAN, NAN)};
|
||||
Coordinate2D<double> maxima[numberOfMaxima] = {
|
||||
Coordinate2D<double>(NAN, NAN)};
|
||||
assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, &globalContext);
|
||||
}
|
||||
{
|
||||
constexpr int numberOfMinima = 1;
|
||||
Coordinate2D minima[numberOfMinima] = {
|
||||
Coordinate2D(0.0, 0.0)};
|
||||
Coordinate2D<double> minima[numberOfMinima] = {
|
||||
Coordinate2D<double>(0.0, 0.0)};
|
||||
assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, &globalContext);
|
||||
}
|
||||
}
|
||||
@@ -97,14 +97,14 @@ QUIZ_CASE(poincare_function_extremum) {
|
||||
Expression e = Rational::Builder(3);
|
||||
{
|
||||
constexpr int numberOfMaxima = 1;
|
||||
Coordinate2D maxima[numberOfMaxima] = {
|
||||
Coordinate2D(NAN, 3.0)};
|
||||
Coordinate2D<double> maxima[numberOfMaxima] = {
|
||||
Coordinate2D<double>(NAN, 3.0)};
|
||||
assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, &globalContext);
|
||||
}
|
||||
{
|
||||
constexpr int numberOfMinima = 1;
|
||||
Coordinate2D minima[numberOfMinima] = {
|
||||
Coordinate2D(NAN, 3.0)};
|
||||
Coordinate2D<double> minima[numberOfMinima] = {
|
||||
Coordinate2D<double>(NAN, 3.0)};
|
||||
assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, &globalContext);
|
||||
}
|
||||
}
|
||||
@@ -114,14 +114,14 @@ QUIZ_CASE(poincare_function_extremum) {
|
||||
Expression e = Rational::Builder(0);
|
||||
{
|
||||
constexpr int numberOfMaxima = 1;
|
||||
Coordinate2D maxima[numberOfMaxima] = {
|
||||
Coordinate2D(NAN, 0.0)};
|
||||
Coordinate2D<double> maxima[numberOfMaxima] = {
|
||||
Coordinate2D<double>(NAN, 0.0)};
|
||||
assert_next_extrema_are(ExtremumType::Maximum, numberOfMaxima, maxima, e, symbol, &globalContext);
|
||||
}
|
||||
{
|
||||
constexpr int numberOfMinima = 1;
|
||||
Coordinate2D minima[numberOfMinima] = {
|
||||
Coordinate2D(NAN, 0.0)};
|
||||
Coordinate2D<double> minima[numberOfMinima] = {
|
||||
Coordinate2D<double>(NAN, 0.0)};
|
||||
assert_next_extrema_are(ExtremumType::Minimum, numberOfMinima, minima, e, symbol, &globalContext);
|
||||
}
|
||||
}
|
||||
@@ -135,35 +135,35 @@ QUIZ_CASE(poincare_function_root) {
|
||||
// cos
|
||||
Expression e = Cosine::Builder(Symbol::Builder(symbol, symbolLength));
|
||||
constexpr int numberOfRoots = 3;
|
||||
Coordinate2D roots[numberOfRoots] = {
|
||||
Coordinate2D(90.0, 0.0),
|
||||
Coordinate2D(270.0, 0.0),
|
||||
Coordinate2D(450.0, 0.0)};
|
||||
Coordinate2D<double> roots[numberOfRoots] = {
|
||||
Coordinate2D<double>(90.0, 0.0),
|
||||
Coordinate2D<double>(270.0, 0.0),
|
||||
Coordinate2D<double>(450.0, 0.0)};
|
||||
assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext, 0.0, 0.1, 500.0);
|
||||
}
|
||||
{
|
||||
// x^2
|
||||
Expression e = Power::Builder(Symbol::Builder(symbol, symbolLength), Rational::Builder(2));
|
||||
constexpr int numberOfRoots = 1;
|
||||
Coordinate2D roots[numberOfRoots] = {
|
||||
Coordinate2D(0.0, 0.0)};
|
||||
Coordinate2D<double> roots[numberOfRoots] = {
|
||||
Coordinate2D<double>(0.0, 0.0)};
|
||||
assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext);
|
||||
}
|
||||
{
|
||||
// x^2-4
|
||||
Expression e = Subtraction::Builder(Power::Builder(Symbol::Builder(symbol, symbolLength), Rational::Builder(2)), Rational::Builder(4));
|
||||
constexpr int numberOfRoots = 2;
|
||||
Coordinate2D roots[numberOfRoots] = {
|
||||
Coordinate2D(-2.0, 0.0),
|
||||
Coordinate2D(2.0, 0.0)};
|
||||
Coordinate2D<double> roots[numberOfRoots] = {
|
||||
Coordinate2D<double>(-2.0, 0.0),
|
||||
Coordinate2D<double>(2.0, 0.0)};
|
||||
assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext, -5.0);
|
||||
}
|
||||
{
|
||||
// 3
|
||||
Expression e = Rational::Builder(3);
|
||||
constexpr int numberOfRoots = 1;
|
||||
Coordinate2D roots[numberOfRoots] = {
|
||||
Coordinate2D(NAN, 0.0)};
|
||||
Coordinate2D<double> roots[numberOfRoots] = {
|
||||
Coordinate2D<double>(NAN, 0.0)};
|
||||
assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext);
|
||||
}
|
||||
|
||||
@@ -171,8 +171,8 @@ QUIZ_CASE(poincare_function_root) {
|
||||
// 0
|
||||
Expression e = Rational::Builder(0);
|
||||
constexpr int numberOfRoots = 1;
|
||||
Coordinate2D roots[numberOfRoots] = {
|
||||
Coordinate2D(-0.9, 0.0)};
|
||||
Coordinate2D<double> roots[numberOfRoots] = {
|
||||
Coordinate2D<double>(-0.9, 0.0)};
|
||||
assert_next_extrema_are(ExtremumType::Root, numberOfRoots, roots, e, symbol, &globalContext);
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ QUIZ_CASE(poincare_function_root) {
|
||||
void assert_next_intersections_are(
|
||||
Expression otherExpression,
|
||||
int numberOfIntersections,
|
||||
Coordinate2D * intersections,
|
||||
Coordinate2D<double> * intersections,
|
||||
Expression e,
|
||||
const char * symbol,
|
||||
Context * context,
|
||||
@@ -194,7 +194,7 @@ void assert_next_intersections_are(
|
||||
double currentStart = start;
|
||||
for (int i = 0; i < numberOfIntersections; i++) {
|
||||
quiz_assert_log_if_failure(!std::isnan(currentStart), e);
|
||||
Coordinate2D nextIntersection = e.nextIntersection(symbol, currentStart, step, max, context, complexFormat, angleUnit, otherExpression);
|
||||
Coordinate2D<double> nextIntersection = e.nextIntersection(symbol, currentStart, step, max, context, complexFormat, angleUnit, otherExpression);
|
||||
currentStart = nextIntersection.abscissa() + step;
|
||||
quiz_assert_log_if_failure(
|
||||
(doubles_are_approximately_equal(intersections[i].abscissa(), nextIntersection.abscissa()))
|
||||
@@ -212,8 +212,8 @@ QUIZ_CASE(poincare_function_intersection) {
|
||||
// cos with y=2
|
||||
Expression otherExpression = Rational::Builder(2);
|
||||
constexpr int numberOfIntersections = 1;
|
||||
Coordinate2D intersections[numberOfIntersections] = {
|
||||
Coordinate2D(NAN, NAN)};
|
||||
Coordinate2D<double> intersections[numberOfIntersections] = {
|
||||
Coordinate2D<double>(NAN, NAN)};
|
||||
assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol, &globalContext);
|
||||
}
|
||||
|
||||
@@ -221,9 +221,9 @@ QUIZ_CASE(poincare_function_intersection) {
|
||||
// cos with y=1
|
||||
Expression otherExpression = Rational::Builder(1);
|
||||
constexpr int numberOfIntersections = 2;
|
||||
Coordinate2D intersections[numberOfIntersections] = {
|
||||
Coordinate2D(0.0, 1.0),
|
||||
Coordinate2D(360.0, 1.0)};
|
||||
Coordinate2D<double> intersections[numberOfIntersections] = {
|
||||
Coordinate2D<double>(0.0, 1.0),
|
||||
Coordinate2D<double>(360.0, 1.0)};
|
||||
assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol, &globalContext);
|
||||
}
|
||||
|
||||
@@ -231,10 +231,10 @@ QUIZ_CASE(poincare_function_intersection) {
|
||||
// cos with y=0
|
||||
Expression otherExpression = Rational::Builder(0);
|
||||
constexpr int numberOfIntersections = 3;
|
||||
Coordinate2D intersections[numberOfIntersections] = {
|
||||
Coordinate2D(90.0, 0.0),
|
||||
Coordinate2D(270.0, 0.0),
|
||||
Coordinate2D(450.0, 0.0)};
|
||||
Coordinate2D<double> intersections[numberOfIntersections] = {
|
||||
Coordinate2D<double>(90.0, 0.0),
|
||||
Coordinate2D<double>(270.0, 0.0),
|
||||
Coordinate2D<double>(450.0, 0.0)};
|
||||
assert_next_intersections_are(otherExpression, numberOfIntersections, intersections, e, symbol, &globalContext);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user