feat: force_numerical_value_in(U) added

This commit is contained in:
Mateusz Pusz
2023-09-12 16:33:02 +02:00
parent 40c809091d
commit 2b2f62d038
4 changed files with 27 additions and 20 deletions

View File

@@ -33,7 +33,7 @@ template<mp_units::Quantity Target, mp_units::Quantity Source>
requires std::constructible_from<Target, Source> requires std::constructible_from<Target, Source>
inline constexpr double conversion_factor(Target, Source) inline constexpr double conversion_factor(Target, Source)
{ {
return mp_units::value_cast<Target::unit>(1. * Source::reference).numerical_value_ref_in(Target::unit); return (1. * Source::reference).force_numerical_value_in(Target::unit);
} }
} // namespace } // namespace

View File

@@ -183,6 +183,13 @@ public:
return (*this).in(U{}).numerical_value_ref_in(U{}); return (*this).in(U{}).numerical_value_ref_in(U{});
} }
template<Unit U>
requires requires(quantity q) { value_cast<U{}>(q); }
[[nodiscard]] constexpr rep force_numerical_value_in(U) const noexcept
{
return value_cast<U{}>(*this).numerical_value_in(U{});
}
template<Unit U> template<Unit U>
requires detail::QuantityConvertibleTo<quantity, quantity<quantity_spec[U{}], Rep>> requires detail::QuantityConvertibleTo<quantity, quantity<quantity_spec[U{}], Rep>>
[[nodiscard]] constexpr quantity<quantity_spec[U{}], Rep> in(U) const [[nodiscard]] constexpr quantity<quantity_spec[U{}], Rep> in(U) const

View File

