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