fix: common_unit handling fixed for some corner cases

This commit is contained in:
Mateusz Pusz
2024-10-05 17:52:52 +02:00
parent 07e4e795c1
commit 569f27af8b
7 changed files with 58 additions and 12 deletions

View File

@@ -214,6 +214,7 @@ static_assert(UnitOf<struct si::hertz, inverse(isq::time)>);
static_assert(UnitOf<struct one, dimensionless>);
static_assert(UnitOf<struct percent, dimensionless>);
static_assert(UnitOf<struct si::radian, isq::angular_measure>);
static_assert(UnitOf<struct si::degree, isq::angular_measure>);
static_assert(UnitOf<struct one, isq::angular_measure>);
static_assert(UnitOf<struct percent, isq::angular_measure>);
static_assert(!UnitOf<struct si::radian, dimensionless>);
@@ -247,9 +248,15 @@ static_assert(ReferenceOf<decltype(dimensionless[one]), dimensionless>);
static_assert(ReferenceOf<decltype(isq::rotation[one]), isq::rotation>);
static_assert(ReferenceOf<decltype(isq::rotation[one]), dimensionless>);
static_assert(ReferenceOf<struct si::radian, isq::angular_measure>);
static_assert(ReferenceOf<struct si::degree, isq::angular_measure>);
static_assert(ReferenceOf<decltype(get_common_unit(si::degree, si::radian)), isq::angular_measure>);
static_assert(!ReferenceOf<struct si::radian, dimensionless>);
static_assert(!ReferenceOf<struct si::degree, dimensionless>);
static_assert(!ReferenceOf<decltype(get_common_unit(si::degree, si::radian)), dimensionless>);
static_assert(ReferenceOf<decltype(isq::angular_measure[si::radian]), isq::angular_measure>);
static_assert(ReferenceOf<decltype(isq::angular_measure[si::degree]), isq::angular_measure>);
static_assert(!ReferenceOf<decltype(isq::angular_measure[si::radian]), dimensionless>);
static_assert(!ReferenceOf<decltype(isq::angular_measure[si::degree]), dimensionless>);
static_assert(ReferenceOf<struct one, isq::rotation>);
static_assert(ReferenceOf<struct one, isq::angular_measure>);
static_assert(!ReferenceOf<decltype(dimensionless[one]), isq::rotation>);

View File

@@ -273,6 +273,10 @@ static_assert(quantity<isq::length[m], int>(2000 * m).force_in(km).numerical_val
static_assert((15. * m).in(nm).numerical_value_in(m) == 15.);
static_assert((15'000. * nm).in(m).numerical_value_in(nm) == 15'000.);
// check if unit conversion works - don't bother about the actual result
static_assert((1. * rad + 1. * deg).in(rad) != 0 * rad);
static_assert((1. * rad + 1. * deg).in(deg) != 0 * deg);
#if MP_UNITS_HOSTED
using namespace std::complex_literals;
static_assert(((2. + 1i) * V).in(mV).numerical_value_in(mV) == 2000. + 1000i);
@@ -788,6 +792,12 @@ consteval bool invalid_arithmetic(Ts... ts)
static_assert(invalid_arithmetic(5 * isq::activity[Bq], 5 * isq::frequency[Hz]));
static_assert(invalid_arithmetic(5 * isq::activity[Bq], 10 / (2 * isq::time[s]), 5 * isq::frequency[Hz]));
// irrational conversion factors require floating point representation
static_assert(invalid_arithmetic(1 * rad, 1 * deg));
static_assert(is_of_type<1. * rad + 1 * deg, quantity<common_unit<struct si::degree, struct si::radian>{}, double>>);
static_assert(is_of_type<1 * rad + 1. * deg, quantity<common_unit<struct si::degree, struct si::radian>{}, double>>);
static_assert(is_of_type<1. * rad + 1. * deg, quantity<common_unit<struct si::degree, struct si::radian>{}, double>>);
// Physical constants
static_assert(1 * si::si2019::speed_of_light_in_vacuum + 10 * isq::speed[m / s] == 299'792'468 * isq::speed[m / s]);

View File

@@ -20,6 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <mp-units/systems/angular.h>
#include <mp-units/systems/iau.h>
#include <mp-units/systems/iec.h>
#include <mp-units/systems/international.h>
@@ -209,6 +210,10 @@ static_assert(unit_symbol(get_common_unit(kilo<metre> / hour, metre / second) /
"EQUIV{[1/5 km/h], [1/18 m/s]}/s");
static_assert(unit_symbol(get_common_unit(kilo<metre> / hour, metre / second) * second) ==
"EQUIV{[1/5 km/h], [1/18 m/s]} s");
static_assert(unit_symbol(get_common_unit(radian, degree)) == "EQUIV{[1/𝜋°], [1/180 rad]}");
static_assert(unit_symbol(get_common_unit(angular::radian, angular::revolution)) == "EQUIV{rad, [2⁻¹ 𝜋⁻¹ rev]}");
static_assert(unit_symbol<usf{.solidus = always}>(get_common_unit(angular::radian, angular::revolution)) ==
"EQUIV{rad, [1/(2 𝜋) rev]}");
// derived units
static_assert(unit_symbol(one) == ""); // NOLINT(readability-container-size-empty)

View File

@@ -69,6 +69,7 @@ inline constexpr struct nu_second_ final : named_unit<"s"> {} nu_second;
// derived named units
inline constexpr struct radian_ final : named_unit<"rad", metre / metre> {} radian;
inline constexpr struct revolution_ final : named_unit<"rev", mag<2> * mag<pi> * radian> {} revolution;
inline constexpr struct steradian_ final : named_unit<"sr", square(metre) / square(metre)> {} steradian;
inline constexpr struct hertz_ final : named_unit<"Hz", inverse(second)> {} hertz;
inline constexpr struct becquerel_ final : named_unit<"Bq", inverse(second)> {} becquerel;
@@ -539,6 +540,9 @@ static_assert(is_of_type<get_common_unit(mile, yard), yard_>);
static_assert(
is_of_type<get_common_unit(speed_of_light_in_vacuum, metre / second), derived_unit<metre_, per<second_>>>);
static_assert(is_of_type<get_common_unit(radian, revolution), common_unit<radian_, revolution_>>);
static_assert(is_of_type<get_common_unit(radian, degree), common_unit<degree_, radian_>>);
// those should return instantiations of the `common_unit` class template
static_assert(is_of_type<get_common_unit(kilometre, mile), common_unit<kilo_<metre_>, mile_>>);
static_assert(is_of_type<get_common_unit(mile, kilometre), common_unit<kilo_<metre_>, mile_>>);