7 #if !defined(CNL_IMPL_SCALED_INTEGER_TAGGED_CONVERT_OPERATOR_H)
8 #define CNL_IMPL_SCALED_INTEGER_TAGGED_CONVERT_OPERATOR_H
10 #include "../../integer.h"
11 #include "../overflow/overflow_operator.h"
12 #include "../power_value.h"
13 #include "../rounding/native_rounding_tag.h"
14 #include "../rounding/nearest_rounding_tag.h"
15 #include "../rounding/neg_inf_rounding_tag.h"
16 #include "../rounding/tie_to_pos_inf_rounding_tag.h"
17 #include "../scaled/is_scaled_tag.h"
18 #include "definition.h"
28 template<
typename Input,
typename Result,
int Radix>
31 op_value<Input, nearest_rounding_tag>,
35 op_value<Input, power<0, Radix>>,
36 op_value<Result, nearest_rounding_tag>> {
42 typename InputRep,
int InputExponent,
43 typename ResultRep,
int ResultExponent,
47 op_value<scaled_integer<InputRep, power<InputExponent, Radix>>, power<0, Radix>>,
48 op_value<scaled_integer<ResultRep, power<ResultExponent, Radix>>, nearest_rounding_tag>> {
53 [[nodiscard]]
static constexpr
auto half()
55 return static_cast<input
>(_impl::from_rep<result>(1)) / 2;
59 [[nodiscard]] constexpr
auto operator()(input
const& from)
const
62 return static_cast<result
>(from + ((from >= 0) ? half() : -half()));
68 typename InputRep,
int InputExponent,
69 typename ResultRep,
int ResultExponent,
71 requires(ResultExponent <= InputExponent)
struct custom_operator<
73 op_value<scaled_integer<InputRep, power<InputExponent, Radix>>, power<0, Radix>>,
74 op_value<scaled_integer<ResultRep, power<ResultExponent, Radix>>, nearest_rounding_tag>> {
79 template<std::
floating_po
int Input,
typename ResultRep,
int ResultExponent,
int ResultRadix>
80 struct custom_operator<
82 op_value<Input, power<0, ResultRadix>>,
83 op_value<scaled_integer<ResultRep, power<ResultExponent, ResultRadix>>, nearest_rounding_tag>> {
85 using result = scaled_integer<ResultRep, power<ResultExponent, ResultRadix>>;
87 [[nodiscard]]
static constexpr
auto half()
89 return _impl::power_value<Input, ResultExponent - 1, ResultRadix>();
93 [[nodiscard]] constexpr
auto operator()(Input
const& from)
const
96 return static_cast<result
>(from + ((from >= 0) ? half() : -half()));
100 template<
integer Input,
typename ResultRep,
int ResultExponent,
int ResultRadix>
101 struct custom_operator<
103 op_value<Input, power<0, ResultRadix>>,
104 op_value<scaled_integer<ResultRep, power<ResultExponent, ResultRadix>>, nearest_rounding_tag>>
107 op_value<scaled_integer<Input>, power<0, ResultRadix>>,
108 op_value<scaled_integer<ResultRep, power<ResultExponent, ResultRadix>>, nearest_rounding_tag>> {
111 template<
typename InputRep,
int InputExponent,
int InputRadix,
integer Result>
112 struct custom_operator<
114 op_value<scaled_integer<InputRep, power<InputExponent, InputRadix>>, power<0, InputRadix>>,
115 op_value<Result, nearest_rounding_tag>> {
117 using input = scaled_integer<InputRep, power<InputExponent, InputRadix>>;
120 [[nodiscard]] constexpr
auto operator()(input
const& from)
const
122 return _impl::to_rep(custom_operator<
124 op_value<input, power<0, InputRadix>>,
125 op_value<scaled_integer<Result>, nearest_rounding_tag>>{}(from));
129 template<
typename Input,
typename ResultRep,
int ResultExponent,
int ResultRadix>
130 struct custom_operator<
132 op_value<Input, _impl::native_tag>,
133 op_value<scaled_integer<ResultRep, power<ResultExponent, ResultRadix>>, nearest_rounding_tag>> {
135 [[nodiscard]] constexpr
auto
136 operator()(Input
const& from)
const
138 return custom_operator<
140 op_value<Input, power<0, ResultRadix>>,
141 op_value<scaled_integer<ResultRep, power<ResultExponent, ResultRadix>>, nearest_rounding_tag>>{}(from);
151 typename InputRep,
int InputExponent,
152 typename ResultRep,
int ResultExponent,
154 requires(ResultExponent <= InputExponent)
struct custom_operator<
156 op_value<scaled_integer<InputRep, power<InputExponent, Radix>>, _impl::native_tag>,
157 op_value<scaled_integer<ResultRep, power<ResultExponent, Radix>>, tie_to_pos_inf_rounding_tag>>
160 op_value<scaled_integer<InputRep, power<InputExponent, Radix>>, _impl::native_tag>,
161 op_value<scaled_integer<ResultRep, power<ResultExponent, Radix>>, native_rounding_tag>> {
166 typename InputRep,
int InputExponent,
167 typename ResultRep,
int ResultExponent,
169 requires(!(ResultExponent <= InputExponent))
struct custom_operator<
171 op_value<scaled_integer<InputRep, power<InputExponent, Radix>>, _impl::native_tag>,
172 op_value<scaled_integer<ResultRep, power<ResultExponent, Radix>>, tie_to_pos_inf_rounding_tag>> {
174 using result = scaled_integer<ResultRep, power<ResultExponent, Radix>>;
175 using input = scaled_integer<InputRep, power<InputExponent, Radix>>;
177 [[nodiscard]]
static constexpr
auto half()
179 return static_cast<input
>(_impl::from_rep<result>(1)) / 2;
183 [[nodiscard]] constexpr
auto operator()(input
const& from)
const -> result
186 return _impl::from_rep<result>(
187 _impl::to_rep(from + half()) >> (ResultExponent - InputExponent));
194 std::floating_point Input,
195 typename ResultRep,
int ResultExponent,
int ResultRadix>
199 op_value<scaled_integer<ResultRep, power<ResultExponent, ResultRadix>>, tie_to_pos_inf_rounding_tag>> {
203 [[nodiscard]]
static constexpr
auto half()
205 return _impl::power_value<Input, ResultExponent - 1, ResultRadix>();
209 [[nodiscard]] constexpr
auto operator()(Input
const& from)
const
212 return static_cast<result
>(from + half());
216 template<
integer Input,
integer ResultRep, scaled_tag ResultScale>
220 op_value<scaled_integer<ResultRep, ResultScale>, tie_to_pos_inf_rounding_tag>>
223 op_value<scaled_integer<Input>, _impl::native_tag>,
224 op_value<scaled_integer<ResultRep, ResultScale>, tie_to_pos_inf_rounding_tag>> {
227 template<
integer InputRep, scaled_tag InputScale,
integer Result>
228 struct custom_operator<
230 op_value<scaled_integer<InputRep, InputScale>, _impl::native_tag>,
231 op_value<Result, tie_to_pos_inf_rounding_tag>> {
233 using input = scaled_integer<InputRep, InputScale>;
236 [[nodiscard]] constexpr
auto operator()(input
const& from)
const
238 return _impl::to_rep(custom_operator<
240 op_value<input, _impl::native_tag>,
241 op_value<scaled_integer<Result>, tie_to_pos_inf_rounding_tag>>{}(from));
251 typename InputRep,
int InputExponent,
252 typename ResultRep,
int ResultExponent,
254 requires(ResultExponent <= InputExponent)
struct custom_operator<
256 op_value<scaled_integer<InputRep, power<InputExponent, Radix>>, _impl::native_tag>,
257 op_value<scaled_integer<ResultRep, power<ResultExponent, Radix>>, neg_inf_rounding_tag>>
260 op_value<scaled_integer<InputRep, power<InputExponent, Radix>>, _impl::native_tag>,
261 op_value<scaled_integer<ResultRep, power<ResultExponent, Radix>>, native_rounding_tag>> {
266 typename InputRep,
int InputExponent,
267 typename ResultRep,
int ResultExponent,
269 requires(!(ResultExponent <= InputExponent))
struct custom_operator<
271 op_value<scaled_integer<InputRep, power<InputExponent, Radix>>, _impl::native_tag>,
272 op_value<scaled_integer<ResultRep, power<ResultExponent, Radix>>, neg_inf_rounding_tag>> {
274 using result = scaled_integer<ResultRep, power<ResultExponent, Radix>>;
275 using input = scaled_integer<InputRep, power<InputExponent, Radix>>;
278 [[nodiscard]] constexpr
auto operator()(input
const& from)
const
281 return _impl::from_rep<result>(
282 _impl::to_rep(from) >> (ResultExponent - InputExponent));
289 std::floating_point Input,
290 typename ResultRep,
int ResultExponent,
int ResultRadix>
294 op_value<scaled_integer<ResultRep, power<ResultExponent, ResultRadix>>, neg_inf_rounding_tag>> {
299 [[nodiscard]] constexpr
auto operator()(Input
const& from)
const
302 return static_cast<result
>(from);
306 template<
integer Input,
integer ResultRep, scaled_tag ResultScale>
310 op_value<scaled_integer<ResultRep, ResultScale>, neg_inf_rounding_tag>>
313 op_value<scaled_integer<Input>, _impl::native_tag>,
314 op_value<scaled_integer<ResultRep, ResultScale>, neg_inf_rounding_tag>> {
317 template<
integer InputRep, scaled_tag InputScale,
integer Result>
318 struct custom_operator<
320 op_value<scaled_integer<InputRep, InputScale>, _impl::native_tag>,
321 op_value<Result, neg_inf_rounding_tag>> {
323 using input = scaled_integer<InputRep, InputScale>;
326 [[nodiscard]] constexpr
auto operator()(input
const& from)
const -> Result
328 return _impl::to_rep(custom_operator<
330 op_value<input, _impl::native_tag>,
331 op_value<scaled_integer<Result>, neg_inf_rounding_tag>>{}(from));
336 #endif // CNL_IMPL_SCALED_INTEGER_TAGGED_CONVERT_OPERATOR_H