From 86ef8362d863fdfa0f00fcd93178118f6e57166f Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 07:30:18 +0200 Subject: [PATCH 01/51] Enhance CI workflow for C++ with benchmarks Added CI configuration for C++ builds with matrix strategy for compilers and build types, including benchmark execution and result storage. --- .github/workflows/ci.yml | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f7f69e6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,57 @@ +name: C/C++ CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest] + compiler: [g++-12, clang++-15] + build_type: [Debug, Release] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + + - name: Configure & build demos + run: | + cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DLNIT_BUILD_DEMO + cmake --build build --parallel + + - name: Configure & build benchmarks + run: | + cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DLNIT_BUILD_BENCHMARK=ON + cmake --build build --parallel + + - name: Run benchmarks + run: | + ./build/benchmark/benchmark_addaptiveQuadratures --benchmark_format=json --benchmark_out=bench_addaptiveQuadratures_result.json + ./build/benchmark/benchmark_LevermoreLikePDF --benchmark_format=json --benchmark_out=bench_LevermoreLikePDF_result.json + + - name: Store benchmark addaptive quadratures result & detect regressions + uses: benchmark-action/github-action-benchmark@v1 + with: + tool: 'googlecpp' + output-file-path: bench_addaptiveQuadratures_result.json + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true + alert-threshold: '150%' + comment-on-alert: true + fail-on-alert: true + + - name: Store benchmark Levermore like PDF result & detect regressions + uses: benchmark-action/github-action-benchmark@v1 + with: + tool: 'googlecpp' + output-file-path: bench_LevermoreLikePDF_result.json + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true + alert-threshold: '150%' + comment-on-alert: true + fail-on-alert: true From 5c16782be44474be052e95fea52759b8accf41f2 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 07:31:25 +0200 Subject: [PATCH 02/51] Enable demo builds in CI configuration --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7f69e6..4ba8455 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - name: Configure & build demos run: | - cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DLNIT_BUILD_DEMO + cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DLNIT_BUILD_DEMO=ON cmake --build build --parallel - name: Configure & build benchmarks From 6d02a970b6035eda7728d8ce4bd53d9e47655eb0 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 07:33:21 +0200 Subject: [PATCH 03/51] Add installation of clang-15 and libfmt-dev Added step to install toolchain and dependencies before building demos. --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ba8455..8aa85f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,11 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install toolchain and dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang-15 libfmt-dev + - name: Configure & build demos run: | cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DLNIT_BUILD_DEMO=ON From 651d1d3e00ccff0926de1dc5dafb7b7c94668f2b Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 07:35:04 +0200 Subject: [PATCH 04/51] Use typename for dependent type definitions --- .../ClenshawCurtisHybridAdaptiveQuadrature.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature.hpp b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature.hpp index 2a88473..75a97ce 100644 --- a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature.hpp +++ b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature.hpp @@ -36,9 +36,9 @@ class ClenshawCurtisHybridAdaptiveQuadrature : public AdaptiveQuadratureBase< Cl { using Base = AdaptiveQuadratureBase< ClenshawCurtisHybridAdaptiveQuadrature >; public: - using Size = Base::Size; ///< @brief Type for iteration counters. - using Scalar = Base::Scalar; ///< @brief Floating point type for integration (e.g., double). - using LongScalar = Base::LongScalar; ///< @brief Higher precision type for accumulation (e.g., long double). + using Size = typename Base::Size; ///< @brief Type for iteration counters. + using Scalar = typename Base::Scalar; ///< @brief Floating point type for integration (e.g., double). + using LongScalar = typename Base::LongScalar; ///< @brief Higher precision type for accumulation (e.g., long double). /** * @brief Estimate integral and error on [xmin, xmax]. From f9e51b9c56b47a6b6874b2a47621e789c69e8308 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 07:36:46 +0200 Subject: [PATCH 05/51] Use typename for dependent type definitions --- .../ClenshawCurtisAdaptiveQuadrature.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp index 8597b59..ae2a1ae 100644 --- a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp +++ b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp @@ -33,9 +33,9 @@ class ClenshawCurtisAdaptiveQuadrature : public AdaptiveQuadratureBase< Clenshaw { using Base = AdaptiveQuadratureBase< ClenshawCurtisAdaptiveQuadrature >; public: - using Size = Base::Size; ///< @brief Type for iteration counters. - using Scalar = Base::Scalar; ///< @brief Floating point type for integration (e.g., double). - using LongScalar = Base::LongScalar; ///< @brief Higher precision type for accumulation (e.g., long double). + using Size = typename Base::Size; ///< @brief Type for iteration counters. + using Scalar = typename Base::Scalar; ///< @brief Floating point type for integration (e.g., double). + using LongScalar = typename Base::LongScalar; ///< @brief Higher precision type for accumulation (e.g., long double). /** * @brief Estimate integral and error on [xmin, xmax]. From 1012e0f6d50f9a0308d081477578feebb6b5950e Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 07:37:13 +0200 Subject: [PATCH 06/51] Use typename for dependent type declarations --- include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp b/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp index eb90c42..40d7ba5 100644 --- a/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp +++ b/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp @@ -37,9 +37,9 @@ class GLCCAdaptiveQuadrature : public AdaptiveQuadratureBase< GLCCAdaptiveQuadra { using Base = AdaptiveQuadratureBase< GLCCAdaptiveQuadrature >; public: - using Size = Base::Size; ///< @brief Type for iteration counters. - using Scalar = Base::Scalar; ///< @brief Floating point type for integration (e.g., double). - using LongScalar = Base::LongScalar; ///< @brief Higher precision type for accumulation (e.g., long double). + using Size = typename Base::Size; ///< @brief Type for iteration counters. + using Scalar = typename Base::Scalar; ///< @brief Floating point type for integration (e.g., double). + using LongScalar = typename Base::LongScalar; ///< @brief Higher precision type for accumulation (e.g., long double). /** * @brief Estimate integral and error on [xmin, xmax]. From 25ba669b0078980b0fe6d66e12d6235b743b6c84 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 07:37:27 +0200 Subject: [PATCH 07/51] Fix type aliasing in GaussLegendreAdaptiveQuadrature --- .../AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp b/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp index 4d861fc..c88c134 100644 --- a/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp +++ b/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp @@ -24,9 +24,9 @@ class GaussLegendreAdaptiveQuadrature : public AdaptiveQuadratureBase< GaussLege { using Base = AdaptiveQuadratureBase< GaussLegendreAdaptiveQuadrature >; public: - using Size = Base::Size; ///< @brief Type for iteration counters. - using Scalar = Base::Scalar; ///< @brief Floating point type for integration (e.g., double). - using LongScalar = Base::LongScalar; ///< @brief Higher precision type for accumulation (e.g., long double). + using Size = typename Base::Size; ///< @brief Type for iteration counters. + using Scalar = typename Base::Scalar; ///< @brief Floating point type for integration (e.g., double). + using LongScalar = typename Base::LongScalar; ///< @brief Higher precision type for accumulation (e.g., long double). /** * @brief Estimate integral and error on [xmin, xmax]. From ce6dc76ae97bfe27c92bfaef58c6362037b16d0a Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 07:44:16 +0200 Subject: [PATCH 08/51] Update compiler versions in CI workflow --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8aa85f2..906f986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - compiler: [g++-12, clang++-15] + compiler: [g++-14, clang++-18] build_type: [Debug, Release] runs-on: ${{ matrix.os }} From 2289ee42db5639b2d77843587d076769716a8a8b Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 08:02:05 +0200 Subject: [PATCH 09/51] Modify CI workflow for compiler updates and benchmarks Updated CI configuration to use newer compilers and added benchmark job. --- .github/workflows/ci.yml | 42 +++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 906f986..cfab53f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: branches: [ "main" ] pull_request: branches: [ "main" ] - + jobs: build: strategy: @@ -22,27 +22,50 @@ jobs: - name: Install toolchain and dependencies run: | sudo apt-get update - sudo apt-get install -y clang-15 libfmt-dev + sudo apt-get install -y g++-14 clang-18 libfmt-dev - - name: Configure & build demos + - name: Configure & build run: | - cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DLNIT_BUILD_DEMO=ON + cmake -B build \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} \ + -DLNIT_BUILD_DEMO=ON \ + -DLNIT_BUILD_BENCHMARK=ON cmake --build build --parallel + benchmark: + # only track regressions from main; PRs/forks shouldn't push to gh-pages + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + + - name: Install toolchain and dependencies + run: | + sudo apt-get update + sudo apt-get install -y g++-14 libfmt-dev + - name: Configure & build benchmarks run: | - cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DLNIT_BUILD_BENCHMARK=ON + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_COMPILER=g++-14 \ + -DLNIT_BUILD_BENCHMARK=ON cmake --build build --parallel - + - name: Run benchmarks run: | ./build/benchmark/benchmark_addaptiveQuadratures --benchmark_format=json --benchmark_out=bench_addaptiveQuadratures_result.json ./build/benchmark/benchmark_LevermoreLikePDF --benchmark_format=json --benchmark_out=bench_LevermoreLikePDF_result.json - - - name: Store benchmark addaptive quadratures result & detect regressions + + - name: Store adaptive quadratures benchmark & detect regressions uses: benchmark-action/github-action-benchmark@v1 with: tool: 'googlecpp' + name: 'Adaptive Quadratures' output-file-path: bench_addaptiveQuadratures_result.json github-token: ${{ secrets.GITHUB_TOKEN }} auto-push: true @@ -50,10 +73,11 @@ jobs: comment-on-alert: true fail-on-alert: true - - name: Store benchmark Levermore like PDF result & detect regressions + - name: Store Levermore-like PDF benchmark & detect regressions uses: benchmark-action/github-action-benchmark@v1 with: tool: 'googlecpp' + name: 'Levermore-like PDF' output-file-path: bench_LevermoreLikePDF_result.json github-token: ${{ secrets.GITHUB_TOKEN }} auto-push: true From b5ea7328126e7059cc47bf02b3d68c8e28726fb6 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 08:35:42 +0200 Subject: [PATCH 10/51] Add adaptQuadrature function template declaration --- include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp index 04629dd..7283fea 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp @@ -168,6 +168,8 @@ class AdaptiveQuadratureBase constexpr std::span getSubIntervals() const { return m_intervals; } private: + template LongScalar addaptQuadrature(const Function& func); + std::vector m_intervals; std::vector m_subIntergrals; std::vector m_subIntergralsErr; From ecbf6fd2e7a3df939037b0a0cfdca2381e5c5471 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 08:35:46 +0200 Subject: [PATCH 11/51] Refactor integrate method to use addaptQuadrature Refactored integrate method to use addaptQuadrature for adaptive integration. --- .../AdaptiveQuadratureBase_impl.hpp | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 907469c..0eb9330 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -27,6 +27,38 @@ AdaptiveQuadratureBase::AdaptiveQuadratureBase(const Size& maxIt, const m_subIntergralsErr.reserve(maxIt); } +template template +auto AdaptiveQuadratureBase::addaptQuadrature(const Function& func) -> LongScalar +{ + for (m_it=0; m_it!=m_maxIt; ++m_it) + { + const LongScalar I = getEstimatedIntegral(); + const LongScalar err = getEstimatedError(); + + if (m_out) { fmt::print(m_out, "{} {:10.4e} {:10.4e} {:10.4e} {:10.4e}\n", m_it, Scalar(I), Scalar(err), Scalar(abs(I))*m_relativeTol, Scalar(m_absoluteTol)); } + + if (not isfinite(I)) { return I; } + if (err < abs(I)*LongScalar(m_relativeTol) or err < LongScalar(m_absoluteTol)) { m_hasConverged = true; return I; } + + // we find the interval over which the integral is the least accurate + const const_Iterator maxErrIt = std::ranges::max_element(m_subIntergralsErr); + const Size maxErrIdx = Size(std::ranges::distance(m_subIntergralsErr.begin(), maxErrIt)); + // we split it in two + const auto& [a, b] = m_intervals[maxErrIdx]; + + Scalar midPoint = std::midpoint(a, b); // non-const because I want to move it when I do not need it. + // first interval + m_intervals[maxErrIdx] = Interval(a, midPoint); + std::tie(m_subIntergrals[maxErrIdx], m_subIntergralsErr[maxErrIdx]) = estimateIntegral(f, a, midPoint); + // second interval + std::tie(res, estimatedErr) = estimateIntegral(f, midPoint, b); + m_intervals.emplace_back(std::move(midPoint), b); + m_subIntergrals.push_back(res); + m_subIntergralsErr.push_back(estimatedErr); + } + return getEstimatedIntegral(); +} + template template auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& xmin, const Scalar& xmax) -> LongScalar { @@ -52,7 +84,7 @@ auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& m_intervals.reserve(N); m_subIntergrals.reserve(N); m_subIntergralsErr.reserve(N); - + for (Size i=0; i!=N; ++i) { const Scalar x_i = xmin + Scalar(i)*(xmax - xmin) / Scalar(N); @@ -64,34 +96,8 @@ auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& m_subIntergrals.push_back(res); m_subIntergralsErr.push_back(estimatedErr); } - - for (m_it=0; m_it!=m_maxIt; ++m_it) - { - const LongScalar I = getEstimatedIntegral(); - const LongScalar err = getEstimatedError(); - if (m_out) { fmt::print(m_out, "{} {:10.4e} {:10.4e} {:10.4e} {:10.4e}\n", m_it, Scalar(I), Scalar(err), Scalar(abs(I))*m_relativeTol, Scalar(m_absoluteTol)); } - - if (not isfinite(I)) { return I; } - if (err < abs(I)*LongScalar(m_relativeTol) or err < LongScalar(m_absoluteTol)) { m_hasConverged = true; return I; } - - // we find the interval over which the integral is the least accurate - const const_Iterator maxErrIt = std::ranges::max_element(m_subIntergralsErr); - const Size maxErrIdx = Size(std::ranges::distance(m_subIntergralsErr.begin(), maxErrIt)); - // we split it in two - const auto& [a, b] = m_intervals[maxErrIdx]; - - Scalar midPoint = std::midpoint(a, b); // non-const because I want to move it when I do not need it. - // first interval - m_intervals[maxErrIdx] = Interval(a, midPoint); - std::tie(m_subIntergrals[maxErrIdx], m_subIntergralsErr[maxErrIdx]) = estimateIntegral(f, a, midPoint); - // second interval - std::tie(res, estimatedErr) = estimateIntegral(f, midPoint, b); - m_intervals.emplace_back(std::move(midPoint), b); - m_subIntergrals.push_back(res); - m_subIntergralsErr.push_back(estimatedErr); - } - return getEstimatedIntegral(); + return addaptQuadrature(func); } template template From 830df5bbe0360cf31f5c7cfb900fd9054b8267ec Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 08:53:24 +0200 Subject: [PATCH 12/51] Refactor adaptive quadrature implementation Refactor adaptive quadrature methods to improve clarity and reduce redundancy. --- .../AdaptiveQuadratureBase_impl.hpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 0eb9330..e74b62c 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -30,6 +30,16 @@ AdaptiveQuadratureBase::AdaptiveQuadratureBase(const Size& maxIt, const template template auto AdaptiveQuadratureBase::addaptQuadrature(const Function& func) -> LongScalar { + using std::abs; + using std::isfinite; + + using const_Iterator = typename std::vector::const_iterator; + + m_hasConverged = false; + + if (m_out) { fmt::print(m_out, "#NumericalIntegrator addapting quadrature over [{}, {}]\n", xmin, xmax); } + if (m_out) { fmt::print(m_out, "#Iteration integral estimated_error relative_tol absolute_tol\n"); } + for (m_it=0; m_it!=m_maxIt; ++m_it) { const LongScalar I = getEstimatedIntegral(); @@ -63,12 +73,7 @@ template template auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& xmin, const Scalar& xmax) -> LongScalar { using std::ceil; - using std::abs; - using std::isfinite; - - using const_Iterator = typename std::vector::const_iterator; - m_hasConverged = false; m_intervals.clear(); m_subIntergrals.clear(); m_subIntergralsErr.clear(); @@ -76,9 +81,6 @@ auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& LongScalar res; LongScalar estimatedErr; - if (m_out) { fmt::print(m_out, "#NumericalIntegrator addapting quadrature over [{}, {}]\n", xmin, xmax); } - if (m_out) { fmt::print(m_out, "#Iteration integral estimated_error relative_tol absolute_tol\n"); } - const Size N = Size(ceil(getMaxDeltaX(xmin, xmax))); m_intervals.reserve(N); From ea5bfadd08af1e5e3a76dd74da761023898c4b98 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 08:55:34 +0200 Subject: [PATCH 13/51] Remove duplicate output message for quadrature --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index e74b62c..35c807f 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -37,7 +37,6 @@ auto AdaptiveQuadratureBase::addaptQuadrature(const Function& func) -> m_hasConverged = false; - if (m_out) { fmt::print(m_out, "#NumericalIntegrator addapting quadrature over [{}, {}]\n", xmin, xmax); } if (m_out) { fmt::print(m_out, "#Iteration integral estimated_error relative_tol absolute_tol\n"); } for (m_it=0; m_it!=m_maxIt; ++m_it) @@ -99,6 +98,7 @@ auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& m_subIntergralsErr.push_back(estimatedErr); } + if (m_out) { fmt::print(m_out, "#NumericalIntegrator addapting quadrature over [{}, {}]\n", xmin, xmax); } return addaptQuadrature(func); } From 12c500d5baca10f78ad1e25f8994a6675cb7cb3b Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 10:42:09 +0200 Subject: [PATCH 14/51] Fix parameter name in addaptQuadrature method --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 35c807f..4e93d33 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -28,7 +28,7 @@ AdaptiveQuadratureBase::AdaptiveQuadratureBase(const Size& maxIt, const } template template -auto AdaptiveQuadratureBase::addaptQuadrature(const Function& func) -> LongScalar +auto AdaptiveQuadratureBase::addaptQuadrature(const Function& f) -> LongScalar { using std::abs; using std::isfinite; @@ -99,7 +99,7 @@ auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& } if (m_out) { fmt::print(m_out, "#NumericalIntegrator addapting quadrature over [{}, {}]\n", xmin, xmax); } - return addaptQuadrature(func); + return addaptQuadrature(f); } template template From c817cd20e66ae2713307c8ffbdb780e80bde4bf9 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 10:44:29 +0200 Subject: [PATCH 15/51] Refactor variable declaration for estimated error --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 4e93d33..7b85662 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -60,7 +60,7 @@ auto AdaptiveQuadratureBase::addaptQuadrature(const Function& f) -> Lon m_intervals[maxErrIdx] = Interval(a, midPoint); std::tie(m_subIntergrals[maxErrIdx], m_subIntergralsErr[maxErrIdx]) = estimateIntegral(f, a, midPoint); // second interval - std::tie(res, estimatedErr) = estimateIntegral(f, midPoint, b); + const auto [res, estimatedErr] = estimateIntegral(f, midPoint, b); m_intervals.emplace_back(std::move(midPoint), b); m_subIntergrals.push_back(res); m_subIntergralsErr.push_back(estimatedErr); From af3fbacfc3a051657e0817202854a3a7989488ff Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 10:57:03 +0200 Subject: [PATCH 16/51] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp index 7283fea..ccdff68 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp @@ -168,7 +168,7 @@ class AdaptiveQuadratureBase constexpr std::span getSubIntervals() const { return m_intervals; } private: - template LongScalar addaptQuadrature(const Function& func); + template LongScalar adaptQuadrature(const Function& func); std::vector m_intervals; std::vector m_subIntergrals; From 5d0eae0aa9dd24cbada455bdcba13ae4228e25f4 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 10:57:28 +0200 Subject: [PATCH 17/51] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 7b85662..416e163 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -28,7 +28,7 @@ AdaptiveQuadratureBase::AdaptiveQuadratureBase(const Size& maxIt, const } template template -auto AdaptiveQuadratureBase::addaptQuadrature(const Function& f) -> LongScalar +auto AdaptiveQuadratureBase::adaptQuadrature(const Function& f) -> LongScalar { using std::abs; using std::isfinite; From afe3eee353d38737fb54162184b943730249e070 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 10:57:51 +0200 Subject: [PATCH 18/51] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 416e163..2a23147 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -98,8 +98,8 @@ auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& m_subIntergralsErr.push_back(estimatedErr); } - if (m_out) { fmt::print(m_out, "#NumericalIntegrator addapting quadrature over [{}, {}]\n", xmin, xmax); } - return addaptQuadrature(f); + if (m_out) { fmt::print(m_out, "#NumericalIntegrator adapting quadrature over [{}, {}]\n", xmin, xmax); } + return adaptQuadrature(f); } template template From f54b823885c75c2e3ed83d89567d93d65f5dbb3f Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 11:39:34 +0200 Subject: [PATCH 19/51] Implement integrateWithHints method for quadrature --- .../AdaptiveQuadratureBase_impl.hpp | 79 ++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 2a23147..88db4d8 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -102,13 +102,90 @@ auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& return adaptQuadrature(f); } +template template +auto AdaptiveQuadratureBase::integrateWithHints(const Function& f, const std::span mu, const Scalar& sigma) -> LongScalar +{ + using std::abs; + using std::isfinite; + using std::swap; + + using Iterator = typename std::vector::iterator; + + constexpr Size scal = 3; + + GaussLaguerreQuadrature gLaguerreQuad; + + m_intervals.clear(); + m_subIntergrals.clear(); + m_subIntergralsErr.clear(); + + m_intervals.reserve(2*mu.size()); + + // First pass, we compute intervals near the peaks on which the function is not null. + for (const double& mu_i : mu) + { + Interval curr(mu_i - scal*sigma, mu_i + scal*sigma); + + if (curr.first > curr.second) { swap(curr.first, curr.second); } + + LongScalar leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, curr.first); + while (isfinite(leftIntegral) and abs(leftIntegral) >= NumTraits::epsilon) + { + curr.first -= scal*sigma; + leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, curr.first); + assert(curr.first <= curr.second); + } + + if (not isfinite(leftIntegral)) { return NumTraits::NaN; } + + LongScalar rightIntegral = gLaguerreQuad.integrateRightInfinite(f, curr.second); + while (isfinite(rightIntegral) and abs(rightIntegral) >= NumTraits::epsilon) + { + curr.second += scal*sigma; + rightIntegral = gLaguerreQuad.integrateRightInfinite(f, curr.second); + assert(curr.first <= curr.second); + } + + if (not isfinite(rightIntegral)) { return NumTraits::NaN; } + + Iterator firstInterval = m_intervals.begin(); + while (firstInterval != m_intervals.end() and firstInterval->second < curr.first) { ++firstInterval; } + + Iterator boundInterval = firstInterval; + for ( ;boundInterval != m_intervals.end() and boundInterval->first <= curr.second; ++boundInterval) + { + curr.first = std::min(curr.first, boundInterval->first); + curr.second = std::max(curr.second, boundInterval->second); + } + + const Iterator it = m_intervals.erase(firstInterval, boundInterval); + m_intervals.insert(it, curr); + } + + LongScalar res; + LongScalar estimatedErr; + + m_subIntergrals.reserve(m_intervals.size()); + m_subIntergralsErr.reserve(m_intervals.size()); + + for (const auto& [xmin, xmax] : m_intervals) + { + std::tie(res, estimatedErr) = estimateIntegral(f, xmin, xmax); + + m_subIntergrals.push_back(res); + m_subIntergralsErr.push_back(estimatedErr); + } + + if (m_out) { fmt::print(m_out, "#NumericalIntegrator adapting quadrature over {}\n", m_intervals); } + return adaptQuadrature(f); +} + template template auto AdaptiveQuadratureBase::integrateLeftInfinite(const Function& f, const Scalar& xmax) -> LongScalar { using std::isfinite; using std::abs; - GaussLaguerreQuadrature gLaguerreQuad; Scalar xmin = -1; From 2165495bc3a7afaa9fcdf358473676d3feb0dc4e Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 11:40:22 +0200 Subject: [PATCH 20/51] Add integrateWithHints method declaration --- include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp index ccdff68..4990a9f 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp @@ -76,7 +76,9 @@ class AdaptiveQuadratureBase * @return Approximation of the integral. */ template LongScalar integrate(const Function& f, const Scalar& xmin, const Scalar& xmax); - + + template template LongScalar integrateWithHints(const Function& f, const std::span mu, const Scalar& sigma); + /** * @brief Perform adaptive quadrature on (-inf, xmax]. * From dc2e60300ba42e5453ded91fdfc8605d0632bdea Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 12:11:11 +0200 Subject: [PATCH 21/51] corrected integrateWithHints template declaration --- include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp index 4990a9f..799e2ee 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp @@ -77,7 +77,7 @@ class AdaptiveQuadratureBase */ template LongScalar integrate(const Function& f, const Scalar& xmin, const Scalar& xmax); - template template LongScalar integrateWithHints(const Function& f, const std::span mu, const Scalar& sigma); + template LongScalar integrateWithHints(const Function& f, const std::span mu, const Scalar& sigma); /** * @brief Perform adaptive quadrature on (-inf, xmax]. From d0ad859a5e1bbe77c5dc5e4e2bd0d19b6950d8ca Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 12:22:39 +0200 Subject: [PATCH 22/51] Add assertion for sigma in AdaptiveQuadratureBase_impl --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 88db4d8..8297c1f 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -113,6 +113,8 @@ auto AdaptiveQuadratureBase::integrateWithHints(const Function& f, cons constexpr Size scal = 3; + assert(sigma > Scalar{}); + GaussLaguerreQuadrature gLaguerreQuad; m_intervals.clear(); From 5df074b9cc7702e3737453d2be6f6a47ee868360 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 12:50:28 +0200 Subject: [PATCH 23/51] Refactor integral estimation and error handling --- .../AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 8297c1f..ef527fc 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -35,6 +35,9 @@ auto AdaptiveQuadratureBase::adaptQuadrature(const Function& f) -> Long using const_Iterator = typename std::vector::const_iterator; + LongScalar res; + LongScalar estimatedErr; + m_hasConverged = false; if (m_out) { fmt::print(m_out, "#Iteration integral estimated_error relative_tol absolute_tol\n"); } @@ -60,7 +63,7 @@ auto AdaptiveQuadratureBase::adaptQuadrature(const Function& f) -> Long m_intervals[maxErrIdx] = Interval(a, midPoint); std::tie(m_subIntergrals[maxErrIdx], m_subIntergralsErr[maxErrIdx]) = estimateIntegral(f, a, midPoint); // second interval - const auto [res, estimatedErr] = estimateIntegral(f, midPoint, b); + std::tie(res, estimatedErr) = estimateIntegral(f, midPoint, b); m_intervals.emplace_back(std::move(midPoint), b); m_subIntergrals.push_back(res); m_subIntergralsErr.push_back(estimatedErr); @@ -249,9 +252,7 @@ auto AdaptiveQuadratureBase::remapAndIntegrate(const Function& f) -> Lo const LongScalar fx = f(t / (1 - t*t)); const Scalar dxdt = (1 + t*t) / ((1 - t*t)*(1 - t*t)); - return isnan(fx*dxdt) - ? LongScalar{} - : fx*dxdt; + return fx*dxdt; }; return integrate(fref, -1 + eps, 1 - eps); From e4bf178b0510daf329f4242f56cc9eea0978b423 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Jul 2026 11:18:59 +0000 Subject: [PATCH 24/51] Restore isnan guard in remapAndIntegrate to handle NaN/Inf at endpoints --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index ef527fc..6d9d28e 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -252,7 +252,9 @@ auto AdaptiveQuadratureBase::remapAndIntegrate(const Function& f) -> Lo const LongScalar fx = f(t / (1 - t*t)); const Scalar dxdt = (1 + t*t) / ((1 - t*t)*(1 - t*t)); - return fx*dxdt; + return isnan(fx*dxdt) + ? LongScalar{} + : fx*dxdt; }; return integrate(fref, -1 + eps, 1 - eps); From 20bbfdd3cf74b71d532fe6be03e76b1367140300 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 13:20:18 +0200 Subject: [PATCH 25/51] Fix integration limits in AdaptiveQuadratureBase_impl.hpp --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 6d9d28e..6a60cb9 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -257,7 +257,7 @@ auto AdaptiveQuadratureBase::remapAndIntegrate(const Function& f) -> Lo : fx*dxdt; }; - return integrate(fref, -1 + eps, 1 - eps); + return integrate(fref, -1, 1); } template template From 34028cfa37073847784cfe651de1cc11581c710f Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:01:44 +0200 Subject: [PATCH 26/51] Change integrate function parameter to rvalue reference --- include/LNIT/GaussHermiteQuadrature.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/GaussHermiteQuadrature.hpp b/include/LNIT/GaussHermiteQuadrature.hpp index 9f9fafd..c0c0f6b 100644 --- a/include/LNIT/GaussHermiteQuadrature.hpp +++ b/include/LNIT/GaussHermiteQuadrature.hpp @@ -24,7 +24,7 @@ class GaussHermiteQuadrature constexpr GaussHermiteQuadrature() {} ///< @brief Default constructor. - template constexpr LongScalar integrate(const Function& f) const; + template constexpr LongScalar integrate(Function&& f) const; private: static constexpr std::array s_wi = { Scalar(0.72500244352094499799), Scalar(0.55908539234713480356), Scalar(0.48645731979545141956), Scalar(0.44287166385270444111), Scalar(0.41289257970879246181), From 14f34a921902e3b15a48519ad7449f78d163cc7d Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:03:39 +0200 Subject: [PATCH 27/51] Change function parameter type to rvalue reference --- include/LNIT/GaussLaguerreQuadrature.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/GaussLaguerreQuadrature.hpp b/include/LNIT/GaussLaguerreQuadrature.hpp index 1d0522e..ed3df28 100644 --- a/include/LNIT/GaussLaguerreQuadrature.hpp +++ b/include/LNIT/GaussLaguerreQuadrature.hpp @@ -38,7 +38,7 @@ class GaussLaguerreQuadrature * @param a Upper bound of integration (default = 0). * @return Approximated integral value. */ - template constexpr LongScalar integrateLeftInfinite (const Function& f, const Scalar& a = Scalar{}) const; + template constexpr LongScalar integrateLeftInfinite (Function&& f, const Scalar& a = Scalar{}) const; /** * @brief Approximate integral over the right semi-infinite interval. * @@ -53,7 +53,7 @@ class GaussLaguerreQuadrature * @param a Lower bound of integration (default = 0). * @return Approximated integral value. */ - template constexpr LongScalar integrateRightInfinite (const Function& f, const Scalar& a = Scalar{}) const; + template constexpr LongScalar integrateRightInfinite (Function&& f, const Scalar& a = Scalar{}) const; private: static constexpr std::array s_wi = { Scalar(0.11077730587320757274), Scalar(0.25810528128189475158), Scalar(0.40622176868437369247), Scalar(0.55526230959922306292), Scalar(0.70555738765958285661), From ac6d11c9817e2706a23a8b9bb1d1d47d05f5ce09 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:04:20 +0200 Subject: [PATCH 28/51] Change function parameter from const& to && --- include/LNIT/GaussLaguerreQuadrature_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/GaussLaguerreQuadrature_impl.hpp b/include/LNIT/GaussLaguerreQuadrature_impl.hpp index 9fa7486..f5210df 100644 --- a/include/LNIT/GaussLaguerreQuadrature_impl.hpp +++ b/include/LNIT/GaussLaguerreQuadrature_impl.hpp @@ -18,7 +18,7 @@ extern template class GaussLaguerreQuadrature; //// method implementations //// template template -constexpr LongScalar GaussLaguerreQuadrature::integrateLeftInfinite(const Function& f, const Scalar& a) const +constexpr LongScalar GaussLaguerreQuadrature::integrateLeftInfinite(Function&& f, const Scalar& a) const { const auto fx = s_xi | std::views::transform([&f, &a](const Scalar& x) -> LongScalar { @@ -29,7 +29,7 @@ constexpr LongScalar GaussLaguerreQuadrature::integrateLeftI } template template -constexpr LongScalar GaussLaguerreQuadrature::integrateRightInfinite(const Function& f, const Scalar& a) const +constexpr LongScalar GaussLaguerreQuadrature::integrateRightInfinite(Function&& f, const Scalar& a) const { const auto fx = s_xi | std::views::transform([&f, &a](const Scalar& x) -> LongScalar { From fe0850121e01e38775cd2c35238f20706a020a52 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:04:41 +0200 Subject: [PATCH 29/51] Change integrate function parameter to rvalue reference --- include/LNIT/GaussHermiteQuadrature_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/GaussHermiteQuadrature_impl.hpp b/include/LNIT/GaussHermiteQuadrature_impl.hpp index bd88aab..db3adca 100644 --- a/include/LNIT/GaussHermiteQuadrature_impl.hpp +++ b/include/LNIT/GaussHermiteQuadrature_impl.hpp @@ -22,7 +22,7 @@ extern template class GaussHermiteQuadrature; //// method implementations //// template template -constexpr LongScalar GaussHermiteQuadrature::integrate(const Function& f) const +constexpr LongScalar GaussHermiteQuadrature::integrate(Function&& f) const { const auto fx = s_xi | std::views::transform([&f](const Scalar& x) -> LongScalar { From 0a17d59fe5c2d8962aa98d81bd75b548bb30e612 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:07:33 +0200 Subject: [PATCH 30/51] Change function parameter type from const& to && --- .../AdaptiveQuadratureBase.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp index 799e2ee..4d7e6c6 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp @@ -65,7 +65,7 @@ class AdaptiveQuadratureBase * * @return Pair (integral, estimated error). */ - template constexpr std::pair estimateIntegral(const Function& f, const Scalar& xmin, const Scalar& xmax) { return derived().estimateIntegralImpl(f, xmin, xmax); } + template constexpr std::pair estimateIntegral(Function&& f, const Scalar& xmin, const Scalar& xmax) { return derived().estimateIntegralImpl(f, xmin, xmax); } /** * @brief Perform adaptive quadrature on [xmin, xmax]. @@ -75,9 +75,9 @@ class AdaptiveQuadratureBase * @param xmax Upper bound of interval. * @return Approximation of the integral. */ - template LongScalar integrate(const Function& f, const Scalar& xmin, const Scalar& xmax); + template LongScalar integrate(Function&& f, const Scalar& xmin, const Scalar& xmax); - template LongScalar integrateWithHints(const Function& f, const std::span mu, const Scalar& sigma); + template LongScalar integrateWithHints(Function&& f, const std::span mu, const Scalar& sigma); /** * @brief Perform adaptive quadrature on (-inf, xmax]. @@ -94,7 +94,7 @@ class AdaptiveQuadratureBase * @param xmax Upper bound of interval. * @return Approximation of the integral. */ - template LongScalar integrateLeftInfinite(const Function& f, const Scalar& xmax); + template LongScalar integrateLeftInfinite(Function&& f, const Scalar& xmax); /** * @brief Perform adaptive quadrature on [xmin, inf). @@ -111,7 +111,7 @@ class AdaptiveQuadratureBase * @param xmax Upper bound of interval. * @return Approximation of the integral. */ - template LongScalar integrateRightInfinite(const Function& f, const Scalar& xmin); + template LongScalar integrateRightInfinite(Function&& f, const Scalar& xmin); /** * @brief Perform adaptive quadrature on (-inf, inf). @@ -126,7 +126,7 @@ class AdaptiveQuadratureBase * \f] * Finally addapt the quadrature over [xmin, xmax]. */ - template LongScalar integrate(const Function& f); + template LongScalar integrate(Function&& f); /** * @brief Perform adaptive quadrature on (-inf, inf) using a coordinate-remapping technique. @@ -141,9 +141,9 @@ class AdaptiveQuadratureBase * \int_{-1}^{1} f(x(t))\frac{1 + t^2}{(1 - t^2)^2} dt. * \f] */ - template LongScalar remapAndIntegrate(const Function& f); + template LongScalar remapAndIntegrate(Function&& f); - template std::invoke_result_t integrateWithoutAdaptation(const Function& f) const; + template std::invoke_result_t integrateWithoutAdaptation(Function&& f) const; constexpr Size getMaxIt() const { return m_maxIt; } ///< @brief Maximum iterations allowed. constexpr Size getNits() const { return m_it; } ///< @brief Number of iterations performed. @@ -170,7 +170,7 @@ class AdaptiveQuadratureBase constexpr std::span getSubIntervals() const { return m_intervals; } private: - template LongScalar adaptQuadrature(const Function& func); + template LongScalar adaptQuadrature(Function&& func); std::vector m_intervals; std::vector m_subIntergrals; From 8d3f3fda4e68f08785b4d22defcf24cb83d92fad Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:14:00 +0200 Subject: [PATCH 31/51] Change Function parameter to rvalue reference --- .../AdaptiveQuadratureBase_impl.hpp | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 6a60cb9..94eb773 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -28,7 +28,7 @@ AdaptiveQuadratureBase::AdaptiveQuadratureBase(const Size& maxIt, const } template template -auto AdaptiveQuadratureBase::adaptQuadrature(const Function& f) -> LongScalar +auto AdaptiveQuadratureBase::adaptQuadrature(Function&& f) -> LongScalar { using std::abs; using std::isfinite; @@ -72,7 +72,7 @@ auto AdaptiveQuadratureBase::adaptQuadrature(const Function& f) -> Long } template template -auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& xmin, const Scalar& xmax) -> LongScalar +auto AdaptiveQuadratureBase::integrate(Function&& f, const Scalar& xmin, const Scalar& xmax) -> LongScalar { using std::ceil; @@ -102,11 +102,11 @@ auto AdaptiveQuadratureBase::integrate(const Function& f, const Scalar& } if (m_out) { fmt::print(m_out, "#NumericalIntegrator adapting quadrature over [{}, {}]\n", xmin, xmax); } - return adaptQuadrature(f); + return adaptQuadrature(std::forward(f)); } template template -auto AdaptiveQuadratureBase::integrateWithHints(const Function& f, const std::span mu, const Scalar& sigma) -> LongScalar +auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std::span mu, const Scalar& sigma) -> LongScalar { using std::abs; using std::isfinite; @@ -182,11 +182,11 @@ auto AdaptiveQuadratureBase::integrateWithHints(const Function& f, cons } if (m_out) { fmt::print(m_out, "#NumericalIntegrator adapting quadrature over {}\n", m_intervals); } - return adaptQuadrature(f); + return adaptQuadrature(std::forward(f)); } template template -auto AdaptiveQuadratureBase::integrateLeftInfinite(const Function& f, const Scalar& xmax) -> LongScalar +auto AdaptiveQuadratureBase::integrateLeftInfinite(Function&& f, const Scalar& xmax) -> LongScalar { using std::isfinite; using std::abs; @@ -200,11 +200,11 @@ auto AdaptiveQuadratureBase::integrateLeftInfinite(const Function& f, c xmin *= 2; leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, xmin); } - return isfinite(leftIntegral) ? integrate(f, xmin, xmax) : NumTraits::NaN; + return isfinite(leftIntegral) ? integrate(std::forward(f), xmin, xmax) : NumTraits::NaN; } template template -auto AdaptiveQuadratureBase::integrateRightInfinite(const Function& f, const Scalar& xmin) -> LongScalar +auto AdaptiveQuadratureBase::integrateRightInfinite(Function&& f, const Scalar& xmin) -> LongScalar { using std::isfinite; using std::abs; @@ -218,11 +218,15 @@ auto AdaptiveQuadratureBase::integrateRightInfinite(const Function& f, xmax *= 2; rightIntegral = gLaguerreQuad.integrateRightInfinite(f, xmax); } - return isfinite(rightIntegral) ? integrate(f, xmin, xmax) : NumTraits::NaN; + const LongScalar ret = isfinite(rightIntegral) + ? integrate(std::forward(f), xmin, xmax) + : NumTraits::NaN; + + return ret; } template template -auto AdaptiveQuadratureBase::integrate(const Function& f) -> LongScalar +auto AdaptiveQuadratureBase::integrate(Function&& f) -> LongScalar { using std::isfinite; using std::abs; @@ -237,17 +241,19 @@ auto AdaptiveQuadratureBase::integrate(const Function& f) -> LongScalar leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, xmin); } - return isfinite(leftIntegral) ? integrateRightInfinite(f, xmin) : NumTraits::NaN; + const LongScalar ret = isfinite(leftIntegral) + ? integrateRightInfinite(std::forward(f), xmin) + : NumTraits::NaN; + + return ret; } template template -auto AdaptiveQuadratureBase::remapAndIntegrate(const Function& f) -> LongScalar +auto AdaptiveQuadratureBase::remapAndIntegrate(Function&& f) -> LongScalar { using std::isnan; - constexpr Scalar eps = {}; - - const auto fref = [&f](const Scalar t) -> LongScalar + return integrate([&f](const Scalar t) -> LongScalar { const LongScalar fx = f(t / (1 - t*t)); const Scalar dxdt = (1 + t*t) / ((1 - t*t)*(1 - t*t)); @@ -255,13 +261,11 @@ auto AdaptiveQuadratureBase::remapAndIntegrate(const Function& f) -> Lo return isnan(fx*dxdt) ? LongScalar{} : fx*dxdt; - }; - - return integrate(fref, -1, 1); + }, -1, 1); } template template -auto AdaptiveQuadratureBase::integrateWithoutAdaptation(const Function& f) const -> std::invoke_result_t +auto AdaptiveQuadratureBase::integrateWithoutAdaptation(Function&& f) const -> std::invoke_result_t { const auto localIntegrals = m_intervals | std::views::transform([&self = derived(), &f](const Interval& interval) -> std::invoke_result_t { From b8670f9979e552f3b1dad3289879c12354be4133 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:14:43 +0200 Subject: [PATCH 32/51] Change function parameter types to rvalue references --- .../AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp index ae2a1ae..e2832f3 100644 --- a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp +++ b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature.hpp @@ -45,9 +45,9 @@ class ClenshawCurtisAdaptiveQuadrature : public AdaptiveQuadratureBase< Clenshaw * @param xmax Upper bound. * @return Pair (integral, estimated error). */ - template constexpr std::pair estimateIntegralImpl(const Function& f, const Scalar& xmin, const Scalar& xmax); + template constexpr std::pair estimateIntegralImpl(Function&& f, const Scalar& xmin, const Scalar& xmax); - template constexpr std::invoke_result_t integrateImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const; + template constexpr std::invoke_result_t integrateImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const; constexpr Scalar getMaxDeltaXImpl(const Scalar& xmin, const Scalar& xmax) const { return (xmax - xmin)*misc::maxDiff(std::span{s_xi}); } private: From 30a2fcf1840bf740b7aa9ff9f8a6e7ce07fd0b22 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:15:34 +0200 Subject: [PATCH 33/51] Change function parameter from const reference to rvalue reference --- .../ClenshawCurtisAdaptiveQuadrature_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature_impl.hpp b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature_impl.hpp index 756c74b..4bb6e06 100644 --- a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisAdaptiveQuadrature_impl.hpp @@ -21,7 +21,7 @@ extern template class ClenshawCurtisAdaptiveQuadrature //// method implementations //// template template -constexpr auto ClenshawCurtisAdaptiveQuadrature::estimateIntegralImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) -> std::pair +constexpr auto ClenshawCurtisAdaptiveQuadrature::estimateIntegralImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) -> std::pair { using std::abs; @@ -52,7 +52,7 @@ constexpr auto ClenshawCurtisAdaptiveQuadrature::estimateIntegralImpl(cons } template template -constexpr auto ClenshawCurtisAdaptiveQuadrature::integrateImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const -> std::invoke_result_t +constexpr auto ClenshawCurtisAdaptiveQuadrature::integrateImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const -> std::invoke_result_t { const auto fx = s_xi | std::views::transform([&f, &xmin, &xmax](const Scalar& xi) -> std::invoke_result_t { From fac70398943478708dabb6860b57a320b2dc92a4 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:17:02 +0200 Subject: [PATCH 34/51] Change function parameter types to rvalue references --- .../ClenshawCurtisHybridAdaptiveQuadrature.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature.hpp b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature.hpp index 75a97ce..8ef1005 100644 --- a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature.hpp +++ b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature.hpp @@ -48,9 +48,9 @@ class ClenshawCurtisHybridAdaptiveQuadrature : public AdaptiveQuadratureBase< Cl * @param xmax Upper bound. * @return Pair (integral, estimated error). */ - template constexpr std::pair estimateIntegralImpl(const Function& f, const Scalar& xmin, const Scalar& xmax); + template constexpr std::pair estimateIntegralImpl(Function&& f, const Scalar& xmin, const Scalar& xmax); - template constexpr std::invoke_result_t integrateImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const; + template constexpr std::invoke_result_t integrateImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const; constexpr Scalar getMaxDeltaXImpl(const Scalar& xmin, const Scalar& xmax) const { return (xmax - xmin)*misc::maxDiff(std::span{s_xi}); } private: From b0991c67edc3fdc2ddcf6d55738b17c52551e9cd Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:17:44 +0200 Subject: [PATCH 35/51] Change Function parameter to rvalue reference in methods --- .../ClenshawCurtisHybridAdaptiveQuadrature_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature_impl.hpp b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature_impl.hpp index 8247edf..34bec7a 100644 --- a/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/ClenshawCurtisHybridAdaptiveQuadrature_impl.hpp @@ -20,7 +20,7 @@ extern template class ClenshawCurtisHybridAdaptiveQuadrature template -constexpr auto ClenshawCurtisHybridAdaptiveQuadrature::estimateIntegralImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) -> std::pair +constexpr auto ClenshawCurtisHybridAdaptiveQuadrature::estimateIntegralImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) -> std::pair { using std::abs; @@ -38,7 +38,7 @@ constexpr auto ClenshawCurtisHybridAdaptiveQuadrature::estimateIntegralImp } template template -constexpr auto ClenshawCurtisHybridAdaptiveQuadrature::integrateImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const -> std::invoke_result_t +constexpr auto ClenshawCurtisHybridAdaptiveQuadrature::integrateImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const -> std::invoke_result_t { const auto fx = s_xi | std::views::transform([&f, &xmin, &xmax](const Scalar& xi) -> std::invoke_result_t { From d2d4f51d14e10c9223970580269e52dee560994d Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:18:11 +0200 Subject: [PATCH 36/51] Change function parameter from const& to && --- include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp b/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp index 40d7ba5..1c58758 100644 --- a/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp +++ b/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature.hpp @@ -49,9 +49,9 @@ class GLCCAdaptiveQuadrature : public AdaptiveQuadratureBase< GLCCAdaptiveQuadra * @param xmax Upper bound. * @return Pair (integral, estimated error). */ - template constexpr std::pair estimateIntegralImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const; + template constexpr std::pair estimateIntegralImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const; - template constexpr std::invoke_result_t integrateImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const; + template constexpr std::invoke_result_t integrateImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const; constexpr Scalar getMaxDeltaXImpl(const Scalar xmin, const Scalar xmax) const { return (xmax - xmin)*misc::maxDiff(std::span{s_xi_cc}); } private: From 256d39245dd1c62212676cff81b620f088d1ccdd Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:18:43 +0200 Subject: [PATCH 37/51] Change function parameter from const& to && --- .../LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature_impl.hpp b/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature_impl.hpp index 906dadc..7306575 100644 --- a/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/GLCCAdaptiveQuadrature_impl.hpp @@ -20,7 +20,7 @@ extern template class GLCCAdaptiveQuadrature; //// method implementations //// template template -constexpr auto GLCCAdaptiveQuadrature::estimateIntegralImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const -> std::pair +constexpr auto GLCCAdaptiveQuadrature::estimateIntegralImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const -> std::pair { using std::abs; @@ -43,7 +43,7 @@ constexpr auto GLCCAdaptiveQuadrature::estimateIntegralImpl(const Function } template template -constexpr auto GLCCAdaptiveQuadrature::integrateImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const -> std::invoke_result_t +constexpr auto GLCCAdaptiveQuadrature::integrateImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const -> std::invoke_result_t { const auto fx = s_xi_gl | std::views::transform([&f, &xmin, &xmax](const Scalar& xi) -> std::invoke_result_t { From 6b193a4a561e6c4295bc90c789c48105e5775e37 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:19:06 +0200 Subject: [PATCH 38/51] Change function parameter types to rvalue references --- .../AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp b/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp index c88c134..4b15474 100644 --- a/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp +++ b/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature.hpp @@ -36,9 +36,9 @@ class GaussLegendreAdaptiveQuadrature : public AdaptiveQuadratureBase< GaussLege * @param xmax Upper bound. * @return Pair (integral, estimated error). */ - template constexpr std::pair estimateIntegralImpl(const Function& f, const Scalar& xmin, const Scalar& xmax); + template constexpr std::pair estimateIntegralImpl(Function&& f, const Scalar& xmin, const Scalar& xmax); - template constexpr std::invoke_result_t integrateImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const; + template constexpr std::invoke_result_t integrateImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const; inline constexpr Scalar getMaxDeltaXImpl(const Scalar xmin, const Scalar xmax) const { return (xmax - xmin)*misc::maxDiff(std::span{s_xi}); } private: From 5054a534ecd37f4b254a766ef8cd61d21fdc144a Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:19:28 +0200 Subject: [PATCH 39/51] Change function parameter from const& to && --- .../GaussLegendreAdaptiveQuadrature_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature_impl.hpp b/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature_impl.hpp index bf3fdff..a348c84 100644 --- a/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/GaussLegendreAdaptiveQuadrature_impl.hpp @@ -20,7 +20,7 @@ extern template class GaussLegendreAdaptiveQuadrature; //// method implementations //// template template -constexpr auto GaussLegendreAdaptiveQuadrature::estimateIntegralImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) -> std::pair +constexpr auto GaussLegendreAdaptiveQuadrature::estimateIntegralImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) -> std::pair { using std::abs; @@ -43,7 +43,7 @@ constexpr auto GaussLegendreAdaptiveQuadrature::estimateIntegralImpl(const } template template -constexpr auto GaussLegendreAdaptiveQuadrature::integrateImpl(const Function& f, const Scalar& xmin, const Scalar& xmax) const -> std::invoke_result_t +constexpr auto GaussLegendreAdaptiveQuadrature::integrateImpl(Function&& f, const Scalar& xmin, const Scalar& xmax) const -> std::invoke_result_t { const auto fx = s_xi | std::views::transform([&f, &xmin, &xmax](const Scalar& xi) -> std::invoke_result_t { From e45d8b53cfbf359a6052bc133f8638dabd8486e4 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:27:08 +0200 Subject: [PATCH 40/51] Fix inner_product range in GaussLaguerreQuadrature --- include/LNIT/GaussLaguerreQuadrature_impl.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/LNIT/GaussLaguerreQuadrature_impl.hpp b/include/LNIT/GaussLaguerreQuadrature_impl.hpp index f5210df..6723e8e 100644 --- a/include/LNIT/GaussLaguerreQuadrature_impl.hpp +++ b/include/LNIT/GaussLaguerreQuadrature_impl.hpp @@ -20,23 +20,23 @@ extern template class GaussLaguerreQuadrature; template template constexpr LongScalar GaussLaguerreQuadrature::integrateLeftInfinite(Function&& f, const Scalar& a) const { - const auto fx = s_xi | std::views::transform([&f, &a](const Scalar& x) -> LongScalar + const auto fx = s_xi | std::views::transform([&&f, &a](const Scalar& x) -> LongScalar { return f(a - x); }); - return std::inner_product(s_wi.begin(), s_wi.end(), fx.end(), LongScalar{}); + return std::inner_product(s_wi.begin(), s_wi.end(), fx.begin(), LongScalar{}); } template template constexpr LongScalar GaussLaguerreQuadrature::integrateRightInfinite(Function&& f, const Scalar& a) const { - const auto fx = s_xi | std::views::transform([&f, &a](const Scalar& x) -> LongScalar + const auto fx = s_xi | std::views::transform([&&f, &a](const Scalar& x) -> LongScalar { return f(x + a); }); - return std::inner_product(s_wi.begin(), s_wi.end(), fx.end(), LongScalar{}); + return std::inner_product(s_wi.begin(), s_wi.end(), fx.begin(), LongScalar{}); } } // namespace LNIT From 7cfb75eafd551740dd396d9130eb4c756b5868ea Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:29:38 +0200 Subject: [PATCH 41/51] Fix lambda capture in GaussLaguerreQuadrature methods --- include/LNIT/GaussLaguerreQuadrature_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/LNIT/GaussLaguerreQuadrature_impl.hpp b/include/LNIT/GaussLaguerreQuadrature_impl.hpp index 6723e8e..526ce53 100644 --- a/include/LNIT/GaussLaguerreQuadrature_impl.hpp +++ b/include/LNIT/GaussLaguerreQuadrature_impl.hpp @@ -20,7 +20,7 @@ extern template class GaussLaguerreQuadrature; template template constexpr LongScalar GaussLaguerreQuadrature::integrateLeftInfinite(Function&& f, const Scalar& a) const { - const auto fx = s_xi | std::views::transform([&&f, &a](const Scalar& x) -> LongScalar + const auto fx = s_xi | std::views::transform([&f, &a](const Scalar& x) -> LongScalar { return f(a - x); }); @@ -31,7 +31,7 @@ constexpr LongScalar GaussLaguerreQuadrature::integrateLeftI template template constexpr LongScalar GaussLaguerreQuadrature::integrateRightInfinite(Function&& f, const Scalar& a) const { - const auto fx = s_xi | std::views::transform([&&f, &a](const Scalar& x) -> LongScalar + const auto fx = s_xi | std::views::transform([&f, &a](const Scalar& x) -> LongScalar { return f(x + a); }); From e86d6281c05eb4543de8eb5920123801dc22bd55 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:30:23 +0200 Subject: [PATCH 42/51] Fix inner_product call to use fx.begin() --- include/LNIT/GaussHermiteQuadrature_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/GaussHermiteQuadrature_impl.hpp b/include/LNIT/GaussHermiteQuadrature_impl.hpp index db3adca..904c196 100644 --- a/include/LNIT/GaussHermiteQuadrature_impl.hpp +++ b/include/LNIT/GaussHermiteQuadrature_impl.hpp @@ -29,7 +29,7 @@ constexpr LongScalar GaussHermiteQuadrature::integrate(Funct return f(x); }); - return std::inner_product(s_wi.begin(), s_wi.end(), fx.end(), LongScalar{}); + return std::inner_product(s_wi.begin(), s_wi.end(), fx.begin(), LongScalar{}); } } // namespace LNIT From 740eb2478b1fb154b3be670d98e4195631abec6e Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:44:51 +0200 Subject: [PATCH 43/51] Refactor integration logic for clarity and safety --- .../AdaptiveQuadratureBase_impl.hpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 94eb773..f7caedf 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -200,7 +201,11 @@ auto AdaptiveQuadratureBase::integrateLeftInfinite(Function&& f, const xmin *= 2; leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, xmin); } - return isfinite(leftIntegral) ? integrate(std::forward(f), xmin, xmax) : NumTraits::NaN; + const LongScalar ret = isfinite(leftIntegral) + ? integrate(std::forward(f), xmin, xmax) + : NumTraits::NaN; + + return ret; } template template @@ -255,12 +260,13 @@ auto AdaptiveQuadratureBase::remapAndIntegrate(Function&& f) -> LongSca return integrate([&f](const Scalar t) -> LongScalar { - const LongScalar fx = f(t / (1 - t*t)); - const Scalar dxdt = (1 + t*t) / ((1 - t*t)*(1 - t*t)); - - return isnan(fx*dxdt) + const LongScalar fx = f(t / (1 - t*t)); + const Scalar dxdt = (1 + t*t) / ((1 - t*t)*(1 - t*t)); + const LongScalar ret = isnan(fx*dxdt) ? LongScalar{} : fx*dxdt; + + return ret; }, -1, 1); } From 94f9aab446ffe4d1dad50892c8e90c68fda42243 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 16:46:09 +0200 Subject: [PATCH 44/51] Use std::forward in estimateIntegral function --- include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp index 4d7e6c6..5d95deb 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase.hpp @@ -65,7 +65,7 @@ class AdaptiveQuadratureBase * * @return Pair (integral, estimated error). */ - template constexpr std::pair estimateIntegral(Function&& f, const Scalar& xmin, const Scalar& xmax) { return derived().estimateIntegralImpl(f, xmin, xmax); } + template constexpr std::pair estimateIntegral(Function&& f, const Scalar& xmin, const Scalar& xmax) { return derived().estimateIntegralImpl(std::forward(f), xmin, xmax); } /** * @brief Perform adaptive quadrature on [xmin, xmax]. From bdf8d2b9c34946032065ae9ebc634bf6979ba029 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 18:21:53 +0200 Subject: [PATCH 45/51] Refactor adaptive quadrature interval handling Updated the scaling factor and improved interval handling in the adaptive quadrature implementation. Added checks for finite integrals and adjusted the logic for adding intervals to capture the entire support. --- .../AdaptiveQuadratureBase_impl.hpp | 84 ++++++++++--------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index f7caedf..a71220a 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -115,45 +115,23 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std using Iterator = typename std::vector::iterator; - constexpr Size scal = 3; + const Scalar scal = 2.58; assert(sigma > Scalar{}); - - GaussLaguerreQuadrature gLaguerreQuad; m_intervals.clear(); m_subIntergrals.clear(); m_subIntergralsErr.clear(); - m_intervals.reserve(2*mu.size()); + m_intervals.reserve(2*mu.size() + 2); - // First pass, we compute intervals near the peaks on which the function is not null. + // First pass, we compute intervals near the peaks. for (const double& mu_i : mu) { Interval curr(mu_i - scal*sigma, mu_i + scal*sigma); if (curr.first > curr.second) { swap(curr.first, curr.second); } - LongScalar leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, curr.first); - while (isfinite(leftIntegral) and abs(leftIntegral) >= NumTraits::epsilon) - { - curr.first -= scal*sigma; - leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, curr.first); - assert(curr.first <= curr.second); - } - - if (not isfinite(leftIntegral)) { return NumTraits::NaN; } - - LongScalar rightIntegral = gLaguerreQuad.integrateRightInfinite(f, curr.second); - while (isfinite(rightIntegral) and abs(rightIntegral) >= NumTraits::epsilon) - { - curr.second += scal*sigma; - rightIntegral = gLaguerreQuad.integrateRightInfinite(f, curr.second); - assert(curr.first <= curr.second); - } - - if (not isfinite(rightIntegral)) { return NumTraits::NaN; } - Iterator firstInterval = m_intervals.begin(); while (firstInterval != m_intervals.end() and firstInterval->second < curr.first) { ++firstInterval; } @@ -168,6 +146,43 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std m_intervals.insert(it, curr); } + // Second pass: add interval in between the previously computed intervals + for (size_t i=0; i+1!=m_intervals.size(); ++i) + { + assert(m_intervals[i].second != m_intervals[i+1].first); + ret.emplace(std::next(m_intervals.begin(), i + 1), m_intervals[i].second, m_intervals[i+1].first); + } + + // now add interval at the front and rear to ensure we capture the whole support + GaussLaguerreQuadrature gLaguerreQuad; + + Scalar xmin = m_intervals.front().first - sigma; + LongScalar leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, xmin); + + while (isfinite(leftIntegral) and abs(leftIntegral) >= NumTraits::epsilon) + { + xmin -= sigma; + leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, xmin); + } + + if (not isfinite(leftIntegral)) { return NumTraits::NaN; } + + m_intervals.emplace(m_intervals.begin(), xmin, m_intervals.front().first); + + Scalar xmax = m_intervals.back().second + sigma; + LongScalar rightIntegral = gLaguerreQuad.integrateRightInfinite(f, xmax); + while (isfinite(rightIntegral) and abs(rightIntegral) >= NumTraits::epsilon) + { + xmax += sigma; + rightIntegral = gLaguerreQuad.integrateRightInfinite(f, xmax); + } + + if (not isfinite(rightIntegral)) { return NumTraits::NaN; } + + m_intervals.emplace_back(m_intervals.back().second, xmax); + + // Finally setup the adaptive quadrature. + LongScalar res; LongScalar estimatedErr; @@ -201,11 +216,10 @@ auto AdaptiveQuadratureBase::integrateLeftInfinite(Function&& f, const xmin *= 2; leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, xmin); } - const LongScalar ret = isfinite(leftIntegral) + + return isfinite(leftIntegral) ? integrate(std::forward(f), xmin, xmax) : NumTraits::NaN; - - return ret; } template template @@ -223,11 +237,9 @@ auto AdaptiveQuadratureBase::integrateRightInfinite(Function&& f, const xmax *= 2; rightIntegral = gLaguerreQuad.integrateRightInfinite(f, xmax); } - const LongScalar ret = isfinite(rightIntegral) + return isfinite(rightIntegral) ? integrate(std::forward(f), xmin, xmax) : NumTraits::NaN; - - return ret; } template template @@ -246,11 +258,9 @@ auto AdaptiveQuadratureBase::integrate(Function&& f) -> LongScalar leftIntegral = gLaguerreQuad.integrateLeftInfinite(f, xmin); } - const LongScalar ret = isfinite(leftIntegral) + return isfinite(leftIntegral) ? integrateRightInfinite(std::forward(f), xmin) : NumTraits::NaN; - - return ret; } template template @@ -262,11 +272,9 @@ auto AdaptiveQuadratureBase::remapAndIntegrate(Function&& f) -> LongSca { const LongScalar fx = f(t / (1 - t*t)); const Scalar dxdt = (1 + t*t) / ((1 - t*t)*(1 - t*t)); - const LongScalar ret = isnan(fx*dxdt) + return isnan(fx*dxdt) ? LongScalar{} - : fx*dxdt; - - return ret; + : fx*dxdt; }, -1, 1); } From 691c6506d0db6039c51b936ead8bd4d0daae5056 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 18:26:57 +0200 Subject: [PATCH 46/51] Fix interval handling in AdaptiveQuadratureBase_impl --- .../AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index a71220a..6a771f0 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -150,7 +150,7 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std for (size_t i=0; i+1!=m_intervals.size(); ++i) { assert(m_intervals[i].second != m_intervals[i+1].first); - ret.emplace(std::next(m_intervals.begin(), i + 1), m_intervals[i].second, m_intervals[i+1].first); + m_intervals.emplace(std::next(m_intervals.begin(), i + 1), m_intervals[i].second, m_intervals[i+1].first); } // now add interval at the front and rear to ensure we capture the whole support @@ -189,9 +189,9 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std m_subIntergrals.reserve(m_intervals.size()); m_subIntergralsErr.reserve(m_intervals.size()); - for (const auto& [xmin, xmax] : m_intervals) + for (const auto& [a, b] : m_intervals) { - std::tie(res, estimatedErr) = estimateIntegral(f, xmin, xmax); + std::tie(res, estimatedErr) = estimateIntegral(f, a, b); m_subIntergrals.push_back(res); m_subIntergralsErr.push_back(estimatedErr); From 158a069ac976c79e7224cd3e4c8a7c27ccc582c9 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 18:35:20 +0200 Subject: [PATCH 47/51] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 6a771f0..a4a3c0d 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -126,7 +126,7 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std m_intervals.reserve(2*mu.size() + 2); // First pass, we compute intervals near the peaks. - for (const double& mu_i : mu) + for (const Scalar& mu_i : mu) { Interval curr(mu_i - scal*sigma, mu_i + scal*sigma); From e4c634bc6196311098625712af87b6c8836c4314 Mon Sep 17 00:00:00 2001 From: Alexandre Hoffmann Date: Fri, 24 Jul 2026 18:40:56 +0200 Subject: [PATCH 48/51] Fix loop condition in interval insertion logic --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index a4a3c0d..739c6a7 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -147,7 +147,7 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std } // Second pass: add interval in between the previously computed intervals - for (size_t i=0; i+1!=m_intervals.size(); ++i) + for (size_t i=0; i+1 Date: Fri, 24 Jul 2026 18:45:33 +0200 Subject: [PATCH 49/51] Fix loop condition to use m_intervals size --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 739c6a7..3ad8afa 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -147,7 +147,7 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std } // Second pass: add interval in between the previously computed intervals - for (size_t i=0; i+1 Date: Fri, 24 Jul 2026 18:54:47 +0200 Subject: [PATCH 50/51] Change scal to constexpr for better optimization --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index 3ad8afa..adea15c 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -115,7 +115,7 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std using Iterator = typename std::vector::iterator; - const Scalar scal = 2.58; + constexpr Scalar scal = Scalar(2.58); assert(sigma > Scalar{}); From d0bc7c61f0ac10afe2394736a21b94453f26b9eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Jul 2026 16:56:20 +0000 Subject: [PATCH 51/51] Add early guard in integrateWithHints for empty mu --- .../LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp index adea15c..8f2069a 100644 --- a/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp +++ b/include/LNIT/AdaptiveQuadratures/AdaptiveQuadratureBase_impl.hpp @@ -123,6 +123,8 @@ auto AdaptiveQuadratureBase::integrateWithHints(Function&& f, const std m_subIntergrals.clear(); m_subIntergralsErr.clear(); + if (mu.empty()) { return integrate(std::forward(f)); } + m_intervals.reserve(2*mu.size() + 2); // First pass, we compute intervals near the peaks.