array_reverse.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) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2009 Ricard Marxer <email@ricardmarxer.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 <iostream>
13 
14 using namespace std;
15 
16 template<typename MatrixType> void reverse(const MatrixType& m)
17 {
18  typedef typename MatrixType::Scalar Scalar;
20 
21  Index rows = m.rows();
22  Index cols = m.cols();
23 
24  // this test relies a lot on Random.h, and there's not much more that we can do
25  // to test it, hence I consider that we will have tested Random.h
26  MatrixType m1 = MatrixType::Random(rows, cols), m2;
27  VectorType v1 = VectorType::Random(rows);
28 
29  MatrixType m1_r = m1.reverse();
30  // Verify that MatrixBase::reverse() works
31  for ( int i = 0; i < rows; i++ ) {
32  for ( int j = 0; j < cols; j++ ) {
33  VERIFY_IS_APPROX(m1_r(i, j), m1(rows - 1 - i, cols - 1 - j));
34  }
35  }
36 
37  Reverse<MatrixType> m1_rd(m1);
38  // Verify that a Reverse default (in both directions) of an expression works
39  for ( int i = 0; i < rows; i++ ) {
40  for ( int j = 0; j < cols; j++ ) {
41  VERIFY_IS_APPROX(m1_rd(i, j), m1(rows - 1 - i, cols - 1 - j));
42  }
43  }
44 
46  // Verify that a Reverse in both directions of an expression works
47  for ( int i = 0; i < rows; i++ ) {
48  for ( int j = 0; j < cols; j++ ) {
49  VERIFY_IS_APPROX(m1_rb(i, j), m1(rows - 1 - i, cols - 1 - j));
50  }
51  }
52 
54  // Verify that a Reverse in the vertical directions of an expression works
55  for ( int i = 0; i < rows; i++ ) {
56  for ( int j = 0; j < cols; j++ ) {
57  VERIFY_IS_APPROX(m1_rv(i, j), m1(rows - 1 - i, j));
58  }
59  }
60 
62  // Verify that a Reverse in the horizontal directions of an expression works
63  for ( int i = 0; i < rows; i++ ) {
64  for ( int j = 0; j < cols; j++ ) {
65  VERIFY_IS_APPROX(m1_rh(i, j), m1(i, cols - 1 - j));
66  }
67  }
68 
69  VectorType v1_r = v1.reverse();
70  // Verify that a VectorType::reverse() of an expression works
71  for ( int i = 0; i < rows; i++ ) {
72  VERIFY_IS_APPROX(v1_r(i), v1(rows - 1 - i));
73  }
74 
75  MatrixType m1_cr = m1.colwise().reverse();
76  // Verify that PartialRedux::reverse() works (for colwise())
77  for ( int i = 0; i < rows; i++ ) {
78  for ( int j = 0; j < cols; j++ ) {
79  VERIFY_IS_APPROX(m1_cr(i, j), m1(rows - 1 - i, j));
80  }
81  }
82 
83  MatrixType m1_rr = m1.rowwise().reverse();
84  // Verify that PartialRedux::reverse() works (for rowwise())
85  for ( int i = 0; i < rows; i++ ) {
86  for ( int j = 0; j < cols; j++ ) {
87  VERIFY_IS_APPROX(m1_rr(i, j), m1(i, cols - 1 - j));
88  }
89  }
90 
91  Scalar x = internal::random<Scalar>();
92 
93  Index r = internal::random<Index>(0, rows-1),
94  c = internal::random<Index>(0, cols-1);
95 
96  m1.reverse()(r, c) = x;
97  VERIFY_IS_APPROX(x, m1(rows - 1 - r, cols - 1 - c));
98 
99  m2 = m1;
100  m2.reverseInPlace();
101  VERIFY_IS_APPROX(m2,m1.reverse().eval());
102 
103  m2 = m1;
104  m2.col(0).reverseInPlace();
105  VERIFY_IS_APPROX(m2.col(0),m1.col(0).reverse().eval());
106 
107  m2 = m1;
108  m2.row(0).reverseInPlace();
109  VERIFY_IS_APPROX(m2.row(0),m1.row(0).reverse().eval());
110 
111  m2 = m1;
112  m2.rowwise().reverseInPlace();
113  VERIFY_IS_APPROX(m2,m1.rowwise().reverse().eval());
114 
115  m2 = m1;
116  m2.colwise().reverseInPlace();
117  VERIFY_IS_APPROX(m2,m1.colwise().reverse().eval());
118 
119  m1.colwise().reverse()(r, c) = x;
120  VERIFY_IS_APPROX(x, m1(rows - 1 - r, c));
121 
122  m1.rowwise().reverse()(r, c) = x;
123  VERIFY_IS_APPROX(x, m1(r, cols - 1 - c));
124 }
125 
126 template<int>
128 {
129  Vector4f x; x << 1, 2, 3, 4;
130  Vector4f y; y << 4, 3, 2, 1;
131  VERIFY(x.reverse()[1] == 3);
132  VERIFY(x.reverse() == y);
133 }
134 
135 // Simpler version of reverseInPlace leveraging a bug
136 // in clang 6/7 with -O2 and AVX or AVX512 enabled.
137 // This simpler version ensure that the clang bug is not simply hidden
138 // through mis-inlining of reverseInPlace or other minor changes.
139 template<typename MatrixType>
142 {
143  m2 = m1;
144  m2.col(0).swap(m2.col(3));
145  m2.col(1).swap(m2.col(2));
146 }
147 
148 template<typename MatrixType>
151 {
152  m2 = m1; // load m1/m2 in AVX registers
153  m1.col(0) = m2.col(3); // perform 128 bits moves
154  m1.col(1) = m2.col(2);
155  m1.col(2) = m2.col(1);
156  m1.col(3) = m2.col(0);
157 }
158 
159 template<typename MatrixType>
162 {
163  m2 = m1;
164  Vector4f tmp;
165  tmp = m2.col(0);
166  m2.col(0) = m2.col(3);
167  m2.col(3) = tmp;
168  tmp = m2.col(1);
169  m2.col(1) = m2.col(2);
170  m2.col(2) = tmp;
171 
172 }
173 
174 template<int>
175 void bug1684()
176 {
177  Matrix4f m1 = Matrix4f::Random();
178  Matrix4f m2 = Matrix4f::Random();
179  bug1684_job1(m1,m2);
180  VERIFY_IS_APPROX(m2, m1.rowwise().reverse().eval());
181  bug1684_job2(m1,m2);
182  VERIFY_IS_APPROX(m2, m1.rowwise().reverse().eval());
183  // This one still fail after our swap's workaround,
184  // but I expect users not to implement their own swap.
185  // bug1684_job3(m1,m2);
186  // VERIFY_IS_APPROX(m2, m1.rowwise().reverse().eval());
187 }
188 
190 {
191  for(int i = 0; i < g_repeat; i++) {
193  CALL_SUBTEST_2( reverse(Matrix2f()) );
194  CALL_SUBTEST_3( reverse(Matrix4f()) );
195  CALL_SUBTEST_4( reverse(Matrix4d()) );
196  CALL_SUBTEST_5( reverse(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
197  CALL_SUBTEST_6( reverse(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
198  CALL_SUBTEST_7( reverse(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
200  CALL_SUBTEST_9( reverse(Matrix<float,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
201  CALL_SUBTEST_3( bug1684<0>() );
202  }
203  CALL_SUBTEST_3( array_reverse_extra<0>() );
204 }
Matrix3f m
constexpr EIGEN_STRONG_INLINE array< T, N > array_reverse(array< T, N > arr)
Definition: CXX11Meta.h:344
SCALAR Scalar
Definition: bench_gemm.cpp:46
#define CALL_SUBTEST_9(FUNC)
#define CALL_SUBTEST_6(FUNC)
void bug1684()
#define CALL_SUBTEST_4(FUNC)
Scalar * y
Vector v1
void array_reverse_extra()
#define CALL_SUBTEST_3(FUNC)
MatrixType m2(n_dims)
#define CALL_SUBTEST_7(FUNC)
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
Definition: BFloat16.h:88
MatrixXf MatrixType
#define EIGEN_DONT_INLINE
Definition: Macros.h:940
#define VERIFY_IS_APPROX(a, b)
#define CALL_SUBTEST_1(FUNC)
Matrix3d m1
Definition: IOFormat.cpp:2
static int g_repeat
Definition: main.h:169
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:74
#define CALL_SUBTEST_8(FUNC)
EIGEN_DECLARE_TEST(array_reverse)
EIGEN_DONT_INLINE void bug1684_job3(MatrixType &m1, MatrixType &m2)
EIGEN_DONT_INLINE void bug1684_job1(MatrixType &m1, MatrixType &m2)
#define CALL_SUBTEST_5(FUNC)
#define VERIFY(a)
Definition: main.h:380
void reverse(const MatrixType &m)
#define EIGEN_TEST_MAX_SIZE
EIGEN_DONT_INLINE void bug1684_job2(MatrixType &m1, MatrixType &m2)
#define CALL_SUBTEST_2(FUNC)
The matrix class, also used for vectors and row-vectors.
Expression of the reverse of a vector or matrix.
Definition: Reverse.h:63
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
std::ptrdiff_t j


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:33:54