From 62a1c911cd1fca97c381ac5cb21d0345934148a4 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 5 Feb 2016 21:24:35 +0100 Subject: [PATCH 1/9] Remove posix_memalign, _mm_malloc, and _aligned_malloc special paths. --- Eigen/src/Core/util/Memory.h | 110 +++------------------------------ doc/PreprocessorDirectives.dox | 3 - 2 files changed, 8 insertions(+), 105 deletions(-) diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 415bc48cb5..84fb0516cb 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -59,28 +59,6 @@ #endif -#ifndef EIGEN_HAS_POSIX_MEMALIGN - // See bug 554 (http://eigen.tuxfamily.org/bz/show_bug.cgi?id=554) - // It seems to be unsafe to check _POSIX_ADVISORY_INFO without including unistd.h first. - // Currently, let's include it only on unix systems: - #if EIGEN_OS_UNIX && !(EIGEN_OS_SUN || EIGEN_OS_SOLARIS) - #include - #if (EIGEN_OS_QNX || (defined _GNU_SOURCE) || EIGEN_COMP_PGI || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0) - #define EIGEN_HAS_POSIX_MEMALIGN 1 - #endif - #endif - - #ifndef EIGEN_HAS_POSIX_MEMALIGN - #define EIGEN_HAS_POSIX_MEMALIGN 0 - #endif -#endif - -#if defined EIGEN_VECTORIZE_SSE || defined EIGEN_VECTORIZE_AVX - #define EIGEN_HAS_MM_MALLOC 1 -#else - #define EIGEN_HAS_MM_MALLOC 0 -#endif - namespace Eigen { namespace internal { @@ -122,7 +100,7 @@ inline void handmade_aligned_free(void *ptr) /** \internal * \brief Reallocates aligned memory. - * Since we know that our handmade version is based on std::realloc + * Since we know that our handmade version is based on std::malloc * we can use std::realloc to implement efficient reallocation. */ inline void* handmade_aligned_realloc(void* ptr, std::size_t size, std::size_t = 0) @@ -141,47 +119,6 @@ inline void* handmade_aligned_realloc(void* ptr, std::size_t size, std::size_t = return aligned; } -/***************************************************************************** -*** Implementation of generic aligned realloc (when no realloc can be used)*** -*****************************************************************************/ - -EIGEN_DEVICE_FUNC void* aligned_malloc(std::size_t size); -EIGEN_DEVICE_FUNC void aligned_free(void *ptr); - -/** \internal - * \brief Reallocates aligned memory. - * Allows reallocation with aligned ptr types. This implementation will - * always create a new memory chunk and copy the old data. - */ -inline void* generic_aligned_realloc(void* ptr, size_t size, size_t old_size) -{ - if (ptr==0) - return aligned_malloc(size); - - if (size==0) - { - aligned_free(ptr); - return 0; - } - - void* newptr = aligned_malloc(size); - if (newptr == 0) - { - #ifdef EIGEN_HAS_ERRNO - errno = ENOMEM; // according to the standard - #endif - return 0; - } - - if (ptr != 0) - { - std::memcpy(newptr, ptr, (std::min)(size,old_size)); - aligned_free(ptr); - } - - return newptr; -} - /***************************************************************************** *** Implementation of portable aligned versions of malloc/free/realloc *** *****************************************************************************/ @@ -218,16 +155,8 @@ EIGEN_DEVICE_FUNC inline void* aligned_malloc(size_t size) check_that_malloc_is_allowed(); void *result; - #if EIGEN_DEFAULT_ALIGN_BYTES==0 + #if (EIGEN_DEFAULT_ALIGN_BYTES==0) || EIGEN_MALLOC_ALREADY_ALIGNED result = std::malloc(size); - #elif EIGEN_MALLOC_ALREADY_ALIGNED - result = std::malloc(size); - #elif EIGEN_HAS_POSIX_MEMALIGN - if(posix_memalign(&result, EIGEN_DEFAULT_ALIGN_BYTES, size)) result = 0; - #elif EIGEN_HAS_MM_MALLOC - result = _mm_malloc(size, EIGEN_DEFAULT_ALIGN_BYTES); - #elif EIGEN_OS_WIN_STRICT - result = _aligned_malloc(size, EIGEN_DEFAULT_ALIGN_BYTES); #else result = handmade_aligned_malloc(size); #endif @@ -241,48 +170,25 @@ EIGEN_DEVICE_FUNC inline void* aligned_malloc(size_t size) /** \internal Frees memory allocated with aligned_malloc. */ EIGEN_DEVICE_FUNC inline void aligned_free(void *ptr) { - #if EIGEN_DEFAULT_ALIGN_BYTES==0 + #if (EIGEN_DEFAULT_ALIGN_BYTES==0) || EIGEN_MALLOC_ALREADY_ALIGNED std::free(ptr); - #elif EIGEN_MALLOC_ALREADY_ALIGNED - std::free(ptr); - #elif EIGEN_HAS_POSIX_MEMALIGN - std::free(ptr); - #elif EIGEN_HAS_MM_MALLOC - _mm_free(ptr); - #elif EIGEN_OS_WIN_STRICT - _aligned_free(ptr); #else handmade_aligned_free(ptr); #endif } /** -* \internal -* \brief Reallocates an aligned block of memory. -* \throws std::bad_alloc on allocation failure -**/ + * \internal + * \brief Reallocates an aligned block of memory. + * \throws std::bad_alloc on allocation failure + */ inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size) { EIGEN_UNUSED_VARIABLE(old_size); void *result; -#if EIGEN_DEFAULT_ALIGN_BYTES==0 +#if (EIGEN_DEFAULT_ALIGN_BYTES==0) || EIGEN_MALLOC_ALREADY_ALIGNED result = std::realloc(ptr,new_size); -#elif EIGEN_MALLOC_ALREADY_ALIGNED - result = std::realloc(ptr,new_size); -#elif EIGEN_HAS_POSIX_MEMALIGN - result = generic_aligned_realloc(ptr,new_size,old_size); -#elif EIGEN_HAS_MM_MALLOC - // The defined(_mm_free) is just here to verify that this MSVC version - // implements _mm_malloc/_mm_free based on the corresponding _aligned_ - // functions. This may not always be the case and we just try to be safe. - #if EIGEN_OS_WIN_STRICT && defined(_mm_free) - result = _aligned_realloc(ptr,new_size,EIGEN_DEFAULT_ALIGN_BYTES); - #else - result = generic_aligned_realloc(ptr,new_size,old_size); - #endif -#elif EIGEN_OS_WIN_STRICT - result = _aligned_realloc(ptr,new_size,EIGEN_DEFAULT_ALIGN_BYTES); #else result = handmade_aligned_realloc(ptr,new_size,old_size); #endif diff --git a/doc/PreprocessorDirectives.dox b/doc/PreprocessorDirectives.dox index 7cde1a36fc..14e84bc204 100644 --- a/doc/PreprocessorDirectives.dox +++ b/doc/PreprocessorDirectives.dox @@ -87,9 +87,6 @@ run time. However, these assertions do cost time and can thus be turned off. - \b EIGEN_STACK_ALLOCATION_LIMIT - defines the maximum bytes for a buffer to be allocated on the stack. For internal temporary buffers, dynamic memory allocation is employed as a fall back. For fixed-size matrices or arrays, exceeding this threshold raises a compile time assertion. Use 0 to set no limit. Default is 128 KB. - - \b EIGEN_HAS_POSIX_MEMALIGN - defines whether aligned memory allocation can be performed through the \c posix_memalign - function. The availability of \c posix_memalign is automatically checked on most platform, but this option allows to - by-pass %Eigen's built-in rules. \section TopicPreprocessorDirectivesPlugins Plugins From e8e1d504d6cbeb47c33169a36c052aa21bea32ee Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 5 Feb 2016 21:38:16 +0100 Subject: [PATCH 2/9] Add an explicit assersion on the alignment of the pointer returned by std::malloc --- Eigen/src/Core/util/Memory.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 84fb0516cb..01513a59eb 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -157,6 +157,9 @@ EIGEN_DEVICE_FUNC inline void* aligned_malloc(size_t size) void *result; #if (EIGEN_DEFAULT_ALIGN_BYTES==0) || EIGEN_MALLOC_ALREADY_ALIGNED result = std::malloc(size); + #if EIGEN_DEFAULT_ALIGN_BYTES==16 + eigen_assert((size<16 || (std::size_t(result)%16)==0) && "System's malloc returned an unaligned pointer. Compile with EIGEN_MALLOC_ALREADY_ALIGNED=0 to fallback to handmade alignd memory allocator."); + #endif #else result = handmade_aligned_malloc(size); #endif From 5b2d287878d4f049c1ba6c55c1fcaac1129d6df0 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 5 Feb 2016 21:46:39 +0100 Subject: [PATCH 3/9] bug #779: allow non aligned buffers for buffers smaller than the requested alignment. --- Eigen/src/Core/MapBase.h | 3 ++- test/dynalloc.cpp | 6 +++--- test/mapped_matrix.cpp | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Eigen/src/Core/MapBase.h b/Eigen/src/Core/MapBase.h index 75a80daaad..afa47540e6 100644 --- a/Eigen/src/Core/MapBase.h +++ b/Eigen/src/Core/MapBase.h @@ -165,7 +165,8 @@ template class MapBase void checkSanity() const { #if EIGEN_MAX_ALIGN_BYTES>0 - eigen_assert(((size_t(m_data) % EIGEN_PLAIN_ENUM_MAX(1,internal::traits::Alignment)) == 0) && "data is not aligned"); + eigen_assert(( ((size_t(m_data) % EIGEN_PLAIN_ENUM_MAX(1,internal::traits::Alignment)) == 0) + || (cols() * rows() * innerStride() * sizeof(Scalar)) < internal::traits::Alignment ) && "data is not aligned"); #endif } diff --git a/test/dynalloc.cpp b/test/dynalloc.cpp index 6f22e1ab4c..5f587007cb 100644 --- a/test/dynalloc.cpp +++ b/test/dynalloc.cpp @@ -31,7 +31,7 @@ void check_handmade_aligned_malloc() void check_aligned_malloc() { - for(int i = 1; i < 1000; i++) + for(int i = ALIGNMENT; i < 1000; i++) { char *p = (char*)internal::aligned_malloc(i); VERIFY(size_t(p)%ALIGNMENT==0); @@ -43,7 +43,7 @@ void check_aligned_malloc() void check_aligned_new() { - for(int i = 1; i < 1000; i++) + for(int i = ALIGNMENT; i < 1000; i++) { float *p = internal::aligned_new(i); VERIFY(size_t(p)%ALIGNMENT==0); @@ -55,7 +55,7 @@ void check_aligned_new() void check_aligned_stack_alloc() { - for(int i = 1; i < 400; i++) + for(int i = ALIGNMENT; i < 400; i++) { ei_declare_aligned_stack_constructed_variable(float,p,i,0); VERIFY(size_t(p)%ALIGNMENT==0); diff --git a/test/mapped_matrix.cpp b/test/mapped_matrix.cpp index 7c7099792d..88653e887c 100644 --- a/test/mapped_matrix.cpp +++ b/test/mapped_matrix.cpp @@ -40,7 +40,7 @@ template void map_class_vector(const VectorType& m) VERIFY_IS_EQUAL(ma1, ma3); VERIFY_IS_EQUAL(ma1, ma4); #ifdef EIGEN_VECTORIZE - if(internal::packet_traits::Vectorizable) + if(internal::packet_traits::Vectorizable && size>=AlignedMax) VERIFY_RAISES_ASSERT((Map(array3unaligned, size))) #endif From fb00a4af2b28ec0b92c072ab059934a673dc2454 Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Sat, 6 Feb 2016 01:42:14 +0000 Subject: [PATCH 4/9] Made the tensor fft test compile on tegra x1 --- unsupported/test/cxx11_tensor_fft.cpp | 46 +++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/unsupported/test/cxx11_tensor_fft.cpp b/unsupported/test/cxx11_tensor_fft.cpp index 0f6e091061..b2a4b5a96e 100644 --- a/unsupported/test/cxx11_tensor_fft.cpp +++ b/unsupported/test/cxx11_tensor_fft.cpp @@ -14,7 +14,7 @@ using Eigen::Tensor; template static void test_fft_2D_golden() { - Tensor input(2, 3); + Tensor input(2, 3); input(0, 0) = 1; input(0, 1) = 2; input(0, 2) = 3; @@ -22,11 +22,11 @@ static void test_fft_2D_golden() { input(1, 1) = 5; input(1, 2) = 6; - array fft; + array fft; fft[0] = 0; fft[1] = 1; - Tensor, 2, DataLayout, long> output = input.template fft(fft); + Tensor, 2, DataLayout> output = input.template fft(fft); std::complex output_golden[6]; // in ColMajor order output_golden[0] = std::complex(21, 0); @@ -57,24 +57,24 @@ static void test_fft_2D_golden() { } static void test_fft_complex_input_golden() { - Tensor, 1, ColMajor, long> input(5); + Tensor, 1, ColMajor> input(5); input(0) = std::complex(1, 1); input(1) = std::complex(2, 2); input(2) = std::complex(3, 3); input(3) = std::complex(4, 4); input(4) = std::complex(5, 5); - array fft; + array fft; fft[0] = 0; - Tensor, 1, ColMajor, long> forward_output_both_parts = input.fft(fft); - Tensor, 1, ColMajor, long> reverse_output_both_parts = input.fft(fft); + Tensor, 1, ColMajor> forward_output_both_parts = input.fft(fft); + Tensor, 1, ColMajor> reverse_output_both_parts = input.fft(fft); - Tensor forward_output_real_part = input.fft(fft); - Tensor reverse_output_real_part = input.fft(fft); + Tensor forward_output_real_part = input.fft(fft); + Tensor reverse_output_real_part = input.fft(fft); - Tensor forward_output_imag_part = input.fft(fft); - Tensor reverse_output_imag_part = input.fft(fft); + Tensor forward_output_imag_part = input.fft(fft); + Tensor reverse_output_imag_part = input.fft(fft); VERIFY_IS_EQUAL(forward_output_both_parts.dimension(0), input.dimension(0)); VERIFY_IS_EQUAL(reverse_output_both_parts.dimension(0), input.dimension(0)); @@ -114,24 +114,24 @@ static void test_fft_complex_input_golden() { } static void test_fft_real_input_golden() { - Tensor input(5); + Tensor input(5); input(0) = 1.0; input(1) = 2.0; input(2) = 3.0; input(3) = 4.0; input(4) = 5.0; - array fft; + array fft; fft[0] = 0; - Tensor, 1, ColMajor, long> forward_output_both_parts = input.fft(fft); - Tensor, 1, ColMajor, long> reverse_output_both_parts = input.fft(fft); + Tensor, 1, ColMajor> forward_output_both_parts = input.fft(fft); + Tensor, 1, ColMajor> reverse_output_both_parts = input.fft(fft); - Tensor forward_output_real_part = input.fft(fft); - Tensor reverse_output_real_part = input.fft(fft); + Tensor forward_output_real_part = input.fft(fft); + Tensor reverse_output_real_part = input.fft(fft); - Tensor forward_output_imag_part = input.fft(fft); - Tensor reverse_output_imag_part = input.fft(fft); + Tensor forward_output_imag_part = input.fft(fft); + Tensor reverse_output_imag_part = input.fft(fft); VERIFY_IS_EQUAL(forward_output_both_parts.dimension(0), input.dimension(0)); VERIFY_IS_EQUAL(reverse_output_both_parts.dimension(0), input.dimension(0)); @@ -178,17 +178,17 @@ static void test_fft_real_input_golden() { template static void test_fft_real_input_energy() { - Eigen::DSizes dimensions; - int total_size = 1; + Eigen::DSizes dimensions; + ptrdiff_t total_size = 1; for (int i = 0; i < TensorRank; ++i) { dimensions[i] = rand() % 20 + 1; total_size *= dimensions[i]; } - const DSizes arr = dimensions; + const DSizes arr = dimensions; typedef typename internal::conditional, RealScalar>::type InputScalar; - Tensor input; + Tensor input; input.resize(arr); input.setRandom(); From d2cba520152fadcddb481142ba2250b5bbf0ad81 Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Fri, 5 Feb 2016 18:14:23 -0800 Subject: [PATCH 5/9] Only enable the cxx11_tensor_uint128 test on 64 bit machines since 32 bit systems don't support the __uin128_t type --- unsupported/test/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt index 42e0189a48..c202cf0e41 100644 --- a/unsupported/test/CMakeLists.txt +++ b/unsupported/test/CMakeLists.txt @@ -117,7 +117,6 @@ if(EIGEN_TEST_CXX11) ei_add_test(cxx11_tensor_of_const_values "-std=c++0x") ei_add_test(cxx11_tensor_of_complex "-std=c++0x") ei_add_test(cxx11_tensor_of_strings "-std=c++0x") - ei_add_test(cxx11_tensor_uint128 "-std=c++0x") ei_add_test(cxx11_tensor_intdiv "-std=c++0x") ei_add_test(cxx11_tensor_lvalue "-std=c++0x") ei_add_test(cxx11_tensor_map "-std=c++0x") @@ -149,6 +148,11 @@ if(EIGEN_TEST_CXX11) ei_add_test(cxx11_tensor_ifft "-std=c++0x") ei_add_test(cxx11_tensor_empty "-std=c++0x") + if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + # This test requires __uint128_t which is only available on 64bit systems + ei_add_test(cxx11_tensor_uint128 "-std=c++0x") + endif() + endif() # These tests needs nvcc From 4d4211c04ebded41109a672002401cc65ef2d3a0 Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Fri, 5 Feb 2016 18:19:41 -0800 Subject: [PATCH 6/9] Avoid unecessary type conversions --- unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h | 2 +- unsupported/test/cxx11_tensor_fft.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h b/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h index 3bfaf6d234..9e675ad0ff 100644 --- a/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h +++ b/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h @@ -206,7 +206,7 @@ struct TensorEvaluator, D } for (size_t i = 0; i < m_fft.size(); ++i) { - int dim = m_fft[i]; + Index dim = m_fft[i]; eigen_assert(dim >= 0 && dim < NumDims); Index line_len = m_dimensions[dim]; eigen_assert(line_len >= 1); diff --git a/unsupported/test/cxx11_tensor_fft.cpp b/unsupported/test/cxx11_tensor_fft.cpp index b2a4b5a96e..89874349fa 100644 --- a/unsupported/test/cxx11_tensor_fft.cpp +++ b/unsupported/test/cxx11_tensor_fft.cpp @@ -192,7 +192,7 @@ static void test_fft_real_input_energy() { input.resize(arr); input.setRandom(); - array fft; + array fft; for (int i = 0; i < TensorRank; ++i) { fft[i] = i; } From c6a12d1dc61cb38f5c9d48241d30cd99c9b99fd2 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sat, 6 Feb 2016 18:06:51 +0100 Subject: [PATCH 7/9] Fix warning with gcc < 4.8 --- Eigen/src/Core/MapBase.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Eigen/src/Core/MapBase.h b/Eigen/src/Core/MapBase.h index afa47540e6..12c464a5ac 100644 --- a/Eigen/src/Core/MapBase.h +++ b/Eigen/src/Core/MapBase.h @@ -130,7 +130,7 @@ template class MapBase explicit inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime) { EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) - checkSanity(); + checkSanity(); } EIGEN_DEVICE_FUNC @@ -142,7 +142,7 @@ template class MapBase EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) eigen_assert(vecSize >= 0); eigen_assert(dataPtr == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == vecSize); - checkSanity(); + checkSanity(); } EIGEN_DEVICE_FUNC @@ -152,7 +152,7 @@ template class MapBase eigen_assert( (dataPtr == 0) || ( rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols))); - checkSanity(); + checkSanity(); } #ifdef EIGEN_MAPBASE_PLUGIN @@ -161,15 +161,21 @@ template class MapBase protected: + template EIGEN_DEVICE_FUNC - void checkSanity() const + void checkSanity(typename internal::enable_if<(internal::traits::Alignment>0),void*>::type = 0) const { #if EIGEN_MAX_ALIGN_BYTES>0 - eigen_assert(( ((size_t(m_data) % EIGEN_PLAIN_ENUM_MAX(1,internal::traits::Alignment)) == 0) + eigen_assert(( ((size_t(m_data) % internal::traits::Alignment) == 0) || (cols() * rows() * innerStride() * sizeof(Scalar)) < internal::traits::Alignment ) && "data is not aligned"); #endif } + template + EIGEN_DEVICE_FUNC + void checkSanity(typename internal::enable_if::Alignment==0,void*>::type = 0) const + {} + PointerType m_data; const internal::variable_if_dynamic m_rows; const internal::variable_if_dynamic m_cols; From 8e599bc098cef7030004489dca2b9dab920f2cc8 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sat, 6 Feb 2016 20:26:59 +0100 Subject: [PATCH 8/9] Fix warning in unit test --- test/zerosized.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/zerosized.cpp b/test/zerosized.cpp index 85c5534538..2404fdc2b3 100644 --- a/test/zerosized.cpp +++ b/test/zerosized.cpp @@ -49,8 +49,8 @@ template void zeroSizedMatrix() if(MatrixType::MaxColsAtCompileTime!=0 && MatrixType::MaxRowsAtCompileTime!=0) { - Index rows = MatrixType::RowsAtCompileTime==Dynamic ? internal::random(1,10) : MatrixType::RowsAtCompileTime; - Index cols = MatrixType::ColsAtCompileTime==Dynamic ? internal::random(1,10) : MatrixType::ColsAtCompileTime; + Index rows = MatrixType::RowsAtCompileTime==Dynamic ? internal::random(1,10) : Index(MatrixType::RowsAtCompileTime); + Index cols = MatrixType::ColsAtCompileTime==Dynamic ? internal::random(1,10) : Index(MatrixType::ColsAtCompileTime); MatrixType m(rows,cols); zeroReduction(m.template block<0,MatrixType::ColsAtCompileTime>(0,0,0,cols)); zeroReduction(m.template block(0,0,rows,0)); From 010afe1619c9200b885f74d3c3937e000ec76b1d Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sat, 6 Feb 2016 22:49:18 +0100 Subject: [PATCH 9/9] Add exemples for reshaping/slicing with Map. --- doc/Manual.dox | 2 + doc/TutorialReshapeSlicing.dox | 65 ++++++++++++++++++++++++ doc/snippets/Tutorial_ReshapeMat2Mat.cpp | 6 +++ doc/snippets/Tutorial_ReshapeMat2Vec.cpp | 11 ++++ doc/snippets/Tutorial_SlicingCol.cpp | 11 ++++ doc/snippets/Tutorial_SlicingVec.cpp | 4 ++ 6 files changed, 99 insertions(+) create mode 100644 doc/TutorialReshapeSlicing.dox create mode 100644 doc/snippets/Tutorial_ReshapeMat2Mat.cpp create mode 100644 doc/snippets/Tutorial_ReshapeMat2Vec.cpp create mode 100644 doc/snippets/Tutorial_SlicingCol.cpp create mode 100644 doc/snippets/Tutorial_SlicingVec.cpp diff --git a/doc/Manual.dox b/doc/Manual.dox index c10c490a76..70aaa9a425 100644 --- a/doc/Manual.dox +++ b/doc/Manual.dox @@ -59,6 +59,8 @@ namespace Eigen { \ingroup DenseMatrixManipulation_chapter */ /** \addtogroup TutorialMapClass \ingroup DenseMatrixManipulation_chapter */ +/** \addtogroup TutorialReshapeSlicing + \ingroup DenseMatrixManipulation_chapter */ /** \addtogroup TopicAliasing \ingroup DenseMatrixManipulation_chapter */ /** \addtogroup TopicStorageOrders diff --git a/doc/TutorialReshapeSlicing.dox b/doc/TutorialReshapeSlicing.dox new file mode 100644 index 0000000000..eb0fb0df0c --- /dev/null +++ b/doc/TutorialReshapeSlicing.dox @@ -0,0 +1,65 @@ +namespace Eigen { + +/** \eigenManualPage TutorialReshapeSlicing Reshape and Slicing + +%Eigen does not expose convenient methods to take slices or to reshape a matrix yet. +Nonetheless, such features can easily be emulated using the Map class. + +\eigenAutoToc + +\section TutorialReshape Reshape + +A reshape operation consists in modifying the sizes of a matrix while keeping the same coefficients. +Instead of modifying the input matrix itself, which is not possible for compile-time sizes, the approach consist in creating a different \em view on the storage using class Map. +Here is a typical example creating a 1D linear view of a matrix: + + + + +
Example:Output:
+\include Tutorial_ReshapeMat2Vec.cpp + +\verbinclude Tutorial_ReshapeMat2Vec.out +
+ +Remark how the storage order of the input matrix modifies the order of the coefficients in the linear view. +Here is another example reshaping a 2x6 matrix to a 6x2 one: + + + +
Example:Output:
+\include Tutorial_ReshapeMat2Mat.cpp + +\verbinclude Tutorial_ReshapeMat2Mat.out +
+ + + +\section TutorialSlicing Slicing + +Slicing consists in taking a set of rows, or columns, or elements, uniformly spaced within a matrix. +Again, the class Map allows to easily mimic this feature. + +For instance, one can take skip every P elements in a vector: + + + +
Example:Output:
+\include Tutorial_SlicingVec.cpp + +\verbinclude Tutorial_SlicingVec.out +
+ +One can olso take one column over three using an adequate outer-stride or inner-stride depending on the actual storage order: + + + +
Example:Output:
+\include Tutorial_SlicingCol.cpp + +\verbinclude Tutorial_SlicingCol.out +
+ +*/ + +} diff --git a/doc/snippets/Tutorial_ReshapeMat2Mat.cpp b/doc/snippets/Tutorial_ReshapeMat2Mat.cpp new file mode 100644 index 0000000000..f84d6e76d0 --- /dev/null +++ b/doc/snippets/Tutorial_ReshapeMat2Mat.cpp @@ -0,0 +1,6 @@ +MatrixXf M1(2,6); // Column-major storage +M1 << 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12; + +Map M2(M1.data(), 6,2); +cout << "M2:" << endl << M2 << endl; \ No newline at end of file diff --git a/doc/snippets/Tutorial_ReshapeMat2Vec.cpp b/doc/snippets/Tutorial_ReshapeMat2Vec.cpp new file mode 100644 index 0000000000..95bd4e0e6b --- /dev/null +++ b/doc/snippets/Tutorial_ReshapeMat2Vec.cpp @@ -0,0 +1,11 @@ +MatrixXf M1(3,3); // Column-major storage +M1 << 1, 2, 3, + 4, 5, 6, + 7, 8, 9; + +Map v1(M1.data(), M1.size()); +cout << "v1:" << endl << v1 << endl; + +Matrix M2(M1); +Map v2(M2.data(), M2.size()); +cout << "v2:" << endl << v2 << endl; \ No newline at end of file diff --git a/doc/snippets/Tutorial_SlicingCol.cpp b/doc/snippets/Tutorial_SlicingCol.cpp new file mode 100644 index 0000000000..f667ff6894 --- /dev/null +++ b/doc/snippets/Tutorial_SlicingCol.cpp @@ -0,0 +1,11 @@ +MatrixXf M1 = MatrixXf::Random(3,8); +cout << "Column major input:" << endl << M1 << "\n"; +Map > M2(M1.data(), M1.rows(), (M1.cols()+2)/3, OuterStride<>(M1.outerStride()*3)); +cout << "1 column over 3:" << endl << M2 << "\n"; + +typedef Matrix RowMajorMatrixXf; +RowMajorMatrixXf M3(M1); +cout << "Row major input:" << endl << M3 << "\n"; +Map > M4(M3.data(), M3.rows(), (M3.cols()+2)/3, + Stride(M3.outerStride(),3)); +cout << "1 column over 3:" << endl << M4 << "\n"; \ No newline at end of file diff --git a/doc/snippets/Tutorial_SlicingVec.cpp b/doc/snippets/Tutorial_SlicingVec.cpp new file mode 100644 index 0000000000..07e10bf695 --- /dev/null +++ b/doc/snippets/Tutorial_SlicingVec.cpp @@ -0,0 +1,4 @@ +RowVectorXf v = RowVectorXf::LinSpaced(20,0,19); +cout << "Input:" << endl << v << endl; +Map > v2(v.data(), v.size()/2); +cout << "Even:" << v2 << endl; \ No newline at end of file