11#ifndef EIGEN_TENSOR_TENSOR_UINT128_H
12#define EIGEN_TENSOR_TENSOR_UINT128_H
15#include "./InternalHeaderCheck.h"
22 static constexpr uint64_t value = n;
23 constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
operator uint64_t()
const {
return n; }
25 constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static_val() =
default;
28 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static_val(
const T& v) {
29 EIGEN_UNUSED_VARIABLE(v);
34template <
typename HIGH = u
int64_t,
typename LOW = u
int64_t>
39 template <
typename OTHER_HIGH,
typename OTHER_LOW>
40 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE TensorUInt128(
const TensorUInt128<OTHER_HIGH, OTHER_LOW>& other)
41 : high(other.high), low(other.low) {
42 EIGEN_STATIC_ASSERT(
sizeof(OTHER_HIGH) <=
sizeof(HIGH), YOU_MADE_A_PROGRAMMING_MISTAKE);
43 EIGEN_STATIC_ASSERT(
sizeof(OTHER_LOW) <=
sizeof(LOW), YOU_MADE_A_PROGRAMMING_MISTAKE);
46 template <
typename OTHER_HIGH,
typename OTHER_LOW>
47 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE TensorUInt128& operator=(
const TensorUInt128<OTHER_HIGH, OTHER_LOW>& other) {
48 EIGEN_STATIC_ASSERT(
sizeof(OTHER_HIGH) <=
sizeof(HIGH), YOU_MADE_A_PROGRAMMING_MISTAKE);
49 EIGEN_STATIC_ASSERT(
sizeof(OTHER_LOW) <=
sizeof(LOW), YOU_MADE_A_PROGRAMMING_MISTAKE);
56 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
explicit TensorUInt128(
const T& x) : high(0), low(x) {
58 (
static_cast<std::conditional_t<sizeof(T) == 8, uint64_t, uint32_t
>>(x) <= NumTraits<uint64_t>::highest()));
62 constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE TensorUInt128(HIGH y, LOW x) : high(y), low(x) {}
64 constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
operator LOW()
const {
return low; }
65 constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LOW lower()
const {
return low; }
66 constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE HIGH upper()
const {
return high; }
69template <
typename HL,
typename LL,
typename HR,
typename LR>
70constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool operator==(
const TensorUInt128<HL, LL>& lhs,
71 const TensorUInt128<HR, LR>& rhs) {
72 return (lhs.high == rhs.high) && (lhs.low == rhs.low);
75template <
typename HL,
typename LL,
typename HR,
typename LR>
76constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool operator!=(
const TensorUInt128<HL, LL>& lhs,
77 const TensorUInt128<HR, LR>& rhs) {
78 return (lhs.high != rhs.high) || (lhs.low != rhs.low);
81template <
typename HL,
typename LL,
typename HR,
typename LR>
82constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool operator>=(
const TensorUInt128<HL, LL>& lhs,
83 const TensorUInt128<HR, LR>& rhs) {
84 if (lhs.high != rhs.high) {
85 return lhs.high > rhs.high;
87 return lhs.low >= rhs.low;
90template <
typename HL,
typename LL,
typename HR,
typename LR>
91constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool operator<(
const TensorUInt128<HL, LL>& lhs,
92 const TensorUInt128<HR, LR>& rhs) {
93 if (lhs.high != rhs.high) {
94 return lhs.high < rhs.high;
96 return lhs.low < rhs.low;
99template <
typename HL,
typename LL,
typename HR,
typename LR>
100constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE TensorUInt128<uint64_t, uint64_t> operator+(
101 const TensorUInt128<HL, LL>& lhs,
const TensorUInt128<HR, LR>& rhs) {
102 TensorUInt128<uint64_t, uint64_t> result(lhs.high + rhs.high, lhs.low + rhs.low);
103 if (result.low < rhs.low) {
109template <
typename HL,
typename LL,
typename HR,
typename LR>
110constexpr EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE TensorUInt128<uint64_t, uint64_t> operator-(
111 const TensorUInt128<HL, LL>& lhs,
const TensorUInt128<HR, LR>& rhs) {
112 TensorUInt128<uint64_t, uint64_t> result(lhs.high - rhs.high, lhs.low - rhs.low);
113 if (result.low > lhs.low) {
119template <
typename HL,
typename LL,
typename HR,
typename LR>
120static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorUInt128<uint64_t, uint64_t> operator*(
121 const TensorUInt128<HL, LL>& lhs,
const TensorUInt128<HR, LR>& rhs) {
133 const uint64_t LOW = 0x00000000FFFFFFFFLL;
134 const uint64_t HIGH = 0xFFFFFFFF00000000LL;
136 uint64_t d = lhs.low & LOW;
137 uint64_t c = (lhs.low & HIGH) >> 32LL;
138 uint64_t b = lhs.high & LOW;
139 uint64_t a = (lhs.high & HIGH) >> 32LL;
141 uint64_t h = rhs.low & LOW;
142 uint64_t g = (rhs.low & HIGH) >> 32LL;
143 uint64_t f = rhs.high & LOW;
144 uint64_t e = (rhs.high & HIGH) >> 32LL;
147 uint64_t acc = d * h;
148 uint64_t low = acc & LOW;
152 uint64_t acc2 = acc + c * h;
160 low |= (acc << 32LL);
164 acc2 = (acc >> 32LL) | (carry << 32LL);
179 uint64_t high = acc & LOW;
182 acc2 = (acc >> 32LL) | (carry << 32LL);
188 high |= (acc2 << 32LL);
190 return TensorUInt128<uint64_t, uint64_t>(high, low);
193template <
typename HL,
typename LL,
typename HR,
typename LR>
194static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorUInt128<uint64_t, uint64_t> operator/(
195 const TensorUInt128<HL, LL>& lhs,
const TensorUInt128<HR, LR>& rhs) {
196 if (rhs == TensorUInt128<static_val<0>, static_val<1>>(1)) {
197 return TensorUInt128<uint64_t, uint64_t>(lhs.high, lhs.low);
198 }
else if (lhs < rhs) {
199 return TensorUInt128<uint64_t, uint64_t>(0);
202 TensorUInt128<uint64_t, uint64_t> power2(1);
203 TensorUInt128<uint64_t, uint64_t> d(rhs);
205 if (d.high >> 63)
break;
207 power2 = power2 + power2;
210 TensorUInt128<uint64_t, uint64_t> tmp(lhs.high, lhs.low);
211 TensorUInt128<uint64_t, uint64_t> result(0);
212 while (power2 != TensorUInt128<static_val<0>, static_val<0>>(0)) {
215 result = result + power2;
218 power2 = TensorUInt128<uint64_t, uint64_t>(power2.high >> 1, (power2.low >> 1) | (power2.high << 63));
219 d = TensorUInt128<uint64_t, uint64_t>(d.high >> 1, (d.low >> 1) | (d.high << 63));
Namespace containing all symbols from the Eigen library.