File indexing completed on 2026-09-28 09:20:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef _MathRoot_Brent_HeaderFile
0015 #define _MathRoot_Brent_HeaderFile
0016
0017 #include <MathUtils_Types.hxx>
0018 #include <MathUtils_Config.hxx>
0019 #include <MathUtils_Core.hxx>
0020
0021 #include <cmath>
0022 #include <utility>
0023
0024 namespace MathRoot
0025 {
0026 using namespace MathUtils;
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 template <typename Function>
0045 MathUtils::ScalarResult Brent(Function& theFunc,
0046 double theLower,
0047 double theUpper,
0048 const MathUtils::Config& theConfig = MathUtils::Config())
0049 {
0050 MathUtils::ScalarResult aResult;
0051
0052 double aA = theLower;
0053 double aB = theUpper;
0054 double aFa = 0.0;
0055 double aFb = 0.0;
0056
0057
0058 if (!theFunc.Value(aA, aFa))
0059 {
0060 aResult.Status = MathUtils::Status::NumericalError;
0061 return aResult;
0062 }
0063 if (!theFunc.Value(aB, aFb))
0064 {
0065 aResult.Status = MathUtils::Status::NumericalError;
0066 return aResult;
0067 }
0068
0069
0070 if (aFa * aFb > 0.0)
0071 {
0072 aResult.Status = MathUtils::Status::InvalidInput;
0073 return aResult;
0074 }
0075
0076
0077 if (std::abs(aFa) < std::abs(aFb))
0078 {
0079 std::swap(aA, aB);
0080 std::swap(aFa, aFb);
0081 }
0082
0083 double aC = aA;
0084 double aFc = aFa;
0085 double aD = aB - aA;
0086 double aE = aD;
0087
0088 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0089 {
0090 aResult.NbIterations = anIter + 1;
0091
0092 const double aTol = 2.0 * MathUtils::THE_EPSILON * std::abs(aB) + 0.5 * theConfig.XTolerance;
0093 const double aM = 0.5 * (aC - aB);
0094
0095 if (std::abs(aFb) < theConfig.FTolerance || aFb == 0.0 || std::abs(aM) <= aTol)
0096 {
0097 aResult.Status = MathUtils::Status::OK;
0098 aResult.Root = aB;
0099 aResult.Value = aFb;
0100 return aResult;
0101 }
0102
0103 double aS = 0.0;
0104
0105
0106 if (std::abs(aFa - aFc) > MathUtils::THE_ZERO_TOL
0107 && std::abs(aFb - aFc) > MathUtils::THE_ZERO_TOL)
0108 {
0109
0110 aS = aA * aFb * aFc / ((aFa - aFb) * (aFa - aFc))
0111 + aB * aFa * aFc / ((aFb - aFa) * (aFb - aFc))
0112 + aC * aFa * aFb / ((aFc - aFa) * (aFc - aFb));
0113 }
0114 else
0115 {
0116
0117 aS = aB - aFb * (aB - aA) / (aFb - aFa);
0118 }
0119
0120
0121 bool aUseInterp = false;
0122
0123
0124 const double aBound1 = (3.0 * aA + aB) / 4.0;
0125 if ((aS > std::min(aBound1, aB) && aS < std::max(aBound1, aB)))
0126 {
0127
0128
0129 if (std::abs(aS - aB) < std::abs(aE) / 2.0)
0130 {
0131 aUseInterp = true;
0132 }
0133 }
0134
0135 if (!aUseInterp)
0136 {
0137
0138 aS = aB + aM;
0139 aE = aM;
0140 aD = aM;
0141 }
0142 else
0143 {
0144 aE = aD;
0145 aD = aS - aB;
0146 }
0147
0148
0149 aA = aB;
0150 aFa = aFb;
0151
0152
0153 if (std::abs(aD) > aTol)
0154 {
0155 aB = aS;
0156 }
0157 else
0158 {
0159 aB += (aM > 0.0) ? aTol : -aTol;
0160 }
0161
0162
0163 if (!theFunc.Value(aB, aFb))
0164 {
0165 aResult.Status = MathUtils::Status::NumericalError;
0166 aResult.Root = aB;
0167 return aResult;
0168 }
0169
0170
0171 if (aFb * aFc > 0.0)
0172 {
0173 aC = aA;
0174 aFc = aFa;
0175 aD = aB - aA;
0176 aE = aD;
0177 }
0178 else if (std::abs(aFc) < std::abs(aFb))
0179 {
0180
0181 aA = aB;
0182 aFa = aFb;
0183 std::swap(aB, aC);
0184 std::swap(aFb, aFc);
0185 }
0186 }
0187
0188
0189 aResult.Status = MathUtils::Status::MaxIterations;
0190 aResult.Root = aB;
0191 aResult.Value = aFb;
0192 return aResult;
0193 }
0194
0195 }
0196
0197 #endif