Skip to content

Commit

Permalink
Merge pull request #649 from mpusz/cpo_refactor
Browse files Browse the repository at this point in the history
refactor: CPOs refactored to be more constrained
  • Loading branch information
mpusz authored Nov 26, 2024
2 parents febdaec + 52b003e commit 81e83db
Showing 21 changed files with 236 additions and 284 deletions.
3 changes: 0 additions & 3 deletions example/include/ranged_representation.h
Original file line number Diff line number Diff line change
@@ -62,9 +62,6 @@ class ranged_representation : public validated_type<T, is_in_range_t<T, Min, Max
}
};

template<typename T, auto Min, auto Max>
constexpr bool mp_units::is_scalar<ranged_representation<T, Min, Max>> = mp_units::is_scalar<T>;

template<typename T, auto Min, auto Max, typename Char>
struct MP_UNITS_STD_FMT::formatter<ranged_representation<T, Min, Max>, Char> : formatter<T, Char> {
template<typename FormatContext>
3 changes: 0 additions & 3 deletions example/include/validated_type.h
Original file line number Diff line number Diff line change
@@ -113,9 +113,6 @@ class validated_type {
= default;
};

template<typename T, typename Validator>
constexpr bool mp_units::is_scalar<validated_type<T, Validator>> = mp_units::is_scalar<T>;


template<typename CharT, typename Traits, typename T, typename Validator>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
4 changes: 0 additions & 4 deletions example/kalman_filter/kalman_filter-example_2.cpp
Original file line number Diff line number Diff line change
@@ -38,10 +38,6 @@ import mp_units;

// Based on: https://www.kalmanfilter.net/alphabeta.html#ex2

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

using namespace mp_units;

void print_header(const kalman::SystemState auto& initial)
4 changes: 0 additions & 4 deletions example/kalman_filter/kalman_filter-example_3.cpp
Original file line number Diff line number Diff line change
@@ -38,10 +38,6 @@ import mp_units;

// Based on: https://www.kalmanfilter.net/alphabeta.html#ex3

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

using namespace mp_units;

void print_header(const kalman::SystemState auto& initial)
4 changes: 0 additions & 4 deletions example/kalman_filter/kalman_filter-example_4.cpp
Original file line number Diff line number Diff line change
@@ -38,10 +38,6 @@ import mp_units;

// Based on: https://www.kalmanfilter.net/alphabeta.html#ex4

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

using namespace mp_units;

void print_header(const kalman::SystemState auto& initial)
13 changes: 8 additions & 5 deletions example/measurement.cpp
Original file line number Diff line number Diff line change
@@ -124,19 +124,22 @@ class measurement {
return os << v.value() << " ± " << v.uncertainty();
}

[[nodiscard]] friend constexpr measurement abs(const measurement& v)
requires requires { abs(v.value()); } || requires { std::abs(v.value()); }
{
using std::abs;
return measurement(abs(v.value()), v.uncertainty());
}

private:
value_type value_{};
value_type uncertainty_{};
};

} // namespace

template<typename T>
constexpr bool mp_units::is_scalar<measurement<T>> = true;
template<typename T>
constexpr bool mp_units::is_vector<measurement<T>> = true;

static_assert(mp_units::RepresentationOf<measurement<double>, mp_units::quantity_character::scalar>);
static_assert(mp_units::RepresentationOf<measurement<double>, mp_units::quantity_character::vector>);

