Home | History | Annotate | Download | only in test
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog (at) 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 using Eigen::Tensor;
     15 
     16 template<typename>
     17 static void test_simple_reshape()
     18 {
     19   Tensor<float, 5> tensor1(2,3,1,7,1);
     20   tensor1.setRandom();
     21 
     22   Tensor<float, 3> tensor2(2,3,7);
     23   Tensor<float, 2> tensor3(6,7);
     24   Tensor<float, 2> tensor4(2,21);
     25 
     26   Tensor<float, 3>::Dimensions dim1(2,3,7);
     27   tensor2 = tensor1.reshape(dim1);
     28   Tensor<float, 2>::Dimensions dim2(6,7);
     29   tensor3 = tensor1.reshape(dim2);
     30   Tensor<float, 2>::Dimensions dim3(2,21);
     31   tensor4 = tensor1.reshape(dim1).reshape(dim3);
     32 
     33   for (int i = 0; i < 2; ++i) {
     34     for (int j = 0; j < 3; ++j) {
     35       for (int k = 0; k < 7; ++k) {
     36         VERIFY_IS_EQUAL(tensor1(i,j,0,k,0), tensor2(i,j,k));
     37         VERIFY_IS_EQUAL(tensor1(i,j,0,k,0), tensor3(i+2*j,k));
     38         VERIFY_IS_EQUAL(tensor1(i,j,0,k,0), tensor4(i,j+3*k));
     39       }
     40     }
     41   }
     42 }
     43 
     44 template<typename>
     45 static void test_reshape_in_expr() {
     46   MatrixXf m1(2,3*5*7*11);
     47   MatrixXf m2(3*5*7*11,13);
     48   m1.setRandom();
     49   m2.setRandom();
     50   MatrixXf m3 = m1 * m2;
     51 
     52   TensorMap<Tensor<float, 5>> tensor1(m1.data(), 2,3,5,7,11);
     53   TensorMap<Tensor<float, 5>> tensor2(m2.data(), 3,5,7,11,13);
     54   Tensor<float, 2>::Dimensions newDims1(2,3*5*7*11);
     55   Tensor<float, 2>::Dimensions newDims2(3*5*7*11,13);
     56   typedef Tensor<float, 1>::DimensionPair DimPair;
     57   array<DimPair, 1> contract_along{{DimPair(1, 0)}};
     58   Tensor<float, 2> tensor3(2,13);
     59   tensor3 = tensor1.reshape(newDims1).contract(tensor2.reshape(newDims2), contract_along);
     60 
     61   Map<MatrixXf> res(tensor3.data(), 2, 13);
     62   for (int i = 0; i < 2; ++i) {
     63     for (int j = 0; j < 13; ++j) {
     64       VERIFY_IS_APPROX(res(i,j), m3(i,j));
     65     }
     66   }
     67 }
     68 
     69 template<typename>
     70 static void test_reshape_as_lvalue()
     71 {
     72   Tensor<float, 3> tensor(2,3,7);
     73   tensor.setRandom();
     74 
     75   Tensor<float, 2> tensor2d(6,7);
     76   Tensor<float, 3>::Dimensions dim(2,3,7);
     77   tensor2d.reshape(dim) = tensor;
     78 
     79   float scratch[2*3*1*7*1];
     80   TensorMap<Tensor<float, 5>> tensor5d(scratch, 2,3,1,7,1);
     81   tensor5d.reshape(dim).device(Eigen::DefaultDevice()) = tensor;
     82 
     83   for (int i = 0; i < 2; ++i) {
     84     for (int j = 0; j < 3; ++j) {
     85       for (int k = 0; k < 7; ++k) {
     86         VERIFY_IS_EQUAL(tensor2d(i+2*j,k), tensor(i,j,k));
     87         VERIFY_IS_EQUAL(tensor5d(i,j,0,k,0), tensor(i,j,k));
     88       }
     89     }
     90   }
     91 }
     92 
     93 template<int DataLayout>
     94 static void test_simple_slice()
     95 {
     96   Tensor<float, 5, DataLayout> tensor(2,3,5,7,11);
     97   tensor.setRandom();
     98 
     99   Tensor<float, 5, DataLayout> slice1(1,1,1,1,1);
    100   Eigen::DSizes<ptrdiff_t, 5> indices(1,2,3,4,5);
    101   Eigen::DSizes<ptrdiff_t, 5> sizes(1,1,1,1,1);
    102   slice1 = tensor.slice(indices, sizes);
    103   VERIFY_IS_EQUAL(slice1(0,0,0,0,0), tensor(1,2,3,4,5));
    104 
    105   Tensor<float, 5, DataLayout> slice2(1,1,2,2,3);
    106   Eigen::DSizes<ptrdiff_t, 5> indices2(1,1,3,4,5);
    107   Eigen::DSizes<ptrdiff_t, 5> sizes2(1,1,2,2,3);
    108   slice2 = tensor.slice(indices2, sizes2);
    109   for (int i = 0; i < 2; ++i) {
    110     for (int j = 0; j < 2; ++j) {
    111       for (int k = 0; k < 3; ++k) {
    112         VERIFY_IS_EQUAL(slice2(0,0,i,j,k), tensor(1,1,3+i,4+j,5+k));
    113       }
    114     }
    115   }
    116 }
    117 
    118 template<typename=void>
    119 static void test_const_slice()
    120 {
    121   const float b[1] = {42};
    122   TensorMap<Tensor<const float, 1> > m(b, 1);
    123   DSizes<DenseIndex, 1> offsets;
    124   offsets[0] = 0;
    125   TensorRef<Tensor<const float, 1> > slice_ref(m.slice(offsets, m.dimensions()));
    126   VERIFY_IS_EQUAL(slice_ref(0), 42);
    127 }
    128 
    129 template<int DataLayout>
    130 static void test_slice_in_expr() {
    131   typedef Matrix<float, Dynamic, Dynamic, DataLayout> Mtx;
    132   Mtx m1(7,7);
    133   Mtx m2(3,3);
    134   m1.setRandom();
    135   m2.setRandom();
    136 
    137   Mtx m3 = m1.block(1, 2, 3, 3) * m2.block(0, 2, 3, 1);
    138 
    139   TensorMap<Tensor<float, 2, DataLayout>> tensor1(m1.data(), 7, 7);
    140   TensorMap<Tensor<float, 2, DataLayout>> tensor2(m2.data(), 3, 3);
    141   Tensor<float, 2, DataLayout> tensor3(3,1);
    142   typedef Tensor<float, 1>::DimensionPair DimPair;
    143   array<DimPair, 1> contract_along{{DimPair(1, 0)}};
    144 
    145   Eigen::DSizes<ptrdiff_t, 2> indices1(1,2);
    146   Eigen::DSizes<ptrdiff_t, 2> sizes1(3,3);
    147   Eigen::DSizes<ptrdiff_t, 2> indices2(0,2);
    148   Eigen::DSizes<ptrdiff_t, 2> sizes2(3,1);
    149   tensor3 = tensor1.slice(indices1, sizes1).contract(tensor2.slice(indices2, sizes2), contract_along);
    150 
    151   Map<Mtx> res(tensor3.data(), 3, 1);
    152   for (int i = 0; i < 3; ++i) {
    153     for (int j = 0; j < 1; ++j) {
    154       VERIFY_IS_APPROX(res(i,j), m3(i,j));
    155     }
    156   }
    157 
    158   // Take an arbitrary slice of an arbitrarily sized tensor.
    159   TensorMap<Tensor<const float, 2, DataLayout>> tensor4(m1.data(), 7, 7);
    160   Tensor<float, 1, DataLayout> tensor6 = tensor4.reshape(DSizes<ptrdiff_t, 1>(7*7)).exp().slice(DSizes<ptrdiff_t, 1>(0), DSizes<ptrdiff_t, 1>(35));
    161   for (int i = 0; i < 35; ++i) {
    162     VERIFY_IS_APPROX(tensor6(i), expf(tensor4.data()[i]));
    163   }
    164 }
    165 
    166 template<int DataLayout>
    167 static void test_slice_as_lvalue()
    168 {
    169   Tensor<float, 3, DataLayout> tensor1(2,2,7);
    170   tensor1.setRandom();
    171   Tensor<float, 3, DataLayout> tensor2(2,2,7);
    172   tensor2.setRandom();
    173   Tensor<float, 3, DataLayout> tensor3(4,3,5);
    174   tensor3.setRandom();
    175   Tensor<float, 3, DataLayout> tensor4(4,3,2);
    176   tensor4.setRandom();
    177   Tensor<float, 3, DataLayout> tensor5(10,13,12);
    178   tensor5.setRandom();
    179 
    180   Tensor<float, 3, DataLayout> result(4,5,7);
    181   Eigen::DSizes<ptrdiff_t, 3> sizes12(2,2,7);
    182   Eigen::DSizes<ptrdiff_t, 3> first_slice(0,0,0);
    183   result.slice(first_slice, sizes12) = tensor1;
    184   Eigen::DSizes<ptrdiff_t, 3> second_slice(2,0,0);
    185   result.slice(second_slice, sizes12).device(Eigen::DefaultDevice()) = tensor2;
    186 
    187   Eigen::DSizes<ptrdiff_t, 3> sizes3(4,3,5);
    188   Eigen::DSizes<ptrdiff_t, 3> third_slice(0,2,0);
    189   result.slice(third_slice, sizes3) = tensor3;
    190 
    191   Eigen::DSizes<ptrdiff_t, 3> sizes4(4,3,2);
    192   Eigen::DSizes<ptrdiff_t, 3> fourth_slice(0,2,5);
    193   result.slice(fourth_slice, sizes4) = tensor4;
    194 
    195   for (int j = 0; j < 2; ++j) {
    196     for (int k = 0; k < 7; ++k) {
    197       for (int i = 0; i < 2; ++i) {
    198         VERIFY_IS_EQUAL(result(i,j,k), tensor1(i,j,k));
    199         VERIFY_IS_EQUAL(result(i+2,j,k), tensor2(i,j,k));
    200       }
    201     }
    202   }
    203   for (int i = 0; i < 4; ++i) {
    204     for (int j = 2; j < 5; ++j) {
    205       for (int k = 0; k < 5; ++k) {
    206         VERIFY_IS_EQUAL(result(i,j,k), tensor3(i,j-2,k));
    207       }
    208       for (int k = 5; k < 7; ++k) {
    209         VERIFY_IS_EQUAL(result(i,j,k), tensor4(i,j-2,k-5));
    210       }
    211     }
    212   }
    213 
    214   Eigen::DSizes<ptrdiff_t, 3> sizes5(4,5,7);
    215   Eigen::DSizes<ptrdiff_t, 3> fifth_slice(0,0,0);
    216   result.slice(fifth_slice, sizes5) = tensor5.slice(fifth_slice, sizes5);
    217   for (int i = 0; i < 4; ++i) {
    218     for (int j = 2; j < 5; ++j) {
    219       for (int k = 0; k < 7; ++k) {
    220         VERIFY_IS_EQUAL(result(i,j,k), tensor5(i,j,k));
    221       }
    222     }
    223   }
    224 }
    225 
    226 template<int DataLayout>
    227 static void test_slice_raw_data()
    228 {
    229   Tensor<float, 4, DataLayout> tensor(3,5,7,11);
    230   tensor.setRandom();
    231 
    232   Eigen::DSizes<ptrdiff_t, 4> offsets(1,2,3,4);
    233   Eigen::DSizes<ptrdiff_t, 4> extents(1,1,1,1);
    234   typedef TensorEvaluator<decltype(tensor.slice(offsets, extents)), DefaultDevice> SliceEvaluator;
    235   auto slice1 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    236   VERIFY_IS_EQUAL(slice1.dimensions().TotalSize(), 1);
    237   VERIFY_IS_EQUAL(slice1.data()[0], tensor(1,2,3,4));
    238 
    239   if (DataLayout == ColMajor) {
    240     extents = Eigen::DSizes<ptrdiff_t, 4>(2,1,1,1);
    241     auto slice2 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    242     VERIFY_IS_EQUAL(slice2.dimensions().TotalSize(), 2);
    243     VERIFY_IS_EQUAL(slice2.data()[0], tensor(1,2,3,4));
    244     VERIFY_IS_EQUAL(slice2.data()[1], tensor(2,2,3,4));
    245   } else {
    246     extents = Eigen::DSizes<ptrdiff_t, 4>(1,1,1,2);
    247     auto slice2 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    248     VERIFY_IS_EQUAL(slice2.dimensions().TotalSize(), 2);
    249     VERIFY_IS_EQUAL(slice2.data()[0], tensor(1,2,3,4));
    250     VERIFY_IS_EQUAL(slice2.data()[1], tensor(1,2,3,5));
    251   }
    252 
    253   extents = Eigen::DSizes<ptrdiff_t, 4>(1,2,1,1);
    254   auto slice3 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    255   VERIFY_IS_EQUAL(slice3.dimensions().TotalSize(), 2);
    256   VERIFY_IS_EQUAL(slice3.data(), static_cast<float*>(0));
    257 
    258   if (DataLayout == ColMajor) {
    259     offsets = Eigen::DSizes<ptrdiff_t, 4>(0,2,3,4);
    260     extents = Eigen::DSizes<ptrdiff_t, 4>(3,2,1,1);
    261     auto slice4 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    262     VERIFY_IS_EQUAL(slice4.dimensions().TotalSize(), 6);
    263     for (int i = 0; i < 3; ++i) {
    264       for (int j = 0; j < 2; ++j) {
    265         VERIFY_IS_EQUAL(slice4.data()[i+3*j], tensor(i,2+j,3,4));
    266       }
    267     }
    268   } else {
    269     offsets = Eigen::DSizes<ptrdiff_t, 4>(1,2,3,0);
    270     extents = Eigen::DSizes<ptrdiff_t, 4>(1,1,2,11);
    271     auto slice4 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    272     VERIFY_IS_EQUAL(slice4.dimensions().TotalSize(), 22);
    273     for (int l = 0; l < 11; ++l) {
    274       for (int k = 0; k < 2; ++k) {
    275         VERIFY_IS_EQUAL(slice4.data()[l+11*k], tensor(1,2,3+k,l));
    276       }
    277     }
    278   }
    279 
    280   if (DataLayout == ColMajor) {
    281     offsets = Eigen::DSizes<ptrdiff_t, 4>(0,0,0,4);
    282     extents = Eigen::DSizes<ptrdiff_t, 4>(3,5,7,2);
    283     auto slice5 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    284     VERIFY_IS_EQUAL(slice5.dimensions().TotalSize(), 210);
    285     for (int i = 0; i < 3; ++i) {
    286       for (int j = 0; j < 5; ++j) {
    287         for (int k = 0; k < 7; ++k) {
    288           for (int l = 0; l < 2; ++l) {
    289             int slice_index = i + 3 * (j + 5 * (k + 7 * l));
    290             VERIFY_IS_EQUAL(slice5.data()[slice_index], tensor(i,j,k,l+4));
    291           }
    292         }
    293       }
    294     }
    295   } else {
    296     offsets = Eigen::DSizes<ptrdiff_t, 4>(1,0,0,0);
    297     extents = Eigen::DSizes<ptrdiff_t, 4>(2,5,7,11);
    298     auto slice5 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    299     VERIFY_IS_EQUAL(slice5.dimensions().TotalSize(), 770);
    300     for (int l = 0; l < 11; ++l) {
    301       for (int k = 0; k < 7; ++k) {
    302         for (int j = 0; j < 5; ++j) {
    303           for (int i = 0; i < 2; ++i) {
    304             int slice_index = l + 11 * (k + 7 * (j + 5 * i));
    305             VERIFY_IS_EQUAL(slice5.data()[slice_index], tensor(i+1,j,k,l));
    306           }
    307         }
    308       }
    309     }
    310 
    311   }
    312 
    313   offsets = Eigen::DSizes<ptrdiff_t, 4>(0,0,0,0);
    314   extents = Eigen::DSizes<ptrdiff_t, 4>(3,5,7,11);
    315   auto slice6 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice());
    316   VERIFY_IS_EQUAL(slice6.dimensions().TotalSize(), 3*5*7*11);
    317   VERIFY_IS_EQUAL(slice6.data(), tensor.data());
    318 }
    319 
    320 
    321 template<int DataLayout>
    322 static void test_strided_slice()
    323 {
    324   typedef Tensor<float, 5, DataLayout> Tensor5f;
    325   typedef Eigen::DSizes<Eigen::DenseIndex, 5> Index5;
    326   typedef Tensor<float, 2, DataLayout> Tensor2f;
    327   typedef Eigen::DSizes<Eigen::DenseIndex, 2> Index2;
    328   Tensor<float, 5, DataLayout> tensor(2,3,5,7,11);
    329   Tensor<float, 2, DataLayout> tensor2(7,11);
    330   tensor.setRandom();
    331   tensor2.setRandom();
    332 
    333   if (true) {
    334     Tensor2f slice(2,3);
    335     Index2 strides(-2,-1);
    336     Index2 indicesStart(5,7);
    337     Index2 indicesStop(0,4);
    338     slice = tensor2.stridedSlice(indicesStart, indicesStop, strides);
    339     for (int j = 0; j < 2; ++j) {
    340       for (int k = 0; k < 3; ++k) {
    341         VERIFY_IS_EQUAL(slice(j,k), tensor2(5-2*j,7-k));
    342       }
    343     }
    344   }
    345 
    346   if(true) {
    347     Tensor2f slice(0,1);
    348     Index2 strides(1,1);
    349     Index2 indicesStart(5,4);
    350     Index2 indicesStop(5,5);
    351     slice = tensor2.stridedSlice(indicesStart, indicesStop, strides);
    352   }
    353 
    354   if(true) { // test clamped degenerate interavls
    355     Tensor2f slice(7,11);
    356     Index2 strides(1,-1);
    357     Index2 indicesStart(-3,20); // should become 0,10
    358     Index2 indicesStop(20,-11); // should become 11, -1
    359     slice = tensor2.stridedSlice(indicesStart, indicesStop, strides);
    360     for (int j = 0; j < 7; ++j) {
    361       for (int k = 0; k < 11; ++k) {
    362         VERIFY_IS_EQUAL(slice(j,k), tensor2(j,10-k));
    363       }
    364     }
    365   }
    366 
    367   if(true) {
    368     Tensor5f slice1(1,1,1,1,1);
    369     Eigen::DSizes<Eigen::DenseIndex, 5> indicesStart(1, 2, 3, 4, 5);
    370     Eigen::DSizes<Eigen::DenseIndex, 5> indicesStop(2, 3, 4, 5, 6);
    371     Eigen::DSizes<Eigen::DenseIndex, 5> strides(1, 1, 1, 1, 1);
    372     slice1 = tensor.stridedSlice(indicesStart, indicesStop, strides);
    373     VERIFY_IS_EQUAL(slice1(0,0,0,0,0), tensor(1,2,3,4,5));
    374   }
    375 
    376   if(true) {
    377     Tensor5f slice(1,1,2,2,3);
    378     Index5 start(1, 1, 3, 4, 5);
    379     Index5 stop(2, 2, 5, 6, 8);
    380     Index5 strides(1, 1, 1, 1, 1);
    381     slice = tensor.stridedSlice(start, stop, strides);
    382     for (int i = 0; i < 2; ++i) {
    383       for (int j = 0; j < 2; ++j) {
    384         for (int k = 0; k < 3; ++k) {
    385           VERIFY_IS_EQUAL(slice(0,0,i,j,k), tensor(1,1,3+i,4+j,5+k));
    386         }
    387       }
    388     }
    389   }
    390 
    391   if(true) {
    392     Tensor5f slice(1,1,2,2,3);
    393     Index5 strides3(1, 1, -2, 1, -1);
    394     Index5 indices3Start(1, 1, 4, 4, 7);
    395     Index5 indices3Stop(2, 2, 0, 6, 4);
    396     slice = tensor.stridedSlice(indices3Start, indices3Stop, strides3);
    397     for (int i = 0; i < 2; ++i) {
    398       for (int j = 0; j < 2; ++j) {
    399         for (int k = 0; k < 3; ++k) {
    400           VERIFY_IS_EQUAL(slice(0,0,i,j,k), tensor(1,1,4-2*i,4+j,7-k));
    401         }
    402       }
    403     }
    404   }
    405 
    406   if(false) { // tests degenerate interval
    407     Tensor5f slice(1,1,2,2,3);
    408     Index5 strides3(1, 1, 2, 1, 1);
    409     Index5 indices3Start(1, 1, 4, 4, 7);
    410     Index5 indices3Stop(2, 2, 0, 6, 4);
    411     slice = tensor.stridedSlice(indices3Start, indices3Stop, strides3);
    412   }
    413 }
    414 
    415 template<int DataLayout>
    416 static void test_strided_slice_write()
    417 {
    418   typedef Tensor<float, 2, DataLayout> Tensor2f;
    419   typedef Eigen::DSizes<Eigen::DenseIndex, 2> Index2;
    420 
    421   Tensor<float, 2, DataLayout> tensor(7,11),tensor2(7,11);
    422   tensor.setRandom();
    423   tensor2=tensor;
    424   Tensor2f slice(2,3);
    425 
    426   slice.setRandom();
    427 
    428   Index2 strides(1,1);
    429   Index2 indicesStart(3,4);
    430   Index2 indicesStop(5,7);
    431   Index2 lengths(2,3);
    432 
    433   tensor.slice(indicesStart,lengths)=slice;
    434   tensor2.stridedSlice(indicesStart,indicesStop,strides)=slice;
    435 
    436   for(int i=0;i<7;i++) for(int j=0;j<11;j++){
    437     VERIFY_IS_EQUAL(tensor(i,j), tensor2(i,j));
    438   }
    439 }
    440 
    441 
    442 template<int DataLayout>
    443 static void test_composition()
    444 {
    445   Eigen::Tensor<float, 2, DataLayout> matrix(7, 11);
    446   matrix.setRandom();
    447 
    448   const DSizes<ptrdiff_t, 3> newDims(1, 1, 11);
    449   Eigen::Tensor<float, 3, DataLayout> tensor =
    450       matrix.slice(DSizes<ptrdiff_t, 2>(2, 0), DSizes<ptrdiff_t, 2>(1, 11)).reshape(newDims);
    451 
    452   VERIFY_IS_EQUAL(tensor.dimensions().TotalSize(), 11);
    453   VERIFY_IS_EQUAL(tensor.dimension(0), 1);
    454   VERIFY_IS_EQUAL(tensor.dimension(1), 1);
    455   VERIFY_IS_EQUAL(tensor.dimension(2), 11);
    456   for (int i = 0; i < 11; ++i) {
    457     VERIFY_IS_EQUAL(tensor(0,0,i), matrix(2,i));
    458   }
    459 }
    460 
    461 
    462 void test_cxx11_tensor_morphing()
    463 {
    464   CALL_SUBTEST_1(test_simple_reshape<void>());
    465   CALL_SUBTEST_1(test_reshape_in_expr<void>());
    466   CALL_SUBTEST_1(test_reshape_as_lvalue<void>());
    467 
    468   CALL_SUBTEST_1(test_simple_slice<ColMajor>());
    469   CALL_SUBTEST_1(test_simple_slice<RowMajor>());
    470   CALL_SUBTEST_1(test_const_slice());
    471   CALL_SUBTEST_2(test_slice_in_expr<ColMajor>());
    472   CALL_SUBTEST_3(test_slice_in_expr<RowMajor>());
    473   CALL_SUBTEST_4(test_slice_as_lvalue<ColMajor>());
    474   CALL_SUBTEST_4(test_slice_as_lvalue<RowMajor>());
    475   CALL_SUBTEST_5(test_slice_raw_data<ColMajor>());
    476   CALL_SUBTEST_5(test_slice_raw_data<RowMajor>());
    477 
    478   CALL_SUBTEST_6(test_strided_slice_write<ColMajor>());
    479   CALL_SUBTEST_6(test_strided_slice<ColMajor>());
    480   CALL_SUBTEST_6(test_strided_slice_write<RowMajor>());
    481   CALL_SUBTEST_6(test_strided_slice<RowMajor>());
    482 
    483   CALL_SUBTEST_7(test_composition<ColMajor>());
    484   CALL_SUBTEST_7(test_composition<RowMajor>());
    485 }
    486