7#include "../concepts.hpp"
24template<
typename Op,
typename L,
typename R>
31 static constexpr std::size_t
arity_v = std::max(L::arity_v, R::arity_v);
38 [[nodiscard]]
constexpr value_type eval(std::span<value_type const> args)
const {
42 if constexpr (std::is_same_v<Op, Add>) {
44 }
else if constexpr (std::is_same_v<Op, Sub>) {
46 }
else if constexpr (std::is_same_v<Op, Mul>) {
48 }
else if constexpr (std::is_same_v<Op, Div>) {
53 [[nodiscard]] [[deprecated(
"use eval() instead")]]
60 template<std::
size_t Dim>
62 auto dl =
left.template derivative<Dim>();
63 auto dr =
right.template derivative<Dim>();
65 if constexpr (std::is_same_v<Op, Add>) {
67 }
else if constexpr (std::is_same_v<Op, Sub>) {
69 }
else if constexpr (std::is_same_v<Op, Mul>) {
71 }
else if constexpr (std::is_same_v<Op, Div>) {
80 if constexpr (std::is_same_v<Op, Add>) {
82 }
else if constexpr (std::is_same_v<Op, Sub>) {
84 }
else if constexpr (std::is_same_v<Op, Mul>) {
86 }
else if constexpr (std::is_same_v<Op, Div>) {
89 return "(" + op_str +
" " +
left.to_string() +
" " +
right.to_string() +
")";
104template<
typename T,
typename =
void>
108struct is_expr_node<T, std::void_t<decltype(T::arity_v)>> : std::true_type {};
117template<
typename L,
typename R>
118 requires (is_expr_node_v<L> && is_expr_node_v<R>)
119[[nodiscard]]
constexpr auto operator+(L l, R r) {
120 if constexpr (is_zero_v<L>) {
122 }
else if constexpr (is_zero_v<R>) {
124 }
else if constexpr (is_const_expr_v<L> && is_const_expr_v<R>) {
126 }
else if constexpr (std::is_same_v<L, R>) {
127 using T =
typename L::value_type;
135template<
typename L,
typename T>
136 requires (is_expr_node_v<L> && std::is_arithmetic_v<T>)
137[[nodiscard]]
constexpr auto operator+(L l, T r) {
138 using VT =
typename L::value_type;
143template<
typename T,
typename R>
144 requires (std::is_arithmetic_v<T> && is_expr_node_v<R>)
145[[nodiscard]]
constexpr auto operator+(T l, R r) {
146 using VT =
typename R::value_type;
151template<
typename L,
typename R>
152 requires (is_expr_node_v<L> && is_expr_node_v<R>)
153[[nodiscard]]
constexpr auto operator-(L l, R r) {
154 if constexpr (is_zero_v<R>) {
156 }
else if constexpr (is_zero_v<L>) {
158 }
else if constexpr (is_const_expr_v<L> && is_const_expr_v<R>) {
160 }
else if constexpr (std::is_same_v<L, R>) {
168template<
typename L,
typename T>
169 requires (is_expr_node_v<L> && std::is_arithmetic_v<T>)
170[[nodiscard]]
constexpr auto operator-(L l, T r) {
171 using VT =
typename L::value_type;
176template<
typename T,
typename R>
177 requires (std::is_arithmetic_v<T> && is_expr_node_v<R>)
178[[nodiscard]]
constexpr auto operator-(T l, R r) {
179 using VT =
typename R::value_type;
184template<
typename L,
typename R>
185 requires (is_expr_node_v<L> && is_expr_node_v<R> && !is_integral<L>::value && !is_integral<R>::value)
186[[nodiscard]]
constexpr auto operator*(L l, R r) {
187 if constexpr (is_zero_v<L>) {
189 }
else if constexpr (is_zero_v<R>) {
191 }
else if constexpr (is_one_v<L>) {
193 }
else if constexpr (is_one_v<R>) {
195 }
else if constexpr (is_const_expr_v<L> && is_const_expr_v<R>) {
203template<
typename L,
typename T>
204 requires (is_expr_node_v<L> && std::is_arithmetic_v<T>)
205[[nodiscard]]
constexpr auto operator*(L l, T r) {
206 using VT =
typename L::value_type;
211template<
typename T,
typename R>
212 requires (std::is_arithmetic_v<T> && is_expr_node_v<R>)
213[[nodiscard]]
constexpr auto operator*(T l, R r) {
214 using VT =
typename R::value_type;
219template<
typename L,
typename R>
220 requires (is_expr_node_v<L> && is_expr_node_v<R>)
221[[nodiscard]]
constexpr auto operator/(L l, R r) {
222 if constexpr (is_zero_v<L>) {
224 }
else if constexpr (is_one_v<R>) {
226 }
else if constexpr (is_const_expr_v<L> && is_const_expr_v<R>) {
228 }
else if constexpr (std::is_same_v<L, R>) {
236template<
typename L,
typename T>
237 requires (is_expr_node_v<L> && std::is_arithmetic_v<T>)
238[[nodiscard]]
constexpr auto operator/(L l, T r) {
239 using VT =
typename L::value_type;
244template<
typename T,
typename R>
245 requires (std::is_arithmetic_v<T> && is_expr_node_v<R>)
246[[nodiscard]]
constexpr auto operator/(T l, R r) {
247 using VT =
typename R::value_type;
Expression layer for composable calculus.
constexpr bool is_const_expr_v
constexpr bool is_expr_node_v
constexpr Binary(L l, R r) noexcept
constexpr value_type evaluate(std::span< value_type const > args) const
constexpr auto derivative() const
std::string to_string() const
typename L::value_type value_type
static constexpr std::size_t arity_v
constexpr value_type eval(std::span< value_type const > args) const