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_Secant_HeaderFile
0015 #define _MathRoot_Secant_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 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 Secant(Function& theFunc,
0046 double theX0,
0047 double theX1,
0048 const MathUtils::Config& theConfig = MathUtils::Config())
0049 {
0050 MathUtils::ScalarResult aResult;
0051
0052 double aX0 = theX0;
0053 double aX1 = theX1;
0054 double aF0 = 0.0;
0055 double aF1 = 0.0;
0056
0057
0058 if (!theFunc.Value(aX0, aF0))
0059 {
0060 aResult.Status = MathUtils::Status::NumericalError;
0061 return aResult;
0062 }
0063 if (!theFunc.Value(aX1, aF1))
0064 {
0065 aResult.Status = MathUtils::Status::NumericalError;
0066 return aResult;
0067 }
0068
0069 for (int anIter = 0; anIter < theConfig.MaxIterations; ++anIter)
0070 {
0071 aResult.NbIterations = anIter + 1;
0072
0073
0074 if (MathUtils::IsFConverged(aF1, theConfig.FTolerance))
0075 {
0076 aResult.Status = MathUtils::Status::OK;
0077 aResult.Root = aX1;
0078 aResult.Value = aF1;
0079 return aResult;
0080 }
0081
0082
0083 const double aDenom = aF1 - aF0;
0084 if (MathUtils::IsZero(aDenom))
0085 {
0086 aResult.Status = MathUtils::Status::NumericalError;
0087 aResult.Root = aX1;
0088 aResult.Value = aF1;
0089 return aResult;
0090 }
0091
0092 const double aXNew = aX1 - aF1 * (aX1 - aX0) / aDenom;
0093
0094
0095 if (MathUtils::IsXConverged(aX1, aXNew, theConfig.XTolerance))
0096 {
0097 double aFNew = 0.0;
0098 theFunc.Value(aXNew, aFNew);
0099 aResult.Status = MathUtils::Status::OK;
0100 aResult.Root = aXNew;
0101 aResult.Value = aFNew;
0102 return aResult;
0103 }
0104
0105
0106 aX0 = aX1;
0107 aF0 = aF1;
0108 aX1 = aXNew;
0109
0110 if (!theFunc.Value(aX1, aF1))
0111 {
0112 aResult.Status = MathUtils::Status::NumericalError;
0113 aResult.Root = aX1;
0114 return aResult;
0115 }
0116 }
0117
0118 aResult.Status = MathUtils::Status::MaxIterations;
0119 aResult.Root = aX1;
0120 aResult.Value = aF1;
0121 return aResult;
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 template <typename Function>
0133 MathUtils::ScalarResult SecantAuto(Function& theFunc,
0134 double theX0,
0135 const MathUtils::Config& theConfig = MathUtils::Config())
0136 {
0137
0138 const double aDelta = (std::abs(theX0) > 1.0) ? 0.01 * theX0 : 0.01;
0139 return Secant(theFunc, theX0, theX0 + aDelta, theConfig);
0140 }
0141
0142 }
0143
0144 #endif