9 CartesianFunction::CartesianFunction(
const char * text,
KDColor color) :
11 m_displayDerivative(
false)
16 return m_displayDerivative;
20 m_displayDerivative = display;
66 }, context,
function);
68 if (
std::fabs(result.value) < step*k_precision) {
78 bool endCondition =
false;
80 bracketMinimum(x, step, max, bracket, evaluate, context,
function);
81 result = brentMinimum(bracket[0], bracket[2], evaluate, context,
function);
83 endCondition =
std::isnan(result.abscissa) && (step > 0.0 ? x <= max : x >= max);
84 if (lookForRootMinimum) {
85 endCondition |=
std::fabs(result.value) >= k_sqrtEps && (step > 0.0 ? x <= max : x >= max);
87 }
while (endCondition);
89 if (
std::fabs(result.abscissa) < step*k_precision) {
91 result.value = evaluate(0, context,
this,
function);
93 if (
std::fabs(result.value) < step*k_precision) {
96 if (lookForRootMinimum) {
97 result.abscissa =
std::fabs(result.value) >= k_sqrtEps ?
NAN : result.abscissa;
102 void CartesianFunction::bracketMinimum(
double start,
double step,
double max,
double result[3], Evaluation evaluate,
Context * context,
const Shared::Function *
function)
const {
104 p[0] = {.abscissa =
start, .value = evaluate(
start, context,
this,
function)};
105 p[1] = {.abscissa =
start+step, .value = evaluate(
start+step, context,
this,
function)};
106 double x =
start+2.0*step;
107 while (step > 0.0 ? x <= max : x >= max) {
108 p[2] = {.abscissa = x, .value = evaluate(x, context,
this,
function)};
109 if (p[0].value > p[1].value && p[2].value > p[1].value) {
110 result[0] = p[0].abscissa;
111 result[1] = p[1].abscissa;
112 result[2] = p[2].abscissa;
115 if (p[0].value > p[1].value && p[1].value == p[2].value) {
135 return brentMinimum(bx, ax, evaluate, context,
function);
140 double x = a+k_goldenRatio*(b-a);
143 double fx = evaluate(x, context,
this,
function);
150 for (
int i = 0; i < 100; i++) {
151 double m = 0.5*(a+b);
152 double tol1 = k_sqrtEps*
std::fabs(x)+1E-10;
153 double tol2 = 2.0*tol1;
155 double middleFax = evaluate((x+a)/2.0, context,
this,
function);
156 double middleFbx = evaluate((x+b)/2.0, context,
this,
function);
157 double fa = evaluate(a, context,
this,
function);
158 double fb = evaluate(b, context,
this,
function);
159 if (middleFax-fa <= k_sqrtEps && fx-middleFax <= k_sqrtEps && fx-middleFbx <= k_sqrtEps && middleFbx-fb <= k_sqrtEps) {
160 Point result = {.abscissa = x, .value = fx};
170 p = (x-v)*q -(x-w)*r;
183 if (u-a < tol2 || b-u < tol2) {
184 d = x < m ? tol1 : -tol1;
190 u = x + (
std::fabs(d) >= tol1 ? d : (d>0 ? tol1 : -tol1));
191 fu = evaluate(u, context,
this,
function);
210 if (fu <= fw || w == x) {
215 }
else if (fu <= fv || v == x || v == w) {
221 Point result = {.abscissa =
NAN, .value =
NAN};
225 double CartesianFunction::nextIntersectionWithFunction(
double start,
double step,
double max, Evaluation evaluation,
Context * context,
const Shared::Function *
function)
const {
228 static double precisionByGradUnit = 1
E6;
229 double x =
start+step;
231 bracketRoot(x, step, max, bracket, evaluation, context,
function);
232 result = brentRoot(bracket[0], bracket[1],
std::fabs(step/precisionByGradUnit), evaluation, context,
function);
234 }
while (
std::isnan(result) && (step > 0.0 ? x <= max : x >= max));
236 double extremumMax =
std::isnan(result) ? max : result;
237 Point resultExtremum[2] = {
244 }, context,
function,
true),
251 }, context,
function,
true)};
252 for (
int i = 0; i < 2; i++) {
254 result = resultExtremum[i].
abscissa;
257 if (
std::fabs(result) < step*k_precision) {
263 void CartesianFunction::bracketRoot(
double start,
double step,
double max,
double result[2], Evaluation evaluation,
Context * context,
const Shared::Function *
function)
const {
265 double b =
start+step;
266 while (step > 0.0 ? b <= max : b >= max) {
267 double fa = evaluation(a, context,
this,
function);
268 double fb = evaluation(b, context,
this,
function);
282 double CartesianFunction::brentRoot(
double ax,
double bx,
double precision, Evaluation evaluation,
Poincare::Context * context,
const Shared::Function *
function)
const {
284 return brentRoot(bx, ax, precision, evaluation, context,
function);
291 double fa = evaluation(a, context,
this,
function);
292 double fb = evaluation(b, context,
this,
function);
294 for (
int i = 0; i < 100; i++) {
295 if ((fb > 0.0 && fc > 0.0) || (fb < 0.0 && fc < 0.0)) {
310 double xm = 0.5*(
c-b);
311 if (
std::fabs(xm) <= tol1 || fb == 0.0) {
312 double fbcMiddle = evaluation(0.5*(b+
c), context,
this,
function);
313 double isContinuous = (fb <= fbcMiddle && fbcMiddle <= fc) || (fc <= fbcMiddle && fbcMiddle <= fb);
325 p = s*(2.0*xm*q*(q-r)-(b-a)*(r-1.0));
326 q = (q-1.0)*(r-1.0)*(s-1.0);
328 q = p > 0.0 ? -q : q;
330 double min1 = 3.0*xm*q-
std::fabs(tol1*q);
332 if (2.0*p < (min1 < min2 ? min1 : min2)) {
348 b += xm > 0.0 ? tol1 : tol1;
350 fb = evaluation(b, context,
this,
function);
Point nextMaximumFrom(double start, double step, double max, Poincare::Context *context) const
double sumBetweenBounds(double start, double end, Poincare::Context *context) const override
void(* Function)(const char *input)
void setDisplayDerivative(bool display)
Poincare::Expression * expression(Poincare::Context *context) const
double approximateDerivative(double x, Poincare::Context *context) const
double nextRootFrom(double start, double step, double max, Poincare::Context *context) const
char symbol() const override
static Complex< T > Float(T x)
virtual float evaluateAtAbscissa(float x, Poincare::Context *context) const
T approximateToScalar(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Point nextIntersectionFrom(double start, double step, double max, Poincare::Context *context, const Shared::Function *function) const
Point nextMinimumFrom(double start, double step, double max, Poincare::Context *context) const