7 #if !defined(CNL_IMPL_DUPLEX_INTEGER_DIVIDE_H)
8 #define CNL_IMPL_DUPLEX_INTEGER_DIVIDE_H
10 #include "../custom_operator/definition.h"
11 #include "../custom_operator/native_tag.h"
12 #include "../custom_operator/op.h"
13 #include "../numbers/set_signedness.h"
14 #include "../wide_integer/definition.h"
16 #include "definition.h"
18 #include "numeric_limits.h"
27 template<
typename Lhs,
typename Rhs>
28 struct heterogeneous_duplex_divide_operator {
30 std::max(digits_v<Lhs>, digits_v<Rhs>),
31 numbers::set_signedness_t<int, numbers::signedness_v<Lhs> | numbers::signedness_v<Rhs>>>>;
33 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const -> Lhs
35 return static_cast<Lhs
>(
36 static_cast<common_type
>(lhs) /
static_cast<common_type
>(rhs));
42 template<
typename Upper,
typename Lower>
43 struct custom_operator<
45 op_value<_impl::duplex_integer<Upper, Lower>>,
46 op_value<_impl::duplex_integer<Upper, Lower>>> {
48 using duplex_integer = _impl::duplex_integer<Upper, Lower>;
49 using unsigned_duplex_integer = numbers::set_signedness_t<duplex_integer, false>;
52 [[nodiscard]] constexpr
auto operator()(
53 duplex_integer
const& lhs, duplex_integer
const& rhs)
const -> duplex_integer
55 return (lhs < duplex_integer{0}) ? (rhs < duplex_integer{0})
56 ? non_negative_division(-lhs, -rhs)
57 : -non_negative_division(-lhs, rhs)
58 : (rhs < duplex_integer{0}) ? -non_negative_division(lhs, -rhs)
59 : non_negative_division(lhs, rhs);
64 static constexpr
auto non_negative_division(
65 unsigned_duplex_integer
const& dividend, unsigned_duplex_integer
const& divisor)
66 -> unsigned_duplex_integer
68 auto const high = divisor.upper();
70 return div_by_lower(dividend, divisor.lower());
74 auto quot = div_by_lower(dividend >> n, (divisor >> n).lower());
79 if ((dividend - quot * divisor) >= divisor) {
86 static constexpr
auto fls(Upper n) ->
int
93 auto const msd = Upper{1} << (half_digits - 1);
94 for (
int r = half_digits;; n <<= 1, r--) {
102 static constexpr
auto div_by_lower(
103 unsigned_duplex_integer
const& dividend, Lower
const& divisor)
104 -> unsigned_duplex_integer
106 unsigned_duplex_integer rem = dividend;
107 unsigned_duplex_integer b = divisor;
108 unsigned_duplex_integer d = 1;
110 using unsigned_upper = numbers::set_signedness_t<Upper, false>;
111 auto high = rem.upper();
113 unsigned_duplex_integer quot = 0;
114 if (
static_cast<unsigned_upper
>(high) >= divisor) {
116 quot = unsigned_duplex_integer{high, 0};
117 rem -= unsigned_duplex_integer(high * divisor, 0);
138 template<
typename LhsUpper,
typename LhsLower,
typename RhsUpper,
typename RhsLower>
139 struct custom_operator<
141 op_value<_impl::duplex_integer<LhsUpper, LhsLower>>,
142 op_value<_impl::duplex_integer<RhsUpper, RhsLower>>>
143 : _impl::heterogeneous_duplex_divide_operator<
144 _impl::duplex_integer<LhsUpper, LhsLower>,
145 _impl::duplex_integer<RhsUpper, RhsLower>> {
148 template<
typename Lhs,
typename RhsUpper,
typename RhsLower>
149 struct custom_operator<
152 op_value<_impl::duplex_integer<RhsUpper, RhsLower>>>
153 : _impl::heterogeneous_duplex_divide_operator<
154 Lhs, _impl::duplex_integer<RhsUpper, RhsLower>> {
157 template<
typename LhsUpper,
typename LhsLower,
typename Rhs>
158 struct custom_operator<
160 op_value<_impl::duplex_integer<LhsUpper, LhsLower>>,
162 : _impl::heterogeneous_duplex_divide_operator<
163 _impl::duplex_integer<LhsUpper, LhsLower>, Rhs> {
167 #endif // CNL_IMPL_DUPLEX_INTEGER_DIVIDE_H