mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-01 19:34:29 +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>
|
||||
[[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>
|
||||
requires detail::gt_zero<Base>
|
||||
[[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
|
||||
|
||||
|
||||
@@ -426,37 +449,28 @@ private:
|
||||
|
||||
[[nodiscard]] friend consteval auto _magnitude_text(magnitude)
|
||||
{
|
||||
constexpr auto exp10 = _extract_power_of_10(magnitude{});
|
||||
|
||||
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 {
|
||||
if constexpr (magnitude{} == magnitude<1>{}) {
|
||||
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,
|
||||
bool negative_power)
|
||||
{
|
||||
if constexpr (M == mag<1>) {
|
||||
// no ratio/prefix
|
||||
return unit_symbol_impl<CharT>(out, u.reference_unit, fmt, negative_power);
|
||||
} else {
|
||||
constexpr auto mag_txt = _magnitude_text(M);
|
||||
out = copy<CharT>(mag_txt, fmt.encoding, 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);
|
||||
}
|
||||
*out++ = '[';
|
||||
constexpr auto mag_txt = _magnitude_text(M);
|
||||
out = copy<CharT>(mag_txt, fmt.encoding, out);
|
||||
if constexpr (space_before_unit_symbol<scaled_unit<M, U>::reference_unit>) *out++ = ' ';
|
||||
unit_symbol_impl<CharT>(out, u.reference_unit, fmt, negative_power);
|
||||
*out++ = ']';
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename... Us, Unit U>
|
||||
|
@@ -110,19 +110,29 @@ static_assert(unit_symbol(zebi<bit>) == "Zibit");
|
||||
static_assert(unit_symbol(yobi<bit>) == "Yibit");
|
||||
|
||||
// scaled units
|
||||
static_assert(unit_symbol(mag<100> * metre) == "× 10² m");
|
||||
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<100> * metre) == "x 10^2 m");
|
||||
static_assert(unit_symbol(mag<60> * second) == "[6 × 10¹] s");
|
||||
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<60> * second) == "[6 x 10^1] s");
|
||||
static_assert(unit_symbol(mag_ratio<1, 18> * metre / second) == "[1/18] m/s");
|
||||
static_assert(unit_symbol(mag<100> * metre) == "[100 m]");
|
||||
static_assert(unit_symbol<unit_symbol_formatting{.encoding = ascii}>(mag<100> * metre) == "[100 m]");
|
||||
static_assert(unit_symbol(mag<1000> * metre) == "[10³ m]");
|
||||
static_assert(unit_symbol(mag_power<10, 3> * metre) == "[10³ m]");
|
||||
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
|
||||
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>, 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) / 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) ==
|
||||
"EQUIV{[1/5] km/h, [1/18] m/s} s");
|
||||
"EQUIV{[1/5 km/h], [1/18 m/s]} s");
|
||||
|
||||
// derived units
|
||||
static_assert(unit_symbol(one) == ""); // NOLINT(readability-container-size-empty)
|
||||
|
Reference in New Issue
Block a user