feat: math functions can now be safely used with user-defined types

Resolves #310
This commit is contained in:
Mateusz Pusz
2021-11-09 19:26:26 +01:00
parent 506408a316
commit 6e6c5c281a

View File

@@ -49,7 +49,8 @@ namespace units {
*/ */
template<std::intmax_t Num, std::intmax_t Den = 1, Quantity Q> template<std::intmax_t Num, std::intmax_t Den = 1, Quantity Q>
requires detail::non_zero<Den> requires detail::non_zero<Den>
[[nodiscard]] inline auto pow(const Q& q) noexcept requires requires { std::pow(q.number(), 1.0); } [[nodiscard]] inline auto pow(const Q& q) noexcept
requires requires { pow(q.number(), 1.0); } || requires { std::pow(q.number(), 1.0); }
{ {
using rep = TYPENAME Q::rep; using rep = TYPENAME Q::rep;
if constexpr (Num == 0) { if constexpr (Num == 0) {
@@ -57,8 +58,9 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Quantity Q>
} else { } else {
using dim = dimension_pow<typename Q::dimension, Num, Den>; using dim = dimension_pow<typename Q::dimension, Num, Den>;
using unit = downcast_unit<dim, pow<Num, Den>(Q::unit::ratio)>; using unit = downcast_unit<dim, pow<Num, Den>(Q::unit::ratio)>;
using std::pow;
return quantity<dim, unit, rep>( return quantity<dim, unit, rep>(
static_cast<rep>(std::pow(q.number(), static_cast<double>(Num) / static_cast<double>(Den)))); static_cast<rep>(pow(q.number(), static_cast<double>(Num) / static_cast<double>(Den))));
} }
} }
@@ -72,12 +74,13 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Quantity Q>
*/ */
template<Quantity Q> template<Quantity Q>
[[nodiscard]] inline Quantity auto sqrt(const Q& q) noexcept [[nodiscard]] inline Quantity auto sqrt(const Q& q) noexcept
requires requires { std::sqrt(q.number()); } requires requires { sqrt(q.number()); } || requires { std::sqrt(q.number()); }
{ {
using dim = dimension_pow<typename Q::dimension, 1, 2>; using dim = dimension_pow<typename Q::dimension, 1, 2>;
using unit = downcast_unit<dim, sqrt(Q::unit::ratio)>; using unit = downcast_unit<dim, sqrt(Q::unit::ratio)>;
using rep = TYPENAME Q::rep; using rep = TYPENAME Q::rep;
return quantity<dim, unit, rep>(static_cast<rep>(std::sqrt(q.number()))); using std::sqrt;
return quantity<dim, unit, rep>(static_cast<rep>(sqrt(q.number())));
} }
/** /**
@@ -90,12 +93,13 @@ template<Quantity Q>
*/ */
template<Quantity Q> template<Quantity Q>
[[nodiscard]] inline Quantity auto cbrt(const Q& q) noexcept [[nodiscard]] inline Quantity auto cbrt(const Q& q) noexcept
requires requires { std::cbrt(q.number()); } requires requires { cbrt(q.number()); } || requires { std::cbrt(q.number()); }
{ {
using dim = dimension_pow<typename Q::dimension, 1, 3>; using dim = dimension_pow<typename Q::dimension, 1, 3>;
using unit = downcast_unit<dim, cbrt(Q::unit::ratio)>; using unit = downcast_unit<dim, cbrt(Q::unit::ratio)>;
using rep = TYPENAME Q::rep; using rep = TYPENAME Q::rep;
return quantity<dim, unit, rep>(static_cast<rep>(std::cbrt(q.number()))); using std::cbrt;
return quantity<dim, unit, rep>(static_cast<rep>(cbrt(q.number())));
} }
/** /**
@@ -108,8 +112,10 @@ template<Quantity Q>
*/ */
template<typename U, typename Rep> template<typename U, typename Rep>
[[nodiscard]] inline dimensionless<U, Rep> exp(const dimensionless<U, Rep>& q) [[nodiscard]] inline dimensionless<U, Rep> exp(const dimensionless<U, Rep>& q)
requires requires { exp(q.number()); } || requires { std::exp(q.number()); }
{ {
return quantity_cast<U>(dimensionless<one, Rep>(std::exp(quantity_cast<one>(q).number()))); using std::exp;
return quantity_cast<U>(dimensionless<one, Rep>(exp(quantity_cast<one>(q).number())));
} }
/** /**
@@ -120,9 +126,10 @@ template<typename U, typename Rep>
*/ */
template<typename D, typename U, typename Rep> template<typename D, typename U, typename Rep>
[[nodiscard]] inline quantity<D, U, Rep> abs(const quantity<D, U, Rep>& q) noexcept [[nodiscard]] inline quantity<D, U, Rep> abs(const quantity<D, U, Rep>& q) noexcept
requires requires { std::abs(q.number()); } requires requires { abs(q.number()); } || requires { std::abs(q.number()); }
{ {
return quantity<D, U, Rep>(std::abs(q.number())); using std::abs;
return quantity<D, U, Rep>(abs(q.number()));
} }
/** /**