cxx11_tensor_uint128.cpp
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2015 Benoit Steiner <benoit.steiner.goog@gmail.com>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #include "main.h"
11 
12 #include <Eigen/CXX11/Tensor>
13 
14 
15 #if EIGEN_COMP_MSVC
16 #define EIGEN_NO_INT128
17 #else
18 typedef __uint128_t uint128_t;
19 #endif
20 
21 // Only run the test on compilers that support 128bit integers natively
22 #ifndef EIGEN_NO_INT128
23 
26 
28  bool matchl = actual.lower() == static_cast<uint64_t>(expected);
29  bool matchh = actual.upper() == static_cast<uint64_t>(expected >> 64);
30  if (!matchl || !matchh) {
31  const char* testname = g_test_stack.back().c_str();
32  std::cerr << "Test " << testname << " failed in " << __FILE__
33  << " (" << __LINE__ << ")"
34  << std::endl;
35  abort();
36  }
37 }
38 
39 
40 void test_add() {
41  uint64_t incr = internal::random<uint64_t>(1, 9999999999);
42  for (uint64_t i1 = 0; i1 < 100; ++i1) {
43  for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
45  uint128_t a = (static_cast<uint128_t>(i1) << 64) + static_cast<uint128_t>(i2);
46  for (uint64_t j1 = 0; j1 < 100; ++j1) {
47  for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
49  uint128_t b = (static_cast<uint128_t>(j1) << 64) + static_cast<uint128_t>(j2);
50  TensorUInt128<uint64_t, uint64_t> actual = i + j;
51  uint128_t expected = a + b;
52  VERIFY_EQUAL(actual, expected);
53  }
54  }
55  }
56  }
57 }
58 
59 void test_sub() {
60  uint64_t incr = internal::random<uint64_t>(1, 9999999999);
61  for (uint64_t i1 = 0; i1 < 100; ++i1) {
62  for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
64  uint128_t a = (static_cast<uint128_t>(i1) << 64) + static_cast<uint128_t>(i2);
65  for (uint64_t j1 = 0; j1 < 100; ++j1) {
66  for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
68  uint128_t b = (static_cast<uint128_t>(j1) << 64) + static_cast<uint128_t>(j2);
69  TensorUInt128<uint64_t, uint64_t> actual = i - j;
70  uint128_t expected = a - b;
71  VERIFY_EQUAL(actual, expected);
72  }
73  }
74  }
75  }
76 }
77 
78 void test_mul() {
79  uint64_t incr = internal::random<uint64_t>(1, 9999999999);
80  for (uint64_t i1 = 0; i1 < 100; ++i1) {
81  for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
83  uint128_t a = (static_cast<uint128_t>(i1) << 64) + static_cast<uint128_t>(i2);
84  for (uint64_t j1 = 0; j1 < 100; ++j1) {
85  for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
87  uint128_t b = (static_cast<uint128_t>(j1) << 64) + static_cast<uint128_t>(j2);
88  TensorUInt128<uint64_t, uint64_t> actual = i * j;
89  uint128_t expected = a * b;
90  VERIFY_EQUAL(actual, expected);
91  }
92  }
93  }
94  }
95 }
96 
97 void test_div() {
98  uint64_t incr = internal::random<uint64_t>(1, 9999999999);
99  for (uint64_t i1 = 0; i1 < 100; ++i1) {
100  for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
102  uint128_t a = (static_cast<uint128_t>(i1) << 64) + static_cast<uint128_t>(i2);
103  for (uint64_t j1 = 0; j1 < 100; ++j1) {
104  for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
106  uint128_t b = (static_cast<uint128_t>(j1) << 64) + static_cast<uint128_t>(j2);
107  TensorUInt128<uint64_t, uint64_t> actual = i / j;
108  uint128_t expected = a / b;
109  VERIFY_EQUAL(actual, expected);
110  }
111  }
112  }
113  }
114 }
115 
116 void test_misc1() {
117  uint64_t incr = internal::random<uint64_t>(1, 9999999999);
118  for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
119  TensorUInt128<static_val<0>, uint64_t> i(0, i2);
120  uint128_t a = static_cast<uint128_t>(i2);
121  for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
122  TensorUInt128<static_val<0>, uint64_t> j(0, j2);
123  uint128_t b = static_cast<uint128_t>(j2);
124  uint64_t actual = (i * j).upper();
125  uint64_t expected = (a * b) >> 64;
126  VERIFY_IS_EQUAL(actual, expected);
127  }
128  }
129 }
130 
131 void test_misc2() {
132  int64_t incr = internal::random<int64_t>(1, 100);
133  for (int64_t log_div = 0; log_div < 63; ++log_div) {
134  for (int64_t divider = 1; divider <= 1000000 * incr; divider += incr) {
135  uint64_t expected = (static_cast<uint128_t>(1) << (64+log_div)) / static_cast<uint128_t>(divider) - (static_cast<uint128_t>(1) << 64) + 1;
136  uint64_t shift = 1ULL << log_div;
137 
139  uint64_t actual = static_cast<uint64_t>(result);
140  VERIFY_IS_EQUAL(actual, expected);
141  }
142  }
143 }
144 #endif
145 
146 
148 {
149 #ifdef EIGEN_NO_INT128
150  // Skip the test on compilers that don't support 128bit integers natively
151  return;
152 #else
153  CALL_SUBTEST_1(test_add());
154  CALL_SUBTEST_2(test_sub());
155  CALL_SUBTEST_3(test_mul());
156  CALL_SUBTEST_4(test_div());
157  CALL_SUBTEST_5(test_misc1());
158  CALL_SUBTEST_6(test_misc2());
159 #endif
160 }
void test_div()
void test_mul()
void test_add()
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE HIGH upper() const
Definition: TensorUInt128.h:70
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE LOW lower() const
Definition: TensorUInt128.h:67
void test_misc2()
void VERIFY_EQUAL(TensorUInt128< uint64_t, uint64_t > actual, uint128_t expected)
void test_misc1()
void test_cxx11_tensor_uint128()
EIGEN_DEVICE_FUNC const Scalar & b
void test_sub()
__uint128_t uint128_t


hebiros
Author(s): Xavier Artache , Matthew Tesch
autogenerated on Thu Sep 3 2020 04:08:09