cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

array_reverse.cpp (6383B)


      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;
     19   typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
     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 
     45   Reverse<MatrixType, BothDirections> m1_rb(m1);
     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 
     53   Reverse<MatrixType, Vertical> m1_rv(m1);
     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 
     61   Reverse<MatrixType, Horizontal> m1_rh(m1);
     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>
    127 void array_reverse_extra()
    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>
    140 EIGEN_DONT_INLINE
    141 void bug1684_job1(MatrixType& m1, MatrixType& m2)
    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>
    149 EIGEN_DONT_INLINE
    150 void bug1684_job2(MatrixType& m1, MatrixType& m2)
    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>
    160 EIGEN_DONT_INLINE
    161 void bug1684_job3(MatrixType& m1, MatrixType& m2)
    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 
    189 EIGEN_DECLARE_TEST(array_reverse)
    190 {
    191   for(int i = 0; i < g_repeat; i++) {
    192     CALL_SUBTEST_1( reverse(Matrix<float, 1, 1>()) );
    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))) );
    199     CALL_SUBTEST_8( reverse(Matrix<float, 100, 100>()) );
    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 }