7 #if !defined(CNL_IMPL_SCALED_CONVERT_OPERATOR_H)
8 #define CNL_IMPL_SCALED_CONVERT_OPERATOR_H
10 #include "../../fraction.h"
11 #include "../../integer.h"
12 #include "../custom_operator/native_tag.h"
13 #include "../num_traits/fixed_width_scale.h"
14 #include "../num_traits/scale.h"
15 #include "../power_value.h"
16 #include "../scaled_integer/definition.h"
17 #include "is_same_tag_family.h"
25 template<
integer Src,
int SrcExponent, std::
floating_po
int Dest,
int DestExponent,
int Radix>
26 struct custom_operator<
28 op_value<Src, power<SrcExponent, Radix>>,
29 op_value<Dest, power<DestExponent, Radix>>> {
30 [[nodiscard]] constexpr
auto operator()(Src
const& from)
const
32 return Dest(from) * _impl::power_value<Dest, SrcExponent - DestExponent, Radix>();
37 template<std::
floating_po
int Input,
int SrcExponent,
integer Result,
int DestExponent,
int Radix>
38 struct custom_operator<
40 op_value<Input, power<SrcExponent, Radix>>,
41 op_value<Result, power<DestExponent, Radix>>> {
42 [[nodiscard]] constexpr
auto operator()(Input
const& from)
const
44 return static_cast<Result
>(
45 from * _impl::power_value<Input, SrcExponent - DestExponent, Radix>());
50 template<
integer Input,
int SrcExponent,
integer Result,
int DestExponent,
int Radix>
51 struct custom_operator<
53 op_value<Input, power<SrcExponent, Radix>>, op_value<Result, power<DestExponent, Radix>>> {
54 [[nodiscard]] constexpr
auto operator()(Input
const& from)
const
57 return static_cast<Result
>(_impl::scale<SrcExponent - DestExponent, Radix>(
58 _impl::from_value<Result>(from)));
64 integer Input,
int SrcExponent,
int SrcRadix,
65 integer Result,
int DestExponent,
int DestRadix>
66 struct custom_operator<
68 op_value<Input, power<SrcExponent, SrcRadix>>,
69 op_value<Result, power<DestExponent, DestRadix>>> {
70 [[nodiscard]] constexpr
auto operator()(Input
const& from)
const
72 auto result{_impl::from_value<Result>(from)};
73 if constexpr (SrcExponent > 0) {
74 result = _impl::scale<SrcExponent, SrcRadix>(result);
76 if constexpr (DestExponent < 0) {
77 result = _impl::scale<-DestExponent, DestRadix>(result);
79 if constexpr (SrcExponent < 0) {
80 result = _impl::scale<SrcExponent, SrcRadix>(result);
82 if constexpr (DestExponent > 0) {
83 result = _impl::scale<-DestExponent, DestRadix>(result);
90 template<
typename Input,
typename Result,
int DestExponent,
int DestRadix>
91 struct custom_operator<_impl::convert_op, op_value<Input>, op_value<Result, power<DestExponent, DestRadix>>>
94 op_value<Input, power<0, DestRadix>>,
95 op_value<Result, power<DestExponent, DestRadix>>> {
98 template<
typename Input,
int SrcExponent,
int SrcRadix,
typename Result>
99 struct custom_operator<_impl::convert_op, op_value<Input, power<SrcExponent, SrcRadix>>, op_value<Result>>
100 : custom_operator<_impl::convert_op, op_value<Input, power<SrcExponent, SrcRadix>>, op_value<Result, power<0, SrcRadix>>> {
107 template<
typename Number>
108 [[nodiscard]] constexpr
auto not_scaled_integer(Number
const& n)
113 template<
typename Rep,
int Exponent,
int Radix>
114 [[nodiscard]] constexpr
auto not_scaled_integer(
117 return _impl::to_rep(f);
120 template<
typename Number>
121 struct exponent : constant<0> {
124 template<
typename Rep,
int Exponent,
int Radix>
125 struct exponent<
scaled_integer<Rep, power<Exponent, Radix>>> : constant<Exponent> {
128 template<
class Quotient,
class Div
idend,
class Divisor>
129 struct exponent_shift
131 int, _impl::exponent<Dividend>::value - _impl::exponent<Divisor>::value
132 - _impl::exponent<Quotient>::value> {
137 typename SrcNumerator,
typename SrcDenominator,
138 typename Dest,
int DestExponent,
int Radix>
139 struct custom_operator<
141 op_value<cnl::fraction<SrcNumerator, SrcDenominator>, cnl::power<0, Radix>>,
142 op_value<Dest, cnl::power<DestExponent, Radix>>> {
143 [[nodiscard]] constexpr
auto operator()(
146 static_assert(_impl::exponent<Dest>::value == 0,
"TODO");
148 return static_cast<Dest
>(
149 _impl::fixed_width_scale<
150 _impl::exponent<SrcNumerator>::value
151 - _impl::exponent<SrcDenominator>::value - DestExponent,
152 Radix>(
static_cast<Dest
>(_impl::not_scaled_integer(from.numerator)))
153 / _impl::not_scaled_integer(from.denominator));
158 #endif // CNL_IMPL_SCALED_CONVERT_OPERATOR_H