fix: modulo operation logic fixed

This commit is contained in:
Mateusz Pusz
2023-04-10 19:46:50 +02:00
parent ccb06bc0c4
commit 7ef8193dfc
2 changed files with 6 additions and 94 deletions

View File

@@ -284,34 +284,6 @@ public:
return *this;
}
template<typename Rep2>
requires(!Quantity<Rep2>) && (!treat_as_floating_point<rep>) && (!treat_as_floating_point<Rep2>) &&
requires(rep a, const Rep2 b) {
{
a %= b
} -> std::same_as<rep&>;
}
constexpr quantity& operator%=(const Rep2& rhs)
{
gsl_ExpectsAudit(rhs != quantity_values<Rep2>::zero());
number_ %= rhs;
return *this;
}
template<QuantityOf<dimension_one> Q>
requires(Q::unit == ::mp_units::one) && (!treat_as_floating_point<rep>) &&
(!treat_as_floating_point<typename Q::rep>) && requires(rep a, const typename Q::rep b) {
{
a %= b
} -> std::same_as<rep&>;
}
constexpr quantity& operator%=(const Q& rhs)
{
gsl_ExpectsAudit(rhs.number() != quantity_values<typename Q::rep>::zero());
number_ %= rhs.number();
return *this;
}
constexpr quantity& operator%=(const quantity& q)
requires(!treat_as_floating_point<rep>) && requires(rep a, rep b) {
{
@@ -398,23 +370,6 @@ public:
return v / q.number() * (::mp_units::one / reference);
}
template<typename Value>
requires(!Quantity<Value>) && (!treat_as_floating_point<rep>) && (!treat_as_floating_point<Value>) &&
detail::InvokeResultIsRepresentationOf<quantity_spec.character, std::modulus<>, rep, Value>
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& q, const Value& v)
{
gsl_ExpectsAudit(v != quantity_values<Value>::zero());
return (q.number() % v) * reference;
}
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity& rhs)
requires(!treat_as_floating_point<rep>) &&
detail::InvokeResultIsRepresentationOf<quantity_spec.character, std::modulus<>, rep, rep>
{
gsl_ExpectsAudit(rhs.number() != quantity_values<rep>::zero());
return (lhs.number() % rhs.number()) * reference;
}
template<Quantity Q>
requires(!treat_as_floating_point<rep>) && (!treat_as_floating_point<typename Q::rep>) &&
requires {
@@ -428,16 +383,6 @@ public:
return (ret(lhs).number() % ret(rhs).number()) * ref;
}
template<Quantity Q>
requires(!treat_as_floating_point<rep>) && (!treat_as_floating_point<typename Q::rep>) &&
(Q::dimension == dimension_one) && (Q::unit == ::mp_units::one) &&
detail::InvokeResultIsRepresentationOf<quantity_spec.character, std::modulus<>, rep, typename Q::rep>
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const Q& rhs)
{
gsl_ExpectsAudit(rhs.number() != quantity_values<rep>::zero());
return (lhs.number() % rhs.number()) * reference;
}
template<Quantity Q>
requires requires { common_reference(reference, Q::reference); } &&
std::equality_comparable_with<rep, typename Q::rep>

View File

