mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-04 12:54:25 +02:00
implementing units::ratio_add and tests
not yet used in src/include/units/bits/dim_consolidate.h because it breaks and cascades (due to new exponent we think)
This commit is contained in:
committed by
Mateusz Pusz
parent
dfb9042e9d
commit
0566cc631d
@@ -56,7 +56,7 @@ struct dim_consolidate<exp_list<E1, ERest...>> {
|
||||
|
||||
template<BaseDimension Dim, std::intmax_t Num1, std::intmax_t Den1, std::intmax_t Num2, std::intmax_t Den2, typename... ERest>
|
||||
struct dim_consolidate<exp_list<exp<Dim, Num1, Den1>, exp<Dim, Num2, Den2>, ERest...>> {
|
||||
// TODO: provide custom implementation for ratio_add
|
||||
// TODO: we have ration_add now, but dim_consolidate etc, now need to cope with our new ratio
|
||||
using r1 = std::ratio<Num1, Den1>;
|
||||
using r2 = std::ratio<Num2, Den2>;
|
||||
using r = std::ratio_add<r1, r2>;
|
||||
|
@@ -35,13 +35,11 @@ namespace units {
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] constexpr T abs(T v) noexcept
|
||||
{
|
||||
[[nodiscard]] constexpr T abs(T v) noexcept {
|
||||
return v < 0 ? -v : v;
|
||||
}
|
||||
|
||||
constexpr std::tuple<std::intmax_t, std::intmax_t, std::intmax_t> normalize(std::intmax_t num, std::intmax_t den, std::intmax_t exp)
|
||||
{
|
||||
constexpr std::tuple<std::intmax_t, std::intmax_t, std::intmax_t> normalize(std::intmax_t num, std::intmax_t den, std::intmax_t exp) {
|
||||
std::intmax_t gcd = std::gcd(num, den);
|
||||
num = num * (den < 0 ? -1 : 1) / gcd;
|
||||
den = detail::abs(den) / gcd;
|
||||
@@ -81,13 +79,47 @@ namespace detail {
|
||||
template<intmax_t Num, intmax_t Den, intmax_t Exp>
|
||||
inline constexpr bool is_ratio<ratio<Num, Den, Exp>> = true;
|
||||
|
||||
} // namespace detail
|
||||
template<Ratio R1, Ratio R2>
|
||||
constexpr std::tuple<std::intmax_t, std::intmax_t, std::intmax_t> ratio_add_detail() {
|
||||
std::intmax_t num1 = R1::num;
|
||||
std::intmax_t num2 = R2::num;
|
||||
|
||||
// align exponents
|
||||
std::intmax_t new_exp = R1::exp;
|
||||
if constexpr (R1::exp > R2::exp) {
|
||||
new_exp = R1::exp;
|
||||
while (new_exp > R2::exp) {
|
||||
num1 *= 10;
|
||||
--new_exp;
|
||||
}
|
||||
} else if constexpr (R1::exp < R2::exp) {
|
||||
new_exp = R2::exp;
|
||||
while (R1::exp < new_exp) {
|
||||
num2 *= 10;
|
||||
--new_exp;
|
||||
}
|
||||
}
|
||||
|
||||
// common denominator
|
||||
std::intmax_t lcm_den = std::lcm(R1::den, R2::den);
|
||||
num1 = num1 * (lcm_den / R1::den);
|
||||
num2 = num2 * (lcm_den / R2::den);
|
||||
|
||||
return std::make_tuple(num1 + num2, lcm_den, new_exp);
|
||||
}
|
||||
|
||||
|
||||
template<Ratio R1, Ratio R2>
|
||||
struct ratio_add_impl {
|
||||
static constexpr auto detail = ratio_add_detail<R1, R2>();
|
||||
using type = ratio<std::get<0>(detail), std::get<1>(detail), std::get<2>(detail)>;
|
||||
};
|
||||
}// namespace detail
|
||||
|
||||
|
||||
// ratio_add
|
||||
// TODO implement ratio_add
|
||||
// template<Ratio R1, Ratio R2>
|
||||
// using ratio_add = detail::ratio_add_impl<R1, R2>::type;
|
||||
template<Ratio R1, Ratio R2>
|
||||
using ratio_add = detail::ratio_add_impl<R1, R2>::type;
|
||||
|
||||
// ratio_subtract
|
||||
// TODO implement ratio_subtract
|
||||
|
@@ -39,4 +39,5 @@ namespace {
|
||||
static_assert(std::is_same_v<decltype(sqrt(4km2)), decltype(2km)>);
|
||||
static_assert(std::is_same_v<decltype(sqrt(4ft2)), decltype(2ft)>);
|
||||
|
||||
|
||||
} // namespace
|
||||
|
@@ -76,9 +76,22 @@
|
||||
static_assert(std::is_same_v<ratio_sqrt<ratio<0>>, ratio<0>>);
|
||||
static_assert(std::is_same_v<ratio_sqrt<ratio<1, 4>>, ratio<1, 2>>);
|
||||
|
||||
// // sqrt with exponents: TODO not working yet. Also not sure the non exponent version is accurate.
|
||||
// static_assert(std::is_same_v<ratio_sqrt<ratio<9, 1, 2>>, ratio<3, 1, 1>>);
|
||||
// static_assert(std::is_same_v<ratio_sqrt<ratio<4>>, ratio<2>>);
|
||||
// sqrt with exponents
|
||||
static_assert(std::is_same_v<ratio_sqrt<ratio<9, 1, 2>>, ratio<3, 1, 1>>);
|
||||
static_assert(std::is_same_v<ratio_sqrt<ratio<4>>, ratio<2>>);
|
||||
|
||||
static_assert(std::is_same_v<units::ratio_add<units::ratio<1, 2, 0>, units::ratio<1, 3, 0>>, units::ratio<5, 6, 0>>);
|
||||
static_assert(std::is_same_v<units::ratio_add<units::ratio<1, 2, 1>, units::ratio<1, 3, 1>>, units::ratio<5, 6, 1>>);
|
||||
static_assert(std::is_same_v<units::ratio_add<units::ratio<3, 8, 2>, units::ratio<2, 7, 2>>, units::ratio<37, 56, 2>>);
|
||||
|
||||
static_assert(std::is_same_v<units::ratio_add<units::ratio<3, 8, 2>, units::ratio<2, 7, 1>>, units::ratio<226, 56, 1>>);
|
||||
static_assert(std::is_same_v<units::ratio_add<units::ratio<2, 7, 1>, units::ratio<3, 8, 2>>, units::ratio<226, 56, 1>>);
|
||||
|
||||
static_assert(std::is_same_v<units::ratio_add<units::ratio<3, 8, -2>, units::ratio<2, 7, -1>>, units::ratio<181, 56, -2>>);
|
||||
static_assert(std::is_same_v<units::ratio_add<units::ratio<2, 7, -1>, units::ratio<3, 8, -2>>, units::ratio<181, 56, -2>>);
|
||||
|
||||
|
||||
|
||||
|
||||
// common_ratio
|
||||
// note use of ::type is required because template params are changed while stamping out template
|
||||
|
Reference in New Issue
Block a user