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_Newton_HeaderFile
0015 #define _MathRoot_Newton_HeaderFile
0016
0017 #include <MathUtils_Types.hxx>
0018 #include <MathUtils_Config.hxx>
0019 #include <MathUtils_Core.hxx>
0020 #include <MathUtils_Convergence.hxx>
0021
0022 #include <cmath>
0023
0024
0025 namespace MathRoot
0026 {
0027 using namespace MathUtils;
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 template <typename Function>
0045 MathUtils::ScalarResult Newton(Function& theFunc,
0046 double theGuess,
0047 const MathUtils::Config& theConfig = MathUtils::Config())
0048 {
0049 MathUtils::ScalarResult aResult;
0050 double aX = theGuess;
0051 double aFx = 0.0;
0052 double aDfx = 0.0;
0053
0054 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0055 {
0056 const double anXOld = aX;
0057
0058
0059 if (!theFunc.Values(aX, aFx, aDfx))
0060 {
0061 aResult.Status = MathUtils::Status::NumericalError;
0062 aResult.Root = aX;
0063 aResult.NbIterations = anIter;
0064 return aResult;
0065 }
0066
0067
0068 if (MathUtils::IsZero(aDfx))
0069 {
0070
0071 if (!MathUtils::IsFConverged(aFx, theConfig.FTolerance))
0072 {
0073 aResult.Status = MathUtils::Status::NumericalError;
0074 aResult.Root = aX;
0075 aResult.Value = aFx;
0076 aResult.Derivative = aDfx;
0077 aResult.NbIterations = anIter;
0078 return aResult;
0079 }
0080
0081 }
0082 else
0083 {
0084
0085 aX -= aFx / aDfx;
0086 }
0087
0088 aResult.NbIterations = anIter + 1;
0089
0090
0091 if (MathUtils::IsConverged(anXOld, aX, aFx, theConfig))
0092 {
0093 aResult.Status = MathUtils::Status::OK;
0094 aResult.Root = aX;
0095 aResult.Value = aFx;
0096 aResult.Derivative = aDfx;
0097 return aResult;
0098 }
0099 }
0100
0101
0102 aResult.Status = MathUtils::Status::MaxIterations;
0103 aResult.Root = aX;
0104 aResult.Value = aFx;
0105 aResult.Derivative = aDfx;
0106 return aResult;
0107 }
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 template <typename Function>
0121 MathUtils::ScalarResult NewtonBounded(Function& theFunc,
0122 double theGuess,
0123 double theLower,
0124 double theUpper,
0125 const MathUtils::Config& theConfig = MathUtils::Config())
0126 {
0127 MathUtils::ScalarResult aResult;
0128
0129
0130 double aX = MathUtils::Clamp(theGuess, theLower, theUpper);
0131 double aXLo = theLower;
0132 double aXHi = theUpper;
0133
0134 double aFx = 0.0;
0135 double aDfx = 0.0;
0136 double aFLo = 0.0;
0137 double aFHi = 0.0;
0138 double aDummy = 0.0;
0139
0140
0141 if (!theFunc.Values(aXLo, aFLo, aDummy))
0142 {
0143 aResult.Status = MathUtils::Status::NumericalError;
0144 return aResult;
0145 }
0146 if (!theFunc.Values(aXHi, aFHi, aDummy))
0147 {
0148 aResult.Status = MathUtils::Status::NumericalError;
0149 return aResult;
0150 }
0151
0152
0153 const bool aBracketed = (aFLo * aFHi < 0.0);
0154
0155 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0156 {
0157 const double anXOld = aX;
0158
0159
0160 if (!theFunc.Values(aX, aFx, aDfx))
0161 {
0162 aResult.Status = MathUtils::Status::NumericalError;
0163 aResult.Root = aX;
0164 aResult.NbIterations = anIter;
0165 return aResult;
0166 }
0167
0168 aResult.NbIterations = anIter + 1;
0169
0170
0171 if (MathUtils::IsFConverged(aFx, theConfig.FTolerance))
0172 {
0173 aResult.Status = MathUtils::Status::OK;
0174 aResult.Root = aX;
0175 aResult.Value = aFx;
0176 aResult.Derivative = aDfx;
0177 return aResult;
0178 }
0179
0180
0181 double aXNew = aX;
0182 if (!MathUtils::IsZero(aDfx))
0183 {
0184 aXNew = aX - aFx / aDfx;
0185 }
0186
0187
0188 if (aXNew < aXLo || aXNew > aXHi)
0189 {
0190
0191 if (aBracketed)
0192 {
0193 aXNew = 0.5 * (aXLo + aXHi);
0194 }
0195 else
0196 {
0197
0198 aXNew = MathUtils::Clamp(aXNew, aXLo, aXHi);
0199 }
0200 }
0201
0202 aX = aXNew;
0203
0204
0205 if (aBracketed)
0206 {
0207 if (aFx * aFLo < 0.0)
0208 {
0209 aXHi = anXOld;
0210 aFHi = aFx;
0211 }
0212 else
0213 {
0214 aXLo = anXOld;
0215 aFLo = aFx;
0216 }
0217 }
0218
0219
0220 if (MathUtils::IsXConverged(anXOld, aX, theConfig.XTolerance))
0221 {
0222
0223 theFunc.Values(aX, aFx, aDfx);
0224 aResult.Status = MathUtils::Status::OK;
0225 aResult.Root = aX;
0226 aResult.Value = aFx;
0227 aResult.Derivative = aDfx;
0228 return aResult;
0229 }
0230 }
0231
0232
0233 aResult.Status = MathUtils::Status::MaxIterations;
0234 aResult.Root = aX;
0235 aResult.Value = aFx;
0236 aResult.Derivative = aDfx;
0237 return aResult;
0238 }
0239
0240 }
0241
0242 #endif