12b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// This file is part of Eigen, a lightweight C++ template library
22b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// for linear algebra.
32b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang//
42b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
52b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang//
62b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// This Source Code Form is subject to the terms of the Mozilla
72b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Public License v. 2.0. If a copy of the MPL was not distributed
82b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
92b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#include "main.h"
112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#include <limits>
122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#include <numeric>
132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#include <Eigen/CXX11/Tensor>
142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangusing Eigen::Tensor;
162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_trivial_reductions() {
192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> tensor;
212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    tensor.setRandom();
222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    array<ptrdiff_t, 0> reduction_axis;
232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> result = tensor.sum(reduction_axis);
252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(result(), tensor());
262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 1, DataLayout> tensor(7);
302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    tensor.setRandom();
312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    array<ptrdiff_t, 0> reduction_axis;
322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 1, DataLayout> result = tensor.sum(reduction_axis);
342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(result.dimension(0), 7);
352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int i = 0; i < 7; ++i) {
362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_EQUAL(result(i), tensor(i));
372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 2, DataLayout> tensor(2, 3);
422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    tensor.setRandom();
432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    array<ptrdiff_t, 0> reduction_axis;
442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 2, DataLayout> result = tensor.sum(reduction_axis);
462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(result.dimension(0), 2);
472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(result.dimension(1), 3);
482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int i = 0; i < 2; ++i) {
492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int j = 0; j < 3; ++j) {
502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        VERIFY_IS_EQUAL(result(i, j), tensor(i, j));
512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_simple_reductions() {
582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7);
592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  tensor.setRandom();
602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<ptrdiff_t, 2> reduction_axis2;
612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[0] = 1;
622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[1] = 3;
632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 2, DataLayout> result = tensor.sum(reduction_axis2);
652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(0), 2);
662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(1), 5);
672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 2; ++i) {
682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 5; ++j) {
692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float sum = 0.0f;
702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 3; ++k) {
712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 7; ++l) {
722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          sum += tensor(i, k, j, l);
732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(result(i, j), sum);
762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> sum1 = tensor.sum();
812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(sum1.rank(), 0);
822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    array<ptrdiff_t, 4> reduction_axis4;
842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[0] = 0;
852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[1] = 1;
862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[2] = 2;
872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[3] = 3;
882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> sum2 = tensor.sum(reduction_axis4);
892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(sum2.rank(), 0);
902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_APPROX(sum1(), sum2());
922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[0] = 0;
952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[1] = 2;
962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  result = tensor.prod(reduction_axis2);
972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(0), 3);
982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(1), 7);
992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 3; ++i) {
1002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 7; ++j) {
1012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float prod = 1.0f;
1022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 2; ++k) {
1032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 5; ++l) {
1042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          prod *= tensor(k, i, l, j);
1052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
1062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
1072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(result(i, j), prod);
1082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1092b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
1102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
1122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> prod1 = tensor.prod();
1132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(prod1.rank(), 0);
1142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    array<ptrdiff_t, 4> reduction_axis4;
1162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[0] = 0;
1172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[1] = 1;
1182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[2] = 2;
1192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[3] = 3;
1202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> prod2 = tensor.prod(reduction_axis4);
1212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(prod2.rank(), 0);
1222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_APPROX(prod1(), prod2());
1242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
1252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[0] = 0;
1272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[1] = 2;
1282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  result = tensor.maximum(reduction_axis2);
1292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(0), 3);
1302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(1), 7);
1312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 3; ++i) {
1322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 7; ++j) {
1332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float max_val = std::numeric_limits<float>::lowest();
1342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 2; ++k) {
1352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 5; ++l) {
1362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          max_val = (std::max)(max_val, tensor(k, i, l, j));
1372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
1382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
1392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(result(i, j), max_val);
1402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
1422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
1442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> max1 = tensor.maximum();
1452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(max1.rank(), 0);
1462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    array<ptrdiff_t, 4> reduction_axis4;
1482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[0] = 0;
1492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[1] = 1;
1502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[2] = 2;
1512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[3] = 3;
1522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> max2 = tensor.maximum(reduction_axis4);
1532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(max2.rank(), 0);
1542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_APPROX(max1(), max2());
1562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
1572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[0] = 0;
1592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[1] = 1;
1602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  result = tensor.minimum(reduction_axis2);
1612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(0), 5);
1622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(1), 7);
1632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 5; ++i) {
1642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 7; ++j) {
1652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float min_val = (std::numeric_limits<float>::max)();
1662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 2; ++k) {
1672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 3; ++l) {
1682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          min_val = (std::min)(min_val, tensor(k, l, i, j));
1692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
1702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
1712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(result(i, j), min_val);
1722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
1742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
1762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> min1 = tensor.minimum();
1772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(min1.rank(), 0);
1782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    array<ptrdiff_t, 4> reduction_axis4;
1802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[0] = 0;
1812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[1] = 1;
1822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[2] = 2;
1832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[3] = 3;
1842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> min2 = tensor.minimum(reduction_axis4);
1852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(min2.rank(), 0);
1862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_APPROX(min1(), min2());
1882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
1892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[0] = 0;
1912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[1] = 1;
1922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  result = tensor.mean(reduction_axis2);
1932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(0), 5);
1942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(1), 7);
1952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 5; ++i) {
1962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 7; ++j) {
1972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float sum = 0.0f;
1982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      int count = 0;
1992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 2; ++k) {
2002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 3; ++l) {
2012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          sum += tensor(k, l, i, j);
2022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          ++count;
2032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
2042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
2052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(result(i, j), sum / count);
2062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
2072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2092b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
2102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> mean1 = tensor.mean();
2112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(mean1.rank(), 0);
2122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    array<ptrdiff_t, 4> reduction_axis4;
2142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[0] = 0;
2152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[1] = 1;
2162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[2] = 2;
2172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    reduction_axis4[3] = 3;
2182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<float, 0, DataLayout> mean2 = tensor.mean(reduction_axis4);
2192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_EQUAL(mean2.rank(), 0);
2202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_APPROX(mean1(), mean2());
2222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  {
2252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    Tensor<int, 1> ints(10);
2262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    std::iota(ints.data(), ints.data() + ints.dimension(0), 0);
2272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    TensorFixedSize<bool, Sizes<> > all;
2292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    all = ints.all();
2302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY(!all());
2312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    all = (ints >= ints.constant(0)).all();
2322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY(all());
2332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    TensorFixedSize<bool, Sizes<> > any;
2352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    any = (ints > ints.constant(10)).any();
2362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY(!any());
2372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    any = (ints < ints.constant(1)).any();
2382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY(any());
2392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
2412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
2442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_reductions_in_expr() {
2452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7);
2462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  tensor.setRandom();
2472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<ptrdiff_t, 2> reduction_axis2;
2482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[0] = 1;
2492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis2[1] = 3;
2502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 2, DataLayout> result(2, 5);
2522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  result = result.constant(1.0f) - tensor.sum(reduction_axis2);
2532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(0), 2);
2542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(1), 5);
2552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 2; ++i) {
2562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 5; ++j) {
2572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float sum = 0.0f;
2582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 3; ++k) {
2592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 7; ++l) {
2602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          sum += tensor(i, k, j, l);
2612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
2622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
2632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(result(i, j), 1.0f - sum);
2642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
2652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
2672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
2702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_full_reductions() {
2712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 2, DataLayout> tensor(2, 3);
2722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  tensor.setRandom();
2732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<ptrdiff_t, 2> reduction_axis;
2742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[0] = 0;
2752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[1] = 1;
2762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 0, DataLayout> result = tensor.sum(reduction_axis);
2782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.rank(), 0);
2792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  float sum = 0.0f;
2812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 2; ++i) {
2822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 3; ++j) {
2832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      sum += tensor(i, j);
2842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
2852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_APPROX(result(0), sum);
2872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  result = tensor.square().sum(reduction_axis).sqrt();
2892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.rank(), 0);
2902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  sum = 0.0f;
2922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 2; ++i) {
2932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 3; ++j) {
2942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      sum += tensor(i, j) * tensor(i, j);
2952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
2962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_APPROX(result(), sqrtf(sum));
2982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
2992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstruct UserReducer {
3012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  static const bool PacketAccess = false;
3022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  UserReducer(float offset) : offset_(offset) {}
3032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  void reduce(const float val, float* accum) { *accum += val * val; }
3042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  float initialize() const { return 0; }
3052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  float finalize(const float accum) const { return 1.0f / (accum + offset_); }
3062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang private:
3082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  const float offset_;
3092b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang};
3102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
3122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_user_defined_reductions() {
3132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 2, DataLayout> tensor(5, 7);
3142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  tensor.setRandom();
3152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<ptrdiff_t, 1> reduction_axis;
3162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[0] = 1;
3172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  UserReducer reducer(10.0f);
3192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 1, DataLayout> result = tensor.reduce(reduction_axis, reducer);
3202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  VERIFY_IS_EQUAL(result.dimension(0), 5);
3212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 5; ++i) {
3222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    float expected = 10.0f;
3232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 7; ++j) {
3242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      expected += tensor(i, j) * tensor(i, j);
3252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
3262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    expected = 1.0f / expected;
3272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    VERIFY_IS_APPROX(result(i), expected);
3282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
3292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
3302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
3322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_tensor_maps() {
3332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  int inputs[2 * 3 * 5 * 7];
3342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  TensorMap<Tensor<int, 4, DataLayout> > tensor_map(inputs, 2, 3, 5, 7);
3352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  TensorMap<Tensor<const int, 4, DataLayout> > tensor_map_const(inputs, 2, 3, 5,
3362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang                                                                7);
3372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  const TensorMap<Tensor<const int, 4, DataLayout> > tensor_map_const_const(
3382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      inputs, 2, 3, 5, 7);
3392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  tensor_map.setRandom();
3412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<ptrdiff_t, 2> reduction_axis;
3422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[0] = 1;
3432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[1] = 3;
3442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<int, 2, DataLayout> result = tensor_map.sum(reduction_axis);
3462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<int, 2, DataLayout> result2 = tensor_map_const.sum(reduction_axis);
3472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<int, 2, DataLayout> result3 =
3482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      tensor_map_const_const.sum(reduction_axis);
3492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 2; ++i) {
3512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 5; ++j) {
3522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      int sum = 0;
3532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 3; ++k) {
3542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 7; ++l) {
3552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          sum += tensor_map(i, k, j, l);
3562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
3572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
3582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_EQUAL(result(i, j), sum);
3592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_EQUAL(result2(i, j), sum);
3602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_EQUAL(result3(i, j), sum);
3612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
3622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
3632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
3642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
3662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_static_dims() {
3672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 4, DataLayout> in(72, 53, 97, 113);
3682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 2, DataLayout> out(72, 97);
3692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  in.setRandom();
3702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#if !EIGEN_HAS_CONSTEXPR
3722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<int, 2> reduction_axis;
3732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[0] = 1;
3742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[1] = 3;
3752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#else
3762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Eigen::IndexList<Eigen::type2index<1>, Eigen::type2index<3> > reduction_axis;
3772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#endif
3782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  out = in.maximum(reduction_axis);
3802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 72; ++i) {
3822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 97; ++j) {
3832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float expected = -1e10f;
3842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 53; ++k) {
3852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 113; ++l) {
3862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          expected = (std::max)(expected, in(i, k, j, l));
3872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
3882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
3892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(out(i, j), expected);
3902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
3912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
3922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
3932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
3942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
3952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_innermost_last_dims() {
3962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 4, DataLayout> in(72, 53, 97, 113);
3972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 2, DataLayout> out(97, 113);
3982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  in.setRandom();
3992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Reduce on the innermost dimensions.
4012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#if !EIGEN_HAS_CONSTEXPR
4022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<int, 2> reduction_axis;
4032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[0] = 0;
4042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[1] = 1;
4052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#else
4062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  // This triggers the use of packets for ColMajor.
4072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Eigen::IndexList<Eigen::type2index<0>, Eigen::type2index<1> > reduction_axis;
4082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#endif
4092b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  out = in.maximum(reduction_axis);
4112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 97; ++i) {
4132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 113; ++j) {
4142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float expected = -1e10f;
4152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 53; ++k) {
4162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 72; ++l) {
4172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          expected = (std::max)(expected, in(l, k, i, j));
4182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
4192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
4202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(out(i, j), expected);
4212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
4222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
4232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
4242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
4262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_innermost_first_dims() {
4272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 4, DataLayout> in(72, 53, 97, 113);
4282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 2, DataLayout> out(72, 53);
4292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  in.setRandom();
4302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Reduce on the innermost dimensions.
4322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#if !EIGEN_HAS_CONSTEXPR
4332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<int, 2> reduction_axis;
4342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[0] = 2;
4352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[1] = 3;
4362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#else
4372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  // This triggers the use of packets for RowMajor.
4382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Eigen::IndexList<Eigen::type2index<2>, Eigen::type2index<3>> reduction_axis;
4392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#endif
4402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  out = in.maximum(reduction_axis);
4422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 72; ++i) {
4442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 53; ++j) {
4452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float expected = -1e10f;
4462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 97; ++k) {
4472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 113; ++l) {
4482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          expected = (std::max)(expected, in(i, j, k, l));
4492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
4502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
4512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(out(i, j), expected);
4522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
4532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
4542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
4552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate <int DataLayout>
4572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangstatic void test_reduce_middle_dims() {
4582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 4, DataLayout> in(72, 53, 97, 113);
4592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Tensor<float, 2, DataLayout> out(72, 53);
4602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  in.setRandom();
4612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Reduce on the innermost dimensions.
4632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#if !EIGEN_HAS_CONSTEXPR
4642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  array<int, 2> reduction_axis;
4652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[0] = 1;
4662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  reduction_axis[1] = 2;
4672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#else
4682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  // This triggers the use of packets for RowMajor.
4692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Eigen::IndexList<Eigen::type2index<1>, Eigen::type2index<2>> reduction_axis;
4702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#endif
4712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  out = in.maximum(reduction_axis);
4732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (int i = 0; i < 72; ++i) {
4752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (int j = 0; j < 113; ++j) {
4762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      float expected = -1e10f;
4772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (int k = 0; k < 53; ++k) {
4782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (int l = 0; l < 97; ++l) {
4792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          expected = (std::max)(expected, in(i, k, l, j));
4802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        }
4812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
4822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      VERIFY_IS_APPROX(out(i, j), expected);
4832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
4842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
4852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
4862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
4872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangvoid test_cxx11_tensor_reduction() {
4882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_trivial_reductions<ColMajor>());
4892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_trivial_reductions<RowMajor>());
4902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_simple_reductions<ColMajor>());
4912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_simple_reductions<RowMajor>());
4922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_reductions_in_expr<ColMajor>());
4932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_reductions_in_expr<RowMajor>());
4942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_full_reductions<ColMajor>());
4952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_full_reductions<RowMajor>());
4962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_user_defined_reductions<ColMajor>());
4972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_user_defined_reductions<RowMajor>());
4982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_tensor_maps<ColMajor>());
4992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_tensor_maps<RowMajor>());
5002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_static_dims<ColMajor>());
5012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_static_dims<RowMajor>());
5022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_innermost_last_dims<ColMajor>());
5032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_innermost_last_dims<RowMajor>());
5042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_innermost_first_dims<ColMajor>());
5052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_innermost_first_dims<RowMajor>());
5062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_reduce_middle_dims<ColMajor>());
5072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  CALL_SUBTEST(test_reduce_middle_dims<RowMajor>());
5082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
509