feat: quantity_spec conversions improved

This commit is contained in:
Mateusz Pusz
2024-12-28 14:02:03 +01:00
parent b685521a18
commit 06cbfae3b3
26 changed files with 1013 additions and 1147 deletions

View File

@ -98,6 +98,32 @@ static_assert(QuantitySpec<MP_UNITS_NONCONST_TYPE(speed)>);
static_assert(!QuantitySpec<struct isq::dim_length>);
static_assert(!QuantitySpec<int>);
// QuantitySpecOf
static_assert(QuantitySpecOf<struct isq::length, isq::length>);
static_assert(QuantitySpecOf<struct isq::height, isq::length>);
static_assert(!QuantitySpecOf<struct isq::length, isq::height>);
static_assert(QuantitySpecOf<struct isq::displacement, isq::length>);
static_assert(!QuantitySpecOf<struct isq::length, isq::displacement>);
static_assert(QuantitySpecOf<struct isq::thickness, isq::width>);
static_assert(!QuantitySpecOf<struct isq::width, isq::thickness>);
static_assert(QuantitySpecOf<kind_of_<struct isq::length>, isq::height>);
static_assert(QuantitySpecOf<kind_of_<struct isq::length>, isq::displacement>);
static_assert(!QuantitySpecOf<struct isq::angular_measure, dimensionless>);
static_assert(!QuantitySpecOf<struct isq::angular_measure, kind_of<dimensionless>>);
static_assert(!QuantitySpecOf<kind_of_<struct isq::angular_measure>, dimensionless>);
static_assert(!QuantitySpecOf<kind_of_<struct isq::angular_measure>, kind_of<dimensionless>>);
static_assert(!QuantitySpecOf<struct dimensionless, isq::angular_measure>);
static_assert(!QuantitySpecOf<struct dimensionless, kind_of<isq::angular_measure>>);
static_assert(QuantitySpecOf<kind_of_<struct dimensionless>, isq::angular_measure>);
static_assert(QuantitySpecOf<kind_of_<struct dimensionless>, kind_of<isq::angular_measure>>);
static_assert(!QuantitySpecOf<struct isq::solid_angular_measure, isq::angular_measure>);
static_assert(!QuantitySpecOf<struct isq::solid_angular_measure, kind_of<isq::angular_measure>>);
static_assert(!QuantitySpecOf<kind_of_<struct isq::solid_angular_measure>, isq::angular_measure>);
static_assert(!QuantitySpecOf<kind_of_<struct isq::solid_angular_measure>, kind_of<isq::angular_measure>>);
// NamedQuantitySpec
static_assert(detail::NamedQuantitySpec<struct isq::length>);
static_assert(detail::NamedQuantitySpec<struct isq::radius>);
@ -134,9 +160,6 @@ static_assert(!detail::QuantityKindSpec<MP_UNITS_NONCONST_TYPE(speed)>);
static_assert(!detail::QuantityKindSpec<struct isq::dim_length>);
static_assert(!detail::QuantityKindSpec<int>);
// QuantitySpecOf
// TODO add tests
// Unit
static_assert(Unit<struct si::metre>);
static_assert(Unit<MP_UNITS_NONCONST_TYPE(si::kilogram)>);
@ -229,6 +252,8 @@ 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<MP_UNITS_NONCONST_TYPE(si::radian / si::second), isq::angular_velocity>);
static_assert(UnitOf<MP_UNITS_NONCONST_TYPE(one / si::second), isq::angular_velocity>);
static_assert(!UnitOf<struct si::radian, dimensionless>);
static_assert(!UnitOf<struct si::metre, isq::time>);
static_assert(!UnitOf<struct natural::electronvolt, isq::energy>);

View File

