diff options
author | 2015-10-16 22:12:54 +0200 | |
---|---|---|
committer | 2015-10-16 22:12:54 +0200 | |
commit | e99279f444232c81901a84b4d15dae5fcf6d7d37 (patch) | |
tree | 26fdf7a5d40406c83b6931c47044b40831def1b0 | |
parent | c0adf6e38d9f9d3a8f8e5c1ff4c2c3939cf0e070 (diff) | |
parent | de1e9f29f4db2c837ffb354c90f9e9fb7df05e85 (diff) |
merge
-rw-r--r-- | unsupported/Eigen/CXX11/Tensor | 1 | ||||
-rw-r--r-- | unsupported/Eigen/CXX11/src/Tensor/Tensor.h | 75 | ||||
-rw-r--r-- | unsupported/Eigen/CXX11/src/Tensor/TensorMacros.h | 44 | ||||
-rw-r--r-- | unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h | 53 | ||||
-rw-r--r-- | unsupported/test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unsupported/test/cxx11_tensor_custom_index.cpp | 100 | ||||
-rw-r--r-- | unsupported/test/cxx11_tensor_simple.cpp | 4 |
7 files changed, 262 insertions, 16 deletions
diff --git a/unsupported/Eigen/CXX11/Tensor b/unsupported/Eigen/CXX11/Tensor index cbe416602..3331ccb55 100644 --- a/unsupported/Eigen/CXX11/Tensor +++ b/unsupported/Eigen/CXX11/Tensor @@ -57,6 +57,7 @@ #endif +#include "src/Tensor/TensorMacros.h" #include "src/Tensor/TensorForwardDeclarations.h" #include "src/Tensor/TensorMeta.h" #include "src/Tensor/TensorDeviceType.h" diff --git a/unsupported/Eigen/CXX11/src/Tensor/Tensor.h b/unsupported/Eigen/CXX11/src/Tensor/Tensor.h index 6c16e0faa..3ac465d24 100644 --- a/unsupported/Eigen/CXX11/src/Tensor/Tensor.h +++ b/unsupported/Eigen/CXX11/src/Tensor/Tensor.h @@ -88,6 +88,15 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp protected: TensorStorage<Scalar, Dimensions, Options> m_storage; +#ifdef EIGEN_HAS_SFINAE + template<typename CustomIndices> + struct isOfNormalIndex{ + static const bool is_array = internal::is_base_of<array<Index, NumIndices>, CustomIndices>::value; + static const bool is_int = NumTraits<CustomIndices>::IsInteger; + static const bool value = is_array | is_int; + }; +#endif + public: // Metadata EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rank() const { return NumIndices; } @@ -113,12 +122,24 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp } #endif + // normal indices EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(const array<Index, NumIndices>& indices) const { eigen_internal_assert(checkIndexRange(indices)); return m_storage.data()[linearizedIndex(indices)]; } + // custom indices +#ifdef EIGEN_HAS_SFINAE + template<typename CustomIndices, + EIGEN_SFINAE_ENABLE_IF( !(isOfNormalIndex<CustomIndices>::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(CustomIndices& indices) const + { + return coeff(internal::customIndices2Array<Index,NumIndices>(indices)); + } +#endif + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const { eigen_internal_assert(index >= 0 && index < size()); @@ -135,12 +156,24 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp } #endif + // normal indices EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(const array<Index, NumIndices>& indices) { eigen_internal_assert(checkIndexRange(indices)); return m_storage.data()[linearizedIndex(indices)]; } + // custom indices +#ifdef EIGEN_HAS_SFINAE + template<typename CustomIndices, + EIGEN_SFINAE_ENABLE_IF( !(isOfNormalIndex<CustomIndices>::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(CustomIndices& indices) + { + return coeffRef(internal::customIndices2Array<Index,NumIndices>(indices)); + } +#endif + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { eigen_internal_assert(index >= 0 && index < size()); @@ -178,9 +211,20 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp } #endif + // custom indices +#ifdef EIGEN_HAS_SFINAE + template<typename CustomIndices, + EIGEN_SFINAE_ENABLE_IF( !(isOfNormalIndex<CustomIndices>::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(CustomIndices& indices) const + { + return coeff(internal::customIndices2Array<Index,NumIndices>(indices)); + } +#endif + + // normal indices EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(const array<Index, NumIndices>& indices) const { - eigen_assert(checkIndexRange(indices)); return coeff(indices); } @@ -228,12 +272,23 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp } #endif + // normal indices EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(const array<Index, NumIndices>& indices) { - eigen_assert(checkIndexRange(indices)); return coeffRef(indices); } + // custom indices +#ifdef EIGEN_HAS_SFINAE + template<typename CustomIndices, + EIGEN_SFINAE_ENABLE_IF( !(isOfNormalIndex<CustomIndices>::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(CustomIndices& indices) + { + return coeffRef(internal::customIndices2Array<Index,NumIndices>(indices)); + } +#endif + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index index) { eigen_assert(index >= 0 && index < size()); @@ -295,6 +350,7 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp } #endif + /** Normal Dimension */ inline explicit Tensor(const array<Index, NumIndices>& dimensions) : m_storage(internal::array_prod(dimensions), dimensions) { @@ -341,7 +397,7 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp } #ifdef EIGEN_HAS_VARIADIC_TEMPLATES - template<typename... IndexTypes> EIGEN_DEVICE_FUNC + template<typename... IndexTypes> EIGEN_DEVICE_FUNC void resize(Index firstDimension, IndexTypes... otherDimensions) { // The number of dimensions used to resize a tensor must be equal to the rank of the tensor. @@ -350,6 +406,7 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp } #endif + /** Normal Dimension */ EIGEN_DEVICE_FUNC void resize(const array<Index, NumIndices>& dimensions) { std::size_t i; @@ -367,6 +424,7 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp #endif } + // Why this overload, DSizes is derived from array ??? // EIGEN_DEVICE_FUNC void resize(const DSizes<Index, NumIndices>& dimensions) { array<Index, NumIndices> dims; for (std::size_t i = 0; i < NumIndices; ++i) { @@ -375,6 +433,17 @@ class Tensor : public TensorBase<Tensor<Scalar_, NumIndices_, Options_, IndexTyp resize(dims); } + /** Custom Dimension */ +#ifdef EIGEN_HAS_SFINAE + template<typename CustomDimension, + EIGEN_SFINAE_ENABLE_IF( !(isOfNormalIndex<CustomDimension>::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(CustomDimension& dimensions) + { + resize(internal::customIndices2Array<Index,NumIndices>(dimensions)); + } +#endif + #ifndef EIGEN_EMULATE_CXX11_META_H template <typename std::ptrdiff_t... Indices> EIGEN_DEVICE_FUNC diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorMacros.h b/unsupported/Eigen/CXX11/src/Tensor/TensorMacros.h new file mode 100644 index 000000000..6d9cc4f38 --- /dev/null +++ b/unsupported/Eigen/CXX11/src/Tensor/TensorMacros.h @@ -0,0 +1,44 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2015 Benoit Steiner <benoit.steiner.goog@gmail.com> +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CXX11_TENSOR_TENSOR_META_MACROS_H +#define EIGEN_CXX11_TENSOR_TENSOR_META_MACROS_H + + +/** use this macro in sfinae selection in templated functions + * + * template<typename T, + * typename std::enable_if< isBanana<T>::value , int >::type = 0 + * > + * void foo(){} + * + * becomes => + * + * template<typename TopoType, + * SFINAE_ENABLE_IF( isBanana<T>::value ) + * > + * void foo(){} + */ + +#ifdef EIGEN_HAS_VARIADIC_TEMPLATES +#define EIGEN_HAS_SFINAE +#endif + +#define EIGEN_SFINAE_ENABLE_IF( __condition__ ) \ + typename internal::enable_if< ( __condition__ ) , int >::type = 0 + + +#if defined(EIGEN_HAS_CONSTEXPR) +#define EIGEN_CONSTEXPR constexpr +#else +#define EIGEN_CONSTEXPR +#endif + + +#endif diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h b/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h index 7dfa04760..07735fa5f 100644 --- a/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h +++ b/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h @@ -32,14 +32,6 @@ template <> struct max_n_1<0> { }; - - -#if defined(EIGEN_HAS_CONSTEXPR) -#define EIGEN_CONSTEXPR constexpr -#else -#define EIGEN_CONSTEXPR -#endif - // Tuple mimics std::pair but works on e.g. nvcc. template <typename U, typename V> struct Tuple { public: @@ -83,7 +75,50 @@ bool operator!=(const Tuple<U, V>& x, const Tuple<U, V>& y) { return !(x == y); } -#undef EIGEN_CONSTEXPR + + +#ifdef EIGEN_HAS_SFINAE +namespace internal{ + + template<typename IndexType, Index... Is> + EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + array<Index, sizeof...(Is)> customIndices2Array(IndexType& idx, numeric_list<Index, Is...>) { + return { idx[Is]... }; + } + + /** Make an array (for index/dimensions) out of a custom index */ + template<typename Index, int NumIndices, typename IndexType> + EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + array<Index, NumIndices> customIndices2Array(IndexType& idx) { + return customIndices2Array(idx, typename gen_numeric_list<Index, NumIndices>::type{}); + } + + + template <typename B, typename D> + struct is_base_of + { + + typedef char (&yes)[1]; + typedef char (&no)[2]; + + template <typename BB, typename DD> + struct Host + { + operator BB*() const; + operator DD*(); + }; + + template<typename T> + static yes check(D*, T); + static no check(B*, int); + + static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes); + }; + +} +#endif + + } // namespace Eigen diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt index 7a1737edd..8865892e6 100644 --- a/unsupported/test/CMakeLists.txt +++ b/unsupported/test/CMakeLists.txt @@ -142,6 +142,7 @@ if(EIGEN_TEST_CXX11) ei_add_test(cxx11_tensor_io "-std=c++0x") ei_add_test(cxx11_tensor_generator "-std=c++0x") ei_add_test(cxx11_tensor_custom_op "-std=c++0x") + ei_add_test(cxx11_tensor_custom_index "-std=c++0x") # These tests needs nvcc # ei_add_test(cxx11_tensor_device "-std=c++0x") diff --git a/unsupported/test/cxx11_tensor_custom_index.cpp b/unsupported/test/cxx11_tensor_custom_index.cpp new file mode 100644 index 000000000..4528cc176 --- /dev/null +++ b/unsupported/test/cxx11_tensor_custom_index.cpp @@ -0,0 +1,100 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2015 Benoit Steiner <benoit.steiner.goog@gmail.com> +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "main.h" +#include <limits> +#include <map> + +#include <Eigen/Dense> +#include <Eigen/CXX11/Tensor> + +using Eigen::Tensor; + + +template <int DataLayout> +static void test_map_as_index() +{ +#ifdef EIGEN_HAS_SFINAE + Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7); + tensor.setRandom(); + + using NormalIndex = DSizes<ptrdiff_t, 4>; + using CustomIndex = std::map<ptrdiff_t, ptrdiff_t>; + CustomIndex coeffC; + coeffC[0] = 1; + coeffC[1] = 2; + coeffC[2] = 4; + coeffC[3] = 1; + NormalIndex coeff(1,2,4,1); + + VERIFY_IS_EQUAL(tensor.coeff(coeffC), tensor.coeff(coeff)); + VERIFY_IS_EQUAL(tensor.coeffRef(coeffC), tensor.coeffRef(coeff)); +#endif +} + + +template <int DataLayout> +static void test_matrix_as_index() +{ +#ifdef EIGEN_HAS_SFINAE + Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7); + tensor.setRandom(); + + using NormalIndex = DSizes<ptrdiff_t, 4>; + using CustomIndex = Matrix<unsigned int, 4, 1>; + CustomIndex coeffC(1,2,4,1); + NormalIndex coeff(1,2,4,1); + + VERIFY_IS_EQUAL(tensor.coeff(coeffC), tensor.coeff(coeff)); + VERIFY_IS_EQUAL(tensor.coeffRef(coeffC), tensor.coeffRef(coeff)); +#endif +} + + +template <int DataLayout> +static void test_varlist_as_index() +{ +#ifdef EIGEN_HAS_SFINAE + Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7); + tensor.setRandom(); + + DSizes<ptrdiff_t, 4> coeff(1,2,4,1); + + VERIFY_IS_EQUAL(tensor.coeff({1,2,4,1}), tensor.coeff(coeff)); + VERIFY_IS_EQUAL(tensor.coeffRef({1,2,4,1}), tensor.coeffRef(coeff)); +#endif +} + + +template <int DataLayout> +static void test_sizes_as_index() +{ +#ifdef EIGEN_HAS_SFINAE + Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7); + tensor.setRandom(); + + DSizes<ptrdiff_t, 4> coeff(1,2,4,1); + Sizes<1,2,4,1> coeffC; + + VERIFY_IS_EQUAL(tensor.coeff(coeffC), tensor.coeff(coeff)); + VERIFY_IS_EQUAL(tensor.coeffRef(coeffC), tensor.coeffRef(coeff)); +#endif +} + + +void test_cxx11_tensor_custom_index() { + test_map_as_index<ColMajor>(); + test_map_as_index<RowMajor>(); + test_matrix_as_index<ColMajor>(); + test_matrix_as_index<RowMajor>(); + test_varlist_as_index<ColMajor>(); + test_varlist_as_index<RowMajor>(); + test_sizes_as_index<ColMajor>(); + test_sizes_as_index<RowMajor>(); +} diff --git a/unsupported/test/cxx11_tensor_simple.cpp b/unsupported/test/cxx11_tensor_simple.cpp index 8cd2ab7fd..0ce92eed9 100644 --- a/unsupported/test/cxx11_tensor_simple.cpp +++ b/unsupported/test/cxx11_tensor_simple.cpp @@ -293,7 +293,3 @@ void test_cxx11_tensor_simple() CALL_SUBTEST(test_simple_assign()); CALL_SUBTEST(test_resize()); } - -/* - * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle; - */ |