cxx11_tensor_morphing.cpp (18215B)
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@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_static_reshape() { 46 #if defined(EIGEN_HAS_INDEX_LIST) 47 using Eigen::type2index; 48 49 Tensor<float, 5> tensor(2, 3, 1, 7, 1); 50 tensor.setRandom(); 51 52 // New dimensions: [2, 3, 7] 53 Eigen::IndexList<type2index<2>, type2index<3>, type2index<7>> dim; 54 Tensor<float, 3> reshaped = tensor.reshape(static_cast<Eigen::DSizes<ptrdiff_t,3>>(dim)); 55 56 for (int i = 0; i < 2; ++i) { 57 for (int j = 0; j < 3; ++j) { 58 for (int k = 0; k < 7; ++k) { 59 VERIFY_IS_EQUAL(tensor(i, j, 0, k, 0), reshaped(i, j, k)); 60 } 61 } 62 } 63 #endif 64 } 65 66 template <typename> 67 static void test_reshape_in_expr() { 68 MatrixXf m1(2,3*5*7*11); 69 MatrixXf m2(3*5*7*11,13); 70 m1.setRandom(); 71 m2.setRandom(); 72 MatrixXf m3 = m1 * m2; 73 74 TensorMap<Tensor<float, 5>> tensor1(m1.data(), 2,3,5,7,11); 75 TensorMap<Tensor<float, 5>> tensor2(m2.data(), 3,5,7,11,13); 76 Tensor<float, 2>::Dimensions newDims1(2,3*5*7*11); 77 Tensor<float, 2>::Dimensions newDims2(3*5*7*11,13); 78 typedef Tensor<float, 1>::DimensionPair DimPair; 79 array<DimPair, 1> contract_along{{DimPair(1, 0)}}; 80 Tensor<float, 2> tensor3(2,13); 81 tensor3 = tensor1.reshape(newDims1).contract(tensor2.reshape(newDims2), contract_along); 82 83 Map<MatrixXf> res(tensor3.data(), 2, 13); 84 for (int i = 0; i < 2; ++i) { 85 for (int j = 0; j < 13; ++j) { 86 VERIFY_IS_APPROX(res(i,j), m3(i,j)); 87 } 88 } 89 } 90 91 template<typename> 92 static void test_reshape_as_lvalue() 93 { 94 Tensor<float, 3> tensor(2,3,7); 95 tensor.setRandom(); 96 97 Tensor<float, 2> tensor2d(6,7); 98 Tensor<float, 3>::Dimensions dim(2,3,7); 99 tensor2d.reshape(dim) = tensor; 100 101 float scratch[2*3*1*7*1]; 102 TensorMap<Tensor<float, 5>> tensor5d(scratch, 2,3,1,7,1); 103 tensor5d.reshape(dim).device(Eigen::DefaultDevice()) = tensor; 104 105 for (int i = 0; i < 2; ++i) { 106 for (int j = 0; j < 3; ++j) { 107 for (int k = 0; k < 7; ++k) { 108 VERIFY_IS_EQUAL(tensor2d(i+2*j,k), tensor(i,j,k)); 109 VERIFY_IS_EQUAL(tensor5d(i,j,0,k,0), tensor(i,j,k)); 110 } 111 } 112 } 113 } 114 115 template<typename T, int DataLayout> 116 static void test_simple_slice() 117 { 118 Tensor<T, 5, DataLayout> tensor(2,3,5,7,11); 119 tensor.setRandom(); 120 121 Tensor<T, 5, DataLayout> slice1(1,1,1,1,1); 122 Eigen::DSizes<ptrdiff_t, 5> indices(1,2,3,4,5); 123 Eigen::DSizes<ptrdiff_t, 5> sizes(1,1,1,1,1); 124 slice1 = tensor.slice(indices, sizes); 125 VERIFY_IS_EQUAL(slice1(0,0,0,0,0), tensor(1,2,3,4,5)); 126 127 Tensor<T, 5, DataLayout> slice2(1,1,2,2,3); 128 Eigen::DSizes<ptrdiff_t, 5> indices2(1,1,3,4,5); 129 Eigen::DSizes<ptrdiff_t, 5> sizes2(1,1,2,2,3); 130 slice2 = tensor.slice(indices2, sizes2); 131 for (int i = 0; i < 2; ++i) { 132 for (int j = 0; j < 2; ++j) { 133 for (int k = 0; k < 3; ++k) { 134 VERIFY_IS_EQUAL(slice2(0,0,i,j,k), tensor(1,1,3+i,4+j,5+k)); 135 } 136 } 137 } 138 } 139 140 template<typename T> 141 static void test_const_slice() 142 { 143 const T b[1] = {42}; 144 TensorMap<Tensor<const T, 1> > m(b, 1); 145 DSizes<DenseIndex, 1> offsets; 146 offsets[0] = 0; 147 TensorRef<Tensor<const T, 1> > slice_ref(m.slice(offsets, m.dimensions())); 148 VERIFY_IS_EQUAL(slice_ref(0), 42); 149 } 150 151 template<typename T, int DataLayout> 152 static void test_slice_in_expr() { 153 typedef Matrix<T, Dynamic, Dynamic, DataLayout> Mtx; 154 Mtx m1(7,7); 155 Mtx m2(3,3); 156 m1.setRandom(); 157 m2.setRandom(); 158 159 Mtx m3 = m1.block(1, 2, 3, 3) * m2.block(0, 2, 3, 1); 160 161 TensorMap<Tensor<T, 2, DataLayout>> tensor1(m1.data(), 7, 7); 162 TensorMap<Tensor<T, 2, DataLayout>> tensor2(m2.data(), 3, 3); 163 Tensor<T, 2, DataLayout> tensor3(3,1); 164 typedef typename Tensor<T, 1>::DimensionPair DimPair; 165 array<DimPair, 1> contract_along{{DimPair(1, 0)}}; 166 167 Eigen::DSizes<ptrdiff_t, 2> indices1(1,2); 168 Eigen::DSizes<ptrdiff_t, 2> sizes1(3,3); 169 Eigen::DSizes<ptrdiff_t, 2> indices2(0,2); 170 Eigen::DSizes<ptrdiff_t, 2> sizes2(3,1); 171 tensor3 = tensor1.slice(indices1, sizes1).contract(tensor2.slice(indices2, sizes2), contract_along); 172 173 Map<Mtx> res(tensor3.data(), 3, 1); 174 for (int i = 0; i < 3; ++i) { 175 for (int j = 0; j < 1; ++j) { 176 VERIFY_IS_APPROX(res(i,j), m3(i,j)); 177 } 178 } 179 180 // Take an arbitrary slice of an arbitrarily sized tensor. 181 TensorMap<Tensor<const T, 2, DataLayout>> tensor4(m1.data(), 7, 7); 182 Tensor<T, 1, DataLayout> tensor6 = tensor4.reshape(DSizes<ptrdiff_t, 1>(7*7)).exp().slice(DSizes<ptrdiff_t, 1>(0), DSizes<ptrdiff_t, 1>(35)); 183 for (int i = 0; i < 35; ++i) { 184 VERIFY_IS_APPROX(tensor6(i), expf(tensor4.data()[i])); 185 } 186 } 187 188 template<typename T, int DataLayout> 189 static void test_slice_as_lvalue() 190 { 191 Tensor<T, 3, DataLayout> tensor1(2,2,7); 192 tensor1.setRandom(); 193 Tensor<T, 3, DataLayout> tensor2(2,2,7); 194 tensor2.setRandom(); 195 Tensor<T, 3, DataLayout> tensor3(4,3,5); 196 tensor3.setRandom(); 197 Tensor<T, 3, DataLayout> tensor4(4,3,2); 198 tensor4.setRandom(); 199 Tensor<T, 3, DataLayout> tensor5(10,13,12); 200 tensor5.setRandom(); 201 202 Tensor<T, 3, DataLayout> result(4,5,7); 203 Eigen::DSizes<ptrdiff_t, 3> sizes12(2,2,7); 204 Eigen::DSizes<ptrdiff_t, 3> first_slice(0,0,0); 205 result.slice(first_slice, sizes12) = tensor1; 206 Eigen::DSizes<ptrdiff_t, 3> second_slice(2,0,0); 207 result.slice(second_slice, sizes12).device(Eigen::DefaultDevice()) = tensor2; 208 209 Eigen::DSizes<ptrdiff_t, 3> sizes3(4,3,5); 210 Eigen::DSizes<ptrdiff_t, 3> third_slice(0,2,0); 211 result.slice(third_slice, sizes3) = tensor3; 212 213 Eigen::DSizes<ptrdiff_t, 3> sizes4(4,3,2); 214 Eigen::DSizes<ptrdiff_t, 3> fourth_slice(0,2,5); 215 result.slice(fourth_slice, sizes4) = tensor4; 216 217 for (int j = 0; j < 2; ++j) { 218 for (int k = 0; k < 7; ++k) { 219 for (int i = 0; i < 2; ++i) { 220 VERIFY_IS_EQUAL(result(i,j,k), tensor1(i,j,k)); 221 VERIFY_IS_EQUAL(result(i+2,j,k), tensor2(i,j,k)); 222 } 223 } 224 } 225 for (int i = 0; i < 4; ++i) { 226 for (int j = 2; j < 5; ++j) { 227 for (int k = 0; k < 5; ++k) { 228 VERIFY_IS_EQUAL(result(i,j,k), tensor3(i,j-2,k)); 229 } 230 for (int k = 5; k < 7; ++k) { 231 VERIFY_IS_EQUAL(result(i,j,k), tensor4(i,j-2,k-5)); 232 } 233 } 234 } 235 236 Eigen::DSizes<ptrdiff_t, 3> sizes5(4,5,7); 237 Eigen::DSizes<ptrdiff_t, 3> fifth_slice(0,0,0); 238 result.slice(fifth_slice, sizes5) = tensor5.slice(fifth_slice, sizes5); 239 for (int i = 0; i < 4; ++i) { 240 for (int j = 2; j < 5; ++j) { 241 for (int k = 0; k < 7; ++k) { 242 VERIFY_IS_EQUAL(result(i,j,k), tensor5(i,j,k)); 243 } 244 } 245 } 246 } 247 248 template<typename T, int DataLayout> 249 static void test_slice_raw_data() 250 { 251 Tensor<T, 4, DataLayout> tensor(3,5,7,11); 252 tensor.setRandom(); 253 254 Eigen::DSizes<ptrdiff_t, 4> offsets(1,2,3,4); 255 Eigen::DSizes<ptrdiff_t, 4> extents(1,1,1,1); 256 typedef TensorEvaluator<decltype(tensor.slice(offsets, extents)), DefaultDevice> SliceEvaluator; 257 auto slice1 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 258 VERIFY_IS_EQUAL(slice1.dimensions().TotalSize(), 1); 259 VERIFY_IS_EQUAL(slice1.data()[0], tensor(1,2,3,4)); 260 261 if (DataLayout == ColMajor) { 262 extents = Eigen::DSizes<ptrdiff_t, 4>(2,1,1,1); 263 auto slice2 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 264 VERIFY_IS_EQUAL(slice2.dimensions().TotalSize(), 2); 265 VERIFY_IS_EQUAL(slice2.data()[0], tensor(1,2,3,4)); 266 VERIFY_IS_EQUAL(slice2.data()[1], tensor(2,2,3,4)); 267 } else { 268 extents = Eigen::DSizes<ptrdiff_t, 4>(1,1,1,2); 269 auto slice2 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 270 VERIFY_IS_EQUAL(slice2.dimensions().TotalSize(), 2); 271 VERIFY_IS_EQUAL(slice2.data()[0], tensor(1,2,3,4)); 272 VERIFY_IS_EQUAL(slice2.data()[1], tensor(1,2,3,5)); 273 } 274 275 extents = Eigen::DSizes<ptrdiff_t, 4>(1,2,1,1); 276 auto slice3 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 277 VERIFY_IS_EQUAL(slice3.dimensions().TotalSize(), 2); 278 VERIFY_IS_EQUAL(slice3.data(), static_cast<T*>(0)); 279 280 if (DataLayout == ColMajor) { 281 offsets = Eigen::DSizes<ptrdiff_t, 4>(0,2,3,4); 282 extents = Eigen::DSizes<ptrdiff_t, 4>(3,2,1,1); 283 auto slice4 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 284 VERIFY_IS_EQUAL(slice4.dimensions().TotalSize(), 6); 285 for (int i = 0; i < 3; ++i) { 286 for (int j = 0; j < 2; ++j) { 287 VERIFY_IS_EQUAL(slice4.data()[i+3*j], tensor(i,2+j,3,4)); 288 } 289 } 290 } else { 291 offsets = Eigen::DSizes<ptrdiff_t, 4>(1,2,3,0); 292 extents = Eigen::DSizes<ptrdiff_t, 4>(1,1,2,11); 293 auto slice4 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 294 VERIFY_IS_EQUAL(slice4.dimensions().TotalSize(), 22); 295 for (int l = 0; l < 11; ++l) { 296 for (int k = 0; k < 2; ++k) { 297 VERIFY_IS_EQUAL(slice4.data()[l+11*k], tensor(1,2,3+k,l)); 298 } 299 } 300 } 301 302 if (DataLayout == ColMajor) { 303 offsets = Eigen::DSizes<ptrdiff_t, 4>(0,0,0,4); 304 extents = Eigen::DSizes<ptrdiff_t, 4>(3,5,7,2); 305 auto slice5 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 306 VERIFY_IS_EQUAL(slice5.dimensions().TotalSize(), 210); 307 for (int i = 0; i < 3; ++i) { 308 for (int j = 0; j < 5; ++j) { 309 for (int k = 0; k < 7; ++k) { 310 for (int l = 0; l < 2; ++l) { 311 int slice_index = i + 3 * (j + 5 * (k + 7 * l)); 312 VERIFY_IS_EQUAL(slice5.data()[slice_index], tensor(i,j,k,l+4)); 313 } 314 } 315 } 316 } 317 } else { 318 offsets = Eigen::DSizes<ptrdiff_t, 4>(1,0,0,0); 319 extents = Eigen::DSizes<ptrdiff_t, 4>(2,5,7,11); 320 auto slice5 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 321 VERIFY_IS_EQUAL(slice5.dimensions().TotalSize(), 770); 322 for (int l = 0; l < 11; ++l) { 323 for (int k = 0; k < 7; ++k) { 324 for (int j = 0; j < 5; ++j) { 325 for (int i = 0; i < 2; ++i) { 326 int slice_index = l + 11 * (k + 7 * (j + 5 * i)); 327 VERIFY_IS_EQUAL(slice5.data()[slice_index], tensor(i+1,j,k,l)); 328 } 329 } 330 } 331 } 332 333 } 334 335 offsets = Eigen::DSizes<ptrdiff_t, 4>(0,0,0,0); 336 extents = Eigen::DSizes<ptrdiff_t, 4>(3,5,7,11); 337 auto slice6 = SliceEvaluator(tensor.slice(offsets, extents), DefaultDevice()); 338 VERIFY_IS_EQUAL(slice6.dimensions().TotalSize(), 3*5*7*11); 339 VERIFY_IS_EQUAL(slice6.data(), tensor.data()); 340 } 341 342 343 template<typename T, int DataLayout> 344 static void test_strided_slice() 345 { 346 typedef Tensor<T, 5, DataLayout> Tensor5f; 347 typedef Eigen::DSizes<Eigen::DenseIndex, 5> Index5; 348 typedef Tensor<T, 2, DataLayout> Tensor2f; 349 typedef Eigen::DSizes<Eigen::DenseIndex, 2> Index2; 350 Tensor<T, 5, DataLayout> tensor(2,3,5,7,11); 351 Tensor<T, 2, DataLayout> tensor2(7,11); 352 tensor.setRandom(); 353 tensor2.setRandom(); 354 355 if (true) { 356 Tensor2f slice(2,3); 357 Index2 strides(-2,-1); 358 Index2 indicesStart(5,7); 359 Index2 indicesStop(0,4); 360 slice = tensor2.stridedSlice(indicesStart, indicesStop, strides); 361 for (int j = 0; j < 2; ++j) { 362 for (int k = 0; k < 3; ++k) { 363 VERIFY_IS_EQUAL(slice(j,k), tensor2(5-2*j,7-k)); 364 } 365 } 366 } 367 368 if(true) { 369 Tensor2f slice(0,1); 370 Index2 strides(1,1); 371 Index2 indicesStart(5,4); 372 Index2 indicesStop(5,5); 373 slice = tensor2.stridedSlice(indicesStart, indicesStop, strides); 374 } 375 376 if(true) { // test clamped degenerate interavls 377 Tensor2f slice(7,11); 378 Index2 strides(1,-1); 379 Index2 indicesStart(-3,20); // should become 0,10 380 Index2 indicesStop(20,-11); // should become 11, -1 381 slice = tensor2.stridedSlice(indicesStart, indicesStop, strides); 382 for (int j = 0; j < 7; ++j) { 383 for (int k = 0; k < 11; ++k) { 384 VERIFY_IS_EQUAL(slice(j,k), tensor2(j,10-k)); 385 } 386 } 387 } 388 389 if(true) { 390 Tensor5f slice1(1,1,1,1,1); 391 Eigen::DSizes<Eigen::DenseIndex, 5> indicesStart(1, 2, 3, 4, 5); 392 Eigen::DSizes<Eigen::DenseIndex, 5> indicesStop(2, 3, 4, 5, 6); 393 Eigen::DSizes<Eigen::DenseIndex, 5> strides(1, 1, 1, 1, 1); 394 slice1 = tensor.stridedSlice(indicesStart, indicesStop, strides); 395 VERIFY_IS_EQUAL(slice1(0,0,0,0,0), tensor(1,2,3,4,5)); 396 } 397 398 if(true) { 399 Tensor5f slice(1,1,2,2,3); 400 Index5 start(1, 1, 3, 4, 5); 401 Index5 stop(2, 2, 5, 6, 8); 402 Index5 strides(1, 1, 1, 1, 1); 403 slice = tensor.stridedSlice(start, stop, strides); 404 for (int i = 0; i < 2; ++i) { 405 for (int j = 0; j < 2; ++j) { 406 for (int k = 0; k < 3; ++k) { 407 VERIFY_IS_EQUAL(slice(0,0,i,j,k), tensor(1,1,3+i,4+j,5+k)); 408 } 409 } 410 } 411 } 412 413 if(true) { 414 Tensor5f slice(1,1,2,2,3); 415 Index5 strides3(1, 1, -2, 1, -1); 416 Index5 indices3Start(1, 1, 4, 4, 7); 417 Index5 indices3Stop(2, 2, 0, 6, 4); 418 slice = tensor.stridedSlice(indices3Start, indices3Stop, strides3); 419 for (int i = 0; i < 2; ++i) { 420 for (int j = 0; j < 2; ++j) { 421 for (int k = 0; k < 3; ++k) { 422 VERIFY_IS_EQUAL(slice(0,0,i,j,k), tensor(1,1,4-2*i,4+j,7-k)); 423 } 424 } 425 } 426 } 427 428 if(false) { // tests degenerate interval 429 Tensor5f slice(1,1,2,2,3); 430 Index5 strides3(1, 1, 2, 1, 1); 431 Index5 indices3Start(1, 1, 4, 4, 7); 432 Index5 indices3Stop(2, 2, 0, 6, 4); 433 slice = tensor.stridedSlice(indices3Start, indices3Stop, strides3); 434 } 435 } 436 437 template<typename T, int DataLayout> 438 static void test_strided_slice_write() 439 { 440 typedef Tensor<T, 2, DataLayout> Tensor2f; 441 typedef Eigen::DSizes<Eigen::DenseIndex, 2> Index2; 442 443 Tensor<T, 2, DataLayout> tensor(7,11),tensor2(7,11); 444 tensor.setRandom(); 445 tensor2=tensor; 446 Tensor2f slice(2,3); 447 448 slice.setRandom(); 449 450 Index2 strides(1,1); 451 Index2 indicesStart(3,4); 452 Index2 indicesStop(5,7); 453 Index2 lengths(2,3); 454 455 tensor.slice(indicesStart,lengths)=slice; 456 tensor2.stridedSlice(indicesStart,indicesStop,strides)=slice; 457 458 for(int i=0;i<7;i++) for(int j=0;j<11;j++){ 459 VERIFY_IS_EQUAL(tensor(i,j), tensor2(i,j)); 460 } 461 } 462 463 template<typename T, int DataLayout> 464 static void test_composition() 465 { 466 Eigen::Tensor<T, 2, DataLayout> matrix(7, 11); 467 matrix.setRandom(); 468 469 const DSizes<ptrdiff_t, 3> newDims(1, 1, 11); 470 Eigen::Tensor<T, 3, DataLayout> tensor = 471 matrix.slice(DSizes<ptrdiff_t, 2>(2, 0), DSizes<ptrdiff_t, 2>(1, 11)).reshape(newDims); 472 473 VERIFY_IS_EQUAL(tensor.dimensions().TotalSize(), 11); 474 VERIFY_IS_EQUAL(tensor.dimension(0), 1); 475 VERIFY_IS_EQUAL(tensor.dimension(1), 1); 476 VERIFY_IS_EQUAL(tensor.dimension(2), 11); 477 for (int i = 0; i < 11; ++i) { 478 VERIFY_IS_EQUAL(tensor(0,0,i), matrix(2,i)); 479 } 480 } 481 482 template<typename T, int DataLayout> 483 static void test_empty_slice() 484 { 485 Tensor<T, 3, DataLayout> tensor(2,3,5); 486 tensor.setRandom(); 487 Tensor<T, 3, DataLayout> copy = tensor; 488 489 // empty size in first dimension 490 Eigen::DSizes<ptrdiff_t, 3> indices1(1,2,3); 491 Eigen::DSizes<ptrdiff_t, 3> sizes1(0,1,2); 492 Tensor<T, 3, DataLayout> slice1(0,1,2); 493 slice1.setRandom(); 494 tensor.slice(indices1, sizes1) = slice1; 495 496 // empty size in second dimension 497 Eigen::DSizes<ptrdiff_t, 3> indices2(1,2,3); 498 Eigen::DSizes<ptrdiff_t, 3> sizes2(1,0,2); 499 Tensor<T, 3, DataLayout> slice2(1,0,2); 500 slice2.setRandom(); 501 tensor.slice(indices2, sizes2) = slice2; 502 503 // empty size in third dimension 504 Eigen::DSizes<ptrdiff_t, 3> indices3(1,2,3); 505 Eigen::DSizes<ptrdiff_t, 3> sizes3(1,1,0); 506 Tensor<T, 3, DataLayout> slice3(1,1,0); 507 slice3.setRandom(); 508 tensor.slice(indices3, sizes3) = slice3; 509 510 // empty size in first and second dimension 511 Eigen::DSizes<ptrdiff_t, 3> indices4(1,2,3); 512 Eigen::DSizes<ptrdiff_t, 3> sizes4(0,0,2); 513 Tensor<T, 3, DataLayout> slice4(0,0,2); 514 slice4.setRandom(); 515 tensor.slice(indices4, sizes4) = slice4; 516 517 // empty size in second and third dimension 518 Eigen::DSizes<ptrdiff_t, 3> indices5(1,2,3); 519 Eigen::DSizes<ptrdiff_t, 3> sizes5(1,0,0); 520 Tensor<T, 3, DataLayout> slice5(1,0,0); 521 slice5.setRandom(); 522 tensor.slice(indices5, sizes5) = slice5; 523 524 // empty size in all dimensions 525 Eigen::DSizes<ptrdiff_t, 3> indices6(1,2,3); 526 Eigen::DSizes<ptrdiff_t, 3> sizes6(0,0,0); 527 Tensor<T, 3, DataLayout> slice6(0,0,0); 528 slice6.setRandom(); 529 tensor.slice(indices6, sizes6) = slice6; 530 531 // none of these operations should change the tensor's components 532 // because all of the rvalue slices have at least one zero dimension 533 for (int i = 0; i < 2; ++i) { 534 for (int j = 0; j < 3; ++j) { 535 for (int k = 0; k < 5; ++k) { 536 VERIFY_IS_EQUAL(tensor(i,j,k), copy(i,j,k)); 537 } 538 } 539 } 540 } 541 542 #define CALL_SUBTEST_PART(PART) \ 543 CALL_SUBTEST_##PART 544 545 #define CALL_SUBTESTS_TYPES_LAYOUTS(PART, NAME) \ 546 CALL_SUBTEST_PART(PART)((NAME<float, ColMajor>())); \ 547 CALL_SUBTEST_PART(PART)((NAME<float, RowMajor>())); \ 548 CALL_SUBTEST_PART(PART)((NAME<bool, ColMajor>())); \ 549 CALL_SUBTEST_PART(PART)((NAME<bool, RowMajor>())) 550 551 EIGEN_DECLARE_TEST(cxx11_tensor_morphing) 552 { 553 CALL_SUBTEST_1(test_simple_reshape<void>()); 554 CALL_SUBTEST_1(test_static_reshape<void>()); 555 CALL_SUBTEST_1(test_reshape_as_lvalue<void>()); 556 CALL_SUBTEST_1(test_reshape_in_expr<void>()); 557 CALL_SUBTEST_1(test_const_slice<float>()); 558 559 CALL_SUBTESTS_TYPES_LAYOUTS(2, test_simple_slice); 560 CALL_SUBTESTS_TYPES_LAYOUTS(3, test_slice_as_lvalue); 561 CALL_SUBTESTS_TYPES_LAYOUTS(4, test_slice_raw_data); 562 CALL_SUBTESTS_TYPES_LAYOUTS(5, test_strided_slice_write); 563 CALL_SUBTESTS_TYPES_LAYOUTS(6, test_strided_slice); 564 CALL_SUBTESTS_TYPES_LAYOUTS(7, test_composition); 565 }