runCalculation method Null safety
override
Run the solve/integrate algorithm.
Implementation
@override
Future<bool> runCalculation() async {
// Algorithm translated from doc/HP-15C.tcl, secant, at line 5987
double x0 = model.yF;
double x1 = model.xF;
const ebs = 1e-14;
int cntmax = 25;
int ii = 2;
bool chs = false;
bool rc;
// From page 192 of the owner's handbook
if (x0 == x1) {
if (x0 == 0) {
x1 = 1e-7;
} else {
// "One count in the seventh significant digit"
x1 += pow(10, log10(x0).floorToDouble()) * 1e-6;
}
}
double resultX0 = await runSubroutine(x0);
double resultX1 = await runSubroutine(x1);
if (resultX0.isInfinite || resultX1.isInfinite) {
if (resultX0.isInfinite) {
model.zF = resultX0;
} else {
model.zF = resultX1;
}
model.yF = x0;
model.xF = x1;
return false;
}
for (;;) {
double slope;
if (resultX1 - resultX0 != 0) {
slope = (x1 - x0) / (resultX1 - resultX0);
slope = slope.abs() > 10 ? slope * 2 : slope;
} else if (resultX0 < 0) {
slope = -0.5001;
} else {
slope = 0.5001;
}
double x2 = x1 - resultX1 * slope;
// Optimization 1 (see TCL source)
if ((x2 - x1).abs() > 100 * (x0 - x1).abs()) {
x2 = x1 - 100 * (x0 - x1);
}
// Optimization 2 (see TCL source)
if (resultX0 * resultX1 < 0 && (x2 < min(x0, x1) || x2 > max(x0, x1))) {
x2 = (x0 + x1) / 2;
}
double resultX2 = await runSubroutine(x2);
while (resultX2.isInfinite && ii < cntmax) {
// Oops! Try a less agressive estimate, by backing off the slope.
// "4" is a guess. FWIW, this made
// "HP-15C_4.4.00_Programs/Users/Eddie Shore/Reactance chart solver.15c"
// work with the given example, and trying something when we get
// infinity from the function we call won't hurt.
slope /= 4;
x2 = x1 - resultX1 * slope;
resultX2 = await runSubroutine(x2);
cntmax++;
}
x0 = x1;
resultX0 = resultX1;
x1 = x2;
resultX1 = resultX2;
if (resultX0 * resultX1 < 0) {
chs = true;
}
ii++;
// Root found or abort?
if (resultX2.abs() < ebs ||
(resultX0 * resultX1 < 0 && (x0.abs() - x1.abs()).abs() < ebs)) {
rc = true;
break;
} else if (ii > cntmax) {
rc = chs;
break;
}
}
model.zF = resultX1;
model.yF = x0;
model.xF = x1;
return rc;
}