16 #ifndef OPENKALMAN_VALUE_ARITHMETIC_HPP 17 #define OPENKALMAN_VALUE_ARITHMETIC_HPP 29 template<
typename Arg1,
typename Arg2>
30 using binary_common_type = std::common_type<number_type_of_t<Arg1>, number_type_of_t<Arg2>>;
32 template<
typename Arg1,
typename Arg2>
33 using binary_common_type_t = std::common_type_t<number_type_of_t<Arg1>, number_type_of_t<Arg2>>;
36 #ifndef __cpp_concepts 37 template<
typename Arg1,
typename Arg2,
typename =
void>
40 template<
typename Arg1,
typename Arg2>
42 std::decay_t<decltype(values::to_number(std::declval<Arg1>()))>,
43 std::decay_t<decltype(values::to_number(std::declval<Arg2>()))>>::type>>
48 template<
typename Arg1,
typename Arg2>
50 concept value_common_with = value<Arg1> and value<Arg2> and std::common_with<number_type_of_t<Arg1>, number_type_of_t<Arg2>>;
60 template<
typename Arg, std::enable_if_t<value<Arg>,
int> = 0>
62 constexpr Arg&& operator+(Arg&& arg)
64 return std::forward<Arg>(arg);
69 template<value Arg> requires requires(Arg arg) { -
to_number(std::move(arg)); }
71 template<
typename Arg, std::enable_if_t<value<Arg>,
int> = 0>
73 constexpr
auto operator-(Arg arg)
75 if constexpr (fixed<Arg>)
76 return operation {std::negate{}, std::move(arg)};
83 template<value Arg1, detail::value_common_with<Arg1> Arg2> requires
84 std::invocable<std::plus<detail::binary_common_type_t<Arg1, Arg2>>, Arg1&&, Arg2&&>
86 template<
typename Arg1,
typename Arg2, std::enable_if_t<detail::value_common_with<Arg1, Arg2> and
87 std::is_invocable<std::plus<detail::binary_common_type_t<Arg1, Arg2>>, Arg1&&, Arg2&&>::value,
int> = 0>
89 constexpr
auto operator+(Arg1 arg1, Arg2 arg2)
91 using Common = detail::binary_common_type_t<Arg1, Arg2>;
92 if constexpr (fixed<Arg1> and fixed<Arg2>)
return operation {std::plus<Common>{}, std::move(arg1), std::move(arg2)};
93 else return static_cast<Common
>(
to_number(std::move(arg1))) + static_cast<Common>(
to_number(std::move(arg2)));
98 template<value Arg1, detail::value_common_with<Arg1> Arg2> requires
99 std::invocable<std::minus<detail::binary_common_type_t<Arg1, Arg2>>, Arg1&&, Arg2&&>
101 template<
typename Arg1,
typename Arg2, std::enable_if_t<detail::value_common_with<Arg1, Arg2> and
102 std::is_invocable<std::minus<detail::binary_common_type_t<Arg1, Arg2>>, Arg1&&, Arg2&&>::value,
int> = 0>
104 constexpr
auto operator-(Arg1 arg1, Arg2 arg2)
106 using Common = detail::binary_common_type_t<Arg1, Arg2>;
107 if constexpr (fixed<Arg1> and fixed<Arg2>)
return operation {std::minus<Common>{}, std::move(arg1), std::move(arg2)};
108 else return static_cast<Common
>(
to_number(std::move(arg1))) - static_cast<Common>(
to_number(std::move(arg2)));
112 #ifdef __cpp_concepts 113 template<value Arg1, detail::value_common_with<Arg1> Arg2> requires
114 std::invocable<std::multiplies<detail::binary_common_type_t<Arg1, Arg2>>, Arg1&&, Arg2&&>
116 template<
typename Arg1,
typename Arg2, std::enable_if_t<detail::value_common_with<Arg1, Arg2> and
117 std::is_invocable<std::multiplies<detail::binary_common_type_t<Arg1, Arg2>>, Arg1&&, Arg2&&>::value,
int> = 0>
119 constexpr
auto operator*(Arg1 arg1, Arg2 arg2)
121 using Common = detail::binary_common_type_t<Arg1, Arg2>;
122 if constexpr (fixed<Arg1> and fixed<Arg2>)
return operation {std::multiplies<Common>{}, std::move(arg1), std::move(arg2)};
123 else return static_cast<Common
>(
to_number(std::move(arg1))) * static_cast<Common>(
to_number(std::move(arg2)));
127 #ifdef __cpp_concepts 128 template<value Arg1, detail::value_common_with<Arg1> Arg2> requires
129 std::invocable<std::divides<detail::binary_common_type_t<Arg1, Arg2>>, Arg1&&, Arg2&&>
131 template<
typename Arg1,
typename Arg2, std::enable_if_t<detail::value_common_with<Arg1, Arg2> and
132 std::is_invocable<std::div
ides<detail::binary_common_type_t<Arg1, Arg2>>, Arg1&&, Arg2&&>::value,
int> = 0>
134 constexpr
auto operator/(Arg1 arg1, Arg2 arg2)
136 using Common = detail::binary_common_type_t<Arg1, Arg2>;
137 if constexpr (fixed<Arg1> and fixed<Arg2>)
return operation {std::divides<Common>{}, std::move(arg1), std::move(arg2)};
138 else return static_cast<Common
>(
to_number(std::move(arg1))) / static_cast<Common>(
to_number(std::move(arg2)));
142 #if defined(__cpp_concepts) and defined(__cpp_impl_three_way_comparison) 143 template<value A, detail::value_common_with<A> B> requires
145 constexpr
auto operator<=>(
const A& a,
const B& b)
147 using Common = detail::binary_common_type_t<A, B>;
151 template<value A, detail::value_common_with<A> B> requires
153 constexpr
bool operator==(
const A& a,
const B& b)
155 return std::is_eq(a <=> b);
158 template<
typename A,
typename B, std::enable_if_t<detail::value_common_with<A, B> and
159 std::is_invocable<std::equal_to<detail::binary_common_type_t<A, B>>, const A&, const B&>::value,
int> = 0>
160 constexpr
bool operator==(
const A& a,
const B& b)
162 using Common = detail::binary_common_type_t<A, B>;
166 template<
typename A,
typename B, std::enable_if_t<detail::value_common_with<A, B> and
167 std::is_invocable<std::not_equal_to<detail::binary_common_type_t<A, B>>, const A&, const B&>::value,
int> = 0>
168 constexpr
bool operator!=(
const A& a,
const B& b)
170 using Common = detail::binary_common_type_t<A, B>;
174 template<
typename A,
typename B, std::enable_if_t<detail::value_common_with<A, B> and
175 std::is_invocable<std::less<detail::binary_common_type_t<A, B>>, const A&, const B&>::value,
int> = 0>
176 constexpr
auto operator<(
const A& a,
const B& b)
178 using Common = detail::binary_common_type_t<A, B>;
182 template<
typename A,
typename B, std::enable_if_t<detail::value_common_with<A, B> and
183 std::is_invocable<std::greater<detail::binary_common_type_t<A, B>>, const A&, const B&>::value,
int> = 0>
184 constexpr
auto operator>(
const A& a,
const B& b)
186 using Common = detail::binary_common_type_t<A, B>;
190 template<
typename A,
typename B, std::enable_if_t<detail::value_common_with<A, B> and
191 std::is_invocable<std::less_equal<detail::binary_common_type_t<A, B>>, const A&, const B&>::value,
int> = 0>
192 constexpr
auto operator<=(
const A& a,
const B& b)
194 using Common = detail::binary_common_type_t<A, B>;
198 template<
typename A,
typename B, std::enable_if_t<detail::value_common_with<A, B> and
199 std::is_invocable<std::greater_equal<detail::binary_common_type_t<A, B>>, const A&, const B&>::value,
int> = 0>
200 constexpr
auto operator>=(
const A& a,
const B& b)
202 using Common = detail::binary_common_type_t<A, B>;
210 #endif //OPENKALMAN_VALUE_ARITHMETIC_HPP
Definition for values::to_number.
An operation involving some number of values.
Definition: operation.hpp:69
Definition: tuple_reverse.hpp:103
constexpr auto to_number(Arg arg)
Convert any values::value to a values::number.
Definition: to_number.hpp:34
Definition: value-arithmetic.hpp:38
Definition for values::abs.
Definition: constant_coefficient.hpp:25
std::decay_t< decltype(values::to_number(std::declval< T >()))> number_type_of_t
Obtain the values::number type associated with avalues::value.
Definition: number_type_of_t.hpp:34
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:448