File indexing completed on 2025-01-18 09:40:40
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_MATH_TOOLS_MINIMA_HPP
0008 #define BOOST_MATH_TOOLS_MINIMA_HPP
0009
0010 #ifdef _MSC_VER
0011 #pragma once
0012 #endif
0013
0014 #include <cstdint>
0015 #include <cmath>
0016 #include <utility>
0017 #include <boost/math/tools/precision.hpp>
0018 #include <boost/math/policies/policy.hpp>
0019
0020 namespace boost{ namespace math{ namespace tools{
0021
0022 template <class F, class T>
0023 std::pair<T, T> brent_find_minima(F f, T min, T max, int bits, std::uintmax_t& max_iter)
0024 noexcept(BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
0025 {
0026 BOOST_MATH_STD_USING
0027 bits = (std::min)(policies::digits<T, policies::policy<> >() / 2, bits);
0028 T tolerance = static_cast<T>(ldexp(1.0, 1-bits));
0029 T x;
0030 T w;
0031 T v;
0032 T u;
0033 T delta;
0034 T delta2;
0035 T fu, fv, fw, fx;
0036 T mid;
0037 T fract1, fract2;
0038
0039 static const T golden = 0.3819660f;
0040
0041 x = w = v = max;
0042 fw = fv = fx = f(x);
0043 delta2 = delta = 0;
0044
0045 uintmax_t count = max_iter;
0046
0047 do{
0048
0049 mid = (min + max) / 2;
0050
0051 fract1 = tolerance * fabs(x) + tolerance / 4;
0052 fract2 = 2 * fract1;
0053 if(fabs(x - mid) <= (fract2 - (max - min) / 2))
0054 break;
0055
0056 if(fabs(delta2) > fract1)
0057 {
0058
0059 T r = (x - w) * (fx - fv);
0060 T q = (x - v) * (fx - fw);
0061 T p = (x - v) * q - (x - w) * r;
0062 q = 2 * (q - r);
0063 if(q > 0)
0064 p = -p;
0065 q = fabs(q);
0066 T td = delta2;
0067 delta2 = delta;
0068
0069 if((fabs(p) >= fabs(q * td / 2)) || (p <= q * (min - x)) || (p >= q * (max - x)))
0070 {
0071
0072 delta2 = (x >= mid) ? min - x : max - x;
0073 delta = golden * delta2;
0074 }
0075 else
0076 {
0077
0078 delta = p / q;
0079 u = x + delta;
0080 if(((u - min) < fract2) || ((max- u) < fract2))
0081 delta = (mid - x) < 0 ? (T)-fabs(fract1) : (T)fabs(fract1);
0082 }
0083 }
0084 else
0085 {
0086
0087 delta2 = (x >= mid) ? min - x : max - x;
0088 delta = golden * delta2;
0089 }
0090
0091 u = (fabs(delta) >= fract1) ? T(x + delta) : (delta > 0 ? T(x + fabs(fract1)) : T(x - fabs(fract1)));
0092 fu = f(u);
0093 if(fu <= fx)
0094 {
0095
0096
0097 if(u >= x)
0098 min = x;
0099 else
0100 max = x;
0101
0102 v = w;
0103 w = x;
0104 x = u;
0105 fv = fw;
0106 fw = fx;
0107 fx = fu;
0108 }
0109 else
0110 {
0111
0112
0113 if(u < x)
0114 min = u;
0115 else
0116 max = u;
0117 if((fu <= fw) || (w == x))
0118 {
0119
0120 v = w;
0121 w = u;
0122 fv = fw;
0123 fw = fu;
0124 }
0125 else if((fu <= fv) || (v == x) || (v == w))
0126 {
0127
0128 v = u;
0129 fv = fu;
0130 }
0131 }
0132
0133 }while(--count);
0134
0135 max_iter -= count;
0136
0137 return std::make_pair(x, fx);
0138 }
0139
0140 template <class F, class T>
0141 inline std::pair<T, T> brent_find_minima(F f, T min, T max, int digits)
0142 noexcept(BOOST_MATH_IS_FLOAT(T) && noexcept(std::declval<F>()(std::declval<T>())))
0143 {
0144 std::uintmax_t m = (std::numeric_limits<std::uintmax_t>::max)();
0145 return brent_find_minima(f, min, max, digits, m);
0146 }
0147
0148 }}}
0149
0150 #endif
0151
0152
0153
0154