Skip to content

Commit

Permalink
Dividing 1/<unit> will no longer calculate the ratio in
Browse files Browse the repository at this point in the history
  • Loading branch information
bernedom committed Feb 11, 2022
1 parent 507be9e commit bbe5246
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 20 deletions.
18 changes: 6 additions & 12 deletions include/SI/detail/unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ struct unit_t {
_type value_;
};

/// operator to divide primitive type by unit encapsulating the same type
/// operator to divide scalar type by unit encapsulating the same type
/// template specialisation handling integer types
/// @results unit with negative exponent
template <typename _type, char _symbol, typename _exponent, typename _rhs_type,
Expand All @@ -468,13 +468,11 @@ operator/(const _type &lhs,
"Implicit ratio conversion disabled, convert to ratio<1> "
"before dividing");
static_assert(detail::is_ratio_v<_exponent>, "Exponent is a ratio type");
return unit_cast<unit_t<
_symbol, std::ratio_multiply<std::ratio<-1>, _exponent>, _type, _ratio>>(
unit_t<_symbol, std::ratio_multiply<std::ratio<-1>, _exponent>, _type,
std::ratio<1>>{lhs / (rhs.value() * (_ratio::num / _ratio::den))});
return unit_t<_symbol, std::ratio_multiply<std::ratio<-1>, _exponent>, _type,
_ratio>{lhs / rhs.value()};
}

/// operator to divide primitive type by unit encapsulating the same type
/// operator to divide scalar type by unit encapsulating the same type
/// template specialisation for floating point types, to avoid possible loss
/// of precision when adjusting for ratio
/// @results unit with negative exponent
Expand All @@ -489,12 +487,8 @@ operator/(const _type &lhs,
"Implicit ratio conversion disabled, convert to ratio<1> "
"before dividing");
static_assert(detail::is_ratio_v<_exponent>, "Exponent is a ratio type");
return unit_cast<unit_t<
_symbol, std::ratio_multiply<std::ratio<-1>, _exponent>, _type, _ratio>>(
unit_t<_symbol, std::ratio_multiply<std::ratio<-1>, _exponent>, _type,
std::ratio<1>>{lhs /
(rhs.value() * (static_cast<_type>(_ratio::num) /
static_cast<_type>(_ratio::den)))});
return unit_t<_symbol, std::ratio_multiply<std::ratio<-1>, _exponent>, _type,
_ratio>{lhs / rhs.value()};
}

} // namespace SI::detail
6 changes: 6 additions & 0 deletions test/src/base_unit_tests/length_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -511,3 +511,9 @@ TEST_CASE("GIVEN a string of '1Em' WHEN streamed into exa_metre_t THEN result "
REQUIRE(!ss.fail());
REQUIRE(value == 1_Em);
}

// TEST_CASE("Test") {
// constexpr auto r = 2L / 1_mm;
// // constexpr auto x = 2.0 / SI::milli_metre_t<double>{1};
// // constexpr auto x = 2 / SI::milli_metre_t<double>{1};
// }
31 changes: 23 additions & 8 deletions test/src/detail_tests/unit_t_operator_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -343,33 +343,48 @@ TEST_CASE("GIVEN a unit with ratio<1> and a scalar AND internal type is "
STATIC_REQUIRE(eps_equals(result.value(), 500.0L));
}

TEST_CASE("GIVEN a unit with ratio<1, 1000> and a scalar AND interal type is "
TEST_CASE("GIVEN a unit with ratio<10, 1> and a scalar AND interal type is "
"integral WHEN scalar is dived "
"by unit THEN resulting value is adjusted by ratio",
"by unit THEN resulting value is not adjusted by ratio",
"[unit_t][operator/]") {
constexpr int64_t v1{1000};
constexpr unit_t<'X', std::ratio<1>, int64_t, std::deca> v2{2};

constexpr auto result = v1 / v2;
constexpr unit_t<'X', std::ratio<-1>, int64_t, std::deca> expected{5};
constexpr unit_t<'X', std::ratio<-1>, int64_t, std::deca> expected{500};
STATIC_REQUIRE(v2.value() == 2);
STATIC_REQUIRE(std::ratio_equal<std::deca, decltype(result)::ratio>::value);
STATIC_REQUIRE(result.value() == 5);
STATIC_REQUIRE(result.value() == 500);
STATIC_REQUIRE(result == expected);
}

TEST_CASE("GIVEN a unit with ratio<1, 1000> and a scalar AND interal type is "
TEST_CASE("GIVEN a unit with ratio<10, 1> and a scalar AND interal type is "
"floating point WHEN scalar is dived "
"by unit THEN resulting value is adjusted by ratio",
"by unit THEN resulting value is not adjusted by ratio",
"[unit_t][operator/]") {
constexpr long double v1{1000};
constexpr unit_t<'X', std::ratio<1>, long double, std::deca> v2{2};

constexpr auto result = v1 / v2;
constexpr unit_t<'X', std::ratio<-1>, long double, std::deca> expected{5};
constexpr unit_t<'X', std::ratio<-1>, long double, std::deca> expected{500};
STATIC_REQUIRE(v2.value() == 2);
STATIC_REQUIRE(std::ratio_equal<std::deca, decltype(result)::ratio>::value);
STATIC_REQUIRE(eps_equals(result.value(), 5.0L));
STATIC_REQUIRE(eps_equals(result.value(), 500.0L));
STATIC_REQUIRE(result == expected);
}

TEST_CASE("GIVEN a unit with ratio<1, 1000> and a scalar AND interal type is "
"floating point WHEN scalar is dived "
"by unit THEN resulting value is not adjusted by ratio",
"[unit_t][operator/]") {
constexpr long double v1{1000};
constexpr unit_t<'X', std::ratio<1>, long double, std::milli> v2{2};

constexpr auto result = v1 / v2;
constexpr unit_t<'X', std::ratio<-1>, long double, std::milli> expected{500};
STATIC_REQUIRE(v2.value() == 2);
STATIC_REQUIRE(std::ratio_equal<std::milli, decltype(result)::ratio>::value);
STATIC_REQUIRE(eps_equals(result.value(), 500.0L));
STATIC_REQUIRE(result == expected);
}

Expand Down

0 comments on commit bbe5246

Please sign in to comment.