File indexing completed on 2026-09-28 09:20:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef _MathUtils_Poly_HeaderFile
0015 #define _MathUtils_Poly_HeaderFile
0016
0017 #include <MathUtils_Core.hxx>
0018
0019 #include <cmath>
0020 #include <array>
0021
0022
0023 namespace MathUtils
0024 {
0025
0026
0027
0028
0029
0030
0031
0032 inline double EvalPoly(const double* theCoeffs, int theDegree, double theX)
0033 {
0034 double aResult = theCoeffs[theDegree];
0035 for (int i = theDegree - 1; i >= 0; --i)
0036 {
0037 aResult = aResult * theX + theCoeffs[i];
0038 }
0039 return aResult;
0040 }
0041
0042
0043
0044
0045
0046
0047
0048
0049 inline void EvalPolyDeriv(const double* theCoeffs,
0050 int theDegree,
0051 double theX,
0052 double& theValue,
0053 double& theDeriv)
0054 {
0055 theValue = theCoeffs[theDegree];
0056 theDeriv = 0.0;
0057 for (int i = theDegree - 1; i >= 0; --i)
0058 {
0059 theDeriv = theDeriv * theX + theValue;
0060 theValue = theValue * theX + theCoeffs[i];
0061 }
0062 }
0063
0064
0065
0066
0067
0068
0069
0070 inline double EvalPolyDesc(const double* theCoeffs, int theDegree, double theX)
0071 {
0072 double aResult = theCoeffs[0];
0073 for (int i = 1; i <= theDegree; ++i)
0074 {
0075 aResult = aResult * theX + theCoeffs[i];
0076 }
0077 return aResult;
0078 }
0079
0080
0081
0082
0083
0084
0085
0086
0087 inline double RefinePolyRoot(const double* theCoeffs,
0088 int theDegree,
0089 double theRoot,
0090 int theMaxIter = 5)
0091 {
0092 double aX = theRoot;
0093 for (int i = 0; i < theMaxIter; ++i)
0094 {
0095 double aF = 0.0;
0096 double aDf = 0.0;
0097 EvalPolyDeriv(theCoeffs, theDegree, aX, aF, aDf);
0098
0099 if (IsZero(aDf))
0100 {
0101 break;
0102 }
0103
0104 const double aDx = aF / aDf;
0105 aX -= aDx;
0106
0107 if (std::abs(aDx) < THE_EPSILON * std::max(1.0, std::abs(aX)))
0108 {
0109 break;
0110 }
0111 }
0112 return aX;
0113 }
0114
0115
0116
0117
0118
0119
0120
0121 inline double RefinePolyRootDesc(const double* theCoeffs,
0122 int theDegree,
0123 double theRoot,
0124 int theMaxIter = 5)
0125 {
0126
0127 std::array<double, 5> aAsc;
0128 for (int i = 0; i <= theDegree; ++i)
0129 {
0130 aAsc[i] = theCoeffs[theDegree - i];
0131 }
0132 return RefinePolyRoot(aAsc.data(), theDegree, theRoot, theMaxIter);
0133 }
0134
0135
0136
0137
0138 inline void SortRoots(double* theRoots, size_t theCount)
0139 {
0140 for (size_t i = 1; i < theCount; ++i)
0141 {
0142 const double aKey = theRoots[i];
0143 size_t j = i;
0144 while (j > 0 && theRoots[j - 1] > aKey)
0145 {
0146 theRoots[j] = theRoots[j - 1];
0147 --j;
0148 }
0149 theRoots[j] = aKey;
0150 }
0151 }
0152
0153
0154
0155
0156
0157
0158 inline size_t RemoveDuplicateRoots(double* theRoots, size_t theCount, double theTolerance = 1.0e-10)
0159 {
0160 if (theCount <= 1)
0161 {
0162 return theCount;
0163 }
0164
0165 size_t aNewCount = 1;
0166 for (size_t i = 1; i < theCount; ++i)
0167 {
0168 if (std::abs(theRoots[i] - theRoots[aNewCount - 1]) > theTolerance)
0169 {
0170 theRoots[aNewCount] = theRoots[i];
0171 ++aNewCount;
0172 }
0173 }
0174 return aNewCount;
0175 }
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 inline void DepressCubic(double theB,
0186 double theC,
0187 double theD,
0188 double& theP,
0189 double& theQ,
0190 double& theShift)
0191 {
0192 theShift = theB / 3.0;
0193 const double aB2 = theB * theB;
0194 theP = theC - aB2 / 3.0;
0195 theQ = theD - theB * theC / 3.0 + 2.0 * aB2 * theB / 27.0;
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 inline void DepressQuartic(double theB,
0209 double theC,
0210 double theD,
0211 double theE,
0212 double& theP,
0213 double& theQ,
0214 double& theR,
0215 double& theShift)
0216 {
0217 theShift = theB / 4.0;
0218 const double aB2 = theB * theB;
0219 const double aB3 = aB2 * theB;
0220 const double aB4 = aB2 * aB2;
0221
0222 theP = theC - 3.0 * aB2 / 8.0;
0223 theQ = theD - theB * theC / 2.0 + aB3 / 8.0;
0224 theR = theE - theB * theD / 4.0 + aB2 * theC / 16.0 - 3.0 * aB4 / 256.0;
0225 }
0226
0227 }
0228
0229 #endif