47#include "../algorithms/core/result.hpp"
58template<
typename E, std::
size_t Dim,
typename Lo,
typename Hi>
61template<
typename E, std::
size_t Dims>
64template<
typename I1,
typename I2>
65struct ProductIntegral;
70template<
typename T,
typename =
void>
71struct integral_variable_set {
72 static constexpr std::uint64_t value = 0;
77struct integral_variable_set<T, std::void_t<typename T::integrand_type>> {
78 static constexpr std::uint64_t value = variable_set_v<typename T::integrand_type>;
82template<
typename I1,
typename I2>
83struct integral_variable_set<ProductIntegral<I1, I2>> {
84 static constexpr std::uint64_t value =
85 integral_variable_set<I1>::value | integral_variable_set<I2>::value;
137template<
typename I1,
typename I2>
147 (detail::integral_variable_set_v<I1> & detail::integral_variable_set_v<I2>) == 0,
148 "ProductIntegral requires integrals over independent variables. "
149 "The integrand variable sets must be disjoint."
156 [[nodiscard]] algorithms::integration_result<value_type>
158 return combine_results(
left.eval(),
right.eval());
162 template<
typename... Args>
165 return combine_results(
166 left.eval(std::forward<Args>(args)...),
167 right.eval(std::forward<Args>(args)...));
179 return {value, error,
188 return "(product-integral " +
left.to_string() +
" " +
right.to_string() +
")";
192 template<
typename I3>
193 [[nodiscard]]
constexpr auto operator*(I3
const& other)
const {
205template<
typename I1,
typename I2>
218 { t.eval() } -> std::same_as<algorithms::integration_result<typename T::value_type>>;
227template<
typename I1,
typename I2>
228 requires (is_integral_v<I1> && is_integral_v<I2>)
229[[nodiscard]]
constexpr auto operator*(I1
const& i1, I2
const& i2) {
234template<
typename I1,
typename I2,
typename I3>
235 requires is_integral_v<I3>
241template<
typename I1,
typename I2,
typename I3>
242 requires is_integral_v<I3>
252template<
typename I1,
typename I2>
254 (detail::integral_variable_set_v<I1> & detail::integral_variable_set_v<I2>) == 0;
274template<
typename I1,
typename I2>
276[[nodiscard]]
constexpr auto product(I1
const& i1, I2
const& i2) {
293template<
typename I1,
typename I2,
typename... Is>
294 requires (EvaluableIntegral<I1> && EvaluableIntegral<I2> && (EvaluableIntegral<Is> && ...))
295[[nodiscard]]
constexpr auto product(I1
const& i1, I2
const& i2, Is
const&... is) {
Concept for types that can be evaluated as integrals.
constexpr bool is_product_integral_v
constexpr bool are_independent_integrals_v
Check if multiplying integrals is valid (they must be over independent dimensions)
constexpr std::uint64_t integral_variable_set_v
Expression layer for composable calculus.
constexpr auto operator*(L l, R r)
constexpr auto product(E body, int lo, int hi)
constexpr T error() const noexcept
constexpr std::size_t iterations() const noexcept
constexpr T value() const noexcept
constexpr std::size_t evaluations() const noexcept
Product of two independent integrals.
algorithms::integration_result< value_type > eval(Args &&... args) const
Evaluate with arguments (for integrals with free variables)
constexpr ProductIntegral(I1 i1, I2 i2) noexcept
std::string to_string() const
String representation.
constexpr auto operator*(I3 const &other) const
Multiply with another integral (chaining)
typename I1::value_type value_type
algorithms::integration_result< value_type > eval() const
Evaluate the product integral (no outer arguments)