namespace {

6 changes: 0 additions & 6 deletions example/storage_tank.cpp
Original file line number Diff line number Diff line change
@@ -40,12 +40,6 @@ import mp_units;
#include <mp-units/systems/si.h>
#endif

// allows standard gravity (acceleration) and weight (force) to be expressed with scalar representation
// types instead of requiring the usage of Linear Algebra library for this simple example
template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

namespace {

using namespace mp_units;
4 changes: 0 additions & 4 deletions example/strong_angular_quantities.cpp
Original file line number Diff line number Diff line change
@@ -33,10 +33,6 @@ import mp_units;
#include <mp-units/systems/si.h>
#endif

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

int main()
{
using namespace mp_units;
4 changes: 0 additions & 4 deletions example/total_energy.cpp
Original file line number Diff line number Diff line change
@@ -37,10 +37,6 @@ import mp_units;
#include <mp-units/systems/si.h>
#endif

template<class T>
requires mp_units::is_scalar<T>
constexpr bool mp_units::is_vector<T> = true;

namespace {

using namespace mp_units;
5 changes: 1 addition & 4 deletions src/core/include/mp-units/cartesian_vector.h
Original file line number Diff line number Diff line change
@@ -215,7 +215,7 @@ class cartesian_vector {
lhs._coordinates_[2] == rhs._coordinates_[2];
}

[[nodiscard]] friend constexpr T norm(const cartesian_vector& vec)
[[nodiscard]] friend constexpr T magnitude(const cartesian_vector& vec)
requires treat_as_floating_point<T>
{
return vec.magnitude();
@@ -263,9 +263,6 @@ template<typename Arg, typename... Args>
requires(sizeof...(Args) <= 2) && requires { typename std::common_type_t<Arg, Args...>; }
cartesian_vector(Arg, Args...) -> cartesian_vector<std::common_type_t<Arg, Args...>>;

template<class T>
constexpr bool is_vector<cartesian_vector<T>> = true;

} // namespace mp_units

#if MP_UNITS_HOSTED
6 changes: 3 additions & 3 deletions src/core/include/mp-units/complex.h
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@
#include <mp-units/bits/requires_hosted.h>
//
#include <mp-units/bits/module_macros.h>
#include <mp-units/framework/customization_points.h>
#include <mp-units/framework/representation_concepts.h>

#ifndef MP_UNITS_IN_MODULE_INTERFACE
#ifdef MP_UNITS_IMPORT_STD
@@ -38,6 +38,6 @@ import std;
namespace mp_units {

template<typename T>
constexpr bool is_complex<std::complex<T>> = true;
constexpr bool disable_scalar<std::complex<T>> = true;

}
} // namespace mp_units
145 changes: 5 additions & 140 deletions src/core/include/mp-units/framework/customization_points.h
Original file line number Diff line number Diff line change
@@ -60,157 +60,22 @@ constexpr bool treat_as_floating_point =
std::is_floating_point_v<value_type_t<Rep>>;
#endif

/**
* @brief Specifies a type to have a scalar character
*
* A scalar is a physical quantity that has magnitude but no direction.
*/
template<typename Rep>
constexpr bool is_scalar = std::is_floating_point_v<Rep> || (std::is_integral_v<Rep> && !is_same_v<Rep, bool>);
[[deprecated("`is_scalar` is no longer necessary and can simply be removed")]]
constexpr bool is_scalar = false;

/**
* @brief Specifies a type to have a complex character
*
* A complex is a physical quantity that has a complex representation type.
*/
template<typename Rep>
[[deprecated("`is_complex` is no longer necessary and can simply be removed")]]
constexpr bool is_complex = false;

/**
* @brief Specifies a type to have a vector character
*
* Vectors are physical quantities that possess both magnitude and direction
* and whose operations obey the axioms of a vector space.
*
* In specific cases a scalar can represent a vector with the default direction.
* If that is the intent, a user should provide a partial specialization:
*
* @code{.cpp}
* template<class T>
* requires mp_units::is_scalar<T>
* constexpr bool mp_units::is_vector<T> = true;
* @endcode
*/
template<typename Rep>
[[deprecated("`is_vector` is no longer necessary and can simply be removed")]]
constexpr bool is_vector = false;

/**
* @brief Specifies a type to have a tensor character
*
* Tensors can be used to describe more general physical quantities.
*
* A vector is a tensor of the first order and a scalar is a tensor of order zero.
* Similarly to `is_vector` a partial specialization is needed in such cases.
*/
template<typename Rep>
[[deprecated("`is_tensor` is no longer necessary and can simply be removed")]]
constexpr bool is_tensor = false;

MP_UNITS_EXPORT_END

namespace detail::norm_impl {

void norm() = delete; // poison pill

struct norm_t {
template<typename T>
[[nodiscard]] constexpr auto operator()(const T& vec) const
{
if constexpr (requires { vec.norm(); })
return vec.norm();
else if constexpr (requires { norm(vec); })
return norm(vec);
else if constexpr (requires { vec.magnitude(); })
return vec.magnitude();
else if constexpr (requires { magnitude(vec); })
return magnitude(vec);
// TODO Is it a good idea to enable fundamental types to represent vector quantities?
// else if constexpr (is_scalar<T>)
// return std::abs(vec);
}
};

} // namespace detail::norm_impl

inline namespace cpo {

MP_UNITS_EXPORT inline constexpr ::mp_units::detail::norm_impl::norm_t norm;

}

namespace detail::real_impl {

void real() = delete; // poison pill

struct real_t {
template<typename T>
[[nodiscard]] constexpr auto operator()(const T& clx) const
{
if constexpr (requires { clx.real(); })
return clx.real();
else if constexpr (requires { real(clx); })
return real(clx);
}
};

} // namespace detail::real_impl

inline namespace cpo {

MP_UNITS_EXPORT inline constexpr ::mp_units::detail::real_impl::real_t real;

}

namespace detail::imag_impl {

void imag() = delete; // poison pill

struct imag_t {
template<typename T>
[[nodiscard]] constexpr auto operator()(const T& clx) const
{
if constexpr (requires { clx.imag(); })
return clx.imag();
else if constexpr (requires { imag(clx); })
return imag(clx);
}
};

} // namespace detail::imag_impl

inline namespace cpo {

MP_UNITS_EXPORT inline constexpr ::mp_units::detail::imag_impl::imag_t imag;

}

namespace detail::modulus_impl {

void modulus() = delete; // poison pill

struct modulus_t {
template<typename T>
[[nodiscard]] constexpr auto operator()(const T& clx) const
{
if constexpr (requires { clx.modulus(); })
return clx.modulus();
else if constexpr (requires { modulus(clx); })
return modulus(clx);
// `std` made a precedence of using `abs` for modulo on `std::complex`
else if constexpr (requires { abs(clx); })
return abs(clx);
}
};

} // namespace detail::modulus_impl

inline namespace cpo {

MP_UNITS_EXPORT inline constexpr ::mp_units::detail::modulus_impl::modulus_t modulus;

}

MP_UNITS_EXPORT_BEGIN

/**
* @brief A type trait that defines zero, one, min, and max for a representation type
*
4 changes: 4 additions & 0 deletions src/core/include/mp-units/framework/quantity_concepts.h
Original file line number Diff line number Diff line change
@@ -43,6 +43,10 @@ template<typename T>
constexpr bool is_derived_from_specialization_of_quantity =
requires(T* type) { to_base_specialization_of_quantity(type); };

template<typename T>
requires is_derived_from_specialization_of_quantity<T>
constexpr bool is_quantity<T> = true;

} // namespace detail

/**
Loading

0 comments on commit 81e83db

Please sign in to comment.