67 if (thetamax <= 0)
throw UnsupportedError(
"snc_thetaopt: thetamax must be positive");
69 const double loExp = -6.0, hiExp = std::log10(thetamax);
70 std::vector<double> grid(GRID), fval(GRID);
72 for (
int i = 0; i < GRID; ++i) {
73 grid[i] = std::pow(10.0, loExp + (hiExp - loExp) * i / (GRID - 1.0));
74 fval[i] = detail::snc_safeval(fun, grid[i]);
75 if (fval[i] < fval[imin]) imin = i;
77 double val = fval[imin];
79 return SncResult{std::numeric_limits<double>::infinity(),
80 std::numeric_limits<double>::quiet_NaN()};
81 double theta = grid[imin];
83 double lo = std::log10(grid[std::max(imin - 1, 0)]);
84 double hi = std::log10(grid[std::min(imin + 1, GRID - 1)]);
86 const double invphi = (std::sqrt(5.0) - 1.0) / 2.0;
87 double x1 = hi - invphi * (hi - lo), x2 = lo + invphi * (hi - lo);
88 double f1 = detail::snc_safeval(fun, std::pow(10.0, x1));
89 double f2 = detail::snc_safeval(fun, std::pow(10.0, x2));
90 for (
int it = 0; it < 200 && (hi - lo) > 1e-12; ++it) {
95 x1 = hi - invphi * (hi - lo);
96 f1 = detail::snc_safeval(fun, std::pow(10.0, x1));
101 x2 = lo + invphi * (hi - lo);
102 f2 = detail::snc_safeval(fun, std::pow(10.0, x2));
105 const double xopt = 0.5 * (lo + hi);
106 const double vopt = detail::snc_safeval(fun, std::pow(10.0, xopt));
109 theta = std::pow(10.0, xopt);