mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-03 20:34:26 +02:00
feat: scaled_unit
symbol printing improved ([]
around the entire unit, small magnitude values do not use a power of 10
anymore)
This commit is contained in:
@@ -234,8 +234,6 @@ template<auto M>
|
|||||||
template<auto M>
|
template<auto M>
|
||||||
[[nodiscard]] consteval auto remove_positive_power(magnitude<M> m);
|
[[nodiscard]] consteval auto remove_positive_power(magnitude<M> m);
|
||||||
|
|
||||||
inline constexpr symbol_text base_multiplier(u8"× 10", "x 10");
|
|
||||||
|
|
||||||
template<std::intmax_t Base, std::intmax_t Pow>
|
template<std::intmax_t Base, std::intmax_t Pow>
|
||||||
requires detail::gt_zero<Base>
|
requires detail::gt_zero<Base>
|
||||||
[[nodiscard]] consteval Magnitude auto mag_power_lazy();
|
[[nodiscard]] consteval Magnitude auto mag_power_lazy();
|
||||||
@@ -316,6 +314,31 @@ struct magnitude_base<magnitude<H, T...>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<auto num_value, auto den_value>
|
||||||
|
[[nodiscard]] consteval auto ratio_txt()
|
||||||
|
{
|
||||||
|
if constexpr (den_value == 1)
|
||||||
|
return detail::regular<num_value>();
|
||||||
|
else
|
||||||
|
return detail::regular<num_value>() + symbol_text("/") + detail::regular<den_value>();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<auto num, auto den, auto exp10>
|
||||||
|
[[nodiscard]] consteval auto magnitude_text_impl()
|
||||||
|
{
|
||||||
|
constexpr auto num_value = get_value<std::intmax_t>(num);
|
||||||
|
constexpr auto den_value = get_value<std::intmax_t>(den);
|
||||||
|
|
||||||
|
if constexpr (num_value == 1 && den_value == 1 && exp10 != 0) {
|
||||||
|
return symbol_text("10") + detail::superscript<exp10>();
|
||||||
|
} else {
|
||||||
|
if constexpr (exp10 == 0)
|
||||||
|
return ratio_txt<num_value, den_value>();
|
||||||
|
else
|
||||||
|
return ratio_txt<num_value, den_value>() + symbol_text(u8" × 10", " x 10") + detail::superscript<exp10>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
@@ -426,37 +449,28 @@ private:
|
|||||||
|
|
||||||
[[nodiscard]] friend consteval auto _magnitude_text(magnitude)
|
[[nodiscard]] friend consteval auto _magnitude_text(magnitude)
|
||||||
{
|
{
|
||||||
constexpr auto exp10 = _extract_power_of_10(magnitude{});
|
if constexpr (magnitude{} == magnitude<1>{}) {
|
||||||
|
|
||||||
constexpr Magnitude auto base = magnitude{} / detail::mag_power_lazy<10, exp10>();
|
|
||||||
constexpr Magnitude auto num = _numerator(base);
|
|
||||||
constexpr Magnitude auto den = _denominator(base);
|
|
||||||
// TODO address the below
|
|
||||||
static_assert(base == num / den, "Printing rational powers, or irrational bases, not yet supported");
|
|
||||||
|
|
||||||
constexpr auto num_value = get_value<std::intmax_t>(num);
|
|
||||||
constexpr auto den_value = get_value<std::intmax_t>(den);
|
|
||||||
|
|
||||||
if constexpr (num_value == 1 && den_value == 1 && exp10 != 0) {
|
|
||||||
return detail::base_multiplier + detail::superscript<exp10>();
|
|
||||||
} else if constexpr (num_value != 1 || den_value != 1 || exp10 != 0) {
|
|
||||||
auto txt = symbol_text("[") + detail::regular<num_value>();
|
|
||||||
if constexpr (den_value == 1) {
|
|
||||||
if constexpr (exp10 == 0) {
|
|
||||||
return txt + symbol_text("]");
|
|
||||||
} else {
|
|
||||||
return txt + symbol_text(" ") + detail::base_multiplier + detail::superscript<exp10>() + symbol_text("]");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if constexpr (exp10 == 0) {
|
|
||||||
return txt + symbol_text("/") + detail::regular<den_value>() + symbol_text("]");
|
|
||||||
} else {
|
|
||||||
return txt + symbol_text("/") + detail::regular<den_value>() + symbol_text(" ") + detail::base_multiplier +
|
|
||||||
detail::superscript<exp10>() + symbol_text("]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return symbol_text("");
|
return symbol_text("");
|
||||||
|
} else {
|
||||||
|
constexpr auto exp10 = _extract_power_of_10(magnitude{});
|
||||||
|
if constexpr (detail::abs(exp10) < 3) {
|
||||||
|
// print the value as a regular number (without exponent)
|
||||||
|
constexpr Magnitude auto num = _numerator(magnitude{});
|
||||||
|
constexpr Magnitude auto den = _denominator(magnitude{});
|
||||||
|
// TODO address the below
|
||||||
|
static_assert(magnitude{} == num / den, "Printing rational powers, or irrational bases, not yet supported");
|
||||||
|
return detail::magnitude_text_impl<num, den, 0>();
|
||||||
|
} else {
|
||||||
|
// print the value as a number with exponent
|
||||||
|
// if user wanted a regular number for this magnitude then probably a better scaled unit should be used
|
||||||
|
constexpr Magnitude auto base = magnitude{} / detail::mag_power_lazy<10, exp10>();
|
||||||
|
constexpr Magnitude auto num = _numerator(base);
|
||||||
|
constexpr Magnitude auto den = _denominator(base);
|
||||||
|
|
||||||
|
// TODO address the below
|
||||||
|
static_assert(base == num / den, "Printing rational powers, or irrational bases, not yet supported");
|
||||||
|
return detail::magnitude_text_impl<num, den, exp10>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -830,16 +830,13 @@ template<typename CharT, std::output_iterator<CharT> Out, auto M, typename U>
|
|||||||
constexpr Out unit_symbol_impl(Out out, const scaled_unit_impl<M, U>& u, const unit_symbol_formatting& fmt,
|
constexpr Out unit_symbol_impl(Out out, const scaled_unit_impl<M, U>& u, const unit_symbol_formatting& fmt,
|
||||||
bool negative_power)
|
bool negative_power)
|
||||||
{
|
{
|
||||||
if constexpr (M == mag<1>) {
|
*out++ = '[';
|
||||||
// no ratio/prefix
|
constexpr auto mag_txt = _magnitude_text(M);
|
||||||
return unit_symbol_impl<CharT>(out, u.reference_unit, fmt, negative_power);
|
out = copy<CharT>(mag_txt, fmt.encoding, out);
|
||||||
} else {
|
if constexpr (space_before_unit_symbol<scaled_unit<M, U>::reference_unit>) *out++ = ' ';
|
||||||
constexpr auto mag_txt = _magnitude_text(M);
|
unit_symbol_impl<CharT>(out, u.reference_unit, fmt, negative_power);
|
||||||
out = copy<CharT>(mag_txt, fmt.encoding, out);
|
*out++ = ']';
|
||||||
|
return out;
|
||||||
if constexpr (space_before_unit_symbol<scaled_unit<M, U>::reference_unit>) *out++ = ' ';
|
|
||||||
return unit_symbol_impl<CharT>(out, u.reference_unit, fmt, negative_power);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Us, Unit U>
|
template<typename... Us, Unit U>
|
||||||
|
@@ -110,19 +110,29 @@ static_assert(unit_symbol(zebi<bit>) == "Zibit");
|
|||||||
static_assert(unit_symbol(yobi<bit>) == "Yibit");
|
static_assert(unit_symbol(yobi<bit>) == "Yibit");
|
||||||
|
|
||||||
// scaled units
|
// scaled units
|
||||||
static_assert(unit_symbol(mag<100> * metre) == "× 10² m");
|
static_assert(unit_symbol(mag<100> * metre) == "[100 m]");
|
||||||
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<100> * metre) == "x 10^2 m");
|
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<100> * metre) == "[100 m]");
|
||||||
static_assert(unit_symbol(mag<60> * second) == "[6 × 10¹] s");
|
static_assert(unit_symbol(mag<1000> * metre) == "[10³ m]");
|
||||||
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<60> * second) == "[6 x 10^1] s");
|
static_assert(unit_symbol(mag_power<10, 3> * metre) == "[10³ m]");
|
||||||
static_assert(unit_symbol(mag_ratio<1, 18> * metre / second) == "[1/18] m/s");
|
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<1000> * metre) == "[10^3 m]");
|
||||||
|
static_assert(unit_symbol(mag<6000> * metre) == "[6 × 10³ m]");
|
||||||
|
static_assert(unit_symbol(mag<6> * mag_power<10, 3> * metre) == "[6 × 10³ m]");
|
||||||
|
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<6000> * metre) == "[6 x 10^3 m]");
|
||||||
|
static_assert(unit_symbol(mag<10600> * metre) == "[10600 m]");
|
||||||
|
static_assert(unit_symbol(mag<60> * second) == "[60 s]");
|
||||||
|
static_assert(unit_symbol(mag_ratio<1, 18> * metre / second) == "[1/18 m/s]");
|
||||||
|
static_assert(unit_symbol(mag_ratio<1, 1800> * metre / second) == "[1/1800 m/s]");
|
||||||
|
static_assert(unit_symbol(mag_ratio<1, 18000> * metre / second) == "[1/18 × 10⁻³ m/s]");
|
||||||
|
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag_ratio<1, 18000> * metre / second) ==
|
||||||
|
"[1/18 x 10^-3 m/s]");
|
||||||
|
|
||||||
// common units
|
// common units
|
||||||
static_assert(unit_symbol(get_common_unit(kilo<metre>, mile)) == "EQUIV{[1/25146] mi, [1/15625] km}");
|
static_assert(unit_symbol(get_common_unit(kilo<metre>, mile)) == "EQUIV{[1/25146 mi], [1/15625 km]}");
|
||||||
static_assert(unit_symbol(get_common_unit(kilo<metre> / hour, metre / second)) == "EQUIV{[1/5] km/h, [1/18] m/s}");
|
static_assert(unit_symbol(get_common_unit(kilo<metre> / hour, metre / second)) == "EQUIV{[1/5 km/h], [1/18 m/s]}");
|
||||||
static_assert(unit_symbol(get_common_unit(kilo<metre> / hour, metre / second) / second) ==
|
static_assert(unit_symbol(get_common_unit(kilo<metre> / hour, metre / second) / second) ==
|
||||||
"EQUIV{[1/5] km/h, [1/18] m/s}/s");
|
"EQUIV{[1/5 km/h], [1/18 m/s]}/s");
|
||||||
static_assert(unit_symbol(get_common_unit(kilo<metre> / hour, metre / second) * second) ==
|
static_assert(unit_symbol(get_common_unit(kilo<metre> / hour, metre / second) * second) ==
|
||||||
"EQUIV{[1/5] km/h, [1/18] m/s} s");
|
"EQUIV{[1/5 km/h], [1/18 m/s]} s");
|
||||||
|
|
||||||
// derived units
|
// derived units
|
||||||
static_assert(unit_symbol(one) == ""); // NOLINT(readability-container-size-empty)
|
static_assert(unit_symbol(one) == ""); // NOLINT(readability-container-size-empty)
|
||||||
|
Reference in New Issue
Block a user