Virtual Testbed
Ship dynamics simulator for extreme conditions
bisection.hh
1 #ifndef VTESTBED_CORE_BISECTION_HH
2 #define VTESTBED_CORE_BISECTION_HH
3 
4 #include <vtestbed/base/blitz.hh>
5 
6 //#define VTB_DEBUG_BISECTION
7 
8 namespace vtb {
9 
10  namespace core {
11 
12  template <class T, int N, class F>
13  blitz::TinyVector<T,N>
14  bisection(
15  blitz::TinyVector<T,N> a,
16  blitz::TinyVector<T,N> b,
17  F func,
18  const blitz::TinyVector<T,N>& arg_eps,
19  const blitz::TinyVector<T,N>& func_eps,
20  int max_iter
21  ) {
22  typedef blitz::TinyVector<T,N> vec;
23  vec fa{func(a)};
24  if (all(abs(fa) < func_eps)) {
25  #if defined(VTB_DEBUG_BISECTION)
26  std::clog
27  << __func__ << ": "
28  << "a=" << a
29  << ",b=" << b
30  << ",fa=" << fa
31  << '\n';
32  #endif
33  return a;
34  }
35  vec fb{func(b)};
36  if (all(abs(fb) < func_eps)) {
37  #if defined(VTB_DEBUG_BISECTION)
38  std::clog
39  << __func__ << ": "
40  << "a=" << a
41  << ",b=" << b
42  << ",fb=" << fb
43  << '\n';
44  #endif
45  return b;
46  }
47  vec c, fc;
48  c = 0, fc = 0;
49  for (int i=1; i<=max_iter; ++i) {
50  c = T{0.5}*(a + b);
51  fc = func(c);
52  for (int j=0; j<N; ++j) {
53  if (fa(j)*fc(j) < 0) {
54  b(j) = c(j);
55  fb(j) = fc(j);
56  } else if (fb(j)*fc(j) < 0) {
57  a(j) = c(j);
58  fa(j) = fc(j);
59  } else {
60  if (abs(fa(j)) < abs(fb(j))) {
61  c(j) = a(j);
62  } else {
63  c(j) = b(j);
64  }
65  //return c;
66  }
67  }
68  #if defined(VTB_DEBUG_BISECTION)
69  std::clog
70  << __func__ << ": "
71  << "a=" << a
72  << ",b=" << b
73  << ",c=" << c
74  << ",fa=" << fa
75  << ",fb=" << fb
76  << ",fc=" << fc
77  << '\n';
78  #endif
79  if (all(abs(b-a) < arg_eps) && all(abs(fc) < func_eps)) {
80  break;
81  }
82  }
83  return c;
84  }
85 
95  template <class T, class F>
96  T
97  bisection(T a, T b, F func, T arg_eps, T func_eps, int max_iter) {
98  using std::abs;
99  T fa = func(a);
100  if (abs(fa) < func_eps) {
101  return a;
102  }
103  T fb = func(b);
104  if (abs(fb) < func_eps) {
105  return b;
106  }
107  T c{0}, fc{0};
108  for (int i=0; i<max_iter; ++i) {
109  c = T{0.5}*(a + b);
110  fc = func(c);
111  if (fa*fc < 0) {
112  b = c;
113  fb = fc;
114  } else if (fb*fc < 0) {
115  a = c;
116  fa = fc;
117  } else {
118  if (abs(fa) < abs(fb)) {
119  c = a;
120  } else {
121  c = b;
122  }
123  break;
124  }
125  #if defined(VTB_DEBUG_BISECTON)
126  const int w = 12;
127  std::clog
128  << std::setw(w) << i
129  << std::setw(w) << a
130  << std::setw(w) << b
131  << std::setw(w) << fa
132  << std::setw(w) << fb
133  << std::setw(w) << fc
134  << std::endl;
135  #endif
136  if (abs(b-a) < arg_eps && abs(fc) < func_eps) {
137  break;
138  }
139  }
140  return c;
141  }
142 
143  template <class T, int N>
144  class Bisection {
145 
146  private:
147  using vec = blitz::TinyVector<T,N>;
148 
149  private:
150  vec _argeps{T{1e-3}};
151  vec _funceps{T{1e-3}};
152  int _niterations = 100;
153 
154  public:
155 
156  Bisection() = default;
157 
158  inline
159  Bisection(
160  const vec& argeps,
161  const vec& funceps,
162  int niterations
163  ):
164  _argeps(argeps),
165  _funceps(funceps),
166  _niterations(niterations)
167  {}
168 
169  template <class Func>
170  vec
171  operator()(const vec& lbound, const vec& ubound, Func func) const {
172  return bisection<T,N,Func>(
173  lbound,
174  ubound,
175  func,
176  this->_argeps,
177  this->_funceps,
178  this->_niterations
179  );
180  }
181 
182  inline void
183  argument_precision(const vec& eps) {
184  this->_argeps = eps;
185  }
186 
187  inline void
188  function_precision(const vec& eps) {
189  this->_funceps = eps;
190  }
191 
192  inline int max_iterations() const noexcept { return this->_niterations; }
193  inline void max_iterations(int n) { this->_niterations = n; }
194 
195  };
196 
197  template <class T>
198  class Bisection<T,1> {
199 
200  private:
201  T _argeps{1e-3};
202  T _funceps{1e-3};
203  int _niterations = 100;
204 
205  public:
206 
207  Bisection() = default;
208 
209  inline
210  Bisection(const T& argeps, const T& funceps, int niterations):
211  _argeps(argeps), _funceps(funceps), _niterations(niterations) {}
212 
213  template <class Func>
214  T
215  operator()(const T& lbound, const T& ubound, Func func) const {
216  return bisection<T,Func>(
217  lbound,
218  ubound,
219  func,
220  this->_argeps,
221  this->_funceps,
222  this->_niterations
223  );
224  }
225 
226  inline void
227  argument_precision(T eps) {
228  this->_argeps = eps;
229  }
230 
231  inline void
232  function_precision(T eps) {
233  this->_funceps = eps;
234  }
235 
236  inline int
237  max_iterations() const noexcept {
238  return this->_niterations;
239  }
240 
241  inline void
242  max_iterations(int n) {
243  this->_niterations = n;
244  }
245 
246  };
247 
248  }
249 
250 }
251 
252 #endif // vim:filetype=cpp
Main namespace.
Definition: convert.hh:9