|
| struct | AbsTag |
| |
| struct | AcoshTag |
| |
| struct | AcosTag |
| |
| struct | Add |
| |
| struct | antiderivative_impl |
| |
| struct | antiderivative_impl< Dim, Binary< Add, L, R > > |
| |
| struct | antiderivative_impl< Dim, Binary< Mul, Const< T >, R > > |
| |
| struct | antiderivative_impl< Dim, Binary< Mul, L, Const< T > > > |
| |
| struct | antiderivative_impl< Dim, Binary< Sub, L, R > > |
| |
| struct | antiderivative_impl< Dim, Const< T > > |
| |
| struct | antiderivative_impl< Dim, One< T > > |
| |
| struct | antiderivative_impl< Dim, Pow< Var< Dim, T >, N > > |
| |
| struct | antiderivative_impl< Dim, Unary< Neg, E > > |
| |
| struct | antiderivative_impl< Dim, UnaryFunc< CosTag, Var< Dim, T > > > |
| |
| struct | antiderivative_impl< Dim, UnaryFunc< ExpTag, Var< Dim, T > > > |
| |
| struct | antiderivative_impl< Dim, UnaryFunc< SinTag, Var< Dim, T > > > |
| |
| struct | antiderivative_impl< Dim, Var< Dim, T > > |
| |
| struct | antiderivative_impl< Dim, Zero< T > > |
| |
| struct | AnyExpr |
| |
| struct | AsinhTag |
| |
| struct | AsinTag |
| |
| struct | AtanhTag |
| |
| struct | AtanTag |
| |
| struct | Binary |
| |
| struct | BinaryFunc |
| |
| struct | BoundExpr |
| |
| struct | BoxIntegral |
| | N-dimensional integral over a rectangular box. More...
|
| |
| struct | Conditional |
| |
| struct | Const |
| |
| struct | ConstBound |
| | Constant integration bound (e.g., 0.0, 1.0) More...
|
| |
| struct | ConstrainedBoxIntegral |
| | Box integral with constraint for irregular regions. More...
|
| |
| struct | CoshTag |
| |
| struct | CosTag |
| |
| struct | DerivativeBuilder |
| | Fluent builder for computing symbolic derivatives. More...
|
| |
| struct | Div |
| |
| struct | ExprBound |
| | Expression-valued integration bound (depends on outer variables) More...
|
| |
| struct | ExpTag |
| |
| struct | FiniteProduct |
| |
| struct | FiniteSum |
| |
| struct | has_antiderivative |
| |
| struct | has_antiderivative< Binary< Add, L, R >, Dim > |
| |
| struct | has_antiderivative< Binary< Mul, L, R >, Dim, std::enable_if_t< has_antiderivative_v< L, Dim > &&(is_const_expr_v< R >||is_zero_v< R >||is_one_v< R >) &&!is_const_expr_v< L > &&!is_zero_v< L > &&!is_one_v< L > > > |
| |
| struct | has_antiderivative< Binary< Mul, L, R >, Dim, std::enable_if_t<(is_const_expr_v< L >||is_zero_v< L >||is_one_v< L >||(is_expr_node_v< L > &&!std::is_same_v< L, Var< Dim, typename L::value_type > > &&L::arity_v<=Dim)) &&has_antiderivative_v< R, Dim > > > |
| |
| struct | has_antiderivative< Binary< Sub, L, R >, Dim > |
| |
| struct | has_antiderivative< Const< T >, Dim > |
| |
| struct | has_antiderivative< One< T >, Dim > |
| |
| struct | has_antiderivative< Pow< E, N >, Dim, std::enable_if_t< N !=-1 &&has_antiderivative_v< E, Dim > &&std::is_same_v< E, Var< Dim, typename E::value_type > > > > |
| |
| struct | has_antiderivative< Unary< Neg, E >, Dim > |
| |
| struct | has_antiderivative< UnaryFunc< CosTag, E >, Dim, std::enable_if_t< std::is_same_v< E, Var< Dim, typename E::value_type > > > > |
| |
| struct | has_antiderivative< UnaryFunc< ExpTag, E >, Dim, std::enable_if_t< std::is_same_v< E, Var< Dim, typename E::value_type > > > > |
| |
| struct | has_antiderivative< UnaryFunc< SinTag, E >, Dim, std::enable_if_t< std::is_same_v< E, Var< Dim, typename E::value_type > > > > |
| |
| struct | has_antiderivative< Var< N, T >, Dim > |
| |
| struct | has_antiderivative< Zero< T >, Dim > |
| |
| struct | Integral |
| | Definite integral expression node. More...
|
| |
| struct | IntegralBuilder |
| | Fluent builder for constructing integrals. More...
|
| |
| struct | is_box_integral |
| |
| struct | is_box_integral< BoxIntegral< E, D > > |
| |
| struct | is_conditional |
| |
| struct | is_conditional< Conditional< C, T, E > > |
| |
| struct | is_const_expr |
| |
| struct | is_const_expr< Const< T > > |
| |
| struct | is_constrained_box_integral |
| |
| struct | is_constrained_box_integral< ConstrainedBoxIntegral< E, D, C > > |
| |
| struct | is_derivative_builder |
| |
| struct | is_derivative_builder< DerivativeBuilder< E > > |
| |
| struct | is_expr_node |
| |
| struct | is_expr_node< T, std::void_t< decltype(T::arity_v)> > |
| |
| struct | is_finite_product |
| |
| struct | is_finite_product< FiniteProduct< E, I > > |
| |
| struct | is_finite_sum |
| |
| struct | is_finite_sum< FiniteSum< E, I > > |
| |
| struct | is_integral |
| |
| struct | is_integral< Integral< E, Dim, Lo, Hi > > |
| |
| struct | is_named_var |
| |
| struct | is_named_var< NamedVar< T > > |
| |
| struct | is_product_integral |
| |
| struct | is_product_integral< ProductIntegral< I1, I2 > > |
| |
| struct | is_separable |
| |
| struct | is_static_named_var |
| |
| struct | is_static_named_var< StaticNamedVar< N, T > > |
| |
| struct | LogTag |
| |
| struct | MaxTag |
| |
| struct | MinTag |
| |
| struct | Mul |
| |
| struct | NamedVar |
| |
| struct | Neg |
| |
| struct | negation_inner |
| |
| struct | negation_inner< Unary< Neg, E > > |
| |
| struct | One |
| |
| struct | Pow |
| |
| struct | pow_base |
| |
| struct | pow_base< Pow< E, N > > |
| |
| struct | PowTag |
| |
| struct | ProductIntegral |
| | Product of two independent integrals. More...
|
| |
| struct | SinhTag |
| |
| struct | SinTag |
| |
| struct | SqrtTag |
| |
| struct | StaticNamedVar |
| |
| struct | Sub |
| |
| struct | TanhTag |
| |
| struct | TanTag |
| |
| struct | TransformedIntegral |
| | Integral with change of variables (substitution). More...
|
| |
| struct | Unary |
| |
| struct | UnaryFunc |
| |
| struct | Var |
| |
| struct | variable_set |
| |
| struct | variable_set< Binary< Op, L, R > > |
| | Binary<Op, L, R>: Union of both children's dependencies. More...
|
| |
| struct | variable_set< BoundExpr< E, Dim, BoundValue > > |
| | BoundExpr: Remove the bound dimension, keep remaining dependencies. More...
|
| |
| struct | variable_set< ExprBound< E > > |
| | ExprBound<E>: Same dependencies as the expression. More...
|
| |
| struct | variable_set< Integral< E, Dim, Lo, Hi > > |
| |
| struct | variable_set< Unary< Op, E > > |
| | Unary<Op, E>: Same dependencies as child. More...
|
| |
| struct | variable_set< UnaryFunc< Tag, E > > |
| | UnaryFunc<Tag, E>: Same dependencies as child. More...
|
| |
| struct | variable_set< Var< N, T > > |
| | Var<N, T>: Variable N depends on dimension N. More...
|
| |
| struct | Zero |
| |
|
| template<std::size_t D1, std::size_t D2, typename E > |
| constexpr auto | separate (E const &expr) |
| |
| template<std::size_t Dim, typename E > |
| constexpr auto | antiderivative (E expr) |
| |
| template<std::size_t Dim, typename E , typename T > |
| constexpr T | definite_integral_symbolic (E expr, T a, T b) |
| |
| template<typename E , std::size_t Dims> |
| constexpr auto | over_box (E expr, std::array< std::pair< typename E::value_type, typename E::value_type >, Dims > bounds) |
| | Create a box integral from an expression.
|
| |
| template<typename E > |
| auto | box2d (E expr, typename E::value_type x0, typename E::value_type x1, typename E::value_type y0, typename E::value_type y1) |
| | Create a 2D box integral (specialization for common case)
|
| |
| template<typename E > |
| auto | box3d (E expr, typename E::value_type x0, typename E::value_type x1, typename E::value_type y0, typename E::value_type y1, typename E::value_type z0, typename E::value_type z1) |
| | Create a 3D box integral (specialization for common case)
|
| |
template<std::size_t Dim, typename E >
requires is_expr_node_v<E> |
| constexpr auto | derivative (E expr) |
| |
template<typename E >
requires is_expr_node_v<E> |
| auto | derivative (E expr, std::size_t dim) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | gradient (E expr) |
| |
template<std::size_t Dim, std::size_t... Dims, typename E >
requires is_expr_node_v<E> |
| constexpr auto | derivative_n (E expr) |
| |
template<typename E >
requires (is_expr_node_v<E> && !is_derivative_builder_v<E>) |
| constexpr auto | derivative (E expr) |
| | Create a DerivativeBuilder for fluent derivative computation.
|
| |
template<typename T >
requires std::is_arithmetic_v<T> |
| constexpr auto | make_bound (T value) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | make_bound (E expr) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | integral (E expr) |
| | Create an IntegralBuilder for fluent integral construction.
|
| |
template<typename L , typename R >
requires (is_expr_node_v<L> && is_expr_node_v<R>) |
| constexpr auto | operator+ (L l, R r) |
| |
template<typename L , typename T >
requires (is_expr_node_v<L> && std::is_arithmetic_v<T>) |
| constexpr auto | operator+ (L l, T r) |
| |
template<typename T , typename R >
requires (std::is_arithmetic_v<T> && is_expr_node_v<R>) |
| constexpr auto | operator+ (T l, R r) |
| |
template<typename L , typename R >
requires (is_expr_node_v<L> && is_expr_node_v<R>) |
| constexpr auto | operator- (L l, R r) |
| |
template<typename L , typename T >
requires (is_expr_node_v<L> && std::is_arithmetic_v<T>) |
| constexpr auto | operator- (L l, T r) |
| |
template<typename T , typename R >
requires (std::is_arithmetic_v<T> && is_expr_node_v<R>) |
| constexpr auto | operator- (T l, R r) |
| |
template<typename L , typename R >
requires (is_expr_node_v<L> && is_expr_node_v<R> && !is_integral<L>::value && !is_integral<R>::value) |
| constexpr auto | operator* (L l, R r) |
| |
template<typename L , typename T >
requires (is_expr_node_v<L> && std::is_arithmetic_v<T>) |
| constexpr auto | operator* (L l, T r) |
| |
template<typename T , typename R >
requires (std::is_arithmetic_v<T> && is_expr_node_v<R>) |
| constexpr auto | operator* (T l, R r) |
| |
template<typename L , typename R >
requires (is_expr_node_v<L> && is_expr_node_v<R>) |
| constexpr auto | operator/ (L l, R r) |
| |
template<typename L , typename T >
requires (is_expr_node_v<L> && std::is_arithmetic_v<T>) |
| constexpr auto | operator/ (L l, T r) |
| |
template<typename T , typename R >
requires (std::is_arithmetic_v<T> && is_expr_node_v<R>) |
| constexpr auto | operator/ (T l, R r) |
| |
template<typename L , typename R >
requires (is_expr_node_v<L> && is_expr_node_v<R>) |
| constexpr auto | pow (L base, R exponent) |
| |
template<typename L , typename T >
requires (is_expr_node_v<L> && std::is_arithmetic_v<T>) |
| constexpr auto | pow (L base, T exponent) |
| |
template<typename T , typename R >
requires (std::is_arithmetic_v<T> && is_expr_node_v<R>) |
| constexpr auto | pow (T base, R exponent) |
| |
template<typename L , typename R >
requires (is_expr_node_v<L> && is_expr_node_v<R>) |
| constexpr auto | max (L a, R b) |
| |
template<typename L , typename T >
requires (is_expr_node_v<L> && std::is_arithmetic_v<T>) |
| constexpr auto | max (L a, T b) |
| |
template<typename T , typename R >
requires (std::is_arithmetic_v<T> && is_expr_node_v<R>) |
| constexpr auto | max (T a, R b) |
| |
template<typename L , typename R >
requires (is_expr_node_v<L> && is_expr_node_v<R>) |
| constexpr auto | min (L a, R b) |
| |
template<typename L , typename T >
requires (is_expr_node_v<L> && std::is_arithmetic_v<T>) |
| constexpr auto | min (L a, T b) |
| |
template<typename T , typename R >
requires (std::is_arithmetic_v<T> && is_expr_node_v<R>) |
| constexpr auto | min (T a, R b) |
| |
template<std::size_t Dim, typename E , typename T >
requires is_expr_node_v<E> |
| constexpr auto | bind (E expr, T value) |
| |
template<std::size_t Dim, std::size_t... Dims, typename E , typename T , typename... Ts>
requires is_expr_node_v<E> |
| constexpr auto | bind_all (E expr, T value, Ts... values) |
| |
template<typename E , typename T >
requires is_expr_node_v<E> |
| constexpr auto | partial (E expr, T value) |
| |
template<typename E , typename T >
requires is_expr_node_v<E> |
| constexpr auto | partial_right (E expr, T value) |
| |
template<typename C , typename T , typename E >
requires (is_expr_node_v<C> && is_expr_node_v<T> && is_expr_node_v<E>) |
| constexpr auto | if_then_else (C cond, T then_expr, E else_expr) |
| |
template<typename C , typename T >
requires (is_expr_node_v<C> && std::is_arithmetic_v<T>) |
| constexpr auto | if_then_else (C cond, T then_val, T else_val) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | heaviside (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | ramp (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | sign (E e) |
| |
template<typename E , typename T >
requires (is_expr_node_v<E> && std::is_arithmetic_v<T>) |
| constexpr auto | clamp (E e, T lo, T hi) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | indicator (E e) |
| |
| template<typename T > |
| | Const (T) -> Const< T > |
| |
| template<typename T > |
| constexpr auto | constant (T value) noexcept |
| |
| template<typename T = double> |
| constexpr NamedVar< T > | var (std::size_t dim, std::string_view name) noexcept |
| |
| template<std::size_t N, typename T = double> |
| constexpr StaticNamedVar< N, T > | named (std::string_view name) noexcept |
| |
| template<std::size_t N, typename T , std::size_t... Is> |
| constexpr auto | declare_vars_impl (std::array< std::string_view, N > const &names, std::index_sequence< Is... >) |
| |
template<std::size_t N, typename T = double, typename... Names>
requires (sizeof...(Names) == N) |
| constexpr auto | declare_vars (Names... names) |
| | Usage: auto [x, y, z] = declare_vars<3>("x", "y", "z");.
|
| |
| template<typename T = double> |
| constexpr auto | vars_xy (std::string_view x_name="x", std::string_view y_name="y") |
| |
| template<typename T = double> |
| constexpr auto | vars_xyz (std::string_view x_name="x", std::string_view y_name="y", std::string_view z_name="z") |
| |
template<int N, typename E >
requires is_expr_node_v<E> |
| constexpr auto | pow (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | square (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | cube (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | exp (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | log (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | sin (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | cos (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | sqrt (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | abs (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | tan (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | sinh (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | cosh (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | tanh (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | asin (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | acos (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | atan (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | asinh (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | acosh (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | atanh (E e) |
| |
template<std::size_t IndexDim, typename E >
requires is_expr_node_v<E> |
| constexpr auto | sum (E body, int lo, int hi) |
| |
template<std::size_t IndexDim, typename E >
requires is_expr_node_v<E> |
| constexpr auto | product (E body, int lo, int hi) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | operator- (E e) |
| |
template<typename E >
requires is_expr_node_v<E> |
| constexpr auto | operator+ (E e) |
| |
template<typename I1 , typename I2 >
requires (is_integral_v<I1> && is_integral_v<I2>) |
| constexpr auto | operator* (I1 const &i1, I2 const &i2) |
| |
template<typename I1 , typename I2 , typename I3 >
requires is_integral_v<I3> |
| constexpr auto | operator* (ProductIntegral< I1, I2 > const &pi, I3 const &i3) |
| | Multiply ProductIntegral with another integral.
|
| |
template<typename I1 , typename I2 , typename I3 >
requires is_integral_v<I3> |
| constexpr auto | operator* (I3 const &i3, ProductIntegral< I1, I2 > const &pi) |
| | Multiply integral with ProductIntegral.
|
| |
template<typename I1 , typename I2 >
requires (EvaluableIntegral<I1> && EvaluableIntegral<I2>) |
| constexpr auto | product (I1 const &i1, I2 const &i2) |
| | Create a product of two independent integrals.
|
| |
template<typename I1 , typename I2 , typename... Is>
requires (EvaluableIntegral<I1> && EvaluableIntegral<I2> && (EvaluableIntegral<Is> && ...)) |
| constexpr auto | product (I1 const &i1, I2 const &i2, Is const &... is) |
| | Create a product of multiple independent integrals.
|
| |
template<typename E >
requires is_expr_node_v<E> |
| std::string | to_string (E const &expr) |
| |
template<typename E >
requires is_expr_node_v<E> |
| std::string | pretty_print (E const &expr) |
| |
template<typename E >
requires is_expr_node_v<E> |
| std::ostream & | operator<< (std::ostream &os, E const &expr) |
| |
|
| template<typename E > |
| constexpr std::uint64_t | variable_set_v = variable_set<E>::value |
| | Helper variable template for cleaner syntax.
|
| |
| template<typename E , std::size_t Dim> |
| constexpr bool | depends_on_v = (variable_set<E>::value & (1ULL << Dim)) != 0 |
| | Check if an expression depends on a specific dimension.
|
| |
| template<typename E , std::uint64_t Mask> |
| constexpr bool | depends_on_any_v = (variable_set<E>::value & Mask) != 0 |
| | Check if an expression depends on any of the given dimensions (mask)
|
| |
| template<typename E , std::uint64_t Mask> |
| constexpr bool | depends_on_all_v = (variable_set<E>::value & Mask) == Mask |
| | Check if an expression depends on all of the given dimensions (mask)
|
| |
| template<typename E > |
| constexpr bool | is_constant_v = (variable_set<E>::value == 0) |
| | Check if an expression is constant (depends on no variables)
|
| |
| template<typename E > |
| constexpr std::size_t | dependency_count_v |
| | Count the number of dimensions an expression depends on.
|
| |
| template<typename E > |
| constexpr std::size_t | max_dimension_v |
| | Get the maximum dimension index an expression depends on (0 if constant)
|
| |
| template<typename E , std::size_t D1, std::size_t D2> |
| constexpr bool | is_separable_v = is_separable<E, D1, D2>::value |
| |
| template<typename E , std::size_t Dim> |
| constexpr bool | has_antiderivative_v = has_antiderivative<E, Dim>::value |
| |
| template<typename T > |
| constexpr bool | is_box_integral_v = is_box_integral<T>::value |
| |
| template<typename T > |
| constexpr bool | is_constrained_box_integral_v = is_constrained_box_integral<T>::value |
| |
| template<typename T > |
| constexpr bool | is_derivative_builder_v = is_derivative_builder<T>::value |
| |
| template<typename T > |
| constexpr bool | is_integral_v = is_integral<T>::value |
| |
| template<typename T > |
| constexpr bool | is_const_expr_v = is_const_expr<T>::value |
| |
| template<typename T > |
| constexpr bool | is_expr_node_v = is_expr_node<T>::value |
| |
| template<typename E > |
| constexpr bool | is_binary_func_v = false |
| |
| template<typename Tag , typename L , typename R > |
| constexpr bool | is_binary_func_v< BinaryFunc< Tag, L, R > > = true |
| |
| template<typename E > |
| constexpr bool | is_runtime_pow_v = false |
| |
| template<typename L , typename R > |
| constexpr bool | is_runtime_pow_v< BinaryFunc< PowTag, L, R > > = true |
| |
| template<typename E > |
| constexpr bool | is_max_v = false |
| |
| template<typename L , typename R > |
| constexpr bool | is_max_v< BinaryFunc< MaxTag, L, R > > = true |
| |
| template<typename E > |
| constexpr bool | is_min_v = false |
| |
| template<typename L , typename R > |
| constexpr bool | is_min_v< BinaryFunc< MinTag, L, R > > = true |
| |
| template<typename T > |
| constexpr bool | is_conditional_v = is_conditional<T>::value |
| |
| template<typename E > |
| constexpr bool | is_zero_v = false |
| |
| template<typename T > |
| constexpr bool | is_zero_v< Zero< T > > = true |
| |
| template<typename E > |
| constexpr bool | is_one_v = false |
| |
| template<typename T > |
| constexpr bool | is_one_v< One< T > > = true |
| |
| template<typename T > |
| constexpr bool | is_named_var_v = is_named_var<T>::value |
| |
| template<typename T > |
| constexpr bool | is_static_named_var_v = is_static_named_var<T>::value |
| |
| template<typename E > |
| constexpr bool | is_pow_v = false |
| |
| template<typename E , int N> |
| constexpr bool | is_pow_v< Pow< E, N > > = true |
| |
| template<typename E > |
| constexpr int | pow_exponent_v = 0 |
| |
| template<typename E , int N> |
| constexpr int | pow_exponent_v< Pow< E, N > > = N |
| |
| template<typename T > |
| constexpr bool | is_finite_sum_v = is_finite_sum<T>::value |
| |
| template<typename T > |
| constexpr bool | is_finite_product_v = is_finite_product<T>::value |
| |
| template<typename E > |
| constexpr bool | is_negation_v = false |
| |
| template<typename E > |
| constexpr bool | is_negation_v< Unary< Neg, E > > = true |
| |
| template<typename T = double> |
| constexpr Var< 0, T > | x {} |
| |
| template<typename T = double> |
| constexpr Var< 1, T > | y {} |
| |
| template<typename T = double> |
| constexpr Var< 2, T > | z {} |
| |
| template<std::size_t N, typename T = double> |
| constexpr Var< N, T > | arg {} |
| |
| template<typename T > |
| constexpr bool | is_product_integral_v = is_product_integral<T>::value |
| |
| template<typename I1 , typename I2 > |
| constexpr bool | are_independent_integrals_v |
| | Check if multiplying integrals is valid (they must be over independent dimensions)
|
| |