@@ -116,8 +116,8 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
requires { std::exp(q.numerical_value_ref_in(q.unit)); } requires { std::exp(q.numerical_value_ref_in(q.unit)); }
{ {
using std::exp; using std::exp;
return value_cast<get_unit(R)>(make_quantity<detail::clone_reference_with<one>(R)>( return value_cast<get_unit(R)>(
static_cast<Rep>(exp(value_cast<one>(q).numerical_value_ref_in(q.unit))))); make_quantity<detail::clone_reference_with<one>(R)>(static_cast<Rep>(exp(q.force_numerical_value_in(q.unit)))));
} }
/** /**
@@ -178,8 +178,8 @@ template<Unit auto To, auto R, typename Rep>
return make_quantity<detail::clone_reference_with<To>(R)>( return make_quantity<detail::clone_reference_with<To>(R)>(
static_cast<Rep>(floor(q.numerical_value_ref_in(q.unit)))); static_cast<Rep>(floor(q.numerical_value_ref_in(q.unit))));
} else { } else {
return handle_signed_results(make_quantity<detail::clone_reference_with<To>(R)>( return handle_signed_results(
static_cast<Rep>(floor(value_cast<To>(q).numerical_value_ref_in(To))))); make_quantity<detail::clone_reference_with<To>(R)>(static_cast<Rep>(floor(q.force_numerical_value_in(To)))));
} }
} else { } else {
if constexpr (To == get_unit(R)) { if constexpr (To == get_unit(R)) {
@@ -218,8 +218,8 @@ template<Unit auto To, auto R, typename Rep>
return make_quantity<detail::clone_reference_with<To>(R)>( return make_quantity<detail::clone_reference_with<To>(R)>(
static_cast<Rep>(ceil(q.numerical_value_ref_in(q.unit)))); static_cast<Rep>(ceil(q.numerical_value_ref_in(q.unit))));
} else { } else {
return handle_signed_results(make_quantity<detail::clone_reference_with<To>(R)>( return handle_signed_results(
static_cast<Rep>(ceil(value_cast<To>(q).numerical_value_ref_in(To))))); make_quantity<detail::clone_reference_with<To>(R)>(static_cast<Rep>(ceil(q.force_numerical_value_in(To)))));
} }
} else { } else {
if constexpr (To == get_unit(R)) { if constexpr (To == get_unit(R)) {
@@ -327,7 +327,7 @@ template<ReferenceOf<angular_measure> auto R, typename Rep>
using std::sin; using std::sin;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(sin(value_cast<si::radian>(q).numerical_value_in(si::radian))); using rep = decltype(sin(q.force_numerical_value_in(si::radian)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<one>(sin(value_cast<rep>(q).numerical_value_in(si::radian))); return make_quantity<one>(sin(value_cast<rep>(q).numerical_value_in(si::radian)));
} else } else
@@ -342,7 +342,7 @@ template<ReferenceOf<angular_measure> auto R, typename Rep>
using std::cos; using std::cos;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(cos(value_cast<si::radian>(q).numerical_value_in(si::radian))); using rep = decltype(cos(q.force_numerical_value_in(si::radian)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<one>(cos(value_cast<rep>(q).numerical_value_in(si::radian))); return make_quantity<one>(cos(value_cast<rep>(q).numerical_value_in(si::radian)));
} else } else
@@ -357,7 +357,7 @@ template<ReferenceOf<angular_measure> auto R, typename Rep>
using std::tan; using std::tan;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(tan(value_cast<si::radian>(q).numerical_value_in(si::radian))); using rep = decltype(tan(q.force_numerical_value_in(si::radian)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<one>(tan(value_cast<rep>(q).numerical_value_in(si::radian))); return make_quantity<one>(tan(value_cast<rep>(q).numerical_value_in(si::radian)));
} else } else
@@ -372,7 +372,7 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
using std::asin; using std::asin;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(asin(value_cast<one>(q).numerical_value_in(one))); using rep = decltype(asin(q.force_numerical_value_in(one)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<si::radian>(asin(value_cast<rep>(q).numerical_value_in(one))); return make_quantity<si::radian>(asin(value_cast<rep>(q).numerical_value_in(one)));
} else } else
@@ -387,7 +387,7 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
using std::acos; using std::acos;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(acos(value_cast<one>(q).numerical_value())); using rep = decltype(acos(q.force_numerical_value_in(one)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<si::radian>(acos(value_cast<rep>(q).numerical_value_in(one))); return make_quantity<si::radian>(acos(value_cast<rep>(q).numerical_value_in(one)));
} else } else
@@ -402,7 +402,7 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
using std::atan; using std::atan;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(atan(value_cast<one>(q).numerical_value_in(one))); using rep = decltype(atan(q.force_numerical_value_in(one)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<si::radian>(atan(value_cast<rep>(q).numerical_value_in(one))); return make_quantity<si::radian>(atan(value_cast<rep>(q).numerical_value_in(one)));
} else } else
@@ -421,7 +421,7 @@ template<ReferenceOf<angle> auto R, typename Rep>
using std::sin; using std::sin;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(sin(value_cast<radian>(q).numerical_value_in(radian))); using rep = decltype(sin(q.force_numerical_value_in(radian)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<one>(sin(value_cast<rep>(q).numerical_value_in(radian))); return make_quantity<one>(sin(value_cast<rep>(q).numerical_value_in(radian)));
} else } else
@@ -436,7 +436,7 @@ template<ReferenceOf<angle> auto R, typename Rep>
using std::cos; using std::cos;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(cos(value_cast<radian>(q).numerical_value_in(radian))); using rep = decltype(cos(q.force_numerical_value_in(radian)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<one>(cos(value_cast<rep>(q).numerical_value_in(radian))); return make_quantity<one>(cos(value_cast<rep>(q).numerical_value_in(radian)));
} else } else
@@ -451,7 +451,7 @@ template<ReferenceOf<angle> auto R, typename Rep>
using std::tan; using std::tan;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(tan(value_cast<radian>(q).numerical_value_in(radian))); using rep = decltype(tan(q.force_numerical_value_in(radian)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<one>(tan(value_cast<rep>(q).numerical_value_in(radian))); return make_quantity<one>(tan(value_cast<rep>(q).numerical_value_in(radian)));
} else } else
@@ -466,7 +466,7 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
using std::asin; using std::asin;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(asin(value_cast<one>(q).numerical_value_in(one))); using rep = decltype(asin(q.force_numerical_value_in(one)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<radian>(asin(value_cast<rep>(q).numerical_value_in(one))); return make_quantity<radian>(asin(value_cast<rep>(q).numerical_value_in(one)));
} else } else
@@ -481,7 +481,7 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
using std::acos; using std::acos;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(acos(value_cast<one>(q).numerical_value_in(one))); using rep = decltype(acos(q.force_numerical_value_in(one)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<radian>(acos(value_cast<rep>(q).numerical_value_in(one))); return make_quantity<radian>(acos(value_cast<rep>(q).numerical_value_in(one)));
} else } else
@@ -496,7 +496,7 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
using std::atan; using std::atan;
if constexpr (!treat_as_floating_point<Rep>) { if constexpr (!treat_as_floating_point<Rep>) {
// check what is the return type when called with the integral value // check what is the return type when called with the integral value
using rep = decltype(atan(value_cast<one>(q).numerical_value_in(one))); using rep = decltype(atan(q.force_numerical_value_in(one)));
// use this type ahead of calling the function to prevent narrowing if a unit conversion is needed // use this type ahead of calling the function to prevent narrowing if a unit conversion is needed
return make_quantity<radian>(atan(value_cast<rep>(q).numerical_value_in(one))); return make_quantity<radian>(atan(value_cast<rep>(q).numerical_value_in(one)));
} else } else

View File

@@ -93,7 +93,7 @@ TEST_CASE("vector quantity", "[la]")
SECTION("truncating") SECTION("truncating")
{ {
const auto v = vector<int>{1001, 1002, 1003} * isq::position_vector[m]; const auto v = vector<int>{1001, 1002, 1003} * isq::position_vector[m];
CHECK(value_cast<km>(v).numerical_value_ref_in(km) == vector<int>{1, 1, 1}); CHECK(v.force_numerical_value_in(km) == vector<int>{1, 1, 1});
} }
} }