File indexing completed on 2026-09-28 09:20:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef _MathInteg_Gauss_HeaderFile
0015 #define _MathInteg_Gauss_HeaderFile
0016
0017 #include <MathUtils_Types.hxx>
0018 #include <MathUtils_Config.hxx>
0019 #include <MathUtils_Core.hxx>
0020 #include <MathUtils_Gauss.hxx>
0021
0022 #include <algorithm>
0023 #include <cmath>
0024
0025
0026 namespace MathInteg
0027 {
0028 using namespace MathUtils;
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 template <typename Function>
0047 IntegResult Gauss(Function& theFunc, double theLower, double theUpper, int theNbPoints = 15)
0048 {
0049 IntegResult aResult;
0050 if (theNbPoints < 1)
0051 {
0052 aResult.Status = Status::InvalidInput;
0053 return aResult;
0054 }
0055
0056
0057 math_Vector aPoints(1, theNbPoints);
0058 math_Vector aWeights(1, theNbPoints);
0059
0060 if (!MathUtils::GetGaussPointsAndWeights(theNbPoints, aPoints, aWeights))
0061 {
0062 aResult.Status = Status::InvalidInput;
0063 return aResult;
0064 }
0065
0066
0067 const double aHalfLen = 0.5 * (theUpper - theLower);
0068 const double aMid = 0.5 * (theUpper + theLower);
0069
0070 double aSum = 0.0;
0071 for (int i = 1; i <= theNbPoints; ++i)
0072 {
0073 const double aX = aMid + aHalfLen * aPoints(i);
0074 double aF = 0.0;
0075 if (!theFunc.Value(aX, aF))
0076 {
0077 aResult.Status = Status::NumericalError;
0078 return aResult;
0079 }
0080 aSum += aWeights(i) * aF;
0081 }
0082
0083 aResult.Status = Status::OK;
0084 aResult.Value = aHalfLen * aSum;
0085 aResult.NbPoints = theNbPoints;
0086 aResult.NbIterations = 1;
0087 return aResult;
0088 }
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 template <typename Function>
0105 IntegResult GaussAdaptive(Function& theFunc,
0106 double theLower,
0107 double theUpper,
0108 const IntegConfig& theConfig = IntegConfig())
0109 {
0110 IntegResult aResult;
0111
0112 if (theConfig.InitialOrder < 1 || theConfig.MaxOrder < theConfig.InitialOrder
0113 || theConfig.MaxOrder > 61 || theConfig.MaxIterations < 1)
0114 {
0115 aResult.Status = Status::InvalidInput;
0116 return aResult;
0117 }
0118
0119 int aCoarseOrder = theConfig.InitialOrder;
0120 int aFineOrder = std::min(theConfig.MaxOrder, std::min(61, 2 * aCoarseOrder));
0121 if (aFineOrder == aCoarseOrder)
0122 {
0123 if (aCoarseOrder > 1)
0124 {
0125 aCoarseOrder -= 1;
0126 }
0127 else if (theConfig.MaxOrder > 1)
0128 {
0129 aFineOrder = 2;
0130 }
0131 }
0132
0133
0134 IntegResult aCoarse = Gauss(theFunc, theLower, theUpper, aCoarseOrder);
0135 if (!aCoarse.IsDone())
0136 {
0137 return aCoarse;
0138 }
0139
0140 IntegResult aFine = Gauss(theFunc, theLower, theUpper, aFineOrder);
0141 if (!aFine.IsDone())
0142 {
0143 return aFine;
0144 }
0145
0146 const double aError = std::abs(*aFine.Value - *aCoarse.Value);
0147 const double aScale = std::max(std::abs(*aFine.Value), 1.0e-15);
0148
0149
0150 if (aError < theConfig.Tolerance * aScale)
0151 {
0152 aResult.Status = Status::OK;
0153 aResult.Value = *aFine.Value;
0154 aResult.AbsoluteError = aError;
0155 aResult.RelativeError = aError / aScale;
0156 aResult.NbPoints = static_cast<size_t>(aFineOrder);
0157 aResult.NbIterations = 1;
0158 return aResult;
0159 }
0160
0161
0162 if (theConfig.MaxIterations <= 1)
0163 {
0164 aResult.Status = Status::MaxIterations;
0165 aResult.Value = *aFine.Value;
0166 aResult.AbsoluteError = aError;
0167 aResult.RelativeError = aError / aScale;
0168 aResult.NbPoints = static_cast<size_t>(aFineOrder);
0169 aResult.NbIterations = 1;
0170 return aResult;
0171 }
0172
0173
0174 const double aMid = 0.5 * (theLower + theUpper);
0175
0176 IntegConfig aSubConfig = theConfig;
0177 aSubConfig.MaxIterations = theConfig.MaxIterations - 1;
0178
0179 IntegResult aLeft = GaussAdaptive(theFunc, theLower, aMid, aSubConfig);
0180 if (!aLeft.IsDone())
0181 {
0182 aResult.Status = aLeft.Status;
0183 aResult.Value = aLeft.Value;
0184 return aResult;
0185 }
0186
0187 IntegResult aRight = GaussAdaptive(theFunc, aMid, theUpper, aSubConfig);
0188 if (!aRight.IsDone())
0189 {
0190 aResult.Status = aRight.Status;
0191 aResult.Value = *aLeft.Value + (aRight.Value ? *aRight.Value : 0.0);
0192 return aResult;
0193 }
0194
0195 aResult.Status = Status::OK;
0196 aResult.Value = *aLeft.Value + *aRight.Value;
0197 aResult.AbsoluteError = *aLeft.AbsoluteError + *aRight.AbsoluteError;
0198 aResult.RelativeError = *aResult.AbsoluteError / std::max(std::abs(*aResult.Value), 1.0e-15);
0199 aResult.NbPoints = aLeft.NbPoints + aRight.NbPoints;
0200 aResult.NbIterations = std::max(aLeft.NbIterations, aRight.NbIterations) + 1;
0201 return aResult;
0202 }
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 template <typename Function>
0216 IntegResult GaussComposite(Function& theFunc,
0217 double theLower,
0218 double theUpper,
0219 int theNbIntervals,
0220 int theNbPoints = 7)
0221 {
0222 IntegResult aResult;
0223
0224 if (theNbIntervals < 1)
0225 {
0226 aResult.Status = Status::InvalidInput;
0227 return aResult;
0228 }
0229
0230 const double aH = (theUpper - theLower) / theNbIntervals;
0231 double aSum = 0.0;
0232 size_t aTotalPoints = 0;
0233
0234 for (int i = 0; i < theNbIntervals; ++i)
0235 {
0236 const double aA = theLower + i * aH;
0237 const double aB = aA + aH;
0238
0239 IntegResult aSubResult = Gauss(theFunc, aA, aB, theNbPoints);
0240 if (!aSubResult.IsDone())
0241 {
0242 aResult.Status = aSubResult.Status;
0243 aResult.Value = aSum;
0244 aResult.NbPoints = aTotalPoints;
0245 return aResult;
0246 }
0247
0248 aSum += *aSubResult.Value;
0249 aTotalPoints += aSubResult.NbPoints;
0250 }
0251
0252 aResult.Status = Status::OK;
0253 aResult.Value = aSum;
0254 aResult.NbPoints = aTotalPoints;
0255 aResult.NbIterations = 1;
0256 return aResult;
0257 }
0258
0259 }
0260
0261 #endif