1 //===-- include/flang/Common/uint128.h --------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Portable 128-bit integer arithmetic for use in impoverished C++
10 // implementations lacking __uint128_t & __int128_t.
11 
12 #ifndef FORTRAN_COMMON_UINT128_H_
13 #define FORTRAN_COMMON_UINT128_H_
14 
15 // Define AVOID_NATIVE_UINT128_T to force the use of UnsignedInt128 below
16 // instead of the C++ compiler's native 128-bit unsigned integer type, if
17 // it has one.
18 #ifndef AVOID_NATIVE_UINT128_T
19 #define AVOID_NATIVE_UINT128_T 0
20 #endif
21 
22 #include "leading-zero-bit-count.h"
23 #include <cstdint>
24 #include <type_traits>
25 
26 namespace Fortran::common {
27 
28 template <bool IS_SIGNED = false> class Int128 {
29 public:
Int128()30   constexpr Int128() {}
31   // This means of definition provides some portability for
32   // "size_t" operands.
Int128(unsigned n)33   constexpr Int128(unsigned n) : low_{n} {}
Int128(unsigned long n)34   constexpr Int128(unsigned long n) : low_{n} {}
Int128(unsigned long long n)35   constexpr Int128(unsigned long long n) : low_{n} {}
Int128(int n)36   constexpr Int128(int n)
37       : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
38                                                  n < 0)} {}
Int128(long n)39   constexpr Int128(long n)
40       : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
41                                                  n < 0)} {}
Int128(long long n)42   constexpr Int128(long long n)
43       : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
44                                                  n < 0)} {}
45   constexpr Int128(const Int128 &) = default;
46   constexpr Int128(Int128 &&) = default;
47   constexpr Int128 &operator=(const Int128 &) = default;
48   constexpr Int128 &operator=(Int128 &&) = default;
49 
Int128(const Int128<!IS_SIGNED> & n)50   explicit constexpr Int128(const Int128<!IS_SIGNED> &n)
51       : low_{n.low()}, high_{n.high()} {}
Int128(Int128<!IS_SIGNED> && n)52   explicit constexpr Int128(Int128<!IS_SIGNED> &&n)
53       : low_{n.low()}, high_{n.high()} {}
54 
55   constexpr Int128 operator+() const { return *this; }
56   constexpr Int128 operator~() const { return {~high_, ~low_}; }
57   constexpr Int128 operator-() const { return ~*this + 1; }
58   constexpr bool operator!() const { return !low_ && !high_; }
59   constexpr explicit operator bool() const { return low_ || high_; }
uint64_t()60   constexpr explicit operator std::uint64_t() const { return low_; }
int64_t()61   constexpr explicit operator std::int64_t() const { return low_; }
62   constexpr explicit operator int() const { return static_cast<int>(low_); }
63 
high()64   constexpr std::uint64_t high() const { return high_; }
low()65   constexpr std::uint64_t low() const { return low_; }
66 
67   constexpr Int128 operator++(/*prefix*/) {
68     *this += 1;
69     return *this;
70   }
71   constexpr Int128 operator++(int /*postfix*/) {
72     Int128 result{*this};
73     *this += 1;
74     return result;
75   }
76   constexpr Int128 operator--(/*prefix*/) {
77     *this -= 1;
78     return *this;
79   }
80   constexpr Int128 operator--(int /*postfix*/) {
81     Int128 result{*this};
82     *this -= 1;
83     return result;
84   }
85 
86   constexpr Int128 operator&(Int128 that) const {
87     return {high_ & that.high_, low_ & that.low_};
88   }
89   constexpr Int128 operator|(Int128 that) const {
90     return {high_ | that.high_, low_ | that.low_};
91   }
92   constexpr Int128 operator^(Int128 that) const {
93     return {high_ ^ that.high_, low_ ^ that.low_};
94   }
95 
96   constexpr Int128 operator<<(Int128 that) const {
97     if (that >= 128) {
98       return {};
99     } else if (that == 0) {
100       return *this;
101     } else {
102       std::uint64_t n{that.low_};
103       if (n >= 64) {
104         return {low_ << (n - 64), 0};
105       } else {
106         return {(high_ << n) | (low_ >> (64 - n)), low_ << n};
107       }
108     }
109   }
110   constexpr Int128 operator>>(Int128 that) const {
111     if (that >= 128) {
112       return {};
113     } else if (that == 0) {
114       return *this;
115     } else {
116       std::uint64_t n{that.low_};
117       if (n >= 64) {
118         return {0, high_ >> (n - 64)};
119       } else {
120         return {high_ >> n, (high_ << (64 - n)) | (low_ >> n)};
121       }
122     }
123   }
124 
125   constexpr Int128 operator+(Int128 that) const {
126     std::uint64_t lower{(low_ & ~topBit) + (that.low_ & ~topBit)};
127     bool carry{((lower >> 63) + (low_ >> 63) + (that.low_ >> 63)) > 1};
128     return {high_ + that.high_ + carry, low_ + that.low_};
129   }
130   constexpr Int128 operator-(Int128 that) const { return *this + -that; }
131 
132   constexpr Int128 operator*(Int128 that) const {
133     std::uint64_t mask32{0xffffffff};
134     if (high_ == 0 && that.high_ == 0) {
135       std::uint64_t x0{low_ & mask32}, x1{low_ >> 32};
136       std::uint64_t y0{that.low_ & mask32}, y1{that.low_ >> 32};
137       Int128 x0y0{x0 * y0}, x0y1{x0 * y1};
138       Int128 x1y0{x1 * y0}, x1y1{x1 * y1};
139       return x0y0 + ((x0y1 + x1y0) << 32) + (x1y1 << 64);
140     } else {
141       std::uint64_t x0{low_ & mask32}, x1{low_ >> 32}, x2{high_ & mask32},
142           x3{high_ >> 32};
143       std::uint64_t y0{that.low_ & mask32}, y1{that.low_ >> 32},
144           y2{that.high_ & mask32}, y3{that.high_ >> 32};
145       Int128 x0y0{x0 * y0}, x0y1{x0 * y1}, x0y2{x0 * y2}, x0y3{x0 * y3};
146       Int128 x1y0{x1 * y0}, x1y1{x1 * y1}, x1y2{x1 * y2};
147       Int128 x2y0{x2 * y0}, x2y1{x2 * y1};
148       Int128 x3y0{x3 * y0};
149       return x0y0 + ((x0y1 + x1y0) << 32) + ((x0y2 + x1y1 + x2y0) << 64) +
150           ((x0y3 + x1y2 + x2y1 + x3y0) << 96);
151     }
152   }
153 
154   constexpr Int128 operator/(Int128 that) const {
155     int j{LeadingZeroes()};
156     Int128 bits{*this};
157     bits <<= j;
158     Int128 numerator{};
159     Int128 quotient{};
160     for (; j < 128; ++j) {
161       numerator <<= 1;
162       if (bits.high_ & topBit) {
163         numerator.low_ |= 1;
164       }
165       bits <<= 1;
166       quotient <<= 1;
167       if (numerator >= that) {
168         ++quotient;
169         numerator -= that;
170       }
171     }
172     return quotient;
173   }
174 
175   constexpr Int128 operator%(Int128 that) const {
176     int j{LeadingZeroes()};
177     Int128 bits{*this};
178     bits <<= j;
179     Int128 remainder{};
180     for (; j < 128; ++j) {
181       remainder <<= 1;
182       if (bits.high_ & topBit) {
183         remainder.low_ |= 1;
184       }
185       bits <<= 1;
186       if (remainder >= that) {
187         remainder -= that;
188       }
189     }
190     return remainder;
191   }
192 
193   constexpr bool operator<(Int128 that) const {
194     if (IS_SIGNED && (high_ ^ that.high_) & topBit) {
195       return (high_ & topBit) != 0;
196     }
197     return high_ < that.high_ || (high_ == that.high_ && low_ < that.low_);
198   }
199   constexpr bool operator<=(Int128 that) const { return !(*this > that); }
200   constexpr bool operator==(Int128 that) const {
201     return low_ == that.low_ && high_ == that.high_;
202   }
203   constexpr bool operator!=(Int128 that) const { return !(*this == that); }
204   constexpr bool operator>=(Int128 that) const { return that <= *this; }
205   constexpr bool operator>(Int128 that) const { return that < *this; }
206 
207   constexpr Int128 &operator&=(const Int128 &that) {
208     *this = *this & that;
209     return *this;
210   }
211   constexpr Int128 &operator|=(const Int128 &that) {
212     *this = *this | that;
213     return *this;
214   }
215   constexpr Int128 &operator^=(const Int128 &that) {
216     *this = *this ^ that;
217     return *this;
218   }
219   constexpr Int128 &operator<<=(const Int128 &that) {
220     *this = *this << that;
221     return *this;
222   }
223   constexpr Int128 &operator>>=(const Int128 &that) {
224     *this = *this >> that;
225     return *this;
226   }
227   constexpr Int128 &operator+=(const Int128 &that) {
228     *this = *this + that;
229     return *this;
230   }
231   constexpr Int128 &operator-=(const Int128 &that) {
232     *this = *this - that;
233     return *this;
234   }
235   constexpr Int128 &operator*=(const Int128 &that) {
236     *this = *this * that;
237     return *this;
238   }
239   constexpr Int128 &operator/=(const Int128 &that) {
240     *this = *this / that;
241     return *this;
242   }
243   constexpr Int128 &operator%=(const Int128 &that) {
244     *this = *this % that;
245     return *this;
246   }
247 
248 private:
Int128(std::uint64_t hi,std::uint64_t lo)249   constexpr Int128(std::uint64_t hi, std::uint64_t lo) : low_{lo}, high_{hi} {}
LeadingZeroes()250   constexpr int LeadingZeroes() const {
251     if (high_ == 0) {
252       return 64 + LeadingZeroBitCount(low_);
253     } else {
254       return LeadingZeroBitCount(high_);
255     }
256   }
257   static constexpr std::uint64_t topBit{std::uint64_t{1} << 63};
258   std::uint64_t low_{0}, high_{0};
259 };
260 
261 using UnsignedInt128 = Int128<false>;
262 using SignedInt128 = Int128<true>;
263 
264 #if !AVOID_NATIVE_UINT128_t && (defined __GNUC__ || defined __clang__) && \
265     defined __SIZEOF_INT128__
266 using uint128_t = __uint128_t;
267 using int128_t = __int128_t;
268 #else
269 using uint128_t = UnsignedInt128;
270 using int128_t = SignedInt128;
271 #endif
272 
273 template <int BITS> struct HostUnsignedIntTypeHelper {
274   using type = std::conditional_t<(BITS <= 8), std::uint8_t,
275       std::conditional_t<(BITS <= 16), std::uint16_t,
276           std::conditional_t<(BITS <= 32), std::uint32_t,
277               std::conditional_t<(BITS <= 64), std::uint64_t, uint128_t>>>>;
278 };
279 template <int BITS> struct HostSignedIntTypeHelper {
280   using type = std::conditional_t<(BITS <= 8), std::int8_t,
281       std::conditional_t<(BITS <= 16), std::int16_t,
282           std::conditional_t<(BITS <= 32), std::int32_t,
283               std::conditional_t<(BITS <= 64), std::int64_t, int128_t>>>>;
284 };
285 template <int BITS>
286 using HostUnsignedIntType = typename HostUnsignedIntTypeHelper<BITS>::type;
287 template <int BITS>
288 using HostSignedIntType = typename HostSignedIntTypeHelper<BITS>::type;
289 
290 } // namespace Fortran::common
291 #endif
292