@ -1697,7 +1697,8 @@ static_assert(invalid_subtraction(zero_Bq + 5 * isq::activity[Bq], 5 * isq::freq
static_assert(invalid_subtraction(zero_Bq + 5 * isq::activity[Bq], zero_Hz + 5 * isq::frequency[Hz]));
static_assert(invalid_addition(zero_Bq + 5 * isq::activity[Bq], 10 / (2 * isq::time[s]), 5 * isq::frequency[Hz]));
static_assert(invalid_addition(5 * isq::activity[Bq], zero_Hz + 10 / (2 * isq::time[s]), 5 * isq::frequency[Hz]));
static_assert(invalid_addition(5 * isq::activity[Bq], zero_Hz + 10 / (2 * isq::period_duration[s]),
5 * isq::frequency[Hz]));
static_assert(invalid_addition(5 * isq::activity[Bq], 10 / (2 * isq::time[s]), zero_Hz + 5 * isq::frequency[Hz]));
static_assert(invalid_subtraction(zero_Bq + 5 * isq::activity[Bq], 10 / (2 * isq::time[s]), 5 * isq::frequency[Hz]));

View File

@ -40,6 +40,7 @@ using dim_one_ = struct dimension_one;
inline constexpr struct dim_length_ final : base_dimension<"L"> {} dim_length;
inline constexpr struct dim_mass_ final : base_dimension<"M"> {} dim_mass;
inline constexpr struct dim_time_ final : base_dimension<"T"> {} dim_time;
inline constexpr struct dim_electric_current_ final : base_dimension<"I"> {} dim_electric_current;
// quantities specification
QUANTITY_SPEC_(length, dim_length);
@ -48,6 +49,7 @@ QUANTITY_SPEC_(time, dim_time);
inline constexpr struct second_ final : named_unit<"s", kind_of<time>> {} second;
QUANTITY_SPEC_(horizontal_length, length);
QUANTITY_SPEC_(height, length);
QUANTITY_SPEC_(width, length);
QUANTITY_SPEC_(radius, width);
@ -65,12 +67,17 @@ QUANTITY_SPEC_(activity, inverse(time));
QUANTITY_SPEC_(area, pow<2>(length));
QUANTITY_SPEC_(volume, pow<3>(length));
QUANTITY_SPEC_(angular_measure, dimensionless, arc_length / radius, is_kind);
QUANTITY_SPEC_(special_angular_measure, angular_measure);
QUANTITY_SPEC_(rotational_displacement, angular_measure, path_length / radius);
QUANTITY_SPEC_(phase_angle, angular_measure);
QUANTITY_SPEC_(solid_angular_measure, dimensionless, area / pow<2>(radius), is_kind);
QUANTITY_SPEC_(dimensionless_rate, dimensionless / time);
QUANTITY_SPEC_(angular_measure_rate, angular_measure / time);
QUANTITY_SPEC_(solid_angular_measure_rate, solid_angular_measure / time);
QUANTITY_SPEC_(speed, length / time);
QUANTITY_SPEC_(velocity, speed, displacement / time);
QUANTITY_SPEC_(special_speed, speed);
QUANTITY_SPEC_(horizontal_speed, speed, horizontal_length / time);
QUANTITY_SPEC_(rate_of_climb, speed, height / time);
QUANTITY_SPEC_(special_rate_of_climb, rate_of_climb);
QUANTITY_SPEC_(acceleration, velocity / time);
@ -90,6 +97,18 @@ QUANTITY_SPEC_(mechanical_energy, energy);
QUANTITY_SPEC_(potential_energy, mechanical_energy);
QUANTITY_SPEC_(gravitational_potential_energy, potential_energy, mass * acceleration_of_free_fall * height);
QUANTITY_SPEC_(kinetic_energy, mechanical_energy, mass* pow<2>(speed));
QUANTITY_SPEC_(electric_current, dim_electric_current);
QUANTITY_SPEC_(electric_charge, electric_current* time);
QUANTITY_SPEC_(electric_field_strength, force / electric_charge); // vector
QUANTITY_SPEC_(electric_potential, electric_field_strength* length, quantity_character::scalar);
QUANTITY_SPEC_(voltage, electric_potential);
QUANTITY_SPEC_(electromagnetism_power, power, voltage* electric_current);
QUANTITY_SPEC_(electric_current_phasor, electric_current, quantity_character::complex);
QUANTITY_SPEC_(voltage_phasor, voltage, quantity_character::complex);
QUANTITY_SPEC_(active_power, power, inverse(period_duration) * (electromagnetism_power * time));
QUANTITY_SPEC_(complex_power, voltage_phasor* electric_current_phasor); // separate kind
QUANTITY_SPEC_(apparent_power, complex_power, quantity_character::scalar);
// clang-format on
// concepts verification
@ -416,6 +435,7 @@ static_assert(get_kind(energy) == kind_of<energy>);
static_assert(get_kind(potential_energy) == kind_of<energy>);
static_assert(get_kind(kinetic_energy) == kind_of<energy>);
static_assert(get_kind(pow<1, 2>(area)) == kind_of<pow<1, 2>(area)>);
static_assert(get_kind(dimensionless) == kind_of<dimensionless>);
static_assert(get_kind(angular_measure) == kind_of<angular_measure>);
static_assert(get_kind(phase_angle) == kind_of<angular_measure>);
static_assert(get_kind(rotational_displacement) == kind_of<angular_measure>);
@ -446,6 +466,8 @@ static_assert(!defines_equation(potential_energy));
static_assert(get_complexity(length) == 0);
static_assert(get_complexity(pow<4>(length)) == 0);
static_assert(get_complexity(dimensionless) == 0);
static_assert(get_complexity(angular_measure) == 1);
static_assert(get_complexity(solid_angular_measure) == 2);
static_assert(get_complexity(length / time) == 0);
static_assert(get_complexity(mass * length / time) == 0);
static_assert(get_complexity(frequency) == 1);
@ -453,9 +475,15 @@ static_assert(get_complexity(area) == 1);
static_assert(get_complexity(pow<2>(area)) == 1);
static_assert(get_complexity(volume) == 1);
static_assert(get_complexity(speed) == 1);
static_assert(get_complexity(special_speed) == 1);
static_assert(get_complexity(horizontal_speed) == 1);
static_assert(get_complexity(special_rate_of_climb) == 1);
static_assert(get_complexity(velocity) == 1);
static_assert(get_complexity(acceleration) == 2);
static_assert(get_complexity(force) == 3);
static_assert(get_complexity(dimensionless_rate) == 1);
static_assert(get_complexity(angular_measure_rate) == 2);
static_assert(get_complexity(solid_angular_measure_rate) == 3);
static_assert(get_complexity(acceleration * time) == 2);
static_assert(get_complexity(acceleration / time) == 2);
@ -470,21 +498,28 @@ static_assert(get_complexity(area / force) == 3);
static_assert(get_complexity(speed * area / frequency) == 1);
// explode
static_assert(explode<get_complexity(inverse(time))>(frequency).quantity == inverse(period_duration));
static_assert(explode<get_complexity(kind_of<length / time>)>(speed).quantity == length / time);
static_assert(explode<get_complexity(kind_of<length / time>)>(velocity).quantity == displacement / time);
static_assert(explode<get_complexity(dimensionless)>(angular_measure).quantity == arc_length / radius);
static_assert(explode<get_complexity(velocity)>(acceleration * time).quantity == velocity);
static_assert(explode<get_complexity(area)>(area).quantity == area);
static_assert(explode<get_complexity(area)>(volume / length).quantity == volume / length);
static_assert(explode<get_complexity(area)>(volume / height).quantity == volume / height);
static_assert(explode<get_complexity(area)>(pow<3>(length) / height).quantity == pow<3>(length) / height);
static_assert(explode<get_complexity(area)>(area * time / period_duration).quantity == area * time / period_duration);
static_assert(explode<get_complexity(area)>(pow<2>(length) * time / period_duration).quantity ==
pow<2>(length) * time / period_duration);
static_assert(explode(frequency).equation == inverse(period_duration));
static_assert(explode(speed).equation == length / time);
static_assert(explode(special_speed).equation == length / time);
static_assert(explode(horizontal_speed).equation == horizontal_length / time);
static_assert(explode(rate_of_climb).equation == height / time);
static_assert(explode(special_rate_of_climb).equation == height / time);
static_assert(explode(velocity).equation == displacement / time);
using enum specs_convertible_result;
static_assert(have_common_base(width, length));
static_assert(have_common_base(width, height));
static_assert(have_common_base(angular_measure, dimensionless));
static_assert(have_common_base(angular_measure, solid_angular_measure));
static_assert(convertible_common_base(width, length) == yes);
static_assert(convertible_common_base(length, width) == explicit_conversion);
static_assert(convertible_common_base(width, height) == cast);
static_assert(convertible_common_base(angular_measure, dimensionless) == explicit_conversion_beyond_kind);
static_assert(convertible_common_base(dimensionless, angular_measure) == explicit_conversion);
static_assert(convertible_common_base(angular_measure, solid_angular_measure) == no);
static_assert(are_ingredients_convertible(length / time, length / time) == yes);
static_assert(are_ingredients_convertible(mass * length / time, mass* length / time) == yes);
static_assert(are_ingredients_convertible(area / length, area / length) == yes);
@ -528,6 +563,7 @@ static_assert(convertible(height, width) == cast);
static_assert(convertible(potential_energy, kinetic_energy) == cast);
static_assert(convertible(kinetic_energy, potential_energy) == cast);
static_assert(convertible(rate_of_climb, velocity) == cast);
static_assert(convertible(rate_of_climb, horizontal_speed) == cast);
// converting to a different kind
static_assert(convertible(frequency, activity) == no);
@ -547,9 +583,12 @@ static_assert(convertible(special_rate_of_climb, speed) == yes);
static_assert(convertible(velocity, speed) == yes);
static_assert(convertible(potential_energy, energy) == yes);
static_assert(convertible(kinetic_energy, energy) == yes);
static_assert(convertible(angular_measure, dimensionless) == yes);
// upcasting beyond the hierarchy/kind
static_assert(convertible(angular_measure, dimensionless) == explicit_conversion_beyond_kind);
static_assert(convertible(angular_measure * time / period_duration, dimensionless) == explicit_conversion_beyond_kind);
// upcasting to the derived quantity
static_assert(convertible(frequency, inverse(time)) == yes);
static_assert(convertible(speed, length / time) == yes);
static_assert(convertible(speed, length / time) == yes);
@ -557,6 +596,8 @@ static_assert(convertible(velocity, length / time) == yes);
static_assert(convertible(rate_of_climb, length / time) == yes);
static_assert(convertible(rate_of_climb, height / time) == yes);
static_assert(convertible(gravitational_potential_energy, mass* acceleration* length) == yes);
static_assert(convertible(angular_measure, arc_length / radius) == yes);
static_assert(convertible(solid_angular_measure, area / pow<2>(radius)) == yes);
// downcasting same hierarchy branch
static_assert(convertible(length, width) == explicit_conversion);
@ -572,12 +613,6 @@ static_assert(convertible(energy, kinetic_energy) == explicit_conversion);
static_assert(convertible(dimensionless, rotation) == explicit_conversion);
static_assert(convertible(dimensionless, rotational_displacement) == explicit_conversion);
// downcasting to a different kind
static_assert(convertible(dimensionless, angular_measure) == yes);
static_assert(convertible(dimensionless, kind_of<angular_measure>) == yes);
static_assert(convertible(kind_of<dimensionless>, angular_measure) == yes);
static_assert(convertible(kind_of<dimensionless>, kind_of<angular_measure>) == yes);
// derived quantities to type
static_assert(convertible(inverse(frequency), time) == yes);
static_assert(convertible(inverse(period_duration), frequency) == yes);
@ -612,6 +647,8 @@ static_assert(convertible(pow<1, 2>(area), length) == yes);
static_assert(convertible(length, pow<1, 2>(area)) == yes);
static_assert(convertible(mass * acceleration_of_free_fall * height, gravitational_potential_energy) == yes);
static_assert(convertible(mass * pow<2>(length) / pow<2>(time), kinetic_energy) == yes);
static_assert(convertible(arc_length / radius, angular_measure) == yes);
static_assert(convertible(area / pow<2>(radius), solid_angular_measure) == yes);
// additional dimensionless remainder
static_assert(convertible(length / speed, time) == yes);
@ -624,6 +661,10 @@ static_assert(convertible(length / time, rate_of_climb) == explicit_conversion);
static_assert(convertible(acceleration / velocity, frequency) == explicit_conversion);
static_assert(convertible(force * length, torque) == explicit_conversion);
static_assert(convertible(mass * acceleration * length, gravitational_potential_energy) == explicit_conversion);
static_assert(convertible(length / radius, angular_measure) == explicit_conversion);
static_assert(convertible(length / length, angular_measure) == explicit_conversion);
static_assert(convertible(arc_length / length, angular_measure) == explicit_conversion);
static_assert(convertible(area / pow<2>(length), solid_angular_measure) == explicit_conversion);
// derived quantities to more specialized type
static_assert(convertible(force * position_vector, torque) == explicit_conversion);
@ -678,17 +719,25 @@ static_assert(convertible(height / period_duration, length / time) == yes);
static_assert(convertible(height / width, length / length) == yes);
static_assert(convertible(height * width, length* length) == yes);
static_assert(convertible(inverse(path_length * distance), inverse(pow<2>(path_length))) == yes);
static_assert(convertible(path_length * period_duration, length* time) == yes);
static_assert(convertible(volume * length, pow<2>(area)) == yes);
static_assert(convertible(pow<4>(length), pow<2>(area)) == yes);
static_assert(convertible(pow<2>(radius), pow<2>(length)) == yes);
static_assert(convertible(height * time / period_duration, length) == yes);
static_assert(convertible(angular_measure * time / period_duration, arc_length / radius) == yes);
static_assert(convertible(special_angular_measure * solid_angular_measure, angular_measure* solid_angular_measure) ==
yes);
// derived to more specialized derived
static_assert(convertible(length / time, height / period_duration) == explicit_conversion);
static_assert(convertible(length * length, height* width) == explicit_conversion);
static_assert(convertible(length * time, radius* period_duration) == explicit_conversion);
// derived to incompatible specialized derived
static_assert(convertible(height / time, distance / time) == cast);
static_assert(convertible(path_length * time, radius* period_duration) == cast);
// when more than one possible combination is present
// TODO revise that
@ -754,17 +803,18 @@ static_assert(convertible(energy, kind_of<energy>) == yes);
static_assert(convertible(potential_energy, kind_of<energy>) == yes);
static_assert(convertible(kinetic_energy, kind_of<energy>) == yes);
static_assert(convertible(rotation, kind_of<dimensionless>) == yes);
static_assert(convertible(angular_measure, kind_of<dimensionless>) == yes);
static_assert(convertible(rotational_displacement, kind_of<dimensionless>) == yes);
static_assert(convertible(angular_measure, kind_of<dimensionless>) == explicit_conversion_beyond_kind);
static_assert(convertible(rotational_displacement, kind_of<dimensionless>) == explicit_conversion_beyond_kind);
// converting derived type to a kind
static_assert(convertible(inverse(time), kind_of<frequency>) == yes);
static_assert(convertible(inverse(period_duration), kind_of<frequency>) == yes);
static_assert(convertible(inverse(time), kind_of<frequency>) == explicit_conversion);
static_assert(convertible(length / time, kind_of<speed>) == yes);
static_assert(convertible(length / pow<2>(time), kind_of<acceleration>) == yes);
static_assert(convertible(length / pow<2>(time), kind_of<acceleration>) == explicit_conversion);
// converting kind to a kind
static_assert(convertible(kind_of<dimensionless>, kind_of<angular_measure>) == yes);
static_assert(convertible(kind_of<angular_measure>, kind_of<dimensionless>) == yes);
static_assert(convertible(kind_of<angular_measure>, kind_of<dimensionless>) == explicit_conversion_beyond_kind);
// converting derived kind to a kind
static_assert(convertible(kind_of<inverse(time)>, kind_of<frequency>) == yes);
@ -788,9 +838,181 @@ static_assert(convertible(frequency * period_duration, dimensionless) == yes);
static_assert(convertible(frequency * time, dimensionless) == yes);
static_assert(convertible(length / length, dimensionless) == yes);
static_assert(convertible(length / width, dimensionless) == yes);
static_assert(convertible(active_power / apparent_power, dimensionless) == yes);
static_assert(convertible(efficiency, strain) == cast);
// nested kinds
static_assert(convertible(dimensionless, dimensionless) == yes);
static_assert(convertible(angular_measure, dimensionless) == explicit_conversion_beyond_kind);
static_assert(convertible(solid_angular_measure, dimensionless) == explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<dimensionless>, dimensionless) == yes);
static_assert(convertible(kind_of<angular_measure>, dimensionless) == explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<solid_angular_measure>, dimensionless) == explicit_conversion_beyond_kind);
static_assert(convertible(dimensionless, kind_of<dimensionless>) == yes);
static_assert(convertible(angular_measure, kind_of<dimensionless>) == explicit_conversion_beyond_kind);
static_assert(convertible(solid_angular_measure, kind_of<dimensionless>) == explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<dimensionless>, kind_of<dimensionless>) == yes);
static_assert(convertible(kind_of<angular_measure>, kind_of<dimensionless>) == explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<solid_angular_measure>, kind_of<dimensionless>) == explicit_conversion_beyond_kind);
static_assert(convertible(angular_measure, solid_angular_measure) == no);
static_assert(convertible(angular_measure, kind_of<solid_angular_measure>) == no);
static_assert(convertible(kind_of<angular_measure>, kind_of<solid_angular_measure>) == no);
static_assert(convertible(dimensionless, angular_measure) == explicit_conversion);
static_assert(convertible(dimensionless, solid_angular_measure) == explicit_conversion);
static_assert(convertible(dimensionless, kind_of<angular_measure>) == explicit_conversion);
static_assert(convertible(dimensionless, kind_of<solid_angular_measure>) == explicit_conversion);
static_assert(convertible(kind_of<dimensionless>, angular_measure) == yes);
static_assert(convertible(kind_of<dimensionless>, solid_angular_measure) == yes);
static_assert(convertible(kind_of<dimensionless>, kind_of<angular_measure>) == yes);
static_assert(convertible(kind_of<dimensionless>, kind_of<solid_angular_measure>) == yes);
// derived nested kinds
static_assert(convertible(dimensionless / time, dimensionless / time) == yes);
static_assert(convertible(angular_measure / time, dimensionless / time) == explicit_conversion_beyond_kind);
static_assert(convertible(solid_angular_measure / time, dimensionless / time) == explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<dimensionless / time>, dimensionless / time) == yes);
static_assert(convertible(kind_of<angular_measure / time>, dimensionless / time) == explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<solid_angular_measure / time>, dimensionless / time) ==
explicit_conversion_beyond_kind);
static_assert(convertible(dimensionless / time, kind_of<dimensionless / time>) == yes);
static_assert(convertible(angular_measure / time, kind_of<dimensionless / time>) == explicit_conversion_beyond_kind);
static_assert(convertible(solid_angular_measure / time, kind_of<dimensionless / time>) ==
explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<dimensionless / time>, kind_of<dimensionless / time>) == yes);
static_assert(convertible(kind_of<angular_measure / time>, kind_of<dimensionless / time>) ==
explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<solid_angular_measure / time>, kind_of<dimensionless / time>) ==
explicit_conversion_beyond_kind);
static_assert(convertible(angular_measure / time, solid_angular_measure / time) == no);
static_assert(convertible(angular_measure / time, kind_of<solid_angular_measure / time>) == no);
static_assert(convertible(kind_of<angular_measure / time>, kind_of<solid_angular_measure / time>) == no);
static_assert(convertible(dimensionless / time, angular_measure / time) == explicit_conversion);
static_assert(convertible(dimensionless / time, solid_angular_measure / time) == explicit_conversion);
static_assert(convertible(dimensionless / time, kind_of<angular_measure / time>) == explicit_conversion);
static_assert(convertible(dimensionless / time, kind_of<solid_angular_measure / time>) == explicit_conversion);
static_assert(convertible(kind_of<dimensionless / time>, angular_measure / time) == yes);
static_assert(convertible(kind_of<dimensionless / time>, solid_angular_measure / time) == yes);
static_assert(convertible(kind_of<dimensionless / time>, kind_of<angular_measure / time>) == yes);
static_assert(convertible(kind_of<dimensionless / time>, kind_of<solid_angular_measure / time>) == yes);
// named derived nested kinds
static_assert(convertible(dimensionless_rate, dimensionless_rate) == yes);
static_assert(convertible(angular_measure_rate, dimensionless_rate) == no);
static_assert(convertible(solid_angular_measure_rate, dimensionless_rate) == no);
static_assert(convertible(kind_of<dimensionless_rate>, dimensionless_rate) == yes);
static_assert(convertible(kind_of<angular_measure_rate>, dimensionless_rate) == no);
static_assert(convertible(kind_of<solid_angular_measure_rate>, dimensionless_rate) == no);
static_assert(convertible(dimensionless_rate, kind_of<dimensionless_rate>) == yes);
static_assert(convertible(angular_measure_rate, kind_of<dimensionless_rate>) == no);
static_assert(convertible(solid_angular_measure_rate, kind_of<dimensionless_rate>) == no);
static_assert(convertible(kind_of<dimensionless_rate>, kind_of<dimensionless_rate>) == yes);
static_assert(convertible(kind_of<angular_measure_rate>, kind_of<dimensionless_rate>) == no);
static_assert(convertible(kind_of<solid_angular_measure_rate>, kind_of<dimensionless_rate>) == no);
static_assert(convertible(angular_measure_rate, solid_angular_measure_rate) == no);
static_assert(convertible(angular_measure_rate, kind_of<solid_angular_measure_rate>) == no);
static_assert(convertible(kind_of<angular_measure_rate>, kind_of<solid_angular_measure_rate>) == no);
static_assert(convertible(dimensionless_rate, angular_measure_rate) == no);
static_assert(convertible(dimensionless_rate, solid_angular_measure_rate) == no);
static_assert(convertible(dimensionless_rate, kind_of<angular_measure_rate>) == no);
static_assert(convertible(dimensionless_rate, kind_of<solid_angular_measure_rate>) == no);
static_assert(convertible(kind_of<dimensionless_rate>, angular_measure_rate) == no);
static_assert(convertible(kind_of<dimensionless_rate>, solid_angular_measure_rate) == no);
static_assert(convertible(kind_of<dimensionless_rate>, kind_of<angular_measure_rate>) == no);
static_assert(convertible(kind_of<dimensionless_rate>, kind_of<solid_angular_measure_rate>) == no);
static_assert(convertible(dimensionless_rate, dimensionless / time) == yes);
static_assert(convertible(angular_measure_rate, dimensionless / time) == explicit_conversion_beyond_kind);
static_assert(convertible(solid_angular_measure_rate, dimensionless / time) == explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<dimensionless_rate>, dimensionless / time) == yes);
static_assert(convertible(kind_of<angular_measure_rate>, dimensionless / time) == explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<solid_angular_measure_rate>, dimensionless / time) ==
explicit_conversion_beyond_kind);
static_assert(convertible(dimensionless_rate, kind_of<dimensionless / time>) == yes);
static_assert(convertible(angular_measure_rate, kind_of<dimensionless / time>) == explicit_conversion_beyond_kind);
static_assert(convertible(solid_angular_measure_rate, kind_of<dimensionless / time>) ==
explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<dimensionless_rate>, kind_of<dimensionless / time>) == yes);
static_assert(convertible(kind_of<angular_measure_rate>, kind_of<dimensionless / time>) ==
explicit_conversion_beyond_kind);
static_assert(convertible(kind_of<solid_angular_measure_rate>, kind_of<dimensionless / time>) ==
explicit_conversion_beyond_kind);
static_assert(convertible(angular_measure_rate, solid_angular_measure / time) == no);
static_assert(convertible(angular_measure_rate, kind_of<solid_angular_measure / time>) == no);
static_assert(convertible(kind_of<angular_measure_rate>, kind_of<solid_angular_measure / time>) == no);
static_assert(convertible(dimensionless_rate, angular_measure / time) == explicit_conversion);
static_assert(convertible(dimensionless_rate, kind_of<angular_measure / time>) == explicit_conversion);
static_assert(convertible(dimensionless_rate, solid_angular_measure / time) == explicit_conversion);
static_assert(convertible(dimensionless_rate, kind_of<solid_angular_measure / time>) == explicit_conversion);
static_assert(convertible(kind_of<dimensionless_rate>, angular_measure / time) == yes);
static_assert(convertible(kind_of<dimensionless_rate>, solid_angular_measure / time) == yes);
static_assert(convertible(kind_of<dimensionless_rate>, kind_of<angular_measure / time>) == yes);
static_assert(convertible(kind_of<dimensionless_rate>, kind_of<solid_angular_measure / time>) == yes);
static_assert(convertible(dimensionless / time, dimensionless_rate) == yes);
static_assert(convertible(angular_measure / time, dimensionless_rate) == yes);
static_assert(convertible(solid_angular_measure / time, dimensionless_rate) == yes);
static_assert(convertible(kind_of<dimensionless / time>, dimensionless_rate) == yes);
static_assert(convertible(kind_of<angular_measure / time>, dimensionless_rate) == yes);
static_assert(convertible(kind_of<solid_angular_measure / time>, dimensionless_rate) == yes);
static_assert(convertible(dimensionless / time, kind_of<dimensionless_rate>) == yes);
static_assert(convertible(angular_measure / time, kind_of<dimensionless_rate>) == yes);
static_assert(convertible(solid_angular_measure / time, kind_of<dimensionless_rate>) == yes);
static_assert(convertible(kind_of<dimensionless / time>, kind_of<dimensionless_rate>) == yes);
static_assert(convertible(kind_of<angular_measure / time>, kind_of<dimensionless_rate>) == yes);
static_assert(convertible(kind_of<solid_angular_measure / time>, kind_of<dimensionless_rate>) == yes);
static_assert(convertible(angular_measure / time, solid_angular_measure_rate) == no);
static_assert(convertible(angular_measure / time, kind_of<solid_angular_measure_rate>) == no);
static_assert(convertible(kind_of<angular_measure / time>, kind_of<solid_angular_measure_rate>) == no);
static_assert(convertible(dimensionless / time, angular_measure_rate) == explicit_conversion);
static_assert(convertible(dimensionless / time, solid_angular_measure_rate) == explicit_conversion);
static_assert(convertible(dimensionless / time, kind_of<angular_measure_rate>) == explicit_conversion);
static_assert(convertible(dimensionless / time, kind_of<solid_angular_measure_rate>) == explicit_conversion);
static_assert(convertible(kind_of<dimensionless / time>, angular_measure_rate) == yes);
static_assert(convertible(kind_of<dimensionless / time>, solid_angular_measure_rate) == yes);
static_assert(convertible(kind_of<dimensionless / time>, kind_of<angular_measure_rate>) == yes);
static_assert(convertible(kind_of<dimensionless / time>, kind_of<solid_angular_measure_rate>) == yes);
// quantity character checks
static_assert((displacement / time).character == quantity_character::vector);
static_assert((position_vector / position_vector * time).character == quantity_character::scalar);
@ -803,6 +1025,8 @@ static_assert(get_common_quantity_spec(kind_of<length>, length) == length);
static_assert(get_common_quantity_spec(length, kind_of<length>) == length);
static_assert(get_common_quantity_spec(width, kind_of<length>) == width);
static_assert(get_common_quantity_spec(kind_of<length>, width) == width);
static_assert(get_common_quantity_spec(kind_of<dimensionless>, kind_of<angular_measure>) == kind_of<angular_measure>);
static_assert(get_common_quantity_spec(kind_of<dimensionless>, angular_measure) == angular_measure);
static_assert(get_common_quantity_spec(width, height) == length);
static_assert(get_common_quantity_spec(distance, path_length) == path_length);
@ -832,11 +1056,21 @@ static_assert(get_common_quantity_spec(mass * acceleration * length, gravitation
mass * acceleration * length);
template<auto T1, auto T2>
concept no_common_type = requires {
requires !requires { typename std::common_type_t<decltype(T1), decltype(T2)>; };
requires !requires { typename std::common_type_t<decltype(T2), decltype(T1)>; };
concept no_common_quantity_spec = requires {
requires !requires { get_common_quantity_spec(T1, T2); };
requires !requires { get_common_quantity_spec(T2, T1); };
};
static_assert(no_common_type<energy, torque>);
static_assert(no_common_type<frequency, activity>);
static_assert(no_common_quantity_spec<energy, torque>);
static_assert(no_common_quantity_spec<kind_of<energy>, torque>);
static_assert(no_common_quantity_spec<frequency, activity>);
static_assert(no_common_quantity_spec<kind_of<frequency>, activity>);
static_assert(no_common_quantity_spec<frequency, kind_of<activity>>);
static_assert(no_common_quantity_spec<kind_of<frequency>, kind_of<activity>>);
static_assert(no_common_quantity_spec<dimensionless, angular_measure>);
static_assert(no_common_quantity_spec<dimensionless, kind_of<angular_measure>>);
static_assert(no_common_quantity_spec<angular_measure, solid_angular_measure>);
static_assert(no_common_quantity_spec<kind_of<angular_measure>, solid_angular_measure>);
static_assert(no_common_quantity_spec<angular_measure, kind_of<solid_angular_measure>>);
static_assert(no_common_quantity_spec<kind_of<angular_measure>, kind_of<solid_angular_measure>>);
} // namespace

View File

@ -260,6 +260,12 @@ static_assert(std::convertible_to<quantity<isq::length[km], int>, quantity<isq::
static_assert(std::constructible_from<quantity<isq::length[km]>, quantity<isq::length[m], int>>);
static_assert(std::convertible_to<quantity<isq::length[m], int>, quantity<isq::length[km]>>);
static_assert(!std::convertible_to<quantity<isq::angular_measure[rad]>, quantity<dimensionless[one]>>);
static_assert(!std::convertible_to<quantity<isq::angular_measure[rad]>, quantity<one>>);
static_assert(!std::convertible_to<quantity<rad>, quantity<one>>);
static_assert(!std::convertible_to<quantity<isq::angular_measure[one]>, quantity<dimensionless[one]>>);
static_assert(!std::convertible_to<quantity<isq::angular_measure[one]>, quantity<one>>);
///////////////////////
// obtaining a number
///////////////////////
@ -337,6 +343,7 @@ 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);
static_assert((1. * rad + 1. * deg).in(one) != 0 * one);
#if MP_UNITS_HOSTED
static_assert(((2.f + 1if) * isq::voltage_phasor[V]).in(mV).numerical_value_in(mV) == 2000.f + 1000if);
@ -1309,12 +1316,25 @@ static_assert(is_of_type<quantity_cast<isq::distance>(1 * m), quantity<isq::dist
static_assert(is_of_type<quantity_cast<isq::distance>(isq::length(1 * m)), quantity<isq::distance[m], int>>);
static_assert(is_of_type<quantity_cast<kind_of<isq::length>>(isq::length(1 * m)), quantity<si::metre, int>>);
static_assert(is_of_type<quantity_cast<kind_of<isq::length>>(isq::distance(1 * m)), quantity<si::metre, int>>);
static_assert(is_of_type<quantity_cast<dimensionless>(1. * isq::angular_measure[one]), quantity<dimensionless[one]>>);
static_assert(
is_of_type<quantity_cast<dimensionless>((1. * isq::angular_measure[rad]).in(one)), quantity<dimensionless[one]>>);
static_assert(is_of_type<quantity_cast<dimensionless>((1. * rad).in(one)), quantity<dimensionless[one]>>);
// lvalue references in quantity_cast
namespace lvalue_tests {
constexpr quantity<m, int> lvalue_q = 1 * m;
static_assert(is_of_type<quantity_cast<isq::distance>(lvalue_q), quantity<isq::distance[m], int>>);
} // namespace lvalue_tests
template<template<auto, typename> typename Q>
concept invalid_quantity_cast = requires {
requires !requires { quantity_cast<dimensionless>(Q<rad, double>(42. * rad)); };
requires !requires { quantity_cast<dimensionless>(Q<isq::angular_measure[rad], double>(42. * rad)); };
};
static_assert(invalid_quantity_cast<quantity>);
// QuantityOf
static_assert(QuantityOf<quantity<isq::length[m]>, isq::length>);
static_assert(QuantityOf<quantity<isq::width[m]>, isq::length>);

View File

@ -284,14 +284,8 @@ static_assert(invalid_unit<storage_capacity, steradian>);
static_assert(is_of_type<get_common_reference(dimensionless[one], one), reference<dimensionless_, one_>>);
static_assert(is_of_type<get_common_reference(radian, one), radian_>);
static_assert(is_of_type<get_common_reference(one, radian), radian_>);
static_assert(is_of_type<get_common_reference(radian, dimensionless[one]), reference<angular_measure_, radian_>>);
static_assert(is_of_type<get_common_reference(dimensionless[one], radian), reference<angular_measure_, radian_>>);
static_assert(is_of_type<get_common_reference(angular_measure[radian], one), reference<angular_measure_, radian_>>);
static_assert(is_of_type<get_common_reference(one, angular_measure[radian]), reference<angular_measure_, radian_>>);
static_assert(
is_of_type<get_common_reference(angular_measure[radian], dimensionless[one]), reference<angular_measure_, radian_>>);
static_assert(
is_of_type<get_common_reference(dimensionless[one], angular_measure[radian]), reference<angular_measure_, radian_>>);
template<auto R1, auto R2>
concept no_common_reference = requires {
@ -307,43 +301,29 @@ static_assert(no_common_reference<radian, steradian>);
static_assert(no_common_reference<angular_measure[radian], steradian>);
static_assert(no_common_reference<radian, solid_angular_measure[steradian]>);
static_assert(no_common_reference<angular_measure[radian], solid_angular_measure[steradian]>);
static_assert(no_common_reference<radian, dimensionless[one]>);
static_assert(no_common_reference<angular_measure[radian], dimensionless[one]>);
// addition of various dimensionless quantities
static_assert(is_of_type<1 * radian + 1 * one, quantity<radian, int>>);
static_assert(is_of_type<1 * radian + dimensionless(1 * one), quantity<angular_measure[radian], int>>);
static_assert(is_of_type<angular_measure(1 * radian) + 1 * one, quantity<angular_measure[radian], int>>);
static_assert(is_of_type<angular_measure(1 * radian) + dimensionless(1 * one), quantity<angular_measure[radian], int>>);
static_assert(is_of_type<1 * steradian + 1 * one, quantity<steradian, int>>);
static_assert(is_of_type<1 * steradian + dimensionless(1 * one), quantity<solid_angular_measure[steradian], int>>);
static_assert(
is_of_type<solid_angular_measure(1 * steradian) + 1 * one, quantity<solid_angular_measure[steradian], int>>);
static_assert(is_of_type<solid_angular_measure(1 * steradian) + dimensionless(1 * one),
quantity<solid_angular_measure[steradian], int>>);
// subtraction of various dimensionless quantities
static_assert(is_of_type<1 * radian - 1 * one, quantity<radian, int>>);
static_assert(is_of_type<1 * radian - dimensionless(1 * one), quantity<angular_measure[radian], int>>);
static_assert(is_of_type<angular_measure(1 * radian) - 1 * one, quantity<angular_measure[radian], int>>);
static_assert(is_of_type<angular_measure(1 * radian) - dimensionless(1 * one), quantity<angular_measure[radian], int>>);
static_assert(is_of_type<1 * steradian - 1 * one, quantity<steradian, int>>);
static_assert(is_of_type<1 * steradian - dimensionless(1 * one), quantity<solid_angular_measure[steradian], int>>);
static_assert(
is_of_type<solid_angular_measure(1 * steradian) - 1 * one, quantity<solid_angular_measure[steradian], int>>);
static_assert(is_of_type<solid_angular_measure(1 * steradian) - dimensionless(1 * one),
quantity<solid_angular_measure[steradian], int>>);
// comparison of various dimensionless quantities
static_assert(1 * radian == 1 * one);
static_assert(1 * radian == dimensionless(1 * one));
static_assert(angular_measure(1 * radian) == 1 * one);
static_assert(angular_measure(1 * radian) == dimensionless(1 * one));
static_assert(1 * steradian == 1 * one);
static_assert(1 * steradian == dimensionless(1 * one));
static_assert(solid_angular_measure(1 * steradian) == 1 * one);
static_assert(solid_angular_measure(1 * steradian) == dimensionless(1 * one));
// invalid operations on dimensionless quantities
template<auto Q1, auto Q2>
@ -358,6 +338,8 @@ static_assert(invalid_addition<1 * radian, 1 * bit>);
static_assert(invalid_addition<frequency(1 * hertz), activity(1 * becquerel)>);
static_assert(invalid_addition<angular_measure(1 * radian), solid_angular_measure(1 * steradian)>);
static_assert(invalid_addition<angular_measure(1 * radian), storage_capacity(1 * bit)>);
static_assert(invalid_addition<1 * radian, dimensionless(1 * one)>);
static_assert(invalid_addition<angular_measure(1 * radian), dimensionless(1 * one)>);
template<auto Q1, auto Q2>
concept invalid_subtraction = requires {
@ -371,6 +353,8 @@ static_assert(invalid_subtraction<1 * radian, 1 * bit>);
static_assert(invalid_subtraction<frequency(1 * hertz), activity(1 * becquerel)>);
static_assert(invalid_subtraction<angular_measure(1 * radian), solid_angular_measure(1 * steradian)>);
static_assert(invalid_subtraction<angular_measure(1 * radian), storage_capacity(1 * bit)>);
static_assert(invalid_subtraction<1 * radian, dimensionless(1 * one)>);
static_assert(invalid_subtraction<angular_measure(1 * radian), dimensionless(1 * one)>);
template<auto Q1, auto Q2>
concept invalid_comparison = requires {
@ -384,6 +368,8 @@ static_assert(invalid_comparison<1 * radian, 1 * bit>);
static_assert(invalid_comparison<frequency(1 * hertz), activity(1 * becquerel)>);
static_assert(invalid_comparison<angular_measure(1 * radian), solid_angular_measure(1 * steradian)>);
static_assert(invalid_comparison<angular_measure(1 * radian), storage_capacity(1 * bit)>);
static_assert(invalid_comparison<1 * radian, dimensionless(1 * one)>);
static_assert(invalid_comparison<angular_measure(1 * radian), dimensionless(1 * one)>);
// make_reference
static_assert(is_of_type<make_reference(length, metre), reference<length_, metre_>>);

View File

@ -156,6 +156,17 @@ static_assert(is_same_v<type_list_split_half<type_list<int, long, double, float>
static_assert(
is_same_v<type_list_split_half<type_list<int, long, double, float>>::second_list, type_list<double, float>>);
// type_list_extract
static_assert(is_same_v<type_list_extract<type_list<int>, 0>::element, int>);
static_assert(is_same_v<type_list_extract<type_list<int>, 0>::rest, type_list<>>);
static_assert(is_same_v<type_list_extract<type_list<int, long>, 0>::element, int>);
static_assert(is_same_v<type_list_extract<type_list<int, long>, 0>::rest, type_list<long>>);
static_assert(is_same_v<type_list_extract<type_list<int, long>, 1>::element, long>);
static_assert(is_same_v<type_list_extract<type_list<int, long>, 1>::rest, type_list<int>>);
static_assert(is_same_v<type_list_extract<type_list<int, long, double>, 1>::element, long>);
static_assert(is_same_v<type_list_extract<type_list<int, long, double>, 1>::rest, type_list<int, double>>);
template<auto V>
struct constant {
static constexpr auto value = V;

View File

@ -120,15 +120,15 @@ static_assert(!PrefixableUnit<MP_UNITS_NONCONST_TYPE(kilometre)>);
static_assert(is_of_type<metre, metre_>);
static_assert(is_of_type<get_canonical_unit(metre).reference_unit, metre_>);
static_assert(get_canonical_unit(metre).mag == mag<1>);
static_assert(convertible(metre, metre));
static_assert(!convertible(metre, second));
static_assert(interconvertible(metre, metre));
static_assert(!interconvertible(metre, second));
static_assert(metre == metre);
static_assert(metre != second);
static_assert(is_of_type<degree_Celsius, degree_Celsius_>);
static_assert(is_of_type<get_canonical_unit(degree_Celsius).reference_unit, kelvin_>);
static_assert(get_canonical_unit(degree_Celsius).mag == mag<1>);
static_assert(convertible(degree_Celsius, kelvin));
static_assert(interconvertible(degree_Celsius, kelvin));
static_assert(degree_Celsius != kelvin);
static_assert(equivalent(degree_Celsius, kelvin));
@ -139,28 +139,31 @@ static_assert(get_canonical_unit(radian).mag == mag<1>);
static_assert(is_of_type<degree, degree_>);
static_assert(is_of_type<get_canonical_unit(degree).reference_unit, one_>);
static_assert(get_canonical_unit(degree).mag == mag<π> / mag<180>);
static_assert(convertible(radian, degree));
static_assert(interconvertible(radian, degree));
static_assert(radian != degree);
static_assert(interconvertible(one, radian));
static_assert(interconvertible(radian, one));
static_assert(radian != one);
static_assert(is_of_type<steradian, steradian_>);
static_assert(is_of_type<get_canonical_unit(steradian).reference_unit, one_>);
static_assert(get_canonical_unit(steradian).mag == mag<1>);
static_assert(!convertible(radian, steradian));
static_assert(!interconvertible(radian, steradian));
static_assert(radian != steradian);
static_assert(is_of_type<minute, minute_>);
static_assert(is_of_type<get_canonical_unit(minute).reference_unit, second_>);
static_assert(get_canonical_unit(minute).mag == mag<60>);
static_assert(convertible(minute, second));
static_assert(interconvertible(minute, second));
static_assert(minute != second);
static_assert(is_of_type<hour, hour_>);
static_assert(is_of_type<get_canonical_unit(hour).reference_unit, second_>);
static_assert(get_canonical_unit(hour).mag == mag<3600>);
static_assert(convertible(hour, second));
static_assert(interconvertible(hour, second));
static_assert(convertible(hour, minute));
static_assert(convertible(hour, hour));
static_assert(interconvertible(hour, minute));
static_assert(interconvertible(hour, hour));
static_assert(hour != second);
static_assert(hour != minute);
static_assert(hour == hour);
@ -169,14 +172,14 @@ static_assert(is_of_type<newton, newton_>);
static_assert(
is_of_type<get_canonical_unit(newton).reference_unit, derived_unit<gram_, metre_, per<power<second_, 2>>>>);
static_assert(get_canonical_unit(newton).mag == mag<1000>); // !!! (because of kilogram)
static_assert(convertible(newton, newton));
static_assert(interconvertible(newton, newton));
static_assert(newton == newton);
static_assert(is_of_type<joule, joule_>);
static_assert(
is_of_type<get_canonical_unit(joule).reference_unit, derived_unit<gram_, power<metre_, 2>, per<power<second_, 2>>>>);
static_assert(get_canonical_unit(joule).mag == mag<1000>); // !!! (because of kilogram)
static_assert(convertible(joule, joule));
static_assert(interconvertible(joule, joule));
static_assert(joule == joule);
static_assert(joule != newton);
@ -187,8 +190,8 @@ static_assert(is_of_type<standard_gravity, standard_gravity_>);
static_assert(
is_of_type<get_canonical_unit(standard_gravity).reference_unit, derived_unit<metre_, per<power<second_, 2>>>>);
static_assert(get_canonical_unit(standard_gravity).mag == mag_ratio<980'665, 100'000>);
static_assert(convertible(standard_gravity, standard_gravity));
static_assert(convertible(standard_gravity, metre / square(second)));
static_assert(interconvertible(standard_gravity, standard_gravity));
static_assert(interconvertible(standard_gravity, metre / square(second)));
static_assert(standard_gravity == standard_gravity);
static_assert(standard_gravity != metre / square(second)); // magnitude is different
static_assert(standard_gravity._symbol_ == symbol_text{u8"g₀", "g_0"});
@ -197,7 +200,7 @@ static_assert(standard_gravity._symbol_ == symbol_text{u8"g₀", "g_0"});
static_assert(is_of_type<kilometre, MP_UNITS_NONCONST_TYPE(kilo<metre>)>);
static_assert(is_of_type<get_canonical_unit(kilometre).reference_unit, metre_>);
static_assert(get_canonical_unit(kilometre).mag == mag<1000>);
static_assert(convertible(kilometre, metre));
static_assert(interconvertible(kilometre, metre));
static_assert(kilometre != metre);
static_assert(kilometre._symbol_ == "km");
@ -205,7 +208,7 @@ static_assert(is_of_type<kilojoule, MP_UNITS_NONCONST_TYPE(kilo<joule>)>);
static_assert(is_of_type<get_canonical_unit(kilojoule).reference_unit,
derived_unit<gram_, power<metre_, 2>, per<power<second_, 2>>>>);
static_assert(get_canonical_unit(kilojoule).mag == mag<1'000'000>);
static_assert(convertible(kilojoule, joule));
static_assert(interconvertible(kilojoule, joule));
static_assert(kilojoule != joule);
static_assert(kilojoule._symbol_ == "kJ");
@ -448,11 +451,11 @@ static_assert(equivalent(kilo<metre> * milli<metre>, si::deca<metre>* si::deci<m
// comparisons of equivalent units (named vs unnamed/derived)
static_assert(one / second != hertz);
static_assert(equivalent(one / second, hertz));
static_assert(convertible(one / second, hertz));
static_assert(interconvertible(one / second, hertz));
// comparisons of equivalent units of different quantities
static_assert(hertz != becquerel);
static_assert(!convertible(hertz, becquerel));
static_assert(!interconvertible(hertz, becquerel));
// comparisons of scaled units
static_assert(kilo<metre> == kilometre);
@ -460,23 +463,23 @@ static_assert(mag<1000> * metre != kilo<metre>);
static_assert(equivalent(mag<1000> * metre, kilo<metre>));
static_assert(mag<1000> * metre != kilometre);
static_assert(equivalent(mag<1000> * metre, kilometre));
static_assert(convertible(kilo<metre>, kilometre));
static_assert(convertible(mag<1000> * metre, kilo<metre>));
static_assert(convertible(mag<1000> * metre, kilometre));
static_assert(interconvertible(kilo<metre>, kilometre));
static_assert(interconvertible(mag<1000> * metre, kilo<metre>));
static_assert(interconvertible(mag<1000> * metre, kilometre));
static_assert(mag<60> * metre / second != metre / (mag_ratio<1, 60> * second));
static_assert(equivalent(mag<60> * metre / second, metre / (mag_ratio<1, 60> * second)));
static_assert(metre != kilometre);
static_assert(convertible(metre, kilometre));
static_assert(interconvertible(metre, kilometre));
static_assert(mag<100> * metre != kilometre);
static_assert(convertible(mag<100> * metre, kilometre));
static_assert(interconvertible(mag<100> * metre, kilometre));
static_assert(milli<metre> != kilometre);
static_assert(convertible(milli<metre>, kilometre));
static_assert(interconvertible(milli<metre>, kilometre));
// comparisons of non-convertible units
// comparisons of non-interconvertible units
static_assert(metre != metre * metre);
static_assert(!convertible(metre, metre* metre));
static_assert(!interconvertible(metre, metre* metre));
// one
static_assert(is_of_type<metre / metre, one_>);