[poincare/Coordinate2D] Template for double or float

This commit is contained in:
Léa Saviot
2019-08-28 11:20:38 +02:00
parent 22dd9752a5
commit a15bc53e06
18 changed files with 104 additions and 103 deletions

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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];

View File

@@ -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;
};
}

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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];

View File

@@ -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;
};

View File

@@ -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);
}
}

View File

@@ -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;
};
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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;
};
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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>

View File

@@ -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);
}
}