runCalculation method Null safety

  1. @override
Future<bool> runCalculation()
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;
}