public void RootsTest3(double step) { Test.Begin("cubic roots tests"); var range = new Range1d(-1.0, 1.0); double half = 0.5 * step; double epsilon = Fun.Cbrt(Constant <double> .PositiveTinyValue); Report.Value("epsilon", epsilon); var stats = Stats <bool> .ComputeMaxMean; var uniqueStats = Stats <bool> .ComputeMaxMean; var multipleStats = Stats <bool> .ComputeMaxMean; var residualStats = Stats <bool> .ComputeMaxMean; var uniqueHisto = new Histogram(-16, -8, 8); var multipleHisto = new Histogram(-16, 0, 16); var uniqueResidualStats = Stats <bool> .ComputeMaxMean; var multipleResidualStats = Stats <bool> .ComputeMaxMean; long multipleCount = 0; for (double x0 = range.Min; x0 < range.Max + half; x0 += step) { var p0 = new double[] { -x0, 1.0 }; for (double x1 = range.Min; x1 < range.Max + half; x1 += step) { var p1 = new double[] { -x1, 1.0 }; var p01 = Polynomial.Multiply(p0, p1); for (double x2 = range.Min; x2 < range.Max + half; x2 += step) { var p2 = new double[] { -x2, 1.0 }; var p012 = Polynomial.Multiply(p01, p2); var t = Triple.CreateAscending(x0, x1, x2); var exact = new double[] { t.E0, t.E1, t.E2 }; var roots = p012.RealRoots(); var multiple = CountDoubles(exact, 0.0001); if (multiple > 0) { ++multipleCount; } var rootCountsOk = exact.Length == roots.Length; Test.IsTrue(rootCountsOk, "wrong number of roots found"); if (!rootCountsOk) { using (Report.Job("problematic roots:")) { Report.Line("exact: [" + exact.Select(x => x.ToString()).Join(",") + "]"); Report.Line("roots: [" + roots.Select(x => x.ToString()).Join(",") + "]"); } continue; } for (int i = 0; i < 3; i++) { var err = (exact[i] - roots[i]).Abs(); Test.IsTrue(err < epsilon, "root differs significantly from exact value {0}", err); double res = p012.Evaluate(roots[i]).Abs(); stats.Add(err); residualStats.Add(res); if (multiple == 0) { uniqueStats.Add(err); uniqueHisto.AddLog10(err); uniqueResidualStats.Add(res); } else { multipleStats.Add(err); multipleHisto.AddLog10(err); multipleResidualStats.Add(res); } } } } } Report.Value("roots error", stats); Report.Value("unique roots error", uniqueStats); Report.Value("unique roots log error histogram", uniqueHisto); Report.Value("multiple roots error", multipleStats); Report.Value("multiple roots log error histogram", multipleHisto); Report.Value("residual error", residualStats); Report.Value("unique roots residual error", uniqueResidualStats); Report.Value("multiple residual error", multipleResidualStats); Test.End(); }