mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-29 18:07:16 +02:00
refactor: multiplication and division by scalars was a bad idea for Complex
and Vector
This commit is contained in:
@ -168,22 +168,18 @@ constexpr bool disable_complex = false;
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Complex =
|
concept Complex = (!disable_complex<T>) && WeaklyRegular<T> && requires(T a, T b) {
|
||||||
(!disable_complex<T>) && WeaklyRegular<T> && Scalar<value_type_t<T>> &&
|
// complex operations
|
||||||
std::constructible_from<T, value_type_t<T>, value_type_t<T>> && requires(T a, T b, value_type_t<T> s) {
|
{ -a } -> std::common_with<T>;
|
||||||
// complex operations
|
{ a + b } -> std::common_with<T>;
|
||||||
{ -a } -> std::common_with<T>;
|
{ a - b } -> std::common_with<T>;
|
||||||
{ a + b } -> std::common_with<T>;
|
{ a* b } -> std::common_with<T>;
|
||||||
{ a - b } -> std::common_with<T>;
|
{ a / b } -> std::common_with<T>;
|
||||||
{ a* b } -> std::common_with<T>;
|
::mp_units::real(a);
|
||||||
{ a / b } -> std::common_with<T>;
|
::mp_units::imag(a);
|
||||||
{ a* s } -> std::common_with<T>;
|
::mp_units::modulus(a);
|
||||||
{ s* a } -> std::common_with<T>;
|
requires std::constructible_from<T, decltype(::mp_units::real(a)), decltype(::mp_units::imag(a))>;
|
||||||
{ a / s } -> std::common_with<T>;
|
};
|
||||||
::mp_units::real(a);
|
|
||||||
::mp_units::imag(a);
|
|
||||||
::mp_units::modulus(a);
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace magnitude_impl {
|
namespace magnitude_impl {
|
||||||
|
|
||||||
@ -233,23 +229,19 @@ constexpr bool disable_vector = false;
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept Vector =
|
concept Vector = (!disable_vector<T>) && WeaklyRegular<T> && requires(T a, T b) {
|
||||||
(!disable_vector<T>) && WeaklyRegular<T> && Scalar<value_type_t<T>> && requires(T a, T b, value_type_t<T> s) {
|
// vector operations
|
||||||
// vector operations
|
{ -a } -> std::common_with<T>;
|
||||||
{ -a } -> std::common_with<T>;
|
{ a + b } -> std::common_with<T>;
|
||||||
{ a + b } -> std::common_with<T>;
|
{ a - b } -> std::common_with<T>;
|
||||||
{ a - b } -> std::common_with<T>;
|
::mp_units::magnitude(a);
|
||||||
{ a* s } -> std::common_with<T>;
|
// TODO should we also check for the below (e.g., when `size() > 1` or `2`)
|
||||||
{ s* a } -> std::common_with<T>;
|
// { zero_vector<T>() } -> Vector;
|
||||||
{ a / s } -> std::common_with<T>;
|
// { unit_vector(a) } -> Vector;
|
||||||
::mp_units::magnitude(a);
|
// { scalar_product(a, b) } -> Scalar;
|
||||||
// TODO should we check for the below as well (e.g., when `size() > 1` or `2`)
|
// { vector_product(a, b) } -> Vector;
|
||||||
// { zero_vector<T>() } -> Vector;
|
// { tensor_product(a, b) } -> Tensor2;
|
||||||
// { unit_vector(a) } -> Vector;
|
};
|
||||||
// { scalar_product(a, b) } -> Scalar;
|
|
||||||
// { vector_product(a, b) } -> Vector;
|
|
||||||
// { tensor_product(a, b) } -> Tensor2;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO provide when some actual operations will be required
|
// TODO provide when some actual operations will be required
|
||||||
// template<typename T>
|
// template<typename T>
|
||||||
@ -266,27 +258,33 @@ constexpr bool is_quantity = false;
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
using scaling_factor_type_t = conditional<treat_as_floating_point<T>, long double, std::intmax_t>;
|
using scaling_factor_type_t = conditional<treat_as_floating_point<T>, long double, std::intmax_t>;
|
||||||
|
|
||||||
|
// TODO how can we use `(!Quantity<T>)` below?
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept ScalarRepresentation = (!is_quantity<T>) && Scalar<T> && requires(T a, T b, scaling_factor_type_t<T> f) {
|
concept ScalarRepresentation = (!is_quantity<T>) && Scalar<T> && requires(T v, scaling_factor_type_t<T> f) {
|
||||||
// scaling
|
// scaling
|
||||||
{ a* f } -> std::common_with<T>;
|
{ v* f } -> std::common_with<T>;
|
||||||
{ f* a } -> std::common_with<T>;
|
{ f* v } -> std::common_with<T>;
|
||||||
{ a / f } -> std::common_with<T>;
|
{ v / f } -> std::common_with<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept ComplexRepresentation = (!is_quantity<T>) && Complex<T> && requires(T a, T b, scaling_factor_type_t<T> f) {
|
concept ComplexRepresentation = (!is_quantity<T>) && Complex<T> && requires(T v, scaling_factor_type_t<T> f) {
|
||||||
// scaling
|
// scaling
|
||||||
// TODO The below conversion to `T` is an exception compared to other representation types
|
// TODO The below conversion to `T` is an exception compared to other representation types
|
||||||
// `std::complex<T>` * `U` do not work, but `std::complex<T>` is convertible from `U`
|
// `std::complex<T>` * `U` do not work, but `std::complex<T>` is convertible from `U`
|
||||||
// Maybe expose this as a customization point?
|
// Maybe expose this as a customization point?
|
||||||
{ a* T(f) } -> std::common_with<T>;
|
{ v* T(f) } -> std::common_with<T>;
|
||||||
{ T(f) * a } -> std::common_with<T>;
|
{ T(f) * v } -> std::common_with<T>;
|
||||||
{ a / T(f) } -> std::common_with<T>;
|
{ v / T(f) } -> std::common_with<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept VectorRepresentation = (!is_quantity<T>) && Vector<T>;
|
concept VectorRepresentation = (!is_quantity<T>) && Vector<T> && requires(T v, scaling_factor_type_t<T> f) {
|
||||||
|
// scaling
|
||||||
|
{ v* f } -> std::common_with<T>;
|
||||||
|
{ f* v } -> std::common_with<T>;
|
||||||
|
{ v / f } -> std::common_with<T>;
|
||||||
|
};
|
||||||
|
|
||||||
// template<typename T>
|
// template<typename T>
|
||||||
// concept TensorRepresentation = (!is_quantity<T>) && Tensor<T>;
|
// concept TensorRepresentation = (!is_quantity<T>) && Tensor<T>;
|
||||||
|
@ -434,4 +434,14 @@ static_assert(!QuantityPointLike<quantity<isq::time[si::second]>>);
|
|||||||
static_assert(!QuantityPointLike<quantity_point<si::metre, my_origin>>);
|
static_assert(!QuantityPointLike<quantity_point<si::metre, my_origin>>);
|
||||||
static_assert(!QuantityPointLike<int>);
|
static_assert(!QuantityPointLike<int>);
|
||||||
|
|
||||||
|
// Quantity Characters
|
||||||
|
|
||||||
|
static_assert(detail::Scalar<quantity<one>>);
|
||||||
|
static_assert(detail::Scalar<quantity<one, int>>);
|
||||||
|
static_assert(!detail::Scalar<quantity_point<one>>);
|
||||||
|
static_assert(!detail::Scalar<quantity_point<si::metre>>);
|
||||||
|
// TODO it would be make the below work
|
||||||
|
static_assert(!detail::Scalar<quantity<si::metre>>);
|
||||||
|
static_assert(!detail::Scalar<quantity<isq::speed[si::metre / si::second], int>>);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
Reference in New Issue
Block a user