solve method

  1. @override
({double convergence, double efficiency, List<double> guesses}) solve()
override

Generates the succession generated by the root-finding algorithm. Returns a Record object whose members are:

  • a guesses named field, which contains the list of values generated by the algorithm on each step;

  • a convergence named field, whose value represents the convergence rate for the generated succession (computed using convergence).

  • a efficiency named field, whose value represents the efficiency of the algorithm (computed using efficiency).

Implementation

@override
({List<double> guesses, double convergence, double efficiency}) solve() {
  final guesses = <double>[];
  var n = 1;

  final evalA = evaluateOn(a);
  final evalB = evaluateOn(b);

  // Making sure that the root is in the given interval
  if (evalA * evalB >= 0) {
    throw const NonlinearException('The root is not bracketed.');
  }

  // Variables setup
  var valueA = a;
  var valueB = b;
  var valueC = a;
  var valueD = 0.0;
  var diff = (valueB - valueA).abs();
  var s = 0.0;
  var flag = true;

  if (evalA.abs() < evalB.abs()) {
    final temp = valueA;
    valueA = valueB;
    valueB = temp;
  }

  while ((diff >= tolerance) && (n <= maxSteps)) {
    final fa = evaluateOn(valueA);
    final fb = evaluateOn(valueB);
    final fc = evaluateOn(valueC);

    if ((fa != fc) && (fb != fc)) {
      // Inverse quadratic interpolation method
      final term1 = valueA * fb * fc / ((fa - fb) * (fa - fc));
      final term2 = valueB * fa * fc / ((fb - fa) * (fb - fc));
      final term3 = valueC * fa * fb / ((fc - fa) * (fc - fb));

      s = term1 + term2 + term3;
    } else {
      // Secant method
      s = valueB - (fb * ((valueB - valueA) / (fb - fa)));
    }

    if (_condition1(s, valueA, valueB) ||
        _condition2(s, flag, valueB, valueC) ||
        _condition3(s, flag, valueB, valueC, valueD) ||
        _condition4(flag, valueB, valueC) ||
        _condition5(flag, valueC, valueD)) {
      // Bisection method
      s = (valueA + valueB) / 2;
    } else {
      flag = false;
    }

    // 's' is the value of the root to be discovered
    guesses.add(s);

    // Generating new brackets for the next iteration
    final fs = evaluateOn(s);
    valueD = valueC;
    valueC = valueB;

    if (fa * fs < 0) {
      valueB = s;
    } else {
      valueA = s;
    }

    if (fa.abs() < fb.abs()) {
      final temp = valueA;
      valueA = valueB;
      valueB = temp;
    }

    // Updating the exit conditions
    ++n;
    diff = (valueB - valueA).abs();
  }

  return (
    guesses: guesses,
    convergence: convergence(guesses, maxSteps),
    efficiency: efficiency(guesses, maxSteps),
  );
}