mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-03 12:24:26 +02:00
@@ -34,6 +34,7 @@
|
|||||||
- fix: downcasting facility for non-default-constructible types
|
- fix: downcasting facility for non-default-constructible types
|
||||||
- fix: restore user-warnings within the library implementation
|
- fix: restore user-warnings within the library implementation
|
||||||
- fix: the text symbol of `foot_pound_force` and `foot_pound_force_per_second`
|
- fix: the text symbol of `foot_pound_force` and `foot_pound_force_per_second`
|
||||||
|
- fix: quantity modulo arithmetics fixed
|
||||||
- (!) build: Conan testing version is now hosted on [Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units)
|
- (!) build: Conan testing version is now hosted on [Artifactory](https://mpusz.jfrog.io/ui/packages/conan:%2F%2Fmp-units)
|
||||||
- (!) build: Linear Algebra is now hosted on its [Artifactory](https://twonington.jfrog.io/artifactory/api/conan/conan-oss)
|
- (!) build: Linear Algebra is now hosted on its [Artifactory](https://twonington.jfrog.io/artifactory/api/conan/conan-oss)
|
||||||
- (!) build: `BUILD_DOCS` CMake option renamed to `UNITS_BUILD_DOCS`
|
- (!) build: `BUILD_DOCS` CMake option renamed to `UNITS_BUILD_DOCS`
|
||||||
|
@@ -426,25 +426,15 @@ template<Quantity Q1, Quantity Q2>
|
|||||||
return detail::make_quantity<Q1::reference / Q2::reference>(lhs.number() / rhs.number());
|
return detail::make_quantity<Q1::reference / Q2::reference>(lhs.number() / rhs.number());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename D1, typename U1, typename Rep1, typename U2, typename Rep2>
|
template<Quantity Q1, Quantity Q2>
|
||||||
requires (!floating_point_<Rep1>) && (!floating_point_<Rep2>) &&
|
|
||||||
quantity_value_for_<std::modulus<>, Rep1, Rep2>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator%(const quantity<D1, U1, Rep1>& lhs, const quantity<dim_one, U2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
gsl_ExpectsAudit(rhs.number() != quantity_values<Rep2>::zero());
|
|
||||||
using unit = downcast_unit<D1, U1::ratio * U2::ratio>;
|
|
||||||
using ret = quantity<D1, unit, std::invoke_result_t<std::modulus<>, Rep1, Rep2>>;
|
|
||||||
return ret(lhs.number() % rhs.number());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
|
||||||
requires (!floating_point_<typename Q1::rep>) && (!floating_point_<typename Q2::rep>) &&
|
requires (!floating_point_<typename Q1::rep>) && (!floating_point_<typename Q2::rep>) &&
|
||||||
|
(QuantityEquivalentTo<Q2, Q1> || Dimensionless<Q2>) &&
|
||||||
quantity_value_for_<std::modulus<>, typename Q1::rep, typename Q2::rep>
|
quantity_value_for_<std::modulus<>, typename Q1::rep, typename Q2::rep>
|
||||||
[[nodiscard]] constexpr Quantity auto operator%(const Q1& lhs, const Q2& rhs)
|
[[nodiscard]] constexpr Quantity auto operator%(const Q1& lhs, const Q2& rhs)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q2::rep>::zero());
|
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q2::rep>::zero());
|
||||||
using ret = common_quantity_for<std::modulus<>, Q1, Q2>;
|
using ret = quantity<typename Q1::dimension, typename Q1::unit, std::invoke_result_t<std::modulus<>, typename Q1::rep, typename Q2::rep>>;
|
||||||
return ret(ret(lhs).number() % ret(rhs).number());
|
return ret(lhs.number() % rhs.number());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
|
||||||
|
@@ -612,7 +612,7 @@ static_assert(same(height<metre, double>(2. * m) / (3 * s), rate_of_climb<metre_
|
|||||||
static_assert(same(width<metre, int>(2 * m) * dimensionless<percent, int>(3), width<centimetre, int>(6 * cm)));
|
static_assert(same(width<metre, int>(2 * m) * dimensionless<percent, int>(3), width<centimetre, int>(6 * cm)));
|
||||||
static_assert(same(dimensionless<percent, int>(2) * width<metre, int>(3 * m), width<centimetre, int>(6 * cm)));
|
static_assert(same(dimensionless<percent, int>(2) * width<metre, int>(3 * m), width<centimetre, int>(6 * cm)));
|
||||||
static_assert(same(width<metre, int>(2 * m) / dimensionless<percent, double>(3), width<hectometre, double>(2. / 3 * hm)));
|
static_assert(same(width<metre, int>(2 * m) / dimensionless<percent, double>(3), width<hectometre, double>(2. / 3 * hm)));
|
||||||
static_assert(same(width<metre, int>(2 * m) % dimensionless<percent, int>(3), width<centimetre, int>(2 * cm)));
|
static_assert(same(width<metre, int>(2 * m) % dimensionless<percent, int>(3), width<metre, int>(2 * m)));
|
||||||
|
|
||||||
static_assert(same(height<metre, int>(2 * m) / (3 * m),
|
static_assert(same(height<metre, int>(2 * m) / (3 * m),
|
||||||
quantity_kind<downcast_kind<height_kind, dim_one>, one, int>(0)));
|
quantity_kind<downcast_kind<height_kind, dim_one>, one, int>(0)));
|
||||||
|
@@ -399,7 +399,7 @@ static_assert(is_same_v<decltype(1_q_m % 1_q_m), length<metre, std::int64_t>>);
|
|||||||
static_assert(compare<decltype(1_q_m * dimensionless<percent, std::int64_t>(1)), length<centimetre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m * dimensionless<percent, std::int64_t>(1)), length<centimetre, std::int64_t>>);
|
||||||
static_assert(compare<decltype(dimensionless<percent, std::int64_t>(1) * 1_q_m), length<centimetre, std::int64_t>>);
|
static_assert(compare<decltype(dimensionless<percent, std::int64_t>(1) * 1_q_m), length<centimetre, std::int64_t>>);
|
||||||
static_assert(compare<decltype(1_q_m / dimensionless<percent, std::int64_t>(1)), length<hectometre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m / dimensionless<percent, std::int64_t>(1)), length<hectometre, std::int64_t>>);
|
||||||
static_assert(compare<decltype(1_q_m % dimensionless<percent, std::int64_t>(1)), length<centimetre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m % dimensionless<percent, std::int64_t>(1)), length<metre, std::int64_t>>);
|
||||||
static_assert(compare<decltype(1_q_m * 1_q_m), area<square_metre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m * 1_q_m), area<square_metre, std::int64_t>>);
|
||||||
static_assert(compare<decltype(1_q_m / 1_q_m), dimensionless<one, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m / 1_q_m), dimensionless<one, std::int64_t>>);
|
||||||
static_assert(compare<decltype(1 / 1_q_s), frequency<hertz, std::int64_t>>);
|
static_assert(compare<decltype(1 / 1_q_s), frequency<hertz, std::int64_t>>);
|
||||||
@@ -433,7 +433,7 @@ static_assert(compare<decltype(quantity{1} / 1._q_s), frequency<hertz, long doub
|
|||||||
static_assert(compare<decltype(dimensionless<percent, std::int64_t>(1) / 1._q_s), frequency<scaled_unit<ratio(1, 100), hertz>, long double>>);
|
static_assert(compare<decltype(dimensionless<percent, std::int64_t>(1) / 1._q_s), frequency<scaled_unit<ratio(1, 100), hertz>, long double>>);
|
||||||
static_assert(compare<decltype(1_q_m % short(1)), length<metre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m % short(1)), length<metre, std::int64_t>>);
|
||||||
static_assert(compare<decltype(1_q_m % quantity{short(1)}), length<metre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m % quantity{short(1)}), length<metre, std::int64_t>>);
|
||||||
static_assert(compare<decltype(1_q_m % dimensionless<percent, short>(1)), length<centimetre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m % dimensionless<percent, short>(1)), length<metre, std::int64_t>>);
|
||||||
static_assert(compare<decltype(1_q_m % length<metre, short>(1)), length<metre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m % length<metre, short>(1)), length<metre, std::int64_t>>);
|
||||||
|
|
||||||
static_assert(is_same_v<decltype(1._q_m + 1_q_m), length<metre, long double>>);
|
static_assert(is_same_v<decltype(1._q_m + 1_q_m), length<metre, long double>>);
|
||||||
@@ -475,7 +475,7 @@ static_assert(is_same_v<decltype(1_q_km - 1._q_m), length<metre, long double>>);
|
|||||||
static_assert(is_same_v<decltype(1._q_km - 1._q_m), length<metre, long double>>);
|
static_assert(is_same_v<decltype(1._q_km - 1._q_m), length<metre, long double>>);
|
||||||
|
|
||||||
static_assert(is_same_v<decltype(1_q_m % 1_q_km), length<metre, std::int64_t>>);
|
static_assert(is_same_v<decltype(1_q_m % 1_q_km), length<metre, std::int64_t>>);
|
||||||
static_assert(is_same_v<decltype(1_q_km % 1_q_m), length<metre, std::int64_t>>);
|
static_assert(is_same_v<decltype(1_q_km % 1_q_m), length<kilometre, std::int64_t>>);
|
||||||
|
|
||||||
// different dimensions
|
// different dimensions
|
||||||
static_assert(compare<decltype(1_q_m_per_s * 1_q_s), length<metre, std::int64_t>>);
|
static_assert(compare<decltype(1_q_m_per_s * 1_q_s), length<metre, std::int64_t>>);
|
||||||
@@ -545,7 +545,7 @@ static_assert((7_q_m % 2).number() == 1);
|
|||||||
static_assert((7_q_m % quantity{2}).number() == 1);
|
static_assert((7_q_m % quantity{2}).number() == 1);
|
||||||
static_assert((7_q_m % dimensionless<percent, int>(2)).number() == 1);
|
static_assert((7_q_m % dimensionless<percent, int>(2)).number() == 1);
|
||||||
static_assert((7_q_m % 2_q_m).number() == 1);
|
static_assert((7_q_m % 2_q_m).number() == 1);
|
||||||
static_assert((7_q_km % 2000_q_m).number() == 1000);
|
static_assert((7_q_km % 2000_q_m).number() == 7);
|
||||||
|
|
||||||
static_assert((10_q_km2 * 10_q_km2) / 50_q_km2 == 2_q_km2);
|
static_assert((10_q_km2 * 10_q_km2) / 50_q_km2 == 2_q_km2);
|
||||||
|
|
||||||
@@ -560,8 +560,7 @@ static_assert(quantity_cast<one>(10_q_km / 5_q_m).number() == 2000);
|
|||||||
|
|
||||||
static_assert((10_q_s * 2_q_kHz).number() == 20);
|
static_assert((10_q_s * 2_q_kHz).number() == 20);
|
||||||
|
|
||||||
// unit constants
|
// quantity references
|
||||||
|
|
||||||
static_assert(2_q_m * (1 * m) == (2_q_m2));
|
static_assert(2_q_m * (1 * m) == (2_q_m2));
|
||||||
static_assert(2_q_m2 / (1 * m) == (2_q_m));
|
static_assert(2_q_m2 / (1 * m) == (2_q_m));
|
||||||
|
|
||||||
@@ -787,4 +786,62 @@ static_assert(is_same_v<decltype(1_q_mm + 1_q_km), length<millimetre, std::int64
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// modulo arithmetics
|
||||||
|
|
||||||
|
constexpr auto quotient_remainder_theorem(auto q1, auto q2)
|
||||||
|
{
|
||||||
|
auto quotient = q1 / q2;
|
||||||
|
auto reminder = q1 % q2;
|
||||||
|
auto q = quotient * q2 + reminder;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto qr1 = quotient_remainder_theorem(3'000 * m, 400 * m);
|
||||||
|
static_assert(qr1 == 3'000 * m);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr1)>, decltype(3'000 * m)>);
|
||||||
|
|
||||||
|
constexpr auto qr2 = quotient_remainder_theorem(3 * km, 400 * m);
|
||||||
|
static_assert(qr2 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr2)>, decltype(3 * km)>);
|
||||||
|
|
||||||
|
constexpr auto qr3 = quotient_remainder_theorem(3 * km, 2 * m);
|
||||||
|
static_assert(qr3 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr2)>, decltype(3 * km)>);
|
||||||
|
|
||||||
|
constexpr auto qr4 = quotient_remainder_theorem(3 * km, 400'000 * mm);
|
||||||
|
static_assert(qr4 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr4)>, decltype(3 * km)>);
|
||||||
|
|
||||||
|
constexpr auto qr5 = quotient_remainder_theorem(3 * km, 2'000 * mm);
|
||||||
|
static_assert(qr5 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr5)>, decltype(3 * km)>);
|
||||||
|
|
||||||
|
constexpr auto qr6 = quotient_remainder_theorem(3 * km, 400 * mm);
|
||||||
|
static_assert(qr6 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr6)>, decltype(3 * km)>);
|
||||||
|
|
||||||
|
constexpr auto qr7 = quotient_remainder_theorem(3 * km, 2 * mm);
|
||||||
|
static_assert(qr7 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr7)>, decltype(3 * km)>);
|
||||||
|
|
||||||
|
constexpr auto qr8 = quotient_remainder_theorem(3'000 * m, 400);
|
||||||
|
static_assert(qr8 == 3'000 * m);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr8)>, decltype(3'000 * m)>);
|
||||||
|
|
||||||
|
constexpr auto qr9 = quotient_remainder_theorem(3'000 * m, quantity(400));
|
||||||
|
static_assert(qr9 == 3'000 * m);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr9)>, decltype(3'000 * m)>);
|
||||||
|
|
||||||
|
constexpr auto qr10 = quotient_remainder_theorem(3 * km, quantity(400));
|
||||||
|
static_assert(qr10 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr10)>, decltype(3 * km)>);
|
||||||
|
|
||||||
|
constexpr auto qr11 = quotient_remainder_theorem(3 * km, quantity(2));
|
||||||
|
static_assert(qr11 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr11)>, decltype(3 * km)>);
|
||||||
|
|
||||||
|
constexpr auto qr12 = quotient_remainder_theorem(3 * km, dimensionless<scaled_unit<ratio(1, 1000), one>, int>(400));
|
||||||
|
static_assert(qr12 == 3 * km);
|
||||||
|
static_assert(is_same_v<std::remove_cvref_t<decltype(qr12)>, decltype(3 * km)>);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
Reference in New Issue
Block a user