-
-
Notifications
You must be signed in to change notification settings - Fork 119
Fix #580 by using a fixed-point implementation for unit conversions using integer representations #615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #580 by using a fixed-point implementation for unit conversions using integer representations #615
Changes from 3 commits
cf9c05f
3635260
74f30da
2f54c76
e003a58
60c94da
d00b330
99d4315
653d3d2
ed2574f
e688ffc
55d8fd6
38dcf64
ad76149
95cc9f3
5f8eb5c
1b57404
f673619
f642d37
b6a6752
647ce6b
464ecd4
e933be7
6873c8b
65a0ee4
0c1971e
4ef0210
ef0e7b3
b777ad6
8578dab
3357a82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,7 +46,7 @@ using minimal_floating_point_type = | |
| template<typename To, typename T> | ||
| constexpr auto cast_integral(const T& value) | ||
| { | ||
| if constexpr (std::is_integral_v<T>) { | ||
| if constexpr (std::is_integral_v<value_type_t<T>>) { | ||
| return static_cast<To>(value); | ||
| } else { | ||
| return value; | ||
|
||
|
|
@@ -63,8 +63,10 @@ struct floating_point_scaling_factor_type { | |
| template<std::floating_point T> | ||
| struct floating_point_scaling_factor_type<T> : std::type_identity<T> {}; | ||
|
|
||
| // try to choose the smallest standard floating-point type which can represent the integer exactly (has at least as many | ||
| // mantiassa bits as the integer is wide) | ||
| template<std::integral T> | ||
| struct floating_point_scaling_factor_type<T> : std::common_type<T, float> {}; | ||
| struct floating_point_scaling_factor_type<T> : std::type_identity<min_digit_float_t<std::numeric_limits<T>::digits>> {}; | ||
|
|
||
| template<typename T> | ||
| requires requires { typename scaling_traits<T>::floating_point_scaling_factor_type; } | ||
|
|
@@ -74,8 +76,6 @@ struct floating_point_scaling_factor_type<T> : | |
|
|
||
| template<Magnitude auto M> | ||
| struct floating_point_scaling_impl { | ||
| static constexpr Magnitude auto num = _numerator(M); | ||
| static constexpr Magnitude auto den = _denominator(M); | ||
| template<typename T> | ||
| static constexpr T ratio = [] { | ||
| using U = long double; | ||
|
|
@@ -88,9 +88,9 @@ struct floating_point_scaling_impl { | |
| using U = minimal_floating_point_type<typename floating_point_scaling_factor_type<To>::type, | ||
| typename floating_point_scaling_factor_type<From>::type>; | ||
| if constexpr (_is_integral(M)) { | ||
| return static_cast<To>(cast_integral<U>(value) * _get_value<U>(num)); | ||
| return static_cast<To>(cast_integral<U>(value) * _get_value<U>(M)); | ||
| } else if constexpr (_is_integral(_pow<-1>(M))) { | ||
| return static_cast<To>(cast_integral<U>(value) / _get_value<U>(den)); | ||
| return static_cast<To>(cast_integral<U>(value) / _get_value<U>(_pow<-1>(M))); | ||
| } else { | ||
| return static_cast<To>(cast_integral<U>(value) * ratio<U>); | ||
| } | ||
|
|
@@ -118,7 +118,7 @@ struct floating_point_scaling_traits { | |
| static constexpr Rep scale_from(M, const From& value) | ||
| { | ||
| return floating_point_scaling_impl<M{}>::template scale<Rep>(value); | ||
| }; | ||
| } | ||
|
|
||
| template<Magnitude M> | ||
| static constexpr auto scale(M, const Rep& value) | ||
|
|
@@ -131,8 +131,6 @@ struct floating_point_scaling_traits { | |
|
|
||
| template<Magnitude auto M> | ||
| struct fixed_point_scaling_impl { | ||
| static constexpr Magnitude auto num = _numerator(M); | ||
| static constexpr Magnitude auto den = _denominator(M); | ||
| template<std::integral T> | ||
| static constexpr auto ratio = [] { | ||
| using U = long double; | ||
|
|
@@ -145,9 +143,9 @@ struct fixed_point_scaling_impl { | |
| { | ||
| using U = std::common_type_t<value_type_t<From>, value_type_t<To>>; | ||
| if constexpr (_is_integral(M)) { | ||
| return static_cast<To>(static_cast<value_type_t<From>>(value) * _get_value<U>(num)); | ||
| return static_cast<To>(static_cast<value_type_t<From>>(value) * _get_value<U>(M)); | ||
| } else if constexpr (_is_integral(_pow<-1>(M))) { | ||
| return static_cast<To>(static_cast<value_type_t<From>>(value) / _get_value<U>(den)); | ||
| return static_cast<To>(static_cast<value_type_t<From>>(value) / _get_value<U>(_pow<-1>(M))); | ||
| } else { | ||
| return static_cast<To>(ratio<U>.scale(static_cast<value_type_t<From>>(value))); | ||
| } | ||
|
|
@@ -161,7 +159,7 @@ struct fixed_point_scaling_traits { | |
| static constexpr Rep scale_from(M, const From& value) | ||
| { | ||
| return fixed_point_scaling_impl<M{}>::template scale<Rep>(value); | ||
| }; | ||
| } | ||
|
|
||
| template<Magnitude M> | ||
| static constexpr auto scale(M, const Rep& value) | ||
|
|
@@ -201,6 +199,8 @@ concept HasScalingTraits = !std::convertible_to<decltype(select_scaling_traits<T | |
|
|
||
| } // namespace detail | ||
|
|
||
| MP_UNITS_EXPORT_BEGIN | ||
|
||
|
|
||
| template<typename To, Magnitude M, typename From> | ||
| requires detail::HasScalingTraits<To, From> || | ||
| requires(const From& value) { value.scale(std::type_identity<To>{}, M{}); } | ||
|
|
@@ -226,4 +226,7 @@ constexpr auto scale(M scaling_factor, const From& value) | |
| } | ||
| } | ||
|
|
||
|
|
||
| MP_UNITS_EXPORT_END | ||
|
|
||
| } // namespace mp_units | ||
Uh oh!
There was an error while loading. Please reload this page.