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_Bisection_HeaderFile
0015 #define _MathRoot_Bisection_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 Bisection(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 (aA > aB)
0078 {
0079 std::swap(aA, aB);
0080 std::swap(aFa, aFb);
0081 }
0082
0083
0084
0085 bool aIsNegAtA = (aFa < 0.0);
0086
0087 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0088 {
0089
0090 const double aM = 0.5 * (aA + aB);
0091 double aFm = 0.0;
0092
0093 if (!theFunc.Value(aM, aFm))
0094 {
0095 aResult.Status = MathUtils::Status::NumericalError;
0096 aResult.Root = aM;
0097 aResult.NbIterations = anIter + 1;
0098 return aResult;
0099 }
0100
0101 aResult.NbIterations = anIter + 1;
0102
0103
0104 if (std::abs(aFm) < theConfig.FTolerance)
0105 {
0106 aResult.Status = MathUtils::Status::OK;
0107 aResult.Root = aM;
0108 aResult.Value = aFm;
0109 return aResult;
0110 }
0111
0112
0113 if ((aB - aA) < theConfig.XTolerance * std::max(1.0, std::abs(aM)))
0114 {
0115 aResult.Status = MathUtils::Status::OK;
0116 aResult.Root = aM;
0117 aResult.Value = aFm;
0118 return aResult;
0119 }
0120
0121
0122 const bool aIsNegAtM = (aFm < 0.0);
0123 if (aIsNegAtM == aIsNegAtA)
0124 {
0125
0126 aA = aM;
0127 aFa = aFm;
0128 }
0129 else
0130 {
0131
0132 aB = aM;
0133 aFb = aFm;
0134 }
0135 }
0136
0137
0138 aResult.Status = MathUtils::Status::MaxIterations;
0139 aResult.Root = 0.5 * (aA + aB);
0140 aResult.Value = 0.0;
0141 theFunc.Value(*aResult.Root, *aResult.Value);
0142 return aResult;
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 template <typename Function>
0156 MathUtils::ScalarResult BisectionNewton(Function& theFunc,
0157 double theLower,
0158 double theUpper,
0159 const MathUtils::Config& theConfig = MathUtils::Config())
0160 {
0161 MathUtils::ScalarResult aResult;
0162
0163 double aA = theLower;
0164 double aB = theUpper;
0165 double aFa = 0.0;
0166 double aFb = 0.0;
0167 double aDummy = 0.0;
0168
0169
0170 if (!theFunc.Values(aA, aFa, aDummy))
0171 {
0172 aResult.Status = MathUtils::Status::NumericalError;
0173 return aResult;
0174 }
0175 if (!theFunc.Values(aB, aFb, aDummy))
0176 {
0177 aResult.Status = MathUtils::Status::NumericalError;
0178 return aResult;
0179 }
0180
0181
0182 if (aFa * aFb > 0.0)
0183 {
0184 aResult.Status = MathUtils::Status::InvalidInput;
0185 return aResult;
0186 }
0187
0188
0189 if (aA > aB)
0190 {
0191 std::swap(aA, aB);
0192 std::swap(aFa, aFb);
0193 }
0194
0195
0196 bool aIsNegAtA = (aFa < 0.0);
0197
0198
0199 double aX = 0.5 * (aA + aB);
0200 double aFx = 0.0;
0201 double aDfx = 0.0;
0202
0203 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0204 {
0205 if (!theFunc.Values(aX, aFx, aDfx))
0206 {
0207 aResult.Status = MathUtils::Status::NumericalError;
0208 aResult.Root = aX;
0209 aResult.NbIterations = anIter + 1;
0210 return aResult;
0211 }
0212
0213 aResult.NbIterations = anIter + 1;
0214
0215
0216 if (std::abs(aFx) < theConfig.FTolerance)
0217 {
0218 aResult.Status = MathUtils::Status::OK;
0219 aResult.Root = aX;
0220 aResult.Value = aFx;
0221 aResult.Derivative = aDfx;
0222 return aResult;
0223 }
0224
0225 if ((aB - aA) < theConfig.XTolerance * std::max(1.0, std::abs(aX)))
0226 {
0227 aResult.Status = MathUtils::Status::OK;
0228 aResult.Root = aX;
0229 aResult.Value = aFx;
0230 aResult.Derivative = aDfx;
0231 return aResult;
0232 }
0233
0234
0235 double aXNew = aX;
0236 if (!MathUtils::IsZero(aDfx))
0237 {
0238 aXNew = aX - aFx / aDfx;
0239 }
0240
0241
0242 if (aXNew <= aA || aXNew >= aB)
0243 {
0244
0245 aXNew = 0.5 * (aA + aB);
0246 }
0247
0248
0249 const bool aIsNegAtX = (aFx < 0.0);
0250 if (aIsNegAtX == aIsNegAtA)
0251 {
0252
0253 aA = aX;
0254 }
0255 else
0256 {
0257
0258 aB = aX;
0259 }
0260
0261 aX = aXNew;
0262 }
0263
0264
0265 aResult.Status = MathUtils::Status::MaxIterations;
0266 aResult.Root = aX;
0267 aResult.Value = 0.0;
0268 aResult.Derivative = 0.0;
0269 theFunc.Values(*aResult.Root, *aResult.Value, *aResult.Derivative);
0270 return aResult;
0271 }
0272
0273 }
0274
0275 #endif