12#ifndef FORTRAN_COMMON_UINT128_H_
13#define FORTRAN_COMMON_UINT128_H_
18#ifndef AVOID_NATIVE_UINT128_T
19#define AVOID_NATIVE_UINT128_T 0
22#include "leading-zero-bit-count.h"
23#include "flang/Common/api-attrs.h"
29template <
bool IS_SIGNED = false>
class Int128 {
34 constexpr Int128(
unsigned n) : low_{n} {}
35 constexpr Int128(
unsigned long n) : low_{n} {}
36 constexpr Int128(
unsigned long long n) : low_{n} {}
38 low_ =
static_cast<std::uint64_t
>(n);
39 high_ = -
static_cast<std::uint64_t
>(n < 0);
42 low_ =
static_cast<std::uint64_t
>(n);
43 high_ = -
static_cast<std::uint64_t
>(n < 0);
45 constexpr Int128(
long long n) {
46 low_ =
static_cast<std::uint64_t
>(n);
47 high_ = -
static_cast<std::uint64_t
>(n < 0);
55 : low_{n.low()}, high_{n.high()} {}
57 : low_{n.low()}, high_{n.high()} {}
59 constexpr Int128 operator+()
const {
return *
this; }
60 constexpr Int128 operator~()
const {
return {~high_, ~low_}; }
61 constexpr Int128 operator-()
const {
return ~*
this + 1; }
62 constexpr bool operator!()
const {
return !low_ && !high_; }
63 constexpr explicit operator bool()
const {
return low_ || high_; }
64 constexpr explicit operator std::uint64_t()
const {
return low_; }
65 constexpr explicit operator std::int64_t()
const {
return low_; }
66 constexpr explicit operator int()
const {
return static_cast<int>(low_); }
68 constexpr std::uint64_t high()
const {
return high_; }
69 constexpr std::uint64_t low()
const {
return low_; }
71 constexpr Int128 operator++() {
75 constexpr Int128 operator++(
int ) {
80 constexpr Int128 operator--() {
84 constexpr Int128 operator--(
int ) {
91 return {high_ & that.high_, low_ & that.low_};
94 return {high_ | that.high_, low_ | that.low_};
97 return {high_ ^ that.high_, low_ ^ that.low_};
103 }
else if (that == 0) {
106 std::uint64_t n{that.low_};
108 return {low_ << (n - 64), 0};
110 return {(high_ << n) | (low_ >> (64 - n)), low_ << n};
117 }
else if (that == 0) {
120 std::uint64_t n{that.low_};
122 return {0, high_ >> (n - 64)};
124 return {high_ >> n, (high_ << (64 - n)) | (low_ >> n)};
130 std::uint64_t lower{(low_ & ~topBit) + (that.low_ & ~topBit)};
131 bool carry{((lower >> 63) + (low_ >> 63) + (that.low_ >> 63)) > 1};
132 return {high_ + that.high_ + carry, low_ + that.low_};
134 constexpr Int128 operator-(
Int128 that)
const {
return *
this + -that; }
137 std::uint64_t mask32{0xffffffff};
138 if (high_ == 0 && that.high_ == 0) {
139 std::uint64_t x0{low_ & mask32}, x1{low_ >> 32};
140 std::uint64_t y0{that.low_ & mask32}, y1{that.low_ >> 32};
141 Int128 x0y0{x0 * y0}, x0y1{x0 * y1};
142 Int128 x1y0{x1 * y0}, x1y1{x1 * y1};
143 return x0y0 + ((x0y1 + x1y0) << 32) + (x1y1 << 64);
145 std::uint64_t x0{low_ & mask32}, x1{low_ >> 32}, x2{high_ & mask32},
147 std::uint64_t y0{that.low_ & mask32}, y1{that.low_ >> 32},
148 y2{that.high_ & mask32}, y3{that.high_ >> 32};
149 Int128 x0y0{x0 * y0}, x0y1{x0 * y1}, x0y2{x0 * y2}, x0y3{x0 * y3};
150 Int128 x1y0{x1 * y0}, x1y1{x1 * y1}, x1y2{x1 * y2};
151 Int128 x2y0{x2 * y0}, x2y1{x2 * y1};
153 return x0y0 + ((x0y1 + x1y0) << 32) + ((x0y2 + x1y1 + x2y0) << 64) +
154 ((x0y3 + x1y2 + x2y1 + x3y0) << 96);
159 int j{LeadingZeroes()};
164 for (; j < 128; ++j) {
166 if (bits.high_ & topBit) {
171 if (numerator >= that) {
180 int j{LeadingZeroes()};
184 for (; j < 128; ++j) {
186 if (bits.high_ & topBit) {
190 if (remainder >= that) {
197 constexpr bool operator<(
Int128 that)
const {
198 if (IS_SIGNED && (high_ ^ that.high_) & topBit) {
199 return (high_ & topBit) != 0;
201 return high_ < that.high_ || (high_ == that.high_ && low_ < that.low_);
203 constexpr bool operator<=(
Int128 that)
const {
return !(*
this > that); }
204 constexpr bool operator==(
Int128 that)
const {
205 return low_ == that.low_ && high_ == that.high_;
207 constexpr bool operator!=(
Int128 that)
const {
return !(*
this == that); }
208 constexpr bool operator>=(
Int128 that)
const {
return that <= *
this; }
209 constexpr bool operator>(
Int128 that)
const {
return that < *
this; }
212 *
this = *
this & that;
216 *
this = *
this | that;
220 *
this = *
this ^ that;
224 *
this = *
this << that;
228 *
this = *
this >> that;
232 *
this = *
this + that;
236 *
this = *
this - that;
240 *
this = *
this * that;
244 *
this = *
this / that;
248 *
this = *
this % that;
253 constexpr Int128(std::uint64_t hi, std::uint64_t lo) {
257 constexpr int LeadingZeroes()
const {
259 return 64 + LeadingZeroBitCount(low_);
261 return LeadingZeroBitCount(high_);
265 static constexpr std::uint64_t topBit{std::uint64_t{1} << 63};
267#if FLANG_LITTLE_ENDIAN
268 std::uint64_t low_{0}, high_{0};
269#elif FLANG_BIG_ENDIAN
270 std::uint64_t high_{0}, low_{0};
272#error host endianness is not known
279#if !AVOID_NATIVE_UINT128_T && (defined __GNUC__ || defined __clang__) && \
280 defined __SIZEOF_INT128__
289 using type = std::conditional_t<(BITS <= 8), std::uint8_t,
290 std::conditional_t<(BITS <= 16), std::uint16_t,
291 std::conditional_t<(BITS <= 32), std::uint32_t,
292 std::conditional_t<(BITS <= 64), std::uint64_t,
uint128_t>>>>;
295 using type = std::conditional_t<(BITS <= 8), std::int8_t,
296 std::conditional_t<(BITS <= 16), std::int16_t,
297 std::conditional_t<(BITS <= 32), std::int32_t,
298 std::conditional_t<(BITS <= 64), std::int64_t,
int128_t>>>>;
301using HostUnsignedIntType =
typename HostUnsignedIntTypeHelper<BITS>::type;
303using HostSignedIntType =
typename HostSignedIntTypeHelper<BITS>::type;
Definition: bit-population-count.h:20
Definition: uint128.h:294
Definition: uint128.h:288