@@ -376,10 +376,8 @@ static_assert((1 * m += 1 * m).number() == 2);
static_assert((2 * m -= 1 * m).number() == 1);
static_assert((1 * m *= 2).number() == 2);
static_assert((2 * m /= 2).number() == 1);
static_assert((7 * m %= 2).number() == 1);
static_assert((1 * m *= 2 * one).number() == 2);
static_assert((2 * m /= 2 * one).number() == 1);
static_assert((7 * m %= 2 * one).number() == 1);
static_assert((7 * m %= 2 * m).number() == 1);
// different types
@@ -393,24 +391,8 @@ static_assert((2.5 * m *= 3 * one).number() == 7.5);
static_assert((7.5 * m /= 3 * one).number() == 2.5);
static_assert((3500 * m %= 1 * km).number() == 500);
static_assert((std::uint8_t(255) * m %= 256).number() == [] {
std::uint8_t ui(255);
return ui %= 256;
}());
static_assert((std::uint8_t(255) * m %= 256 * one).number() == [] {
std::uint8_t ui(255);
return ui %= 256;
}());
// static_assert((std::uint8_t(255) * m %= 256 * m).number() != [] { std::uint8_t ui(255); return ui %= 256; }()); //
// UB
static_assert((std::uint8_t(255) * m %= 257).number() == [] {
std::uint8_t ui(255);
return ui %= 257;
}());
static_assert((std::uint8_t(255) * m %= 257 * one).number() == [] {
std::uint8_t ui(255);
return ui %= 257;
}());
// TODO: Fix
static_assert((std::uint8_t(255) * m %= 257 * m).number() != [] {
std::uint8_t ui(255);
@@ -532,7 +514,6 @@ static_assert(is_of_type<4 * m % (2 * m), quantity<si::metre, int>>);
static_assert(is_of_type<1'234 * m % (1 * km), quantity<si::metre, int>>);
static_assert(is_of_type<1 * km % (300 * m), quantity<si::metre, int>>);
static_assert(is_of_type<4 * one % (2 * one), quantity<one, int>>);
static_assert(is_of_type<4 * one % 2, quantity<one, int>>);
// check for integral types promotion
static_assert(is_same_v<decltype((std::uint8_t(0) * m + std::uint8_t(0) * m).number()), int&&>);
@@ -669,7 +650,6 @@ static_assert((7 * m % (2 * m)).number() == 1);
static_assert((7 * km % (2000 * m)).number() == 1000);
static_assert((1300 * m % (1 * km)).number() == 300);
static_assert((7 * one % (2 * one)).number() == 1);
static_assert((7 * one % 2).number() == 1);
static_assert((10 * m2 * (10 * m2)) / (50 * m2) == 2 * m2);
@@ -699,6 +679,10 @@ static_assert(4 % (2 * one) == 0);
// modulo arithmetics
static_assert(5 * h % (120 * min) == 60 * min);
static_assert(300 * min % (2 * h) == 60 * min);
static_assert(300 * min % (120 * min) == 60 * min);
constexpr auto quotient_remainder_theorem(auto q1, auto q2)
{
auto quotient = q1 / q2;
@@ -707,26 +691,9 @@ constexpr auto quotient_remainder_theorem(auto q1, auto q2)
return q;
}
// this works only if two quantities have the same unit
static_assert(quotient_remainder_theorem(7 * m, 3 * m) == 7 * m);
static_assert(quotient_remainder_theorem(3'000 * m, 400 * m) == 3'000 * m);
// static_assert(quotient_remainder_theorem(3 * km, 400 * m) == 3 * km);
// static_assert(quotient_remainder_theorem(3 * km, 2 * m) == 3 * km);
// static_assert(quotient_remainder_theorem(3 * km, 400'000 * mm) == 3 * km);
// static_assert(quotient_remainder_theorem(3 * km, 2'000 * mm) == 3 * km);
// static_assert(quotient_remainder_theorem(3 * km, 400 * mm) == 3 * km);
// static_assert(quotient_remainder_theorem(3 * km, 2 * mm) == 3 * km);
// static_assert(quotient_remainder_theorem(3'000 * m, 400) == 3'000 * m);
// static_assert(quotient_remainder_theorem(3'000 * m, 400 * one) == 3'000 * m);
// static_assert(quotient_remainder_theorem(3 * km, 400 * one) == 3 * km);
// static_assert(quotient_remainder_theorem(3 * km, 2 * one) == 3 * km);
// static_assert(quotient_remainder_theorem(3 * km, 400 * (mag<ratio{1, 1000}> * one)) == 3 * km);
static_assert((7 * m / (3 * m)) * (3 * m) + (7 * m) % (3 * m) == 7 * m);
static_assert((7 * m / 3) * 3 + (7 * m) % 3 == 7 * m);
static_assert((7 * m / (3 * one)) * (3 * one) + (7 * m) % (3 * one) == 7 * m);
static_assert((7 / (3 * one)) * (3 * one) + 7 % (3 * one) == 7);
// static_assert((7 * km / (2500 * m)) * (2500 * m) + (7 * km) % (2500 * m) == 7 * km);
// static_assert((7500 * m / (3 * km)) * (3 * km) + (75000 * m) % (3 * km) == 7500 * m);
static_assert(is_same_v<decltype(0 * one + 0.0), decltype(0.0 * one)>);
static_assert(is_same_v<decltype(0 * one - 0.0), decltype(0.0 * one)>);