141template<
typename E, std::u
int64_t AllowedMask>
145template<
typename E, std::
size_t D1, std::
size_t D2,
typename =
void>
146struct is_separable_impl : std::false_type {};
149template<
typename T, std::
size_t D1, std::
size_t D2>
150struct is_separable_impl<
Const<T>, D1, D2> : std::true_type {};
154template<std::
size_t N,
typename T, std::
size_t D1, std::
size_t D2>
155struct is_separable_impl<Var<N, T>, D1, D2>
156 : std::bool_constant<(N == D1) || (N == D2)> {};
160template<
typename L,
typename R, std::
size_t D1, std::
size_t D2>
161struct is_separable_impl<Binary<Mul, L, R>, D1, D2> {
162 static constexpr std::uint64_t mask_d1 = 1ULL << D1;
163 static constexpr std::uint64_t mask_d2 = 1ULL << D2;
166 static constexpr bool lr_separable =
167 depends_only_on_v<L, mask_d1> && depends_only_on_v<R, mask_d2>;
170 static constexpr bool rl_separable =
171 depends_only_on_v<L, mask_d2> && depends_only_on_v<R, mask_d1>;
173 static constexpr bool value = lr_separable || rl_separable;
178template<
typename L,
typename R, std::
size_t D1, std::
size_t D2>
179struct is_separable_impl<Binary<Add, L, R>, D1, D2>
180 : std::bool_constant<
181 is_separable_impl<L, D1, D2>::value &&
182 is_separable_impl<R, D1, D2>::value
185template<
typename L,
typename R, std::
size_t D1, std::
size_t D2>
186struct is_separable_impl<Binary<Sub, L, R>, D1, D2>
187 : std::bool_constant<
188 is_separable_impl<L, D1, D2>::value &&
189 is_separable_impl<R, D1, D2>::value
194template<
typename E, std::
size_t D1, std::
size_t D2>
198template<
typename Op,
typename E, std::
size_t D1, std::
size_t D2>
199struct is_separable_impl<
Unary<Op, E>, D1, D2>
200 : std::bool_constant<single_child_separable_v<Unary<Op, E>, D1, D2>> {};
202template<
typename Tag,
typename E, std::
size_t D1, std::
size_t D2>
203struct is_separable_impl<
UnaryFunc<Tag, E>, D1, D2>
204 : std::bool_constant<single_child_separable_v<UnaryFunc<Tag, E>, D1, D2>> {};
289 : extract_single_child_factor<Unary<Op, E>, TargetDim, OtherDim> {};
293 : extract_single_child_factor<UnaryFunc<Tag, E>, TargetDim, OtherDim> {};
303 static_assert(is_separable_v<E, D1, D2>,
304 "Expression is not separable with respect to the given dimensions");
306 auto g = detail::extract_factor<E, D1, D2>::extract(expr);
307 auto h = detail::extract_factor<E, D2, D1>::extract(expr);
309 return std::make_pair(g, h);