Warning, file /include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorUInt128.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_CXX11_TENSOR_TENSOR_UINT128_H
0011 #define EIGEN_CXX11_TENSOR_TENSOR_UINT128_H
0012
0013 namespace Eigen {
0014 namespace internal {
0015
0016
0017 template <uint64_t n>
0018 struct static_val {
0019 static const uint64_t value = n;
0020 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE operator uint64_t() const { return n; }
0021
0022 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static_val() { }
0023
0024 template <typename T>
0025 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static_val(const T& v) {
0026 EIGEN_UNUSED_VARIABLE(v);
0027 eigen_assert(v == n);
0028 }
0029 };
0030
0031
0032 template <typename HIGH = uint64_t, typename LOW = uint64_t>
0033 struct TensorUInt128
0034 {
0035 HIGH high;
0036 LOW low;
0037
0038 template<typename OTHER_HIGH, typename OTHER_LOW>
0039 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0040 TensorUInt128(const TensorUInt128<OTHER_HIGH, OTHER_LOW>& other) : high(other.high), low(other.low) {
0041 EIGEN_STATIC_ASSERT(sizeof(OTHER_HIGH) <= sizeof(HIGH), YOU_MADE_A_PROGRAMMING_MISTAKE);
0042 EIGEN_STATIC_ASSERT(sizeof(OTHER_LOW) <= sizeof(LOW), YOU_MADE_A_PROGRAMMING_MISTAKE);
0043 }
0044
0045 template<typename OTHER_HIGH, typename OTHER_LOW>
0046 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0047 TensorUInt128& operator = (const TensorUInt128<OTHER_HIGH, OTHER_LOW>& other) {
0048 EIGEN_STATIC_ASSERT(sizeof(OTHER_HIGH) <= sizeof(HIGH), YOU_MADE_A_PROGRAMMING_MISTAKE);
0049 EIGEN_STATIC_ASSERT(sizeof(OTHER_LOW) <= sizeof(LOW), YOU_MADE_A_PROGRAMMING_MISTAKE);
0050 high = other.high;
0051 low = other.low;
0052 return *this;
0053 }
0054
0055 template<typename T>
0056 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0057 explicit TensorUInt128(const T& x) : high(0), low(x) {
0058 eigen_assert((static_cast<typename conditional<sizeof(T) == 8, uint64_t, uint32_t>::type>(x) <= NumTraits<uint64_t>::highest()));
0059 eigen_assert(x >= 0);
0060 }
0061
0062 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0063 TensorUInt128(HIGH y, LOW x) : high(y), low(x) { }
0064
0065 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE operator LOW() const {
0066 return low;
0067 }
0068 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LOW lower() const {
0069 return low;
0070 }
0071 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE HIGH upper() const {
0072 return high;
0073 }
0074 };
0075
0076
0077 template <typename HL, typename LL, typename HR, typename LR>
0078 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0079 bool operator == (const TensorUInt128<HL, LL>& lhs, const TensorUInt128<HR, LR>& rhs)
0080 {
0081 return (lhs.high == rhs.high) & (lhs.low == rhs.low);
0082 }
0083
0084 template <typename HL, typename LL, typename HR, typename LR>
0085 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0086 bool operator != (const TensorUInt128<HL, LL>& lhs, const TensorUInt128<HR, LR>& rhs)
0087 {
0088 return (lhs.high != rhs.high) | (lhs.low != rhs.low);
0089 }
0090
0091 template <typename HL, typename LL, typename HR, typename LR>
0092 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0093 bool operator >= (const TensorUInt128<HL, LL>& lhs, const TensorUInt128<HR, LR>& rhs)
0094 {
0095 if (lhs.high != rhs.high) {
0096 return lhs.high > rhs.high;
0097 }
0098 return lhs.low >= rhs.low;
0099 }
0100
0101 template <typename HL, typename LL, typename HR, typename LR>
0102 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0103 bool operator < (const TensorUInt128<HL, LL>& lhs, const TensorUInt128<HR, LR>& rhs)
0104 {
0105 if (lhs.high != rhs.high) {
0106 return lhs.high < rhs.high;
0107 }
0108 return lhs.low < rhs.low;
0109 }
0110
0111 template <typename HL, typename LL, typename HR, typename LR>
0112 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0113 TensorUInt128<uint64_t, uint64_t> operator + (const TensorUInt128<HL, LL>& lhs, const TensorUInt128<HR, LR>& rhs)
0114 {
0115 TensorUInt128<uint64_t, uint64_t> result(lhs.high + rhs.high, lhs.low + rhs.low);
0116 if (result.low < rhs.low) {
0117 result.high += 1;
0118 }
0119 return result;
0120 }
0121
0122 template <typename HL, typename LL, typename HR, typename LR>
0123 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
0124 TensorUInt128<uint64_t, uint64_t> operator - (const TensorUInt128<HL, LL>& lhs, const TensorUInt128<HR, LR>& rhs)
0125 {
0126 TensorUInt128<uint64_t, uint64_t> result(lhs.high - rhs.high, lhs.low - rhs.low);
0127 if (result.low > lhs.low) {
0128 result.high -= 1;
0129 }
0130 return result;
0131 }
0132
0133
0134 template <typename HL, typename LL, typename HR, typename LR>
0135 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0136 TensorUInt128<uint64_t, uint64_t> operator * (const TensorUInt128<HL, LL>& lhs, const TensorUInt128<HR, LR>& rhs)
0137 {
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 const uint64_t LOW = 0x00000000FFFFFFFFLL;
0150 const uint64_t HIGH = 0xFFFFFFFF00000000LL;
0151
0152 uint64_t d = lhs.low & LOW;
0153 uint64_t c = (lhs.low & HIGH) >> 32LL;
0154 uint64_t b = lhs.high & LOW;
0155 uint64_t a = (lhs.high & HIGH) >> 32LL;
0156
0157 uint64_t h = rhs.low & LOW;
0158 uint64_t g = (rhs.low & HIGH) >> 32LL;
0159 uint64_t f = rhs.high & LOW;
0160 uint64_t e = (rhs.high & HIGH) >> 32LL;
0161
0162
0163 uint64_t acc = d * h;
0164 uint64_t low = acc & LOW;
0165
0166 acc >>= 32LL;
0167 uint64_t carry = 0;
0168 uint64_t acc2 = acc + c * h;
0169 if (acc2 < acc) {
0170 carry++;
0171 }
0172 acc = acc2 + d * g;
0173 if (acc < acc2) {
0174 carry++;
0175 }
0176 low |= (acc << 32LL);
0177
0178
0179
0180 acc2 = (acc >> 32LL) | (carry << 32LL);
0181 carry = 0;
0182
0183 acc = acc2 + b * h;
0184 if (acc < acc2) {
0185 carry++;
0186 }
0187 acc2 = acc + c * g;
0188 if (acc2 < acc) {
0189 carry++;
0190 }
0191 acc = acc2 + d * f;
0192 if (acc < acc2) {
0193 carry++;
0194 }
0195 uint64_t high = acc & LOW;
0196
0197
0198 acc2 = (acc >> 32LL) | (carry << 32LL);
0199
0200 acc = acc2 + a * h;
0201 acc2 = acc + b * g;
0202 acc = acc2 + c * f;
0203 acc2 = acc + d * e;
0204 high |= (acc2 << 32LL);
0205
0206 return TensorUInt128<uint64_t, uint64_t>(high, low);
0207 }
0208
0209 template <typename HL, typename LL, typename HR, typename LR>
0210 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0211 TensorUInt128<uint64_t, uint64_t> operator / (const TensorUInt128<HL, LL>& lhs, const TensorUInt128<HR, LR>& rhs)
0212 {
0213 if (rhs == TensorUInt128<static_val<0>, static_val<1> >(1)) {
0214 return TensorUInt128<uint64_t, uint64_t>(lhs.high, lhs.low);
0215 } else if (lhs < rhs) {
0216 return TensorUInt128<uint64_t, uint64_t>(0);
0217 } else {
0218
0219 TensorUInt128<uint64_t, uint64_t> power2(1);
0220 TensorUInt128<uint64_t, uint64_t> d(rhs);
0221 TensorUInt128<uint64_t, uint64_t> tmp(lhs - d);
0222 while (lhs >= d) {
0223 tmp = tmp - d;
0224 d = d + d;
0225 power2 = power2 + power2;
0226 }
0227
0228 tmp = TensorUInt128<uint64_t, uint64_t>(lhs.high, lhs.low);
0229 TensorUInt128<uint64_t, uint64_t> result(0);
0230 while (power2 != TensorUInt128<static_val<0>, static_val<0> >(0)) {
0231 if (tmp >= d) {
0232 tmp = tmp - d;
0233 result = result + power2;
0234 }
0235
0236 power2 = TensorUInt128<uint64_t, uint64_t>(power2.high >> 1, (power2.low >> 1) | (power2.high << 63));
0237 d = TensorUInt128<uint64_t, uint64_t>(d.high >> 1, (d.low >> 1) | (d.high << 63));
0238 }
0239
0240 return result;
0241 }
0242 }
0243
0244
0245 }
0246 }
0247
0248
0249 #endif