From 5c516e4e0a1290b9a233c8f3c379fd6bde5ef9c2 Mon Sep 17 00:00:00 2001 From: Sergiu Deitsch Date: Tue, 22 Nov 2016 12:25:06 +0100 Subject: [PATCH 01/13] cmake: added Eigen3::Eigen imported target (grafted from a287140f7292b9c15719bc6a3a4494ac7874e3cd ) --- CMakeLists.txt | 60 ++++++++++++++++++++++++++----- cmake/Eigen3Config.cmake.in | 41 +++++++++------------ cmake/Eigen3ConfigLegacy.cmake.in | 28 +++++++++++++++ doc/Manual.dox | 1 + doc/TopicCMakeGuide.dox | 40 +++++++++++++++++++++ 5 files changed, 138 insertions(+), 32 deletions(-) create mode 100644 cmake/Eigen3ConfigLegacy.cmake.in create mode 100644 doc/TopicCMakeGuide.dox diff --git a/CMakeLists.txt b/CMakeLists.txt index f38e22973..6c1520d7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -510,15 +510,59 @@ set ( EIGEN_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}" ) set ( EIGEN_INCLUDE_DIRS ${EIGEN_INCLUDE_DIR} ) set ( EIGEN_ROOT_DIR ${CMAKE_INSTALL_PREFIX} ) -configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Eigen3Config.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake - @ONLY ESCAPE_QUOTES - ) +# Interface libraries require at least CMake 3.0 +if (NOT CMAKE_VERSION VERSION_LESS 3.0) + include (CMakePackageConfigHelpers) -install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UseEigen3.cmake - ${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake - DESTINATION ${CMAKEPACKAGE_INSTALL_DIR} - ) + # Imported target support + add_library (eigen INTERFACE) + + target_compile_definitions (eigen INTERFACE ${EIGEN_DEFINITIONS}) + target_include_directories (eigen INTERFACE + $ + $ + ) + + # Export as title case Eigen + set_target_properties (eigen PROPERTIES EXPORT_NAME Eigen) + + install (TARGETS eigen EXPORT Eigen3Targets) + + configure_package_config_file ( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Eigen3Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake + INSTALL_DESTINATION ${CMAKEPACKAGE_INSTALL_DIR} + NO_CHECK_REQUIRED_COMPONENTS_MACRO # Eigen does not provide components + ) + write_basic_package_version_file (Eigen3ConfigVersion.cmake + VERSION ${EIGEN_VERSION_NUMBER} COMPATIBILITY SameMajorVersion) + + # The Eigen target will be located in the Eigen3 namespace. Other CMake + # targets can refer to it using Eigen3::Eigen. + export (TARGETS eigen NAMESPACE Eigen3:: FILE Eigen3Targets.cmake) + # Export Eigen3 package to CMake registry such that it can be easily found by + # CMake even if it has not been installed to a standard directory. + export (PACKAGE Eigen3) + + install (EXPORT Eigen3Targets NAMESPACE Eigen3:: DESTINATION + ${CMAKEPACKAGE_INSTALL_DIR}) + install (FILES + ${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/Eigen3ConfigVersion.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UseEigen3.cmake + DESTINATION ${CMAKEPACKAGE_INSTALL_DIR}) +else (NOT CMAKE_VERSION VERSION_LESS 3.0) + # Fallback to legacy Eigen3Config.cmake without the imported target + configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Eigen3ConfigLegacy.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake + @ONLY ESCAPE_QUOTES + ) + + install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UseEigen3.cmake + ${CMAKE_CURRENT_BINARY_DIR}/Eigen3Config.cmake + DESTINATION ${CMAKEPACKAGE_INSTALL_DIR} + ) +endif (NOT CMAKE_VERSION VERSION_LESS 3.0) # Add uninstall target add_custom_target ( uninstall diff --git a/cmake/Eigen3Config.cmake.in b/cmake/Eigen3Config.cmake.in index 04e7886ce..01937a3cc 100644 --- a/cmake/Eigen3Config.cmake.in +++ b/cmake/Eigen3Config.cmake.in @@ -1,28 +1,21 @@ -# -*- cmake -*- -# -# Eigen3Config.cmake(.in) +# This file exports the Eigen3::Eigen CMake target which should be passed to the +# target_link_libraries command. -# Use the following variables to compile and link against Eigen: -# EIGEN3_FOUND - True if Eigen was found on your system -# EIGEN3_USE_FILE - The file making Eigen usable -# EIGEN3_DEFINITIONS - Definitions needed to build with Eigen -# EIGEN3_INCLUDE_DIR - Directory where signature_of_eigen3_matrix_library can be found -# EIGEN3_INCLUDE_DIRS - List of directories of Eigen and it's dependencies -# EIGEN3_ROOT_DIR - The base directory of Eigen -# EIGEN3_VERSION_STRING - A human-readable string containing the version -# EIGEN3_VERSION_MAJOR - The major version of Eigen -# EIGEN3_VERSION_MINOR - The minor version of Eigen -# EIGEN3_VERSION_PATCH - The patch version of Eigen +@PACKAGE_INIT@ -set ( EIGEN3_FOUND 1 ) -set ( EIGEN3_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseEigen3.cmake" ) +include ("${CMAKE_CURRENT_LIST_DIR}/Eigen3Targets.cmake") -set ( EIGEN3_DEFINITIONS "@EIGEN_DEFINITIONS@" ) -set ( EIGEN3_INCLUDE_DIR "@EIGEN_INCLUDE_DIR@" ) -set ( EIGEN3_INCLUDE_DIRS "@EIGEN_INCLUDE_DIRS@" ) -set ( EIGEN3_ROOT_DIR "@EIGEN_ROOT_DIR@" ) +# Legacy variables, do *not* use. May be removed in the future. -set ( EIGEN3_VERSION_STRING "@EIGEN_VERSION_STRING@" ) -set ( EIGEN3_VERSION_MAJOR "@EIGEN_VERSION_MAJOR@" ) -set ( EIGEN3_VERSION_MINOR "@EIGEN_VERSION_MINOR@" ) -set ( EIGEN3_VERSION_PATCH "@EIGEN_VERSION_PATCH@" ) +set (EIGEN3_FOUND 1) +set (EIGEN3_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseEigen3.cmake") + +set (EIGEN3_DEFINITIONS "@EIGEN_DEFINITIONS@") +set (EIGEN3_INCLUDE_DIR "@EIGEN_INCLUDE_DIR@") +set (EIGEN3_INCLUDE_DIRS "@EIGEN_INCLUDE_DIRS@") +set (EIGEN3_ROOT_DIR "@EIGEN_ROOT_DIR@") + +set (EIGEN3_VERSION_STRING "@EIGEN_VERSION_STRING@") +set (EIGEN3_VERSION_MAJOR "@EIGEN_VERSION_MAJOR@") +set (EIGEN3_VERSION_MINOR "@EIGEN_VERSION_MINOR@") +set (EIGEN3_VERSION_PATCH "@EIGEN_VERSION_PATCH@") diff --git a/cmake/Eigen3ConfigLegacy.cmake.in b/cmake/Eigen3ConfigLegacy.cmake.in new file mode 100644 index 000000000..04e7886ce --- /dev/null +++ b/cmake/Eigen3ConfigLegacy.cmake.in @@ -0,0 +1,28 @@ +# -*- cmake -*- +# +# Eigen3Config.cmake(.in) + +# Use the following variables to compile and link against Eigen: +# EIGEN3_FOUND - True if Eigen was found on your system +# EIGEN3_USE_FILE - The file making Eigen usable +# EIGEN3_DEFINITIONS - Definitions needed to build with Eigen +# EIGEN3_INCLUDE_DIR - Directory where signature_of_eigen3_matrix_library can be found +# EIGEN3_INCLUDE_DIRS - List of directories of Eigen and it's dependencies +# EIGEN3_ROOT_DIR - The base directory of Eigen +# EIGEN3_VERSION_STRING - A human-readable string containing the version +# EIGEN3_VERSION_MAJOR - The major version of Eigen +# EIGEN3_VERSION_MINOR - The minor version of Eigen +# EIGEN3_VERSION_PATCH - The patch version of Eigen + +set ( EIGEN3_FOUND 1 ) +set ( EIGEN3_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseEigen3.cmake" ) + +set ( EIGEN3_DEFINITIONS "@EIGEN_DEFINITIONS@" ) +set ( EIGEN3_INCLUDE_DIR "@EIGEN_INCLUDE_DIR@" ) +set ( EIGEN3_INCLUDE_DIRS "@EIGEN_INCLUDE_DIRS@" ) +set ( EIGEN3_ROOT_DIR "@EIGEN_ROOT_DIR@" ) + +set ( EIGEN3_VERSION_STRING "@EIGEN_VERSION_STRING@" ) +set ( EIGEN3_VERSION_MAJOR "@EIGEN_VERSION_MAJOR@" ) +set ( EIGEN3_VERSION_MINOR "@EIGEN_VERSION_MINOR@" ) +set ( EIGEN3_VERSION_PATCH "@EIGEN_VERSION_PATCH@" ) diff --git a/doc/Manual.dox b/doc/Manual.dox index a08609ad7..342b145fd 100644 --- a/doc/Manual.dox +++ b/doc/Manual.dox @@ -26,6 +26,7 @@ namespace Eigen { - \subpage TopicPitfalls - \subpage TopicTemplateKeyword - \subpage UserManual_UnderstandingEigen + - \subpage TopicCMakeGuide */ /** \page UserManual_UnderstandingEigen Understanding Eigen diff --git a/doc/TopicCMakeGuide.dox b/doc/TopicCMakeGuide.dox new file mode 100644 index 000000000..5362413d6 --- /dev/null +++ b/doc/TopicCMakeGuide.dox @@ -0,0 +1,40 @@ +namespace Eigen { + +/** + +\page TopicCMakeGuide Using %Eigen in CMake Projects + +%Eigen provides native CMake support which allows the library to be easily +used in CMake projects. + +\note %CMake 3.0 (or later) is required to enable this functionality. + +%Eigen exports a CMake target called `Eigen3::Eigen` which can be imported +using the `find_package` CMake command and used by calling +`target_link_libraries` as in the following example: +\code{.cmake} +cmake_minimum_required (VERSION 3.0) +project (myproject) + +find_package (Eigen3 3.3 REQUIRED) + +add_executable (example example.cpp) +target_link_libraries (example Eigen3::Eigen) +\endcode + +The above code snippet must be placed in a file called `CMakeLists.txt` alongside +`example.cpp`. After running +\code{.sh} +$ cmake path-to-example-directory +\endcode +CMake will produce project files that generate an executable called `example` +which requires at least version 3.3 of %Eigen. Here, `path-to-example-directory` +is the path to the directory that contains both `CMakeLists.txt` and +`example.cpp`. + + +*/ + +} + +// vim: set ft=cpp.doxygen From a0329f64fbd2d0cf09fea0d55a9a2538a87dad8a Mon Sep 17 00:00:00 2001 From: Rasmus Munk Larsen Date: Tue, 29 Nov 2016 13:18:09 -0800 Subject: [PATCH 02/13] Add a default constructor for the "fake" __half class when not using the __half class provided by CUDA. --- Eigen/src/Core/arch/CUDA/Half.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Eigen/src/Core/arch/CUDA/Half.h b/Eigen/src/Core/arch/CUDA/Half.h index 63371bdf4..5a400307b 100644 --- a/Eigen/src/Core/arch/CUDA/Half.h +++ b/Eigen/src/Core/arch/CUDA/Half.h @@ -53,7 +53,7 @@ namespace half_impl { // Make our own __half definition that is similar to CUDA's. struct __half { - EIGEN_DEVICE_FUNC __half() {} + EIGEN_DEVICE_FUNC __half() : x(0) {} explicit EIGEN_DEVICE_FUNC __half(unsigned short raw) : x(raw) {} unsigned short x; }; From 3440b46e2fead97d0ae4fc2f9c499727278a739f Mon Sep 17 00:00:00 2001 From: Sergiu Deitsch Date: Wed, 30 Nov 2016 15:41:38 +0100 Subject: [PATCH 03/13] doc: mention the NO_MODULE option and target availability (grafted from 65f09be8d2aaeda054cce574ea14a74b00507011 ) --- doc/TopicCMakeGuide.dox | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/TopicCMakeGuide.dox b/doc/TopicCMakeGuide.dox index 5362413d6..a540db68e 100644 --- a/doc/TopicCMakeGuide.dox +++ b/doc/TopicCMakeGuide.dox @@ -16,7 +16,7 @@ using the `find_package` CMake command and used by calling cmake_minimum_required (VERSION 3.0) project (myproject) -find_package (Eigen3 3.3 REQUIRED) +find_package (Eigen3 3.3 REQUIRED NO_MODULE) add_executable (example example.cpp) target_link_libraries (example Eigen3::Eigen) @@ -32,6 +32,15 @@ which requires at least version 3.3 of %Eigen. Here, `path-to-example-directory` is the path to the directory that contains both `CMakeLists.txt` and `example.cpp`. +If the `REQUIRED` option is omitted when locating %Eigen using +`find_package`, one can check whether the package was found as follows: +\code{.cmake} +find_package (Eigen3 3.3 NO_MODULE) + +if (TARGET Eigen3::Eigen) + # Use the imported target +endif (TARGET Eigen3::Eigen) +\endcode */ From 5e3c5c42f6471ba0b1cd1de78e3139d2e0a4c2bb Mon Sep 17 00:00:00 2001 From: Sergiu Deitsch Date: Wed, 30 Nov 2016 15:46:46 +0100 Subject: [PATCH 04/13] cmake: remove architecture dependency from Eigen3ConfigVersion.cmake Also, install Eigen3*.cmake under $prefix/share/eigen3/cmake by default. (grafted from 86ab00cdcfc81ef7ebc92ddc3314d7df67c65354 ) --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c1520d7d..a7d3446d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -380,7 +380,7 @@ else() ) endif() set(CMAKEPACKAGE_INSTALL_DIR - "${CMAKE_INSTALL_LIBDIR}/cmake/eigen3" + "${CMAKE_INSTALL_DATADIR}/eigen3/cmake" CACHE PATH "The directory relative to CMAKE_PREFIX_PATH where Eigen3Config.cmake is installed" ) set(PKGCONFIG_INSTALL_DIR @@ -534,8 +534,15 @@ if (NOT CMAKE_VERSION VERSION_LESS 3.0) INSTALL_DESTINATION ${CMAKEPACKAGE_INSTALL_DIR} NO_CHECK_REQUIRED_COMPONENTS_MACRO # Eigen does not provide components ) + # Remove CMAKE_SIZEOF_VOID_P from Eigen3ConfigVersion.cmake since Eigen does + # not depend on architecture specific settings or libraries. More + # specifically, an Eigen3Config.cmake generated from a 64 bit target can be + # used for 32 bit targets as well (and vice versa). + set (_Eigen3_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) + unset (CMAKE_SIZEOF_VOID_P) write_basic_package_version_file (Eigen3ConfigVersion.cmake VERSION ${EIGEN_VERSION_NUMBER} COMPATIBILITY SameMajorVersion) + set (CMAKE_SIZEOF_VOID_P ${_Eigen3_CMAKE_SIZEOF_VOID_P}) # The Eigen target will be located in the Eigen3 namespace. Other CMake # targets can refer to it using Eigen3::Eigen. From 181138a1cb09e8eac68be36fd6139098466dc48c Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 1 Dec 2016 17:06:20 +0100 Subject: [PATCH 05/13] fix member order --- Eigen/src/SparseCore/SparseCompressedBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Eigen/src/SparseCore/SparseCompressedBase.h b/Eigen/src/SparseCore/SparseCompressedBase.h index febd9039e..710eb0156 100644 --- a/Eigen/src/SparseCore/SparseCompressedBase.h +++ b/Eigen/src/SparseCore/SparseCompressedBase.h @@ -261,8 +261,8 @@ class SparseCompressedBase::ReverseInnerIterator const StorageIndex* m_indices; typedef internal::variable_if_dynamic OuterType; const OuterType m_outer; - Index m_id; Index m_start; + Index m_id; }; namespace internal { From 27873008d431a307bed9c200a12622a361af4d14 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 1 Dec 2016 21:55:10 +0100 Subject: [PATCH 06/13] Clean up SparseCore module regarding ReverseInnerIterator --- Eigen/src/SparseCore/SparseBlock.h | 3 -- Eigen/src/SparseCore/SparseCompressedBase.h | 1 - Eigen/src/SparseCore/SparseCwiseBinaryOp.h | 6 --- Eigen/src/SparseCore/SparseCwiseUnaryOp.h | 54 --------------------- Eigen/src/SparseCore/SparseTranspose.h | 12 ----- 5 files changed, 76 deletions(-) diff --git a/Eigen/src/SparseCore/SparseBlock.h b/Eigen/src/SparseCore/SparseBlock.h index acaf933f4..cb8d9d2e2 100644 --- a/Eigen/src/SparseCore/SparseBlock.h +++ b/Eigen/src/SparseCore/SparseBlock.h @@ -432,7 +432,6 @@ public: protected: // friend class internal::GenericSparseBlockInnerIteratorImpl; - friend class ReverseInnerIterator; friend struct internal::unary_evaluator, internal::IteratorBased, Scalar >; Index nonZeros() const { return Dynamic; } @@ -468,8 +467,6 @@ struct unary_evaluator, IteratorBa typedef typename XprType::StorageIndex StorageIndex; typedef typename XprType::Scalar Scalar; - class ReverseInnerIterator; - enum { IsRowMajor = XprType::IsRowMajor, diff --git a/Eigen/src/SparseCore/SparseCompressedBase.h b/Eigen/src/SparseCore/SparseCompressedBase.h index 710eb0156..e0850795c 100644 --- a/Eigen/src/SparseCore/SparseCompressedBase.h +++ b/Eigen/src/SparseCore/SparseCompressedBase.h @@ -273,7 +273,6 @@ struct evaluator > { typedef typename Derived::Scalar Scalar; typedef typename Derived::InnerIterator InnerIterator; - typedef typename Derived::ReverseInnerIterator ReverseInnerIterator; enum { CoeffReadCost = NumTraits::ReadCost, diff --git a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h index 4ba4d631d..0a9bdeac2 100644 --- a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +++ b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h @@ -68,7 +68,6 @@ protected: typedef typename XprType::StorageIndex StorageIndex; public: - class ReverseInnerIterator; class InnerIterator { public: @@ -161,7 +160,6 @@ protected: typedef typename XprType::StorageIndex StorageIndex; public: - class ReverseInnerIterator; class InnerIterator { enum { IsRowMajor = (int(Rhs::Flags)&RowMajorBit)==RowMajorBit }; @@ -249,7 +247,6 @@ protected: typedef typename XprType::StorageIndex StorageIndex; public: - class ReverseInnerIterator; class InnerIterator { enum { IsRowMajor = (int(Lhs::Flags)&RowMajorBit)==RowMajorBit }; @@ -402,7 +399,6 @@ protected: typedef typename traits::Scalar Scalar; public: - class ReverseInnerIterator; class InnerIterator { public: @@ -487,7 +483,6 @@ protected: typedef typename traits::Scalar Scalar; public: - class ReverseInnerIterator; class InnerIterator { enum { IsRowMajor = (int(RhsArg::Flags)&RowMajorBit)==RowMajorBit }; @@ -561,7 +556,6 @@ protected: typedef typename traits::Scalar Scalar; public: - class ReverseInnerIterator; class InnerIterator { enum { IsRowMajor = (int(LhsArg::Flags)&RowMajorBit)==RowMajorBit }; diff --git a/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/Eigen/src/SparseCore/SparseCwiseUnaryOp.h index 9143a4c82..28f221437 100644 --- a/Eigen/src/SparseCore/SparseCwiseUnaryOp.h +++ b/Eigen/src/SparseCore/SparseCwiseUnaryOp.h @@ -22,7 +22,6 @@ struct unary_evaluator, IteratorBased> typedef CwiseUnaryOp XprType; class InnerIterator; - class ReverseInnerIterator; enum { CoeffReadCost = evaluator::CoeffReadCost + functor_traits::Cost, @@ -41,7 +40,6 @@ struct unary_evaluator, IteratorBased> protected: typedef typename evaluator::InnerIterator EvalIterator; -// typedef typename evaluator::ReverseInnerIterator EvalReverseIterator; const UnaryOp m_functor; evaluator m_argImpl; @@ -70,33 +68,6 @@ class unary_evaluator, IteratorBased>::InnerIterat Scalar& valueRef(); }; -// template -// class unary_evaluator, IteratorBased>::ReverseInnerIterator -// : public unary_evaluator, IteratorBased>::EvalReverseIterator -// { -// typedef typename XprType::Scalar Scalar; -// typedef typename unary_evaluator, IteratorBased>::EvalReverseIterator Base; -// public: -// -// EIGEN_STRONG_INLINE ReverseInnerIterator(const XprType& unaryOp, typename XprType::Index outer) -// : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) -// {} -// -// EIGEN_STRONG_INLINE ReverseInnerIterator& operator--() -// { Base::operator--(); return *this; } -// -// EIGEN_STRONG_INLINE Scalar value() const { return m_functor(Base::value()); } -// -// protected: -// const UnaryOp m_functor; -// private: -// Scalar& valueRef(); -// }; - - - - - template struct unary_evaluator, IteratorBased> : public evaluator_base > @@ -105,7 +76,6 @@ struct unary_evaluator, IteratorBased> typedef CwiseUnaryView XprType; class InnerIterator; - class ReverseInnerIterator; enum { CoeffReadCost = evaluator::CoeffReadCost + functor_traits::Cost, @@ -120,7 +90,6 @@ struct unary_evaluator, IteratorBased> protected: typedef typename evaluator::InnerIterator EvalIterator; -// typedef typename evaluator::ReverseInnerIterator EvalReverseIterator; const ViewOp m_functor; evaluator m_argImpl; @@ -148,29 +117,6 @@ class unary_evaluator, IteratorBased>::InnerItera const ViewOp m_functor; }; -// template -// class unary_evaluator, IteratorBased>::ReverseInnerIterator -// : public unary_evaluator, IteratorBased>::EvalReverseIterator -// { -// typedef typename XprType::Scalar Scalar; -// typedef typename unary_evaluator, IteratorBased>::EvalReverseIterator Base; -// public: -// -// EIGEN_STRONG_INLINE ReverseInnerIterator(const XprType& unaryOp, typename XprType::Index outer) -// : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) -// {} -// -// EIGEN_STRONG_INLINE ReverseInnerIterator& operator--() -// { Base::operator--(); return *this; } -// -// EIGEN_STRONG_INLINE Scalar value() const { return m_functor(Base::value()); } -// EIGEN_STRONG_INLINE Scalar& valueRef() { return m_functor(Base::valueRef()); } -// -// protected: -// const ViewOp m_functor; -// }; - - } // end namespace internal template diff --git a/Eigen/src/SparseCore/SparseTranspose.h b/Eigen/src/SparseCore/SparseTranspose.h index b6f180a41..3757d4c6b 100644 --- a/Eigen/src/SparseCore/SparseTranspose.h +++ b/Eigen/src/SparseCore/SparseTranspose.h @@ -56,7 +56,6 @@ struct unary_evaluator, IteratorBased> : public evaluator_base > { typedef typename evaluator::InnerIterator EvalIterator; - typedef typename evaluator::ReverseInnerIterator EvalReverseIterator; public: typedef Transpose XprType; @@ -75,17 +74,6 @@ struct unary_evaluator, IteratorBased> Index col() const { return EvalIterator::row(); } }; - class ReverseInnerIterator : public EvalReverseIterator - { - public: - EIGEN_STRONG_INLINE ReverseInnerIterator(const unary_evaluator& unaryOp, Index outer) - : EvalReverseIterator(unaryOp.m_argImpl,outer) - {} - - Index row() const { return EvalReverseIterator::col(); } - Index col() const { return EvalReverseIterator::row(); } - }; - enum { CoeffReadCost = evaluator::CoeffReadCost, Flags = XprType::Flags From aeba0d865543634c9b3fe176cfe055268b305da5 Mon Sep 17 00:00:00 2001 From: Angelos Mantzaflaris Date: Thu, 1 Dec 2016 21:23:43 +0100 Subject: [PATCH 07/13] fix two warnings(unused typedef, unused variable) and a typo (grafted from a9aa3bcf50d55b63c8adb493a06c903ec34251c6 ) --- Eigen/src/Core/Dot.h | 4 +++- Eigen/src/Core/PlainObjectBase.h | 1 + Eigen/src/Core/util/Memory.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Eigen/src/Core/Dot.h b/Eigen/src/Core/Dot.h index 1d7f2262e..f4fb4db7e 100644 --- a/Eigen/src/Core/Dot.h +++ b/Eigen/src/Core/Dot.h @@ -70,9 +70,11 @@ MatrixBase::dot(const MatrixBase& other) const EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived) +#if !(defined(EIGEN_NO_STATIC_ASSERT) && defined(EIGEN_NO_DEBUG)) typedef internal::scalar_conj_product_op func; EIGEN_CHECK_BINARY_COMPATIBILIY(func,Scalar,typename OtherDerived::Scalar); - +#endif + eigen_assert(size() == other.size()); return internal::dot_nocheck::run(*this, other); diff --git a/Eigen/src/Core/PlainObjectBase.h b/Eigen/src/Core/PlainObjectBase.h index 2dcd929e6..0c04f8250 100644 --- a/Eigen/src/Core/PlainObjectBase.h +++ b/Eigen/src/Core/PlainObjectBase.h @@ -763,6 +763,7 @@ class PlainObjectBase : public internal::dense_xpr_base::type { // NOTE MSVC 2008 complains if we directly put bool(NumTraits::IsInteger) as the EIGEN_STATIC_ASSERT argument. const bool is_integer = NumTraits::IsInteger; + EIGEN_UNUSED_VARIABLE(is_integer); EIGEN_STATIC_ASSERT(is_integer, FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) resize(size); diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 0439655ca..741f35a0d 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -523,7 +523,7 @@ template struct smart_memmove_helper { template struct smart_memmove_helper { static inline void run(const T* start, const T* end, T* target) { - if (uintptr_t(target) < uintptr_t(start)) + if (IntPtr(target) < IntPtr(start)) { std::copy(start, end, target); } From 8c24723a09cd6b3852d2a5a0748f6a250d1d40f5 Mon Sep 17 00:00:00 2001 From: Angelos Mantzaflaris Date: Thu, 1 Dec 2016 21:25:58 +0100 Subject: [PATCH 08/13] typo UIntPtr (grafted from b6f04a2dd4d68fe1858524709813a5df5b9a085b ) --- Eigen/src/Core/util/Memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 741f35a0d..67053db62 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -523,7 +523,7 @@ template struct smart_memmove_helper { template struct smart_memmove_helper { static inline void run(const T* start, const T* end, T* target) { - if (IntPtr(target) < IntPtr(start)) + if (UIntPtr(target) < UIntPtr(start)) { std::copy(start, end, target); } From 22f7d398e22328ae96f5095e943ab1d46d87efc4 Mon Sep 17 00:00:00 2001 From: Christoph Hertzberg Date: Fri, 2 Dec 2016 11:22:05 +0100 Subject: [PATCH 09/13] bug #1355: Fixed wrong line-endings on two files --- Eigen/src/SparseCore/SparseBlock.h | 1204 ++++++++++++++-------------- README.md | 6 +- 2 files changed, 605 insertions(+), 605 deletions(-) diff --git a/Eigen/src/SparseCore/SparseBlock.h b/Eigen/src/SparseCore/SparseBlock.h index cb8d9d2e2..c3ea7e0e2 100644 --- a/Eigen/src/SparseCore/SparseBlock.h +++ b/Eigen/src/SparseCore/SparseBlock.h @@ -1,602 +1,602 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2014 Gael Guennebaud -// -// 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_SPARSE_BLOCK_H -#define EIGEN_SPARSE_BLOCK_H - -namespace Eigen { - -// Subset of columns or rows -template -class BlockImpl - : public SparseMatrixBase > -{ - typedef typename internal::remove_all::type _MatrixTypeNested; - typedef Block BlockType; -public: - enum { IsRowMajor = internal::traits::IsRowMajor }; -protected: - enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; - typedef SparseMatrixBase Base; - using Base::convert_index; -public: - EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) - - inline BlockImpl(XprType& xpr, Index i) - : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize) - {} - - inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) - : m_matrix(xpr), m_outerStart(convert_index(IsRowMajor ? startRow : startCol)), m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols)) - {} - - EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } - EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } - - Index nonZeros() const - { - typedef internal::evaluator EvaluatorType; - EvaluatorType matEval(m_matrix); - Index nnz = 0; - Index end = m_outerStart + m_outerSize.value(); - for(Index j=m_outerStart; j::non_const_type m_matrix; - Index m_outerStart; - const internal::variable_if_dynamic m_outerSize; - - protected: - // Disable assignment with clear error message. - // Note that simply removing operator= yields compilation errors with ICC+MSVC - template - BlockImpl& operator=(const T&) - { - EIGEN_STATIC_ASSERT(sizeof(T)==0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY); - return *this; - } -}; - - -/*************************************************************************** -* specialization for SparseMatrix -***************************************************************************/ - -namespace internal { - -template -class sparse_matrix_block_impl - : public SparseCompressedBase > -{ - typedef typename internal::remove_all::type _MatrixTypeNested; - typedef Block BlockType; - typedef SparseCompressedBase > Base; - using Base::convert_index; -public: - enum { IsRowMajor = internal::traits::IsRowMajor }; - EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) -protected: - typedef typename Base::IndexVector IndexVector; - enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; -public: - - inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index i) - : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize) - {} - - inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) - : m_matrix(xpr), m_outerStart(convert_index(IsRowMajor ? startRow : startCol)), m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols)) - {} - - template - inline BlockType& operator=(const SparseMatrixBase& other) - { - typedef typename internal::remove_all::type _NestedMatrixType; - _NestedMatrixType& matrix = m_matrix; - // This assignment is slow if this vector set is not empty - // and/or it is not at the end of the nonzeros of the underlying matrix. - - // 1 - eval to a temporary to avoid transposition and/or aliasing issues - Ref > tmp(other.derived()); - eigen_internal_assert(tmp.outerSize()==m_outerSize.value()); - - // 2 - let's check whether there is enough allocated memory - Index nnz = tmp.nonZeros(); - Index start = m_outerStart==0 ? 0 : m_matrix.outerIndexPtr()[m_outerStart]; // starting position of the current block - Index end = m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]; // ending position of the current block - Index block_size = end - start; // available room in the current block - Index tail_size = m_matrix.outerIndexPtr()[m_matrix.outerSize()] - end; - - Index free_size = m_matrix.isCompressed() - ? Index(matrix.data().allocatedSize()) + block_size - : block_size; - - Index tmp_start = tmp.outerIndexPtr()[0]; - - bool update_trailing_pointers = false; - if(nnz>free_size) - { - // realloc manually to reduce copies - typename SparseMatrixType::Storage newdata(m_matrix.data().allocatedSize() - block_size + nnz); - - internal::smart_copy(m_matrix.valuePtr(), m_matrix.valuePtr() + start, newdata.valuePtr()); - internal::smart_copy(m_matrix.innerIndexPtr(), m_matrix.innerIndexPtr() + start, newdata.indexPtr()); - - internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, newdata.valuePtr() + start); - internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz, newdata.indexPtr() + start); - - internal::smart_copy(matrix.valuePtr()+end, matrix.valuePtr()+end + tail_size, newdata.valuePtr()+start+nnz); - internal::smart_copy(matrix.innerIndexPtr()+end, matrix.innerIndexPtr()+end + tail_size, newdata.indexPtr()+start+nnz); - - newdata.resize(m_matrix.outerIndexPtr()[m_matrix.outerSize()] - block_size + nnz); - - matrix.data().swap(newdata); - - update_trailing_pointers = true; - } - else - { - if(m_matrix.isCompressed()) - { - // no need to realloc, simply copy the tail at its respective position and insert tmp - matrix.data().resize(start + nnz + tail_size); - - internal::smart_memmove(matrix.valuePtr()+end, matrix.valuePtr() + end+tail_size, matrix.valuePtr() + start+nnz); - internal::smart_memmove(matrix.innerIndexPtr()+end, matrix.innerIndexPtr() + end+tail_size, matrix.innerIndexPtr() + start+nnz); - - update_trailing_pointers = true; - } - - internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, matrix.valuePtr() + start); - internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz, matrix.innerIndexPtr() + start); - } - - // update outer index pointers and innerNonZeros - if(IsVectorAtCompileTime) - { - if(!m_matrix.isCompressed()) - matrix.innerNonZeroPtr()[m_outerStart] = StorageIndex(nnz); - matrix.outerIndexPtr()[m_outerStart] = StorageIndex(start); - } - else - { - StorageIndex p = StorageIndex(start); - for(Index k=0; k(tmp.innerVector(k).nonZeros()); - if(!m_matrix.isCompressed()) - matrix.innerNonZeroPtr()[m_outerStart+k] = nnz_k; - matrix.outerIndexPtr()[m_outerStart+k] = p; - p += nnz_k; - } - } - - if(update_trailing_pointers) - { - StorageIndex offset = internal::convert_index(nnz - block_size); - for(Index k = m_outerStart + m_outerSize.value(); k<=matrix.outerSize(); ++k) - { - matrix.outerIndexPtr()[k] += offset; - } - } - - return derived(); - } - - inline BlockType& operator=(const BlockType& other) - { - return operator=(other); - } - - inline const Scalar* valuePtr() const - { return m_matrix.valuePtr(); } - inline Scalar* valuePtr() - { return m_matrix.valuePtr(); } - - inline const StorageIndex* innerIndexPtr() const - { return m_matrix.innerIndexPtr(); } - inline StorageIndex* innerIndexPtr() - { return m_matrix.innerIndexPtr(); } - - inline const StorageIndex* outerIndexPtr() const - { return m_matrix.outerIndexPtr() + m_outerStart; } - inline StorageIndex* outerIndexPtr() - { return m_matrix.outerIndexPtr() + m_outerStart; } - - inline const StorageIndex* innerNonZeroPtr() const - { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr()+m_outerStart); } - inline StorageIndex* innerNonZeroPtr() - { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr()+m_outerStart); } - - bool isCompressed() const { return m_matrix.innerNonZeroPtr()==0; } - - inline Scalar& coeffRef(Index row, Index col) - { - return m_matrix.coeffRef(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart)); - } - - inline const Scalar coeff(Index row, Index col) const - { - return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart)); - } - - inline const Scalar coeff(Index index) const - { - return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart); - } - - const Scalar& lastCoeff() const - { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(sparse_matrix_block_impl); - eigen_assert(Base::nonZeros()>0); - if(m_matrix.isCompressed()) - return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1]; - else - return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1]; - } - - EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } - EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } - - inline const SparseMatrixType& nestedExpression() const { return m_matrix; } - inline SparseMatrixType& nestedExpression() { return m_matrix; } - Index startRow() const { return IsRowMajor ? m_outerStart : 0; } - Index startCol() const { return IsRowMajor ? 0 : m_outerStart; } - Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } - Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } - - protected: - - typename internal::ref_selector::non_const_type m_matrix; - Index m_outerStart; - const internal::variable_if_dynamic m_outerSize; - -}; - -} // namespace internal - -template -class BlockImpl,BlockRows,BlockCols,true,Sparse> - : public internal::sparse_matrix_block_impl,BlockRows,BlockCols> -{ -public: - typedef _StorageIndex StorageIndex; - typedef SparseMatrix<_Scalar, _Options, _StorageIndex> SparseMatrixType; - typedef internal::sparse_matrix_block_impl Base; - inline BlockImpl(SparseMatrixType& xpr, Index i) - : Base(xpr, i) - {} - - inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) - : Base(xpr, startRow, startCol, blockRows, blockCols) - {} - - using Base::operator=; -}; - -template -class BlockImpl,BlockRows,BlockCols,true,Sparse> - : public internal::sparse_matrix_block_impl,BlockRows,BlockCols> -{ -public: - typedef _StorageIndex StorageIndex; - typedef const SparseMatrix<_Scalar, _Options, _StorageIndex> SparseMatrixType; - typedef internal::sparse_matrix_block_impl Base; - inline BlockImpl(SparseMatrixType& xpr, Index i) - : Base(xpr, i) - {} - - inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) - : Base(xpr, startRow, startCol, blockRows, blockCols) - {} - - using Base::operator=; -private: - template BlockImpl(const SparseMatrixBase& xpr, Index i); - template BlockImpl(const SparseMatrixBase& xpr); -}; - -//---------- - -/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this - * is col-major (resp. row-major). - */ -template -typename SparseMatrixBase::InnerVectorReturnType SparseMatrixBase::innerVector(Index outer) -{ return InnerVectorReturnType(derived(), outer); } - -/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this - * is col-major (resp. row-major). Read-only. - */ -template -const typename SparseMatrixBase::ConstInnerVectorReturnType SparseMatrixBase::innerVector(Index outer) const -{ return ConstInnerVectorReturnType(derived(), outer); } - -/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this - * is col-major (resp. row-major). - */ -template -typename SparseMatrixBase::InnerVectorsReturnType -SparseMatrixBase::innerVectors(Index outerStart, Index outerSize) -{ - return Block(derived(), - IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart, - IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); - -} - -/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this - * is col-major (resp. row-major). Read-only. - */ -template -const typename SparseMatrixBase::ConstInnerVectorsReturnType -SparseMatrixBase::innerVectors(Index outerStart, Index outerSize) const -{ - return Block(derived(), - IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart, - IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); - -} - -/** Generic implementation of sparse Block expression. - * Real-only. - */ -template -class BlockImpl - : public SparseMatrixBase >, internal::no_assignment_operator -{ - typedef Block BlockType; - typedef SparseMatrixBase Base; - using Base::convert_index; -public: - enum { IsRowMajor = internal::traits::IsRowMajor }; - EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) - - typedef typename internal::remove_all::type _MatrixTypeNested; - - /** Column or Row constructor - */ - inline BlockImpl(XprType& xpr, Index i) - : m_matrix(xpr), - m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? convert_index(i) : 0), - m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? convert_index(i) : 0), - m_blockRows(BlockRows==1 ? 1 : xpr.rows()), - m_blockCols(BlockCols==1 ? 1 : xpr.cols()) - {} - - /** Dynamic-size constructor - */ - inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) - : m_matrix(xpr), m_startRow(convert_index(startRow)), m_startCol(convert_index(startCol)), m_blockRows(convert_index(blockRows)), m_blockCols(convert_index(blockCols)) - {} - - inline Index rows() const { return m_blockRows.value(); } - inline Index cols() const { return m_blockCols.value(); } - - inline Scalar& coeffRef(Index row, Index col) - { - return m_matrix.coeffRef(row + m_startRow.value(), col + m_startCol.value()); - } - - inline const Scalar coeff(Index row, Index col) const - { - return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value()); - } - - inline Scalar& coeffRef(Index index) - { - return m_matrix.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), - m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); - } - - inline const Scalar coeff(Index index) const - { - return m_matrix.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), - m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); - } - - inline const XprType& nestedExpression() const { return m_matrix; } - inline XprType& nestedExpression() { return m_matrix; } - Index startRow() const { return m_startRow.value(); } - Index startCol() const { return m_startCol.value(); } - Index blockRows() const { return m_blockRows.value(); } - Index blockCols() const { return m_blockCols.value(); } - - protected: -// friend class internal::GenericSparseBlockInnerIteratorImpl; - friend struct internal::unary_evaluator, internal::IteratorBased, Scalar >; - - Index nonZeros() const { return Dynamic; } - - typename internal::ref_selector::non_const_type m_matrix; - const internal::variable_if_dynamic m_startRow; - const internal::variable_if_dynamic m_startCol; - const internal::variable_if_dynamic m_blockRows; - const internal::variable_if_dynamic m_blockCols; - - protected: - // Disable assignment with clear error message. - // Note that simply removing operator= yields compilation errors with ICC+MSVC - template - BlockImpl& operator=(const T&) - { - EIGEN_STATIC_ASSERT(sizeof(T)==0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY); - return *this; - } - -}; - -namespace internal { - -template -struct unary_evaluator, IteratorBased > - : public evaluator_base > -{ - class InnerVectorInnerIterator; - class OuterVectorInnerIterator; - public: - typedef Block XprType; - typedef typename XprType::StorageIndex StorageIndex; - typedef typename XprType::Scalar Scalar; - - enum { - IsRowMajor = XprType::IsRowMajor, - - OuterVector = (BlockCols==1 && ArgType::IsRowMajor) - | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&". - // revert to || as soon as not needed anymore. - (BlockRows==1 && !ArgType::IsRowMajor), - - CoeffReadCost = evaluator::CoeffReadCost, - Flags = XprType::Flags - }; - - typedef typename internal::conditional::type InnerIterator; - - explicit unary_evaluator(const XprType& op) - : m_argImpl(op.nestedExpression()), m_block(op) - {} - - inline Index nonZerosEstimate() const { - Index nnz = m_block.nonZeros(); - if(nnz<0) - return m_argImpl.nonZerosEstimate() * m_block.size() / m_block.nestedExpression().size(); - return nnz; - } - - protected: - typedef typename evaluator::InnerIterator EvalIterator; - - evaluator m_argImpl; - const XprType &m_block; -}; - -template -class unary_evaluator, IteratorBased>::InnerVectorInnerIterator - : public EvalIterator -{ - enum { IsRowMajor = unary_evaluator::IsRowMajor }; - const XprType& m_block; - Index m_end; -public: - - EIGEN_STRONG_INLINE InnerVectorInnerIterator(const unary_evaluator& aEval, Index outer) - : EvalIterator(aEval.m_argImpl, outer + (IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol())), - m_block(aEval.m_block), - m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()) - { - while( (EvalIterator::operator bool()) && (EvalIterator::index() < (IsRowMajor ? m_block.startCol() : m_block.startRow())) ) - EvalIterator::operator++(); - } - - inline StorageIndex index() const { return EvalIterator::index() - convert_index(IsRowMajor ? m_block.startCol() : m_block.startRow()); } - inline Index outer() const { return EvalIterator::outer() - (IsRowMajor ? m_block.startRow() : m_block.startCol()); } - inline Index row() const { return EvalIterator::row() - m_block.startRow(); } - inline Index col() const { return EvalIterator::col() - m_block.startCol(); } - - inline operator bool() const { return EvalIterator::operator bool() && EvalIterator::index() < m_end; } -}; - -template -class unary_evaluator, IteratorBased>::OuterVectorInnerIterator -{ - enum { IsRowMajor = unary_evaluator::IsRowMajor }; - const unary_evaluator& m_eval; - Index m_outerPos; - Index m_innerIndex; - Scalar m_value; - Index m_end; -public: - - EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer) - : m_eval(aEval), - m_outerPos( (IsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow()) - 1), // -1 so that operator++ finds the first non-zero entry - m_innerIndex(IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol()), - m_value(0), - m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()) - { - EIGEN_UNUSED_VARIABLE(outer); - eigen_assert(outer==0); - - ++(*this); - } - - inline StorageIndex index() const { return convert_index(m_outerPos - (IsRowMajor ? m_eval.m_block.startCol() : m_eval.m_block.startRow())); } - inline Index outer() const { return 0; } - inline Index row() const { return IsRowMajor ? 0 : index(); } - inline Index col() const { return IsRowMajor ? index() : 0; } - - inline Scalar value() const { return m_value; } - - inline OuterVectorInnerIterator& operator++() - { - // search next non-zero entry - while(++m_outerPos -struct unary_evaluator,BlockRows,BlockCols,true>, IteratorBased> - : evaluator,BlockRows,BlockCols,true> > > -{ - typedef Block,BlockRows,BlockCols,true> XprType; - typedef evaluator > Base; - explicit unary_evaluator(const XprType &xpr) : Base(xpr) {} -}; - -template -struct unary_evaluator,BlockRows,BlockCols,true>, IteratorBased> - : evaluator,BlockRows,BlockCols,true> > > -{ - typedef Block,BlockRows,BlockCols,true> XprType; - typedef evaluator > Base; - explicit unary_evaluator(const XprType &xpr) : Base(xpr) {} -}; - -} // end namespace internal - - -} // end namespace Eigen - -#endif // EIGEN_SPARSE_BLOCK_H +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2014 Gael Guennebaud +// +// 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_SPARSE_BLOCK_H +#define EIGEN_SPARSE_BLOCK_H + +namespace Eigen { + +// Subset of columns or rows +template +class BlockImpl + : public SparseMatrixBase > +{ + typedef typename internal::remove_all::type _MatrixTypeNested; + typedef Block BlockType; +public: + enum { IsRowMajor = internal::traits::IsRowMajor }; +protected: + enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; + typedef SparseMatrixBase Base; + using Base::convert_index; +public: + EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) + + inline BlockImpl(XprType& xpr, Index i) + : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize) + {} + + inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) + : m_matrix(xpr), m_outerStart(convert_index(IsRowMajor ? startRow : startCol)), m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols)) + {} + + EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } + EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } + + Index nonZeros() const + { + typedef internal::evaluator EvaluatorType; + EvaluatorType matEval(m_matrix); + Index nnz = 0; + Index end = m_outerStart + m_outerSize.value(); + for(Index j=m_outerStart; j::non_const_type m_matrix; + Index m_outerStart; + const internal::variable_if_dynamic m_outerSize; + + protected: + // Disable assignment with clear error message. + // Note that simply removing operator= yields compilation errors with ICC+MSVC + template + BlockImpl& operator=(const T&) + { + EIGEN_STATIC_ASSERT(sizeof(T)==0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY); + return *this; + } +}; + + +/*************************************************************************** +* specialization for SparseMatrix +***************************************************************************/ + +namespace internal { + +template +class sparse_matrix_block_impl + : public SparseCompressedBase > +{ + typedef typename internal::remove_all::type _MatrixTypeNested; + typedef Block BlockType; + typedef SparseCompressedBase > Base; + using Base::convert_index; +public: + enum { IsRowMajor = internal::traits::IsRowMajor }; + EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) +protected: + typedef typename Base::IndexVector IndexVector; + enum { OuterSize = IsRowMajor ? BlockRows : BlockCols }; +public: + + inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index i) + : m_matrix(xpr), m_outerStart(convert_index(i)), m_outerSize(OuterSize) + {} + + inline sparse_matrix_block_impl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) + : m_matrix(xpr), m_outerStart(convert_index(IsRowMajor ? startRow : startCol)), m_outerSize(convert_index(IsRowMajor ? blockRows : blockCols)) + {} + + template + inline BlockType& operator=(const SparseMatrixBase& other) + { + typedef typename internal::remove_all::type _NestedMatrixType; + _NestedMatrixType& matrix = m_matrix; + // This assignment is slow if this vector set is not empty + // and/or it is not at the end of the nonzeros of the underlying matrix. + + // 1 - eval to a temporary to avoid transposition and/or aliasing issues + Ref > tmp(other.derived()); + eigen_internal_assert(tmp.outerSize()==m_outerSize.value()); + + // 2 - let's check whether there is enough allocated memory + Index nnz = tmp.nonZeros(); + Index start = m_outerStart==0 ? 0 : m_matrix.outerIndexPtr()[m_outerStart]; // starting position of the current block + Index end = m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]; // ending position of the current block + Index block_size = end - start; // available room in the current block + Index tail_size = m_matrix.outerIndexPtr()[m_matrix.outerSize()] - end; + + Index free_size = m_matrix.isCompressed() + ? Index(matrix.data().allocatedSize()) + block_size + : block_size; + + Index tmp_start = tmp.outerIndexPtr()[0]; + + bool update_trailing_pointers = false; + if(nnz>free_size) + { + // realloc manually to reduce copies + typename SparseMatrixType::Storage newdata(m_matrix.data().allocatedSize() - block_size + nnz); + + internal::smart_copy(m_matrix.valuePtr(), m_matrix.valuePtr() + start, newdata.valuePtr()); + internal::smart_copy(m_matrix.innerIndexPtr(), m_matrix.innerIndexPtr() + start, newdata.indexPtr()); + + internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, newdata.valuePtr() + start); + internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz, newdata.indexPtr() + start); + + internal::smart_copy(matrix.valuePtr()+end, matrix.valuePtr()+end + tail_size, newdata.valuePtr()+start+nnz); + internal::smart_copy(matrix.innerIndexPtr()+end, matrix.innerIndexPtr()+end + tail_size, newdata.indexPtr()+start+nnz); + + newdata.resize(m_matrix.outerIndexPtr()[m_matrix.outerSize()] - block_size + nnz); + + matrix.data().swap(newdata); + + update_trailing_pointers = true; + } + else + { + if(m_matrix.isCompressed()) + { + // no need to realloc, simply copy the tail at its respective position and insert tmp + matrix.data().resize(start + nnz + tail_size); + + internal::smart_memmove(matrix.valuePtr()+end, matrix.valuePtr() + end+tail_size, matrix.valuePtr() + start+nnz); + internal::smart_memmove(matrix.innerIndexPtr()+end, matrix.innerIndexPtr() + end+tail_size, matrix.innerIndexPtr() + start+nnz); + + update_trailing_pointers = true; + } + + internal::smart_copy(tmp.valuePtr() + tmp_start, tmp.valuePtr() + tmp_start + nnz, matrix.valuePtr() + start); + internal::smart_copy(tmp.innerIndexPtr() + tmp_start, tmp.innerIndexPtr() + tmp_start + nnz, matrix.innerIndexPtr() + start); + } + + // update outer index pointers and innerNonZeros + if(IsVectorAtCompileTime) + { + if(!m_matrix.isCompressed()) + matrix.innerNonZeroPtr()[m_outerStart] = StorageIndex(nnz); + matrix.outerIndexPtr()[m_outerStart] = StorageIndex(start); + } + else + { + StorageIndex p = StorageIndex(start); + for(Index k=0; k(tmp.innerVector(k).nonZeros()); + if(!m_matrix.isCompressed()) + matrix.innerNonZeroPtr()[m_outerStart+k] = nnz_k; + matrix.outerIndexPtr()[m_outerStart+k] = p; + p += nnz_k; + } + } + + if(update_trailing_pointers) + { + StorageIndex offset = internal::convert_index(nnz - block_size); + for(Index k = m_outerStart + m_outerSize.value(); k<=matrix.outerSize(); ++k) + { + matrix.outerIndexPtr()[k] += offset; + } + } + + return derived(); + } + + inline BlockType& operator=(const BlockType& other) + { + return operator=(other); + } + + inline const Scalar* valuePtr() const + { return m_matrix.valuePtr(); } + inline Scalar* valuePtr() + { return m_matrix.valuePtr(); } + + inline const StorageIndex* innerIndexPtr() const + { return m_matrix.innerIndexPtr(); } + inline StorageIndex* innerIndexPtr() + { return m_matrix.innerIndexPtr(); } + + inline const StorageIndex* outerIndexPtr() const + { return m_matrix.outerIndexPtr() + m_outerStart; } + inline StorageIndex* outerIndexPtr() + { return m_matrix.outerIndexPtr() + m_outerStart; } + + inline const StorageIndex* innerNonZeroPtr() const + { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr()+m_outerStart); } + inline StorageIndex* innerNonZeroPtr() + { return isCompressed() ? 0 : (m_matrix.innerNonZeroPtr()+m_outerStart); } + + bool isCompressed() const { return m_matrix.innerNonZeroPtr()==0; } + + inline Scalar& coeffRef(Index row, Index col) + { + return m_matrix.coeffRef(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart)); + } + + inline const Scalar coeff(Index row, Index col) const + { + return m_matrix.coeff(row + (IsRowMajor ? m_outerStart : 0), col + (IsRowMajor ? 0 : m_outerStart)); + } + + inline const Scalar coeff(Index index) const + { + return m_matrix.coeff(IsRowMajor ? m_outerStart : index, IsRowMajor ? index : m_outerStart); + } + + const Scalar& lastCoeff() const + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(sparse_matrix_block_impl); + eigen_assert(Base::nonZeros()>0); + if(m_matrix.isCompressed()) + return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1]; + else + return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1]; + } + + EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } + EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } + + inline const SparseMatrixType& nestedExpression() const { return m_matrix; } + inline SparseMatrixType& nestedExpression() { return m_matrix; } + Index startRow() const { return IsRowMajor ? m_outerStart : 0; } + Index startCol() const { return IsRowMajor ? 0 : m_outerStart; } + Index blockRows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } + Index blockCols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } + + protected: + + typename internal::ref_selector::non_const_type m_matrix; + Index m_outerStart; + const internal::variable_if_dynamic m_outerSize; + +}; + +} // namespace internal + +template +class BlockImpl,BlockRows,BlockCols,true,Sparse> + : public internal::sparse_matrix_block_impl,BlockRows,BlockCols> +{ +public: + typedef _StorageIndex StorageIndex; + typedef SparseMatrix<_Scalar, _Options, _StorageIndex> SparseMatrixType; + typedef internal::sparse_matrix_block_impl Base; + inline BlockImpl(SparseMatrixType& xpr, Index i) + : Base(xpr, i) + {} + + inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) + : Base(xpr, startRow, startCol, blockRows, blockCols) + {} + + using Base::operator=; +}; + +template +class BlockImpl,BlockRows,BlockCols,true,Sparse> + : public internal::sparse_matrix_block_impl,BlockRows,BlockCols> +{ +public: + typedef _StorageIndex StorageIndex; + typedef const SparseMatrix<_Scalar, _Options, _StorageIndex> SparseMatrixType; + typedef internal::sparse_matrix_block_impl Base; + inline BlockImpl(SparseMatrixType& xpr, Index i) + : Base(xpr, i) + {} + + inline BlockImpl(SparseMatrixType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) + : Base(xpr, startRow, startCol, blockRows, blockCols) + {} + + using Base::operator=; +private: + template BlockImpl(const SparseMatrixBase& xpr, Index i); + template BlockImpl(const SparseMatrixBase& xpr); +}; + +//---------- + +/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this + * is col-major (resp. row-major). + */ +template +typename SparseMatrixBase::InnerVectorReturnType SparseMatrixBase::innerVector(Index outer) +{ return InnerVectorReturnType(derived(), outer); } + +/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this + * is col-major (resp. row-major). Read-only. + */ +template +const typename SparseMatrixBase::ConstInnerVectorReturnType SparseMatrixBase::innerVector(Index outer) const +{ return ConstInnerVectorReturnType(derived(), outer); } + +/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this + * is col-major (resp. row-major). + */ +template +typename SparseMatrixBase::InnerVectorsReturnType +SparseMatrixBase::innerVectors(Index outerStart, Index outerSize) +{ + return Block(derived(), + IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart, + IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); + +} + +/** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this + * is col-major (resp. row-major). Read-only. + */ +template +const typename SparseMatrixBase::ConstInnerVectorsReturnType +SparseMatrixBase::innerVectors(Index outerStart, Index outerSize) const +{ + return Block(derived(), + IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart, + IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); + +} + +/** Generic implementation of sparse Block expression. + * Real-only. + */ +template +class BlockImpl + : public SparseMatrixBase >, internal::no_assignment_operator +{ + typedef Block BlockType; + typedef SparseMatrixBase Base; + using Base::convert_index; +public: + enum { IsRowMajor = internal::traits::IsRowMajor }; + EIGEN_SPARSE_PUBLIC_INTERFACE(BlockType) + + typedef typename internal::remove_all::type _MatrixTypeNested; + + /** Column or Row constructor + */ + inline BlockImpl(XprType& xpr, Index i) + : m_matrix(xpr), + m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? convert_index(i) : 0), + m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? convert_index(i) : 0), + m_blockRows(BlockRows==1 ? 1 : xpr.rows()), + m_blockCols(BlockCols==1 ? 1 : xpr.cols()) + {} + + /** Dynamic-size constructor + */ + inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) + : m_matrix(xpr), m_startRow(convert_index(startRow)), m_startCol(convert_index(startCol)), m_blockRows(convert_index(blockRows)), m_blockCols(convert_index(blockCols)) + {} + + inline Index rows() const { return m_blockRows.value(); } + inline Index cols() const { return m_blockCols.value(); } + + inline Scalar& coeffRef(Index row, Index col) + { + return m_matrix.coeffRef(row + m_startRow.value(), col + m_startCol.value()); + } + + inline const Scalar coeff(Index row, Index col) const + { + return m_matrix.coeff(row + m_startRow.value(), col + m_startCol.value()); + } + + inline Scalar& coeffRef(Index index) + { + return m_matrix.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); + } + + inline const Scalar coeff(Index index) const + { + return m_matrix.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), + m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); + } + + inline const XprType& nestedExpression() const { return m_matrix; } + inline XprType& nestedExpression() { return m_matrix; } + Index startRow() const { return m_startRow.value(); } + Index startCol() const { return m_startCol.value(); } + Index blockRows() const { return m_blockRows.value(); } + Index blockCols() const { return m_blockCols.value(); } + + protected: +// friend class internal::GenericSparseBlockInnerIteratorImpl; + friend struct internal::unary_evaluator, internal::IteratorBased, Scalar >; + + Index nonZeros() const { return Dynamic; } + + typename internal::ref_selector::non_const_type m_matrix; + const internal::variable_if_dynamic m_startRow; + const internal::variable_if_dynamic m_startCol; + const internal::variable_if_dynamic m_blockRows; + const internal::variable_if_dynamic m_blockCols; + + protected: + // Disable assignment with clear error message. + // Note that simply removing operator= yields compilation errors with ICC+MSVC + template + BlockImpl& operator=(const T&) + { + EIGEN_STATIC_ASSERT(sizeof(T)==0, THIS_SPARSE_BLOCK_SUBEXPRESSION_IS_READ_ONLY); + return *this; + } + +}; + +namespace internal { + +template +struct unary_evaluator, IteratorBased > + : public evaluator_base > +{ + class InnerVectorInnerIterator; + class OuterVectorInnerIterator; + public: + typedef Block XprType; + typedef typename XprType::StorageIndex StorageIndex; + typedef typename XprType::Scalar Scalar; + + enum { + IsRowMajor = XprType::IsRowMajor, + + OuterVector = (BlockCols==1 && ArgType::IsRowMajor) + | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&". + // revert to || as soon as not needed anymore. + (BlockRows==1 && !ArgType::IsRowMajor), + + CoeffReadCost = evaluator::CoeffReadCost, + Flags = XprType::Flags + }; + + typedef typename internal::conditional::type InnerIterator; + + explicit unary_evaluator(const XprType& op) + : m_argImpl(op.nestedExpression()), m_block(op) + {} + + inline Index nonZerosEstimate() const { + Index nnz = m_block.nonZeros(); + if(nnz<0) + return m_argImpl.nonZerosEstimate() * m_block.size() / m_block.nestedExpression().size(); + return nnz; + } + + protected: + typedef typename evaluator::InnerIterator EvalIterator; + + evaluator m_argImpl; + const XprType &m_block; +}; + +template +class unary_evaluator, IteratorBased>::InnerVectorInnerIterator + : public EvalIterator +{ + enum { IsRowMajor = unary_evaluator::IsRowMajor }; + const XprType& m_block; + Index m_end; +public: + + EIGEN_STRONG_INLINE InnerVectorInnerIterator(const unary_evaluator& aEval, Index outer) + : EvalIterator(aEval.m_argImpl, outer + (IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol())), + m_block(aEval.m_block), + m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()) + { + while( (EvalIterator::operator bool()) && (EvalIterator::index() < (IsRowMajor ? m_block.startCol() : m_block.startRow())) ) + EvalIterator::operator++(); + } + + inline StorageIndex index() const { return EvalIterator::index() - convert_index(IsRowMajor ? m_block.startCol() : m_block.startRow()); } + inline Index outer() const { return EvalIterator::outer() - (IsRowMajor ? m_block.startRow() : m_block.startCol()); } + inline Index row() const { return EvalIterator::row() - m_block.startRow(); } + inline Index col() const { return EvalIterator::col() - m_block.startCol(); } + + inline operator bool() const { return EvalIterator::operator bool() && EvalIterator::index() < m_end; } +}; + +template +class unary_evaluator, IteratorBased>::OuterVectorInnerIterator +{ + enum { IsRowMajor = unary_evaluator::IsRowMajor }; + const unary_evaluator& m_eval; + Index m_outerPos; + Index m_innerIndex; + Scalar m_value; + Index m_end; +public: + + EIGEN_STRONG_INLINE OuterVectorInnerIterator(const unary_evaluator& aEval, Index outer) + : m_eval(aEval), + m_outerPos( (IsRowMajor ? aEval.m_block.startCol() : aEval.m_block.startRow()) - 1), // -1 so that operator++ finds the first non-zero entry + m_innerIndex(IsRowMajor ? aEval.m_block.startRow() : aEval.m_block.startCol()), + m_value(0), + m_end(IsRowMajor ? aEval.m_block.startCol()+aEval.m_block.blockCols() : aEval.m_block.startRow()+aEval.m_block.blockRows()) + { + EIGEN_UNUSED_VARIABLE(outer); + eigen_assert(outer==0); + + ++(*this); + } + + inline StorageIndex index() const { return convert_index(m_outerPos - (IsRowMajor ? m_eval.m_block.startCol() : m_eval.m_block.startRow())); } + inline Index outer() const { return 0; } + inline Index row() const { return IsRowMajor ? 0 : index(); } + inline Index col() const { return IsRowMajor ? index() : 0; } + + inline Scalar value() const { return m_value; } + + inline OuterVectorInnerIterator& operator++() + { + // search next non-zero entry + while(++m_outerPos +struct unary_evaluator,BlockRows,BlockCols,true>, IteratorBased> + : evaluator,BlockRows,BlockCols,true> > > +{ + typedef Block,BlockRows,BlockCols,true> XprType; + typedef evaluator > Base; + explicit unary_evaluator(const XprType &xpr) : Base(xpr) {} +}; + +template +struct unary_evaluator,BlockRows,BlockCols,true>, IteratorBased> + : evaluator,BlockRows,BlockCols,true> > > +{ + typedef Block,BlockRows,BlockCols,true> XprType; + typedef evaluator > Base; + explicit unary_evaluator(const XprType &xpr) : Base(xpr) {} +}; + +} // end namespace internal + + +} // end namespace Eigen + +#endif // EIGEN_SPARSE_BLOCK_H diff --git a/README.md b/README.md index 04fa63fce..4654a81c3 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -**Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms.** - -For more information go to http://eigen.tuxfamily.org/. +**Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms.** + +For more information go to http://eigen.tuxfamily.org/. From d2718d662c9759c29ed98456ab4abb128fc1a614 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 2 Dec 2016 11:32:03 +0100 Subject: [PATCH 10/13] Re-enable A^T*A action in BTL --- bench/btl/actions/basic_actions.hh | 2 +- bench/btl/libs/BLAS/blas_interface_impl.hh | 6 +++--- bench/btl/libs/BLAS/main.cpp | 2 +- bench/btl/libs/STL/STL_interface.hh | 24 +++++++++++----------- bench/btl/libs/blaze/blaze_interface.hh | 16 +++++++-------- bench/btl/libs/blaze/main.cpp | 6 +++--- bench/btl/libs/eigen3/eigen3_interface.hh | 8 +++++--- bench/btl/libs/eigen3/main_matmat.cpp | 2 +- 8 files changed, 34 insertions(+), 32 deletions(-) diff --git a/bench/btl/actions/basic_actions.hh b/bench/btl/actions/basic_actions.hh index a3333ea26..62442f01f 100644 --- a/bench/btl/actions/basic_actions.hh +++ b/bench/btl/actions/basic_actions.hh @@ -6,7 +6,7 @@ #include "action_atv_product.hh" #include "action_matrix_matrix_product.hh" -// #include "action_ata_product.hh" +#include "action_ata_product.hh" #include "action_aat_product.hh" #include "action_trisolve.hh" diff --git a/bench/btl/libs/BLAS/blas_interface_impl.hh b/bench/btl/libs/BLAS/blas_interface_impl.hh index fc4ba2a1f..9e0a64905 100644 --- a/bench/btl/libs/BLAS/blas_interface_impl.hh +++ b/bench/btl/libs/BLAS/blas_interface_impl.hh @@ -46,9 +46,9 @@ public : BLAS_FUNC(gemm)(¬rans,¬rans,&N,&N,&N,&fone,A,&N,B,&N,&fzero,X,&N); } -// static inline void ata_product(gene_matrix & A, gene_matrix & X, int N){ -// ssyrk_(&lower,&trans,&N,&N,&fone,A,&N,&fzero,X,&N); -// } + static inline void ata_product(gene_matrix & A, gene_matrix & X, int N){ + BLAS_FUNC(syrk)(&lower,&trans,&N,&N,&fone,A,&N,&fzero,X,&N); + } static inline void aat_product(gene_matrix & A, gene_matrix & X, int N){ BLAS_FUNC(syrk)(&lower,¬rans,&N,&N,&fone,A,&N,&fzero,X,&N); diff --git a/bench/btl/libs/BLAS/main.cpp b/bench/btl/libs/BLAS/main.cpp index 564d55ef2..fd991490a 100644 --- a/bench/btl/libs/BLAS/main.cpp +++ b/bench/btl/libs/BLAS/main.cpp @@ -48,7 +48,7 @@ int main() bench > >(MIN_AXPY,MAX_AXPY,NB_POINT); bench > >(MIN_MM,MAX_MM,NB_POINT); -// bench > >(MIN_MM,MAX_MM,NB_POINT); + bench > >(MIN_MM,MAX_MM,NB_POINT); bench > >(MIN_MM,MAX_MM,NB_POINT); bench > >(MIN_MM,MAX_MM,NB_POINT); diff --git a/bench/btl/libs/STL/STL_interface.hh b/bench/btl/libs/STL/STL_interface.hh index ef4cc9233..16658c4ba 100644 --- a/bench/btl/libs/STL/STL_interface.hh +++ b/bench/btl/libs/STL/STL_interface.hh @@ -78,18 +78,18 @@ public : cible[i][j]=source[i][j]; } -// static inline void ata_product(const gene_matrix & A, gene_matrix & X, int N) -// { -// real somme; -// for (int j=0;j > >(MIN_MV,MAX_MV,NB_POINT); bench > >(MIN_MV,MAX_MV,NB_POINT); -// bench > >(MIN_MM,MAX_MM,NB_POINT); -// bench > >(MIN_MM,MAX_MM,NB_POINT); -// bench > >(MIN_MM,MAX_MM,NB_POINT); + bench > >(MIN_MM,MAX_MM,NB_POINT); + bench > >(MIN_MM,MAX_MM,NB_POINT); + bench > >(MIN_MM,MAX_MM,NB_POINT); return 0; } diff --git a/bench/btl/libs/eigen3/eigen3_interface.hh b/bench/btl/libs/eigen3/eigen3_interface.hh index b821fd721..2e302d072 100644 --- a/bench/btl/libs/eigen3/eigen3_interface.hh +++ b/bench/btl/libs/eigen3/eigen3_interface.hh @@ -92,9 +92,11 @@ public : X.noalias() = A.transpose()*B.transpose(); } -// static inline void ata_product(const gene_matrix & A, gene_matrix & X, int /*N*/){ -// X.noalias() = A.transpose()*A; -// } + static inline void ata_product(const gene_matrix & A, gene_matrix & X, int /*N*/){ + //X.noalias() = A.transpose()*A; + X.template triangularView().setZero(); + X.template selfadjointView().rankUpdate(A.transpose()); + } static inline void aat_product(const gene_matrix & A, gene_matrix & X, int /*N*/){ X.template triangularView().setZero(); diff --git a/bench/btl/libs/eigen3/main_matmat.cpp b/bench/btl/libs/eigen3/main_matmat.cpp index 926fa2b01..052810a16 100644 --- a/bench/btl/libs/eigen3/main_matmat.cpp +++ b/bench/btl/libs/eigen3/main_matmat.cpp @@ -25,7 +25,7 @@ BTL_MAIN; int main() { bench > >(MIN_MM,MAX_MM,NB_POINT); -// bench > >(MIN_MM,MAX_MM,NB_POINT); + bench > >(MIN_MM,MAX_MM,NB_POINT); bench > >(MIN_MM,MAX_MM,NB_POINT); bench > >(MIN_MM,MAX_MM,NB_POINT); From 4c0d5f3c01ad74680551d670f7d4fc804ccd822f Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 2 Dec 2016 11:34:12 +0100 Subject: [PATCH 11/13] Add perf monitoring for gemv --- bench/perf_monitoring/gemm/changesets.txt | 3 + bench/perf_monitoring/gemm/gemv.cpp | 68 ++++++++++++++++++++ bench/perf_monitoring/gemm/gemv_settings.txt | 11 ++++ 3 files changed, 82 insertions(+) create mode 100644 bench/perf_monitoring/gemm/gemv.cpp create mode 100644 bench/perf_monitoring/gemm/gemv_settings.txt diff --git a/bench/perf_monitoring/gemm/changesets.txt b/bench/perf_monitoring/gemm/changesets.txt index af8eb9b8f..4bff3cc4a 100644 --- a/bench/perf_monitoring/gemm/changesets.txt +++ b/bench/perf_monitoring/gemm/changesets.txt @@ -59,3 +59,6 @@ before-evaluators 9174:d228bc282ac9 # merge 9212:c90098affa7b # Fix performance regression introduced in changeset 8aad8f35c955 9213:9f1c14e4694b # Fix performance regression in dgemm introduced by changeset 81d53c711775 +3.3-beta2 +3.3-rc1 +3.3.0 diff --git a/bench/perf_monitoring/gemm/gemv.cpp b/bench/perf_monitoring/gemm/gemv.cpp new file mode 100644 index 000000000..b7441a357 --- /dev/null +++ b/bench/perf_monitoring/gemm/gemv.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include "../../BenchTimer.h" +using namespace Eigen; + +#ifndef SCALAR +#error SCALAR must be defined +#endif + +typedef SCALAR Scalar; + +typedef Matrix Mat; +typedef Matrix Vec; + +EIGEN_DONT_INLINE +void gemv(const Mat &A, const Vec &B, Vec &C) +{ + C.noalias() += A * B; +} + +EIGEN_DONT_INLINE +double bench(long m, long n) +{ + Mat A(m,n); + Vec B(n); + Vec C(m); + A.setRandom(); + B.setRandom(); + C.setZero(); + + BenchTimer t; + + double up = 1e9*4/sizeof(Scalar); + double tm0 = 4, tm1 = 10; + if(NumTraits::IsComplex) + { + up /= 4; + tm0 = 2; + tm1 = 4; + } + + double flops = 2. * m * n; + long rep = std::max(1., std::min(100., up/flops) ); + long tries = std::max(tm0, std::min(tm1, up/flops) ); + + BENCH(t, tries, rep, gemv(A,B,C)); + + return 1e-9 * rep * flops / t.best(); +} + +int main(int argc, char **argv) +{ + std::vector results; + + std::ifstream settings("gemv_settings.txt"); + long m, n; + while(settings >> m >> n) + { + //std::cerr << " Testing " << m << " " << n << " " << k << std::endl; + results.push_back( bench(m, n) ); + } + + std::cout << RowVectorXd::Map(results.data(), results.size()); + + return 0; +} diff --git a/bench/perf_monitoring/gemm/gemv_settings.txt b/bench/perf_monitoring/gemm/gemv_settings.txt new file mode 100644 index 000000000..21a5ee051 --- /dev/null +++ b/bench/perf_monitoring/gemm/gemv_settings.txt @@ -0,0 +1,11 @@ +8 8 +9 9 +24 24 +239 239 +240 240 +2400 24 +24 2400 +24 240 +2400 2400 +4800 23 +23 4800 From fe696022ec2f1a743047d1666f0ef8a92c865f2b Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 2 Dec 2016 22:40:25 +0100 Subject: [PATCH 12/13] Operators += and -= do not resize! --- Eigen/src/Core/ProductEvaluators.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Eigen/src/Core/ProductEvaluators.h b/Eigen/src/Core/ProductEvaluators.h index b0e8b189e..583b7f59e 100644 --- a/Eigen/src/Core/ProductEvaluators.h +++ b/Eigen/src/Core/ProductEvaluators.h @@ -158,10 +158,7 @@ struct Assignment, internal::add_assign_op< static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op &) { - Index dstRows = src.rows(); - Index dstCols = src.cols(); - if((dst.rows()!=dstRows) || (dst.cols()!=dstCols)) - dst.resize(dstRows, dstCols); + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); // FIXME shall we handle nested_eval here? generic_product_impl::addTo(dst, src.lhs(), src.rhs()); } @@ -176,10 +173,7 @@ struct Assignment, internal::sub_assign_op< static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op &) { - Index dstRows = src.rows(); - Index dstCols = src.cols(); - if((dst.rows()!=dstRows) || (dst.cols()!=dstCols)) - dst.resize(dstRows, dstCols); + eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols()); // FIXME shall we handle nested_eval here? generic_product_impl::subTo(dst, src.lhs(), src.rhs()); } @@ -377,7 +371,6 @@ struct generic_product_impl { LhsNested actual_lhs(lhs); RhsNested actual_rhs(rhs); - internal::gemv_dense_selector::HasUsableDirectAccess) From 66f65ccc364034150bdc47333e05ebbde29825e5 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 2 Dec 2016 22:41:26 +0100 Subject: [PATCH 13/13] Ease compiler job to generate clean and efficient code in mat*vec. --- Eigen/src/Core/GeneralProduct.h | 91 +++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/Eigen/src/Core/GeneralProduct.h b/Eigen/src/Core/GeneralProduct.h index f62ecfcbe..0f16cd8e3 100644 --- a/Eigen/src/Core/GeneralProduct.h +++ b/Eigen/src/Core/GeneralProduct.h @@ -224,50 +224,65 @@ template<> struct gemv_dense_selector // on, the other hand it is good for the cache to pack the vector anyways... EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime==1), ComplexByReal = (NumTraits::IsComplex) && (!NumTraits::IsComplex), - MightCannotUseDest = (ActualDest::InnerStrideAtCompileTime!=1) || ComplexByReal + MightCannotUseDest = (!EvalToDestAtCompileTime) || ComplexByReal }; - gemv_static_vector_if static_dest; - - const bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0)); - const bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible; - - RhsScalar compatibleAlpha = get_factor::run(actualAlpha); - - ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(), - evalToDest ? dest.data() : static_dest.data()); - - if(!evalToDest) - { - #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN - Index size = dest.size(); - EIGEN_DENSE_STORAGE_CTOR_PLUGIN - #endif - if(!alphaIsCompatible) - { - MappedDest(actualDestPtr, dest.size()).setZero(); - compatibleAlpha = RhsScalar(1); - } - else - MappedDest(actualDestPtr, dest.size()) = dest; - } - typedef const_blas_data_mapper LhsMapper; typedef const_blas_data_mapper RhsMapper; - general_matrix_vector_product - ::run( - actualLhs.rows(), actualLhs.cols(), - LhsMapper(actualLhs.data(), actualLhs.outerStride()), - RhsMapper(actualRhs.data(), actualRhs.innerStride()), - actualDestPtr, 1, - compatibleAlpha); + RhsScalar compatibleAlpha = get_factor::run(actualAlpha); - if (!evalToDest) + if(!MightCannotUseDest) { - if(!alphaIsCompatible) - dest.matrix() += actualAlpha * MappedDest(actualDestPtr, dest.size()); - else - dest = MappedDest(actualDestPtr, dest.size()); + // shortcut if we are sure to be able to use dest directly, + // this ease the compiler to generate cleaner and more optimzized code for most common cases + general_matrix_vector_product + ::run( + actualLhs.rows(), actualLhs.cols(), + LhsMapper(actualLhs.data(), actualLhs.outerStride()), + RhsMapper(actualRhs.data(), actualRhs.innerStride()), + dest.data(), 1, + compatibleAlpha); + } + else + { + gemv_static_vector_if static_dest; + + const bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0)); + const bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible; + + ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(), + evalToDest ? dest.data() : static_dest.data()); + + if(!evalToDest) + { + #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + Index size = dest.size(); + EIGEN_DENSE_STORAGE_CTOR_PLUGIN + #endif + if(!alphaIsCompatible) + { + MappedDest(actualDestPtr, dest.size()).setZero(); + compatibleAlpha = RhsScalar(1); + } + else + MappedDest(actualDestPtr, dest.size()) = dest; + } + + general_matrix_vector_product + ::run( + actualLhs.rows(), actualLhs.cols(), + LhsMapper(actualLhs.data(), actualLhs.outerStride()), + RhsMapper(actualRhs.data(), actualRhs.innerStride()), + actualDestPtr, 1, + compatibleAlpha); + + if (!evalToDest) + { + if(!alphaIsCompatible) + dest.matrix() += actualAlpha * MappedDest(actualDestPtr, dest.size()); + else + dest = MappedDest(actualDestPtr, dest.size()); + } } } };