54#include "../algorithms/integrators/integrators.hpp"
55#include "../methods/methods.hpp"
68template<
typename E, std::
size_t Dim,
typename Lo,
typename Hi>
72struct IntegralBuilder;
74template<
typename OriginalIntegral,
typename Phi,
typename Jacobian>
75struct TransformedIntegral;
81template<std::
size_t Dim,
typename E,
typename T>
83 return [&integrand, outer_args](T
x) -> T {
84 std::vector<T> full_args;
85 full_args.reserve(E::arity_v);
87 std::size_t args_idx = 0;
88 for (std::size_t i = 0; i < E::arity_v; ++i) {
90 full_args.push_back(
x);
91 }
else if (args_idx < outer_args.size()) {
92 full_args.push_back(outer_args[args_idx++]);
94 full_args.push_back(T{0});
98 return integrand.eval(std::span<T const>{full_args});
110template<
typename E, std::
size_t Dim,
typename Lo,
typename Hi>
124 template<
typename Args>
125 [[nodiscard]]
constexpr T
eval(Args
const& )
const noexcept {
129 template<
typename Args>
130 [[nodiscard]] [[deprecated(
"use eval() instead")]]
131 constexpr T
evaluate(Args
const& args)
const noexcept {
136 std::ostringstream oss;
149 template<
typename Args>
150 [[nodiscard]]
constexpr auto eval(Args
const& args)
const {
151 return expr.eval(args);
154 template<
typename Args>
155 [[nodiscard]] [[deprecated(
"use eval() instead")]]
161 return "(bound " +
expr.to_string() +
")";
167 requires std::is_arithmetic_v<T>
173 requires is_expr_node_v<E>
209template<
typename E, std::
size_t Dim,
typename Lo,
typename Hi>
216 static constexpr std::size_t
dim_v = Dim;
217 static constexpr std::size_t
arity_v = (E::arity_v > 0) ? (E::arity_v - 1) : 0;
228 [[nodiscard]] algorithms::integration_result<value_type>
229 eval(std::span<value_type const> args)
const {
232 auto f = detail::make_integrand_fn<Dim>(
integrand, args);
240 return eval(std::span<value_type const>{});
244 template<
typename Method>
245 requires methods::is_integration_method_v<Method>
247 eval(Method
const& method, std::span<value_type const> args)
const {
250 auto f = detail::make_integrand_fn<Dim>(
integrand, args);
252 return method(f, lo, hi);
256 template<
typename Method>
257 requires methods::is_integration_method_v<Method>
259 eval(Method
const& method)
const {
260 return eval(method, std::span<value_type const>{});
264 [[nodiscard]] [[deprecated(
"use eval() instead")]]
270 [[nodiscard]] [[deprecated(
"use eval() instead")]]
276 template<std::
size_t NewDim,
typename NewLo,
typename NewHi>
277 [[nodiscard]]
constexpr auto over(NewLo lo, NewHi hi)
const {
285 template<std::
size_t NewDim>
294 return "(integral " +
integrand.to_string() +
295 " [" + std::to_string(Dim) +
" " +
296 lower.to_string() +
" " +
upper.to_string() +
"])";
314 template<std::
size_t SplitDim = Dim>
316 static_assert(SplitDim == Dim,
317 "split() can only split on the integration dimension");
325 return std::make_pair(left, right);
338 template<std::
size_t D1, std::
size_t D2>
339 requires is_integral_v<E>
340 [[nodiscard]]
constexpr auto swap()
const {
352 using InnerIntegrand =
typename E::integrand_type;
353 using InnerLo =
typename E::lower_bound_type;
354 using InnerHi =
typename E::upper_bound_type;
355 constexpr std::size_t InnerDim = E::dim_v;
363 return NewOuterType{new_inner, inner.
lower, inner.upper,
tolerance};
379 template<
typename Phi,
typename Jacobian>
387 *
this, phi, jacobian, new_lower, new_upper,
tolerance
434 template<std::
size_t Dim,
typename Lo,
typename Hi>
435 [[nodiscard]]
constexpr auto over(Lo lo, Hi hi)
const {
443 template<
typename Lo,
typename Hi>
444 [[nodiscard]]
constexpr auto over(std::size_t dim, Lo lo, Hi hi)
const {
446 if (dim == 0)
return over<0>(lo, hi);
447 if (dim == 1)
return over<1>(lo, hi);
448 if (dim == 2)
return over<2>(lo, hi);
449 if (dim == 3)
return over<3>(lo, hi);
451 return over<0>(lo, hi);
460 template<std::
size_t Dims>
462 std::array<std::pair<value_type, value_type>, Dims> bounds
469 std::pair<value_type, value_type> b0,
470 std::pair<value_type, value_type> b1
477 std::pair<value_type, value_type> b0,
478 std::pair<value_type, value_type> b1,
479 std::pair<value_type, value_type> b2
481 return BoxIntegral<E, 3>{
expr, {{{b0.first, b0.second}, {b1.first, b1.second}, {b2.first, b2.second}}}};
504 requires is_expr_node_v<E>
543template<
typename OriginalIntegral,
typename Phi,
typename Jacobian>
547 static constexpr std::size_t
arity_v = OriginalIntegral::arity_v;
557 OriginalIntegral orig,
573 [[nodiscard]] algorithms::integration_result<value_type>
574 eval(std::span<value_type const> args)
const {
575 constexpr std::size_t dim = OriginalIntegral::dim_v;
576 auto base_fn = detail::make_integrand_fn<dim>(
original.integrand, args);
581 return base_fn(
x) * jac;
589 return eval(std::span<value_type const>{});
593 [[nodiscard]] [[deprecated(
"use eval() instead")]]
599 [[nodiscard]] [[deprecated(
"use eval() instead")]]
605 std::ostringstream oss;
606 oss <<
"(transformed-integral " <<
original.to_string()
616namespace transforms {
624 constexpr linear(T scale, T shift) noexcept :
a{scale},
b{shift} {}
655 return T(2) * std::abs(t);
N-dimensional box integration with Monte Carlo methods.
constexpr auto make_bound(T value)
constexpr bool is_integral_v
constexpr auto integral(E expr)
Create an IntegralBuilder for fluent integral construction.
auto make_integrand_fn(E const &integrand, std::span< T const > outer_args)
Expression layer for composable calculus.
N-dimensional integral over a rectangular box.
Constant integration bound (e.g., 0.0, 1.0)
constexpr ConstBound() noexcept
constexpr T eval(Args const &) const noexcept
constexpr ConstBound(T v) noexcept
std::string to_string() const
constexpr T evaluate(Args const &args) const noexcept
Expression-valued integration bound (depends on outer variables)
constexpr auto evaluate(Args const &args) const
std::string to_string() const
constexpr ExprBound(E e) noexcept
constexpr auto eval(Args const &args) const
Fluent builder for constructing integrals.
constexpr auto over_box(std::array< std::pair< value_type, value_type >, Dims > bounds) const
constexpr auto over_box(std::pair< value_type, value_type > b0, std::pair< value_type, value_type > b1) const
typename E::value_type value_type
constexpr auto over_box(std::pair< value_type, value_type > b0, std::pair< value_type, value_type > b1, std::pair< value_type, value_type > b2) const
constexpr IntegralBuilder with_tolerance(value_type tol) const
constexpr IntegralBuilder(E e, value_type tol=value_type(1e-10)) noexcept
constexpr auto over(Lo lo, Hi hi) const
constexpr auto over(std::size_t dim, Lo lo, Hi hi) const
Definite integral expression node.
constexpr auto swap() const
constexpr auto transform(Phi phi, Jacobian jacobian, value_type new_lower, value_type new_upper) const
algorithms::integration_result< value_type > evaluate() const
constexpr auto over(value_type lo, value_type hi) const
algorithms::integration_result< value_type > evaluate(std::span< value_type const > args) const
static constexpr std::size_t dim_v
algorithms::integration_result< value_type > eval(Method const &method, std::span< value_type const > args) const
Evaluate the integral using a specific integration method.
std::string to_string() const
constexpr auto with_tolerance(value_type tol) const
Set new tolerance for this integral.
static constexpr std::size_t arity_v
constexpr auto split(value_type point) const
algorithms::integration_result< value_type > eval(std::span< value_type const > args) const
algorithms::integration_result< value_type > eval(Method const &method) const
Evaluate the integral using a specific method (no outer arguments)
typename E::value_type value_type
constexpr auto over(NewLo lo, NewHi hi) const
constexpr Integral(E e, Lo lo, Hi hi, value_type tol=value_type(1e-10)) noexcept
algorithms::integration_result< value_type > eval() const