OGS
Root1D.h
Go to the documentation of this file.
1
11#pragma once
12
13#include <cassert>
14#include <cmath>
15#include <limits>
16#include <type_traits>
17#include <utility>
18
19#include "BaseLib/Error.h"
20
21namespace MathLib
22{
23namespace Nonlinear
24{
25
26namespace detail
27{
28
30inline bool same_sign(double a, double b)
31{
32 // note: signbit() casts integers to double and distinguishes between +0.0 and
33 // -0.0. However, the latter is not a problem, because if f(x0) == 0, we've
34 // already found the root x0 that we are searching for.
35 return std::signbit(a) == std::signbit(b);
36}
37
38inline bool almost_zero(double a)
39{
40 return std::abs(a) <= std::numeric_limits<double>::epsilon();
41}
42
43} // namespace detail
44
47template<typename SubType, typename Function>
49{
50public:
53 RegulaFalsi(Function&& f, double a, double b)
54 : f_(f), a_(a), b_(b), fa_(f(a)), fb_(f(b))
55 {
56 static_assert(std::is_same_v<double, decltype(f(0.0))>,
57 "Using this class for functions that do not return double"
58 " involves a lot of casts. Hence it is disabled.");
59
61 {
62 b_ = a_;
63 }
64 else if (detail::almost_zero(fb_))
65 {
66 a_ = b_;
67 }
68 else if (detail::same_sign(fa_, fb_))
69 {
70 OGS_FATAL("Regula falsi cannot be done, because the function values"
71 " at the interval ends have the same sign.");
72 }
73 }
74
76 void step(const unsigned num_steps)
77 {
78 for (unsigned i=0; i<num_steps; ++i)
79 {
80 if (a_ == b_)
81 {
82 return;
83 }
84
85 const double s = (fb_ - fa_) / (b_ - a_);
86 const double c = a_ - fa_ / s;
87 const double fc = f_(c);
88
89 if (detail::almost_zero(fc)) {
90 a_ = b_ = c;
91 return;
92 }
93 if (!detail::same_sign(fc, fb_))
94 {
95 a_ = b_;
96 fa_ = fb_;
97 b_ = c;
98 fb_ = fc;
99 } else {
100 const double m = SubType::get_m(fa_, fb_, fc);
101 fa_ *= m;
102 b_ = c;
103 fb_ = fc;
104 }
105 }
106 }
107
109 double getResult() const
110 {
111 if (a_ == b_)
112 {
113 return a_;
114 }
115
116 const double s = (fb_ - fa_) / (b_ - a_);
117 const double c = a_ - fa_ / s;
118
119 return c;
120 }
121
123 double getRange() const { return std::abs(a_ - b_); }
124
125private:
126 Function f_;
127 double a_, b_, fa_, fb_;
128};
129
130
136template <typename SubType, typename Function>
138 double const a,
139 double const b)
140{
141 return RegulaFalsi<SubType, Function>(std::forward<Function>(f), a, b);
142}
143
144
147{
148 static double get_m(const double /*fa*/, const double /*fb*/, const double /*fc*/)
149 { return 1.0; }
150};
151
154{
155 static double get_m(const double /*fa*/, const double /*fb*/, const double /*fc*/)
156 { return 0.5; }
157};
158
161{
162 static double get_m(const double /*fa*/, const double fb, const double fc)
163 { return fb / (fb+fc); }
164};
165
168{
169 static double get_m(const double /*fa*/, const double fb, const double fc)
170 {
171 const double v = 1.0 - fc / fb;
172 return (v >= 0.0) ? v : 0.5;
173 }
174};
175
176} // namespace Nonlinear
177
178} // namespace MathLib
#define OGS_FATAL(...)
Definition Error.h:26
void step(const unsigned num_steps)
Do num_steps iteration of regula falsi.
Definition Root1D.h:76
double getResult() const
Returns the current estimate of the root.
Definition Root1D.h:109
RegulaFalsi(Function &&f, double a, double b)
Definition Root1D.h:53
double getRange() const
Returns the size of the current search interval.
Definition Root1D.h:123
bool almost_zero(double a)
Definition Root1D.h:38
bool same_sign(double a, double b)
Tells if a and b have the same sign.
Definition Root1D.h:30
RegulaFalsi< SubType, Function > makeRegulaFalsi(Function &&f, double const a, double const b)
Definition Root1D.h:137
static const double s
static const double v
Used by RegulaFalsi in a modified version of the regula falsi algorithm.
Definition Root1D.h:168
static double get_m(const double, const double fb, const double fc)
Definition Root1D.h:169
Used by RegulaFalsi in a modified version of the regula falsi algorithm.
Definition Root1D.h:154
static double get_m(const double, const double, const double)
Definition Root1D.h:155
Used by RegulaFalsi in a modified version of the regula falsi algorithm.
Definition Root1D.h:161
static double get_m(const double, const double fb, const double fc)
Definition Root1D.h:162
Used by RegulaFalsi in the original regula falsi algorithm.
Definition Root1D.h:147
static double get_m(const double, const double, const double)
Definition Root1D.h:148