refactor: math refactored to the latest library state

This commit is contained in:
Mateusz Pusz
2023-02-08 21:49:19 -08:00
parent 859bc20fdc
commit 0417507b49

View File

@@ -23,6 +23,7 @@
#pragma once #pragma once
#include <mp_units/bits/external/hacks.h> #include <mp_units/bits/external/hacks.h>
#include <mp_units/bits/value_cast.h>
#include <mp_units/quantity.h> #include <mp_units/quantity.h>
#include <mp_units/systems/angular/angular.h> #include <mp_units/systems/angular/angular.h>
#include <mp_units/systems/isq/space_and_time.h> #include <mp_units/systems/isq/space_and_time.h>
@@ -114,7 +115,7 @@ template<QuantityOf<dimension_one> Q>
requires requires { exp(q.number()); } || requires { std::exp(q.number()); } requires requires { exp(q.number()); } || requires { std::exp(q.number()); }
{ {
using std::exp; using std::exp;
return quantity_cast<Q::unit>(exp(quantity_cast<one>(q).number()) * dimensionless[one]); return value_cast<Q::unit>(exp(value_cast<one>(q).number()) * dimensionless[one]);
} }
/** /**
@@ -157,7 +158,7 @@ template<Unit auto To, auto R, typename Rep>
requires((!treat_as_floating_point<Rep>) || requires { floor(q.number()); } || requires((!treat_as_floating_point<Rep>) || requires { floor(q.number()); } ||
requires { std::floor(q.number()); }) && requires { std::floor(q.number()); }) &&
(To == get_unit(R) || requires { (To == get_unit(R) || requires {
::mp_units::quantity_cast<To>(q); ::mp_units::value_cast<To>(q);
quantity<reference<get_quantity_spec(R), To>{}, Rep>::one(); quantity<reference<get_quantity_spec(R), To>{}, Rep>::one();
}) })
{ {
@@ -173,13 +174,13 @@ template<Unit auto To, auto R, typename Rep>
return quantity<reference<get_quantity_spec(R), To>{}, Rep>(floor(q.number())); return quantity<reference<get_quantity_spec(R), To>{}, Rep>(floor(q.number()));
} else { } else {
return handle_signed_results( return handle_signed_results(
quantity<reference<get_quantity_spec(R), To>{}, Rep>(floor(quantity_cast<To>(q).number()))); quantity<reference<get_quantity_spec(R), To>{}, Rep>(floor(value_cast<To>(q).number())));
} }
} else { } else {
if constexpr (To == get_unit(R)) { if constexpr (To == get_unit(R)) {
return quantity_cast<To>(q); return value_cast<To>(q);
} else { } else {
return handle_signed_results(quantity_cast<To>(q)); return handle_signed_results(value_cast<To>(q));
} }
} }
} }
@@ -194,7 +195,7 @@ template<Unit auto To, auto R, typename Rep>
[[nodiscard]] constexpr quantity<reference<get_quantity_spec(R), To>{}, Rep> ceil(const quantity<R, Rep>& q) noexcept [[nodiscard]] constexpr quantity<reference<get_quantity_spec(R), To>{}, Rep> ceil(const quantity<R, Rep>& q) noexcept
requires((!treat_as_floating_point<Rep>) || requires { ceil(q.number()); } || requires { std::ceil(q.number()); }) && requires((!treat_as_floating_point<Rep>) || requires { ceil(q.number()); } || requires { std::ceil(q.number()); }) &&
(To == get_unit(R) || requires { (To == get_unit(R) || requires {
::mp_units::quantity_cast<To>(q); ::mp_units::value_cast<To>(q);
quantity<reference<get_quantity_spec(R), To>{}, Rep>::one(); quantity<reference<get_quantity_spec(R), To>{}, Rep>::one();
}) })
{ {
@@ -210,13 +211,13 @@ template<Unit auto To, auto R, typename Rep>
return quantity<reference<get_quantity_spec(R), To>{}, Rep>(ceil(q.number())); return quantity<reference<get_quantity_spec(R), To>{}, Rep>(ceil(q.number()));
} else { } else {
return handle_signed_results( return handle_signed_results(
quantity<reference<get_quantity_spec(R), To>{}, Rep>(ceil(quantity_cast<To>(q).number()))); quantity<reference<get_quantity_spec(R), To>{}, Rep>(ceil(value_cast<To>(q).number())));
} }
} else { } else {
if constexpr (To == get_unit(R)) { if constexpr (To == get_unit(R)) {
return quantity_cast<To>(q); return value_cast<To>(q);
} else { } else {
return handle_signed_results(quantity_cast<To>(q)); return handle_signed_results(value_cast<To>(q));
} }
} }
} }
@@ -243,7 +244,7 @@ template<Unit auto To, auto R, typename Rep>
using std::round; using std::round;
return quantity<reference<get_quantity_spec(R), To>{}, Rep>(round(q.number())); return quantity<reference<get_quantity_spec(R), To>{}, Rep>(round(q.number()));
} else { } else {
return quantity_cast<To>(q); return value_cast<To>(q);
} }
} else { } else {
const auto res_low = mp_units::floor<To>(q); const auto res_low = mp_units::floor<To>(q);
@@ -268,15 +269,15 @@ template<Unit auto To, auto R, typename Rep>
* without undue overflow or underflow at intermediate stages of the computation * without undue overflow or underflow at intermediate stages of the computation
*/ */
template<Quantity Q1, Quantity Q2> template<Quantity Q1, Quantity Q2>
[[nodiscard]] inline QuantityOf<common_reference(Q1::reference, Q2::reference)> auto hypot(const Q1& x, [[nodiscard]] inline QuantityOf<common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec)> auto hypot(
const Q2& y) noexcept const Q1& x, const Q2& y) noexcept
requires requires { common_reference(Q1::reference, Q2::reference); } && requires requires { common_reference(Q1::reference, Q2::reference); } &&
( (
requires { hypot(x.number(), y.number()); } || requires { std::hypot(x.number(), y.number()); }) requires { hypot(x.number(), y.number()); } || requires { std::hypot(x.number(), y.number()); })
{ {
using std::hypot; using std::hypot;
using type = quantity<common_reference(Q1::reference, Q2::reference), decltype(hypot(x.number(), y.number()))>; using type = quantity<common_reference(Q1::reference, Q2::reference), decltype(hypot(x.number(), y.number()))>;
return type{hypot(type{x}.number(), type{y}.number())}; return hypot(type{x}.number(), type{y}.number()) * type::reference;
} }
/** /**
@@ -284,8 +285,8 @@ template<Quantity Q1, Quantity Q2>
* without undue overflow or underflow at intermediate stages of the computation * without undue overflow or underflow at intermediate stages of the computation
*/ */
template<Quantity Q1, Quantity Q2, Quantity Q3> template<Quantity Q1, Quantity Q2, Quantity Q3>
[[nodiscard]] inline QuantityOf<common_reference(Q1::reference, Q2::reference, Q3::reference)> auto hypot( [[nodiscard]] inline QuantityOf<common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec, Q3::quantity_spec)> auto
const Q1& x, const Q2& y, const Q3& z) noexcept hypot(const Q1& x, const Q2& y, const Q3& z) noexcept
requires requires { common_reference(Q1::reference, Q2::reference, Q3::reference); } && requires requires { common_reference(Q1::reference, Q2::reference, Q3::reference); } &&
( (
requires { hypot(x.number(), y.number(), z.number()); } || requires { hypot(x.number(), y.number(), z.number()); } ||
@@ -294,32 +295,32 @@ template<Quantity Q1, Quantity Q2, Quantity Q3>
using std::hypot; using std::hypot;
using type = quantity<common_reference(Q1::reference, Q2::reference, Q3::reference), using type = quantity<common_reference(Q1::reference, Q2::reference, Q3::reference),
decltype(hypot(x.number(), y.number(), z.number()))>; decltype(hypot(x.number(), y.number(), z.number()))>;
return type{hypot(type{x}.number(), type{y}.number(), type{z}.number())}; return hypot(type{x}.number(), type{y}.number(), type{z}.number()) * type::reference;
} }
namespace isq { namespace isq {
template<WeakQuantityOf<angular_measure> Q> template<QuantityOf<angular_measure> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<dimensionless[one]> auto sin(const Q& q) noexcept [[nodiscard]] inline QuantityOf<dimensionless> auto sin(const Q& q) noexcept
requires requires { sin(q.number()); } || requires { std::sin(q.number()); } requires requires { sin(q.number()); } || requires { std::sin(q.number()); }
{ {
using std::sin; using std::sin;
return quantity{sin(q[si::radian].number())}; return quantity{sin(q[si::radian].number())};
} }
template<WeakQuantityOf<angular_measure> Q> template<QuantityOf<angular_measure> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<dimensionless[one]> auto cos(const Q& q) noexcept [[nodiscard]] inline QuantityOf<dimensionless> auto cos(const Q& q) noexcept
requires requires { cos(q.number()); } || requires { std::cos(q.number()); } requires requires { cos(q.number()); } || requires { std::cos(q.number()); }
{ {
using std::cos; using std::cos;
return quantity{cos(q[si::radian].number())}; return quantity{cos(q[si::radian].number())};
} }
template<WeakQuantityOf<angular_measure> Q> template<QuantityOf<angular_measure> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<dimensionless[one]> auto tan(const Q& q) noexcept [[nodiscard]] inline QuantityOf<dimensionless> auto tan(const Q& q) noexcept
requires requires { tan(q.number()); } || requires { std::tan(q.number()); } requires requires { tan(q.number()); } || requires { std::tan(q.number()); }
{ {
using std::tan; using std::tan;
@@ -328,88 +329,88 @@ template<WeakQuantityOf<angular_measure> Q>
template<QuantityOf<dimension_one> Q> template<QuantityOf<dimension_one> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<angular_measure[si::radian]> auto asin(const Q& q) noexcept [[nodiscard]] inline QuantityOf<angular_measure> auto asin(const Q& q) noexcept
requires requires { asin(q.number()); } || requires { std::asin(q.number()); } requires requires { asin(q.number()); } || requires { std::asin(q.number()); }
{ {
using std::asin; using std::asin;
return asin(quantity_cast<one>(q).number()) * angular_measure[si::radian]; return asin(value_cast<one>(q).number()) * angular_measure[si::radian];
} }
template<QuantityOf<dimension_one> Q> template<QuantityOf<dimension_one> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<angular_measure[si::radian]> auto acos(const Q& q) noexcept [[nodiscard]] inline QuantityOf<angular_measure> auto acos(const Q& q) noexcept
requires requires { acos(q.number()); } || requires { std::acos(q.number()); } requires requires { acos(q.number()); } || requires { std::acos(q.number()); }
{ {
using std::acos; using std::acos;
return acos(quantity_cast<one>(q).number()) * angular_measure[si::radian]; return acos(value_cast<one>(q).number()) * angular_measure[si::radian];
} }
template<QuantityOf<dimension_one> Q> template<QuantityOf<dimension_one> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<angular_measure[si::radian]> auto atan(const Q& q) noexcept [[nodiscard]] inline QuantityOf<angular_measure> auto atan(const Q& q) noexcept
requires requires { atan(q.number()); } || requires { std::atan(q.number()); } requires requires { atan(q.number()); } || requires { std::atan(q.number()); }
{ {
using std::atan; using std::atan;
return atan(quantity_cast<one>(q).number()) * angular_measure[si::radian]; return atan(value_cast<one>(q).number()) * angular_measure[si::radian];
} }
} // namespace isq } // namespace isq
namespace angular { namespace angular {
// TODO cannot use `WeakQuantityOf<angle>` as it is not interconvertible with `isq_angle::angular_measure` // TODO cannot use `QuantityOf<angle>` as it is not interconvertible with `isq_angle::angular_measure`
template<QuantityOf<dim_angle> Q> template<QuantityOf<dim_angle> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<dimensionless[one]> auto sin(const Q& q) noexcept [[nodiscard]] inline QuantityOf<dimensionless> auto sin(const Q& q) noexcept
requires requires { sin(q.number()); } || requires { std::sin(q.number()); } requires requires { sin(q.number()); } || requires { std::sin(q.number()); }
{ {
using std::sin; using std::sin;
return quantity{sin(q[radian].number())}; return sin(q[radian].number()) * one;
} }
template<QuantityOf<dim_angle> Q> template<QuantityOf<dim_angle> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<dimensionless[one]> auto cos(const Q& q) noexcept [[nodiscard]] inline QuantityOf<dimensionless> auto cos(const Q& q) noexcept
requires requires { cos(q.number()); } || requires { std::cos(q.number()); } requires requires { cos(q.number()); } || requires { std::cos(q.number()); }
{ {
using std::cos; using std::cos;
return quantity{cos(q[radian].number())}; return cos(q[radian].number()) * one;
} }
template<QuantityOf<dim_angle> Q> template<QuantityOf<dim_angle> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<dimensionless[one]> auto tan(const Q& q) noexcept [[nodiscard]] inline QuantityOf<dimensionless> auto tan(const Q& q) noexcept
requires requires { tan(q.number()); } || requires { std::tan(q.number()); } requires requires { tan(q.number()); } || requires { std::tan(q.number()); }
{ {
using std::tan; using std::tan;
return quantity{tan(q[radian].number())}; return tan(q[radian].number()) * one;
} }
template<QuantityOf<dimension_one> Q> template<QuantityOf<dimension_one> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<angle[radian]> auto asin(const Q& q) noexcept [[nodiscard]] inline QuantityOf<angle> auto asin(const Q& q) noexcept
requires requires { asin(q.number()); } || requires { std::asin(q.number()); } requires requires { asin(q.number()); } || requires { std::asin(q.number()); }
{ {
using std::asin; using std::asin;
return asin(quantity_cast<one>(q).number()) * angle[radian]; return asin(value_cast<one>(q).number()) * angle[radian];
} }
template<QuantityOf<dimension_one> Q> template<QuantityOf<dimension_one> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<angle[radian]> auto acos(const Q& q) noexcept [[nodiscard]] inline QuantityOf<angle> auto acos(const Q& q) noexcept
requires requires { acos(q.number()); } || requires { std::acos(q.number()); } requires requires { acos(q.number()); } || requires { std::acos(q.number()); }
{ {
using std::acos; using std::acos;
return acos(quantity_cast<one>(q).number()) * angle[radian]; return acos(value_cast<one>(q).number()) * angle[radian];
} }
template<QuantityOf<dimension_one> Q> template<QuantityOf<dimension_one> Q>
requires treat_as_floating_point<typename Q::rep> requires treat_as_floating_point<typename Q::rep>
[[nodiscard]] inline QuantityOf<angle[radian]> auto atan(const Q& q) noexcept [[nodiscard]] inline QuantityOf<angle> auto atan(const Q& q) noexcept
requires requires { atan(q.number()); } || requires { std::atan(q.number()); } requires requires { atan(q.number()); } || requires { std::atan(q.number()); }
{ {
using std::atan; using std::atan;
return atan(quantity_cast<one>(q).number()) * angle[radian]; return atan(value_cast<one>(q).number()) * angle[radian];
} }
} // namespace angular } // namespace angular