suanPan
Loading...
Searching...
No Matches
ridders.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 * Copyright (C) 2017-2025 Theodore Chang
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17
18#ifndef RIDDERS_HPP
19#define RIDDERS_HPP
20
21#include <suanPan.h>
22
38template<std::invocable<double> T> double ridders(const T& func, double x1, double f1, double x2, double f2, const double tolerance) {
39 double target;
40
41 auto counter = 0u;
42 while(true) {
43 counter += 2u;
44
45 const auto x3 = .5 * (x1 + x2);
46 const auto f3 = func(x3);
47 if(std::fabs(f3) < tolerance || std::fabs(x2 - x1) < tolerance) {
48 target = x3;
49 break;
50 }
51
52 const auto dx = (x3 - x1) * f3 / std::sqrt(f3 * f3 - f1 * f2);
53
54 const auto x4 = f1 > f2 ? x3 + dx : x3 - dx;
55 const auto f4 = func(x4);
56 if(std::fabs(f4) < tolerance) {
57 target = x4;
58 break;
59 }
60
61 // one end is x4
62 // pick the other from x3, x2, x1
63 if(std::signbit(f4) != std::signbit(f3)) {
64 x1 = x3;
65 f1 = f3;
66 }
67 else if(std::signbit(f4) != std::signbit(f2)) {
68 x1 = x2;
69 f1 = f2;
70 }
71
72 x2 = x4;
73 f2 = f4;
74 }
75
76 suanpan_debug("Ridders' method initial guess {:.5E} with {} iterations.\n", target, counter);
77
78 return target;
79}
80
81template<std::invocable<double> T> double ridders(const T& func, double x1, double x2, const double tolerance) { return ridders(func, x1, func(x1), x2, func(x2), tolerance); }
82
83template<std::invocable<double> T> double ridders_guess(const T& func, double x1, double f1, double x2, double f2, const double tolerance) {
84 while(std::signbit(f1) == std::signbit(f2)) {
85 x1 = x2;
86 f1 = f2;
87 f2 = func(x2 *= 2.);
88 }
89
90 return ridders(func, x1, f1, x2, f2, tolerance);
91}
92
93template<std::invocable<double> T> double ridders_guess(const T& func, double x1, double x2, const double tolerance) { return ridders_guess(func, x1, func(x1), x2, func(x2), tolerance); }
94
95#endif
96
double ridders(const T &func, double x1, double f1, double x2, double f2, const double tolerance)
Implements Ridders' method for finding the root of a function.
Definition ridders.hpp:38
double ridders_guess(const T &func, double x1, double f1, double x2, double f2, const double tolerance)
Definition ridders.hpp:83
#define suanpan_debug(...)
Definition suanPan.h:374