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_Multiple_HeaderFile
0015 #define _MathInteg_Multiple_HeaderFile
0016
0017 #include <MathUtils_Types.hxx>
0018 #include <MathUtils_Config.hxx>
0019 #include <math_Vector.hxx>
0020 #include <math_IntegerVector.hxx>
0021 #include <math_Matrix.hxx>
0022 #include <MathUtils_GaussKronrodWeights.hxx>
0023
0024 #include <NCollection_DynamicArray.hxx>
0025
0026 #include <cmath>
0027 #include <functional>
0028
0029 namespace MathInteg
0030 {
0031 using namespace MathUtils;
0032
0033
0034 struct MultipleConfig
0035 {
0036 int MaxOrder = 61;
0037 };
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 template <typename Func>
0056 IntegResult GaussMultiple(Func& theFunc,
0057 int theNVars,
0058 const math_Vector& theLower,
0059 const math_Vector& theUpper,
0060 const math_IntegerVector& theOrder,
0061 const MultipleConfig& theConfig = MultipleConfig())
0062 {
0063 IntegResult aResult;
0064
0065
0066 if (theNVars <= 0 || theLower.Length() != theNVars || theUpper.Length() != theNVars
0067 || theOrder.Length() != theNVars)
0068 {
0069 aResult.Status = Status::InvalidInput;
0070 return aResult;
0071 }
0072
0073 const int aLowerL = theLower.Lower();
0074 const int aLowerU = theUpper.Lower();
0075 const int aLowerOr = theOrder.Lower();
0076
0077
0078 math_IntegerVector aOrd(0, theNVars - 1);
0079 int aMaxOrder = 0;
0080 for (int i = 0; i < theNVars; ++i)
0081 {
0082 aOrd(i) = std::min(theOrder(i + aLowerOr), theConfig.MaxOrder);
0083 aOrd(i) = std::max(aOrd(i), 1);
0084 if (aOrd(i) > aMaxOrder)
0085 {
0086 aMaxOrder = aOrd(i);
0087 }
0088 }
0089
0090
0091 math_Vector aXm(0, theNVars - 1);
0092 math_Vector aXr(0, theNVars - 1);
0093 for (int i = 0; i < theNVars; ++i)
0094 {
0095 aXm(i) = 0.5 * (theLower(i + aLowerL) + theUpper(i + aLowerU));
0096 aXr(i) = 0.5 * (theUpper(i + aLowerU) - theLower(i + aLowerL));
0097 }
0098
0099
0100
0101 NCollection_DynamicArray<math_Vector> aGaussPoints;
0102 NCollection_DynamicArray<math_Vector> aGaussWeights;
0103
0104 for (int i = 0; i < theNVars; ++i)
0105 {
0106 aGaussPoints.Append(math_Vector(0, aOrd(i) - 1));
0107 aGaussWeights.Append(math_Vector(0, aOrd(i) - 1));
0108
0109 math_Vector aGP(1, aOrd(i));
0110 math_Vector aGW(1, aOrd(i));
0111 if (!GetOrderedGaussPointsAndWeights(aOrd(i), aGP, aGW))
0112 {
0113 aResult.Status = Status::InvalidInput;
0114 return aResult;
0115 }
0116
0117 for (int k = 0; k < aOrd(i); ++k)
0118 {
0119 aGaussPoints.ChangeValue(i)(k) = aGP(k + 1);
0120 aGaussWeights.ChangeValue(i)(k) = aGW(k + 1);
0121 }
0122 }
0123
0124
0125 double aVal = 0.0;
0126 math_Vector aX(1, theNVars);
0127 math_Vector aDx(1, theNVars);
0128
0129
0130 math_IntegerVector aInc(0, theNVars - 1, 0);
0131
0132
0133 std::function<bool(int)> aRecurse = [&](int theN) -> bool {
0134 if (theN == theNVars)
0135 {
0136
0137 for (int j = 0; j < theNVars; ++j)
0138 {
0139 aDx(j + 1) = aXr(j) * aGaussPoints.Value(j)(aInc(j));
0140 aX(j + 1) = aXm(j) + aDx(j + 1);
0141 }
0142
0143 double aF1;
0144 if (!theFunc.Value(aX, aF1))
0145 {
0146 return false;
0147 }
0148
0149
0150 double aWeight = 1.0;
0151 for (int j = 0; j < theNVars; ++j)
0152 {
0153 aWeight *= aGaussWeights.Value(j)(aInc(j));
0154 }
0155
0156 aVal += aWeight * aF1;
0157 return true;
0158 }
0159
0160
0161 for (aInc(theN) = 0; aInc(theN) < aOrd(theN); ++aInc(theN))
0162 {
0163 if (!aRecurse(theN + 1))
0164 {
0165 return false;
0166 }
0167 }
0168 return true;
0169 };
0170
0171 if (!aRecurse(0))
0172 {
0173 aResult.Status = Status::NotConverged;
0174 return aResult;
0175 }
0176
0177
0178 for (int i = 0; i < theNVars; ++i)
0179 {
0180 aVal *= aXr(i);
0181 }
0182
0183 aResult.Value = aVal;
0184 aResult.Status = Status::OK;
0185 return aResult;
0186 }
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197 template <typename Func>
0198 IntegResult GaussMultipleUniform(Func& theFunc,
0199 int theNVars,
0200 const math_Vector& theLower,
0201 const math_Vector& theUpper,
0202 int theOrder)
0203 {
0204 math_IntegerVector aOrders(0, theNVars - 1, theOrder);
0205 return GaussMultiple(theFunc, theNVars, theLower, theUpper, aOrders);
0206 }
0207
0208 }
0209
0210 #endif