From 6edae2d30d5a74a3234f6a91adb5ffdb1b86bbfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20N=C3=BCtzi?= Date: Fri, 9 Oct 2015 18:52:48 +0200 Subject: [PATCH] added CustomIndex capability only to Tensor and not yet to TensorBase. using Sfinae and is_base_of to select correct template which converts to array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit user: Gabriel Nützi branch 'default' added unsupported/Eigen/CXX11/src/Tensor/TensorMetaMacros.h added unsupported/test/cxx11_tensor_customIndex.cpp changed unsupported/Eigen/CXX11/Tensor changed unsupported/Eigen/CXX11/src/Tensor/Tensor.h changed unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h changed unsupported/test/CMakeLists.txt --- unsupported/Eigen/CXX11/Tensor | 1 + unsupported/Eigen/CXX11/src/Tensor/Tensor.h | 81 ++++++++++++++++++- .../Eigen/CXX11/src/Tensor/TensorMeta.h | 51 ++++++++++++ .../Eigen/CXX11/src/Tensor/TensorMetaMacros.h | 33 ++++++++ unsupported/test/CMakeLists.txt | 1 + unsupported/test/cxx11_tensor_customIndex.cpp | 41 ++++++++++ 6 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 unsupported/Eigen/CXX11/src/Tensor/TensorMetaMacros.h create mode 100644 unsupported/test/cxx11_tensor_customIndex.cpp diff --git a/unsupported/Eigen/CXX11/Tensor b/unsupported/Eigen/CXX11/Tensor index cbe416602..ee3a1cdb6 100644 --- a/unsupported/Eigen/CXX11/Tensor +++ b/unsupported/Eigen/CXX11/Tensor @@ -59,6 +59,7 @@ #include "src/Tensor/TensorForwardDeclarations.h" #include "src/Tensor/TensorMeta.h" +#include "src/Tensor/TensorMetaMacros.h" #include "src/Tensor/TensorDeviceType.h" #include "src/Tensor/TensorIndexList.h" #include "src/Tensor/TensorDimensionList.h" diff --git a/unsupported/Eigen/CXX11/src/Tensor/Tensor.h b/unsupported/Eigen/CXX11/src/Tensor/Tensor.h index 6c16e0faa..f9d367e0e 100644 --- a/unsupported/Eigen/CXX11/src/Tensor/Tensor.h +++ b/unsupported/Eigen/CXX11/src/Tensor/Tensor.h @@ -88,6 +88,11 @@ class Tensor : public TensorBase m_storage; + template + struct isOfNormalIndex{ + static const bool value = internal::is_base_of< array, CustomIndex >::value; + }; + public: // Metadata EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rank() const { return NumIndices; } @@ -111,14 +116,29 @@ class Tensor : public TensorBase{{firstIndex, secondIndex, otherIndices...}}); } + + #endif + + /** Normal Index */ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(const array& indices) const { eigen_internal_assert(checkIndexRange(indices)); return m_storage.data()[linearizedIndex(indices)]; } + /** Custom Index */ + template::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(const CustomIndex & indices) const + { + return coeff(internal::customIndex2Array(indices)); + } + + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const { eigen_internal_assert(index >= 0 && index < size()); @@ -135,12 +155,23 @@ class Tensor : public TensorBase& indices) { eigen_internal_assert(checkIndexRange(indices)); return m_storage.data()[linearizedIndex(indices)]; } + /** Custom Index */ + template::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(const CustomIndex & indices) + { + return coeffRef(internal::customIndex2Array(indices)); + } + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { eigen_internal_assert(index >= 0 && index < size()); @@ -178,9 +209,20 @@ class Tensor : public TensorBase::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(const CustomIndex & indices) const + { + //eigen_assert(checkIndexRange(indices)); /* already in coeff */ + return coeff(internal::customIndex2Array(indices)); + } + + /** Normal Index */ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& operator()(const array& indices) const { - eigen_assert(checkIndexRange(indices)); + //eigen_assert(checkIndexRange(indices)); /* already in coeff */ return coeff(indices); } @@ -228,12 +270,23 @@ class Tensor : public TensorBase& indices) { - eigen_assert(checkIndexRange(indices)); + //eigen_assert(checkIndexRange(indices)); /* already in coeff */ return coeffRef(indices); } + /** Custom Index */ + template::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(const CustomIndex & indices) + { + //eigen_assert(checkIndexRange(indices)); /* already in coeff */ + return coeffRef(internal::customIndex2Array(indices)); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& operator()(Index index) { eigen_assert(index >= 0 && index < size()); @@ -295,12 +348,20 @@ class Tensor : public TensorBase& dimensions) : m_storage(internal::array_prod(dimensions), dimensions) { EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED } + /** Custom Dimension (delegating constructor c++11) */ + template::value) ) + > + inline explicit Tensor(const CustomDimension & dimensions) : Tensor(internal::customIndex2Array(dimensions)) + {} + template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Tensor(const TensorBase& other) @@ -341,7 +402,7 @@ class Tensor : public TensorBase EIGEN_DEVICE_FUNC + template 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 +411,7 @@ class Tensor : public TensorBase& dimensions) { std::size_t i; @@ -367,6 +429,8 @@ class Tensor : public TensorBase& dimensions) { array dims; for (std::size_t i = 0; i < NumIndices; ++i) { @@ -375,6 +439,17 @@ class Tensor : public TensorBase::value) ) + > + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resize(const CustomDimension & dimensions) + { + //eigen_assert(checkIndexRange(indices)); /* already in coeff */ + return coeffRef(internal::customIndex2Array(dimensions)); + } + + #ifndef EIGEN_EMULATE_CXX11_META_H template EIGEN_DEVICE_FUNC diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h b/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h index 7dfa04760..60a6c1469 100644 --- a/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h +++ b/unsupported/Eigen/CXX11/src/Tensor/TensorMeta.h @@ -34,6 +34,9 @@ template <> struct max_n_1<0> { + + + #if defined(EIGEN_HAS_CONSTEXPR) #define EIGEN_CONSTEXPR constexpr #else @@ -83,6 +86,54 @@ bool operator!=(const Tuple& x, const Tuple& y) { return !(x == y); } + + + +namespace internal{ + + template + EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + array customIndex2Array(const IndexType & idx, numeric_list) { + return { idx(Is)... }; + } + + /** Make an array (for index/dimensions) out of a custom index */ + template + EIGEN_CONSTEXPR EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE + array customIndex2Array(const IndexType & idx) { + return customIndex2Array(idx, typename gen_numeric_list::type{}); + } + + + template + struct is_base_of + { + + typedef char (&yes)[1]; + typedef char (&no)[2]; + + template + struct Host + { + operator BB*() const; + operator DD*(); + }; + + template + static yes check(D*, T); + static no check(B*, int); + + static const bool value = sizeof(check(Host(), int())) == sizeof(yes); + }; + +} + + + + + + + #undef EIGEN_CONSTEXPR } // namespace Eigen diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorMetaMacros.h b/unsupported/Eigen/CXX11/src/Tensor/TensorMetaMacros.h new file mode 100644 index 000000000..8cb46e703 --- /dev/null +++ b/unsupported/Eigen/CXX11/src/Tensor/TensorMetaMacros.h @@ -0,0 +1,33 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2015 Benoit Steiner +// +// 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::value , int >::type = 0 + * > + * void foo(){} + * + * becomes => + * + * template::value ) + * > + * void foo(){} + */ + +#define EIGEN_SFINAE_ENABLE_IF( __condition__ ) \ + typename internal::enable_if< ( __condition__ ) , int >::type = 0 + + +#endif diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt index 7a1737edd..e9656f404 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_customIndex "-std=c++0x") # These tests needs nvcc # ei_add_test(cxx11_tensor_device "-std=c++0x") diff --git a/unsupported/test/cxx11_tensor_customIndex.cpp b/unsupported/test/cxx11_tensor_customIndex.cpp new file mode 100644 index 000000000..6ec809890 --- /dev/null +++ b/unsupported/test/cxx11_tensor_customIndex.cpp @@ -0,0 +1,41 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2014 Benoit Steiner +// +// 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 + +#include +#include + +using Eigen::Tensor; + + +template +static void test_customIndex() { + + Tensor tensor(2, 3, 5, 7); + + using NormalIndex = DSizes; + using CustomIndex = Matrix; + + tensor.setRandom(); + + 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 )); + +} + + +void test_cxx11_tensor_customIndex() { + CALL_SUBTEST(test_customIndex()); + CALL_SUBTEST(test_customIndex()); +}