public double Solve(VariableRangeRestriction previousValue, VariableRangeRestriction restriction) { double result = _illinois.Solve(previousValue, restriction); if (double.IsNaN(result)) { result = _iteration.Solve(previousValue, restriction); } return result; }
public double Solve(VariableRangeRestriction startValue, VariableRangeRestriction restriction) { double x0 = startValue.GetSomeValue(); double delta = _delta; for (int i = 0; ; i++) { Range[] possibleRanges = Range.CreateClosed(x0 - delta, x0 + delta).Intersect(restriction.PossibleRanges).ToArray(); if (possibleRanges.Length == 0) { return double.NaN; } double x1 = possibleRanges[0].LoApproximateDouble; // TODO: But what if the range is open?? double x2 = possibleRanges[0].HiApproximateDouble; for (int j = 1; j < possibleRanges.Length && x1 == x2; j++) { x2 = possibleRanges[j].HiApproximateDouble; } double f1 = f(x1); double f2 = f(x2); // TODO: What if fL or fH is NaN? Should not happen, because we restrict ourselves to "restriction", but still ... double k = (f2 - f1) / (x2 - x1); double d = f2 - k * x2; x0 = -d / k; if (!restriction.Contains(x0)) { // The secant intersects the x-axis in an undefined segment. // So we have to replace x0 with some valid x; we use the nearest defined x. double bestReplacement = 1e100; foreach (var r in restriction.PossibleRanges) { bestReplacement = BetterReplacement(bestReplacement, x0, r.LoApproximateDouble); bestReplacement = BetterReplacement(bestReplacement, x0, r.HiApproximateDouble); } x0 = bestReplacement; } double f0 = f(x0); // TODO: Again, f0 could be NaN? Should not happen, because we restrict ourselves to "restriction", but still ... delta /= 2.0; if (x1.Near(x2) && f0.Near(0)) { return (x1 + x2) / 2; } if ((1e6 * f0).Near(0)) { return (x1 + x2) / 2; } if (double.IsNaN(f0) || i > 100) { return double.NaN; } } }
public double Solve(VariableRangeRestriction previousValue, VariableRangeRestriction restriction) { foreach (var range in restriction.PossibleRanges) { double x1 = range.LoApproximateDouble; double x2 = range.HiApproximateDouble; var f1 = f(x1); var f2 = f(x2); if (f1 * f2 <= 0) { double result = Illinois(x1, x2, f1, f2); if (!double.IsNaN(result)) { return result; } } } return double.NaN; }