packetmath_test_shared.h
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) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11 #include "main.h"
12 #include <typeinfo>
13 
14 #if defined __GNUC__ && __GNUC__ >= 6
15 #pragma GCC diagnostic ignored "-Wignored-attributes"
16 #endif
17 // using namespace Eigen;
18 
19 bool g_first_pass = true;
20 
21 namespace Eigen {
22 
23 namespace test {
24 
25 template <typename T, std::enable_if_t<NumTraits<T>::IsSigned, bool> = true>
26 T negate(const T& x) {
27  return -x;
28 }
29 
30 template <typename T, std::enable_if_t<!NumTraits<T>::IsSigned, bool> = true>
31 T negate(const T& x) {
32  return T(0) - x;
33 }
34 
35 template <typename T>
36 Map<const Array<unsigned char, sizeof(T), 1> > bits(const T& x) {
37  return Map<const Array<unsigned char, sizeof(T), 1> >(reinterpret_cast<const unsigned char*>(&x));
38 }
39 
40 template <typename T>
41 bool biteq(T a, T b) {
42  return (bits(a) == bits(b)).all();
43 }
44 
45 // NOTE: we disable inlining for this function to workaround a GCC issue when using -O3 and the i387 FPU.
46 template <typename Scalar>
47 EIGEN_DONT_INLINE bool isApproxAbs(const Scalar& a, const Scalar& b, const typename NumTraits<Scalar>::Real& refvalue) {
48  return internal::isMuchSmallerThan(a - b, refvalue);
49 }
50 
51 template <typename Scalar>
52 inline void print_mismatch(const Scalar* ref, const Scalar* vec, int size) {
53  std::cout << "ref: [" << Map<const Matrix<Scalar, 1, Dynamic> >(ref, size) << "]"
54  << " != vec: [" << Map<const Matrix<Scalar, 1, Dynamic> >(vec, size) << "]\n";
55 }
56 
57 template <typename Scalar>
58 bool areApproxAbs(const Scalar* a, const Scalar* b, int size, const typename NumTraits<Scalar>::Real& refvalue) {
59  for (int i = 0; i < size; ++i) {
60  if (!isApproxAbs(a[i], b[i], refvalue)) {
62  std::cout << std::setprecision(16) << "Values differ in position " << i << ": " << a[i] << " vs " << b[i]
63  << std::endl;
64  return false;
65  }
66  }
67  return true;
68 }
69 
70 template <typename Scalar>
71 bool areApprox(const Scalar* a, const Scalar* b, int size) {
72  for (int i = 0; i < size; ++i) {
73  if (numext::not_equal_strict(a[i], b[i]) && !internal::isApprox(a[i], b[i]) &&
74  !((numext::isnan)(a[i]) && (numext::isnan)(b[i]))) {
76  std::cout << std::setprecision(16) << "Values differ in position " << i << ": " << a[i] << " vs " << b[i]
77  << std::endl;
78  return false;
79  }
80  }
81  return true;
82 }
83 
84 template <typename Scalar>
85 bool areEqual(const Scalar* a, const Scalar* b, int size) {
86  for (int i = 0; i < size; ++i) {
87  if (numext::not_equal_strict(a[i], b[i]) && !((numext::isnan)(a[i]) && (numext::isnan)(b[i]))) {
89  std::cout << std::setprecision(16) << "Values differ in position " << i << ": " << a[i] << " vs " << b[i]
90  << std::endl;
91  return false;
92  }
93  }
94  return true;
95 }
96 
97 template <typename Scalar>
98 bool areApprox(const Scalar* a, const Scalar* b, int size, const typename NumTraits<Scalar>::Real& precision) {
99  for (int i = 0; i < size; ++i) {
100  if (numext::not_equal_strict(a[i], b[i]) && !internal::isApprox(a[i], b[i], precision) &&
101  !((numext::isnan)(a[i]) && (numext::isnan)(b[i]))) {
102  print_mismatch(a, b, size);
103  std::cout << std::setprecision(16) << "Values differ in position " << i << ": " << a[i] << " vs " << b[i]
104  << std::endl;
105  return false;
106  }
107  }
108  return true;
109 }
110 
111 #define CHECK_CWISE1(REFOP, POP) \
112  { \
113  for (int i = 0; i < PacketSize; ++i) ref[i] = REFOP(data1[i]); \
114  internal::pstore(data2, POP(internal::pload<Packet>(data1))); \
115  VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
116  }
117 
118 // Checks component-wise for input of size N. All of data1, data2, and ref
119 // should have size at least ceil(N/PacketSize)*PacketSize to avoid memory
120 // access errors.
121 #define CHECK_CWISE1_N(REFOP, POP, N) \
122  { \
123  for (int i = 0; i < N; ++i) ref[i] = REFOP(data1[i]); \
124  for (int j = 0; j < N; j += PacketSize) internal::pstore(data2 + j, POP(internal::pload<Packet>(data1 + j))); \
125  VERIFY(test::areApprox(ref, data2, N) && #POP); \
126  }
127 
128 // Checks component-wise for input of complex type of size N. The real and
129 // the imaginary part are compared separately, with 1ULP relaxed condition
130 // for the imaginary part. All of data1 data2, ref, realdata1 and realref
131 // should have size at least ceil(N/PacketSize)*PacketSize to avoid
132 // memory access errors.
133 #define CHECK_CWISE1_IM1ULP_N(REFOP, POP, N) \
134  { \
135  RealScalar eps_1ulp = RealScalar(1e1) * std::numeric_limits<RealScalar>::epsilon(); \
136  for (int j = 0; j < N; j += PacketSize) \
137  internal::pstore(data2 + j, internal::plog(internal::pload<Packet>(data1 + j))); \
138  for (int i = 0; i < N; ++i) { \
139  ref[i] = REFOP(data1[i]); \
140  realref[i] = ref[i].imag(); \
141  realdata[i] = data2[i].imag(); \
142  } \
143  VERIFY(test::areApprox(realdata, realref, N, eps_1ulp)); \
144  for (int i = 0; i < N; ++i) { \
145  realdata[i] = data2[i].real(); \
146  realref[i] = ref[i].real(); \
147  } \
148  VERIFY(test::areApprox(realdata, realref, N)); \
149  }
150 
151 template <bool Cond, typename Packet>
153  template <typename T>
154  inline Packet load(const T* from) const {
155  return internal::pload<Packet>(from);
156  }
157 
158  template <typename T>
159  inline Packet loadu(const T* from) const {
160  return internal::ploadu<Packet>(from);
161  }
162 
163  template <typename T>
164  inline Packet load(const T* from, unsigned long long umask) const {
165  return internal::ploadu<Packet>(from, umask);
166  }
167 
168  template <typename T>
169  inline void store(T* to, const Packet& x) const {
170  internal::pstore(to, x);
171  }
172 
173  template <typename T>
174  inline void store(T* to, const Packet& x, unsigned long long umask) const {
175  internal::pstoreu(to, x, umask);
176  }
177 
178  template <typename T>
179  inline Packet& forward_reference(Packet& packet, T& /*scalar*/) const {
180  return packet;
181  }
182 };
183 
184 template <typename Packet>
185 struct packet_helper<false, Packet> {
186  template <typename T>
187  inline T load(const T* from) const {
188  return *from;
189  }
190 
191  template <typename T>
192  inline T loadu(const T* from) const {
193  return *from;
194  }
195 
196  template <typename T>
197  inline T load(const T* from, unsigned long long) const {
198  return *from;
199  }
200 
201  template <typename T>
202  inline void store(T* to, const T& x) const {
203  *to = x;
204  }
205 
206  template <typename T>
207  inline void store(T* to, const T& x, unsigned long long) const {
208  *to = x;
209  }
210 
211  template <typename T>
212  inline T& forward_reference(Packet& /*packet*/, T& scalar) const {
213  return scalar;
214  }
215 };
216 
217 #define CHECK_CWISE1_IF(COND, REFOP, POP) \
218  if (COND) { \
219  test::packet_helper<COND, Packet> h; \
220  for (int i = 0; i < PacketSize; ++i) ref[i] = Scalar(REFOP(data1[i])); \
221  h.store(data2, POP(h.load(data1))); \
222  VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
223  }
224 
225 #define CHECK_CWISE1_EXACT_IF(COND, REFOP, POP) \
226  if (COND) { \
227  test::packet_helper<COND, Packet> h; \
228  for (int i = 0; i < PacketSize; ++i) ref[i] = Scalar(REFOP(data1[i])); \
229  h.store(data2, POP(h.load(data1))); \
230  VERIFY(test::areEqual(ref, data2, PacketSize) && #POP); \
231  }
232 
233 #define CHECK_CWISE2_IF(COND, REFOP, POP) \
234  if (COND) { \
235  test::packet_helper<COND, Packet> h; \
236  for (int i = 0; i < PacketSize; ++i) ref[i] = Scalar(REFOP(data1[i], data1[i + PacketSize])); \
237  h.store(data2, POP(h.load(data1), h.load(data1 + PacketSize))); \
238  VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
239  }
240 
241 // One input, one output by reference.
242 #define CHECK_CWISE1_BYREF1_IF(COND, REFOP, POP) \
243  if (COND) { \
244  test::packet_helper<COND, Packet> h; \
245  for (int i = 0; i < PacketSize; ++i) ref[i] = Scalar(REFOP(data1[i], ref[i + PacketSize])); \
246  Packet pout; \
247  Scalar sout; \
248  h.store(data2, POP(h.load(data1), h.forward_reference(pout, sout))); \
249  h.store(data2 + PacketSize, h.forward_reference(pout, sout)); \
250  VERIFY(test::areApprox(ref, data2, 2 * PacketSize) && #POP); \
251  }
252 
253 #define CHECK_CWISE3_IF(COND, REFOP, POP) \
254  if (COND) { \
255  test::packet_helper<COND, Packet> h; \
256  for (int i = 0; i < PacketSize; ++i) \
257  ref[i] = Scalar(REFOP(data1[i], data1[i + PacketSize], data1[i + 2 * PacketSize])); \
258  h.store(data2, POP(h.load(data1), h.load(data1 + PacketSize), h.load(data1 + 2 * PacketSize))); \
259  VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
260  }
261 
262 // Specialize the runall struct in your test file by defining run().
264  bool IsInteger = NumTraits<Scalar>::IsInteger>
265 struct runall;
266 
269  bool HasHalf = !internal::is_same<typename internal::unpacket_traits<PacketType>::half, PacketType>::value>
270 struct runner;
271 
272 template <typename Scalar, typename PacketType>
273 struct runner<Scalar, PacketType, true, true> {
274  static void run() {
277  }
278 };
279 
280 template <typename Scalar, typename PacketType>
281 struct runner<Scalar, PacketType, true, false> {
283 };
284 
285 template <typename Scalar, typename PacketType>
286 struct runner<Scalar, PacketType, false, false> {
288 };
289 
290 } // namespace test
291 } // namespace Eigen
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Eigen::Triplet< double > T
Definition: EigenUnitTest.cpp:11
#define EIGEN_DONT_INLINE
Definition: Macros.h:853
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
Scalar * b
Definition: benchVecAdd.cpp:17
SCALAR Scalar
Definition: bench_gemm.cpp:45
General-purpose arrays with easy API for coefficient-wise operations.
Definition: Array.h:48
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:96
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
@ IsComplex
Definition: common.h:73
const Scalar * a
Definition: level2_cplx_impl.h:32
EIGEN_DEVICE_FUNC bool isApprox(const Scalar &x, const Scalar &y, const typename NumTraits< Scalar >::Real &precision=NumTraits< Scalar >::dummy_precision())
Definition: MathFunctions.h:1923
EIGEN_DEVICE_FUNC bool isMuchSmallerThan(const Scalar &x, const OtherScalar &y, const typename NumTraits< Scalar >::Real &precision=NumTraits< Scalar >::dummy_precision())
Definition: MathFunctions.h:1916
EIGEN_DEVICE_FUNC void pstore(Scalar *to, const Packet &from)
Definition: GenericPacketMath.h:891
EIGEN_DEVICE_FUNC void pstoreu(Scalar *to, const Packet &from)
Definition: GenericPacketMath.h:911
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool() isnan(const Eigen::bfloat16 &h)
Definition: BFloat16.h:742
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const X &x, const Y &y)
Definition: Meta.h:606
void print_mismatch(const Scalar *ref, const Scalar *vec, int size)
Definition: packetmath_test_shared.h:52
bool areEqual(const Scalar *a, const Scalar *b, int size)
Definition: packetmath_test_shared.h:85
Map< const Array< unsigned char, sizeof(T), 1 > > bits(const T &x)
Definition: packetmath_test_shared.h:36
bool areApproxAbs(const Scalar *a, const Scalar *b, int size, const typename NumTraits< Scalar >::Real &refvalue)
Definition: packetmath_test_shared.h:58
bool biteq(T a, T b)
Definition: packetmath_test_shared.h:41
bool areApprox(const Scalar *a, const Scalar *b, int size)
Definition: packetmath_test_shared.h:71
T negate(const T &x)
Definition: packetmath_test_shared.h:26
EIGEN_DONT_INLINE bool isApproxAbs(const Scalar &a, const Scalar &b, const typename NumTraits< Scalar >::Real &refvalue)
Definition: packetmath_test_shared.h:47
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
auto run(Kernel kernel, Args &&... args) -> decltype(kernel(args...))
Definition: gpu_test_helper.h:414
squared absolute value
Definition: GlobalFunctions.h:87
type
Definition: compute_granudrum_aor.py:141
list x
Definition: plotDoE.py:28
Definition: indexed_view.cpp:20
bool g_first_pass
Definition: packetmath_test_shared.h:19
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217
Definition: TensorMeta.h:47
@ Vectorizable
Definition: GenericPacketMath.h:112
void store(T *to, const T &x, unsigned long long) const
Definition: packetmath_test_shared.h:207
T loadu(const T *from) const
Definition: packetmath_test_shared.h:192
T load(const T *from) const
Definition: packetmath_test_shared.h:187
void store(T *to, const T &x) const
Definition: packetmath_test_shared.h:202
T load(const T *from, unsigned long long) const
Definition: packetmath_test_shared.h:197
T & forward_reference(Packet &, T &scalar) const
Definition: packetmath_test_shared.h:212
Definition: packetmath_test_shared.h:152
Packet load(const T *from) const
Definition: packetmath_test_shared.h:154
Packet load(const T *from, unsigned long long umask) const
Definition: packetmath_test_shared.h:164
Packet loadu(const T *from) const
Definition: packetmath_test_shared.h:159
void store(T *to, const Packet &x) const
Definition: packetmath_test_shared.h:169
Packet & forward_reference(Packet &packet, T &) const
Definition: packetmath_test_shared.h:179
void store(T *to, const Packet &x, unsigned long long umask) const
Definition: packetmath_test_shared.h:174
static void run()
Definition: special_packetmath.cpp:145
static void run()
Definition: packetmath_test_shared.h:287
static void run()
Definition: packetmath_test_shared.h:282
static void run()
Definition: packetmath_test_shared.h:274
Definition: packetmath_test_shared.h:270