1388 changed files with 52220 additions and 49501 deletions
-
4resources/3rdParty/eigen/.hg_archival.txt
-
0resources/3rdParty/eigen/.hgeol
-
0resources/3rdParty/eigen/.hgignore
-
24resources/3rdParty/eigen/.hgtags
-
3resources/3rdParty/eigen/.krazy
-
0resources/3rdParty/eigen/CMakeLists.txt
-
0resources/3rdParty/eigen/COPYING.BSD
-
0resources/3rdParty/eigen/COPYING.GPL
-
0resources/3rdParty/eigen/COPYING.LGPL
-
0resources/3rdParty/eigen/COPYING.MINPACK
-
0resources/3rdParty/eigen/COPYING.MPL2
-
0resources/3rdParty/eigen/COPYING.README
-
0resources/3rdParty/eigen/CTestConfig.cmake
-
0resources/3rdParty/eigen/CTestCustom.cmake.in
-
0resources/3rdParty/eigen/Eigen/Array
-
0resources/3rdParty/eigen/Eigen/CMakeLists.txt
-
0resources/3rdParty/eigen/Eigen/Cholesky
-
0resources/3rdParty/eigen/Eigen/CholmodSupport
-
366resources/3rdParty/eigen/Eigen/Core
-
0resources/3rdParty/eigen/Eigen/Dense
-
0resources/3rdParty/eigen/Eigen/Eigen
-
0resources/3rdParty/eigen/Eigen/Eigen2Support
-
46resources/3rdParty/eigen/Eigen/Eigenvalues
-
0resources/3rdParty/eigen/Eigen/Geometry
-
0resources/3rdParty/eigen/Eigen/Householder
-
0resources/3rdParty/eigen/Eigen/IterativeLinearSolvers
-
0resources/3rdParty/eigen/Eigen/Jacobi
-
0resources/3rdParty/eigen/Eigen/LU
-
0resources/3rdParty/eigen/Eigen/LeastSquares
-
23resources/3rdParty/eigen/Eigen/OrderingMethods
-
0resources/3rdParty/eigen/Eigen/PaStiXSupport
-
0resources/3rdParty/eigen/Eigen/PardisoSupport
-
0resources/3rdParty/eigen/Eigen/QR
-
0resources/3rdParty/eigen/Eigen/QtAlignedMalloc
-
0resources/3rdParty/eigen/Eigen/SVD
-
0resources/3rdParty/eigen/Eigen/Sparse
-
0resources/3rdParty/eigen/Eigen/SparseCholesky
-
0resources/3rdParty/eigen/Eigen/SparseCore
-
0resources/3rdParty/eigen/Eigen/StdDeque
-
0resources/3rdParty/eigen/Eigen/StdList
-
0resources/3rdParty/eigen/Eigen/StdVector
-
0resources/3rdParty/eigen/Eigen/SuperLUSupport
-
0resources/3rdParty/eigen/Eigen/UmfPackSupport
-
0resources/3rdParty/eigen/Eigen/src/CMakeLists.txt
-
0resources/3rdParty/eigen/Eigen/src/Cholesky/CMakeLists.txt
-
592resources/3rdParty/eigen/Eigen/src/Cholesky/LDLT.h
-
0resources/3rdParty/eigen/Eigen/src/Cholesky/LLT.h
-
0resources/3rdParty/eigen/Eigen/src/Cholesky/LLT_MKL.h
-
0resources/3rdParty/eigen/Eigen/src/CholmodSupport/CMakeLists.txt
-
579resources/3rdParty/eigen/Eigen/src/CholmodSupport/CholmodSupport.h
-
308resources/3rdParty/eigen/Eigen/src/Core/Array.h
-
0resources/3rdParty/eigen/Eigen/src/Core/ArrayBase.h
-
254resources/3rdParty/eigen/Eigen/src/Core/ArrayWrapper.h
-
0resources/3rdParty/eigen/Eigen/src/Core/Assign.h
-
224resources/3rdParty/eigen/Eigen/src/Core/Assign_MKL.h
-
0resources/3rdParty/eigen/Eigen/src/Core/BandMatrix.h
-
357resources/3rdParty/eigen/Eigen/src/Core/Block.h
-
0resources/3rdParty/eigen/Eigen/src/Core/BooleanRedux.h
-
0resources/3rdParty/eigen/Eigen/src/Core/CMakeLists.txt
-
141resources/3rdParty/eigen/Eigen/src/Core/CommaInitializer.h
-
229resources/3rdParty/eigen/Eigen/src/Core/CwiseBinaryOp.h
-
864resources/3rdParty/eigen/Eigen/src/Core/CwiseNullaryOp.h
-
126resources/3rdParty/eigen/Eigen/src/Core/CwiseUnaryOp.h
-
0resources/3rdParty/eigen/Eigen/src/Core/CwiseUnaryView.h
-
533resources/3rdParty/eigen/Eigen/src/Core/DenseBase.h
-
754resources/3rdParty/eigen/Eigen/src/Core/DenseCoeffsBase.h
-
303resources/3rdParty/eigen/Eigen/src/Core/DenseStorage.h
-
236resources/3rdParty/eigen/Eigen/src/Core/Diagonal.h
-
307resources/3rdParty/eigen/Eigen/src/Core/DiagonalMatrix.h
-
123resources/3rdParty/eigen/Eigen/src/Core/DiagonalProduct.h
-
261resources/3rdParty/eigen/Eigen/src/Core/Dot.h
-
0resources/3rdParty/eigen/Eigen/src/Core/EigenBase.h
-
0resources/3rdParty/eigen/Eigen/src/Core/Flagged.h
-
0resources/3rdParty/eigen/Eigen/src/Core/ForceAlignedAccess.h
-
967resources/3rdParty/eigen/Eigen/src/Core/Functors.h
-
150resources/3rdParty/eigen/Eigen/src/Core/Fuzzy.h
-
613resources/3rdParty/eigen/Eigen/src/Core/GeneralProduct.h
-
0resources/3rdParty/eigen/Eigen/src/Core/GenericPacketMath.h
-
0resources/3rdParty/eigen/Eigen/src/Core/GlobalFunctions.h
-
0resources/3rdParty/eigen/Eigen/src/Core/IO.h
-
192resources/3rdParty/eigen/Eigen/src/Core/Map.h
-
242resources/3rdParty/eigen/Eigen/src/Core/MapBase.h
-
842resources/3rdParty/eigen/Eigen/src/Core/MathFunctions.h
-
0resources/3rdParty/eigen/Eigen/src/Core/Matrix.h
-
511resources/3rdParty/eigen/Eigen/src/Core/MatrixBase.h
-
0resources/3rdParty/eigen/Eigen/src/Core/NestByValue.h
-
125resources/3rdParty/eigen/Eigen/src/Core/NoAlias.h
-
0resources/3rdParty/eigen/Eigen/src/Core/NumTraits.h
-
687resources/3rdParty/eigen/Eigen/src/Core/PermutationMatrix.h
-
767resources/3rdParty/eigen/Eigen/src/Core/PlainObjectBase.h
-
98resources/3rdParty/eigen/Eigen/src/Core/Product.h
-
278resources/3rdParty/eigen/Eigen/src/Core/ProductBase.h
-
152resources/3rdParty/eigen/Eigen/src/Core/Random.h
-
0resources/3rdParty/eigen/Eigen/src/Core/Redux.h
-
177resources/3rdParty/eigen/Eigen/src/Core/Replicate.h
-
0resources/3rdParty/eigen/Eigen/src/Core/ReturnByValue.h
-
0resources/3rdParty/eigen/Eigen/src/Core/Reverse.h
-
162resources/3rdParty/eigen/Eigen/src/Core/Select.h
-
0resources/3rdParty/eigen/Eigen/src/Core/SelfAdjointView.h
-
0resources/3rdParty/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h
@ -0,0 +1,4 @@ |
|||
repo: 8a21fd850624c931e448cbcfb38168cb2717c790 |
|||
node: 5097c01bcdc4dc59c4c85b620e9a0d9825f5d6a5 |
|||
branch: 3.1 |
|||
tag: 3.1.2 |
@ -0,0 +1,24 @@ |
|||
2db9468678c6480c9633b6272ff0e3599d1e11a3 2.0-beta3 |
|||
375224817dce669b6fa31d920d4c895a63fabf32 2.0-beta1 |
|||
3b8120f077865e2a072e10f5be33e1d942b83a06 2.0-rc1 |
|||
19dfc0e7666bcee26f7a49eb42f39a0280a3485e 2.0-beta5 |
|||
7a7d8a9526f003ffa2430dfb0c2c535b5add3023 2.0-beta4 |
|||
7d14ad088ac23769c349518762704f0257f6a39b 2.0.1 |
|||
b9d48561579fd7d4c05b2aa42235dc9de6484bf2 2.0-beta6 |
|||
e17630a40408243cb1a51ad0fe3a99beb75b7450 before-hg-migration |
|||
eda654d4cda2210ce80719addcf854773e6dec5a 2.0.0 |
|||
ee9a7c468a9e73fab12f38f02bac24b07f29ed71 2.0-beta2 |
|||
d49097c25d8049e730c254a2fed725a240ce4858 after-hg-migration |
|||
655348878731bcb5d9bbe0854077b052e75e5237 actual-start-from-scratch |
|||
12a658962d4e6dfdc9a1c350fe7b69e36e70675c 3.0-beta1 |
|||
5c4180ad827b3f869b13b1d82f5a6ce617d6fcee 3.0-beta2 |
|||
7ae24ca6f3891d5ac58ddc7db60ad413c8d6ec35 3.0-beta3 |
|||
c40708b9088d622567fecc9208ad4a426621d364 3.0-beta4 |
|||
b6456624eae74f49ae8683d8e7b2882a2ca0342a 3.0-rc1 |
|||
a810d5dbab47acfe65b3350236efdd98f67d4d8a 3.1.0-alpha1 |
|||
304c88ca3affc16dd0b008b1104873986edd77af 3.1.0-alpha2 |
|||
920fc730b5930daae0a6dbe296d60ce2e3808215 3.1.0-beta1 |
|||
8383e883ebcc6f14695ff0b5e20bb631abab43fb 3.1.0-rc1 |
|||
bf4cb8c934fa3a79f45f1e629610f0225e93e493 3.1.0-rc2 |
|||
ca142d0540d3384180c5082d24ef056bd3c354b6 3.1.0 |
|||
43d9075b23ef596ddf396101956d06f446fc0765 3.1.1 |
@ -0,0 +1,3 @@ |
|||
SKIP /disabled/ |
|||
SKIP /bench/ |
|||
SKIP /build/ |
@ -0,0 +1,366 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2007-2011 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_CORE_H |
|||
#define EIGEN_CORE_H |
|||
|
|||
// first thing Eigen does: stop the compiler from committing suicide |
|||
#include "src/Core/util/DisableStupidWarnings.h" |
|||
|
|||
// then include this file where all our macros are defined. It's really important to do it first because |
|||
// it's where we do all the alignment settings (platform detection and honoring the user's will if he |
|||
// defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization. |
|||
#include "src/Core/util/Macros.h" |
|||
|
|||
#include <complex> |
|||
|
|||
// this include file manages BLAS and MKL related macros |
|||
// and inclusion of their respective header files |
|||
#include "src/Core/util/MKL_support.h" |
|||
|
|||
// if alignment is disabled, then disable vectorization. Note: EIGEN_ALIGN is the proper check, it takes into |
|||
// account both the user's will (EIGEN_DONT_ALIGN) and our own platform checks |
|||
#if !EIGEN_ALIGN |
|||
#ifndef EIGEN_DONT_VECTORIZE |
|||
#define EIGEN_DONT_VECTORIZE |
|||
#endif |
|||
#endif |
|||
|
|||
#ifdef _MSC_VER |
|||
#include <malloc.h> // for _aligned_malloc -- need it regardless of whether vectorization is enabled |
|||
#if (_MSC_VER >= 1500) // 2008 or later |
|||
// Remember that usage of defined() in a #define is undefined by the standard. |
|||
// a user reported that in 64-bit mode, MSVC doesn't care to define _M_IX86_FP. |
|||
#if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || defined(_M_X64) |
|||
#define EIGEN_SSE2_ON_MSVC_2008_OR_LATER |
|||
#endif |
|||
#endif |
|||
#else |
|||
// Remember that usage of defined() in a #define is undefined by the standard |
|||
#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) ) |
|||
#define EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef EIGEN_DONT_VECTORIZE |
|||
|
|||
#if defined (EIGEN_SSE2_ON_NON_MSVC_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER) |
|||
|
|||
// Defines symbols for compile-time detection of which instructions are |
|||
// used. |
|||
// EIGEN_VECTORIZE_YY is defined if and only if the instruction set YY is used |
|||
#define EIGEN_VECTORIZE |
|||
#define EIGEN_VECTORIZE_SSE |
|||
#define EIGEN_VECTORIZE_SSE2 |
|||
|
|||
// Detect sse3/ssse3/sse4: |
|||
// gcc and icc defines __SSE3__, ... |
|||
// there is no way to know about this on msvc. You can define EIGEN_VECTORIZE_SSE* if you |
|||
// want to force the use of those instructions with msvc. |
|||
#ifdef __SSE3__ |
|||
#define EIGEN_VECTORIZE_SSE3 |
|||
#endif |
|||
#ifdef __SSSE3__ |
|||
#define EIGEN_VECTORIZE_SSSE3 |
|||
#endif |
|||
#ifdef __SSE4_1__ |
|||
#define EIGEN_VECTORIZE_SSE4_1 |
|||
#endif |
|||
#ifdef __SSE4_2__ |
|||
#define EIGEN_VECTORIZE_SSE4_2 |
|||
#endif |
|||
|
|||
// include files |
|||
|
|||
// This extern "C" works around a MINGW-w64 compilation issue |
|||
// https://sourceforge.net/tracker/index.php?func=detail&aid=3018394&group_id=202880&atid=983354 |
|||
// In essence, intrin.h is included by windows.h and also declares intrinsics (just as emmintrin.h etc. below do). |
|||
// However, intrin.h uses an extern "C" declaration, and g++ thus complains of duplicate declarations |
|||
// with conflicting linkage. The linkage for intrinsics doesn't matter, but at that stage the compiler doesn't know; |
|||
// so, to avoid compile errors when windows.h is included after Eigen/Core, ensure intrinsics are extern "C" here too. |
|||
// notice that since these are C headers, the extern "C" is theoretically needed anyways. |
|||
extern "C" { |
|||
#include <emmintrin.h> |
|||
#include <xmmintrin.h> |
|||
#ifdef EIGEN_VECTORIZE_SSE3 |
|||
#include <pmmintrin.h> |
|||
#endif |
|||
#ifdef EIGEN_VECTORIZE_SSSE3 |
|||
#include <tmmintrin.h> |
|||
#endif |
|||
#ifdef EIGEN_VECTORIZE_SSE4_1 |
|||
#include <smmintrin.h> |
|||
#endif |
|||
#ifdef EIGEN_VECTORIZE_SSE4_2 |
|||
#include <nmmintrin.h> |
|||
#endif |
|||
} // end extern "C" |
|||
#elif defined __ALTIVEC__ |
|||
#define EIGEN_VECTORIZE |
|||
#define EIGEN_VECTORIZE_ALTIVEC |
|||
#include <altivec.h> |
|||
// We need to #undef all these ugly tokens defined in <altivec.h> |
|||
// => use __vector instead of vector |
|||
#undef bool |
|||
#undef vector |
|||
#undef pixel |
|||
#elif defined __ARM_NEON__ |
|||
#define EIGEN_VECTORIZE |
|||
#define EIGEN_VECTORIZE_NEON |
|||
#include <arm_neon.h> |
|||
#endif |
|||
#endif |
|||
|
|||
#if (defined _OPENMP) && (!defined EIGEN_DONT_PARALLELIZE) |
|||
#define EIGEN_HAS_OPENMP |
|||
#endif |
|||
|
|||
#ifdef EIGEN_HAS_OPENMP |
|||
#include <omp.h> |
|||
#endif |
|||
|
|||
// MSVC for windows mobile does not have the errno.h file |
|||
#if !(defined(_MSC_VER) && defined(_WIN32_WCE)) && !defined(__ARMCC_VERSION) |
|||
#define EIGEN_HAS_ERRNO |
|||
#endif |
|||
|
|||
#ifdef EIGEN_HAS_ERRNO |
|||
#include <cerrno> |
|||
#endif |
|||
#include <cstddef> |
|||
#include <cstdlib> |
|||
#include <cmath> |
|||
#include <cassert> |
|||
#include <functional> |
|||
#include <iosfwd> |
|||
#include <cstring> |
|||
#include <string> |
|||
#include <limits> |
|||
#include <climits> // for CHAR_BIT |
|||
// for min/max: |
|||
#include <algorithm> |
|||
|
|||
// for outputting debug info |
|||
#ifdef EIGEN_DEBUG_ASSIGN |
|||
#include <iostream> |
|||
#endif |
|||
|
|||
// required for __cpuid, needs to be included after cmath |
|||
#if defined(_MSC_VER) && (defined(_M_IX86)||defined(_M_X64)) |
|||
#include <intrin.h> |
|||
#endif |
|||
|
|||
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) |
|||
#define EIGEN_EXCEPTIONS |
|||
#endif |
|||
|
|||
#ifdef EIGEN_EXCEPTIONS |
|||
#include <new> |
|||
#endif |
|||
|
|||
/** \brief Namespace containing all symbols from the %Eigen library. */ |
|||
namespace Eigen { |
|||
|
|||
inline static const char *SimdInstructionSetsInUse(void) { |
|||
#if defined(EIGEN_VECTORIZE_SSE4_2) |
|||
return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2"; |
|||
#elif defined(EIGEN_VECTORIZE_SSE4_1) |
|||
return "SSE, SSE2, SSE3, SSSE3, SSE4.1"; |
|||
#elif defined(EIGEN_VECTORIZE_SSSE3) |
|||
return "SSE, SSE2, SSE3, SSSE3"; |
|||
#elif defined(EIGEN_VECTORIZE_SSE3) |
|||
return "SSE, SSE2, SSE3"; |
|||
#elif defined(EIGEN_VECTORIZE_SSE2) |
|||
return "SSE, SSE2"; |
|||
#elif defined(EIGEN_VECTORIZE_ALTIVEC) |
|||
return "AltiVec"; |
|||
#elif defined(EIGEN_VECTORIZE_NEON) |
|||
return "ARM NEON"; |
|||
#else |
|||
return "None"; |
|||
#endif |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#define STAGE10_FULL_EIGEN2_API 10 |
|||
#define STAGE20_RESOLVE_API_CONFLICTS 20 |
|||
#define STAGE30_FULL_EIGEN3_API 30 |
|||
#define STAGE40_FULL_EIGEN3_STRICTNESS 40 |
|||
#define STAGE99_NO_EIGEN2_SUPPORT 99 |
|||
|
|||
#if defined EIGEN2_SUPPORT_STAGE40_FULL_EIGEN3_STRICTNESS |
|||
#define EIGEN2_SUPPORT |
|||
#define EIGEN2_SUPPORT_STAGE STAGE40_FULL_EIGEN3_STRICTNESS |
|||
#elif defined EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API |
|||
#define EIGEN2_SUPPORT |
|||
#define EIGEN2_SUPPORT_STAGE STAGE30_FULL_EIGEN3_API |
|||
#elif defined EIGEN2_SUPPORT_STAGE20_RESOLVE_API_CONFLICTS |
|||
#define EIGEN2_SUPPORT |
|||
#define EIGEN2_SUPPORT_STAGE STAGE20_RESOLVE_API_CONFLICTS |
|||
#elif defined EIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API |
|||
#define EIGEN2_SUPPORT |
|||
#define EIGEN2_SUPPORT_STAGE STAGE10_FULL_EIGEN2_API |
|||
#elif defined EIGEN2_SUPPORT |
|||
// default to stage 3, that's what it's always meant |
|||
#define EIGEN2_SUPPORT_STAGE30_FULL_EIGEN3_API |
|||
#define EIGEN2_SUPPORT_STAGE STAGE30_FULL_EIGEN3_API |
|||
#else |
|||
#define EIGEN2_SUPPORT_STAGE STAGE99_NO_EIGEN2_SUPPORT |
|||
#endif |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
#undef minor |
|||
#endif |
|||
|
|||
// we use size_t frequently and we'll never remember to prepend it with std:: everytime just to |
|||
// ensure QNX/QCC support |
|||
using std::size_t; |
|||
// gcc 4.6.0 wants std:: for ptrdiff_t |
|||
using std::ptrdiff_t; |
|||
|
|||
/** \defgroup Core_Module Core module |
|||
* This is the main module of Eigen providing dense matrix and vector support |
|||
* (both fixed and dynamic size) with all the features corresponding to a BLAS library |
|||
* and much more... |
|||
* |
|||
* \code |
|||
* #include <Eigen/Core> |
|||
* \endcode |
|||
*/ |
|||
|
|||
/** \defgroup Support_modules Support modules [category] |
|||
* Category of modules which add support for external libraries. |
|||
*/ |
|||
|
|||
#include "src/Core/util/Constants.h" |
|||
#include "src/Core/util/ForwardDeclarations.h" |
|||
#include "src/Core/util/Meta.h" |
|||
#include "src/Core/util/XprHelper.h" |
|||
#include "src/Core/util/StaticAssert.h" |
|||
#include "src/Core/util/Memory.h" |
|||
|
|||
#include "src/Core/NumTraits.h" |
|||
#include "src/Core/MathFunctions.h" |
|||
#include "src/Core/GenericPacketMath.h" |
|||
|
|||
#if defined EIGEN_VECTORIZE_SSE |
|||
#include "src/Core/arch/SSE/PacketMath.h" |
|||
#include "src/Core/arch/SSE/MathFunctions.h" |
|||
#include "src/Core/arch/SSE/Complex.h" |
|||
#elif defined EIGEN_VECTORIZE_ALTIVEC |
|||
#include "src/Core/arch/AltiVec/PacketMath.h" |
|||
#include "src/Core/arch/AltiVec/Complex.h" |
|||
#elif defined EIGEN_VECTORIZE_NEON |
|||
#include "src/Core/arch/NEON/PacketMath.h" |
|||
#include "src/Core/arch/NEON/Complex.h" |
|||
#endif |
|||
|
|||
#include "src/Core/arch/Default/Settings.h" |
|||
|
|||
#include "src/Core/Functors.h" |
|||
#include "src/Core/DenseCoeffsBase.h" |
|||
#include "src/Core/DenseBase.h" |
|||
#include "src/Core/MatrixBase.h" |
|||
#include "src/Core/EigenBase.h" |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874 |
|||
// at least confirmed with Doxygen 1.5.5 and 1.5.6 |
|||
#include "src/Core/Assign.h" |
|||
#endif |
|||
|
|||
#include "src/Core/util/BlasUtil.h" |
|||
#include "src/Core/DenseStorage.h" |
|||
#include "src/Core/NestByValue.h" |
|||
#include "src/Core/ForceAlignedAccess.h" |
|||
#include "src/Core/ReturnByValue.h" |
|||
#include "src/Core/NoAlias.h" |
|||
#include "src/Core/PlainObjectBase.h" |
|||
#include "src/Core/Matrix.h" |
|||
#include "src/Core/Array.h" |
|||
#include "src/Core/CwiseBinaryOp.h" |
|||
#include "src/Core/CwiseUnaryOp.h" |
|||
#include "src/Core/CwiseNullaryOp.h" |
|||
#include "src/Core/CwiseUnaryView.h" |
|||
#include "src/Core/SelfCwiseBinaryOp.h" |
|||
#include "src/Core/Dot.h" |
|||
#include "src/Core/StableNorm.h" |
|||
#include "src/Core/MapBase.h" |
|||
#include "src/Core/Stride.h" |
|||
#include "src/Core/Map.h" |
|||
#include "src/Core/Block.h" |
|||
#include "src/Core/VectorBlock.h" |
|||
#include "src/Core/Transpose.h" |
|||
#include "src/Core/DiagonalMatrix.h" |
|||
#include "src/Core/Diagonal.h" |
|||
#include "src/Core/DiagonalProduct.h" |
|||
#include "src/Core/PermutationMatrix.h" |
|||
#include "src/Core/Transpositions.h" |
|||
#include "src/Core/Redux.h" |
|||
#include "src/Core/Visitor.h" |
|||
#include "src/Core/Fuzzy.h" |
|||
#include "src/Core/IO.h" |
|||
#include "src/Core/Swap.h" |
|||
#include "src/Core/CommaInitializer.h" |
|||
#include "src/Core/Flagged.h" |
|||
#include "src/Core/ProductBase.h" |
|||
#include "src/Core/GeneralProduct.h" |
|||
#include "src/Core/TriangularMatrix.h" |
|||
#include "src/Core/SelfAdjointView.h" |
|||
#include "src/Core/products/GeneralBlockPanelKernel.h" |
|||
#include "src/Core/products/Parallelizer.h" |
|||
#include "src/Core/products/CoeffBasedProduct.h" |
|||
#include "src/Core/products/GeneralMatrixVector.h" |
|||
#include "src/Core/products/GeneralMatrixMatrix.h" |
|||
#include "src/Core/SolveTriangular.h" |
|||
#include "src/Core/products/GeneralMatrixMatrixTriangular.h" |
|||
#include "src/Core/products/SelfadjointMatrixVector.h" |
|||
#include "src/Core/products/SelfadjointMatrixMatrix.h" |
|||
#include "src/Core/products/SelfadjointProduct.h" |
|||
#include "src/Core/products/SelfadjointRank2Update.h" |
|||
#include "src/Core/products/TriangularMatrixVector.h" |
|||
#include "src/Core/products/TriangularMatrixMatrix.h" |
|||
#include "src/Core/products/TriangularSolverMatrix.h" |
|||
#include "src/Core/products/TriangularSolverVector.h" |
|||
#include "src/Core/BandMatrix.h" |
|||
|
|||
#include "src/Core/BooleanRedux.h" |
|||
#include "src/Core/Select.h" |
|||
#include "src/Core/VectorwiseOp.h" |
|||
#include "src/Core/Random.h" |
|||
#include "src/Core/Replicate.h" |
|||
#include "src/Core/Reverse.h" |
|||
#include "src/Core/ArrayBase.h" |
|||
#include "src/Core/ArrayWrapper.h" |
|||
|
|||
#ifdef EIGEN_USE_BLAS |
|||
#include "src/Core/products/GeneralMatrixMatrix_MKL.h" |
|||
#include "src/Core/products/GeneralMatrixVector_MKL.h" |
|||
#include "src/Core/products/GeneralMatrixMatrixTriangular_MKL.h" |
|||
#include "src/Core/products/SelfadjointMatrixMatrix_MKL.h" |
|||
#include "src/Core/products/SelfadjointMatrixVector_MKL.h" |
|||
#include "src/Core/products/TriangularMatrixMatrix_MKL.h" |
|||
#include "src/Core/products/TriangularMatrixVector_MKL.h" |
|||
#include "src/Core/products/TriangularSolverMatrix_MKL.h" |
|||
#endif // EIGEN_USE_BLAS |
|||
|
|||
#ifdef EIGEN_USE_MKL_VML |
|||
#include "src/Core/Assign_MKL.h" |
|||
#endif |
|||
|
|||
#include "src/Core/GlobalFunctions.h" |
|||
|
|||
#include "src/Core/util/ReenableStupidWarnings.h" |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
#include "Eigen2Support" |
|||
#endif |
|||
|
|||
#endif // EIGEN_CORE_H |
@ -0,0 +1,46 @@ |
|||
#ifndef EIGEN_EIGENVALUES_MODULE_H |
|||
#define EIGEN_EIGENVALUES_MODULE_H |
|||
|
|||
#include "Core" |
|||
|
|||
#include "src/Core/util/DisableStupidWarnings.h" |
|||
|
|||
#include "Cholesky" |
|||
#include "Jacobi" |
|||
#include "Householder" |
|||
#include "LU" |
|||
#include "Geometry" |
|||
|
|||
/** \defgroup Eigenvalues_Module Eigenvalues module |
|||
* |
|||
* |
|||
* |
|||
* This module mainly provides various eigenvalue solvers. |
|||
* This module also provides some MatrixBase methods, including: |
|||
* - MatrixBase::eigenvalues(), |
|||
* - MatrixBase::operatorNorm() |
|||
* |
|||
* \code |
|||
* #include <Eigen/Eigenvalues> |
|||
* \endcode |
|||
*/ |
|||
|
|||
#include "src/Eigenvalues/Tridiagonalization.h" |
|||
#include "src/Eigenvalues/RealSchur.h" |
|||
#include "src/Eigenvalues/EigenSolver.h" |
|||
#include "src/Eigenvalues/SelfAdjointEigenSolver.h" |
|||
#include "src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h" |
|||
#include "src/Eigenvalues/HessenbergDecomposition.h" |
|||
#include "src/Eigenvalues/ComplexSchur.h" |
|||
#include "src/Eigenvalues/ComplexEigenSolver.h" |
|||
#include "src/Eigenvalues/MatrixBaseEigenvalues.h" |
|||
#ifdef EIGEN_USE_LAPACKE |
|||
#include "src/Eigenvalues/RealSchur_MKL.h" |
|||
#include "src/Eigenvalues/ComplexSchur_MKL.h" |
|||
#include "src/Eigenvalues/SelfAdjointEigenSolver_MKL.h" |
|||
#endif |
|||
|
|||
#include "src/Core/util/ReenableStupidWarnings.h" |
|||
|
|||
#endif // EIGEN_EIGENVALUES_MODULE_H |
|||
/* vim: set filetype=cpp et sw=2 ts=2 ai: */ |
@ -0,0 +1,23 @@ |
|||
#ifndef EIGEN_ORDERINGMETHODS_MODULE_H |
|||
#define EIGEN_ORDERINGMETHODS_MODULE_H |
|||
|
|||
#include "SparseCore" |
|||
|
|||
#include "src/Core/util/DisableStupidWarnings.h" |
|||
|
|||
/** \ingroup Sparse_modules |
|||
* \defgroup OrderingMethods_Module OrderingMethods module |
|||
* |
|||
* This module is currently for internal use only. |
|||
* |
|||
* |
|||
* \code |
|||
* #include <Eigen/OrderingMethods> |
|||
* \endcode |
|||
*/ |
|||
|
|||
#include "src/OrderingMethods/Amd.h" |
|||
|
|||
#include "src/Core/util/ReenableStupidWarnings.h" |
|||
|
|||
#endif // EIGEN_ORDERINGMETHODS_MODULE_H |
@ -0,0 +1,592 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2009 Keir Mierle <mierle@gmail.com> |
|||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2011 Timothy E. Holy <tim.holy@gmail.com > |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_LDLT_H |
|||
#define EIGEN_LDLT_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
template<typename MatrixType, int UpLo> struct LDLT_Traits; |
|||
} |
|||
|
|||
/** \ingroup Cholesky_Module |
|||
* |
|||
* \class LDLT |
|||
* |
|||
* \brief Robust Cholesky decomposition of a matrix with pivoting |
|||
* |
|||
* \param MatrixType the type of the matrix of which to compute the LDL^T Cholesky decomposition |
|||
* \param UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper. |
|||
* The other triangular part won't be read. |
|||
* |
|||
* Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite |
|||
* matrix \f$ A \f$ such that \f$ A = P^TLDL^*P \f$, where P is a permutation matrix, L |
|||
* is lower triangular with a unit diagonal and D is a diagonal matrix. |
|||
* |
|||
* The decomposition uses pivoting to ensure stability, so that L will have |
|||
* zeros in the bottom right rank(A) - n submatrix. Avoiding the square root |
|||
* on D also stabilizes the computation. |
|||
* |
|||
* Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky |
|||
* decomposition to determine whether a system of equations has a solution. |
|||
* |
|||
* \sa MatrixBase::ldlt(), class LLT |
|||
*/ |
|||
template<typename _MatrixType, int _UpLo> class LDLT |
|||
{ |
|||
public: |
|||
typedef _MatrixType MatrixType; |
|||
enum { |
|||
RowsAtCompileTime = MatrixType::RowsAtCompileTime, |
|||
ColsAtCompileTime = MatrixType::ColsAtCompileTime, |
|||
Options = MatrixType::Options & ~RowMajorBit, // these are the options for the TmpMatrixType, we need a ColMajor matrix here! |
|||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, |
|||
UpLo = _UpLo |
|||
}; |
|||
typedef typename MatrixType::Scalar Scalar; |
|||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; |
|||
typedef typename MatrixType::Index Index; |
|||
typedef Matrix<Scalar, RowsAtCompileTime, 1, Options, MaxRowsAtCompileTime, 1> TmpMatrixType; |
|||
|
|||
typedef Transpositions<RowsAtCompileTime, MaxRowsAtCompileTime> TranspositionType; |
|||
typedef PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime> PermutationType; |
|||
|
|||
typedef internal::LDLT_Traits<MatrixType,UpLo> Traits; |
|||
|
|||
/** \brief Default Constructor. |
|||
* |
|||
* The default constructor is useful in cases in which the user intends to |
|||
* perform decompositions via LDLT::compute(const MatrixType&). |
|||
*/ |
|||
LDLT() : m_matrix(), m_transpositions(), m_isInitialized(false) {} |
|||
|
|||
/** \brief Default Constructor with memory preallocation |
|||
* |
|||
* Like the default constructor but with preallocation of the internal data |
|||
* according to the specified problem \a size. |
|||
* \sa LDLT() |
|||
*/ |
|||
LDLT(Index size) |
|||
: m_matrix(size, size), |
|||
m_transpositions(size), |
|||
m_temporary(size), |
|||
m_isInitialized(false) |
|||
{} |
|||
|
|||
/** \brief Constructor with decomposition |
|||
* |
|||
* This calculates the decomposition for the input \a matrix. |
|||
* \sa LDLT(Index size) |
|||
*/ |
|||
LDLT(const MatrixType& matrix) |
|||
: m_matrix(matrix.rows(), matrix.cols()), |
|||
m_transpositions(matrix.rows()), |
|||
m_temporary(matrix.rows()), |
|||
m_isInitialized(false) |
|||
{ |
|||
compute(matrix); |
|||
} |
|||
|
|||
/** Clear any existing decomposition |
|||
* \sa rankUpdate(w,sigma) |
|||
*/ |
|||
void setZero() |
|||
{ |
|||
m_isInitialized = false; |
|||
} |
|||
|
|||
/** \returns a view of the upper triangular matrix U */ |
|||
inline typename Traits::MatrixU matrixU() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
return Traits::getU(m_matrix); |
|||
} |
|||
|
|||
/** \returns a view of the lower triangular matrix L */ |
|||
inline typename Traits::MatrixL matrixL() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
return Traits::getL(m_matrix); |
|||
} |
|||
|
|||
/** \returns the permutation matrix P as a transposition sequence. |
|||
*/ |
|||
inline const TranspositionType& transpositionsP() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
return m_transpositions; |
|||
} |
|||
|
|||
/** \returns the coefficients of the diagonal matrix D */ |
|||
inline Diagonal<const MatrixType> vectorD() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
return m_matrix.diagonal(); |
|||
} |
|||
|
|||
/** \returns true if the matrix is positive (semidefinite) */ |
|||
inline bool isPositive() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
return m_sign == 1; |
|||
} |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
inline bool isPositiveDefinite() const |
|||
{ |
|||
return isPositive(); |
|||
} |
|||
#endif |
|||
|
|||
/** \returns true if the matrix is negative (semidefinite) */ |
|||
inline bool isNegative(void) const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
return m_sign == -1; |
|||
} |
|||
|
|||
/** \returns a solution x of \f$ A x = b \f$ using the current decomposition of A. |
|||
* |
|||
* This function also supports in-place solves using the syntax <tt>x = decompositionObject.solve(x)</tt> . |
|||
* |
|||
* \note_about_checking_solutions |
|||
* |
|||
* More precisely, this method solves \f$ A x = b \f$ using the decomposition \f$ A = P^T L D L^* P \f$ |
|||
* by solving the systems \f$ P^T y_1 = b \f$, \f$ L y_2 = y_1 \f$, \f$ D y_3 = y_2 \f$, |
|||
* \f$ L^* y_4 = y_3 \f$ and \f$ P x = y_4 \f$ in succession. If the matrix \f$ A \f$ is singular, then |
|||
* \f$ D \f$ will also be singular (all the other matrices are invertible). In that case, the |
|||
* least-square solution of \f$ D y_3 = y_2 \f$ is computed. This does not mean that this function |
|||
* computes the least-square solution of \f$ A x = b \f$ is \f$ A \f$ is singular. |
|||
* |
|||
* \sa MatrixBase::ldlt() |
|||
*/ |
|||
template<typename Rhs> |
|||
inline const internal::solve_retval<LDLT, Rhs> |
|||
solve(const MatrixBase<Rhs>& b) const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
eigen_assert(m_matrix.rows()==b.rows() |
|||
&& "LDLT::solve(): invalid number of rows of the right hand side matrix b"); |
|||
return internal::solve_retval<LDLT, Rhs>(*this, b.derived()); |
|||
} |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
template<typename OtherDerived, typename ResultType> |
|||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const |
|||
{ |
|||
*result = this->solve(b); |
|||
return true; |
|||
} |
|||
#endif |
|||
|
|||
template<typename Derived> |
|||
bool solveInPlace(MatrixBase<Derived> &bAndX) const; |
|||
|
|||
LDLT& compute(const MatrixType& matrix); |
|||
|
|||
template <typename Derived> |
|||
LDLT& rankUpdate(const MatrixBase<Derived>& w,RealScalar alpha=1); |
|||
|
|||
/** \returns the internal LDLT decomposition matrix |
|||
* |
|||
* TODO: document the storage layout |
|||
*/ |
|||
inline const MatrixType& matrixLDLT() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
return m_matrix; |
|||
} |
|||
|
|||
MatrixType reconstructedMatrix() const; |
|||
|
|||
inline Index rows() const { return m_matrix.rows(); } |
|||
inline Index cols() const { return m_matrix.cols(); } |
|||
|
|||
/** \brief Reports whether previous computation was successful. |
|||
* |
|||
* \returns \c Success if computation was succesful, |
|||
* \c NumericalIssue if the matrix.appears to be negative. |
|||
*/ |
|||
ComputationInfo info() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
return Success; |
|||
} |
|||
|
|||
protected: |
|||
|
|||
/** \internal |
|||
* Used to compute and store the Cholesky decomposition A = L D L^* = U^* D U. |
|||
* The strict upper part is used during the decomposition, the strict lower |
|||
* part correspond to the coefficients of L (its diagonal is equal to 1 and |
|||
* is not stored), and the diagonal entries correspond to D. |
|||
*/ |
|||
MatrixType m_matrix; |
|||
TranspositionType m_transpositions; |
|||
TmpMatrixType m_temporary; |
|||
int m_sign; |
|||
bool m_isInitialized; |
|||
}; |
|||
|
|||
namespace internal { |
|||
|
|||
template<int UpLo> struct ldlt_inplace; |
|||
|
|||
template<> struct ldlt_inplace<Lower> |
|||
{ |
|||
template<typename MatrixType, typename TranspositionType, typename Workspace> |
|||
static bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0) |
|||
{ |
|||
typedef typename MatrixType::Scalar Scalar; |
|||
typedef typename MatrixType::RealScalar RealScalar; |
|||
typedef typename MatrixType::Index Index; |
|||
eigen_assert(mat.rows()==mat.cols()); |
|||
const Index size = mat.rows(); |
|||
|
|||
if (size <= 1) |
|||
{ |
|||
transpositions.setIdentity(); |
|||
if(sign) |
|||
*sign = real(mat.coeff(0,0))>0 ? 1:-1; |
|||
return true; |
|||
} |
|||
|
|||
RealScalar cutoff(0), biggest_in_corner; |
|||
|
|||
for (Index k = 0; k < size; ++k) |
|||
{ |
|||
// Find largest diagonal element |
|||
Index index_of_biggest_in_corner; |
|||
biggest_in_corner = mat.diagonal().tail(size-k).cwiseAbs().maxCoeff(&index_of_biggest_in_corner); |
|||
index_of_biggest_in_corner += k; |
|||
|
|||
if(k == 0) |
|||
{ |
|||
// The biggest overall is the point of reference to which further diagonals |
|||
// are compared; if any diagonal is negligible compared |
|||
// to the largest overall, the algorithm bails. |
|||
cutoff = abs(NumTraits<Scalar>::epsilon() * biggest_in_corner); |
|||
|
|||
if(sign) |
|||
*sign = real(mat.diagonal().coeff(index_of_biggest_in_corner)) > 0 ? 1 : -1; |
|||
} |
|||
|
|||
// Finish early if the matrix is not full rank. |
|||
if(biggest_in_corner < cutoff) |
|||
{ |
|||
for(Index i = k; i < size; i++) transpositions.coeffRef(i) = i; |
|||
break; |
|||
} |
|||
|
|||
transpositions.coeffRef(k) = index_of_biggest_in_corner; |
|||
if(k != index_of_biggest_in_corner) |
|||
{ |
|||
// apply the transposition while taking care to consider only |
|||
// the lower triangular part |
|||
Index s = size-index_of_biggest_in_corner-1; // trailing size after the biggest element |
|||
mat.row(k).head(k).swap(mat.row(index_of_biggest_in_corner).head(k)); |
|||
mat.col(k).tail(s).swap(mat.col(index_of_biggest_in_corner).tail(s)); |
|||
std::swap(mat.coeffRef(k,k),mat.coeffRef(index_of_biggest_in_corner,index_of_biggest_in_corner)); |
|||
for(int i=k+1;i<index_of_biggest_in_corner;++i) |
|||
{ |
|||
Scalar tmp = mat.coeffRef(i,k); |
|||
mat.coeffRef(i,k) = conj(mat.coeffRef(index_of_biggest_in_corner,i)); |
|||
mat.coeffRef(index_of_biggest_in_corner,i) = conj(tmp); |
|||
} |
|||
if(NumTraits<Scalar>::IsComplex) |
|||
mat.coeffRef(index_of_biggest_in_corner,k) = conj(mat.coeff(index_of_biggest_in_corner,k)); |
|||
} |
|||
|
|||
// partition the matrix: |
|||
// A00 | - | - |
|||
// lu = A10 | A11 | - |
|||
// A20 | A21 | A22 |
|||
Index rs = size - k - 1; |
|||
Block<MatrixType,Dynamic,1> A21(mat,k+1,k,rs,1); |
|||
Block<MatrixType,1,Dynamic> A10(mat,k,0,1,k); |
|||
Block<MatrixType,Dynamic,Dynamic> A20(mat,k+1,0,rs,k); |
|||
|
|||
if(k>0) |
|||
{ |
|||
temp.head(k) = mat.diagonal().head(k).asDiagonal() * A10.adjoint(); |
|||
mat.coeffRef(k,k) -= (A10 * temp.head(k)).value(); |
|||
if(rs>0) |
|||
A21.noalias() -= A20 * temp.head(k); |
|||
} |
|||
if((rs>0) && (abs(mat.coeffRef(k,k)) > cutoff)) |
|||
A21 /= mat.coeffRef(k,k); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
// Reference for the algorithm: Davis and Hager, "Multiple Rank |
|||
// Modifications of a Sparse Cholesky Factorization" (Algorithm 1) |
|||
// Trivial rearrangements of their computations (Timothy E. Holy) |
|||
// allow their algorithm to work for rank-1 updates even if the |
|||
// original matrix is not of full rank. |
|||
// Here only rank-1 updates are implemented, to reduce the |
|||
// requirement for intermediate storage and improve accuracy |
|||
template<typename MatrixType, typename WDerived> |
|||
static bool updateInPlace(MatrixType& mat, MatrixBase<WDerived>& w, typename MatrixType::RealScalar sigma=1) |
|||
{ |
|||
using internal::isfinite; |
|||
typedef typename MatrixType::Scalar Scalar; |
|||
typedef typename MatrixType::RealScalar RealScalar; |
|||
typedef typename MatrixType::Index Index; |
|||
|
|||
const Index size = mat.rows(); |
|||
eigen_assert(mat.cols() == size && w.size()==size); |
|||
|
|||
RealScalar alpha = 1; |
|||
|
|||
// Apply the update |
|||
for (Index j = 0; j < size; j++) |
|||
{ |
|||
// Check for termination due to an original decomposition of low-rank |
|||
if (!(isfinite)(alpha)) |
|||
break; |
|||
|
|||
// Update the diagonal terms |
|||
RealScalar dj = real(mat.coeff(j,j)); |
|||
Scalar wj = w.coeff(j); |
|||
RealScalar swj2 = sigma*abs2(wj); |
|||
RealScalar gamma = dj*alpha + swj2; |
|||
|
|||
mat.coeffRef(j,j) += swj2/alpha; |
|||
alpha += swj2/dj; |
|||
|
|||
|
|||
// Update the terms of L |
|||
Index rs = size-j-1; |
|||
w.tail(rs) -= wj * mat.col(j).tail(rs); |
|||
if(gamma != 0) |
|||
mat.col(j).tail(rs) += (sigma*conj(wj)/gamma)*w.tail(rs); |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType> |
|||
static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, typename MatrixType::RealScalar sigma=1) |
|||
{ |
|||
// Apply the permutation to the input w |
|||
tmp = transpositions * w; |
|||
|
|||
return ldlt_inplace<Lower>::updateInPlace(mat,tmp,sigma); |
|||
} |
|||
}; |
|||
|
|||
template<> struct ldlt_inplace<Upper> |
|||
{ |
|||
template<typename MatrixType, typename TranspositionType, typename Workspace> |
|||
static EIGEN_STRONG_INLINE bool unblocked(MatrixType& mat, TranspositionType& transpositions, Workspace& temp, int* sign=0) |
|||
{ |
|||
Transpose<MatrixType> matt(mat); |
|||
return ldlt_inplace<Lower>::unblocked(matt, transpositions, temp, sign); |
|||
} |
|||
|
|||
template<typename MatrixType, typename TranspositionType, typename Workspace, typename WType> |
|||
static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, typename MatrixType::RealScalar sigma=1) |
|||
{ |
|||
Transpose<MatrixType> matt(mat); |
|||
return ldlt_inplace<Lower>::update(matt, transpositions, tmp, w.conjugate(), sigma); |
|||
} |
|||
}; |
|||
|
|||
template<typename MatrixType> struct LDLT_Traits<MatrixType,Lower> |
|||
{ |
|||
typedef const TriangularView<const MatrixType, UnitLower> MatrixL; |
|||
typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitUpper> MatrixU; |
|||
static inline MatrixL getL(const MatrixType& m) { return m; } |
|||
static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); } |
|||
}; |
|||
|
|||
template<typename MatrixType> struct LDLT_Traits<MatrixType,Upper> |
|||
{ |
|||
typedef const TriangularView<const typename MatrixType::AdjointReturnType, UnitLower> MatrixL; |
|||
typedef const TriangularView<const MatrixType, UnitUpper> MatrixU; |
|||
static inline MatrixL getL(const MatrixType& m) { return m.adjoint(); } |
|||
static inline MatrixU getU(const MatrixType& m) { return m; } |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/** Compute / recompute the LDLT decomposition A = L D L^* = U^* D U of \a matrix |
|||
*/ |
|||
template<typename MatrixType, int _UpLo> |
|||
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::compute(const MatrixType& a) |
|||
{ |
|||
eigen_assert(a.rows()==a.cols()); |
|||
const Index size = a.rows(); |
|||
|
|||
m_matrix = a; |
|||
|
|||
m_transpositions.resize(size); |
|||
m_isInitialized = false; |
|||
m_temporary.resize(size); |
|||
|
|||
internal::ldlt_inplace<UpLo>::unblocked(m_matrix, m_transpositions, m_temporary, &m_sign); |
|||
|
|||
m_isInitialized = true; |
|||
return *this; |
|||
} |
|||
|
|||
/** Update the LDLT decomposition: given A = L D L^T, efficiently compute the decomposition of A + sigma w w^T. |
|||
* \param w a vector to be incorporated into the decomposition. |
|||
* \param sigma a scalar, +1 for updates and -1 for "downdates," which correspond to removing previously-added column vectors. Optional; default value is +1. |
|||
* \sa setZero() |
|||
*/ |
|||
template<typename MatrixType, int _UpLo> |
|||
template<typename Derived> |
|||
LDLT<MatrixType,_UpLo>& LDLT<MatrixType,_UpLo>::rankUpdate(const MatrixBase<Derived>& w,typename NumTraits<typename MatrixType::Scalar>::Real sigma) |
|||
{ |
|||
const Index size = w.rows(); |
|||
if (m_isInitialized) |
|||
{ |
|||
eigen_assert(m_matrix.rows()==size); |
|||
} |
|||
else |
|||
{ |
|||
m_matrix.resize(size,size); |
|||
m_matrix.setZero(); |
|||
m_transpositions.resize(size); |
|||
for (Index i = 0; i < size; i++) |
|||
m_transpositions.coeffRef(i) = i; |
|||
m_temporary.resize(size); |
|||
m_sign = sigma>=0 ? 1 : -1; |
|||
m_isInitialized = true; |
|||
} |
|||
|
|||
internal::ldlt_inplace<UpLo>::update(m_matrix, m_transpositions, m_temporary, w, sigma); |
|||
|
|||
return *this; |
|||
} |
|||
|
|||
namespace internal { |
|||
template<typename _MatrixType, int _UpLo, typename Rhs> |
|||
struct solve_retval<LDLT<_MatrixType,_UpLo>, Rhs> |
|||
: solve_retval_base<LDLT<_MatrixType,_UpLo>, Rhs> |
|||
{ |
|||
typedef LDLT<_MatrixType,_UpLo> LDLTType; |
|||
EIGEN_MAKE_SOLVE_HELPERS(LDLTType,Rhs) |
|||
|
|||
template<typename Dest> void evalTo(Dest& dst) const |
|||
{ |
|||
eigen_assert(rhs().rows() == dec().matrixLDLT().rows()); |
|||
// dst = P b |
|||
dst = dec().transpositionsP() * rhs(); |
|||
|
|||
// dst = L^-1 (P b) |
|||
dec().matrixL().solveInPlace(dst); |
|||
|
|||
// dst = D^-1 (L^-1 P b) |
|||
// more precisely, use pseudo-inverse of D (see bug 241) |
|||
using std::abs; |
|||
using std::max; |
|||
typedef typename LDLTType::MatrixType MatrixType; |
|||
typedef typename LDLTType::Scalar Scalar; |
|||
typedef typename LDLTType::RealScalar RealScalar; |
|||
const Diagonal<const MatrixType> vectorD = dec().vectorD(); |
|||
RealScalar tolerance = (max)(vectorD.array().abs().maxCoeff() * NumTraits<Scalar>::epsilon(), |
|||
RealScalar(1) / NumTraits<RealScalar>::highest()); // motivated by LAPACK's xGELSS |
|||
for (Index i = 0; i < vectorD.size(); ++i) { |
|||
if(abs(vectorD(i)) > tolerance) |
|||
dst.row(i) /= vectorD(i); |
|||
else |
|||
dst.row(i).setZero(); |
|||
} |
|||
|
|||
// dst = L^-T (D^-1 L^-1 P b) |
|||
dec().matrixU().solveInPlace(dst); |
|||
|
|||
// dst = P^-1 (L^-T D^-1 L^-1 P b) = A^-1 b |
|||
dst = dec().transpositionsP().transpose() * dst; |
|||
} |
|||
}; |
|||
} |
|||
|
|||
/** \internal use x = ldlt_object.solve(x); |
|||
* |
|||
* This is the \em in-place version of solve(). |
|||
* |
|||
* \param bAndX represents both the right-hand side matrix b and result x. |
|||
* |
|||
* \returns true always! If you need to check for existence of solutions, use another decomposition like LU, QR, or SVD. |
|||
* |
|||
* This version avoids a copy when the right hand side matrix b is not |
|||
* needed anymore. |
|||
* |
|||
* \sa LDLT::solve(), MatrixBase::ldlt() |
|||
*/ |
|||
template<typename MatrixType,int _UpLo> |
|||
template<typename Derived> |
|||
bool LDLT<MatrixType,_UpLo>::solveInPlace(MatrixBase<Derived> &bAndX) const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
const Index size = m_matrix.rows(); |
|||
eigen_assert(size == bAndX.rows()); |
|||
|
|||
bAndX = this->solve(bAndX); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/** \returns the matrix represented by the decomposition, |
|||
* i.e., it returns the product: P^T L D L^* P. |
|||
* This function is provided for debug purpose. */ |
|||
template<typename MatrixType, int _UpLo> |
|||
MatrixType LDLT<MatrixType,_UpLo>::reconstructedMatrix() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LDLT is not initialized."); |
|||
const Index size = m_matrix.rows(); |
|||
MatrixType res(size,size); |
|||
|
|||
// P |
|||
res.setIdentity(); |
|||
res = transpositionsP() * res; |
|||
// L^* P |
|||
res = matrixU() * res; |
|||
// D(L^*P) |
|||
res = vectorD().asDiagonal() * res; |
|||
// L(DL^*P) |
|||
res = matrixL() * res; |
|||
// P^T (LDL^*P) |
|||
res = transpositionsP().transpose() * res; |
|||
|
|||
return res; |
|||
} |
|||
|
|||
/** \cholesky_module |
|||
* \returns the Cholesky decomposition with full pivoting without square root of \c *this |
|||
*/ |
|||
template<typename MatrixType, unsigned int UpLo> |
|||
inline const LDLT<typename SelfAdjointView<MatrixType, UpLo>::PlainObject, UpLo> |
|||
SelfAdjointView<MatrixType, UpLo>::ldlt() const |
|||
{ |
|||
return LDLT<PlainObject,UpLo>(m_matrix); |
|||
} |
|||
|
|||
/** \cholesky_module |
|||
* \returns the Cholesky decomposition with full pivoting without square root of \c *this |
|||
*/ |
|||
template<typename Derived> |
|||
inline const LDLT<typename MatrixBase<Derived>::PlainObject> |
|||
MatrixBase<Derived>::ldlt() const |
|||
{ |
|||
return LDLT<PlainObject>(derived()); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_LDLT_H |
@ -0,0 +1,579 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_CHOLMODSUPPORT_H |
|||
#define EIGEN_CHOLMODSUPPORT_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename Scalar, typename CholmodType> |
|||
void cholmod_configure_matrix(CholmodType& mat) |
|||
{ |
|||
if (internal::is_same<Scalar,float>::value) |
|||
{ |
|||
mat.xtype = CHOLMOD_REAL; |
|||
mat.dtype = CHOLMOD_SINGLE; |
|||
} |
|||
else if (internal::is_same<Scalar,double>::value) |
|||
{ |
|||
mat.xtype = CHOLMOD_REAL; |
|||
mat.dtype = CHOLMOD_DOUBLE; |
|||
} |
|||
else if (internal::is_same<Scalar,std::complex<float> >::value) |
|||
{ |
|||
mat.xtype = CHOLMOD_COMPLEX; |
|||
mat.dtype = CHOLMOD_SINGLE; |
|||
} |
|||
else if (internal::is_same<Scalar,std::complex<double> >::value) |
|||
{ |
|||
mat.xtype = CHOLMOD_COMPLEX; |
|||
mat.dtype = CHOLMOD_DOUBLE; |
|||
} |
|||
else |
|||
{ |
|||
eigen_assert(false && "Scalar type not supported by CHOLMOD"); |
|||
} |
|||
} |
|||
|
|||
} // namespace internal |
|||
|
|||
/** Wraps the Eigen sparse matrix \a mat into a Cholmod sparse matrix object. |
|||
* Note that the data are shared. |
|||
*/ |
|||
template<typename _Scalar, int _Options, typename _Index> |
|||
cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat) |
|||
{ |
|||
typedef SparseMatrix<_Scalar,_Options,_Index> MatrixType; |
|||
cholmod_sparse res; |
|||
res.nzmax = mat.nonZeros(); |
|||
res.nrow = mat.rows();; |
|||
res.ncol = mat.cols(); |
|||
res.p = mat.outerIndexPtr(); |
|||
res.i = mat.innerIndexPtr(); |
|||
res.x = mat.valuePtr(); |
|||
res.sorted = 1; |
|||
if(mat.isCompressed()) |
|||
{ |
|||
res.packed = 1; |
|||
} |
|||
else |
|||
{ |
|||
res.packed = 0; |
|||
res.nz = mat.innerNonZeroPtr(); |
|||
} |
|||
|
|||
res.dtype = 0; |
|||
res.stype = -1; |
|||
|
|||
if (internal::is_same<_Index,int>::value) |
|||
{ |
|||
res.itype = CHOLMOD_INT; |
|||
} |
|||
else |
|||
{ |
|||
eigen_assert(false && "Index type different than int is not supported yet"); |
|||
} |
|||
|
|||
// setup res.xtype |
|||
internal::cholmod_configure_matrix<_Scalar>(res); |
|||
|
|||
res.stype = 0; |
|||
|
|||
return res; |
|||
} |
|||
|
|||
template<typename _Scalar, int _Options, typename _Index> |
|||
const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat) |
|||
{ |
|||
cholmod_sparse res = viewAsCholmod(mat.const_cast_derived()); |
|||
return res; |
|||
} |
|||
|
|||
/** Returns a view of the Eigen sparse matrix \a mat as Cholmod sparse matrix. |
|||
* The data are not copied but shared. */ |
|||
template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo> |
|||
cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat) |
|||
{ |
|||
cholmod_sparse res = viewAsCholmod(mat.matrix().const_cast_derived()); |
|||
|
|||
if(UpLo==Upper) res.stype = 1; |
|||
if(UpLo==Lower) res.stype = -1; |
|||
|
|||
return res; |
|||
} |
|||
|
|||
/** Returns a view of the Eigen \b dense matrix \a mat as Cholmod dense matrix. |
|||
* The data are not copied but shared. */ |
|||
template<typename Derived> |
|||
cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat) |
|||
{ |
|||
EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); |
|||
typedef typename Derived::Scalar Scalar; |
|||
|
|||
cholmod_dense res; |
|||
res.nrow = mat.rows(); |
|||
res.ncol = mat.cols(); |
|||
res.nzmax = res.nrow * res.ncol; |
|||
res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride(); |
|||
res.x = mat.derived().data(); |
|||
res.z = 0; |
|||
|
|||
internal::cholmod_configure_matrix<Scalar>(res); |
|||
|
|||
return res; |
|||
} |
|||
|
|||
/** Returns a view of the Cholmod sparse matrix \a cm as an Eigen sparse matrix. |
|||
* The data are not copied but shared. */ |
|||
template<typename Scalar, int Flags, typename Index> |
|||
MappedSparseMatrix<Scalar,Flags,Index> viewAsEigen(cholmod_sparse& cm) |
|||
{ |
|||
return MappedSparseMatrix<Scalar,Flags,Index> |
|||
(cm.nrow, cm.ncol, reinterpret_cast<Index*>(cm.p)[cm.ncol], |
|||
reinterpret_cast<Index*>(cm.p), reinterpret_cast<Index*>(cm.i),reinterpret_cast<Scalar*>(cm.x) ); |
|||
} |
|||
|
|||
enum CholmodMode { |
|||
CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt |
|||
}; |
|||
|
|||
|
|||
/** \ingroup CholmodSupport_Module |
|||
* \class CholmodBase |
|||
* \brief The base class for the direct Cholesky factorization of Cholmod |
|||
* \sa class CholmodSupernodalLLT, class CholmodSimplicialLDLT, class CholmodSimplicialLLT |
|||
*/ |
|||
template<typename _MatrixType, int _UpLo, typename Derived> |
|||
class CholmodBase : internal::noncopyable |
|||
{ |
|||
public: |
|||
typedef _MatrixType MatrixType; |
|||
enum { UpLo = _UpLo }; |
|||
typedef typename MatrixType::Scalar Scalar; |
|||
typedef typename MatrixType::RealScalar RealScalar; |
|||
typedef MatrixType CholMatrixType; |
|||
typedef typename MatrixType::Index Index; |
|||
|
|||
public: |
|||
|
|||
CholmodBase() |
|||
: m_cholmodFactor(0), m_info(Success), m_isInitialized(false) |
|||
{ |
|||
cholmod_start(&m_cholmod); |
|||
} |
|||
|
|||
CholmodBase(const MatrixType& matrix) |
|||
: m_cholmodFactor(0), m_info(Success), m_isInitialized(false) |
|||
{ |
|||
cholmod_start(&m_cholmod); |
|||
compute(matrix); |
|||
} |
|||
|
|||
~CholmodBase() |
|||
{ |
|||
if(m_cholmodFactor) |
|||
cholmod_free_factor(&m_cholmodFactor, &m_cholmod); |
|||
cholmod_finish(&m_cholmod); |
|||
} |
|||
|
|||
inline Index cols() const { return m_cholmodFactor->n; } |
|||
inline Index rows() const { return m_cholmodFactor->n; } |
|||
|
|||
Derived& derived() { return *static_cast<Derived*>(this); } |
|||
const Derived& derived() const { return *static_cast<const Derived*>(this); } |
|||
|
|||
/** \brief Reports whether previous computation was successful. |
|||
* |
|||
* \returns \c Success if computation was succesful, |
|||
* \c NumericalIssue if the matrix.appears to be negative. |
|||
*/ |
|||
ComputationInfo info() const |
|||
{ |
|||
eigen_assert(m_isInitialized && "Decomposition is not initialized."); |
|||
return m_info; |
|||
} |
|||
|
|||
/** Computes the sparse Cholesky decomposition of \a matrix */ |
|||
Derived& compute(const MatrixType& matrix) |
|||
{ |
|||
analyzePattern(matrix); |
|||
factorize(matrix); |
|||
return derived(); |
|||
} |
|||
|
|||
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. |
|||
* |
|||
* \sa compute() |
|||
*/ |
|||
template<typename Rhs> |
|||
inline const internal::solve_retval<CholmodBase, Rhs> |
|||
solve(const MatrixBase<Rhs>& b) const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LLT is not initialized."); |
|||
eigen_assert(rows()==b.rows() |
|||
&& "CholmodDecomposition::solve(): invalid number of rows of the right hand side matrix b"); |
|||
return internal::solve_retval<CholmodBase, Rhs>(*this, b.derived()); |
|||
} |
|||
|
|||
/** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. |
|||
* |
|||
* \sa compute() |
|||
*/ |
|||
template<typename Rhs> |
|||
inline const internal::sparse_solve_retval<CholmodBase, Rhs> |
|||
solve(const SparseMatrixBase<Rhs>& b) const |
|||
{ |
|||
eigen_assert(m_isInitialized && "LLT is not initialized."); |
|||
eigen_assert(rows()==b.rows() |
|||
&& "CholmodDecomposition::solve(): invalid number of rows of the right hand side matrix b"); |
|||
return internal::sparse_solve_retval<CholmodBase, Rhs>(*this, b.derived()); |
|||
} |
|||
|
|||
/** Performs a symbolic decomposition on the sparcity of \a matrix. |
|||
* |
|||
* This function is particularly useful when solving for several problems having the same structure. |
|||
* |
|||
* \sa factorize() |
|||
*/ |
|||
void analyzePattern(const MatrixType& matrix) |
|||
{ |
|||
if(m_cholmodFactor) |
|||
{ |
|||
cholmod_free_factor(&m_cholmodFactor, &m_cholmod); |
|||
m_cholmodFactor = 0; |
|||
} |
|||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>()); |
|||
m_cholmodFactor = cholmod_analyze(&A, &m_cholmod); |
|||
|
|||
this->m_isInitialized = true; |
|||
this->m_info = Success; |
|||
m_analysisIsOk = true; |
|||
m_factorizationIsOk = false; |
|||
} |
|||
|
|||
/** Performs a numeric decomposition of \a matrix |
|||
* |
|||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. |
|||
* |
|||
* \sa analyzePattern() |
|||
*/ |
|||
void factorize(const MatrixType& matrix) |
|||
{ |
|||
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); |
|||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>()); |
|||
cholmod_factorize(&A, m_cholmodFactor, &m_cholmod); |
|||
|
|||
this->m_info = Success; |
|||
m_factorizationIsOk = true; |
|||
} |
|||
|
|||
/** Returns a reference to the Cholmod's configuration structure to get a full control over the performed operations. |
|||
* See the Cholmod user guide for details. */ |
|||
cholmod_common& cholmod() { return m_cholmod; } |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** \internal */ |
|||
template<typename Rhs,typename Dest> |
|||
void _solve(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const |
|||
{ |
|||
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); |
|||
const Index size = m_cholmodFactor->n; |
|||
eigen_assert(size==b.rows()); |
|||
|
|||
// note: cd stands for Cholmod Dense |
|||
cholmod_dense b_cd = viewAsCholmod(b.const_cast_derived()); |
|||
cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod); |
|||
if(!x_cd) |
|||
{ |
|||
this->m_info = NumericalIssue; |
|||
} |
|||
// TODO optimize this copy by swapping when possible (be carreful with alignment, etc.) |
|||
dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols()); |
|||
cholmod_free_dense(&x_cd, &m_cholmod); |
|||
} |
|||
|
|||
/** \internal */ |
|||
template<typename RhsScalar, int RhsOptions, typename RhsIndex, typename DestScalar, int DestOptions, typename DestIndex> |
|||
void _solve(const SparseMatrix<RhsScalar,RhsOptions,RhsIndex> &b, SparseMatrix<DestScalar,DestOptions,DestIndex> &dest) const |
|||
{ |
|||
eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); |
|||
const Index size = m_cholmodFactor->n; |
|||
eigen_assert(size==b.rows()); |
|||
|
|||
// note: cs stands for Cholmod Sparse |
|||
cholmod_sparse b_cs = viewAsCholmod(b); |
|||
cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod); |
|||
if(!x_cs) |
|||
{ |
|||
this->m_info = NumericalIssue; |
|||
} |
|||
// TODO optimize this copy by swapping when possible (be carreful with alignment, etc.) |
|||
dest = viewAsEigen<DestScalar,DestOptions,DestIndex>(*x_cs); |
|||
cholmod_free_sparse(&x_cs, &m_cholmod); |
|||
} |
|||
#endif // EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
template<typename Stream> |
|||
void dumpMemory(Stream& s) |
|||
{} |
|||
|
|||
protected: |
|||
mutable cholmod_common m_cholmod; |
|||
cholmod_factor* m_cholmodFactor; |
|||
mutable ComputationInfo m_info; |
|||
bool m_isInitialized; |
|||
int m_factorizationIsOk; |
|||
int m_analysisIsOk; |
|||
}; |
|||
|
|||
/** \ingroup CholmodSupport_Module |
|||
* \class CholmodSimplicialLLT |
|||
* \brief A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod |
|||
* |
|||
* This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization |
|||
* using the Cholmod library. |
|||
* This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Thefore, it has little practical interest. |
|||
* The sparse matrix A must be selfajoint and positive definite. The vectors or matrices |
|||
* X and B can be either dense or sparse. |
|||
* |
|||
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
|||
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower |
|||
* or Upper. Default is Lower. |
|||
* |
|||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. |
|||
* |
|||
* \sa \ref TutorialSparseDirectSolvers, class CholmodSupernodalLLT, class SimplicialLLT |
|||
*/ |
|||
template<typename _MatrixType, int _UpLo = Lower> |
|||
class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> > |
|||
{ |
|||
typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT> Base; |
|||
using Base::m_cholmod; |
|||
|
|||
public: |
|||
|
|||
typedef _MatrixType MatrixType; |
|||
|
|||
CholmodSimplicialLLT() : Base() { init(); } |
|||
|
|||
CholmodSimplicialLLT(const MatrixType& matrix) : Base() |
|||
{ |
|||
init(); |
|||
compute(matrix); |
|||
} |
|||
|
|||
~CholmodSimplicialLLT() {} |
|||
protected: |
|||
void init() |
|||
{ |
|||
m_cholmod.final_asis = 0; |
|||
m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; |
|||
m_cholmod.final_ll = 1; |
|||
} |
|||
}; |
|||
|
|||
|
|||
/** \ingroup CholmodSupport_Module |
|||
* \class CholmodSimplicialLDLT |
|||
* \brief A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod |
|||
* |
|||
* This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization |
|||
* using the Cholmod library. |
|||
* This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Thefore, it has little practical interest. |
|||
* The sparse matrix A must be selfajoint and positive definite. The vectors or matrices |
|||
* X and B can be either dense or sparse. |
|||
* |
|||
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
|||
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower |
|||
* or Upper. Default is Lower. |
|||
* |
|||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. |
|||
* |
|||
* \sa \ref TutorialSparseDirectSolvers, class CholmodSupernodalLLT, class SimplicialLDLT |
|||
*/ |
|||
template<typename _MatrixType, int _UpLo = Lower> |
|||
class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> > |
|||
{ |
|||
typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT> Base; |
|||
using Base::m_cholmod; |
|||
|
|||
public: |
|||
|
|||
typedef _MatrixType MatrixType; |
|||
|
|||
CholmodSimplicialLDLT() : Base() { init(); } |
|||
|
|||
CholmodSimplicialLDLT(const MatrixType& matrix) : Base() |
|||
{ |
|||
init(); |
|||
compute(matrix); |
|||
} |
|||
|
|||
~CholmodSimplicialLDLT() {} |
|||
protected: |
|||
void init() |
|||
{ |
|||
m_cholmod.final_asis = 1; |
|||
m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; |
|||
} |
|||
}; |
|||
|
|||
/** \ingroup CholmodSupport_Module |
|||
* \class CholmodSupernodalLLT |
|||
* \brief A supernodal Cholesky (LLT) factorization and solver based on Cholmod |
|||
* |
|||
* This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization |
|||
* using the Cholmod library. |
|||
* This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM. |
|||
* The sparse matrix A must be selfajoint and positive definite. The vectors or matrices |
|||
* X and B can be either dense or sparse. |
|||
* |
|||
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
|||
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower |
|||
* or Upper. Default is Lower. |
|||
* |
|||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. |
|||
* |
|||
* \sa \ref TutorialSparseDirectSolvers |
|||
*/ |
|||
template<typename _MatrixType, int _UpLo = Lower> |
|||
class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> > |
|||
{ |
|||
typedef CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT> Base; |
|||
using Base::m_cholmod; |
|||
|
|||
public: |
|||
|
|||
typedef _MatrixType MatrixType; |
|||
|
|||
CholmodSupernodalLLT() : Base() { init(); } |
|||
|
|||
CholmodSupernodalLLT(const MatrixType& matrix) : Base() |
|||
{ |
|||
init(); |
|||
compute(matrix); |
|||
} |
|||
|
|||
~CholmodSupernodalLLT() {} |
|||
protected: |
|||
void init() |
|||
{ |
|||
m_cholmod.final_asis = 1; |
|||
m_cholmod.supernodal = CHOLMOD_SUPERNODAL; |
|||
} |
|||
}; |
|||
|
|||
/** \ingroup CholmodSupport_Module |
|||
* \class CholmodDecomposition |
|||
* \brief A general Cholesky factorization and solver based on Cholmod |
|||
* |
|||
* This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization |
|||
* using the Cholmod library. The sparse matrix A must be selfajoint and positive definite. The vectors or matrices |
|||
* X and B can be either dense or sparse. |
|||
* |
|||
* This variant permits to change the underlying Cholesky method at runtime. |
|||
* On the other hand, it does not provide access to the result of the factorization. |
|||
* The default is to let Cholmod automatically choose between a simplicial and supernodal factorization. |
|||
* |
|||
* \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
|||
* \tparam _UpLo the triangular part that will be used for the computations. It can be Lower |
|||
* or Upper. Default is Lower. |
|||
* |
|||
* This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. |
|||
* |
|||
* \sa \ref TutorialSparseDirectSolvers |
|||
*/ |
|||
template<typename _MatrixType, int _UpLo = Lower> |
|||
class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> > |
|||
{ |
|||
typedef CholmodBase<_MatrixType, _UpLo, CholmodDecomposition> Base; |
|||
using Base::m_cholmod; |
|||
|
|||
public: |
|||
|
|||
typedef _MatrixType MatrixType; |
|||
|
|||
CholmodDecomposition() : Base() { init(); } |
|||
|
|||
CholmodDecomposition(const MatrixType& matrix) : Base() |
|||
{ |
|||
init(); |
|||
compute(matrix); |
|||
} |
|||
|
|||
~CholmodDecomposition() {} |
|||
|
|||
void setMode(CholmodMode mode) |
|||
{ |
|||
switch(mode) |
|||
{ |
|||
case CholmodAuto: |
|||
m_cholmod.final_asis = 1; |
|||
m_cholmod.supernodal = CHOLMOD_AUTO; |
|||
break; |
|||
case CholmodSimplicialLLt: |
|||
m_cholmod.final_asis = 0; |
|||
m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; |
|||
m_cholmod.final_ll = 1; |
|||
break; |
|||
case CholmodSupernodalLLt: |
|||
m_cholmod.final_asis = 1; |
|||
m_cholmod.supernodal = CHOLMOD_SUPERNODAL; |
|||
break; |
|||
case CholmodLDLt: |
|||
m_cholmod.final_asis = 1; |
|||
m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
protected: |
|||
void init() |
|||
{ |
|||
m_cholmod.final_asis = 1; |
|||
m_cholmod.supernodal = CHOLMOD_AUTO; |
|||
} |
|||
}; |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename _MatrixType, int _UpLo, typename Derived, typename Rhs> |
|||
struct solve_retval<CholmodBase<_MatrixType,_UpLo,Derived>, Rhs> |
|||
: solve_retval_base<CholmodBase<_MatrixType,_UpLo,Derived>, Rhs> |
|||
{ |
|||
typedef CholmodBase<_MatrixType,_UpLo,Derived> Dec; |
|||
EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) |
|||
|
|||
template<typename Dest> void evalTo(Dest& dst) const |
|||
{ |
|||
dec()._solve(rhs(),dst); |
|||
} |
|||
}; |
|||
|
|||
template<typename _MatrixType, int _UpLo, typename Derived, typename Rhs> |
|||
struct sparse_solve_retval<CholmodBase<_MatrixType,_UpLo,Derived>, Rhs> |
|||
: sparse_solve_retval_base<CholmodBase<_MatrixType,_UpLo,Derived>, Rhs> |
|||
{ |
|||
typedef CholmodBase<_MatrixType,_UpLo,Derived> Dec; |
|||
EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) |
|||
|
|||
template<typename Dest> void evalTo(Dest& dst) const |
|||
{ |
|||
dec()._solve(rhs(),dst); |
|||
} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_CHOLMODSUPPORT_H |
@ -0,0 +1,308 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_ARRAY_H |
|||
#define EIGEN_ARRAY_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class Array |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief General-purpose arrays with easy API for coefficient-wise operations |
|||
* |
|||
* The %Array class is very similar to the Matrix class. It provides |
|||
* general-purpose one- and two-dimensional arrays. The difference between the |
|||
* %Array and the %Matrix class is primarily in the API: the API for the |
|||
* %Array class provides easy access to coefficient-wise operations, while the |
|||
* API for the %Matrix class provides easy access to linear-algebra |
|||
* operations. |
|||
* |
|||
* This class can be extended with the help of the plugin mechanism described on the page |
|||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_ARRAY_PLUGIN. |
|||
* |
|||
* \sa \ref TutorialArrayClass, \ref TopicClassHierarchy |
|||
*/ |
|||
namespace internal { |
|||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> |
|||
struct traits<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > : traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > |
|||
{ |
|||
typedef ArrayXpr XprKind; |
|||
typedef ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > XprBase; |
|||
}; |
|||
} |
|||
|
|||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> |
|||
class Array |
|||
: public PlainObjectBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > |
|||
{ |
|||
public: |
|||
|
|||
typedef PlainObjectBase<Array> Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Array) |
|||
|
|||
enum { Options = _Options }; |
|||
typedef typename Base::PlainObject PlainObject; |
|||
|
|||
protected: |
|||
template <typename Derived, typename OtherDerived, bool IsVector> |
|||
friend struct internal::conservative_resize_like_impl; |
|||
|
|||
using Base::m_storage; |
|||
|
|||
public: |
|||
|
|||
using Base::base; |
|||
using Base::coeff; |
|||
using Base::coeffRef; |
|||
|
|||
/** |
|||
* The usage of |
|||
* using Base::operator=; |
|||
* fails on MSVC. Since the code below is working with GCC and MSVC, we skipped |
|||
* the usage of 'using'. This should be done only for operator=. |
|||
*/ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Array& operator=(const EigenBase<OtherDerived> &other) |
|||
{ |
|||
return Base::operator=(other); |
|||
} |
|||
|
|||
/** Copies the value of the expression \a other into \c *this with automatic resizing. |
|||
* |
|||
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), |
|||
* it will be initialized. |
|||
* |
|||
* Note that copying a row-vector into a vector (and conversely) is allowed. |
|||
* The resizing, if any, is then done in the appropriate way so that row-vectors |
|||
* remain row-vectors and vectors remain vectors. |
|||
*/ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Array& operator=(const ArrayBase<OtherDerived>& other) |
|||
{ |
|||
return Base::_set(other); |
|||
} |
|||
|
|||
/** This is a special case of the templated operator=. Its purpose is to |
|||
* prevent a default operator= from hiding the templated operator=. |
|||
*/ |
|||
EIGEN_STRONG_INLINE Array& operator=(const Array& other) |
|||
{ |
|||
return Base::_set(other); |
|||
} |
|||
|
|||
/** Default constructor. |
|||
* |
|||
* For fixed-size matrices, does nothing. |
|||
* |
|||
* For dynamic-size matrices, creates an empty matrix of size 0. Does not allocate any array. Such a matrix |
|||
* is called a null matrix. This constructor is the unique way to create null matrices: resizing |
|||
* a matrix to 0 is not supported. |
|||
* |
|||
* \sa resize(Index,Index) |
|||
*/ |
|||
EIGEN_STRONG_INLINE explicit Array() : Base() |
|||
{ |
|||
Base::_check_template_params(); |
|||
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
// FIXME is it still needed ?? |
|||
/** \internal */ |
|||
Array(internal::constructor_without_unaligned_array_assert) |
|||
: Base(internal::constructor_without_unaligned_array_assert()) |
|||
{ |
|||
Base::_check_template_params(); |
|||
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
} |
|||
#endif |
|||
|
|||
/** Constructs a vector or row-vector with given dimension. \only_for_vectors |
|||
* |
|||
* Note that this is only useful for dynamic-size vectors. For fixed-size vectors, |
|||
* it is redundant to pass the dimension here, so it makes more sense to use the default |
|||
* constructor Matrix() instead. |
|||
*/ |
|||
EIGEN_STRONG_INLINE explicit Array(Index dim) |
|||
: Base(dim, RowsAtCompileTime == 1 ? 1 : dim, ColsAtCompileTime == 1 ? 1 : dim) |
|||
{ |
|||
Base::_check_template_params(); |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Array) |
|||
eigen_assert(dim >= 0); |
|||
eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim); |
|||
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
template<typename T0, typename T1> |
|||
EIGEN_STRONG_INLINE Array(const T0& x, const T1& y) |
|||
{ |
|||
Base::_check_template_params(); |
|||
this->template _init2<T0,T1>(x, y); |
|||
} |
|||
#else |
|||
/** constructs an uninitialized matrix with \a rows rows and \a cols columns. |
|||
* |
|||
* This is useful for dynamic-size matrices. For fixed-size matrices, |
|||
* it is redundant to pass these parameters, so one should use the default constructor |
|||
* Matrix() instead. */ |
|||
Array(Index rows, Index cols); |
|||
/** constructs an initialized 2D vector with given coefficients */ |
|||
Array(const Scalar& x, const Scalar& y); |
|||
#endif |
|||
|
|||
/** constructs an initialized 3D vector with given coefficients */ |
|||
EIGEN_STRONG_INLINE Array(const Scalar& x, const Scalar& y, const Scalar& z) |
|||
{ |
|||
Base::_check_template_params(); |
|||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 3) |
|||
m_storage.data()[0] = x; |
|||
m_storage.data()[1] = y; |
|||
m_storage.data()[2] = z; |
|||
} |
|||
/** constructs an initialized 4D vector with given coefficients */ |
|||
EIGEN_STRONG_INLINE Array(const Scalar& x, const Scalar& y, const Scalar& z, const Scalar& w) |
|||
{ |
|||
Base::_check_template_params(); |
|||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Array, 4) |
|||
m_storage.data()[0] = x; |
|||
m_storage.data()[1] = y; |
|||
m_storage.data()[2] = z; |
|||
m_storage.data()[3] = w; |
|||
} |
|||
|
|||
explicit Array(const Scalar *data); |
|||
|
|||
/** Constructor copying the value of the expression \a other */ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Array(const ArrayBase<OtherDerived>& other) |
|||
: Base(other.rows() * other.cols(), other.rows(), other.cols()) |
|||
{ |
|||
Base::_check_template_params(); |
|||
Base::_set_noalias(other); |
|||
} |
|||
/** Copy constructor */ |
|||
EIGEN_STRONG_INLINE Array(const Array& other) |
|||
: Base(other.rows() * other.cols(), other.rows(), other.cols()) |
|||
{ |
|||
Base::_check_template_params(); |
|||
Base::_set_noalias(other); |
|||
} |
|||
/** Copy constructor with in-place evaluation */ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Array(const ReturnByValue<OtherDerived>& other) |
|||
{ |
|||
Base::_check_template_params(); |
|||
Base::resize(other.rows(), other.cols()); |
|||
other.evalTo(*this); |
|||
} |
|||
|
|||
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Array(const EigenBase<OtherDerived> &other) |
|||
: Base(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols()) |
|||
{ |
|||
Base::_check_template_params(); |
|||
Base::resize(other.rows(), other.cols()); |
|||
*this = other; |
|||
} |
|||
|
|||
/** Override MatrixBase::swap() since for dynamic-sized matrices of same type it is enough to swap the |
|||
* data pointers. |
|||
*/ |
|||
template<typename OtherDerived> |
|||
void swap(ArrayBase<OtherDerived> const & other) |
|||
{ this->_swap(other.derived()); } |
|||
|
|||
inline Index innerStride() const { return 1; } |
|||
inline Index outerStride() const { return this->innerSize(); } |
|||
|
|||
#ifdef EIGEN_ARRAY_PLUGIN |
|||
#include EIGEN_ARRAY_PLUGIN |
|||
#endif |
|||
|
|||
private: |
|||
|
|||
template<typename MatrixType, typename OtherDerived, bool SwapPointers> |
|||
friend struct internal::matrix_swap_impl; |
|||
}; |
|||
|
|||
/** \defgroup arraytypedefs Global array typedefs |
|||
* \ingroup Core_Module |
|||
* |
|||
* Eigen defines several typedef shortcuts for most common 1D and 2D array types. |
|||
* |
|||
* The general patterns are the following: |
|||
* |
|||
* \c ArrayRowsColsType where \c Rows and \c Cols can be \c 2,\c 3,\c 4 for fixed size square matrices or \c X for dynamic size, |
|||
* and where \c Type can be \c i for integer, \c f for float, \c d for double, \c cf for complex float, \c cd |
|||
* for complex double. |
|||
* |
|||
* For example, \c Array33d is a fixed-size 3x3 array type of doubles, and \c ArrayXXf is a dynamic-size matrix of floats. |
|||
* |
|||
* There are also \c ArraySizeType which are self-explanatory. For example, \c Array4cf is |
|||
* a fixed-size 1D array of 4 complex floats. |
|||
* |
|||
* \sa class Array |
|||
*/ |
|||
|
|||
#define EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \ |
|||
/** \ingroup arraytypedefs */ \ |
|||
typedef Array<Type, Size, Size> Array##SizeSuffix##SizeSuffix##TypeSuffix; \ |
|||
/** \ingroup arraytypedefs */ \ |
|||
typedef Array<Type, Size, 1> Array##SizeSuffix##TypeSuffix; |
|||
|
|||
#define EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \ |
|||
/** \ingroup arraytypedefs */ \ |
|||
typedef Array<Type, Size, Dynamic> Array##Size##X##TypeSuffix; \ |
|||
/** \ingroup arraytypedefs */ \ |
|||
typedef Array<Type, Dynamic, Size> Array##X##Size##TypeSuffix; |
|||
|
|||
#define EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \ |
|||
EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 2, 2) \ |
|||
EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 3, 3) \ |
|||
EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, 4, 4) \ |
|||
EIGEN_MAKE_ARRAY_TYPEDEFS(Type, TypeSuffix, Dynamic, X) \ |
|||
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \ |
|||
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \ |
|||
EIGEN_MAKE_ARRAY_FIXED_TYPEDEFS(Type, TypeSuffix, 4) |
|||
|
|||
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(int, i) |
|||
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(float, f) |
|||
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(double, d) |
|||
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex<float>, cf) |
|||
EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES(std::complex<double>, cd) |
|||
|
|||
#undef EIGEN_MAKE_ARRAY_TYPEDEFS_ALL_SIZES |
|||
#undef EIGEN_MAKE_ARRAY_TYPEDEFS |
|||
|
|||
#undef EIGEN_MAKE_ARRAY_TYPEDEFS_LARGE |
|||
|
|||
#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \ |
|||
using Eigen::Matrix##SizeSuffix##TypeSuffix; \ |
|||
using Eigen::Vector##SizeSuffix##TypeSuffix; \ |
|||
using Eigen::RowVector##SizeSuffix##TypeSuffix; |
|||
|
|||
#define EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(TypeSuffix) \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \ |
|||
|
|||
#define EIGEN_USING_ARRAY_TYPEDEFS \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(i) \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(f) \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(d) \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cf) \ |
|||
EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cd) |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_ARRAY_H |
@ -0,0 +1,254 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_ARRAYWRAPPER_H |
|||
#define EIGEN_ARRAYWRAPPER_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class ArrayWrapper |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of a mathematical vector or matrix as an array object |
|||
* |
|||
* This class is the return type of MatrixBase::array(), and most of the time |
|||
* this is the only way it is use. |
|||
* |
|||
* \sa MatrixBase::array(), class MatrixWrapper |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename ExpressionType> |
|||
struct traits<ArrayWrapper<ExpressionType> > |
|||
: public traits<typename remove_all<typename ExpressionType::Nested>::type > |
|||
{ |
|||
typedef ArrayXpr XprKind; |
|||
}; |
|||
} |
|||
|
|||
template<typename ExpressionType> |
|||
class ArrayWrapper : public ArrayBase<ArrayWrapper<ExpressionType> > |
|||
{ |
|||
public: |
|||
typedef ArrayBase<ArrayWrapper> Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(ArrayWrapper) |
|||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(ArrayWrapper) |
|||
|
|||
typedef typename internal::conditional< |
|||
internal::is_lvalue<ExpressionType>::value, |
|||
Scalar, |
|||
const Scalar |
|||
>::type ScalarWithConstIfNotLvalue; |
|||
|
|||
typedef typename internal::nested<ExpressionType>::type NestedExpressionType; |
|||
|
|||
inline ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {} |
|||
|
|||
inline Index rows() const { return m_expression.rows(); } |
|||
inline Index cols() const { return m_expression.cols(); } |
|||
inline Index outerStride() const { return m_expression.outerStride(); } |
|||
inline Index innerStride() const { return m_expression.innerStride(); } |
|||
|
|||
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); } |
|||
inline const Scalar* data() const { return m_expression.data(); } |
|||
|
|||
inline CoeffReturnType coeff(Index row, Index col) const |
|||
{ |
|||
return m_expression.coeff(row, col); |
|||
} |
|||
|
|||
inline Scalar& coeffRef(Index row, Index col) |
|||
{ |
|||
return m_expression.const_cast_derived().coeffRef(row, col); |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index row, Index col) const |
|||
{ |
|||
return m_expression.const_cast_derived().coeffRef(row, col); |
|||
} |
|||
|
|||
inline CoeffReturnType coeff(Index index) const |
|||
{ |
|||
return m_expression.coeff(index); |
|||
} |
|||
|
|||
inline Scalar& coeffRef(Index index) |
|||
{ |
|||
return m_expression.const_cast_derived().coeffRef(index); |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index index) const |
|||
{ |
|||
return m_expression.const_cast_derived().coeffRef(index); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline const PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
return m_expression.template packet<LoadMode>(row, col); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline void writePacket(Index row, Index col, const PacketScalar& x) |
|||
{ |
|||
m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline const PacketScalar packet(Index index) const |
|||
{ |
|||
return m_expression.template packet<LoadMode>(index); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline void writePacket(Index index, const PacketScalar& x) |
|||
{ |
|||
m_expression.const_cast_derived().template writePacket<LoadMode>(index, x); |
|||
} |
|||
|
|||
template<typename Dest> |
|||
inline void evalTo(Dest& dst) const { dst = m_expression; } |
|||
|
|||
const typename internal::remove_all<NestedExpressionType>::type& |
|||
nestedExpression() const |
|||
{ |
|||
return m_expression; |
|||
} |
|||
|
|||
/** Forwards the resizing request to the nested expression |
|||
* \sa DenseBase::resize(Index) */ |
|||
void resize(Index newSize) { m_expression.const_cast_derived().resize(newSize); } |
|||
/** Forwards the resizing request to the nested expression |
|||
* \sa DenseBase::resize(Index,Index)*/ |
|||
void resize(Index nbRows, Index nbCols) { m_expression.const_cast_derived().resize(nbRows,nbCols); } |
|||
|
|||
protected: |
|||
NestedExpressionType m_expression; |
|||
}; |
|||
|
|||
/** \class MatrixWrapper |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of an array as a mathematical vector or matrix |
|||
* |
|||
* This class is the return type of ArrayBase::matrix(), and most of the time |
|||
* this is the only way it is use. |
|||
* |
|||
* \sa MatrixBase::matrix(), class ArrayWrapper |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename ExpressionType> |
|||
struct traits<MatrixWrapper<ExpressionType> > |
|||
: public traits<typename remove_all<typename ExpressionType::Nested>::type > |
|||
{ |
|||
typedef MatrixXpr XprKind; |
|||
}; |
|||
} |
|||
|
|||
template<typename ExpressionType> |
|||
class MatrixWrapper : public MatrixBase<MatrixWrapper<ExpressionType> > |
|||
{ |
|||
public: |
|||
typedef MatrixBase<MatrixWrapper<ExpressionType> > Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(MatrixWrapper) |
|||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(MatrixWrapper) |
|||
|
|||
typedef typename internal::conditional< |
|||
internal::is_lvalue<ExpressionType>::value, |
|||
Scalar, |
|||
const Scalar |
|||
>::type ScalarWithConstIfNotLvalue; |
|||
|
|||
typedef typename internal::nested<ExpressionType>::type NestedExpressionType; |
|||
|
|||
inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {} |
|||
|
|||
inline Index rows() const { return m_expression.rows(); } |
|||
inline Index cols() const { return m_expression.cols(); } |
|||
inline Index outerStride() const { return m_expression.outerStride(); } |
|||
inline Index innerStride() const { return m_expression.innerStride(); } |
|||
|
|||
inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); } |
|||
inline const Scalar* data() const { return m_expression.data(); } |
|||
|
|||
inline CoeffReturnType coeff(Index row, Index col) const |
|||
{ |
|||
return m_expression.coeff(row, col); |
|||
} |
|||
|
|||
inline Scalar& coeffRef(Index row, Index col) |
|||
{ |
|||
return m_expression.const_cast_derived().coeffRef(row, col); |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index row, Index col) const |
|||
{ |
|||
return m_expression.derived().coeffRef(row, col); |
|||
} |
|||
|
|||
inline CoeffReturnType coeff(Index index) const |
|||
{ |
|||
return m_expression.coeff(index); |
|||
} |
|||
|
|||
inline Scalar& coeffRef(Index index) |
|||
{ |
|||
return m_expression.const_cast_derived().coeffRef(index); |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index index) const |
|||
{ |
|||
return m_expression.const_cast_derived().coeffRef(index); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline const PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
return m_expression.template packet<LoadMode>(row, col); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline void writePacket(Index row, Index col, const PacketScalar& x) |
|||
{ |
|||
m_expression.const_cast_derived().template writePacket<LoadMode>(row, col, x); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline const PacketScalar packet(Index index) const |
|||
{ |
|||
return m_expression.template packet<LoadMode>(index); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline void writePacket(Index index, const PacketScalar& x) |
|||
{ |
|||
m_expression.const_cast_derived().template writePacket<LoadMode>(index, x); |
|||
} |
|||
|
|||
const typename internal::remove_all<NestedExpressionType>::type& |
|||
nestedExpression() const |
|||
{ |
|||
return m_expression; |
|||
} |
|||
|
|||
/** Forwards the resizing request to the nested expression |
|||
* \sa DenseBase::resize(Index) */ |
|||
void resize(Index newSize) { m_expression.const_cast_derived().resize(newSize); } |
|||
/** Forwards the resizing request to the nested expression |
|||
* \sa DenseBase::resize(Index,Index)*/ |
|||
void resize(Index nbRows, Index nbCols) { m_expression.const_cast_derived().resize(nbRows,nbCols); } |
|||
|
|||
protected: |
|||
NestedExpressionType m_expression; |
|||
}; |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_ARRAYWRAPPER_H |
@ -0,0 +1,224 @@ |
|||
/* |
|||
Copyright (c) 2011, Intel Corporation. All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without modification, |
|||
are permitted provided that the following conditions are met: |
|||
|
|||
* Redistributions of source code must retain the above copyright notice, this |
|||
list of conditions and the following disclaimer. |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
this list of conditions and the following disclaimer in the documentation |
|||
and/or other materials provided with the distribution. |
|||
* Neither the name of Intel Corporation nor the names of its contributors may |
|||
be used to endorse or promote products derived from this software without |
|||
specific prior written permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
|||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
|||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
******************************************************************************** |
|||
* Content : Eigen bindings to Intel(R) MKL |
|||
* MKL VML support for coefficient-wise unary Eigen expressions like a=b.sin() |
|||
******************************************************************************** |
|||
*/ |
|||
|
|||
#ifndef EIGEN_ASSIGN_VML_H |
|||
#define EIGEN_ASSIGN_VML_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename Op> struct vml_call |
|||
{ enum { IsSupported = 0 }; }; |
|||
|
|||
template<typename Dst, typename Src, typename UnaryOp> |
|||
class vml_assign_traits |
|||
{ |
|||
private: |
|||
enum { |
|||
DstHasDirectAccess = Dst::Flags & DirectAccessBit, |
|||
SrcHasDirectAccess = Src::Flags & DirectAccessBit, |
|||
|
|||
StorageOrdersAgree = (int(Dst::IsRowMajor) == int(Src::IsRowMajor)), |
|||
InnerSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::SizeAtCompileTime) |
|||
: int(Dst::Flags)&RowMajorBit ? int(Dst::ColsAtCompileTime) |
|||
: int(Dst::RowsAtCompileTime), |
|||
InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime) |
|||
: int(Dst::Flags)&RowMajorBit ? int(Dst::MaxColsAtCompileTime) |
|||
: int(Dst::MaxRowsAtCompileTime), |
|||
MaxSizeAtCompileTime = Dst::SizeAtCompileTime, |
|||
|
|||
MightEnableVml = vml_call<UnaryOp>::IsSupported && StorageOrdersAgree && DstHasDirectAccess && SrcHasDirectAccess |
|||
&& Src::InnerStrideAtCompileTime==1 && Dst::InnerStrideAtCompileTime==1, |
|||
MightLinearize = MightEnableVml && (int(Dst::Flags) & int(Src::Flags) & LinearAccessBit), |
|||
VmlSize = MightLinearize ? MaxSizeAtCompileTime : InnerMaxSize, |
|||
LargeEnough = VmlSize==Dynamic || VmlSize>=EIGEN_MKL_VML_THRESHOLD, |
|||
MayEnableVml = MightEnableVml && LargeEnough, |
|||
MayLinearize = MayEnableVml && MightLinearize |
|||
}; |
|||
public: |
|||
enum { |
|||
Traversal = MayLinearize ? LinearVectorizedTraversal |
|||
: MayEnableVml ? InnerVectorizedTraversal |
|||
: DefaultTraversal |
|||
}; |
|||
}; |
|||
|
|||
template<typename Derived1, typename Derived2, typename UnaryOp, int Traversal, int Unrolling, |
|||
int VmlTraversal = vml_assign_traits<Derived1, Derived2, UnaryOp>::Traversal > |
|||
struct vml_assign_impl |
|||
: assign_impl<Derived1, Eigen::CwiseUnaryOp<UnaryOp, Derived2>,Traversal,Unrolling,BuiltIn> |
|||
{ |
|||
}; |
|||
|
|||
template<typename Derived1, typename Derived2, typename UnaryOp, int Traversal, int Unrolling> |
|||
struct vml_assign_impl<Derived1, Derived2, UnaryOp, Traversal, Unrolling, InnerVectorizedTraversal> |
|||
{ |
|||
typedef typename Derived1::Scalar Scalar; |
|||
typedef typename Derived1::Index Index; |
|||
static inline void run(Derived1& dst, const CwiseUnaryOp<UnaryOp, Derived2>& src) |
|||
{ |
|||
// in case we want to (or have to) skip VML at runtime we can call: |
|||
// assign_impl<Derived1,Eigen::CwiseUnaryOp<UnaryOp, Derived2>,Traversal,Unrolling,BuiltIn>::run(dst,src); |
|||
const Index innerSize = dst.innerSize(); |
|||
const Index outerSize = dst.outerSize(); |
|||
for(Index outer = 0; outer < outerSize; ++outer) { |
|||
const Scalar *src_ptr = src.IsRowMajor ? &(src.nestedExpression().coeffRef(outer,0)) : |
|||
&(src.nestedExpression().coeffRef(0, outer)); |
|||
Scalar *dst_ptr = dst.IsRowMajor ? &(dst.coeffRef(outer,0)) : &(dst.coeffRef(0, outer)); |
|||
vml_call<UnaryOp>::run(src.functor(), innerSize, src_ptr, dst_ptr ); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived1, typename Derived2, typename UnaryOp, int Traversal, int Unrolling> |
|||
struct vml_assign_impl<Derived1, Derived2, UnaryOp, Traversal, Unrolling, LinearVectorizedTraversal> |
|||
{ |
|||
static inline void run(Derived1& dst, const CwiseUnaryOp<UnaryOp, Derived2>& src) |
|||
{ |
|||
// in case we want to (or have to) skip VML at runtime we can call: |
|||
// assign_impl<Derived1,Eigen::CwiseUnaryOp<UnaryOp, Derived2>,Traversal,Unrolling,BuiltIn>::run(dst,src); |
|||
vml_call<UnaryOp>::run(src.functor(), dst.size(), src.nestedExpression().data(), dst.data() ); |
|||
} |
|||
}; |
|||
|
|||
// Macroses |
|||
|
|||
#define EIGEN_MKL_VML_SPECIALIZE_ASSIGN(TRAVERSAL,UNROLLING) \ |
|||
template<typename Derived1, typename Derived2, typename UnaryOp> \ |
|||
struct assign_impl<Derived1, Eigen::CwiseUnaryOp<UnaryOp, Derived2>, TRAVERSAL, UNROLLING, Specialized> { \ |
|||
static inline void run(Derived1 &dst, const Eigen::CwiseUnaryOp<UnaryOp, Derived2> &src) { \ |
|||
vml_assign_impl<Derived1,Derived2,UnaryOp,TRAVERSAL,UNROLLING>::run(dst, src); \ |
|||
} \ |
|||
}; |
|||
|
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(DefaultTraversal,NoUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(DefaultTraversal,CompleteUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(DefaultTraversal,InnerUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(LinearTraversal,NoUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(LinearTraversal,CompleteUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(InnerVectorizedTraversal,NoUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(InnerVectorizedTraversal,CompleteUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(InnerVectorizedTraversal,InnerUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(LinearVectorizedTraversal,CompleteUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(LinearVectorizedTraversal,NoUnrolling) |
|||
EIGEN_MKL_VML_SPECIALIZE_ASSIGN(SliceVectorizedTraversal,NoUnrolling) |
|||
|
|||
|
|||
#if !defined (EIGEN_FAST_MATH) || (EIGEN_FAST_MATH != 1) |
|||
#define EIGEN_MKL_VML_MODE VML_HA |
|||
#else |
|||
#define EIGEN_MKL_VML_MODE VML_LA |
|||
#endif |
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE) \ |
|||
template<> struct vml_call< scalar_##EIGENOP##_op<EIGENTYPE> > { \ |
|||
enum { IsSupported = 1 }; \ |
|||
static inline void run( const scalar_##EIGENOP##_op<EIGENTYPE>& /*func*/, \ |
|||
int size, const EIGENTYPE* src, EIGENTYPE* dst) { \ |
|||
VMLOP(size, (const VMLTYPE*)src, (VMLTYPE*)dst); \ |
|||
} \ |
|||
}; |
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE) \ |
|||
template<> struct vml_call< scalar_##EIGENOP##_op<EIGENTYPE> > { \ |
|||
enum { IsSupported = 1 }; \ |
|||
static inline void run( const scalar_##EIGENOP##_op<EIGENTYPE>& /*func*/, \ |
|||
int size, const EIGENTYPE* src, EIGENTYPE* dst) { \ |
|||
MKL_INT64 vmlMode = EIGEN_MKL_VML_MODE; \ |
|||
VMLOP(size, (const VMLTYPE*)src, (VMLTYPE*)dst, vmlMode); \ |
|||
} \ |
|||
}; |
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_POW_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE) \ |
|||
template<> struct vml_call< scalar_##EIGENOP##_op<EIGENTYPE> > { \ |
|||
enum { IsSupported = 1 }; \ |
|||
static inline void run( const scalar_##EIGENOP##_op<EIGENTYPE>& func, \ |
|||
int size, const EIGENTYPE* src, EIGENTYPE* dst) { \ |
|||
EIGENTYPE exponent = func.m_exponent; \ |
|||
MKL_INT64 vmlMode = EIGEN_MKL_VML_MODE; \ |
|||
VMLOP(&size, (const VMLTYPE*)src, (const VMLTYPE*)&exponent, \ |
|||
(VMLTYPE*)dst, &vmlMode); \ |
|||
} \ |
|||
}; |
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(EIGENOP, VMLOP) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, vs##VMLOP, float, float) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, vd##VMLOP, double, double) |
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX(EIGENOP, VMLOP) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, vc##VMLOP, scomplex, MKL_Complex8) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, vz##VMLOP, dcomplex, MKL_Complex16) |
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS(EIGENOP, VMLOP) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(EIGENOP, VMLOP) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX(EIGENOP, VMLOP) |
|||
|
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL_LA(EIGENOP, VMLOP) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, vms##VMLOP, float, float) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, vmd##VMLOP, double, double) |
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX_LA(EIGENOP, VMLOP) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, vmc##VMLOP, scomplex, MKL_Complex8) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, vmz##VMLOP, dcomplex, MKL_Complex16) |
|||
|
|||
#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(EIGENOP, VMLOP) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL_LA(EIGENOP, VMLOP) \ |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX_LA(EIGENOP, VMLOP) |
|||
|
|||
|
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(sin, Sin) |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(asin, Asin) |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(cos, Cos) |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(acos, Acos) |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(tan, Tan) |
|||
//EIGEN_MKL_VML_DECLARE_UNARY_CALLS(abs, Abs) |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(exp, Exp) |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(log, Ln) |
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(sqrt, Sqrt) |
|||
|
|||
EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(square, Sqr) |
|||
|
|||
// The vm*powx functions are not avaibale in the windows version of MKL. |
|||
#ifdef _WIN32 |
|||
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmspowx_, float, float) |
|||
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmdpowx_, double, double) |
|||
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmcpowx_, scomplex, MKL_Complex8) |
|||
EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmzpowx_, dcomplex, MKL_Complex16) |
|||
#endif |
|||
|
|||
} // end namespace internal |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_ASSIGN_VML_H |
@ -0,0 +1,357 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_BLOCK_H |
|||
#define EIGEN_BLOCK_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class Block |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of a fixed-size or dynamic-size block |
|||
* |
|||
* \param XprType the type of the expression in which we are taking a block |
|||
* \param BlockRows the number of rows of the block we are taking at compile time (optional) |
|||
* \param BlockCols the number of columns of the block we are taking at compile time (optional) |
|||
* \param _DirectAccessStatus \internal used for partial specialization |
|||
* |
|||
* This class represents an expression of either a fixed-size or dynamic-size block. It is the return |
|||
* type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and |
|||
* most of the time this is the only way it is used. |
|||
* |
|||
* However, if you want to directly maniputate block expressions, |
|||
* for instance if you want to write a function returning such an expression, you |
|||
* will need to use this class. |
|||
* |
|||
* Here is an example illustrating the dynamic case: |
|||
* \include class_Block.cpp |
|||
* Output: \verbinclude class_Block.out |
|||
* |
|||
* \note Even though this expression has dynamic size, in the case where \a XprType |
|||
* has fixed size, this expression inherits a fixed maximal size which means that evaluating |
|||
* it does not cause a dynamic memory allocation. |
|||
* |
|||
* Here is an example illustrating the fixed-size case: |
|||
* \include class_FixedBlock.cpp |
|||
* Output: \verbinclude class_FixedBlock.out |
|||
* |
|||
* \sa DenseBase::block(Index,Index,Index,Index), DenseBase::block(Index,Index), class VectorBlock |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> |
|||
struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType> |
|||
{ |
|||
typedef typename traits<XprType>::Scalar Scalar; |
|||
typedef typename traits<XprType>::StorageKind StorageKind; |
|||
typedef typename traits<XprType>::XprKind XprKind; |
|||
typedef typename nested<XprType>::type XprTypeNested; |
|||
typedef typename remove_reference<XprTypeNested>::type _XprTypeNested; |
|||
enum{ |
|||
MatrixRows = traits<XprType>::RowsAtCompileTime, |
|||
MatrixCols = traits<XprType>::ColsAtCompileTime, |
|||
RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows, |
|||
ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols, |
|||
MaxRowsAtCompileTime = BlockRows==0 ? 0 |
|||
: RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime) |
|||
: int(traits<XprType>::MaxRowsAtCompileTime), |
|||
MaxColsAtCompileTime = BlockCols==0 ? 0 |
|||
: ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime) |
|||
: int(traits<XprType>::MaxColsAtCompileTime), |
|||
XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0, |
|||
IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1 |
|||
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0 |
|||
: XprTypeIsRowMajor, |
|||
HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor), |
|||
InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime), |
|||
InnerStrideAtCompileTime = HasSameStorageOrderAsXprType |
|||
? int(inner_stride_at_compile_time<XprType>::ret) |
|||
: int(outer_stride_at_compile_time<XprType>::ret), |
|||
OuterStrideAtCompileTime = HasSameStorageOrderAsXprType |
|||
? int(outer_stride_at_compile_time<XprType>::ret) |
|||
: int(inner_stride_at_compile_time<XprType>::ret), |
|||
MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0) |
|||
&& (InnerStrideAtCompileTime == 1) |
|||
? PacketAccessBit : 0, |
|||
MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0, |
|||
FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0, |
|||
FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0, |
|||
FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, |
|||
Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) | |
|||
DirectAccessBit | |
|||
MaskPacketAccessBit | |
|||
MaskAlignedBit), |
|||
Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block |
|||
: public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type |
|||
{ |
|||
public: |
|||
|
|||
typedef typename internal::dense_xpr_base<Block>::type Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Block) |
|||
|
|||
class InnerIterator; |
|||
|
|||
/** Column or Row constructor |
|||
*/ |
|||
inline Block(XprType& xpr, Index i) |
|||
: m_xpr(xpr), |
|||
// It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime, |
|||
// and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1, |
|||
// all other cases are invalid. |
|||
// The case a 1x1 matrix seems ambiguous, but the result is the same anyway. |
|||
m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0), |
|||
m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0), |
|||
m_blockRows(BlockRows==1 ? 1 : xpr.rows()), |
|||
m_blockCols(BlockCols==1 ? 1 : xpr.cols()) |
|||
{ |
|||
eigen_assert( (i>=0) && ( |
|||
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows()) |
|||
||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols()))); |
|||
} |
|||
|
|||
/** Fixed-size constructor |
|||
*/ |
|||
inline Block(XprType& xpr, Index startRow, Index startCol) |
|||
: m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), |
|||
m_blockRows(BlockRows), m_blockCols(BlockCols) |
|||
{ |
|||
EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) |
|||
eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows() |
|||
&& startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols()); |
|||
} |
|||
|
|||
/** Dynamic-size constructor |
|||
*/ |
|||
inline Block(XprType& xpr, |
|||
Index startRow, Index startCol, |
|||
Index blockRows, Index blockCols) |
|||
: m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), |
|||
m_blockRows(blockRows), m_blockCols(blockCols) |
|||
{ |
|||
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) |
|||
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); |
|||
eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows() |
|||
&& startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols()); |
|||
} |
|||
|
|||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) |
|||
|
|||
inline Index rows() const { return m_blockRows.value(); } |
|||
inline Index cols() const { return m_blockCols.value(); } |
|||
|
|||
inline Scalar& coeffRef(Index row, Index col) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_LVALUE(XprType) |
|||
return m_xpr.const_cast_derived() |
|||
.coeffRef(row + m_startRow.value(), col + m_startCol.value()); |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index row, Index col) const |
|||
{ |
|||
return m_xpr.derived() |
|||
.coeffRef(row + m_startRow.value(), col + m_startCol.value()); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const |
|||
{ |
|||
return m_xpr.coeff(row + m_startRow.value(), col + m_startCol.value()); |
|||
} |
|||
|
|||
inline Scalar& coeffRef(Index index) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_LVALUE(XprType) |
|||
return m_xpr.const_cast_derived() |
|||
.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
|||
m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index index) const |
|||
{ |
|||
return m_xpr.const_cast_derived() |
|||
.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
|||
m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
|||
} |
|||
|
|||
inline const CoeffReturnType coeff(Index index) const |
|||
{ |
|||
return m_xpr |
|||
.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
|||
m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
return m_xpr.template packet<Unaligned> |
|||
(row + m_startRow.value(), col + m_startCol.value()); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline void writePacket(Index row, Index col, const PacketScalar& x) |
|||
{ |
|||
m_xpr.const_cast_derived().template writePacket<Unaligned> |
|||
(row + m_startRow.value(), col + m_startCol.value(), x); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline PacketScalar packet(Index index) const |
|||
{ |
|||
return m_xpr.template packet<Unaligned> |
|||
(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
|||
m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline void writePacket(Index index, const PacketScalar& x) |
|||
{ |
|||
m_xpr.const_cast_derived().template writePacket<Unaligned> |
|||
(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
|||
m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x); |
|||
} |
|||
|
|||
#ifdef EIGEN_PARSED_BY_DOXYGEN |
|||
/** \sa MapBase::data() */ |
|||
inline const Scalar* data() const; |
|||
inline Index innerStride() const; |
|||
inline Index outerStride() const; |
|||
#endif |
|||
|
|||
const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const |
|||
{ |
|||
return m_xpr; |
|||
} |
|||
|
|||
Index startRow() const |
|||
{ |
|||
return m_startRow.value(); |
|||
} |
|||
|
|||
Index startCol() const |
|||
{ |
|||
return m_startCol.value(); |
|||
} |
|||
|
|||
protected: |
|||
|
|||
const typename XprType::Nested m_xpr; |
|||
const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow; |
|||
const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol; |
|||
const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows; |
|||
const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols; |
|||
}; |
|||
|
|||
/** \internal */ |
|||
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> |
|||
class Block<XprType,BlockRows,BlockCols, InnerPanel,true> |
|||
: public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> > |
|||
{ |
|||
public: |
|||
|
|||
typedef MapBase<Block> Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Block) |
|||
|
|||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) |
|||
|
|||
/** Column or Row constructor |
|||
*/ |
|||
inline Block(XprType& xpr, Index i) |
|||
: Base(internal::const_cast_ptr(&xpr.coeffRef( |
|||
(BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0, |
|||
(BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)), |
|||
BlockRows==1 ? 1 : xpr.rows(), |
|||
BlockCols==1 ? 1 : xpr.cols()), |
|||
m_xpr(xpr) |
|||
{ |
|||
eigen_assert( (i>=0) && ( |
|||
((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows()) |
|||
||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols()))); |
|||
init(); |
|||
} |
|||
|
|||
/** Fixed-size constructor |
|||
*/ |
|||
inline Block(XprType& xpr, Index startRow, Index startCol) |
|||
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr) |
|||
{ |
|||
eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows() |
|||
&& startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols()); |
|||
init(); |
|||
} |
|||
|
|||
/** Dynamic-size constructor |
|||
*/ |
|||
inline Block(XprType& xpr, |
|||
Index startRow, Index startCol, |
|||
Index blockRows, Index blockCols) |
|||
: Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols), |
|||
m_xpr(xpr) |
|||
{ |
|||
eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) |
|||
&& (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); |
|||
eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows() |
|||
&& startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols()); |
|||
init(); |
|||
} |
|||
|
|||
const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const |
|||
{ |
|||
return m_xpr; |
|||
} |
|||
|
|||
/** \sa MapBase::innerStride() */ |
|||
inline Index innerStride() const |
|||
{ |
|||
return internal::traits<Block>::HasSameStorageOrderAsXprType |
|||
? m_xpr.innerStride() |
|||
: m_xpr.outerStride(); |
|||
} |
|||
|
|||
/** \sa MapBase::outerStride() */ |
|||
inline Index outerStride() const |
|||
{ |
|||
return m_outerStride; |
|||
} |
|||
|
|||
#ifndef __SUNPRO_CC |
|||
// FIXME sunstudio is not friendly with the above friend... |
|||
// META-FIXME there is no 'friend' keyword around here. Is this obsolete? |
|||
protected: |
|||
#endif |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** \internal used by allowAligned() */ |
|||
inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols) |
|||
: Base(data, blockRows, blockCols), m_xpr(xpr) |
|||
{ |
|||
init(); |
|||
} |
|||
#endif |
|||
|
|||
protected: |
|||
void init() |
|||
{ |
|||
m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType |
|||
? m_xpr.outerStride() |
|||
: m_xpr.innerStride(); |
|||
} |
|||
|
|||
typename XprType::Nested m_xpr; |
|||
Index m_outerStride; |
|||
}; |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_BLOCK_H |
@ -0,0 +1,141 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_COMMAINITIALIZER_H |
|||
#define EIGEN_COMMAINITIALIZER_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class CommaInitializer |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Helper class used by the comma initializer operator |
|||
* |
|||
* This class is internally used to implement the comma initializer feature. It is |
|||
* the return type of MatrixBase::operator<<, and most of the time this is the only |
|||
* way it is used. |
|||
* |
|||
* \sa \ref MatrixBaseCommaInitRef "MatrixBase::operator<<", CommaInitializer::finished() |
|||
*/ |
|||
template<typename XprType> |
|||
struct CommaInitializer |
|||
{ |
|||
typedef typename XprType::Scalar Scalar; |
|||
typedef typename XprType::Index Index; |
|||
|
|||
inline CommaInitializer(XprType& xpr, const Scalar& s) |
|||
: m_xpr(xpr), m_row(0), m_col(1), m_currentBlockRows(1) |
|||
{ |
|||
m_xpr.coeffRef(0,0) = s; |
|||
} |
|||
|
|||
template<typename OtherDerived> |
|||
inline CommaInitializer(XprType& xpr, const DenseBase<OtherDerived>& other) |
|||
: m_xpr(xpr), m_row(0), m_col(other.cols()), m_currentBlockRows(other.rows()) |
|||
{ |
|||
m_xpr.block(0, 0, other.rows(), other.cols()) = other; |
|||
} |
|||
|
|||
/* inserts a scalar value in the target matrix */ |
|||
CommaInitializer& operator,(const Scalar& s) |
|||
{ |
|||
if (m_col==m_xpr.cols()) |
|||
{ |
|||
m_row+=m_currentBlockRows; |
|||
m_col = 0; |
|||
m_currentBlockRows = 1; |
|||
eigen_assert(m_row<m_xpr.rows() |
|||
&& "Too many rows passed to comma initializer (operator<<)"); |
|||
} |
|||
eigen_assert(m_col<m_xpr.cols() |
|||
&& "Too many coefficients passed to comma initializer (operator<<)"); |
|||
eigen_assert(m_currentBlockRows==1); |
|||
m_xpr.coeffRef(m_row, m_col++) = s; |
|||
return *this; |
|||
} |
|||
|
|||
/* inserts a matrix expression in the target matrix */ |
|||
template<typename OtherDerived> |
|||
CommaInitializer& operator,(const DenseBase<OtherDerived>& other) |
|||
{ |
|||
if(other.cols()==0 || other.rows()==0) |
|||
return *this; |
|||
if (m_col==m_xpr.cols()) |
|||
{ |
|||
m_row+=m_currentBlockRows; |
|||
m_col = 0; |
|||
m_currentBlockRows = other.rows(); |
|||
eigen_assert(m_row+m_currentBlockRows<=m_xpr.rows() |
|||
&& "Too many rows passed to comma initializer (operator<<)"); |
|||
} |
|||
eigen_assert(m_col<m_xpr.cols() |
|||
&& "Too many coefficients passed to comma initializer (operator<<)"); |
|||
eigen_assert(m_currentBlockRows==other.rows()); |
|||
if (OtherDerived::SizeAtCompileTime != Dynamic) |
|||
m_xpr.template block<OtherDerived::RowsAtCompileTime != Dynamic ? OtherDerived::RowsAtCompileTime : 1, |
|||
OtherDerived::ColsAtCompileTime != Dynamic ? OtherDerived::ColsAtCompileTime : 1> |
|||
(m_row, m_col) = other; |
|||
else |
|||
m_xpr.block(m_row, m_col, other.rows(), other.cols()) = other; |
|||
m_col += other.cols(); |
|||
return *this; |
|||
} |
|||
|
|||
inline ~CommaInitializer() |
|||
{ |
|||
eigen_assert((m_row+m_currentBlockRows) == m_xpr.rows() |
|||
&& m_col == m_xpr.cols() |
|||
&& "Too few coefficients passed to comma initializer (operator<<)"); |
|||
} |
|||
|
|||
/** \returns the built matrix once all its coefficients have been set. |
|||
* Calling finished is 100% optional. Its purpose is to write expressions |
|||
* like this: |
|||
* \code |
|||
* quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished()); |
|||
* \endcode |
|||
*/ |
|||
inline XprType& finished() { return m_xpr; } |
|||
|
|||
XprType& m_xpr; // target expression |
|||
Index m_row; // current row id |
|||
Index m_col; // current col id |
|||
Index m_currentBlockRows; // current block height |
|||
}; |
|||
|
|||
/** \anchor MatrixBaseCommaInitRef |
|||
* Convenient operator to set the coefficients of a matrix. |
|||
* |
|||
* The coefficients must be provided in a row major order and exactly match |
|||
* the size of the matrix. Otherwise an assertion is raised. |
|||
* |
|||
* Example: \include MatrixBase_set.cpp |
|||
* Output: \verbinclude MatrixBase_set.out |
|||
* |
|||
* \sa CommaInitializer::finished(), class CommaInitializer |
|||
*/ |
|||
template<typename Derived> |
|||
inline CommaInitializer<Derived> DenseBase<Derived>::operator<< (const Scalar& s) |
|||
{ |
|||
return CommaInitializer<Derived>(*static_cast<Derived*>(this), s); |
|||
} |
|||
|
|||
/** \sa operator<<(const Scalar&) */ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
inline CommaInitializer<Derived> |
|||
DenseBase<Derived>::operator<<(const DenseBase<OtherDerived>& other) |
|||
{ |
|||
return CommaInitializer<Derived>(*static_cast<Derived *>(this), other); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_COMMAINITIALIZER_H |
@ -0,0 +1,229 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_CWISE_BINARY_OP_H |
|||
#define EIGEN_CWISE_BINARY_OP_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class CwiseBinaryOp |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Generic expression where a coefficient-wise binary operator is applied to two expressions |
|||
* |
|||
* \param BinaryOp template functor implementing the operator |
|||
* \param Lhs the type of the left-hand side |
|||
* \param Rhs the type of the right-hand side |
|||
* |
|||
* This class represents an expression where a coefficient-wise binary operator is applied to two expressions. |
|||
* It is the return type of binary operators, by which we mean only those binary operators where |
|||
* both the left-hand side and the right-hand side are Eigen expressions. |
|||
* For example, the return type of matrix1+matrix2 is a CwiseBinaryOp. |
|||
* |
|||
* Most of the time, this is the only way that it is used, so you typically don't have to name |
|||
* CwiseBinaryOp types explicitly. |
|||
* |
|||
* \sa MatrixBase::binaryExpr(const MatrixBase<OtherDerived> &,const CustomBinaryOp &) const, class CwiseUnaryOp, class CwiseNullaryOp |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename BinaryOp, typename Lhs, typename Rhs> |
|||
struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > |
|||
{ |
|||
// we must not inherit from traits<Lhs> since it has |
|||
// the potential to cause problems with MSVC |
|||
typedef typename remove_all<Lhs>::type Ancestor; |
|||
typedef typename traits<Ancestor>::XprKind XprKind; |
|||
enum { |
|||
RowsAtCompileTime = traits<Ancestor>::RowsAtCompileTime, |
|||
ColsAtCompileTime = traits<Ancestor>::ColsAtCompileTime, |
|||
MaxRowsAtCompileTime = traits<Ancestor>::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = traits<Ancestor>::MaxColsAtCompileTime |
|||
}; |
|||
|
|||
// even though we require Lhs and Rhs to have the same scalar type (see CwiseBinaryOp constructor), |
|||
// we still want to handle the case when the result type is different. |
|||
typedef typename result_of< |
|||
BinaryOp( |
|||
typename Lhs::Scalar, |
|||
typename Rhs::Scalar |
|||
) |
|||
>::type Scalar; |
|||
typedef typename promote_storage_type<typename traits<Lhs>::StorageKind, |
|||
typename traits<Rhs>::StorageKind>::ret StorageKind; |
|||
typedef typename promote_index_type<typename traits<Lhs>::Index, |
|||
typename traits<Rhs>::Index>::type Index; |
|||
typedef typename Lhs::Nested LhsNested; |
|||
typedef typename Rhs::Nested RhsNested; |
|||
typedef typename remove_reference<LhsNested>::type _LhsNested; |
|||
typedef typename remove_reference<RhsNested>::type _RhsNested; |
|||
enum { |
|||
LhsCoeffReadCost = _LhsNested::CoeffReadCost, |
|||
RhsCoeffReadCost = _RhsNested::CoeffReadCost, |
|||
LhsFlags = _LhsNested::Flags, |
|||
RhsFlags = _RhsNested::Flags, |
|||
SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value, |
|||
StorageOrdersAgree = (int(Lhs::Flags)&RowMajorBit)==(int(Rhs::Flags)&RowMajorBit), |
|||
Flags0 = (int(LhsFlags) | int(RhsFlags)) & ( |
|||
HereditaryBits |
|||
| (int(LhsFlags) & int(RhsFlags) & |
|||
( AlignedBit |
|||
| (StorageOrdersAgree ? LinearAccessBit : 0) |
|||
| (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0) |
|||
) |
|||
) |
|||
), |
|||
Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit), |
|||
CoeffReadCost = LhsCoeffReadCost + RhsCoeffReadCost + functor_traits<BinaryOp>::Cost |
|||
}; |
|||
}; |
|||
} // end namespace internal |
|||
|
|||
// we require Lhs and Rhs to have the same scalar type. Currently there is no example of a binary functor |
|||
// that would take two operands of different types. If there were such an example, then this check should be |
|||
// moved to the BinaryOp functors, on a per-case basis. This would however require a change in the BinaryOp functors, as |
|||
// currently they take only one typename Scalar template parameter. |
|||
// It is tempting to always allow mixing different types but remember that this is often impossible in the vectorized paths. |
|||
// So allowing mixing different types gives very unexpected errors when enabling vectorization, when the user tries to |
|||
// add together a float matrix and a double matrix. |
|||
#define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP,LHS,RHS) \ |
|||
EIGEN_STATIC_ASSERT((internal::functor_allows_mixing_real_and_complex<BINOP>::ret \ |
|||
? int(internal::is_same<typename NumTraits<LHS>::Real, typename NumTraits<RHS>::Real>::value) \ |
|||
: int(internal::is_same<LHS, RHS>::value)), \ |
|||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) |
|||
|
|||
template<typename BinaryOp, typename Lhs, typename Rhs, typename StorageKind> |
|||
class CwiseBinaryOpImpl; |
|||
|
|||
template<typename BinaryOp, typename Lhs, typename Rhs> |
|||
class CwiseBinaryOp : internal::no_assignment_operator, |
|||
public CwiseBinaryOpImpl< |
|||
BinaryOp, Lhs, Rhs, |
|||
typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind, |
|||
typename internal::traits<Rhs>::StorageKind>::ret> |
|||
{ |
|||
public: |
|||
|
|||
typedef typename CwiseBinaryOpImpl< |
|||
BinaryOp, Lhs, Rhs, |
|||
typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind, |
|||
typename internal::traits<Rhs>::StorageKind>::ret>::Base Base; |
|||
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp) |
|||
|
|||
typedef typename internal::nested<Lhs>::type LhsNested; |
|||
typedef typename internal::nested<Rhs>::type RhsNested; |
|||
typedef typename internal::remove_reference<LhsNested>::type _LhsNested; |
|||
typedef typename internal::remove_reference<RhsNested>::type _RhsNested; |
|||
|
|||
EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp()) |
|||
: m_lhs(lhs), m_rhs(rhs), m_functor(func) |
|||
{ |
|||
EIGEN_CHECK_BINARY_COMPATIBILIY(BinaryOp,typename Lhs::Scalar,typename Rhs::Scalar); |
|||
// require the sizes to match |
|||
EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Lhs, Rhs) |
|||
eigen_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols()); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE Index rows() const { |
|||
// return the fixed size type if available to enable compile time optimizations |
|||
if (internal::traits<typename internal::remove_all<LhsNested>::type>::RowsAtCompileTime==Dynamic) |
|||
return m_rhs.rows(); |
|||
else |
|||
return m_lhs.rows(); |
|||
} |
|||
EIGEN_STRONG_INLINE Index cols() const { |
|||
// return the fixed size type if available to enable compile time optimizations |
|||
if (internal::traits<typename internal::remove_all<LhsNested>::type>::ColsAtCompileTime==Dynamic) |
|||
return m_rhs.cols(); |
|||
else |
|||
return m_lhs.cols(); |
|||
} |
|||
|
|||
/** \returns the left hand side nested expression */ |
|||
const _LhsNested& lhs() const { return m_lhs; } |
|||
/** \returns the right hand side nested expression */ |
|||
const _RhsNested& rhs() const { return m_rhs; } |
|||
/** \returns the functor representing the binary operation */ |
|||
const BinaryOp& functor() const { return m_functor; } |
|||
|
|||
protected: |
|||
LhsNested m_lhs; |
|||
RhsNested m_rhs; |
|||
const BinaryOp m_functor; |
|||
}; |
|||
|
|||
template<typename BinaryOp, typename Lhs, typename Rhs> |
|||
class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Dense> |
|||
: public internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type |
|||
{ |
|||
typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived; |
|||
public: |
|||
|
|||
typedef typename internal::dense_xpr_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >::type Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE( Derived ) |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const |
|||
{ |
|||
return derived().functor()(derived().lhs().coeff(row, col), |
|||
derived().rhs().coeff(row, col)); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(row, col), |
|||
derived().rhs().template packet<LoadMode>(row, col)); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const |
|||
{ |
|||
return derived().functor()(derived().lhs().coeff(index), |
|||
derived().rhs().coeff(index)); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index index) const |
|||
{ |
|||
return derived().functor().packetOp(derived().lhs().template packet<LoadMode>(index), |
|||
derived().rhs().template packet<LoadMode>(index)); |
|||
} |
|||
}; |
|||
|
|||
/** replaces \c *this by \c *this - \a other. |
|||
* |
|||
* \returns a reference to \c *this |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Derived & |
|||
MatrixBase<Derived>::operator-=(const MatrixBase<OtherDerived> &other) |
|||
{ |
|||
SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, Derived, OtherDerived> tmp(derived()); |
|||
tmp = other.derived(); |
|||
return derived(); |
|||
} |
|||
|
|||
/** replaces \c *this by \c *this + \a other. |
|||
* |
|||
* \returns a reference to \c *this |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Derived & |
|||
MatrixBase<Derived>::operator+=(const MatrixBase<OtherDerived>& other) |
|||
{ |
|||
SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, Derived, OtherDerived> tmp(derived()); |
|||
tmp = other.derived(); |
|||
return derived(); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_CWISE_BINARY_OP_H |
@ -0,0 +1,864 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_CWISE_NULLARY_OP_H |
|||
#define EIGEN_CWISE_NULLARY_OP_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class CwiseNullaryOp |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Generic expression of a matrix where all coefficients are defined by a functor |
|||
* |
|||
* \param NullaryOp template functor implementing the operator |
|||
* \param PlainObjectType the underlying plain matrix/array type |
|||
* |
|||
* This class represents an expression of a generic nullary operator. |
|||
* It is the return type of the Ones(), Zero(), Constant(), Identity() and Random() methods, |
|||
* and most of the time this is the only way it is used. |
|||
* |
|||
* However, if you want to write a function returning such an expression, you |
|||
* will need to use this class. |
|||
* |
|||
* \sa class CwiseUnaryOp, class CwiseBinaryOp, DenseBase::NullaryExpr() |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename NullaryOp, typename PlainObjectType> |
|||
struct traits<CwiseNullaryOp<NullaryOp, PlainObjectType> > : traits<PlainObjectType> |
|||
{ |
|||
enum { |
|||
Flags = (traits<PlainObjectType>::Flags |
|||
& ( HereditaryBits |
|||
| (functor_has_linear_access<NullaryOp>::ret ? LinearAccessBit : 0) |
|||
| (functor_traits<NullaryOp>::PacketAccess ? PacketAccessBit : 0))) |
|||
| (functor_traits<NullaryOp>::IsRepeatable ? 0 : EvalBeforeNestingBit), |
|||
CoeffReadCost = functor_traits<NullaryOp>::Cost |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename NullaryOp, typename PlainObjectType> |
|||
class CwiseNullaryOp : internal::no_assignment_operator, |
|||
public internal::dense_xpr_base< CwiseNullaryOp<NullaryOp, PlainObjectType> >::type |
|||
{ |
|||
public: |
|||
|
|||
typedef typename internal::dense_xpr_base<CwiseNullaryOp>::type Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(CwiseNullaryOp) |
|||
|
|||
CwiseNullaryOp(Index rows, Index cols, const NullaryOp& func = NullaryOp()) |
|||
: m_rows(rows), m_cols(cols), m_functor(func) |
|||
{ |
|||
eigen_assert(rows >= 0 |
|||
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) |
|||
&& cols >= 0 |
|||
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE Index rows() const { return m_rows.value(); } |
|||
EIGEN_STRONG_INLINE Index cols() const { return m_cols.value(); } |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar coeff(Index rows, Index cols) const |
|||
{ |
|||
return m_functor(rows, cols); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
return m_functor.packetOp(row, col); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const |
|||
{ |
|||
return m_functor(index); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index index) const |
|||
{ |
|||
return m_functor.packetOp(index); |
|||
} |
|||
|
|||
/** \returns the functor representing the nullary operation */ |
|||
const NullaryOp& functor() const { return m_functor; } |
|||
|
|||
protected: |
|||
const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_rows; |
|||
const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_cols; |
|||
const NullaryOp m_functor; |
|||
}; |
|||
|
|||
|
|||
/** \returns an expression of a matrix defined by a custom functor \a func |
|||
* |
|||
* The parameters \a rows and \a cols are the number of rows and of columns of |
|||
* the returned matrix. Must be compatible with this MatrixBase type. |
|||
* |
|||
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, |
|||
* it is redundant to pass \a rows and \a cols as arguments, so Zero() should be used |
|||
* instead. |
|||
* |
|||
* The template parameter \a CustomNullaryOp is the type of the functor. |
|||
* |
|||
* \sa class CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename CustomNullaryOp> |
|||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived> |
|||
DenseBase<Derived>::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func) |
|||
{ |
|||
return CwiseNullaryOp<CustomNullaryOp, Derived>(rows, cols, func); |
|||
} |
|||
|
|||
/** \returns an expression of a matrix defined by a custom functor \a func |
|||
* |
|||
* The parameter \a size is the size of the returned vector. |
|||
* Must be compatible with this MatrixBase type. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* This variant is meant to be used for dynamic-size vector types. For fixed-size types, |
|||
* it is redundant to pass \a size as argument, so Zero() should be used |
|||
* instead. |
|||
* |
|||
* The template parameter \a CustomNullaryOp is the type of the functor. |
|||
* |
|||
* \sa class CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename CustomNullaryOp> |
|||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived> |
|||
DenseBase<Derived>::NullaryExpr(Index size, const CustomNullaryOp& func) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
if(RowsAtCompileTime == 1) return CwiseNullaryOp<CustomNullaryOp, Derived>(1, size, func); |
|||
else return CwiseNullaryOp<CustomNullaryOp, Derived>(size, 1, func); |
|||
} |
|||
|
|||
/** \returns an expression of a matrix defined by a custom functor \a func |
|||
* |
|||
* This variant is only for fixed-size DenseBase types. For dynamic-size types, you |
|||
* need to use the variants taking size arguments. |
|||
* |
|||
* The template parameter \a CustomNullaryOp is the type of the functor. |
|||
* |
|||
* \sa class CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename CustomNullaryOp> |
|||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, Derived> |
|||
DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func) |
|||
{ |
|||
return CwiseNullaryOp<CustomNullaryOp, Derived>(RowsAtCompileTime, ColsAtCompileTime, func); |
|||
} |
|||
|
|||
/** \returns an expression of a constant matrix of value \a value |
|||
* |
|||
* The parameters \a rows and \a cols are the number of rows and of columns of |
|||
* the returned matrix. Must be compatible with this DenseBase type. |
|||
* |
|||
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, |
|||
* it is redundant to pass \a rows and \a cols as arguments, so Zero() should be used |
|||
* instead. |
|||
* |
|||
* The template parameter \a CustomNullaryOp is the type of the functor. |
|||
* |
|||
* \sa class CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Constant(Index rows, Index cols, const Scalar& value) |
|||
{ |
|||
return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_constant_op<Scalar>(value)); |
|||
} |
|||
|
|||
/** \returns an expression of a constant matrix of value \a value |
|||
* |
|||
* The parameter \a size is the size of the returned vector. |
|||
* Must be compatible with this DenseBase type. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* This variant is meant to be used for dynamic-size vector types. For fixed-size types, |
|||
* it is redundant to pass \a size as argument, so Zero() should be used |
|||
* instead. |
|||
* |
|||
* The template parameter \a CustomNullaryOp is the type of the functor. |
|||
* |
|||
* \sa class CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Constant(Index size, const Scalar& value) |
|||
{ |
|||
return DenseBase<Derived>::NullaryExpr(size, internal::scalar_constant_op<Scalar>(value)); |
|||
} |
|||
|
|||
/** \returns an expression of a constant matrix of value \a value |
|||
* |
|||
* This variant is only for fixed-size DenseBase types. For dynamic-size types, you |
|||
* need to use the variants taking size arguments. |
|||
* |
|||
* The template parameter \a CustomNullaryOp is the type of the functor. |
|||
* |
|||
* \sa class CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Constant(const Scalar& value) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) |
|||
return DenseBase<Derived>::NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_constant_op<Scalar>(value)); |
|||
} |
|||
|
|||
/** |
|||
* \brief Sets a linearly space vector. |
|||
* |
|||
* The function generates 'size' equally spaced values in the closed interval [low,high]. |
|||
* This particular version of LinSpaced() uses sequential access, i.e. vector access is |
|||
* assumed to be a(0), a(1), ..., a(size). This assumption allows for better vectorization |
|||
* and yields faster code than the random access version. |
|||
* |
|||
* When size is set to 1, a vector of length 1 containing 'high' is returned. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* Example: \include DenseBase_LinSpaced_seq.cpp |
|||
* Output: \verbinclude DenseBase_LinSpaced_seq.out |
|||
* |
|||
* \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Index,Scalar,Scalar), CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::SequentialLinSpacedReturnType |
|||
DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,false>(low,high,size)); |
|||
} |
|||
|
|||
/** |
|||
* \copydoc DenseBase::LinSpaced(Sequential_t, Index, const Scalar&, const Scalar&) |
|||
* Special version for fixed size types which does not require the size parameter. |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::SequentialLinSpacedReturnType |
|||
DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) |
|||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,false>(low,high,Derived::SizeAtCompileTime)); |
|||
} |
|||
|
|||
/** |
|||
* \brief Sets a linearly space vector. |
|||
* |
|||
* The function generates 'size' equally spaced values in the closed interval [low,high]. |
|||
* When size is set to 1, a vector of length 1 containing 'high' is returned. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* Example: \include DenseBase_LinSpaced.cpp |
|||
* Output: \verbinclude DenseBase_LinSpaced.out |
|||
* |
|||
* \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Sequential_t,Index,const Scalar&,const Scalar&,Index), CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType |
|||
DenseBase<Derived>::LinSpaced(Index size, const Scalar& low, const Scalar& high) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar,true>(low,high,size)); |
|||
} |
|||
|
|||
/** |
|||
* \copydoc DenseBase::LinSpaced(Index, const Scalar&, const Scalar&) |
|||
* Special version for fixed size types which does not require the size parameter. |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType |
|||
DenseBase<Derived>::LinSpaced(const Scalar& low, const Scalar& high) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) |
|||
return DenseBase<Derived>::NullaryExpr(Derived::SizeAtCompileTime, internal::linspaced_op<Scalar,true>(low,high,Derived::SizeAtCompileTime)); |
|||
} |
|||
|
|||
/** \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */ |
|||
template<typename Derived> |
|||
bool DenseBase<Derived>::isApproxToConstant |
|||
(const Scalar& value, RealScalar prec) const |
|||
{ |
|||
for(Index j = 0; j < cols(); ++j) |
|||
for(Index i = 0; i < rows(); ++i) |
|||
if(!internal::isApprox(this->coeff(i, j), value, prec)) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
/** This is just an alias for isApproxToConstant(). |
|||
* |
|||
* \returns true if all coefficients in this matrix are approximately equal to \a value, to within precision \a prec */ |
|||
template<typename Derived> |
|||
bool DenseBase<Derived>::isConstant |
|||
(const Scalar& value, RealScalar prec) const |
|||
{ |
|||
return isApproxToConstant(value, prec); |
|||
} |
|||
|
|||
/** Alias for setConstant(): sets all coefficients in this expression to \a value. |
|||
* |
|||
* \sa setConstant(), Constant(), class CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& value) |
|||
{ |
|||
setConstant(value); |
|||
} |
|||
|
|||
/** Sets all coefficients in this expression to \a value. |
|||
* |
|||
* \sa fill(), setConstant(Index,const Scalar&), setConstant(Index,Index,const Scalar&), setZero(), setOnes(), Constant(), class CwiseNullaryOp, setZero(), setOnes() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& value) |
|||
{ |
|||
return derived() = Constant(rows(), cols(), value); |
|||
} |
|||
|
|||
/** Resizes to the given \a size, and sets all coefficients in this expression to the given \a value. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* Example: \include Matrix_setConstant_int.cpp |
|||
* Output: \verbinclude Matrix_setConstant_int.out |
|||
* |
|||
* \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&) |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& |
|||
PlainObjectBase<Derived>::setConstant(Index size, const Scalar& value) |
|||
{ |
|||
resize(size); |
|||
return setConstant(value); |
|||
} |
|||
|
|||
/** Resizes to the given size, and sets all coefficients in this expression to the given \a value. |
|||
* |
|||
* \param rows the new number of rows |
|||
* \param cols the new number of columns |
|||
* \param value the value to which all coefficients are set |
|||
* |
|||
* Example: \include Matrix_setConstant_int_int.cpp |
|||
* Output: \verbinclude Matrix_setConstant_int_int.out |
|||
* |
|||
* \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&) |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& |
|||
PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& value) |
|||
{ |
|||
resize(rows, cols); |
|||
return setConstant(value); |
|||
} |
|||
|
|||
/** |
|||
* \brief Sets a linearly space vector. |
|||
* |
|||
* The function generates 'size' equally spaced values in the closed interval [low,high]. |
|||
* When size is set to 1, a vector of length 1 containing 'high' is returned. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* Example: \include DenseBase_setLinSpaced.cpp |
|||
* Output: \verbinclude DenseBase_setLinSpaced.out |
|||
* |
|||
* \sa CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index size, const Scalar& low, const Scalar& high) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
return derived() = Derived::NullaryExpr(size, internal::linspaced_op<Scalar,false>(low,high,size)); |
|||
} |
|||
|
|||
/** |
|||
* \brief Sets a linearly space vector. |
|||
* |
|||
* The function fill *this with equally spaced values in the closed interval [low,high]. |
|||
* When size is set to 1, a vector of length 1 containing 'high' is returned. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(const Scalar& low, const Scalar& high) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
return setLinSpaced(size(), low, high); |
|||
} |
|||
|
|||
// zero: |
|||
|
|||
/** \returns an expression of a zero matrix. |
|||
* |
|||
* The parameters \a rows and \a cols are the number of rows and of columns of |
|||
* the returned matrix. Must be compatible with this MatrixBase type. |
|||
* |
|||
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, |
|||
* it is redundant to pass \a rows and \a cols as arguments, so Zero() should be used |
|||
* instead. |
|||
* |
|||
* Example: \include MatrixBase_zero_int_int.cpp |
|||
* Output: \verbinclude MatrixBase_zero_int_int.out |
|||
* |
|||
* \sa Zero(), Zero(Index) |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Zero(Index rows, Index cols) |
|||
{ |
|||
return Constant(rows, cols, Scalar(0)); |
|||
} |
|||
|
|||
/** \returns an expression of a zero vector. |
|||
* |
|||
* The parameter \a size is the size of the returned vector. |
|||
* Must be compatible with this MatrixBase type. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* This variant is meant to be used for dynamic-size vector types. For fixed-size types, |
|||
* it is redundant to pass \a size as argument, so Zero() should be used |
|||
* instead. |
|||
* |
|||
* Example: \include MatrixBase_zero_int.cpp |
|||
* Output: \verbinclude MatrixBase_zero_int.out |
|||
* |
|||
* \sa Zero(), Zero(Index,Index) |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Zero(Index size) |
|||
{ |
|||
return Constant(size, Scalar(0)); |
|||
} |
|||
|
|||
/** \returns an expression of a fixed-size zero matrix or vector. |
|||
* |
|||
* This variant is only for fixed-size MatrixBase types. For dynamic-size types, you |
|||
* need to use the variants taking size arguments. |
|||
* |
|||
* Example: \include MatrixBase_zero.cpp |
|||
* Output: \verbinclude MatrixBase_zero.out |
|||
* |
|||
* \sa Zero(Index), Zero(Index,Index) |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Zero() |
|||
{ |
|||
return Constant(Scalar(0)); |
|||
} |
|||
|
|||
/** \returns true if *this is approximately equal to the zero matrix, |
|||
* within the precision given by \a prec. |
|||
* |
|||
* Example: \include MatrixBase_isZero.cpp |
|||
* Output: \verbinclude MatrixBase_isZero.out |
|||
* |
|||
* \sa class CwiseNullaryOp, Zero() |
|||
*/ |
|||
template<typename Derived> |
|||
bool DenseBase<Derived>::isZero(RealScalar prec) const |
|||
{ |
|||
for(Index j = 0; j < cols(); ++j) |
|||
for(Index i = 0; i < rows(); ++i) |
|||
if(!internal::isMuchSmallerThan(this->coeff(i, j), static_cast<Scalar>(1), prec)) |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
/** Sets all coefficients in this expression to zero. |
|||
* |
|||
* Example: \include MatrixBase_setZero.cpp |
|||
* Output: \verbinclude MatrixBase_setZero.out |
|||
* |
|||
* \sa class CwiseNullaryOp, Zero() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero() |
|||
{ |
|||
return setConstant(Scalar(0)); |
|||
} |
|||
|
|||
/** Resizes to the given \a size, and sets all coefficients in this expression to zero. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* Example: \include Matrix_setZero_int.cpp |
|||
* Output: \verbinclude Matrix_setZero_int.out |
|||
* |
|||
* \sa DenseBase::setZero(), setZero(Index,Index), class CwiseNullaryOp, DenseBase::Zero() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& |
|||
PlainObjectBase<Derived>::setZero(Index size) |
|||
{ |
|||
resize(size); |
|||
return setConstant(Scalar(0)); |
|||
} |
|||
|
|||
/** Resizes to the given size, and sets all coefficients in this expression to zero. |
|||
* |
|||
* \param rows the new number of rows |
|||
* \param cols the new number of columns |
|||
* |
|||
* Example: \include Matrix_setZero_int_int.cpp |
|||
* Output: \verbinclude Matrix_setZero_int_int.out |
|||
* |
|||
* \sa DenseBase::setZero(), setZero(Index), class CwiseNullaryOp, DenseBase::Zero() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& |
|||
PlainObjectBase<Derived>::setZero(Index rows, Index cols) |
|||
{ |
|||
resize(rows, cols); |
|||
return setConstant(Scalar(0)); |
|||
} |
|||
|
|||
// ones: |
|||
|
|||
/** \returns an expression of a matrix where all coefficients equal one. |
|||
* |
|||
* The parameters \a rows and \a cols are the number of rows and of columns of |
|||
* the returned matrix. Must be compatible with this MatrixBase type. |
|||
* |
|||
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, |
|||
* it is redundant to pass \a rows and \a cols as arguments, so Ones() should be used |
|||
* instead. |
|||
* |
|||
* Example: \include MatrixBase_ones_int_int.cpp |
|||
* Output: \verbinclude MatrixBase_ones_int_int.out |
|||
* |
|||
* \sa Ones(), Ones(Index), isOnes(), class Ones |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Ones(Index rows, Index cols) |
|||
{ |
|||
return Constant(rows, cols, Scalar(1)); |
|||
} |
|||
|
|||
/** \returns an expression of a vector where all coefficients equal one. |
|||
* |
|||
* The parameter \a size is the size of the returned vector. |
|||
* Must be compatible with this MatrixBase type. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* This variant is meant to be used for dynamic-size vector types. For fixed-size types, |
|||
* it is redundant to pass \a size as argument, so Ones() should be used |
|||
* instead. |
|||
* |
|||
* Example: \include MatrixBase_ones_int.cpp |
|||
* Output: \verbinclude MatrixBase_ones_int.out |
|||
* |
|||
* \sa Ones(), Ones(Index,Index), isOnes(), class Ones |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Ones(Index size) |
|||
{ |
|||
return Constant(size, Scalar(1)); |
|||
} |
|||
|
|||
/** \returns an expression of a fixed-size matrix or vector where all coefficients equal one. |
|||
* |
|||
* This variant is only for fixed-size MatrixBase types. For dynamic-size types, you |
|||
* need to use the variants taking size arguments. |
|||
* |
|||
* Example: \include MatrixBase_ones.cpp |
|||
* Output: \verbinclude MatrixBase_ones.out |
|||
* |
|||
* \sa Ones(Index), Ones(Index,Index), isOnes(), class Ones |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType |
|||
DenseBase<Derived>::Ones() |
|||
{ |
|||
return Constant(Scalar(1)); |
|||
} |
|||
|
|||
/** \returns true if *this is approximately equal to the matrix where all coefficients |
|||
* are equal to 1, within the precision given by \a prec. |
|||
* |
|||
* Example: \include MatrixBase_isOnes.cpp |
|||
* Output: \verbinclude MatrixBase_isOnes.out |
|||
* |
|||
* \sa class CwiseNullaryOp, Ones() |
|||
*/ |
|||
template<typename Derived> |
|||
bool DenseBase<Derived>::isOnes |
|||
(RealScalar prec) const |
|||
{ |
|||
return isApproxToConstant(Scalar(1), prec); |
|||
} |
|||
|
|||
/** Sets all coefficients in this expression to one. |
|||
* |
|||
* Example: \include MatrixBase_setOnes.cpp |
|||
* Output: \verbinclude MatrixBase_setOnes.out |
|||
* |
|||
* \sa class CwiseNullaryOp, Ones() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes() |
|||
{ |
|||
return setConstant(Scalar(1)); |
|||
} |
|||
|
|||
/** Resizes to the given \a size, and sets all coefficients in this expression to one. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* Example: \include Matrix_setOnes_int.cpp |
|||
* Output: \verbinclude Matrix_setOnes_int.out |
|||
* |
|||
* \sa MatrixBase::setOnes(), setOnes(Index,Index), class CwiseNullaryOp, MatrixBase::Ones() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& |
|||
PlainObjectBase<Derived>::setOnes(Index size) |
|||
{ |
|||
resize(size); |
|||
return setConstant(Scalar(1)); |
|||
} |
|||
|
|||
/** Resizes to the given size, and sets all coefficients in this expression to one. |
|||
* |
|||
* \param rows the new number of rows |
|||
* \param cols the new number of columns |
|||
* |
|||
* Example: \include Matrix_setOnes_int_int.cpp |
|||
* Output: \verbinclude Matrix_setOnes_int_int.out |
|||
* |
|||
* \sa MatrixBase::setOnes(), setOnes(Index), class CwiseNullaryOp, MatrixBase::Ones() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& |
|||
PlainObjectBase<Derived>::setOnes(Index rows, Index cols) |
|||
{ |
|||
resize(rows, cols); |
|||
return setConstant(Scalar(1)); |
|||
} |
|||
|
|||
// Identity: |
|||
|
|||
/** \returns an expression of the identity matrix (not necessarily square). |
|||
* |
|||
* The parameters \a rows and \a cols are the number of rows and of columns of |
|||
* the returned matrix. Must be compatible with this MatrixBase type. |
|||
* |
|||
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, |
|||
* it is redundant to pass \a rows and \a cols as arguments, so Identity() should be used |
|||
* instead. |
|||
* |
|||
* Example: \include MatrixBase_identity_int_int.cpp |
|||
* Output: \verbinclude MatrixBase_identity_int_int.out |
|||
* |
|||
* \sa Identity(), setIdentity(), isIdentity() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType |
|||
MatrixBase<Derived>::Identity(Index rows, Index cols) |
|||
{ |
|||
return DenseBase<Derived>::NullaryExpr(rows, cols, internal::scalar_identity_op<Scalar>()); |
|||
} |
|||
|
|||
/** \returns an expression of the identity matrix (not necessarily square). |
|||
* |
|||
* This variant is only for fixed-size MatrixBase types. For dynamic-size types, you |
|||
* need to use the variant taking size arguments. |
|||
* |
|||
* Example: \include MatrixBase_identity.cpp |
|||
* Output: \verbinclude MatrixBase_identity.out |
|||
* |
|||
* \sa Identity(Index,Index), setIdentity(), isIdentity() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType |
|||
MatrixBase<Derived>::Identity() |
|||
{ |
|||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) |
|||
return MatrixBase<Derived>::NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_identity_op<Scalar>()); |
|||
} |
|||
|
|||
/** \returns true if *this is approximately equal to the identity matrix |
|||
* (not necessarily square), |
|||
* within the precision given by \a prec. |
|||
* |
|||
* Example: \include MatrixBase_isIdentity.cpp |
|||
* Output: \verbinclude MatrixBase_isIdentity.out |
|||
* |
|||
* \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), setIdentity() |
|||
*/ |
|||
template<typename Derived> |
|||
bool MatrixBase<Derived>::isIdentity |
|||
(RealScalar prec) const |
|||
{ |
|||
for(Index j = 0; j < cols(); ++j) |
|||
{ |
|||
for(Index i = 0; i < rows(); ++i) |
|||
{ |
|||
if(i == j) |
|||
{ |
|||
if(!internal::isApprox(this->coeff(i, j), static_cast<Scalar>(1), prec)) |
|||
return false; |
|||
} |
|||
else |
|||
{ |
|||
if(!internal::isMuchSmallerThan(this->coeff(i, j), static_cast<RealScalar>(1), prec)) |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename Derived, bool Big = (Derived::SizeAtCompileTime>=16)> |
|||
struct setIdentity_impl |
|||
{ |
|||
static EIGEN_STRONG_INLINE Derived& run(Derived& m) |
|||
{ |
|||
return m = Derived::Identity(m.rows(), m.cols()); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
struct setIdentity_impl<Derived, true> |
|||
{ |
|||
typedef typename Derived::Index Index; |
|||
static EIGEN_STRONG_INLINE Derived& run(Derived& m) |
|||
{ |
|||
m.setZero(); |
|||
const Index size = (std::min)(m.rows(), m.cols()); |
|||
for(Index i = 0; i < size; ++i) m.coeffRef(i,i) = typename Derived::Scalar(1); |
|||
return m; |
|||
} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/** Writes the identity expression (not necessarily square) into *this. |
|||
* |
|||
* Example: \include MatrixBase_setIdentity.cpp |
|||
* Output: \verbinclude MatrixBase_setIdentity.out |
|||
* |
|||
* \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), isIdentity() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity() |
|||
{ |
|||
return internal::setIdentity_impl<Derived>::run(derived()); |
|||
} |
|||
|
|||
/** \brief Resizes to the given size, and writes the identity expression (not necessarily square) into *this. |
|||
* |
|||
* \param rows the new number of rows |
|||
* \param cols the new number of columns |
|||
* |
|||
* Example: \include Matrix_setIdentity_int_int.cpp |
|||
* Output: \verbinclude Matrix_setIdentity_int_int.out |
|||
* |
|||
* \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index cols) |
|||
{ |
|||
derived().resize(rows, cols); |
|||
return setIdentity(); |
|||
} |
|||
|
|||
/** \returns an expression of the i-th unit (basis) vector. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa MatrixBase::Unit(Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index size, Index i) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
return BasisReturnType(SquareMatrixType::Identity(size,size), i); |
|||
} |
|||
|
|||
/** \returns an expression of the i-th unit (basis) vector. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* This variant is for fixed-size vector only. |
|||
* |
|||
* \sa MatrixBase::Unit(Index,Index), MatrixBase::UnitX(), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index i) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
return BasisReturnType(SquareMatrixType::Identity(),i); |
|||
} |
|||
|
|||
/** \returns an expression of the X axis unit vector (1{,0}^*) |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitX() |
|||
{ return Derived::Unit(0); } |
|||
|
|||
/** \returns an expression of the Y axis unit vector (0,1{,0}^*) |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitY() |
|||
{ return Derived::Unit(1); } |
|||
|
|||
/** \returns an expression of the Z axis unit vector (0,0,1{,0}^*) |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitZ() |
|||
{ return Derived::Unit(2); } |
|||
|
|||
/** \returns an expression of the W axis unit vector (0,0,0,1) |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa MatrixBase::Unit(Index,Index), MatrixBase::Unit(Index), MatrixBase::UnitY(), MatrixBase::UnitZ(), MatrixBase::UnitW() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitW() |
|||
{ return Derived::Unit(3); } |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_CWISE_NULLARY_OP_H |
@ -0,0 +1,126 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_CWISE_UNARY_OP_H |
|||
#define EIGEN_CWISE_UNARY_OP_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class CwiseUnaryOp |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Generic expression where a coefficient-wise unary operator is applied to an expression |
|||
* |
|||
* \param UnaryOp template functor implementing the operator |
|||
* \param XprType the type of the expression to which we are applying the unary operator |
|||
* |
|||
* This class represents an expression where a unary operator is applied to an expression. |
|||
* It is the return type of all operations taking exactly 1 input expression, regardless of the |
|||
* presence of other inputs such as scalars. For example, the operator* in the expression 3*matrix |
|||
* is considered unary, because only the right-hand side is an expression, and its |
|||
* return type is a specialization of CwiseUnaryOp. |
|||
* |
|||
* Most of the time, this is the only way that it is used, so you typically don't have to name |
|||
* CwiseUnaryOp types explicitly. |
|||
* |
|||
* \sa MatrixBase::unaryExpr(const CustomUnaryOp &) const, class CwiseBinaryOp, class CwiseNullaryOp |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename UnaryOp, typename XprType> |
|||
struct traits<CwiseUnaryOp<UnaryOp, XprType> > |
|||
: traits<XprType> |
|||
{ |
|||
typedef typename result_of< |
|||
UnaryOp(typename XprType::Scalar) |
|||
>::type Scalar; |
|||
typedef typename XprType::Nested XprTypeNested; |
|||
typedef typename remove_reference<XprTypeNested>::type _XprTypeNested; |
|||
enum { |
|||
Flags = _XprTypeNested::Flags & ( |
|||
HereditaryBits | LinearAccessBit | AlignedBit |
|||
| (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)), |
|||
CoeffReadCost = _XprTypeNested::CoeffReadCost + functor_traits<UnaryOp>::Cost |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename UnaryOp, typename XprType, typename StorageKind> |
|||
class CwiseUnaryOpImpl; |
|||
|
|||
template<typename UnaryOp, typename XprType> |
|||
class CwiseUnaryOp : internal::no_assignment_operator, |
|||
public CwiseUnaryOpImpl<UnaryOp, XprType, typename internal::traits<XprType>::StorageKind> |
|||
{ |
|||
public: |
|||
|
|||
typedef typename CwiseUnaryOpImpl<UnaryOp, XprType,typename internal::traits<XprType>::StorageKind>::Base Base; |
|||
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseUnaryOp) |
|||
|
|||
inline CwiseUnaryOp(const XprType& xpr, const UnaryOp& func = UnaryOp()) |
|||
: m_xpr(xpr), m_functor(func) {} |
|||
|
|||
EIGEN_STRONG_INLINE Index rows() const { return m_xpr.rows(); } |
|||
EIGEN_STRONG_INLINE Index cols() const { return m_xpr.cols(); } |
|||
|
|||
/** \returns the functor representing the unary operation */ |
|||
const UnaryOp& functor() const { return m_functor; } |
|||
|
|||
/** \returns the nested expression */ |
|||
const typename internal::remove_all<typename XprType::Nested>::type& |
|||
nestedExpression() const { return m_xpr; } |
|||
|
|||
/** \returns the nested expression */ |
|||
typename internal::remove_all<typename XprType::Nested>::type& |
|||
nestedExpression() { return m_xpr.const_cast_derived(); } |
|||
|
|||
protected: |
|||
typename XprType::Nested m_xpr; |
|||
const UnaryOp m_functor; |
|||
}; |
|||
|
|||
// This is the generic implementation for dense storage. |
|||
// It can be used for any expression types implementing the dense concept. |
|||
template<typename UnaryOp, typename XprType> |
|||
class CwiseUnaryOpImpl<UnaryOp,XprType,Dense> |
|||
: public internal::dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type |
|||
{ |
|||
public: |
|||
|
|||
typedef CwiseUnaryOp<UnaryOp, XprType> Derived; |
|||
typedef typename internal::dense_xpr_base<CwiseUnaryOp<UnaryOp, XprType> >::type Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Derived) |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const |
|||
{ |
|||
return derived().functor()(derived().nestedExpression().coeff(row, col)); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(row, col)); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const |
|||
{ |
|||
return derived().functor()(derived().nestedExpression().coeff(index)); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index index) const |
|||
{ |
|||
return derived().functor().packetOp(derived().nestedExpression().template packet<LoadMode>(index)); |
|||
} |
|||
}; |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_CWISE_UNARY_OP_H |
@ -0,0 +1,533 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_DENSEBASE_H |
|||
#define EIGEN_DENSEBASE_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class DenseBase |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Base class for all dense matrices, vectors, and arrays |
|||
* |
|||
* This class is the base that is inherited by all dense objects (matrix, vector, arrays, |
|||
* and related expression types). The common Eigen API for dense objects is contained in this class. |
|||
* |
|||
* \tparam Derived is the derived type, e.g., a matrix type or an expression. |
|||
* |
|||
* This class can be extended with the help of the plugin mechanism described on the page |
|||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_DENSEBASE_PLUGIN. |
|||
* |
|||
* \sa \ref TopicClassHierarchy |
|||
*/ |
|||
template<typename Derived> class DenseBase |
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
: public internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar, |
|||
typename NumTraits<typename internal::traits<Derived>::Scalar>::Real> |
|||
#else |
|||
: public DenseCoeffsBase<Derived> |
|||
#endif // not EIGEN_PARSED_BY_DOXYGEN |
|||
{ |
|||
public: |
|||
using internal::special_scalar_op_base<Derived,typename internal::traits<Derived>::Scalar, |
|||
typename NumTraits<typename internal::traits<Derived>::Scalar>::Real>::operator*; |
|||
|
|||
class InnerIterator; |
|||
|
|||
typedef typename internal::traits<Derived>::StorageKind StorageKind; |
|||
|
|||
/** \brief The type of indices |
|||
* \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE. |
|||
* \sa \ref TopicPreprocessorDirectives. |
|||
*/ |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
|
|||
typedef typename internal::traits<Derived>::Scalar Scalar; |
|||
typedef typename internal::packet_traits<Scalar>::type PacketScalar; |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
|
|||
typedef DenseCoeffsBase<Derived> Base; |
|||
using Base::derived; |
|||
using Base::const_cast_derived; |
|||
using Base::rows; |
|||
using Base::cols; |
|||
using Base::size; |
|||
using Base::rowIndexByOuterInner; |
|||
using Base::colIndexByOuterInner; |
|||
using Base::coeff; |
|||
using Base::coeffByOuterInner; |
|||
using Base::packet; |
|||
using Base::packetByOuterInner; |
|||
using Base::writePacket; |
|||
using Base::writePacketByOuterInner; |
|||
using Base::coeffRef; |
|||
using Base::coeffRefByOuterInner; |
|||
using Base::copyCoeff; |
|||
using Base::copyCoeffByOuterInner; |
|||
using Base::copyPacket; |
|||
using Base::copyPacketByOuterInner; |
|||
using Base::operator(); |
|||
using Base::operator[]; |
|||
using Base::x; |
|||
using Base::y; |
|||
using Base::z; |
|||
using Base::w; |
|||
using Base::stride; |
|||
using Base::innerStride; |
|||
using Base::outerStride; |
|||
using Base::rowStride; |
|||
using Base::colStride; |
|||
typedef typename Base::CoeffReturnType CoeffReturnType; |
|||
|
|||
enum { |
|||
|
|||
RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime, |
|||
/**< The number of rows at compile-time. This is just a copy of the value provided |
|||
* by the \a Derived type. If a value is not known at compile-time, |
|||
* it is set to the \a Dynamic constant. |
|||
* \sa MatrixBase::rows(), MatrixBase::cols(), ColsAtCompileTime, SizeAtCompileTime */ |
|||
|
|||
ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime, |
|||
/**< The number of columns at compile-time. This is just a copy of the value provided |
|||
* by the \a Derived type. If a value is not known at compile-time, |
|||
* it is set to the \a Dynamic constant. |
|||
* \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */ |
|||
|
|||
|
|||
SizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::RowsAtCompileTime, |
|||
internal::traits<Derived>::ColsAtCompileTime>::ret), |
|||
/**< This is equal to the number of coefficients, i.e. the number of |
|||
* rows times the number of columns, or to \a Dynamic if this is not |
|||
* known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */ |
|||
|
|||
MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime, |
|||
/**< This value is equal to the maximum possible number of rows that this expression |
|||
* might have. If this expression might have an arbitrarily high number of rows, |
|||
* this value is set to \a Dynamic. |
|||
* |
|||
* This value is useful to know when evaluating an expression, in order to determine |
|||
* whether it is possible to avoid doing a dynamic memory allocation. |
|||
* |
|||
* \sa RowsAtCompileTime, MaxColsAtCompileTime, MaxSizeAtCompileTime |
|||
*/ |
|||
|
|||
MaxColsAtCompileTime = internal::traits<Derived>::MaxColsAtCompileTime, |
|||
/**< This value is equal to the maximum possible number of columns that this expression |
|||
* might have. If this expression might have an arbitrarily high number of columns, |
|||
* this value is set to \a Dynamic. |
|||
* |
|||
* This value is useful to know when evaluating an expression, in order to determine |
|||
* whether it is possible to avoid doing a dynamic memory allocation. |
|||
* |
|||
* \sa ColsAtCompileTime, MaxRowsAtCompileTime, MaxSizeAtCompileTime |
|||
*/ |
|||
|
|||
MaxSizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::MaxRowsAtCompileTime, |
|||
internal::traits<Derived>::MaxColsAtCompileTime>::ret), |
|||
/**< This value is equal to the maximum possible number of coefficients that this expression |
|||
* might have. If this expression might have an arbitrarily high number of coefficients, |
|||
* this value is set to \a Dynamic. |
|||
* |
|||
* This value is useful to know when evaluating an expression, in order to determine |
|||
* whether it is possible to avoid doing a dynamic memory allocation. |
|||
* |
|||
* \sa SizeAtCompileTime, MaxRowsAtCompileTime, MaxColsAtCompileTime |
|||
*/ |
|||
|
|||
IsVectorAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime == 1 |
|||
|| internal::traits<Derived>::MaxColsAtCompileTime == 1, |
|||
/**< This is set to true if either the number of rows or the number of |
|||
* columns is known at compile-time to be equal to 1. Indeed, in that case, |
|||
* we are dealing with a column-vector (if there is only one column) or with |
|||
* a row-vector (if there is only one row). */ |
|||
|
|||
Flags = internal::traits<Derived>::Flags, |
|||
/**< This stores expression \ref flags flags which may or may not be inherited by new expressions |
|||
* constructed from this one. See the \ref flags "list of flags". |
|||
*/ |
|||
|
|||
IsRowMajor = int(Flags) & RowMajorBit, /**< True if this expression has row-major storage order. */ |
|||
|
|||
InnerSizeAtCompileTime = int(IsVectorAtCompileTime) ? int(SizeAtCompileTime) |
|||
: int(IsRowMajor) ? int(ColsAtCompileTime) : int(RowsAtCompileTime), |
|||
|
|||
CoeffReadCost = internal::traits<Derived>::CoeffReadCost, |
|||
/**< This is a rough measure of how expensive it is to read one coefficient from |
|||
* this expression. |
|||
*/ |
|||
|
|||
InnerStrideAtCompileTime = internal::inner_stride_at_compile_time<Derived>::ret, |
|||
OuterStrideAtCompileTime = internal::outer_stride_at_compile_time<Derived>::ret |
|||
}; |
|||
|
|||
enum { ThisConstantIsPrivateInPlainObjectBase }; |
|||
|
|||
/** \returns the number of nonzero coefficients which is in practice the number |
|||
* of stored coefficients. */ |
|||
inline Index nonZeros() const { return size(); } |
|||
/** \returns true if either the number of rows or the number of columns is equal to 1. |
|||
* In other words, this function returns |
|||
* \code rows()==1 || cols()==1 \endcode |
|||
* \sa rows(), cols(), IsVectorAtCompileTime. */ |
|||
|
|||
/** \returns the outer size. |
|||
* |
|||
* \note For a vector, this returns just 1. For a matrix (non-vector), this is the major dimension |
|||
* with respect to the \ref TopicStorageOrders "storage order", i.e., the number of columns for a |
|||
* column-major matrix, and the number of rows for a row-major matrix. */ |
|||
Index outerSize() const |
|||
{ |
|||
return IsVectorAtCompileTime ? 1 |
|||
: int(IsRowMajor) ? this->rows() : this->cols(); |
|||
} |
|||
|
|||
/** \returns the inner size. |
|||
* |
|||
* \note For a vector, this is just the size. For a matrix (non-vector), this is the minor dimension |
|||
* with respect to the \ref TopicStorageOrders "storage order", i.e., the number of rows for a |
|||
* column-major matrix, and the number of columns for a row-major matrix. */ |
|||
Index innerSize() const |
|||
{ |
|||
return IsVectorAtCompileTime ? this->size() |
|||
: int(IsRowMajor) ? this->cols() : this->rows(); |
|||
} |
|||
|
|||
/** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are |
|||
* Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does |
|||
* nothing else. |
|||
*/ |
|||
void resize(Index size) |
|||
{ |
|||
EIGEN_ONLY_USED_FOR_DEBUG(size); |
|||
eigen_assert(size == this->size() |
|||
&& "DenseBase::resize() does not actually allow to resize."); |
|||
} |
|||
/** Only plain matrices/arrays, not expressions, may be resized; therefore the only useful resize methods are |
|||
* Matrix::resize() and Array::resize(). The present method only asserts that the new size equals the old size, and does |
|||
* nothing else. |
|||
*/ |
|||
void resize(Index rows, Index cols) |
|||
{ |
|||
EIGEN_ONLY_USED_FOR_DEBUG(rows); |
|||
EIGEN_ONLY_USED_FOR_DEBUG(cols); |
|||
eigen_assert(rows == this->rows() && cols == this->cols() |
|||
&& "DenseBase::resize() does not actually allow to resize."); |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
/** \internal Represents a matrix with all coefficients equal to one another*/ |
|||
typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,Derived> ConstantReturnType; |
|||
/** \internal Represents a vector with linearly spaced coefficients that allows sequential access only. */ |
|||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,false>,Derived> SequentialLinSpacedReturnType; |
|||
/** \internal Represents a vector with linearly spaced coefficients that allows random access. */ |
|||
typedef CwiseNullaryOp<internal::linspaced_op<Scalar,true>,Derived> RandomAccessLinSpacedReturnType; |
|||
/** \internal the return type of MatrixBase::eigenvalues() */ |
|||
typedef Matrix<typename NumTraits<typename internal::traits<Derived>::Scalar>::Real, internal::traits<Derived>::ColsAtCompileTime, 1> EigenvaluesReturnType; |
|||
|
|||
#endif // not EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
/** Copies \a other into *this. \returns a reference to *this. */ |
|||
template<typename OtherDerived> |
|||
Derived& operator=(const DenseBase<OtherDerived>& other); |
|||
|
|||
/** Special case of the template operator=, in order to prevent the compiler |
|||
* from generating a default operator= (issue hit with g++ 4.1) |
|||
*/ |
|||
Derived& operator=(const DenseBase& other); |
|||
|
|||
template<typename OtherDerived> |
|||
Derived& operator=(const EigenBase<OtherDerived> &other); |
|||
|
|||
template<typename OtherDerived> |
|||
Derived& operator+=(const EigenBase<OtherDerived> &other); |
|||
|
|||
template<typename OtherDerived> |
|||
Derived& operator-=(const EigenBase<OtherDerived> &other); |
|||
|
|||
template<typename OtherDerived> |
|||
Derived& operator=(const ReturnByValue<OtherDerived>& func); |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */ |
|||
template<typename OtherDerived> |
|||
Derived& lazyAssign(const DenseBase<OtherDerived>& other); |
|||
#endif // not EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
CommaInitializer<Derived> operator<< (const Scalar& s); |
|||
|
|||
template<unsigned int Added,unsigned int Removed> |
|||
const Flagged<Derived, Added, Removed> flagged() const; |
|||
|
|||
template<typename OtherDerived> |
|||
CommaInitializer<Derived> operator<< (const DenseBase<OtherDerived>& other); |
|||
|
|||
Eigen::Transpose<Derived> transpose(); |
|||
typedef const Transpose<const Derived> ConstTransposeReturnType; |
|||
ConstTransposeReturnType transpose() const; |
|||
void transposeInPlace(); |
|||
#ifndef EIGEN_NO_DEBUG |
|||
protected: |
|||
template<typename OtherDerived> |
|||
void checkTransposeAliasing(const OtherDerived& other) const; |
|||
public: |
|||
#endif |
|||
|
|||
typedef VectorBlock<Derived> SegmentReturnType; |
|||
typedef const VectorBlock<const Derived> ConstSegmentReturnType; |
|||
template<int Size> struct FixedSegmentReturnType { typedef VectorBlock<Derived, Size> Type; }; |
|||
template<int Size> struct ConstFixedSegmentReturnType { typedef const VectorBlock<const Derived, Size> Type; }; |
|||
|
|||
// Note: The "DenseBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations. |
|||
SegmentReturnType segment(Index start, Index size); |
|||
typename DenseBase::ConstSegmentReturnType segment(Index start, Index size) const; |
|||
|
|||
SegmentReturnType head(Index size); |
|||
typename DenseBase::ConstSegmentReturnType head(Index size) const; |
|||
|
|||
SegmentReturnType tail(Index size); |
|||
typename DenseBase::ConstSegmentReturnType tail(Index size) const; |
|||
|
|||
template<int Size> typename FixedSegmentReturnType<Size>::Type head(); |
|||
template<int Size> typename ConstFixedSegmentReturnType<Size>::Type head() const; |
|||
|
|||
template<int Size> typename FixedSegmentReturnType<Size>::Type tail(); |
|||
template<int Size> typename ConstFixedSegmentReturnType<Size>::Type tail() const; |
|||
|
|||
template<int Size> typename FixedSegmentReturnType<Size>::Type segment(Index start); |
|||
template<int Size> typename ConstFixedSegmentReturnType<Size>::Type segment(Index start) const; |
|||
|
|||
static const ConstantReturnType |
|||
Constant(Index rows, Index cols, const Scalar& value); |
|||
static const ConstantReturnType |
|||
Constant(Index size, const Scalar& value); |
|||
static const ConstantReturnType |
|||
Constant(const Scalar& value); |
|||
|
|||
static const SequentialLinSpacedReturnType |
|||
LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high); |
|||
static const RandomAccessLinSpacedReturnType |
|||
LinSpaced(Index size, const Scalar& low, const Scalar& high); |
|||
static const SequentialLinSpacedReturnType |
|||
LinSpaced(Sequential_t, const Scalar& low, const Scalar& high); |
|||
static const RandomAccessLinSpacedReturnType |
|||
LinSpaced(const Scalar& low, const Scalar& high); |
|||
|
|||
template<typename CustomNullaryOp> |
|||
static const CwiseNullaryOp<CustomNullaryOp, Derived> |
|||
NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func); |
|||
template<typename CustomNullaryOp> |
|||
static const CwiseNullaryOp<CustomNullaryOp, Derived> |
|||
NullaryExpr(Index size, const CustomNullaryOp& func); |
|||
template<typename CustomNullaryOp> |
|||
static const CwiseNullaryOp<CustomNullaryOp, Derived> |
|||
NullaryExpr(const CustomNullaryOp& func); |
|||
|
|||
static const ConstantReturnType Zero(Index rows, Index cols); |
|||
static const ConstantReturnType Zero(Index size); |
|||
static const ConstantReturnType Zero(); |
|||
static const ConstantReturnType Ones(Index rows, Index cols); |
|||
static const ConstantReturnType Ones(Index size); |
|||
static const ConstantReturnType Ones(); |
|||
|
|||
void fill(const Scalar& value); |
|||
Derived& setConstant(const Scalar& value); |
|||
Derived& setLinSpaced(Index size, const Scalar& low, const Scalar& high); |
|||
Derived& setLinSpaced(const Scalar& low, const Scalar& high); |
|||
Derived& setZero(); |
|||
Derived& setOnes(); |
|||
Derived& setRandom(); |
|||
|
|||
template<typename OtherDerived> |
|||
bool isApprox(const DenseBase<OtherDerived>& other, |
|||
RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
bool isMuchSmallerThan(const RealScalar& other, |
|||
RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
template<typename OtherDerived> |
|||
bool isMuchSmallerThan(const DenseBase<OtherDerived>& other, |
|||
RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
|
|||
bool isApproxToConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
bool isConstant(const Scalar& value, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
bool isZero(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
bool isOnes(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
|
|||
inline Derived& operator*=(const Scalar& other); |
|||
inline Derived& operator/=(const Scalar& other); |
|||
|
|||
typedef typename internal::add_const_on_value_type<typename internal::eval<Derived>::type>::type EvalReturnType; |
|||
/** \returns the matrix or vector obtained by evaluating this expression. |
|||
* |
|||
* Notice that in the case of a plain matrix or vector (not an expression) this function just returns |
|||
* a const reference, in order to avoid a useless copy. |
|||
*/ |
|||
EIGEN_STRONG_INLINE EvalReturnType eval() const |
|||
{ |
|||
// Even though MSVC does not honor strong inlining when the return type |
|||
// is a dynamic matrix, we desperately need strong inlining for fixed |
|||
// size types on MSVC. |
|||
return typename internal::eval<Derived>::type(derived()); |
|||
} |
|||
|
|||
/** swaps *this with the expression \a other. |
|||
* |
|||
*/ |
|||
template<typename OtherDerived> |
|||
void swap(const DenseBase<OtherDerived>& other, |
|||
int = OtherDerived::ThisConstantIsPrivateInPlainObjectBase) |
|||
{ |
|||
SwapWrapper<Derived>(derived()).lazyAssign(other.derived()); |
|||
} |
|||
|
|||
/** swaps *this with the matrix or array \a other. |
|||
* |
|||
*/ |
|||
template<typename OtherDerived> |
|||
void swap(PlainObjectBase<OtherDerived>& other) |
|||
{ |
|||
SwapWrapper<Derived>(derived()).lazyAssign(other.derived()); |
|||
} |
|||
|
|||
|
|||
inline const NestByValue<Derived> nestByValue() const; |
|||
inline const ForceAlignedAccess<Derived> forceAlignedAccess() const; |
|||
inline ForceAlignedAccess<Derived> forceAlignedAccess(); |
|||
template<bool Enable> inline const typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf() const; |
|||
template<bool Enable> inline typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf(); |
|||
|
|||
Scalar sum() const; |
|||
Scalar mean() const; |
|||
Scalar trace() const; |
|||
|
|||
Scalar prod() const; |
|||
|
|||
typename internal::traits<Derived>::Scalar minCoeff() const; |
|||
typename internal::traits<Derived>::Scalar maxCoeff() const; |
|||
|
|||
template<typename IndexType> |
|||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* row, IndexType* col) const; |
|||
template<typename IndexType> |
|||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* row, IndexType* col) const; |
|||
template<typename IndexType> |
|||
typename internal::traits<Derived>::Scalar minCoeff(IndexType* index) const; |
|||
template<typename IndexType> |
|||
typename internal::traits<Derived>::Scalar maxCoeff(IndexType* index) const; |
|||
|
|||
template<typename BinaryOp> |
|||
typename internal::result_of<BinaryOp(typename internal::traits<Derived>::Scalar)>::type |
|||
redux(const BinaryOp& func) const; |
|||
|
|||
template<typename Visitor> |
|||
void visit(Visitor& func) const; |
|||
|
|||
inline const WithFormat<Derived> format(const IOFormat& fmt) const; |
|||
|
|||
/** \returns the unique coefficient of a 1x1 expression */ |
|||
CoeffReturnType value() const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) |
|||
eigen_assert(this->rows() == 1 && this->cols() == 1); |
|||
return derived().coeff(0,0); |
|||
} |
|||
|
|||
/////////// Array module /////////// |
|||
|
|||
bool all(void) const; |
|||
bool any(void) const; |
|||
Index count() const; |
|||
|
|||
typedef VectorwiseOp<Derived, Horizontal> RowwiseReturnType; |
|||
typedef const VectorwiseOp<const Derived, Horizontal> ConstRowwiseReturnType; |
|||
typedef VectorwiseOp<Derived, Vertical> ColwiseReturnType; |
|||
typedef const VectorwiseOp<const Derived, Vertical> ConstColwiseReturnType; |
|||
|
|||
ConstRowwiseReturnType rowwise() const; |
|||
RowwiseReturnType rowwise(); |
|||
ConstColwiseReturnType colwise() const; |
|||
ColwiseReturnType colwise(); |
|||
|
|||
static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random(Index rows, Index cols); |
|||
static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random(Index size); |
|||
static const CwiseNullaryOp<internal::scalar_random_op<Scalar>,Derived> Random(); |
|||
|
|||
template<typename ThenDerived,typename ElseDerived> |
|||
const Select<Derived,ThenDerived,ElseDerived> |
|||
select(const DenseBase<ThenDerived>& thenMatrix, |
|||
const DenseBase<ElseDerived>& elseMatrix) const; |
|||
|
|||
template<typename ThenDerived> |
|||
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType> |
|||
select(const DenseBase<ThenDerived>& thenMatrix, typename ThenDerived::Scalar elseScalar) const; |
|||
|
|||
template<typename ElseDerived> |
|||
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived > |
|||
select(typename ElseDerived::Scalar thenScalar, const DenseBase<ElseDerived>& elseMatrix) const; |
|||
|
|||
template<int p> RealScalar lpNorm() const; |
|||
|
|||
template<int RowFactor, int ColFactor> |
|||
const Replicate<Derived,RowFactor,ColFactor> replicate() const; |
|||
const Replicate<Derived,Dynamic,Dynamic> replicate(Index rowFacor,Index colFactor) const; |
|||
|
|||
typedef Reverse<Derived, BothDirections> ReverseReturnType; |
|||
typedef const Reverse<const Derived, BothDirections> ConstReverseReturnType; |
|||
ReverseReturnType reverse(); |
|||
ConstReverseReturnType reverse() const; |
|||
void reverseInPlace(); |
|||
|
|||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::DenseBase |
|||
# include "../plugins/BlockMethods.h" |
|||
# ifdef EIGEN_DENSEBASE_PLUGIN |
|||
# include EIGEN_DENSEBASE_PLUGIN |
|||
# endif |
|||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
|
|||
Block<Derived> corner(CornerType type, Index cRows, Index cCols); |
|||
const Block<Derived> corner(CornerType type, Index cRows, Index cCols) const; |
|||
template<int CRows, int CCols> |
|||
Block<Derived, CRows, CCols> corner(CornerType type); |
|||
template<int CRows, int CCols> |
|||
const Block<Derived, CRows, CCols> corner(CornerType type) const; |
|||
|
|||
#endif // EIGEN2_SUPPORT |
|||
|
|||
|
|||
// disable the use of evalTo for dense objects with a nice compilation error |
|||
template<typename Dest> inline void evalTo(Dest& ) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT((internal::is_same<Dest,void>::value),THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS); |
|||
} |
|||
|
|||
protected: |
|||
/** Default constructor. Do nothing. */ |
|||
DenseBase() |
|||
{ |
|||
/* Just checks for self-consistency of the flags. |
|||
* Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down |
|||
*/ |
|||
#ifdef EIGEN_INTERNAL_DEBUGGING |
|||
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, int(IsRowMajor)) |
|||
&& EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, int(!IsRowMajor))), |
|||
INVALID_STORAGE_ORDER_FOR_THIS_VECTOR_EXPRESSION) |
|||
#endif |
|||
} |
|||
|
|||
private: |
|||
explicit DenseBase(int); |
|||
DenseBase(int,int); |
|||
template<typename OtherDerived> explicit DenseBase(const DenseBase<OtherDerived>&); |
|||
}; |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_DENSEBASE_H |
@ -0,0 +1,754 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_DENSECOEFFSBASE_H |
|||
#define EIGEN_DENSECOEFFSBASE_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
template<typename T> struct add_const_on_value_type_if_arithmetic |
|||
{ |
|||
typedef typename conditional<is_arithmetic<T>::value, T, typename add_const_on_value_type<T>::type>::type type; |
|||
}; |
|||
} |
|||
|
|||
/** \brief Base class providing read-only coefficient access to matrices and arrays. |
|||
* \ingroup Core_Module |
|||
* \tparam Derived Type of the derived class |
|||
* \tparam #ReadOnlyAccessors Constant indicating read-only access |
|||
* |
|||
* This class defines the \c operator() \c const function and friends, which can be used to read specific |
|||
* entries of a matrix or array. |
|||
* |
|||
* \sa DenseCoeffsBase<Derived, WriteAccessors>, DenseCoeffsBase<Derived, DirectAccessors>, |
|||
* \ref TopicClassHierarchy |
|||
*/ |
|||
template<typename Derived> |
|||
class DenseCoeffsBase<Derived,ReadOnlyAccessors> : public EigenBase<Derived> |
|||
{ |
|||
public: |
|||
typedef typename internal::traits<Derived>::StorageKind StorageKind; |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
typedef typename internal::traits<Derived>::Scalar Scalar; |
|||
typedef typename internal::packet_traits<Scalar>::type PacketScalar; |
|||
|
|||
// Explanation for this CoeffReturnType typedef. |
|||
// - This is the return type of the coeff() method. |
|||
// - The LvalueBit means exactly that we can offer a coeffRef() method, which means exactly that we can get references |
|||
// to coeffs, which means exactly that we can have coeff() return a const reference (as opposed to returning a value). |
|||
// - The is_artihmetic check is required since "const int", "const double", etc. will cause warnings on some systems |
|||
// while the declaration of "const T", where T is a non arithmetic type does not. Always returning "const Scalar&" is |
|||
// not possible, since the underlying expressions might not offer a valid address the reference could be referring to. |
|||
typedef typename internal::conditional<bool(internal::traits<Derived>::Flags&LvalueBit), |
|||
const Scalar&, |
|||
typename internal::conditional<internal::is_arithmetic<Scalar>::value, Scalar, const Scalar>::type |
|||
>::type CoeffReturnType; |
|||
|
|||
typedef typename internal::add_const_on_value_type_if_arithmetic< |
|||
typename internal::packet_traits<Scalar>::type |
|||
>::type PacketReturnType; |
|||
|
|||
typedef EigenBase<Derived> Base; |
|||
using Base::rows; |
|||
using Base::cols; |
|||
using Base::size; |
|||
using Base::derived; |
|||
|
|||
EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner) const |
|||
{ |
|||
return int(Derived::RowsAtCompileTime) == 1 ? 0 |
|||
: int(Derived::ColsAtCompileTime) == 1 ? inner |
|||
: int(Derived::Flags)&RowMajorBit ? outer |
|||
: inner; |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner) const |
|||
{ |
|||
return int(Derived::ColsAtCompileTime) == 1 ? 0 |
|||
: int(Derived::RowsAtCompileTime) == 1 ? inner |
|||
: int(Derived::Flags)&RowMajorBit ? inner |
|||
: outer; |
|||
} |
|||
|
|||
/** Short version: don't use this function, use |
|||
* \link operator()(Index,Index) const \endlink instead. |
|||
* |
|||
* Long version: this function is similar to |
|||
* \link operator()(Index,Index) const \endlink, but without the assertion. |
|||
* Use this for limiting the performance cost of debugging code when doing |
|||
* repeated coefficient access. Only use this when it is guaranteed that the |
|||
* parameters \a row and \a col are in range. |
|||
* |
|||
* If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this |
|||
* function equivalent to \link operator()(Index,Index) const \endlink. |
|||
* |
|||
* \sa operator()(Index,Index) const, coeffRef(Index,Index), coeff(Index) const |
|||
*/ |
|||
EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const |
|||
{ |
|||
eigen_internal_assert(row >= 0 && row < rows() |
|||
&& col >= 0 && col < cols()); |
|||
return derived().coeff(row, col); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE CoeffReturnType coeffByOuterInner(Index outer, Index inner) const |
|||
{ |
|||
return coeff(rowIndexByOuterInner(outer, inner), |
|||
colIndexByOuterInner(outer, inner)); |
|||
} |
|||
|
|||
/** \returns the coefficient at given the given row and column. |
|||
* |
|||
* \sa operator()(Index,Index), operator[](Index) |
|||
*/ |
|||
EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const |
|||
{ |
|||
eigen_assert(row >= 0 && row < rows() |
|||
&& col >= 0 && col < cols()); |
|||
return derived().coeff(row, col); |
|||
} |
|||
|
|||
/** Short version: don't use this function, use |
|||
* \link operator[](Index) const \endlink instead. |
|||
* |
|||
* Long version: this function is similar to |
|||
* \link operator[](Index) const \endlink, but without the assertion. |
|||
* Use this for limiting the performance cost of debugging code when doing |
|||
* repeated coefficient access. Only use this when it is guaranteed that the |
|||
* parameter \a index is in range. |
|||
* |
|||
* If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this |
|||
* function equivalent to \link operator[](Index) const \endlink. |
|||
* |
|||
* \sa operator[](Index) const, coeffRef(Index), coeff(Index,Index) const |
|||
*/ |
|||
|
|||
EIGEN_STRONG_INLINE CoeffReturnType |
|||
coeff(Index index) const |
|||
{ |
|||
eigen_internal_assert(index >= 0 && index < size()); |
|||
return derived().coeff(index); |
|||
} |
|||
|
|||
|
|||
/** \returns the coefficient at given index. |
|||
* |
|||
* This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. |
|||
* |
|||
* \sa operator[](Index), operator()(Index,Index) const, x() const, y() const, |
|||
* z() const, w() const |
|||
*/ |
|||
|
|||
EIGEN_STRONG_INLINE CoeffReturnType |
|||
operator[](Index index) const |
|||
{ |
|||
#ifndef EIGEN2_SUPPORT |
|||
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, |
|||
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) |
|||
#endif |
|||
eigen_assert(index >= 0 && index < size()); |
|||
return derived().coeff(index); |
|||
} |
|||
|
|||
/** \returns the coefficient at given index. |
|||
* |
|||
* This is synonymous to operator[](Index) const. |
|||
* |
|||
* This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. |
|||
* |
|||
* \sa operator[](Index), operator()(Index,Index) const, x() const, y() const, |
|||
* z() const, w() const |
|||
*/ |
|||
|
|||
EIGEN_STRONG_INLINE CoeffReturnType |
|||
operator()(Index index) const |
|||
{ |
|||
eigen_assert(index >= 0 && index < size()); |
|||
return derived().coeff(index); |
|||
} |
|||
|
|||
/** equivalent to operator[](0). */ |
|||
|
|||
EIGEN_STRONG_INLINE CoeffReturnType |
|||
x() const { return (*this)[0]; } |
|||
|
|||
/** equivalent to operator[](1). */ |
|||
|
|||
EIGEN_STRONG_INLINE CoeffReturnType |
|||
y() const { return (*this)[1]; } |
|||
|
|||
/** equivalent to operator[](2). */ |
|||
|
|||
EIGEN_STRONG_INLINE CoeffReturnType |
|||
z() const { return (*this)[2]; } |
|||
|
|||
/** equivalent to operator[](3). */ |
|||
|
|||
EIGEN_STRONG_INLINE CoeffReturnType |
|||
w() const { return (*this)[3]; } |
|||
|
|||
/** \internal |
|||
* \returns the packet of coefficients starting at the given row and column. It is your responsibility |
|||
* to ensure that a packet really starts there. This method is only available on expressions having the |
|||
* PacketAccessBit. |
|||
* |
|||
* The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select |
|||
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets |
|||
* starting at an address which is a multiple of the packet size. |
|||
*/ |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketReturnType packet(Index row, Index col) const |
|||
{ |
|||
eigen_internal_assert(row >= 0 && row < rows() |
|||
&& col >= 0 && col < cols()); |
|||
return derived().template packet<LoadMode>(row,col); |
|||
} |
|||
|
|||
|
|||
/** \internal */ |
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketReturnType packetByOuterInner(Index outer, Index inner) const |
|||
{ |
|||
return packet<LoadMode>(rowIndexByOuterInner(outer, inner), |
|||
colIndexByOuterInner(outer, inner)); |
|||
} |
|||
|
|||
/** \internal |
|||
* \returns the packet of coefficients starting at the given index. It is your responsibility |
|||
* to ensure that a packet really starts there. This method is only available on expressions having the |
|||
* PacketAccessBit and the LinearAccessBit. |
|||
* |
|||
* The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select |
|||
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets |
|||
* starting at an address which is a multiple of the packet size. |
|||
*/ |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const |
|||
{ |
|||
eigen_internal_assert(index >= 0 && index < size()); |
|||
return derived().template packet<LoadMode>(index); |
|||
} |
|||
|
|||
protected: |
|||
// explanation: DenseBase is doing "using ..." on the methods from DenseCoeffsBase. |
|||
// But some methods are only available in the DirectAccess case. |
|||
// So we add dummy methods here with these names, so that "using... " doesn't fail. |
|||
// It's not private so that the child class DenseBase can access them, and it's not public |
|||
// either since it's an implementation detail, so has to be protected. |
|||
void coeffRef(); |
|||
void coeffRefByOuterInner(); |
|||
void writePacket(); |
|||
void writePacketByOuterInner(); |
|||
void copyCoeff(); |
|||
void copyCoeffByOuterInner(); |
|||
void copyPacket(); |
|||
void copyPacketByOuterInner(); |
|||
void stride(); |
|||
void innerStride(); |
|||
void outerStride(); |
|||
void rowStride(); |
|||
void colStride(); |
|||
}; |
|||
|
|||
/** \brief Base class providing read/write coefficient access to matrices and arrays. |
|||
* \ingroup Core_Module |
|||
* \tparam Derived Type of the derived class |
|||
* \tparam #WriteAccessors Constant indicating read/write access |
|||
* |
|||
* This class defines the non-const \c operator() function and friends, which can be used to write specific |
|||
* entries of a matrix or array. This class inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which |
|||
* defines the const variant for reading specific entries. |
|||
* |
|||
* \sa DenseCoeffsBase<Derived, DirectAccessors>, \ref TopicClassHierarchy |
|||
*/ |
|||
template<typename Derived> |
|||
class DenseCoeffsBase<Derived, WriteAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors> |
|||
{ |
|||
public: |
|||
|
|||
typedef DenseCoeffsBase<Derived, ReadOnlyAccessors> Base; |
|||
|
|||
typedef typename internal::traits<Derived>::StorageKind StorageKind; |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
typedef typename internal::traits<Derived>::Scalar Scalar; |
|||
typedef typename internal::packet_traits<Scalar>::type PacketScalar; |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
|
|||
using Base::coeff; |
|||
using Base::rows; |
|||
using Base::cols; |
|||
using Base::size; |
|||
using Base::derived; |
|||
using Base::rowIndexByOuterInner; |
|||
using Base::colIndexByOuterInner; |
|||
using Base::operator[]; |
|||
using Base::operator(); |
|||
using Base::x; |
|||
using Base::y; |
|||
using Base::z; |
|||
using Base::w; |
|||
|
|||
/** Short version: don't use this function, use |
|||
* \link operator()(Index,Index) \endlink instead. |
|||
* |
|||
* Long version: this function is similar to |
|||
* \link operator()(Index,Index) \endlink, but without the assertion. |
|||
* Use this for limiting the performance cost of debugging code when doing |
|||
* repeated coefficient access. Only use this when it is guaranteed that the |
|||
* parameters \a row and \a col are in range. |
|||
* |
|||
* If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this |
|||
* function equivalent to \link operator()(Index,Index) \endlink. |
|||
* |
|||
* \sa operator()(Index,Index), coeff(Index, Index) const, coeffRef(Index) |
|||
*/ |
|||
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) |
|||
{ |
|||
eigen_internal_assert(row >= 0 && row < rows() |
|||
&& col >= 0 && col < cols()); |
|||
return derived().coeffRef(row, col); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
coeffRefByOuterInner(Index outer, Index inner) |
|||
{ |
|||
return coeffRef(rowIndexByOuterInner(outer, inner), |
|||
colIndexByOuterInner(outer, inner)); |
|||
} |
|||
|
|||
/** \returns a reference to the coefficient at given the given row and column. |
|||
* |
|||
* \sa operator[](Index) |
|||
*/ |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
operator()(Index row, Index col) |
|||
{ |
|||
eigen_assert(row >= 0 && row < rows() |
|||
&& col >= 0 && col < cols()); |
|||
return derived().coeffRef(row, col); |
|||
} |
|||
|
|||
|
|||
/** Short version: don't use this function, use |
|||
* \link operator[](Index) \endlink instead. |
|||
* |
|||
* Long version: this function is similar to |
|||
* \link operator[](Index) \endlink, but without the assertion. |
|||
* Use this for limiting the performance cost of debugging code when doing |
|||
* repeated coefficient access. Only use this when it is guaranteed that the |
|||
* parameters \a row and \a col are in range. |
|||
* |
|||
* If EIGEN_INTERNAL_DEBUGGING is defined, an assertion will be made, making this |
|||
* function equivalent to \link operator[](Index) \endlink. |
|||
* |
|||
* \sa operator[](Index), coeff(Index) const, coeffRef(Index,Index) |
|||
*/ |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
coeffRef(Index index) |
|||
{ |
|||
eigen_internal_assert(index >= 0 && index < size()); |
|||
return derived().coeffRef(index); |
|||
} |
|||
|
|||
/** \returns a reference to the coefficient at given index. |
|||
* |
|||
* This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. |
|||
* |
|||
* \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w() |
|||
*/ |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
operator[](Index index) |
|||
{ |
|||
#ifndef EIGEN2_SUPPORT |
|||
EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime, |
|||
THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD) |
|||
#endif |
|||
eigen_assert(index >= 0 && index < size()); |
|||
return derived().coeffRef(index); |
|||
} |
|||
|
|||
/** \returns a reference to the coefficient at given index. |
|||
* |
|||
* This is synonymous to operator[](Index). |
|||
* |
|||
* This method is allowed only for vector expressions, and for matrix expressions having the LinearAccessBit. |
|||
* |
|||
* \sa operator[](Index) const, operator()(Index,Index), x(), y(), z(), w() |
|||
*/ |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
operator()(Index index) |
|||
{ |
|||
eigen_assert(index >= 0 && index < size()); |
|||
return derived().coeffRef(index); |
|||
} |
|||
|
|||
/** equivalent to operator[](0). */ |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
x() { return (*this)[0]; } |
|||
|
|||
/** equivalent to operator[](1). */ |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
y() { return (*this)[1]; } |
|||
|
|||
/** equivalent to operator[](2). */ |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
z() { return (*this)[2]; } |
|||
|
|||
/** equivalent to operator[](3). */ |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& |
|||
w() { return (*this)[3]; } |
|||
|
|||
/** \internal |
|||
* Stores the given packet of coefficients, at the given row and column of this expression. It is your responsibility |
|||
* to ensure that a packet really starts there. This method is only available on expressions having the |
|||
* PacketAccessBit. |
|||
* |
|||
* The \a LoadMode parameter may have the value \a #Aligned or \a #Unaligned. Its effect is to select |
|||
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets |
|||
* starting at an address which is a multiple of the packet size. |
|||
*/ |
|||
|
|||
template<int StoreMode> |
|||
EIGEN_STRONG_INLINE void writePacket |
|||
(Index row, Index col, const typename internal::packet_traits<Scalar>::type& x) |
|||
{ |
|||
eigen_internal_assert(row >= 0 && row < rows() |
|||
&& col >= 0 && col < cols()); |
|||
derived().template writePacket<StoreMode>(row,col,x); |
|||
} |
|||
|
|||
|
|||
/** \internal */ |
|||
template<int StoreMode> |
|||
EIGEN_STRONG_INLINE void writePacketByOuterInner |
|||
(Index outer, Index inner, const typename internal::packet_traits<Scalar>::type& x) |
|||
{ |
|||
writePacket<StoreMode>(rowIndexByOuterInner(outer, inner), |
|||
colIndexByOuterInner(outer, inner), |
|||
x); |
|||
} |
|||
|
|||
/** \internal |
|||
* Stores the given packet of coefficients, at the given index in this expression. It is your responsibility |
|||
* to ensure that a packet really starts there. This method is only available on expressions having the |
|||
* PacketAccessBit and the LinearAccessBit. |
|||
* |
|||
* The \a LoadMode parameter may have the value \a Aligned or \a Unaligned. Its effect is to select |
|||
* the appropriate vectorization instruction. Aligned access is faster, but is only possible for packets |
|||
* starting at an address which is a multiple of the packet size. |
|||
*/ |
|||
template<int StoreMode> |
|||
EIGEN_STRONG_INLINE void writePacket |
|||
(Index index, const typename internal::packet_traits<Scalar>::type& x) |
|||
{ |
|||
eigen_internal_assert(index >= 0 && index < size()); |
|||
derived().template writePacket<StoreMode>(index,x); |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
/** \internal Copies the coefficient at position (row,col) of other into *this. |
|||
* |
|||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code |
|||
* with usual assignments. |
|||
* |
|||
* Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. |
|||
*/ |
|||
|
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE void copyCoeff(Index row, Index col, const DenseBase<OtherDerived>& other) |
|||
{ |
|||
eigen_internal_assert(row >= 0 && row < rows() |
|||
&& col >= 0 && col < cols()); |
|||
derived().coeffRef(row, col) = other.derived().coeff(row, col); |
|||
} |
|||
|
|||
/** \internal Copies the coefficient at the given index of other into *this. |
|||
* |
|||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code |
|||
* with usual assignments. |
|||
* |
|||
* Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. |
|||
*/ |
|||
|
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE void copyCoeff(Index index, const DenseBase<OtherDerived>& other) |
|||
{ |
|||
eigen_internal_assert(index >= 0 && index < size()); |
|||
derived().coeffRef(index) = other.derived().coeff(index); |
|||
} |
|||
|
|||
|
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE void copyCoeffByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other) |
|||
{ |
|||
const Index row = rowIndexByOuterInner(outer,inner); |
|||
const Index col = colIndexByOuterInner(outer,inner); |
|||
// derived() is important here: copyCoeff() may be reimplemented in Derived! |
|||
derived().copyCoeff(row, col, other); |
|||
} |
|||
|
|||
/** \internal Copies the packet at position (row,col) of other into *this. |
|||
* |
|||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code |
|||
* with usual assignments. |
|||
* |
|||
* Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. |
|||
*/ |
|||
|
|||
template<typename OtherDerived, int StoreMode, int LoadMode> |
|||
EIGEN_STRONG_INLINE void copyPacket(Index row, Index col, const DenseBase<OtherDerived>& other) |
|||
{ |
|||
eigen_internal_assert(row >= 0 && row < rows() |
|||
&& col >= 0 && col < cols()); |
|||
derived().template writePacket<StoreMode>(row, col, |
|||
other.derived().template packet<LoadMode>(row, col)); |
|||
} |
|||
|
|||
/** \internal Copies the packet at the given index of other into *this. |
|||
* |
|||
* This method is overridden in SwapWrapper, allowing swap() assignments to share 99% of their code |
|||
* with usual assignments. |
|||
* |
|||
* Outside of this internal usage, this method has probably no usefulness. It is hidden in the public API dox. |
|||
*/ |
|||
|
|||
template<typename OtherDerived, int StoreMode, int LoadMode> |
|||
EIGEN_STRONG_INLINE void copyPacket(Index index, const DenseBase<OtherDerived>& other) |
|||
{ |
|||
eigen_internal_assert(index >= 0 && index < size()); |
|||
derived().template writePacket<StoreMode>(index, |
|||
other.derived().template packet<LoadMode>(index)); |
|||
} |
|||
|
|||
/** \internal */ |
|||
template<typename OtherDerived, int StoreMode, int LoadMode> |
|||
EIGEN_STRONG_INLINE void copyPacketByOuterInner(Index outer, Index inner, const DenseBase<OtherDerived>& other) |
|||
{ |
|||
const Index row = rowIndexByOuterInner(outer,inner); |
|||
const Index col = colIndexByOuterInner(outer,inner); |
|||
// derived() is important here: copyCoeff() may be reimplemented in Derived! |
|||
derived().template copyPacket< OtherDerived, StoreMode, LoadMode>(row, col, other); |
|||
} |
|||
#endif |
|||
|
|||
}; |
|||
|
|||
/** \brief Base class providing direct read-only coefficient access to matrices and arrays. |
|||
* \ingroup Core_Module |
|||
* \tparam Derived Type of the derived class |
|||
* \tparam #DirectAccessors Constant indicating direct access |
|||
* |
|||
* This class defines functions to work with strides which can be used to access entries directly. This class |
|||
* inherits DenseCoeffsBase<Derived, ReadOnlyAccessors> which defines functions to access entries read-only using |
|||
* \c operator() . |
|||
* |
|||
* \sa \ref TopicClassHierarchy |
|||
*/ |
|||
template<typename Derived> |
|||
class DenseCoeffsBase<Derived, DirectAccessors> : public DenseCoeffsBase<Derived, ReadOnlyAccessors> |
|||
{ |
|||
public: |
|||
|
|||
typedef DenseCoeffsBase<Derived, ReadOnlyAccessors> Base; |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
typedef typename internal::traits<Derived>::Scalar Scalar; |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
|
|||
using Base::rows; |
|||
using Base::cols; |
|||
using Base::size; |
|||
using Base::derived; |
|||
|
|||
/** \returns the pointer increment between two consecutive elements within a slice in the inner direction. |
|||
* |
|||
* \sa outerStride(), rowStride(), colStride() |
|||
*/ |
|||
inline Index innerStride() const |
|||
{ |
|||
return derived().innerStride(); |
|||
} |
|||
|
|||
/** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns |
|||
* in a column-major matrix). |
|||
* |
|||
* \sa innerStride(), rowStride(), colStride() |
|||
*/ |
|||
inline Index outerStride() const |
|||
{ |
|||
return derived().outerStride(); |
|||
} |
|||
|
|||
// FIXME shall we remove it ? |
|||
inline Index stride() const |
|||
{ |
|||
return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); |
|||
} |
|||
|
|||
/** \returns the pointer increment between two consecutive rows. |
|||
* |
|||
* \sa innerStride(), outerStride(), colStride() |
|||
*/ |
|||
inline Index rowStride() const |
|||
{ |
|||
return Derived::IsRowMajor ? outerStride() : innerStride(); |
|||
} |
|||
|
|||
/** \returns the pointer increment between two consecutive columns. |
|||
* |
|||
* \sa innerStride(), outerStride(), rowStride() |
|||
*/ |
|||
inline Index colStride() const |
|||
{ |
|||
return Derived::IsRowMajor ? innerStride() : outerStride(); |
|||
} |
|||
}; |
|||
|
|||
/** \brief Base class providing direct read/write coefficient access to matrices and arrays. |
|||
* \ingroup Core_Module |
|||
* \tparam Derived Type of the derived class |
|||
* \tparam #DirectWriteAccessors Constant indicating direct access |
|||
* |
|||
* This class defines functions to work with strides which can be used to access entries directly. This class |
|||
* inherits DenseCoeffsBase<Derived, WriteAccessors> which defines functions to access entries read/write using |
|||
* \c operator(). |
|||
* |
|||
* \sa \ref TopicClassHierarchy |
|||
*/ |
|||
template<typename Derived> |
|||
class DenseCoeffsBase<Derived, DirectWriteAccessors> |
|||
: public DenseCoeffsBase<Derived, WriteAccessors> |
|||
{ |
|||
public: |
|||
|
|||
typedef DenseCoeffsBase<Derived, WriteAccessors> Base; |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
typedef typename internal::traits<Derived>::Scalar Scalar; |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
|
|||
using Base::rows; |
|||
using Base::cols; |
|||
using Base::size; |
|||
using Base::derived; |
|||
|
|||
/** \returns the pointer increment between two consecutive elements within a slice in the inner direction. |
|||
* |
|||
* \sa outerStride(), rowStride(), colStride() |
|||
*/ |
|||
inline Index innerStride() const |
|||
{ |
|||
return derived().innerStride(); |
|||
} |
|||
|
|||
/** \returns the pointer increment between two consecutive inner slices (for example, between two consecutive columns |
|||
* in a column-major matrix). |
|||
* |
|||
* \sa innerStride(), rowStride(), colStride() |
|||
*/ |
|||
inline Index outerStride() const |
|||
{ |
|||
return derived().outerStride(); |
|||
} |
|||
|
|||
// FIXME shall we remove it ? |
|||
inline Index stride() const |
|||
{ |
|||
return Derived::IsVectorAtCompileTime ? innerStride() : outerStride(); |
|||
} |
|||
|
|||
/** \returns the pointer increment between two consecutive rows. |
|||
* |
|||
* \sa innerStride(), outerStride(), colStride() |
|||
*/ |
|||
inline Index rowStride() const |
|||
{ |
|||
return Derived::IsRowMajor ? outerStride() : innerStride(); |
|||
} |
|||
|
|||
/** \returns the pointer increment between two consecutive columns. |
|||
* |
|||
* \sa innerStride(), outerStride(), rowStride() |
|||
*/ |
|||
inline Index colStride() const |
|||
{ |
|||
return Derived::IsRowMajor ? innerStride() : outerStride(); |
|||
} |
|||
}; |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename Derived, bool JustReturnZero> |
|||
struct first_aligned_impl |
|||
{ |
|||
static inline typename Derived::Index run(const Derived&) |
|||
{ return 0; } |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
struct first_aligned_impl<Derived, false> |
|||
{ |
|||
static inline typename Derived::Index run(const Derived& m) |
|||
{ |
|||
return internal::first_aligned(&m.const_cast_derived().coeffRef(0,0), m.size()); |
|||
} |
|||
}; |
|||
|
|||
/** \internal \returns the index of the first element of the array that is well aligned for vectorization. |
|||
* |
|||
* There is also the variant first_aligned(const Scalar*, Integer) defined in Memory.h. See it for more |
|||
* documentation. |
|||
*/ |
|||
template<typename Derived> |
|||
static inline typename Derived::Index first_aligned(const Derived& m) |
|||
{ |
|||
return first_aligned_impl |
|||
<Derived, (Derived::Flags & AlignedBit) || !(Derived::Flags & DirectAccessBit)> |
|||
::run(m); |
|||
} |
|||
|
|||
template<typename Derived, bool HasDirectAccess = has_direct_access<Derived>::ret> |
|||
struct inner_stride_at_compile_time |
|||
{ |
|||
enum { ret = traits<Derived>::InnerStrideAtCompileTime }; |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
struct inner_stride_at_compile_time<Derived, false> |
|||
{ |
|||
enum { ret = 0 }; |
|||
}; |
|||
|
|||
template<typename Derived, bool HasDirectAccess = has_direct_access<Derived>::ret> |
|||
struct outer_stride_at_compile_time |
|||
{ |
|||
enum { ret = traits<Derived>::OuterStrideAtCompileTime }; |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
struct outer_stride_at_compile_time<Derived, false> |
|||
{ |
|||
enum { ret = 0 }; |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_DENSECOEFFSBASE_H |
@ -0,0 +1,303 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_MATRIXSTORAGE_H |
|||
#define EIGEN_MATRIXSTORAGE_H |
|||
|
|||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN |
|||
#define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN; |
|||
#else |
|||
#define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN |
|||
#endif |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
|
|||
struct constructor_without_unaligned_array_assert {}; |
|||
|
|||
/** \internal |
|||
* Static array. If the MatrixOrArrayOptions require auto-alignment, the array will be automatically aligned: |
|||
* to 16 bytes boundary if the total size is a multiple of 16 bytes. |
|||
*/ |
|||
template <typename T, int Size, int MatrixOrArrayOptions, |
|||
int Alignment = (MatrixOrArrayOptions&DontAlign) ? 0 |
|||
: (((Size*sizeof(T))%16)==0) ? 16 |
|||
: 0 > |
|||
struct plain_array |
|||
{ |
|||
T array[Size]; |
|||
plain_array() {} |
|||
plain_array(constructor_without_unaligned_array_assert) {} |
|||
}; |
|||
|
|||
#ifdef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT |
|||
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) |
|||
#else |
|||
#define EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(sizemask) \ |
|||
eigen_assert((reinterpret_cast<size_t>(array) & sizemask) == 0 \ |
|||
&& "this assertion is explained here: " \ |
|||
"http://eigen.tuxfamily.org/dox-devel/TopicUnalignedArrayAssert.html" \ |
|||
" **** READ THIS WEB PAGE !!! ****"); |
|||
#endif |
|||
|
|||
template <typename T, int Size, int MatrixOrArrayOptions> |
|||
struct plain_array<T, Size, MatrixOrArrayOptions, 16> |
|||
{ |
|||
EIGEN_USER_ALIGN16 T array[Size]; |
|||
plain_array() { EIGEN_MAKE_UNALIGNED_ARRAY_ASSERT(0xf) } |
|||
plain_array(constructor_without_unaligned_array_assert) {} |
|||
}; |
|||
|
|||
template <typename T, int MatrixOrArrayOptions, int Alignment> |
|||
struct plain_array<T, 0, MatrixOrArrayOptions, Alignment> |
|||
{ |
|||
EIGEN_USER_ALIGN16 T array[1]; |
|||
plain_array() {} |
|||
plain_array(constructor_without_unaligned_array_assert) {} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/** \internal |
|||
* |
|||
* \class DenseStorage |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Stores the data of a matrix |
|||
* |
|||
* This class stores the data of fixed-size, dynamic-size or mixed matrices |
|||
* in a way as compact as possible. |
|||
* |
|||
* \sa Matrix |
|||
*/ |
|||
template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage; |
|||
|
|||
// purely fixed-size matrix |
|||
template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseStorage |
|||
{ |
|||
internal::plain_array<T,Size,_Options> m_data; |
|||
public: |
|||
inline explicit DenseStorage() {} |
|||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) |
|||
: m_data(internal::constructor_without_unaligned_array_assert()) {} |
|||
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {} |
|||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); } |
|||
static inline DenseIndex rows(void) {return _Rows;} |
|||
static inline DenseIndex cols(void) {return _Cols;} |
|||
inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {} |
|||
inline void resize(DenseIndex,DenseIndex,DenseIndex) {} |
|||
inline const T *data() const { return m_data.array; } |
|||
inline T *data() { return m_data.array; } |
|||
}; |
|||
|
|||
// null matrix |
|||
template<typename T, int _Rows, int _Cols, int _Options> class DenseStorage<T, 0, _Rows, _Cols, _Options> |
|||
{ |
|||
public: |
|||
inline explicit DenseStorage() {} |
|||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) {} |
|||
inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {} |
|||
inline void swap(DenseStorage& ) {} |
|||
static inline DenseIndex rows(void) {return _Rows;} |
|||
static inline DenseIndex cols(void) {return _Cols;} |
|||
inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {} |
|||
inline void resize(DenseIndex,DenseIndex,DenseIndex) {} |
|||
inline const T *data() const { return 0; } |
|||
inline T *data() { return 0; } |
|||
}; |
|||
|
|||
// more specializations for null matrices; these are necessary to resolve ambiguities |
|||
template<typename T, int _Options> class DenseStorage<T, 0, Dynamic, Dynamic, _Options> |
|||
: public DenseStorage<T, 0, 0, 0, _Options> { }; |
|||
|
|||
template<typename T, int _Rows, int _Options> class DenseStorage<T, 0, _Rows, Dynamic, _Options> |
|||
: public DenseStorage<T, 0, 0, 0, _Options> { }; |
|||
|
|||
template<typename T, int _Cols, int _Options> class DenseStorage<T, 0, Dynamic, _Cols, _Options> |
|||
: public DenseStorage<T, 0, 0, 0, _Options> { }; |
|||
|
|||
// dynamic-size matrix with fixed-size storage |
|||
template<typename T, int Size, int _Options> class DenseStorage<T, Size, Dynamic, Dynamic, _Options> |
|||
{ |
|||
internal::plain_array<T,Size,_Options> m_data; |
|||
DenseIndex m_rows; |
|||
DenseIndex m_cols; |
|||
public: |
|||
inline explicit DenseStorage() : m_rows(0), m_cols(0) {} |
|||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) |
|||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0), m_cols(0) {} |
|||
inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex cols) : m_rows(rows), m_cols(cols) {} |
|||
inline void swap(DenseStorage& other) |
|||
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); } |
|||
inline DenseIndex rows(void) const {return m_rows;} |
|||
inline DenseIndex cols(void) const {return m_cols;} |
|||
inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; } |
|||
inline void resize(DenseIndex, DenseIndex rows, DenseIndex cols) { m_rows = rows; m_cols = cols; } |
|||
inline const T *data() const { return m_data.array; } |
|||
inline T *data() { return m_data.array; } |
|||
}; |
|||
|
|||
// dynamic-size matrix with fixed-size storage and fixed width |
|||
template<typename T, int Size, int _Cols, int _Options> class DenseStorage<T, Size, Dynamic, _Cols, _Options> |
|||
{ |
|||
internal::plain_array<T,Size,_Options> m_data; |
|||
DenseIndex m_rows; |
|||
public: |
|||
inline explicit DenseStorage() : m_rows(0) {} |
|||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) |
|||
: m_data(internal::constructor_without_unaligned_array_assert()), m_rows(0) {} |
|||
inline DenseStorage(DenseIndex, DenseIndex rows, DenseIndex) : m_rows(rows) {} |
|||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); } |
|||
inline DenseIndex rows(void) const {return m_rows;} |
|||
inline DenseIndex cols(void) const {return _Cols;} |
|||
inline void conservativeResize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; } |
|||
inline void resize(DenseIndex, DenseIndex rows, DenseIndex) { m_rows = rows; } |
|||
inline const T *data() const { return m_data.array; } |
|||
inline T *data() { return m_data.array; } |
|||
}; |
|||
|
|||
// dynamic-size matrix with fixed-size storage and fixed height |
|||
template<typename T, int Size, int _Rows, int _Options> class DenseStorage<T, Size, _Rows, Dynamic, _Options> |
|||
{ |
|||
internal::plain_array<T,Size,_Options> m_data; |
|||
DenseIndex m_cols; |
|||
public: |
|||
inline explicit DenseStorage() : m_cols(0) {} |
|||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) |
|||
: m_data(internal::constructor_without_unaligned_array_assert()), m_cols(0) {} |
|||
inline DenseStorage(DenseIndex, DenseIndex, DenseIndex cols) : m_cols(cols) {} |
|||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); } |
|||
inline DenseIndex rows(void) const {return _Rows;} |
|||
inline DenseIndex cols(void) const {return m_cols;} |
|||
inline void conservativeResize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; } |
|||
inline void resize(DenseIndex, DenseIndex, DenseIndex cols) { m_cols = cols; } |
|||
inline const T *data() const { return m_data.array; } |
|||
inline T *data() { return m_data.array; } |
|||
}; |
|||
|
|||
// purely dynamic matrix. |
|||
template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynamic, _Options> |
|||
{ |
|||
T *m_data; |
|||
DenseIndex m_rows; |
|||
DenseIndex m_cols; |
|||
public: |
|||
inline explicit DenseStorage() : m_data(0), m_rows(0), m_cols(0) {} |
|||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) |
|||
: m_data(0), m_rows(0), m_cols(0) {} |
|||
inline DenseStorage(DenseIndex size, DenseIndex rows, DenseIndex cols) |
|||
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows), m_cols(cols) |
|||
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN } |
|||
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); } |
|||
inline void swap(DenseStorage& other) |
|||
{ std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); std::swap(m_cols,other.m_cols); } |
|||
inline DenseIndex rows(void) const {return m_rows;} |
|||
inline DenseIndex cols(void) const {return m_cols;} |
|||
inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex cols) |
|||
{ |
|||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*m_cols); |
|||
m_rows = rows; |
|||
m_cols = cols; |
|||
} |
|||
void resize(DenseIndex size, DenseIndex rows, DenseIndex cols) |
|||
{ |
|||
if(size != m_rows*m_cols) |
|||
{ |
|||
internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, m_rows*m_cols); |
|||
if (size) |
|||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size); |
|||
else |
|||
m_data = 0; |
|||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN |
|||
} |
|||
m_rows = rows; |
|||
m_cols = cols; |
|||
} |
|||
inline const T *data() const { return m_data; } |
|||
inline T *data() { return m_data; } |
|||
}; |
|||
|
|||
// matrix with dynamic width and fixed height (so that matrix has dynamic size). |
|||
template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Rows, Dynamic, _Options> |
|||
{ |
|||
T *m_data; |
|||
DenseIndex m_cols; |
|||
public: |
|||
inline explicit DenseStorage() : m_data(0), m_cols(0) {} |
|||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {} |
|||
inline DenseStorage(DenseIndex size, DenseIndex, DenseIndex cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(cols) |
|||
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN } |
|||
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); } |
|||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); } |
|||
static inline DenseIndex rows(void) {return _Rows;} |
|||
inline DenseIndex cols(void) const {return m_cols;} |
|||
inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex cols) |
|||
{ |
|||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, _Rows*m_cols); |
|||
m_cols = cols; |
|||
} |
|||
EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex, DenseIndex cols) |
|||
{ |
|||
if(size != _Rows*m_cols) |
|||
{ |
|||
internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Rows*m_cols); |
|||
if (size) |
|||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size); |
|||
else |
|||
m_data = 0; |
|||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN |
|||
} |
|||
m_cols = cols; |
|||
} |
|||
inline const T *data() const { return m_data; } |
|||
inline T *data() { return m_data; } |
|||
}; |
|||
|
|||
// matrix with dynamic height and fixed width (so that matrix has dynamic size). |
|||
template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dynamic, _Cols, _Options> |
|||
{ |
|||
T *m_data; |
|||
DenseIndex m_rows; |
|||
public: |
|||
inline explicit DenseStorage() : m_data(0), m_rows(0) {} |
|||
inline DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {} |
|||
inline DenseStorage(DenseIndex size, DenseIndex rows, DenseIndex) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows) |
|||
{ EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN } |
|||
inline ~DenseStorage() { internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); } |
|||
inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); } |
|||
inline DenseIndex rows(void) const {return m_rows;} |
|||
static inline DenseIndex cols(void) {return _Cols;} |
|||
inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex) |
|||
{ |
|||
m_data = internal::conditional_aligned_realloc_new_auto<T,(_Options&DontAlign)==0>(m_data, size, m_rows*_Cols); |
|||
m_rows = rows; |
|||
} |
|||
EIGEN_STRONG_INLINE void resize(DenseIndex size, DenseIndex rows, DenseIndex) |
|||
{ |
|||
if(size != m_rows*_Cols) |
|||
{ |
|||
internal::conditional_aligned_delete_auto<T,(_Options&DontAlign)==0>(m_data, _Cols*m_rows); |
|||
if (size) |
|||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size); |
|||
else |
|||
m_data = 0; |
|||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN |
|||
} |
|||
m_rows = rows; |
|||
} |
|||
inline const T *data() const { return m_data; } |
|||
inline T *data() { return m_data; } |
|||
}; |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_MATRIX_H |
@ -0,0 +1,236 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_DIAGONAL_H |
|||
#define EIGEN_DIAGONAL_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class Diagonal |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of a diagonal/subdiagonal/superdiagonal in a matrix |
|||
* |
|||
* \param MatrixType the type of the object in which we are taking a sub/main/super diagonal |
|||
* \param DiagIndex the index of the sub/super diagonal. The default is 0 and it means the main diagonal. |
|||
* A positive value means a superdiagonal, a negative value means a subdiagonal. |
|||
* You can also use Dynamic so the index can be set at runtime. |
|||
* |
|||
* The matrix is not required to be square. |
|||
* |
|||
* This class represents an expression of the main diagonal, or any sub/super diagonal |
|||
* of a square matrix. It is the return type of MatrixBase::diagonal() and MatrixBase::diagonal(Index) and most of the |
|||
* time this is the only way it is used. |
|||
* |
|||
* \sa MatrixBase::diagonal(), MatrixBase::diagonal(Index) |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename MatrixType, int DiagIndex> |
|||
struct traits<Diagonal<MatrixType,DiagIndex> > |
|||
: traits<MatrixType> |
|||
{ |
|||
typedef typename nested<MatrixType>::type MatrixTypeNested; |
|||
typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested; |
|||
typedef typename MatrixType::StorageKind StorageKind; |
|||
enum { |
|||
RowsAtCompileTime = (int(DiagIndex) == Dynamic || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic |
|||
: (EIGEN_PLAIN_ENUM_MIN(MatrixType::RowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0), |
|||
MatrixType::ColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))), |
|||
ColsAtCompileTime = 1, |
|||
MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic |
|||
: DiagIndex == Dynamic ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime, |
|||
MatrixType::MaxColsAtCompileTime) |
|||
: (EIGEN_PLAIN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0), |
|||
MatrixType::MaxColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))), |
|||
MaxColsAtCompileTime = 1, |
|||
MaskLvalueBit = is_lvalue<MatrixType>::value ? LvalueBit : 0, |
|||
Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit | MaskLvalueBit | DirectAccessBit) & ~RowMajorBit, |
|||
CoeffReadCost = _MatrixTypeNested::CoeffReadCost, |
|||
MatrixTypeOuterStride = outer_stride_at_compile_time<MatrixType>::ret, |
|||
InnerStrideAtCompileTime = MatrixTypeOuterStride == Dynamic ? Dynamic : MatrixTypeOuterStride+1, |
|||
OuterStrideAtCompileTime = 0 |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename MatrixType, int DiagIndex> class Diagonal |
|||
: public internal::dense_xpr_base< Diagonal<MatrixType,DiagIndex> >::type |
|||
{ |
|||
public: |
|||
|
|||
typedef typename internal::dense_xpr_base<Diagonal>::type Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Diagonal) |
|||
|
|||
inline Diagonal(MatrixType& matrix, Index index = DiagIndex) : m_matrix(matrix), m_index(index) {} |
|||
|
|||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Diagonal) |
|||
|
|||
inline Index rows() const |
|||
{ return m_index.value()<0 ? (std::min)(m_matrix.cols(),m_matrix.rows()+m_index.value()) : (std::min)(m_matrix.rows(),m_matrix.cols()-m_index.value()); } |
|||
|
|||
inline Index cols() const { return 1; } |
|||
|
|||
inline Index innerStride() const |
|||
{ |
|||
return m_matrix.outerStride() + 1; |
|||
} |
|||
|
|||
inline Index outerStride() const |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
typedef typename internal::conditional< |
|||
internal::is_lvalue<MatrixType>::value, |
|||
Scalar, |
|||
const Scalar |
|||
>::type ScalarWithConstIfNotLvalue; |
|||
|
|||
inline ScalarWithConstIfNotLvalue* data() { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); } |
|||
inline const Scalar* data() const { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); } |
|||
|
|||
inline Scalar& coeffRef(Index row, Index) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_LVALUE(MatrixType) |
|||
return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset()); |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index row, Index) const |
|||
{ |
|||
return m_matrix.const_cast_derived().coeffRef(row+rowOffset(), row+colOffset()); |
|||
} |
|||
|
|||
inline CoeffReturnType coeff(Index row, Index) const |
|||
{ |
|||
return m_matrix.coeff(row+rowOffset(), row+colOffset()); |
|||
} |
|||
|
|||
inline Scalar& coeffRef(Index index) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_LVALUE(MatrixType) |
|||
return m_matrix.const_cast_derived().coeffRef(index+rowOffset(), index+colOffset()); |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index index) const |
|||
{ |
|||
return m_matrix.const_cast_derived().coeffRef(index+rowOffset(), index+colOffset()); |
|||
} |
|||
|
|||
inline CoeffReturnType coeff(Index index) const |
|||
{ |
|||
return m_matrix.coeff(index+rowOffset(), index+colOffset()); |
|||
} |
|||
|
|||
const typename internal::remove_all<typename MatrixType::Nested>::type& |
|||
nestedExpression() const |
|||
{ |
|||
return m_matrix; |
|||
} |
|||
|
|||
int index() const |
|||
{ |
|||
return m_index.value(); |
|||
} |
|||
|
|||
protected: |
|||
typename MatrixType::Nested m_matrix; |
|||
const internal::variable_if_dynamic<Index, DiagIndex> m_index; |
|||
|
|||
private: |
|||
// some compilers may fail to optimize std::max etc in case of compile-time constants... |
|||
EIGEN_STRONG_INLINE Index absDiagIndex() const { return m_index.value()>0 ? m_index.value() : -m_index.value(); } |
|||
EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value()>0 ? 0 : -m_index.value(); } |
|||
EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value()>0 ? m_index.value() : 0; } |
|||
// triger a compile time error is someone try to call packet |
|||
template<int LoadMode> typename MatrixType::PacketReturnType packet(Index) const; |
|||
template<int LoadMode> typename MatrixType::PacketReturnType packet(Index,Index) const; |
|||
}; |
|||
|
|||
/** \returns an expression of the main diagonal of the matrix \c *this |
|||
* |
|||
* \c *this is not required to be square. |
|||
* |
|||
* Example: \include MatrixBase_diagonal.cpp |
|||
* Output: \verbinclude MatrixBase_diagonal.out |
|||
* |
|||
* \sa class Diagonal */ |
|||
template<typename Derived> |
|||
inline typename MatrixBase<Derived>::DiagonalReturnType |
|||
MatrixBase<Derived>::diagonal() |
|||
{ |
|||
return derived(); |
|||
} |
|||
|
|||
/** This is the const version of diagonal(). */ |
|||
template<typename Derived> |
|||
inline const typename MatrixBase<Derived>::ConstDiagonalReturnType |
|||
MatrixBase<Derived>::diagonal() const |
|||
{ |
|||
return ConstDiagonalReturnType(derived()); |
|||
} |
|||
|
|||
/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this |
|||
* |
|||
* \c *this is not required to be square. |
|||
* |
|||
* The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0 |
|||
* and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal. |
|||
* |
|||
* Example: \include MatrixBase_diagonal_int.cpp |
|||
* Output: \verbinclude MatrixBase_diagonal_int.out |
|||
* |
|||
* \sa MatrixBase::diagonal(), class Diagonal */ |
|||
template<typename Derived> |
|||
inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Dynamic>::Type |
|||
MatrixBase<Derived>::diagonal(Index index) |
|||
{ |
|||
return typename DiagonalIndexReturnType<Dynamic>::Type(derived(), index); |
|||
} |
|||
|
|||
/** This is the const version of diagonal(Index). */ |
|||
template<typename Derived> |
|||
inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Dynamic>::Type |
|||
MatrixBase<Derived>::diagonal(Index index) const |
|||
{ |
|||
return typename ConstDiagonalIndexReturnType<Dynamic>::Type(derived(), index); |
|||
} |
|||
|
|||
/** \returns an expression of the \a DiagIndex-th sub or super diagonal of the matrix \c *this |
|||
* |
|||
* \c *this is not required to be square. |
|||
* |
|||
* The template parameter \a DiagIndex represent a super diagonal if \a DiagIndex > 0 |
|||
* and a sub diagonal otherwise. \a DiagIndex == 0 is equivalent to the main diagonal. |
|||
* |
|||
* Example: \include MatrixBase_diagonal_template_int.cpp |
|||
* Output: \verbinclude MatrixBase_diagonal_template_int.out |
|||
* |
|||
* \sa MatrixBase::diagonal(), class Diagonal */ |
|||
template<typename Derived> |
|||
template<int Index> |
|||
inline typename MatrixBase<Derived>::template DiagonalIndexReturnType<Index>::Type |
|||
MatrixBase<Derived>::diagonal() |
|||
{ |
|||
return derived(); |
|||
} |
|||
|
|||
/** This is the const version of diagonal<int>(). */ |
|||
template<typename Derived> |
|||
template<int Index> |
|||
inline typename MatrixBase<Derived>::template ConstDiagonalIndexReturnType<Index>::Type |
|||
MatrixBase<Derived>::diagonal() const |
|||
{ |
|||
return derived(); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_DIAGONAL_H |
@ -0,0 +1,307 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_DIAGONALMATRIX_H |
|||
#define EIGEN_DIAGONALMATRIX_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
template<typename Derived> |
|||
class DiagonalBase : public EigenBase<Derived> |
|||
{ |
|||
public: |
|||
typedef typename internal::traits<Derived>::DiagonalVectorType DiagonalVectorType; |
|||
typedef typename DiagonalVectorType::Scalar Scalar; |
|||
typedef typename DiagonalVectorType::RealScalar RealScalar; |
|||
typedef typename internal::traits<Derived>::StorageKind StorageKind; |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
|
|||
enum { |
|||
RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, |
|||
ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, |
|||
MaxRowsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime, |
|||
MaxColsAtCompileTime = DiagonalVectorType::MaxSizeAtCompileTime, |
|||
IsVectorAtCompileTime = 0, |
|||
Flags = 0 |
|||
}; |
|||
|
|||
typedef Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, 0, MaxRowsAtCompileTime, MaxColsAtCompileTime> DenseMatrixType; |
|||
typedef DenseMatrixType DenseType; |
|||
typedef DiagonalMatrix<Scalar,DiagonalVectorType::SizeAtCompileTime,DiagonalVectorType::MaxSizeAtCompileTime> PlainObject; |
|||
|
|||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); } |
|||
inline Derived& derived() { return *static_cast<Derived*>(this); } |
|||
|
|||
DenseMatrixType toDenseMatrix() const { return derived(); } |
|||
template<typename DenseDerived> |
|||
void evalTo(MatrixBase<DenseDerived> &other) const; |
|||
template<typename DenseDerived> |
|||
void addTo(MatrixBase<DenseDerived> &other) const |
|||
{ other.diagonal() += diagonal(); } |
|||
template<typename DenseDerived> |
|||
void subTo(MatrixBase<DenseDerived> &other) const |
|||
{ other.diagonal() -= diagonal(); } |
|||
|
|||
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); } |
|||
inline DiagonalVectorType& diagonal() { return derived().diagonal(); } |
|||
|
|||
inline Index rows() const { return diagonal().size(); } |
|||
inline Index cols() const { return diagonal().size(); } |
|||
|
|||
template<typename MatrixDerived> |
|||
const DiagonalProduct<MatrixDerived, Derived, OnTheLeft> |
|||
operator*(const MatrixBase<MatrixDerived> &matrix) const; |
|||
|
|||
inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const DiagonalVectorType> > |
|||
inverse() const |
|||
{ |
|||
return diagonal().cwiseInverse(); |
|||
} |
|||
|
|||
inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DiagonalVectorType> > |
|||
operator*(const Scalar& scalar) const |
|||
{ |
|||
return diagonal() * scalar; |
|||
} |
|||
friend inline const DiagonalWrapper<const CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, const DiagonalVectorType> > |
|||
operator*(const Scalar& scalar, const DiagonalBase& other) |
|||
{ |
|||
return other.diagonal() * scalar; |
|||
} |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
template<typename OtherDerived> |
|||
bool isApprox(const DiagonalBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const |
|||
{ |
|||
return diagonal().isApprox(other.diagonal(), precision); |
|||
} |
|||
template<typename OtherDerived> |
|||
bool isApprox(const MatrixBase<OtherDerived>& other, typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) const |
|||
{ |
|||
return toDenseMatrix().isApprox(other, precision); |
|||
} |
|||
#endif |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
template<typename DenseDerived> |
|||
void DiagonalBase<Derived>::evalTo(MatrixBase<DenseDerived> &other) const |
|||
{ |
|||
other.setZero(); |
|||
other.diagonal() = diagonal(); |
|||
} |
|||
#endif |
|||
|
|||
/** \class DiagonalMatrix |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Represents a diagonal matrix with its storage |
|||
* |
|||
* \param _Scalar the type of coefficients |
|||
* \param SizeAtCompileTime the dimension of the matrix, or Dynamic |
|||
* \param MaxSizeAtCompileTime the dimension of the matrix, or Dynamic. This parameter is optional and defaults |
|||
* to SizeAtCompileTime. Most of the time, you do not need to specify it. |
|||
* |
|||
* \sa class DiagonalWrapper |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime> |
|||
struct traits<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> > |
|||
: traits<Matrix<_Scalar,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> > |
|||
{ |
|||
typedef Matrix<_Scalar,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1> DiagonalVectorType; |
|||
typedef Dense StorageKind; |
|||
typedef DenseIndex Index; |
|||
enum { |
|||
Flags = LvalueBit |
|||
}; |
|||
}; |
|||
} |
|||
template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime> |
|||
class DiagonalMatrix |
|||
: public DiagonalBase<DiagonalMatrix<_Scalar,SizeAtCompileTime,MaxSizeAtCompileTime> > |
|||
{ |
|||
public: |
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
typedef typename internal::traits<DiagonalMatrix>::DiagonalVectorType DiagonalVectorType; |
|||
typedef const DiagonalMatrix& Nested; |
|||
typedef _Scalar Scalar; |
|||
typedef typename internal::traits<DiagonalMatrix>::StorageKind StorageKind; |
|||
typedef typename internal::traits<DiagonalMatrix>::Index Index; |
|||
#endif |
|||
|
|||
protected: |
|||
|
|||
DiagonalVectorType m_diagonal; |
|||
|
|||
public: |
|||
|
|||
/** const version of diagonal(). */ |
|||
inline const DiagonalVectorType& diagonal() const { return m_diagonal; } |
|||
/** \returns a reference to the stored vector of diagonal coefficients. */ |
|||
inline DiagonalVectorType& diagonal() { return m_diagonal; } |
|||
|
|||
/** Default constructor without initialization */ |
|||
inline DiagonalMatrix() {} |
|||
|
|||
/** Constructs a diagonal matrix with given dimension */ |
|||
inline DiagonalMatrix(Index dim) : m_diagonal(dim) {} |
|||
|
|||
/** 2D constructor. */ |
|||
inline DiagonalMatrix(const Scalar& x, const Scalar& y) : m_diagonal(x,y) {} |
|||
|
|||
/** 3D constructor. */ |
|||
inline DiagonalMatrix(const Scalar& x, const Scalar& y, const Scalar& z) : m_diagonal(x,y,z) {} |
|||
|
|||
/** Copy constructor. */ |
|||
template<typename OtherDerived> |
|||
inline DiagonalMatrix(const DiagonalBase<OtherDerived>& other) : m_diagonal(other.diagonal()) {} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** copy constructor. prevent a default copy constructor from hiding the other templated constructor */ |
|||
inline DiagonalMatrix(const DiagonalMatrix& other) : m_diagonal(other.diagonal()) {} |
|||
#endif |
|||
|
|||
/** generic constructor from expression of the diagonal coefficients */ |
|||
template<typename OtherDerived> |
|||
explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : m_diagonal(other) |
|||
{} |
|||
|
|||
/** Copy operator. */ |
|||
template<typename OtherDerived> |
|||
DiagonalMatrix& operator=(const DiagonalBase<OtherDerived>& other) |
|||
{ |
|||
m_diagonal = other.diagonal(); |
|||
return *this; |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** This is a special case of the templated operator=. Its purpose is to |
|||
* prevent a default operator= from hiding the templated operator=. |
|||
*/ |
|||
DiagonalMatrix& operator=(const DiagonalMatrix& other) |
|||
{ |
|||
m_diagonal = other.diagonal(); |
|||
return *this; |
|||
} |
|||
#endif |
|||
|
|||
/** Resizes to given size. */ |
|||
inline void resize(Index size) { m_diagonal.resize(size); } |
|||
/** Sets all coefficients to zero. */ |
|||
inline void setZero() { m_diagonal.setZero(); } |
|||
/** Resizes and sets all coefficients to zero. */ |
|||
inline void setZero(Index size) { m_diagonal.setZero(size); } |
|||
/** Sets this matrix to be the identity matrix of the current size. */ |
|||
inline void setIdentity() { m_diagonal.setOnes(); } |
|||
/** Sets this matrix to be the identity matrix of the given size. */ |
|||
inline void setIdentity(Index size) { m_diagonal.setOnes(size); } |
|||
}; |
|||
|
|||
/** \class DiagonalWrapper |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of a diagonal matrix |
|||
* |
|||
* \param _DiagonalVectorType the type of the vector of diagonal coefficients |
|||
* |
|||
* This class is an expression of a diagonal matrix, but not storing its own vector of diagonal coefficients, |
|||
* instead wrapping an existing vector expression. It is the return type of MatrixBase::asDiagonal() |
|||
* and most of the time this is the only way that it is used. |
|||
* |
|||
* \sa class DiagonalMatrix, class DiagonalBase, MatrixBase::asDiagonal() |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename _DiagonalVectorType> |
|||
struct traits<DiagonalWrapper<_DiagonalVectorType> > |
|||
{ |
|||
typedef _DiagonalVectorType DiagonalVectorType; |
|||
typedef typename DiagonalVectorType::Scalar Scalar; |
|||
typedef typename DiagonalVectorType::Index Index; |
|||
typedef typename DiagonalVectorType::StorageKind StorageKind; |
|||
enum { |
|||
RowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, |
|||
ColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, |
|||
MaxRowsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, |
|||
MaxColsAtCompileTime = DiagonalVectorType::SizeAtCompileTime, |
|||
Flags = traits<DiagonalVectorType>::Flags & LvalueBit |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename _DiagonalVectorType> |
|||
class DiagonalWrapper |
|||
: public DiagonalBase<DiagonalWrapper<_DiagonalVectorType> >, internal::no_assignment_operator |
|||
{ |
|||
public: |
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
typedef _DiagonalVectorType DiagonalVectorType; |
|||
typedef DiagonalWrapper Nested; |
|||
#endif |
|||
|
|||
/** Constructor from expression of diagonal coefficients to wrap. */ |
|||
inline DiagonalWrapper(DiagonalVectorType& diagonal) : m_diagonal(diagonal) {} |
|||
|
|||
/** \returns a const reference to the wrapped expression of diagonal coefficients. */ |
|||
const DiagonalVectorType& diagonal() const { return m_diagonal; } |
|||
|
|||
protected: |
|||
typename DiagonalVectorType::Nested m_diagonal; |
|||
}; |
|||
|
|||
/** \returns a pseudo-expression of a diagonal matrix with *this as vector of diagonal coefficients |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* Example: \include MatrixBase_asDiagonal.cpp |
|||
* Output: \verbinclude MatrixBase_asDiagonal.out |
|||
* |
|||
* \sa class DiagonalWrapper, class DiagonalMatrix, diagonal(), isDiagonal() |
|||
**/ |
|||
template<typename Derived> |
|||
inline const DiagonalWrapper<const Derived> |
|||
MatrixBase<Derived>::asDiagonal() const |
|||
{ |
|||
return derived(); |
|||
} |
|||
|
|||
/** \returns true if *this is approximately equal to a diagonal matrix, |
|||
* within the precision given by \a prec. |
|||
* |
|||
* Example: \include MatrixBase_isDiagonal.cpp |
|||
* Output: \verbinclude MatrixBase_isDiagonal.out |
|||
* |
|||
* \sa asDiagonal() |
|||
*/ |
|||
template<typename Derived> |
|||
bool MatrixBase<Derived>::isDiagonal(RealScalar prec) const |
|||
{ |
|||
if(cols() != rows()) return false; |
|||
RealScalar maxAbsOnDiagonal = static_cast<RealScalar>(-1); |
|||
for(Index j = 0; j < cols(); ++j) |
|||
{ |
|||
RealScalar absOnDiagonal = internal::abs(coeff(j,j)); |
|||
if(absOnDiagonal > maxAbsOnDiagonal) maxAbsOnDiagonal = absOnDiagonal; |
|||
} |
|||
for(Index j = 0; j < cols(); ++j) |
|||
for(Index i = 0; i < j; ++i) |
|||
{ |
|||
if(!internal::isMuchSmallerThan(coeff(i, j), maxAbsOnDiagonal, prec)) return false; |
|||
if(!internal::isMuchSmallerThan(coeff(j, i), maxAbsOnDiagonal, prec)) return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_DIAGONALMATRIX_H |
@ -0,0 +1,123 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_DIAGONALPRODUCT_H |
|||
#define EIGEN_DIAGONALPRODUCT_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
template<typename MatrixType, typename DiagonalType, int ProductOrder> |
|||
struct traits<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> > |
|||
: traits<MatrixType> |
|||
{ |
|||
typedef typename scalar_product_traits<typename MatrixType::Scalar, typename DiagonalType::Scalar>::ReturnType Scalar; |
|||
enum { |
|||
RowsAtCompileTime = MatrixType::RowsAtCompileTime, |
|||
ColsAtCompileTime = MatrixType::ColsAtCompileTime, |
|||
MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, |
|||
|
|||
_StorageOrder = MatrixType::Flags & RowMajorBit ? RowMajor : ColMajor, |
|||
_PacketOnDiag = !((int(_StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft) |
|||
||(int(_StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)), |
|||
_SameTypes = is_same<typename MatrixType::Scalar, typename DiagonalType::Scalar>::value, |
|||
// FIXME currently we need same types, but in the future the next rule should be the one |
|||
//_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && ((!_PacketOnDiag) || (_SameTypes && bool(int(DiagonalType::Flags)&PacketAccessBit))), |
|||
_Vectorizable = bool(int(MatrixType::Flags)&PacketAccessBit) && _SameTypes && ((!_PacketOnDiag) || (bool(int(DiagonalType::Flags)&PacketAccessBit))), |
|||
|
|||
Flags = (HereditaryBits & (unsigned int)(MatrixType::Flags)) | (_Vectorizable ? PacketAccessBit : 0), |
|||
CoeffReadCost = NumTraits<Scalar>::MulCost + MatrixType::CoeffReadCost + DiagonalType::DiagonalVectorType::CoeffReadCost |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename MatrixType, typename DiagonalType, int ProductOrder> |
|||
class DiagonalProduct : internal::no_assignment_operator, |
|||
public MatrixBase<DiagonalProduct<MatrixType, DiagonalType, ProductOrder> > |
|||
{ |
|||
public: |
|||
|
|||
typedef MatrixBase<DiagonalProduct> Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(DiagonalProduct) |
|||
|
|||
inline DiagonalProduct(const MatrixType& matrix, const DiagonalType& diagonal) |
|||
: m_matrix(matrix), m_diagonal(diagonal) |
|||
{ |
|||
eigen_assert(diagonal.diagonal().size() == (ProductOrder == OnTheLeft ? matrix.rows() : matrix.cols())); |
|||
} |
|||
|
|||
inline Index rows() const { return m_matrix.rows(); } |
|||
inline Index cols() const { return m_matrix.cols(); } |
|||
|
|||
const Scalar coeff(Index row, Index col) const |
|||
{ |
|||
return m_diagonal.diagonal().coeff(ProductOrder == OnTheLeft ? row : col) * m_matrix.coeff(row, col); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
enum { |
|||
StorageOrder = Flags & RowMajorBit ? RowMajor : ColMajor |
|||
}; |
|||
const Index indexInDiagonalVector = ProductOrder == OnTheLeft ? row : col; |
|||
|
|||
return packet_impl<LoadMode>(row,col,indexInDiagonalVector,typename internal::conditional< |
|||
((int(StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft) |
|||
||(int(StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)), internal::true_type, internal::false_type>::type()); |
|||
} |
|||
|
|||
protected: |
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet_impl(Index row, Index col, Index id, internal::true_type) const |
|||
{ |
|||
return internal::pmul(m_matrix.template packet<LoadMode>(row, col), |
|||
internal::pset1<PacketScalar>(m_diagonal.diagonal().coeff(id))); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet_impl(Index row, Index col, Index id, internal::false_type) const |
|||
{ |
|||
enum { |
|||
InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime, |
|||
DiagonalVectorPacketLoadMode = (LoadMode == Aligned && ((InnerSize%16) == 0)) ? Aligned : Unaligned |
|||
}; |
|||
return internal::pmul(m_matrix.template packet<LoadMode>(row, col), |
|||
m_diagonal.diagonal().template packet<DiagonalVectorPacketLoadMode>(id)); |
|||
} |
|||
|
|||
typename MatrixType::Nested m_matrix; |
|||
typename DiagonalType::Nested m_diagonal; |
|||
}; |
|||
|
|||
/** \returns the diagonal matrix product of \c *this by the diagonal matrix \a diagonal. |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename DiagonalDerived> |
|||
inline const DiagonalProduct<Derived, DiagonalDerived, OnTheRight> |
|||
MatrixBase<Derived>::operator*(const DiagonalBase<DiagonalDerived> &diagonal) const |
|||
{ |
|||
return DiagonalProduct<Derived, DiagonalDerived, OnTheRight>(derived(), diagonal.derived()); |
|||
} |
|||
|
|||
/** \returns the diagonal matrix product of \c *this by the matrix \a matrix. |
|||
*/ |
|||
template<typename DiagonalDerived> |
|||
template<typename MatrixDerived> |
|||
inline const DiagonalProduct<MatrixDerived, DiagonalDerived, OnTheLeft> |
|||
DiagonalBase<DiagonalDerived>::operator*(const MatrixBase<MatrixDerived> &matrix) const |
|||
{ |
|||
return DiagonalProduct<MatrixDerived, DiagonalDerived, OnTheLeft>(matrix.derived(), derived()); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_DIAGONALPRODUCT_H |
@ -0,0 +1,261 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2006-2008, 2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_DOT_H |
|||
#define EIGEN_DOT_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
|
|||
// helper function for dot(). The problem is that if we put that in the body of dot(), then upon calling dot |
|||
// with mismatched types, the compiler emits errors about failing to instantiate cwiseProduct BEFORE |
|||
// looking at the static assertions. Thus this is a trick to get better compile errors. |
|||
template<typename T, typename U, |
|||
// the NeedToTranspose condition here is taken straight from Assign.h |
|||
bool NeedToTranspose = T::IsVectorAtCompileTime |
|||
&& U::IsVectorAtCompileTime |
|||
&& ((int(T::RowsAtCompileTime) == 1 && int(U::ColsAtCompileTime) == 1) |
|||
| // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&". |
|||
// revert to || as soon as not needed anymore. |
|||
(int(T::ColsAtCompileTime) == 1 && int(U::RowsAtCompileTime) == 1)) |
|||
> |
|||
struct dot_nocheck |
|||
{ |
|||
typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar; |
|||
static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b) |
|||
{ |
|||
return a.template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum(); |
|||
} |
|||
}; |
|||
|
|||
template<typename T, typename U> |
|||
struct dot_nocheck<T, U, true> |
|||
{ |
|||
typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar; |
|||
static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b) |
|||
{ |
|||
return a.transpose().template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum(); |
|||
} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/** \returns the dot product of *this with other. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \note If the scalar type is complex numbers, then this function returns the hermitian |
|||
* (sesquilinear) dot product, conjugate-linear in the first variable and linear in the |
|||
* second variable. |
|||
* |
|||
* \sa squaredNorm(), norm() |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType |
|||
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) |
|||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived) |
|||
typedef internal::scalar_conj_product_op<Scalar,typename OtherDerived::Scalar> func; |
|||
EIGEN_CHECK_BINARY_COMPATIBILIY(func,Scalar,typename OtherDerived::Scalar); |
|||
|
|||
eigen_assert(size() == other.size()); |
|||
|
|||
return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other); |
|||
} |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
/** \returns the dot product of *this with other, with the Eigen2 convention that the dot product is linear in the first variable |
|||
* (conjugating the second variable). Of course this only makes a difference in the complex case. |
|||
* |
|||
* This method is only available in EIGEN2_SUPPORT mode. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa dot() |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
typename internal::traits<Derived>::Scalar |
|||
MatrixBase<Derived>::eigen2_dot(const MatrixBase<OtherDerived>& other) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) |
|||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived) |
|||
EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value), |
|||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) |
|||
|
|||
eigen_assert(size() == other.size()); |
|||
|
|||
return internal::dot_nocheck<OtherDerived,Derived>::run(other,*this); |
|||
} |
|||
#endif |
|||
|
|||
|
|||
//---------- implementation of L2 norm and related functions ---------- |
|||
|
|||
/** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the Frobenius norm. |
|||
* In both cases, it consists in the sum of the square of all the matrix entries. |
|||
* For vectors, this is also equals to the dot product of \c *this with itself. |
|||
* |
|||
* \sa dot(), norm() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const |
|||
{ |
|||
return internal::real((*this).cwiseAbs2().sum()); |
|||
} |
|||
|
|||
/** \returns, for vectors, the \em l2 norm of \c *this, and for matrices the Frobenius norm. |
|||
* In both cases, it consists in the square root of the sum of the square of all the matrix entries. |
|||
* For vectors, this is also equals to the square root of the dot product of \c *this with itself. |
|||
* |
|||
* \sa dot(), squaredNorm() |
|||
*/ |
|||
template<typename Derived> |
|||
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const |
|||
{ |
|||
return internal::sqrt(squaredNorm()); |
|||
} |
|||
|
|||
/** \returns an expression of the quotient of *this by its own norm. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa norm(), normalize() |
|||
*/ |
|||
template<typename Derived> |
|||
inline const typename MatrixBase<Derived>::PlainObject |
|||
MatrixBase<Derived>::normalized() const |
|||
{ |
|||
typedef typename internal::nested<Derived>::type Nested; |
|||
typedef typename internal::remove_reference<Nested>::type _Nested; |
|||
_Nested n(derived()); |
|||
return n / n.norm(); |
|||
} |
|||
|
|||
/** Normalizes the vector, i.e. divides it by its own norm. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* \sa norm(), normalized() |
|||
*/ |
|||
template<typename Derived> |
|||
inline void MatrixBase<Derived>::normalize() |
|||
{ |
|||
*this /= norm(); |
|||
} |
|||
|
|||
//---------- implementation of other norms ---------- |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename Derived, int p> |
|||
struct lpNorm_selector |
|||
{ |
|||
typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar; |
|||
static inline RealScalar run(const MatrixBase<Derived>& m) |
|||
{ |
|||
return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
struct lpNorm_selector<Derived, 1> |
|||
{ |
|||
static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m) |
|||
{ |
|||
return m.cwiseAbs().sum(); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
struct lpNorm_selector<Derived, 2> |
|||
{ |
|||
static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m) |
|||
{ |
|||
return m.norm(); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
struct lpNorm_selector<Derived, Infinity> |
|||
{ |
|||
static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m) |
|||
{ |
|||
return m.cwiseAbs().maxCoeff(); |
|||
} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/** \returns the \f$ \ell^p \f$ norm of *this, that is, returns the p-th root of the sum of the p-th powers of the absolute values |
|||
* of the coefficients of *this. If \a p is the special value \a Eigen::Infinity, this function returns the \f$ \ell^\infty \f$ |
|||
* norm, that is the maximum of the absolute values of the coefficients of *this. |
|||
* |
|||
* \sa norm() |
|||
*/ |
|||
template<typename Derived> |
|||
template<int p> |
|||
inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real |
|||
MatrixBase<Derived>::lpNorm() const |
|||
{ |
|||
return internal::lpNorm_selector<Derived, p>::run(*this); |
|||
} |
|||
|
|||
//---------- implementation of isOrthogonal / isUnitary ---------- |
|||
|
|||
/** \returns true if *this is approximately orthogonal to \a other, |
|||
* within the precision given by \a prec. |
|||
* |
|||
* Example: \include MatrixBase_isOrthogonal.cpp |
|||
* Output: \verbinclude MatrixBase_isOrthogonal.out |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
bool MatrixBase<Derived>::isOrthogonal |
|||
(const MatrixBase<OtherDerived>& other, RealScalar prec) const |
|||
{ |
|||
typename internal::nested<Derived,2>::type nested(derived()); |
|||
typename internal::nested<OtherDerived,2>::type otherNested(other.derived()); |
|||
return internal::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm(); |
|||
} |
|||
|
|||
/** \returns true if *this is approximately an unitary matrix, |
|||
* within the precision given by \a prec. In the case where the \a Scalar |
|||
* type is real numbers, a unitary matrix is an orthogonal matrix, whence the name. |
|||
* |
|||
* \note This can be used to check whether a family of vectors forms an orthonormal basis. |
|||
* Indeed, \c m.isUnitary() returns true if and only if the columns (equivalently, the rows) of m form an |
|||
* orthonormal basis. |
|||
* |
|||
* Example: \include MatrixBase_isUnitary.cpp |
|||
* Output: \verbinclude MatrixBase_isUnitary.out |
|||
*/ |
|||
template<typename Derived> |
|||
bool MatrixBase<Derived>::isUnitary(RealScalar prec) const |
|||
{ |
|||
typename Derived::Nested nested(derived()); |
|||
for(Index i = 0; i < cols(); ++i) |
|||
{ |
|||
if(!internal::isApprox(nested.col(i).squaredNorm(), static_cast<RealScalar>(1), prec)) |
|||
return false; |
|||
for(Index j = 0; j < i; ++j) |
|||
if(!internal::isMuchSmallerThan(nested.col(i).dot(nested.col(j)), static_cast<Scalar>(1), prec)) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_DOT_H |
@ -0,0 +1,967 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_FUNCTORS_H |
|||
#define EIGEN_FUNCTORS_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
|
|||
// associative functors: |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the sum of two scalars |
|||
* |
|||
* \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, MatrixBase::sum() |
|||
*/ |
|||
template<typename Scalar> struct scalar_sum_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op) |
|||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const |
|||
{ return internal::padd(a,b); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const |
|||
{ return internal::predux(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_sum_op<Scalar> > { |
|||
enum { |
|||
Cost = NumTraits<Scalar>::AddCost, |
|||
PacketAccess = packet_traits<Scalar>::HasAdd |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the product of two scalars |
|||
* |
|||
* \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux() |
|||
*/ |
|||
template<typename LhsScalar,typename RhsScalar> struct scalar_product_op { |
|||
enum { |
|||
// TODO vectorize mixed product |
|||
Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul |
|||
}; |
|||
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type; |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op) |
|||
EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const |
|||
{ return internal::pmul(a,b); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const |
|||
{ return internal::predux_mul(a); } |
|||
}; |
|||
template<typename LhsScalar,typename RhsScalar> |
|||
struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > { |
|||
enum { |
|||
Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate! |
|||
PacketAccess = scalar_product_op<LhsScalar,RhsScalar>::Vectorizable |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the conjugate product of two scalars |
|||
* |
|||
* This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y) |
|||
*/ |
|||
template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op { |
|||
|
|||
enum { |
|||
Conj = NumTraits<LhsScalar>::IsComplex |
|||
}; |
|||
|
|||
typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type; |
|||
|
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op) |
|||
EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const |
|||
{ return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); } |
|||
|
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const |
|||
{ return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); } |
|||
}; |
|||
template<typename LhsScalar,typename RhsScalar> |
|||
struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > { |
|||
enum { |
|||
Cost = NumTraits<LhsScalar>::MulCost, |
|||
PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the min of two scalars |
|||
* |
|||
* \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff() |
|||
*/ |
|||
template<typename Scalar> struct scalar_min_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op) |
|||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::min; return (min)(a, b); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const |
|||
{ return internal::pmin(a,b); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const |
|||
{ return internal::predux_min(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_min_op<Scalar> > { |
|||
enum { |
|||
Cost = NumTraits<Scalar>::AddCost, |
|||
PacketAccess = packet_traits<Scalar>::HasMin |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the max of two scalars |
|||
* |
|||
* \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff() |
|||
*/ |
|||
template<typename Scalar> struct scalar_max_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op) |
|||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::max; return (max)(a, b); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const |
|||
{ return internal::pmax(a,b); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const |
|||
{ return internal::predux_max(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_max_op<Scalar> > { |
|||
enum { |
|||
Cost = NumTraits<Scalar>::AddCost, |
|||
PacketAccess = packet_traits<Scalar>::HasMax |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the hypot of two scalars |
|||
* |
|||
* \sa MatrixBase::stableNorm(), class Redux |
|||
*/ |
|||
template<typename Scalar> struct scalar_hypot_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op) |
|||
// typedef typename NumTraits<Scalar>::Real result_type; |
|||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const |
|||
{ |
|||
using std::max; |
|||
using std::min; |
|||
Scalar p = (max)(_x, _y); |
|||
Scalar q = (min)(_x, _y); |
|||
Scalar qp = q/p; |
|||
return p * sqrt(Scalar(1) + qp*qp); |
|||
} |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_hypot_op<Scalar> > { |
|||
enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 }; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the pow of two scalars |
|||
*/ |
|||
template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op) |
|||
inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return internal::pow(a, b); } |
|||
}; |
|||
template<typename Scalar, typename OtherScalar> |
|||
struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > { |
|||
enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; |
|||
}; |
|||
|
|||
// other binary functors: |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the difference of two scalars |
|||
* |
|||
* \sa class CwiseBinaryOp, MatrixBase::operator- |
|||
*/ |
|||
template<typename Scalar> struct scalar_difference_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op) |
|||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const |
|||
{ return internal::psub(a,b); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_difference_op<Scalar> > { |
|||
enum { |
|||
Cost = NumTraits<Scalar>::AddCost, |
|||
PacketAccess = packet_traits<Scalar>::HasSub |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the quotient of two scalars |
|||
* |
|||
* \sa class CwiseBinaryOp, Cwise::operator/() |
|||
*/ |
|||
template<typename Scalar> struct scalar_quotient_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op) |
|||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const |
|||
{ return internal::pdiv(a,b); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_quotient_op<Scalar> > { |
|||
enum { |
|||
Cost = 2 * NumTraits<Scalar>::MulCost, |
|||
PacketAccess = packet_traits<Scalar>::HasDiv |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the and of two booleans |
|||
* |
|||
* \sa class CwiseBinaryOp, ArrayBase::operator&& |
|||
*/ |
|||
struct scalar_boolean_and_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op) |
|||
EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; } |
|||
}; |
|||
template<> struct functor_traits<scalar_boolean_and_op> { |
|||
enum { |
|||
Cost = NumTraits<bool>::AddCost, |
|||
PacketAccess = false |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the or of two booleans |
|||
* |
|||
* \sa class CwiseBinaryOp, ArrayBase::operator|| |
|||
*/ |
|||
struct scalar_boolean_or_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op) |
|||
EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; } |
|||
}; |
|||
template<> struct functor_traits<scalar_boolean_or_op> { |
|||
enum { |
|||
Cost = NumTraits<bool>::AddCost, |
|||
PacketAccess = false |
|||
}; |
|||
}; |
|||
|
|||
// unary functors: |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the opposite of a scalar |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::operator- |
|||
*/ |
|||
template<typename Scalar> struct scalar_opposite_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op) |
|||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const |
|||
{ return internal::pnegate(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_opposite_op<Scalar> > |
|||
{ enum { |
|||
Cost = NumTraits<Scalar>::AddCost, |
|||
PacketAccess = packet_traits<Scalar>::HasNegate }; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the absolute value of a scalar |
|||
* |
|||
* \sa class CwiseUnaryOp, Cwise::abs |
|||
*/ |
|||
template<typename Scalar> struct scalar_abs_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op) |
|||
typedef typename NumTraits<Scalar>::Real result_type; |
|||
EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs(a); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const |
|||
{ return internal::pabs(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_abs_op<Scalar> > |
|||
{ |
|||
enum { |
|||
Cost = NumTraits<Scalar>::AddCost, |
|||
PacketAccess = packet_traits<Scalar>::HasAbs |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the squared absolute value of a scalar |
|||
* |
|||
* \sa class CwiseUnaryOp, Cwise::abs2 |
|||
*/ |
|||
template<typename Scalar> struct scalar_abs2_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op) |
|||
typedef typename NumTraits<Scalar>::Real result_type; |
|||
EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs2(a); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const |
|||
{ return internal::pmul(a,a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_abs2_op<Scalar> > |
|||
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the conjugate of a complex value |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::conjugate() |
|||
*/ |
|||
template<typename Scalar> struct scalar_conjugate_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op) |
|||
EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return internal::conj(a); } |
|||
template<typename Packet> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_conjugate_op<Scalar> > |
|||
{ |
|||
enum { |
|||
Cost = NumTraits<Scalar>::IsComplex ? NumTraits<Scalar>::AddCost : 0, |
|||
PacketAccess = packet_traits<Scalar>::HasConj |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to cast a scalar to another type |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::cast() |
|||
*/ |
|||
template<typename Scalar, typename NewType> |
|||
struct scalar_cast_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op) |
|||
typedef NewType result_type; |
|||
EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); } |
|||
}; |
|||
template<typename Scalar, typename NewType> |
|||
struct functor_traits<scalar_cast_op<Scalar,NewType> > |
|||
{ enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to extract the real part of a complex |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::real() |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_real_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op) |
|||
typedef typename NumTraits<Scalar>::Real result_type; |
|||
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::real(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_real_op<Scalar> > |
|||
{ enum { Cost = 0, PacketAccess = false }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to extract the imaginary part of a complex |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::imag() |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_imag_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op) |
|||
typedef typename NumTraits<Scalar>::Real result_type; |
|||
EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::imag(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_imag_op<Scalar> > |
|||
{ enum { Cost = 0, PacketAccess = false }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to extract the real part of a complex as a reference |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::real() |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_real_ref_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op) |
|||
typedef typename NumTraits<Scalar>::Real result_type; |
|||
EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::real_ref(*const_cast<Scalar*>(&a)); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_real_ref_op<Scalar> > |
|||
{ enum { Cost = 0, PacketAccess = false }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to extract the imaginary part of a complex as a reference |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::imag() |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_imag_ref_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op) |
|||
typedef typename NumTraits<Scalar>::Real result_type; |
|||
EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::imag_ref(*const_cast<Scalar*>(&a)); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_imag_ref_op<Scalar> > |
|||
{ enum { Cost = 0, PacketAccess = false }; }; |
|||
|
|||
/** \internal |
|||
* |
|||
* \brief Template functor to compute the exponential of a scalar |
|||
* |
|||
* \sa class CwiseUnaryOp, Cwise::exp() |
|||
*/ |
|||
template<typename Scalar> struct scalar_exp_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op) |
|||
inline const Scalar operator() (const Scalar& a) const { return internal::exp(a); } |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
inline Packet packetOp(const Packet& a) const { return internal::pexp(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_exp_op<Scalar> > |
|||
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasExp }; }; |
|||
|
|||
/** \internal |
|||
* |
|||
* \brief Template functor to compute the logarithm of a scalar |
|||
* |
|||
* \sa class CwiseUnaryOp, Cwise::log() |
|||
*/ |
|||
template<typename Scalar> struct scalar_log_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op) |
|||
inline const Scalar operator() (const Scalar& a) const { return internal::log(a); } |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
inline Packet packetOp(const Packet& a) const { return internal::plog(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_log_op<Scalar> > |
|||
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to multiply a scalar by a fixed other one |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::operator*, MatrixBase::operator/ |
|||
*/ |
|||
/* NOTE why doing the pset1() in packetOp *is* an optimization ? |
|||
* indeed it seems better to declare m_other as a Packet and do the pset1() once |
|||
* in the constructor. However, in practice: |
|||
* - GCC does not like m_other as a Packet and generate a load every time it needs it |
|||
* - on the other hand GCC is able to moves the pset1() outside the loop :) |
|||
* - simpler code ;) |
|||
* (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y) |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_multiple_op { |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
// FIXME default copy constructors seems bugged with std::complex<> |
|||
EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { } |
|||
EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { } |
|||
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; } |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const |
|||
{ return internal::pmul(a, pset1<Packet>(m_other)); } |
|||
typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other; |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_multiple_op<Scalar> > |
|||
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; |
|||
|
|||
template<typename Scalar1, typename Scalar2> |
|||
struct scalar_multiple2_op { |
|||
typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type; |
|||
EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { } |
|||
EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { } |
|||
EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; } |
|||
typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other; |
|||
}; |
|||
template<typename Scalar1,typename Scalar2> |
|||
struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> > |
|||
{ enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to divide a scalar by a fixed other one |
|||
* |
|||
* This functor is used to implement the quotient of a matrix by |
|||
* a scalar where the scalar type is not necessarily a floating point type. |
|||
* |
|||
* \sa class CwiseUnaryOp, MatrixBase::operator/ |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_quotient1_op { |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
// FIXME default copy constructors seems bugged with std::complex<> |
|||
EIGEN_STRONG_INLINE scalar_quotient1_op(const scalar_quotient1_op& other) : m_other(other.m_other) { } |
|||
EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other) : m_other(other) {} |
|||
EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; } |
|||
EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const |
|||
{ return internal::pdiv(a, pset1<Packet>(m_other)); } |
|||
typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other; |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_quotient1_op<Scalar> > |
|||
{ enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; }; |
|||
|
|||
// nullary functors |
|||
|
|||
template<typename Scalar> |
|||
struct scalar_constant_op { |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
EIGEN_STRONG_INLINE scalar_constant_op(const scalar_constant_op& other) : m_other(other.m_other) { } |
|||
EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) { } |
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; } |
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(Index, Index = 0) const { return internal::pset1<Packet>(m_other); } |
|||
const Scalar m_other; |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_constant_op<Scalar> > |
|||
// FIXME replace this packet test by a safe one |
|||
{ enum { Cost = 1, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = true }; }; |
|||
|
|||
template<typename Scalar> struct scalar_identity_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op) |
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_identity_op<Scalar> > |
|||
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; }; |
|||
|
|||
template <typename Scalar, bool RandomAccess> struct linspaced_op_impl; |
|||
|
|||
// linear access for packet ops: |
|||
// 1) initialization |
|||
// base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0]) |
|||
// 2) each step |
|||
// base += [size*step, ..., size*step] |
|||
template <typename Scalar> |
|||
struct linspaced_op_impl<Scalar,false> |
|||
{ |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
|
|||
linspaced_op_impl(Scalar low, Scalar step) : |
|||
m_low(low), m_step(step), |
|||
m_packetStep(pset1<Packet>(packet_traits<Scalar>::size*step)), |
|||
m_base(padd(pset1<Packet>(low),pmul(pset1<Packet>(step),plset<Scalar>(-packet_traits<Scalar>::size)))) {} |
|||
|
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; } |
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); } |
|||
|
|||
const Scalar m_low; |
|||
const Scalar m_step; |
|||
const Packet m_packetStep; |
|||
mutable Packet m_base; |
|||
}; |
|||
|
|||
// random access for packet ops: |
|||
// 1) each step |
|||
// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) ) |
|||
template <typename Scalar> |
|||
struct linspaced_op_impl<Scalar,true> |
|||
{ |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
|
|||
linspaced_op_impl(Scalar low, Scalar step) : |
|||
m_low(low), m_step(step), |
|||
m_lowPacket(pset1<Packet>(m_low)), m_stepPacket(pset1<Packet>(m_step)), m_interPacket(plset<Scalar>(0)) {} |
|||
|
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; } |
|||
|
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const |
|||
{ return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(i),m_interPacket))); } |
|||
|
|||
const Scalar m_low; |
|||
const Scalar m_step; |
|||
const Packet m_lowPacket; |
|||
const Packet m_stepPacket; |
|||
const Packet m_interPacket; |
|||
}; |
|||
|
|||
// ----- Linspace functor ---------------------------------------------------------------- |
|||
|
|||
// Forward declaration (we default to random access which does not really give |
|||
// us a speed gain when using packet access but it allows to use the functor in |
|||
// nested expressions). |
|||
template <typename Scalar, bool RandomAccess = true> struct linspaced_op; |
|||
template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_op<Scalar,RandomAccess> > |
|||
{ enum { Cost = 1, PacketAccess = packet_traits<Scalar>::HasSetLinear, IsRepeatable = true }; }; |
|||
template <typename Scalar, bool RandomAccess> struct linspaced_op |
|||
{ |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
linspaced_op(Scalar low, Scalar high, int num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/(num_steps-1))) {} |
|||
|
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); } |
|||
|
|||
// We need this function when assigning e.g. a RowVectorXd to a MatrixXd since |
|||
// there row==0 and col is used for the actual iteration. |
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const |
|||
{ |
|||
eigen_assert(col==0 || row==0); |
|||
return impl(col + row); |
|||
} |
|||
|
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); } |
|||
|
|||
// We need this function when assigning e.g. a RowVectorXd to a MatrixXd since |
|||
// there row==0 and col is used for the actual iteration. |
|||
template<typename Index> |
|||
EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const |
|||
{ |
|||
eigen_assert(col==0 || row==0); |
|||
return impl.packetOp(col + row); |
|||
} |
|||
|
|||
// This proxy object handles the actual required temporaries, the different |
|||
// implementations (random vs. sequential access) as well as the |
|||
// correct piping to size 2/4 packet operations. |
|||
const linspaced_op_impl<Scalar,RandomAccess> impl; |
|||
}; |
|||
|
|||
// all functors allow linear access, except scalar_identity_op. So we fix here a quick meta |
|||
// to indicate whether a functor allows linear access, just always answering 'yes' except for |
|||
// scalar_identity_op. |
|||
// FIXME move this to functor_traits adding a functor_default |
|||
template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; }; |
|||
template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; }; |
|||
|
|||
// in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication |
|||
// where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>. |
|||
// FIXME move this to functor_traits adding a functor_default |
|||
template<typename Functor> struct functor_allows_mixing_real_and_complex { enum { ret = 0 }; }; |
|||
template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; }; |
|||
template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; }; |
|||
|
|||
|
|||
/** \internal |
|||
* \brief Template functor to add a scalar to a fixed other one |
|||
* \sa class CwiseUnaryOp, Array::operator+ |
|||
*/ |
|||
/* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */ |
|||
template<typename Scalar> |
|||
struct scalar_add_op { |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
// FIXME default copy constructors seems bugged with std::complex<> |
|||
inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { } |
|||
inline scalar_add_op(const Scalar& other) : m_other(other) { } |
|||
inline Scalar operator() (const Scalar& a) const { return a + m_other; } |
|||
inline const Packet packetOp(const Packet& a) const |
|||
{ return internal::padd(a, pset1<Packet>(m_other)); } |
|||
const Scalar m_other; |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_add_op<Scalar> > |
|||
{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the square root of a scalar |
|||
* \sa class CwiseUnaryOp, Cwise::sqrt() |
|||
*/ |
|||
template<typename Scalar> struct scalar_sqrt_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op) |
|||
inline const Scalar operator() (const Scalar& a) const { return internal::sqrt(a); } |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_sqrt_op<Scalar> > |
|||
{ enum { |
|||
Cost = 5 * NumTraits<Scalar>::MulCost, |
|||
PacketAccess = packet_traits<Scalar>::HasSqrt |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the cosine of a scalar |
|||
* \sa class CwiseUnaryOp, ArrayBase::cos() |
|||
*/ |
|||
template<typename Scalar> struct scalar_cos_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op) |
|||
inline Scalar operator() (const Scalar& a) const { return internal::cos(a); } |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
inline Packet packetOp(const Packet& a) const { return internal::pcos(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_cos_op<Scalar> > |
|||
{ |
|||
enum { |
|||
Cost = 5 * NumTraits<Scalar>::MulCost, |
|||
PacketAccess = packet_traits<Scalar>::HasCos |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the sine of a scalar |
|||
* \sa class CwiseUnaryOp, ArrayBase::sin() |
|||
*/ |
|||
template<typename Scalar> struct scalar_sin_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op) |
|||
inline const Scalar operator() (const Scalar& a) const { return internal::sin(a); } |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
inline Packet packetOp(const Packet& a) const { return internal::psin(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_sin_op<Scalar> > |
|||
{ |
|||
enum { |
|||
Cost = 5 * NumTraits<Scalar>::MulCost, |
|||
PacketAccess = packet_traits<Scalar>::HasSin |
|||
}; |
|||
}; |
|||
|
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the tan of a scalar |
|||
* \sa class CwiseUnaryOp, ArrayBase::tan() |
|||
*/ |
|||
template<typename Scalar> struct scalar_tan_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op) |
|||
inline const Scalar operator() (const Scalar& a) const { return internal::tan(a); } |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
inline Packet packetOp(const Packet& a) const { return internal::ptan(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_tan_op<Scalar> > |
|||
{ |
|||
enum { |
|||
Cost = 5 * NumTraits<Scalar>::MulCost, |
|||
PacketAccess = packet_traits<Scalar>::HasTan |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the arc cosine of a scalar |
|||
* \sa class CwiseUnaryOp, ArrayBase::acos() |
|||
*/ |
|||
template<typename Scalar> struct scalar_acos_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op) |
|||
inline const Scalar operator() (const Scalar& a) const { return internal::acos(a); } |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
inline Packet packetOp(const Packet& a) const { return internal::pacos(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_acos_op<Scalar> > |
|||
{ |
|||
enum { |
|||
Cost = 5 * NumTraits<Scalar>::MulCost, |
|||
PacketAccess = packet_traits<Scalar>::HasACos |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the arc sine of a scalar |
|||
* \sa class CwiseUnaryOp, ArrayBase::asin() |
|||
*/ |
|||
template<typename Scalar> struct scalar_asin_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op) |
|||
inline const Scalar operator() (const Scalar& a) const { return internal::asin(a); } |
|||
typedef typename packet_traits<Scalar>::type Packet; |
|||
inline Packet packetOp(const Packet& a) const { return internal::pasin(a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_asin_op<Scalar> > |
|||
{ |
|||
enum { |
|||
Cost = 5 * NumTraits<Scalar>::MulCost, |
|||
PacketAccess = packet_traits<Scalar>::HasASin |
|||
}; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to raise a scalar to a power |
|||
* \sa class CwiseUnaryOp, Cwise::pow |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_pow_op { |
|||
// FIXME default copy constructors seems bugged with std::complex<> |
|||
inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { } |
|||
inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {} |
|||
inline Scalar operator() (const Scalar& a) const { return internal::pow(a, m_exponent); } |
|||
const Scalar m_exponent; |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_pow_op<Scalar> > |
|||
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the quotient between a scalar and array entries. |
|||
* \sa class CwiseUnaryOp, Cwise::inverse() |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_inverse_mult_op { |
|||
scalar_inverse_mult_op(const Scalar& other) : m_other(other) {} |
|||
inline Scalar operator() (const Scalar& a) const { return m_other / a; } |
|||
template<typename Packet> |
|||
inline const Packet packetOp(const Packet& a) const |
|||
{ return internal::pdiv(pset1<Packet>(m_other),a); } |
|||
Scalar m_other; |
|||
}; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the inverse of a scalar |
|||
* \sa class CwiseUnaryOp, Cwise::inverse() |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_inverse_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op) |
|||
inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; } |
|||
template<typename Packet> |
|||
inline const Packet packetOp(const Packet& a) const |
|||
{ return internal::pdiv(pset1<Packet>(Scalar(1)),a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_inverse_op<Scalar> > |
|||
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the square of a scalar |
|||
* \sa class CwiseUnaryOp, Cwise::square() |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_square_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op) |
|||
inline Scalar operator() (const Scalar& a) const { return a*a; } |
|||
template<typename Packet> |
|||
inline const Packet packetOp(const Packet& a) const |
|||
{ return internal::pmul(a,a); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_square_op<Scalar> > |
|||
{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; |
|||
|
|||
/** \internal |
|||
* \brief Template functor to compute the cube of a scalar |
|||
* \sa class CwiseUnaryOp, Cwise::cube() |
|||
*/ |
|||
template<typename Scalar> |
|||
struct scalar_cube_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op) |
|||
inline Scalar operator() (const Scalar& a) const { return a*a*a; } |
|||
template<typename Packet> |
|||
inline const Packet packetOp(const Packet& a) const |
|||
{ return internal::pmul(a,pmul(a,a)); } |
|||
}; |
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_cube_op<Scalar> > |
|||
{ enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; |
|||
|
|||
// default functor traits for STL functors: |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::multiplies<T> > |
|||
{ enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::divides<T> > |
|||
{ enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::plus<T> > |
|||
{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::minus<T> > |
|||
{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::negate<T> > |
|||
{ enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::logical_or<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::logical_and<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::logical_not<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::greater<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::less<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::greater_equal<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::less_equal<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::equal_to<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::not_equal_to<T> > |
|||
{ enum { Cost = 1, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::binder2nd<T> > |
|||
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::binder1st<T> > |
|||
{ enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::unary_negate<T> > |
|||
{ enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; }; |
|||
|
|||
template<typename T> |
|||
struct functor_traits<std::binary_negate<T> > |
|||
{ enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; }; |
|||
|
|||
#ifdef EIGEN_STDEXT_SUPPORT |
|||
|
|||
template<typename T0,typename T1> |
|||
struct functor_traits<std::project1st<T0,T1> > |
|||
{ enum { Cost = 0, PacketAccess = false }; }; |
|||
|
|||
template<typename T0,typename T1> |
|||
struct functor_traits<std::project2nd<T0,T1> > |
|||
{ enum { Cost = 0, PacketAccess = false }; }; |
|||
|
|||
template<typename T0,typename T1> |
|||
struct functor_traits<std::select2nd<std::pair<T0,T1> > > |
|||
{ enum { Cost = 0, PacketAccess = false }; }; |
|||
|
|||
template<typename T0,typename T1> |
|||
struct functor_traits<std::select1st<std::pair<T0,T1> > > |
|||
{ enum { Cost = 0, PacketAccess = false }; }; |
|||
|
|||
template<typename T0,typename T1> |
|||
struct functor_traits<std::unary_compose<T0,T1> > |
|||
{ enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost, PacketAccess = false }; }; |
|||
|
|||
template<typename T0,typename T1,typename T2> |
|||
struct functor_traits<std::binary_compose<T0,T1,T2> > |
|||
{ enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost + functor_traits<T2>::Cost, PacketAccess = false }; }; |
|||
|
|||
#endif // EIGEN_STDEXT_SUPPORT |
|||
|
|||
// allow to add new functors and specializations of functor_traits from outside Eigen. |
|||
// this macro is really needed because functor_traits must be specialized after it is declared but before it is used... |
|||
#ifdef EIGEN_FUNCTORS_PLUGIN |
|||
#include EIGEN_FUNCTORS_PLUGIN |
|||
#endif |
|||
|
|||
} // end namespace internal |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_FUNCTORS_H |
@ -0,0 +1,150 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_FUZZY_H |
|||
#define EIGEN_FUZZY_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal |
|||
{ |
|||
|
|||
template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> |
|||
struct isApprox_selector |
|||
{ |
|||
static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec) |
|||
{ |
|||
using std::min; |
|||
typename internal::nested<Derived,2>::type nested(x); |
|||
typename internal::nested<OtherDerived,2>::type otherNested(y); |
|||
return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * (min)(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived, typename OtherDerived> |
|||
struct isApprox_selector<Derived, OtherDerived, true> |
|||
{ |
|||
static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar) |
|||
{ |
|||
return x.matrix() == y.matrix(); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived, typename OtherDerived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> |
|||
struct isMuchSmallerThan_object_selector |
|||
{ |
|||
static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec) |
|||
{ |
|||
return x.cwiseAbs2().sum() <= abs2(prec) * y.cwiseAbs2().sum(); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived, typename OtherDerived> |
|||
struct isMuchSmallerThan_object_selector<Derived, OtherDerived, true> |
|||
{ |
|||
static bool run(const Derived& x, const OtherDerived&, typename Derived::RealScalar) |
|||
{ |
|||
return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived, bool is_integer = NumTraits<typename Derived::Scalar>::IsInteger> |
|||
struct isMuchSmallerThan_scalar_selector |
|||
{ |
|||
static bool run(const Derived& x, const typename Derived::RealScalar& y, typename Derived::RealScalar prec) |
|||
{ |
|||
return x.cwiseAbs2().sum() <= abs2(prec * y); |
|||
} |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
struct isMuchSmallerThan_scalar_selector<Derived, true> |
|||
{ |
|||
static bool run(const Derived& x, const typename Derived::RealScalar&, typename Derived::RealScalar) |
|||
{ |
|||
return x.matrix() == Derived::Zero(x.rows(), x.cols()).matrix(); |
|||
} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
|
|||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision |
|||
* determined by \a prec. |
|||
* |
|||
* \note The fuzzy compares are done multiplicatively. Two vectors \f$ v \f$ and \f$ w \f$ |
|||
* are considered to be approximately equal within precision \f$ p \f$ if |
|||
* \f[ \Vert v - w \Vert \leqslant p\,\min(\Vert v\Vert, \Vert w\Vert). \f] |
|||
* For matrices, the comparison is done using the Hilbert-Schmidt norm (aka Frobenius norm |
|||
* L2 norm). |
|||
* |
|||
* \note Because of the multiplicativeness of this comparison, one can't use this function |
|||
* to check whether \c *this is approximately equal to the zero matrix or vector. |
|||
* Indeed, \c isApprox(zero) returns false unless \c *this itself is exactly the zero matrix |
|||
* or vector. If you want to test whether \c *this is zero, use internal::isMuchSmallerThan(const |
|||
* RealScalar&, RealScalar) instead. |
|||
* |
|||
* \sa internal::isMuchSmallerThan(const RealScalar&, RealScalar) const |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
bool DenseBase<Derived>::isApprox( |
|||
const DenseBase<OtherDerived>& other, |
|||
RealScalar prec |
|||
) const |
|||
{ |
|||
return internal::isApprox_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec); |
|||
} |
|||
|
|||
/** \returns \c true if the norm of \c *this is much smaller than \a other, |
|||
* within the precision determined by \a prec. |
|||
* |
|||
* \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is |
|||
* considered to be much smaller than \f$ x \f$ within precision \f$ p \f$ if |
|||
* \f[ \Vert v \Vert \leqslant p\,\vert x\vert. \f] |
|||
* |
|||
* For matrices, the comparison is done using the Hilbert-Schmidt norm. For this reason, |
|||
* the value of the reference scalar \a other should come from the Hilbert-Schmidt norm |
|||
* of a reference matrix of same dimensions. |
|||
* |
|||
* \sa isApprox(), isMuchSmallerThan(const DenseBase<OtherDerived>&, RealScalar) const |
|||
*/ |
|||
template<typename Derived> |
|||
bool DenseBase<Derived>::isMuchSmallerThan( |
|||
const typename NumTraits<Scalar>::Real& other, |
|||
RealScalar prec |
|||
) const |
|||
{ |
|||
return internal::isMuchSmallerThan_scalar_selector<Derived>::run(derived(), other, prec); |
|||
} |
|||
|
|||
/** \returns \c true if the norm of \c *this is much smaller than the norm of \a other, |
|||
* within the precision determined by \a prec. |
|||
* |
|||
* \note The fuzzy compares are done multiplicatively. A vector \f$ v \f$ is |
|||
* considered to be much smaller than a vector \f$ w \f$ within precision \f$ p \f$ if |
|||
* \f[ \Vert v \Vert \leqslant p\,\Vert w\Vert. \f] |
|||
* For matrices, the comparison is done using the Hilbert-Schmidt norm. |
|||
* |
|||
* \sa isApprox(), isMuchSmallerThan(const RealScalar&, RealScalar) const |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
bool DenseBase<Derived>::isMuchSmallerThan( |
|||
const DenseBase<OtherDerived>& other, |
|||
RealScalar prec |
|||
) const |
|||
{ |
|||
return internal::isMuchSmallerThan_object_selector<Derived, OtherDerived>::run(derived(), other.derived(), prec); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_FUZZY_H |
@ -0,0 +1,613 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_GENERAL_PRODUCT_H |
|||
#define EIGEN_GENERAL_PRODUCT_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class GeneralProduct |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of the product of two general matrices or vectors |
|||
* |
|||
* \param LhsNested the type used to store the left-hand side |
|||
* \param RhsNested the type used to store the right-hand side |
|||
* \param ProductMode the type of the product |
|||
* |
|||
* This class represents an expression of the product of two general matrices. |
|||
* We call a general matrix, a dense matrix with full storage. For instance, |
|||
* This excludes triangular, selfadjoint, and sparse matrices. |
|||
* It is the return type of the operator* between general matrices. Its template |
|||
* arguments are determined automatically by ProductReturnType. Therefore, |
|||
* GeneralProduct should never be used direclty. To determine the result type of a |
|||
* function which involves a matrix product, use ProductReturnType::Type. |
|||
* |
|||
* \sa ProductReturnType, MatrixBase::operator*(const MatrixBase<OtherDerived>&) |
|||
*/ |
|||
template<typename Lhs, typename Rhs, int ProductType = internal::product_type<Lhs,Rhs>::value> |
|||
class GeneralProduct; |
|||
|
|||
enum { |
|||
Large = 2, |
|||
Small = 3 |
|||
}; |
|||
|
|||
namespace internal { |
|||
|
|||
template<int Rows, int Cols, int Depth> struct product_type_selector; |
|||
|
|||
template<int Size, int MaxSize> struct product_size_category |
|||
{ |
|||
enum { is_large = MaxSize == Dynamic || |
|||
Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD, |
|||
value = is_large ? Large |
|||
: Size == 1 ? 1 |
|||
: Small |
|||
}; |
|||
}; |
|||
|
|||
template<typename Lhs, typename Rhs> struct product_type |
|||
{ |
|||
typedef typename remove_all<Lhs>::type _Lhs; |
|||
typedef typename remove_all<Rhs>::type _Rhs; |
|||
enum { |
|||
MaxRows = _Lhs::MaxRowsAtCompileTime, |
|||
Rows = _Lhs::RowsAtCompileTime, |
|||
MaxCols = _Rhs::MaxColsAtCompileTime, |
|||
Cols = _Rhs::ColsAtCompileTime, |
|||
MaxDepth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::MaxColsAtCompileTime, |
|||
_Rhs::MaxRowsAtCompileTime), |
|||
Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime, |
|||
_Rhs::RowsAtCompileTime), |
|||
LargeThreshold = EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD |
|||
}; |
|||
|
|||
// the splitting into different lines of code here, introducing the _select enums and the typedef below, |
|||
// is to work around an internal compiler error with gcc 4.1 and 4.2. |
|||
private: |
|||
enum { |
|||
rows_select = product_size_category<Rows,MaxRows>::value, |
|||
cols_select = product_size_category<Cols,MaxCols>::value, |
|||
depth_select = product_size_category<Depth,MaxDepth>::value |
|||
}; |
|||
typedef product_type_selector<rows_select, cols_select, depth_select> selector; |
|||
|
|||
public: |
|||
enum { |
|||
value = selector::ret |
|||
}; |
|||
#ifdef EIGEN_DEBUG_PRODUCT |
|||
static void debug() |
|||
{ |
|||
EIGEN_DEBUG_VAR(Rows); |
|||
EIGEN_DEBUG_VAR(Cols); |
|||
EIGEN_DEBUG_VAR(Depth); |
|||
EIGEN_DEBUG_VAR(rows_select); |
|||
EIGEN_DEBUG_VAR(cols_select); |
|||
EIGEN_DEBUG_VAR(depth_select); |
|||
EIGEN_DEBUG_VAR(value); |
|||
} |
|||
#endif |
|||
}; |
|||
|
|||
|
|||
/* The following allows to select the kind of product at compile time |
|||
* based on the three dimensions of the product. |
|||
* This is a compile time mapping from {1,Small,Large}^3 -> {product types} */ |
|||
// FIXME I'm not sure the current mapping is the ideal one. |
|||
template<int M, int N> struct product_type_selector<M,N,1> { enum { ret = OuterProduct }; }; |
|||
template<int Depth> struct product_type_selector<1, 1, Depth> { enum { ret = InnerProduct }; }; |
|||
template<> struct product_type_selector<1, 1, 1> { enum { ret = InnerProduct }; }; |
|||
template<> struct product_type_selector<Small,1, Small> { enum { ret = CoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<1, Small,Small> { enum { ret = CoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<Small,Small,Small> { enum { ret = CoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<Small, Small, 1> { enum { ret = LazyCoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<Small, Large, 1> { enum { ret = LazyCoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<Large, Small, 1> { enum { ret = LazyCoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<1, Large,Small> { enum { ret = CoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<1, Large,Large> { enum { ret = GemvProduct }; }; |
|||
template<> struct product_type_selector<1, Small,Large> { enum { ret = CoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<Large,1, Small> { enum { ret = CoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<Large,1, Large> { enum { ret = GemvProduct }; }; |
|||
template<> struct product_type_selector<Small,1, Large> { enum { ret = CoeffBasedProductMode }; }; |
|||
template<> struct product_type_selector<Small,Small,Large> { enum { ret = GemmProduct }; }; |
|||
template<> struct product_type_selector<Large,Small,Large> { enum { ret = GemmProduct }; }; |
|||
template<> struct product_type_selector<Small,Large,Large> { enum { ret = GemmProduct }; }; |
|||
template<> struct product_type_selector<Large,Large,Large> { enum { ret = GemmProduct }; }; |
|||
template<> struct product_type_selector<Large,Small,Small> { enum { ret = GemmProduct }; }; |
|||
template<> struct product_type_selector<Small,Large,Small> { enum { ret = GemmProduct }; }; |
|||
template<> struct product_type_selector<Large,Large,Small> { enum { ret = GemmProduct }; }; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/** \class ProductReturnType |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Helper class to get the correct and optimized returned type of operator* |
|||
* |
|||
* \param Lhs the type of the left-hand side |
|||
* \param Rhs the type of the right-hand side |
|||
* \param ProductMode the type of the product (determined automatically by internal::product_mode) |
|||
* |
|||
* This class defines the typename Type representing the optimized product expression |
|||
* between two matrix expressions. In practice, using ProductReturnType<Lhs,Rhs>::Type |
|||
* is the recommended way to define the result type of a function returning an expression |
|||
* which involve a matrix product. The class Product should never be |
|||
* used directly. |
|||
* |
|||
* \sa class Product, MatrixBase::operator*(const MatrixBase<OtherDerived>&) |
|||
*/ |
|||
template<typename Lhs, typename Rhs, int ProductType> |
|||
struct ProductReturnType |
|||
{ |
|||
// TODO use the nested type to reduce instanciations ???? |
|||
// typedef typename internal::nested<Lhs,Rhs::ColsAtCompileTime>::type LhsNested; |
|||
// typedef typename internal::nested<Rhs,Lhs::RowsAtCompileTime>::type RhsNested; |
|||
|
|||
typedef GeneralProduct<Lhs/*Nested*/, Rhs/*Nested*/, ProductType> Type; |
|||
}; |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
struct ProductReturnType<Lhs,Rhs,CoeffBasedProductMode> |
|||
{ |
|||
typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested; |
|||
typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested; |
|||
typedef CoeffBasedProduct<LhsNested, RhsNested, EvalBeforeAssigningBit | EvalBeforeNestingBit> Type; |
|||
}; |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
struct ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode> |
|||
{ |
|||
typedef typename internal::nested<Lhs, Rhs::ColsAtCompileTime, typename internal::plain_matrix_type<Lhs>::type >::type LhsNested; |
|||
typedef typename internal::nested<Rhs, Lhs::RowsAtCompileTime, typename internal::plain_matrix_type<Rhs>::type >::type RhsNested; |
|||
typedef CoeffBasedProduct<LhsNested, RhsNested, NestByRefBit> Type; |
|||
}; |
|||
|
|||
// this is a workaround for sun CC |
|||
template<typename Lhs, typename Rhs> |
|||
struct LazyProductReturnType : public ProductReturnType<Lhs,Rhs,LazyCoeffBasedProductMode> |
|||
{}; |
|||
|
|||
/*********************************************************************** |
|||
* Implementation of Inner Vector Vector Product |
|||
***********************************************************************/ |
|||
|
|||
// FIXME : maybe the "inner product" could return a Scalar |
|||
// instead of a 1x1 matrix ?? |
|||
// Pro: more natural for the user |
|||
// Cons: this could be a problem if in a meta unrolled algorithm a matrix-matrix |
|||
// product ends up to a row-vector times col-vector product... To tackle this use |
|||
// case, we could have a specialization for Block<MatrixType,1,1> with: operator=(Scalar x); |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
struct traits<GeneralProduct<Lhs,Rhs,InnerProduct> > |
|||
: traits<Matrix<typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> > |
|||
{}; |
|||
|
|||
} |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
class GeneralProduct<Lhs, Rhs, InnerProduct> |
|||
: internal::no_assignment_operator, |
|||
public Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> |
|||
{ |
|||
typedef Matrix<typename internal::scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType,1,1> Base; |
|||
public: |
|||
GeneralProduct(const Lhs& lhs, const Rhs& rhs) |
|||
{ |
|||
EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value), |
|||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) |
|||
|
|||
Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum(); |
|||
} |
|||
|
|||
/** Convertion to scalar */ |
|||
operator const typename Base::Scalar() const { |
|||
return Base::coeff(0,0); |
|||
} |
|||
}; |
|||
|
|||
/*********************************************************************** |
|||
* Implementation of Outer Vector Vector Product |
|||
***********************************************************************/ |
|||
|
|||
namespace internal { |
|||
template<int StorageOrder> struct outer_product_selector; |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
struct traits<GeneralProduct<Lhs,Rhs,OuterProduct> > |
|||
: traits<ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> > |
|||
{}; |
|||
|
|||
} |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
class GeneralProduct<Lhs, Rhs, OuterProduct> |
|||
: public ProductBase<GeneralProduct<Lhs,Rhs,OuterProduct>, Lhs, Rhs> |
|||
{ |
|||
public: |
|||
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct) |
|||
|
|||
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) |
|||
{ |
|||
EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::RealScalar, typename Rhs::RealScalar>::value), |
|||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) |
|||
} |
|||
|
|||
template<typename Dest> void scaleAndAddTo(Dest& dest, Scalar alpha) const |
|||
{ |
|||
internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dest, alpha); |
|||
} |
|||
}; |
|||
|
|||
namespace internal { |
|||
|
|||
template<> struct outer_product_selector<ColMajor> { |
|||
template<typename ProductType, typename Dest> |
|||
static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) { |
|||
typedef typename Dest::Index Index; |
|||
// FIXME make sure lhs is sequentially stored |
|||
// FIXME not very good if rhs is real and lhs complex while alpha is real too |
|||
const Index cols = dest.cols(); |
|||
for (Index j=0; j<cols; ++j) |
|||
dest.col(j) += (alpha * prod.rhs().coeff(j)) * prod.lhs(); |
|||
} |
|||
}; |
|||
|
|||
template<> struct outer_product_selector<RowMajor> { |
|||
template<typename ProductType, typename Dest> |
|||
static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) { |
|||
typedef typename Dest::Index Index; |
|||
// FIXME make sure rhs is sequentially stored |
|||
// FIXME not very good if lhs is real and rhs complex while alpha is real too |
|||
const Index rows = dest.rows(); |
|||
for (Index i=0; i<rows; ++i) |
|||
dest.row(i) += (alpha * prod.lhs().coeff(i)) * prod.rhs(); |
|||
} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/*********************************************************************** |
|||
* Implementation of General Matrix Vector Product |
|||
***********************************************************************/ |
|||
|
|||
/* According to the shape/flags of the matrix we have to distinghish 3 different cases: |
|||
* 1 - the matrix is col-major, BLAS compatible and M is large => call fast BLAS-like colmajor routine |
|||
* 2 - the matrix is row-major, BLAS compatible and N is large => call fast BLAS-like rowmajor routine |
|||
* 3 - all other cases are handled using a simple loop along the outer-storage direction. |
|||
* Therefore we need a lower level meta selector. |
|||
* Furthermore, if the matrix is the rhs, then the product has to be transposed. |
|||
*/ |
|||
namespace internal { |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
struct traits<GeneralProduct<Lhs,Rhs,GemvProduct> > |
|||
: traits<ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs> > |
|||
{}; |
|||
|
|||
template<int Side, int StorageOrder, bool BlasCompatible> |
|||
struct gemv_selector; |
|||
|
|||
} // end namespace internal |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
class GeneralProduct<Lhs, Rhs, GemvProduct> |
|||
: public ProductBase<GeneralProduct<Lhs,Rhs,GemvProduct>, Lhs, Rhs> |
|||
{ |
|||
public: |
|||
EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct) |
|||
|
|||
typedef typename Lhs::Scalar LhsScalar; |
|||
typedef typename Rhs::Scalar RhsScalar; |
|||
|
|||
GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) |
|||
{ |
|||
// EIGEN_STATIC_ASSERT((internal::is_same<typename Lhs::Scalar, typename Rhs::Scalar>::value), |
|||
// YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) |
|||
} |
|||
|
|||
enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight }; |
|||
typedef typename internal::conditional<int(Side)==OnTheRight,_LhsNested,_RhsNested>::type MatrixType; |
|||
|
|||
template<typename Dest> void scaleAndAddTo(Dest& dst, Scalar alpha) const |
|||
{ |
|||
eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols()); |
|||
internal::gemv_selector<Side,(int(MatrixType::Flags)&RowMajorBit) ? RowMajor : ColMajor, |
|||
bool(internal::blas_traits<MatrixType>::HasUsableDirectAccess)>::run(*this, dst, alpha); |
|||
} |
|||
}; |
|||
|
|||
namespace internal { |
|||
|
|||
// The vector is on the left => transposition |
|||
template<int StorageOrder, bool BlasCompatible> |
|||
struct gemv_selector<OnTheLeft,StorageOrder,BlasCompatible> |
|||
{ |
|||
template<typename ProductType, typename Dest> |
|||
static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) |
|||
{ |
|||
Transpose<Dest> destT(dest); |
|||
enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor }; |
|||
gemv_selector<OnTheRight,OtherStorageOrder,BlasCompatible> |
|||
::run(GeneralProduct<Transpose<const typename ProductType::_RhsNested>,Transpose<const typename ProductType::_LhsNested>, GemvProduct> |
|||
(prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar,int Size,int MaxSize,bool Cond> struct gemv_static_vector_if; |
|||
|
|||
template<typename Scalar,int Size,int MaxSize> |
|||
struct gemv_static_vector_if<Scalar,Size,MaxSize,false> |
|||
{ |
|||
EIGEN_STRONG_INLINE Scalar* data() { eigen_internal_assert(false && "should never be called"); return 0; } |
|||
}; |
|||
|
|||
template<typename Scalar,int Size> |
|||
struct gemv_static_vector_if<Scalar,Size,Dynamic,true> |
|||
{ |
|||
EIGEN_STRONG_INLINE Scalar* data() { return 0; } |
|||
}; |
|||
|
|||
template<typename Scalar,int Size,int MaxSize> |
|||
struct gemv_static_vector_if<Scalar,Size,MaxSize,true> |
|||
{ |
|||
#if EIGEN_ALIGN_STATICALLY |
|||
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize),0> m_data; |
|||
EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; } |
|||
#else |
|||
// Some architectures cannot align on the stack, |
|||
// => let's manually enforce alignment by allocating more data and return the address of the first aligned element. |
|||
enum { |
|||
ForceAlignment = internal::packet_traits<Scalar>::Vectorizable, |
|||
PacketSize = internal::packet_traits<Scalar>::size |
|||
}; |
|||
internal::plain_array<Scalar,EIGEN_SIZE_MIN_PREFER_FIXED(Size,MaxSize)+(ForceAlignment?PacketSize:0),0> m_data; |
|||
EIGEN_STRONG_INLINE Scalar* data() { |
|||
return ForceAlignment |
|||
? reinterpret_cast<Scalar*>((reinterpret_cast<size_t>(m_data.array) & ~(size_t(15))) + 16) |
|||
: m_data.array; |
|||
} |
|||
#endif |
|||
}; |
|||
|
|||
template<> struct gemv_selector<OnTheRight,ColMajor,true> |
|||
{ |
|||
template<typename ProductType, typename Dest> |
|||
static inline void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) |
|||
{ |
|||
typedef typename ProductType::Index Index; |
|||
typedef typename ProductType::LhsScalar LhsScalar; |
|||
typedef typename ProductType::RhsScalar RhsScalar; |
|||
typedef typename ProductType::Scalar ResScalar; |
|||
typedef typename ProductType::RealScalar RealScalar; |
|||
typedef typename ProductType::ActualLhsType ActualLhsType; |
|||
typedef typename ProductType::ActualRhsType ActualRhsType; |
|||
typedef typename ProductType::LhsBlasTraits LhsBlasTraits; |
|||
typedef typename ProductType::RhsBlasTraits RhsBlasTraits; |
|||
typedef Map<Matrix<ResScalar,Dynamic,1>, Aligned> MappedDest; |
|||
|
|||
ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs()); |
|||
ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs()); |
|||
|
|||
ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs()) |
|||
* RhsBlasTraits::extractScalarFactor(prod.rhs()); |
|||
|
|||
enum { |
|||
// FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1 |
|||
// on, the other hand it is good for the cache to pack the vector anyways... |
|||
EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1, |
|||
ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex), |
|||
MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal |
|||
}; |
|||
|
|||
gemv_static_vector_if<ResScalar,Dest::SizeAtCompileTime,Dest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest; |
|||
|
|||
bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0)); |
|||
bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible; |
|||
|
|||
RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::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 |
|||
int 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 |
|||
<Index,LhsScalar,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run( |
|||
actualLhs.rows(), actualLhs.cols(), |
|||
actualLhs.data(), actualLhs.outerStride(), |
|||
actualRhs.data(), actualRhs.innerStride(), |
|||
actualDestPtr, 1, |
|||
compatibleAlpha); |
|||
|
|||
if (!evalToDest) |
|||
{ |
|||
if(!alphaIsCompatible) |
|||
dest += actualAlpha * MappedDest(actualDestPtr, dest.size()); |
|||
else |
|||
dest = MappedDest(actualDestPtr, dest.size()); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
template<> struct gemv_selector<OnTheRight,RowMajor,true> |
|||
{ |
|||
template<typename ProductType, typename Dest> |
|||
static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) |
|||
{ |
|||
typedef typename ProductType::LhsScalar LhsScalar; |
|||
typedef typename ProductType::RhsScalar RhsScalar; |
|||
typedef typename ProductType::Scalar ResScalar; |
|||
typedef typename ProductType::Index Index; |
|||
typedef typename ProductType::ActualLhsType ActualLhsType; |
|||
typedef typename ProductType::ActualRhsType ActualRhsType; |
|||
typedef typename ProductType::_ActualRhsType _ActualRhsType; |
|||
typedef typename ProductType::LhsBlasTraits LhsBlasTraits; |
|||
typedef typename ProductType::RhsBlasTraits RhsBlasTraits; |
|||
|
|||
typename add_const<ActualLhsType>::type actualLhs = LhsBlasTraits::extract(prod.lhs()); |
|||
typename add_const<ActualRhsType>::type actualRhs = RhsBlasTraits::extract(prod.rhs()); |
|||
|
|||
ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs()) |
|||
* RhsBlasTraits::extractScalarFactor(prod.rhs()); |
|||
|
|||
enum { |
|||
// FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1 |
|||
// on, the other hand it is good for the cache to pack the vector anyways... |
|||
DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1 |
|||
}; |
|||
|
|||
gemv_static_vector_if<RhsScalar,_ActualRhsType::SizeAtCompileTime,_ActualRhsType::MaxSizeAtCompileTime,!DirectlyUseRhs> static_rhs; |
|||
|
|||
ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(), |
|||
DirectlyUseRhs ? const_cast<RhsScalar*>(actualRhs.data()) : static_rhs.data()); |
|||
|
|||
if(!DirectlyUseRhs) |
|||
{ |
|||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN |
|||
int size = actualRhs.size(); |
|||
EIGEN_DENSE_STORAGE_CTOR_PLUGIN |
|||
#endif |
|||
Map<typename _ActualRhsType::PlainObject>(actualRhsPtr, actualRhs.size()) = actualRhs; |
|||
} |
|||
|
|||
general_matrix_vector_product |
|||
<Index,LhsScalar,RowMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsBlasTraits::NeedToConjugate>::run( |
|||
actualLhs.rows(), actualLhs.cols(), |
|||
actualLhs.data(), actualLhs.outerStride(), |
|||
actualRhsPtr, 1, |
|||
dest.data(), dest.innerStride(), |
|||
actualAlpha); |
|||
} |
|||
}; |
|||
|
|||
template<> struct gemv_selector<OnTheRight,ColMajor,false> |
|||
{ |
|||
template<typename ProductType, typename Dest> |
|||
static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) |
|||
{ |
|||
typedef typename Dest::Index Index; |
|||
// TODO makes sure dest is sequentially stored in memory, otherwise use a temp |
|||
const Index size = prod.rhs().rows(); |
|||
for(Index k=0; k<size; ++k) |
|||
dest += (alpha*prod.rhs().coeff(k)) * prod.lhs().col(k); |
|||
} |
|||
}; |
|||
|
|||
template<> struct gemv_selector<OnTheRight,RowMajor,false> |
|||
{ |
|||
template<typename ProductType, typename Dest> |
|||
static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) |
|||
{ |
|||
typedef typename Dest::Index Index; |
|||
// TODO makes sure rhs is sequentially stored in memory, otherwise use a temp |
|||
const Index rows = prod.rows(); |
|||
for(Index i=0; i<rows; ++i) |
|||
dest.coeffRef(i) += alpha * (prod.lhs().row(i).cwiseProduct(prod.rhs().transpose())).sum(); |
|||
} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/*************************************************************************** |
|||
* Implementation of matrix base methods |
|||
***************************************************************************/ |
|||
|
|||
/** \returns the matrix product of \c *this and \a other. |
|||
* |
|||
* \note If instead of the matrix product you want the coefficient-wise product, see Cwise::operator*(). |
|||
* |
|||
* \sa lazyProduct(), operator*=(const MatrixBase&), Cwise::operator*() |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
inline const typename ProductReturnType<Derived, OtherDerived>::Type |
|||
MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const |
|||
{ |
|||
// A note regarding the function declaration: In MSVC, this function will sometimes |
|||
// not be inlined since DenseStorage is an unwindable object for dynamic |
|||
// matrices and product types are holding a member to store the result. |
|||
// Thus it does not help tagging this function with EIGEN_STRONG_INLINE. |
|||
enum { |
|||
ProductIsValid = Derived::ColsAtCompileTime==Dynamic |
|||
|| OtherDerived::RowsAtCompileTime==Dynamic |
|||
|| int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime), |
|||
AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime, |
|||
SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived) |
|||
}; |
|||
// note to the lost user: |
|||
// * for a dot product use: v1.dot(v2) |
|||
// * for a coeff-wise product use: v1.cwiseProduct(v2) |
|||
EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes), |
|||
INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) |
|||
EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), |
|||
INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) |
|||
EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) |
|||
#ifdef EIGEN_DEBUG_PRODUCT |
|||
internal::product_type<Derived,OtherDerived>::debug(); |
|||
#endif |
|||
return typename ProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived()); |
|||
} |
|||
|
|||
/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. |
|||
* |
|||
* The returned product will behave like any other expressions: the coefficients of the product will be |
|||
* computed once at a time as requested. This might be useful in some extremely rare cases when only |
|||
* a small and no coherent fraction of the result's coefficients have to be computed. |
|||
* |
|||
* \warning This version of the matrix product can be much much slower. So use it only if you know |
|||
* what you are doing and that you measured a true speed improvement. |
|||
* |
|||
* \sa operator*(const MatrixBase&) |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename OtherDerived> |
|||
const typename LazyProductReturnType<Derived,OtherDerived>::Type |
|||
MatrixBase<Derived>::lazyProduct(const MatrixBase<OtherDerived> &other) const |
|||
{ |
|||
enum { |
|||
ProductIsValid = Derived::ColsAtCompileTime==Dynamic |
|||
|| OtherDerived::RowsAtCompileTime==Dynamic |
|||
|| int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime), |
|||
AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime, |
|||
SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived) |
|||
}; |
|||
// note to the lost user: |
|||
// * for a dot product use: v1.dot(v2) |
|||
// * for a coeff-wise product use: v1.cwiseProduct(v2) |
|||
EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes), |
|||
INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) |
|||
EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), |
|||
INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) |
|||
EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) |
|||
|
|||
return typename LazyProductReturnType<Derived,OtherDerived>::Type(derived(), other.derived()); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_PRODUCT_H |
@ -0,0 +1,192 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_MAP_H |
|||
#define EIGEN_MAP_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class Map |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief A matrix or vector expression mapping an existing array of data. |
|||
* |
|||
* \tparam PlainObjectType the equivalent matrix type of the mapped data |
|||
* \tparam MapOptions specifies whether the pointer is \c #Aligned, or \c #Unaligned. |
|||
* The default is \c #Unaligned. |
|||
* \tparam StrideType optionally specifies strides. By default, Map assumes the memory layout |
|||
* of an ordinary, contiguous array. This can be overridden by specifying strides. |
|||
* The type passed here must be a specialization of the Stride template, see examples below. |
|||
* |
|||
* This class represents a matrix or vector expression mapping an existing array of data. |
|||
* It can be used to let Eigen interface without any overhead with non-Eigen data structures, |
|||
* such as plain C arrays or structures from other libraries. By default, it assumes that the |
|||
* data is laid out contiguously in memory. You can however override this by explicitly specifying |
|||
* inner and outer strides. |
|||
* |
|||
* Here's an example of simply mapping a contiguous array as a \ref TopicStorageOrders "column-major" matrix: |
|||
* \include Map_simple.cpp |
|||
* Output: \verbinclude Map_simple.out |
|||
* |
|||
* If you need to map non-contiguous arrays, you can do so by specifying strides: |
|||
* |
|||
* Here's an example of mapping an array as a vector, specifying an inner stride, that is, the pointer |
|||
* increment between two consecutive coefficients. Here, we're specifying the inner stride as a compile-time |
|||
* fixed value. |
|||
* \include Map_inner_stride.cpp |
|||
* Output: \verbinclude Map_inner_stride.out |
|||
* |
|||
* Here's an example of mapping an array while specifying an outer stride. Here, since we're mapping |
|||
* as a column-major matrix, 'outer stride' means the pointer increment between two consecutive columns. |
|||
* Here, we're specifying the outer stride as a runtime parameter. Note that here \c OuterStride<> is |
|||
* a short version of \c OuterStride<Dynamic> because the default template parameter of OuterStride |
|||
* is \c Dynamic |
|||
* \include Map_outer_stride.cpp |
|||
* Output: \verbinclude Map_outer_stride.out |
|||
* |
|||
* For more details and for an example of specifying both an inner and an outer stride, see class Stride. |
|||
* |
|||
* \b Tip: to change the array of data mapped by a Map object, you can use the C++ |
|||
* placement new syntax: |
|||
* |
|||
* Example: \include Map_placement_new.cpp |
|||
* Output: \verbinclude Map_placement_new.out |
|||
* |
|||
* This class is the return type of PlainObjectBase::Map() but can also be used directly. |
|||
* |
|||
* \sa PlainObjectBase::Map(), \ref TopicStorageOrders |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename PlainObjectType, int MapOptions, typename StrideType> |
|||
struct traits<Map<PlainObjectType, MapOptions, StrideType> > |
|||
: public traits<PlainObjectType> |
|||
{ |
|||
typedef traits<PlainObjectType> TraitsBase; |
|||
typedef typename PlainObjectType::Index Index; |
|||
typedef typename PlainObjectType::Scalar Scalar; |
|||
enum { |
|||
InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0 |
|||
? int(PlainObjectType::InnerStrideAtCompileTime) |
|||
: int(StrideType::InnerStrideAtCompileTime), |
|||
OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0 |
|||
? int(PlainObjectType::OuterStrideAtCompileTime) |
|||
: int(StrideType::OuterStrideAtCompileTime), |
|||
HasNoInnerStride = InnerStrideAtCompileTime == 1, |
|||
HasNoOuterStride = StrideType::OuterStrideAtCompileTime == 0, |
|||
HasNoStride = HasNoInnerStride && HasNoOuterStride, |
|||
IsAligned = bool(EIGEN_ALIGN) && ((int(MapOptions)&Aligned)==Aligned), |
|||
IsDynamicSize = PlainObjectType::SizeAtCompileTime==Dynamic, |
|||
KeepsPacketAccess = bool(HasNoInnerStride) |
|||
&& ( bool(IsDynamicSize) |
|||
|| HasNoOuterStride |
|||
|| ( OuterStrideAtCompileTime!=Dynamic |
|||
&& ((static_cast<int>(sizeof(Scalar))*OuterStrideAtCompileTime)%16)==0 ) ), |
|||
Flags0 = TraitsBase::Flags & (~NestByRefBit), |
|||
Flags1 = IsAligned ? (int(Flags0) | AlignedBit) : (int(Flags0) & ~AlignedBit), |
|||
Flags2 = (bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime)) |
|||
? int(Flags1) : int(Flags1 & ~LinearAccessBit), |
|||
Flags3 = is_lvalue<PlainObjectType>::value ? int(Flags2) : (int(Flags2) & ~LvalueBit), |
|||
Flags = KeepsPacketAccess ? int(Flags3) : (int(Flags3) & ~PacketAccessBit) |
|||
}; |
|||
private: |
|||
enum { Options }; // Expressions don't have Options |
|||
}; |
|||
} |
|||
|
|||
template<typename PlainObjectType, int MapOptions, typename StrideType> class Map |
|||
: public MapBase<Map<PlainObjectType, MapOptions, StrideType> > |
|||
{ |
|||
public: |
|||
|
|||
typedef MapBase<Map> Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Map) |
|||
|
|||
typedef typename Base::PointerType PointerType; |
|||
#if EIGEN2_SUPPORT_STAGE <= STAGE30_FULL_EIGEN3_API |
|||
typedef const Scalar* PointerArgType; |
|||
inline PointerType cast_to_pointer_type(PointerArgType ptr) { return const_cast<PointerType>(ptr); } |
|||
#else |
|||
typedef PointerType PointerArgType; |
|||
inline PointerType cast_to_pointer_type(PointerArgType ptr) { return ptr; } |
|||
#endif |
|||
|
|||
inline Index innerStride() const |
|||
{ |
|||
return StrideType::InnerStrideAtCompileTime != 0 ? m_stride.inner() : 1; |
|||
} |
|||
|
|||
inline Index outerStride() const |
|||
{ |
|||
return StrideType::OuterStrideAtCompileTime != 0 ? m_stride.outer() |
|||
: IsVectorAtCompileTime ? this->size() |
|||
: int(Flags)&RowMajorBit ? this->cols() |
|||
: this->rows(); |
|||
} |
|||
|
|||
/** Constructor in the fixed-size case. |
|||
* |
|||
* \param data pointer to the array to map |
|||
* \param stride optional Stride object, passing the strides. |
|||
*/ |
|||
inline Map(PointerArgType data, const StrideType& stride = StrideType()) |
|||
: Base(cast_to_pointer_type(data)), m_stride(stride) |
|||
{ |
|||
PlainObjectType::Base::_check_template_params(); |
|||
} |
|||
|
|||
/** Constructor in the dynamic-size vector case. |
|||
* |
|||
* \param data pointer to the array to map |
|||
* \param size the size of the vector expression |
|||
* \param stride optional Stride object, passing the strides. |
|||
*/ |
|||
inline Map(PointerArgType data, Index size, const StrideType& stride = StrideType()) |
|||
: Base(cast_to_pointer_type(data), size), m_stride(stride) |
|||
{ |
|||
PlainObjectType::Base::_check_template_params(); |
|||
} |
|||
|
|||
/** Constructor in the dynamic-size matrix case. |
|||
* |
|||
* \param data pointer to the array to map |
|||
* \param rows the number of rows of the matrix expression |
|||
* \param cols the number of columns of the matrix expression |
|||
* \param stride optional Stride object, passing the strides. |
|||
*/ |
|||
inline Map(PointerArgType data, Index rows, Index cols, const StrideType& stride = StrideType()) |
|||
: Base(cast_to_pointer_type(data), rows, cols), m_stride(stride) |
|||
{ |
|||
PlainObjectType::Base::_check_template_params(); |
|||
} |
|||
|
|||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map) |
|||
|
|||
protected: |
|||
StrideType m_stride; |
|||
}; |
|||
|
|||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> |
|||
inline Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> |
|||
::Array(const Scalar *data) |
|||
{ |
|||
this->_set_noalias(Eigen::Map<const Array>(data)); |
|||
} |
|||
|
|||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> |
|||
inline Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> |
|||
::Matrix(const Scalar *data) |
|||
{ |
|||
this->_set_noalias(Eigen::Map<const Matrix>(data)); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_MAP_H |
@ -0,0 +1,242 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_MAPBASE_H |
|||
#define EIGEN_MAPBASE_H |
|||
|
|||
#define EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) \ |
|||
EIGEN_STATIC_ASSERT((int(internal::traits<Derived>::Flags) & LinearAccessBit) || Derived::IsVectorAtCompileTime, \ |
|||
YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT) |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class MapBase |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Base class for Map and Block expression with direct access |
|||
* |
|||
* \sa class Map, class Block |
|||
*/ |
|||
template<typename Derived> class MapBase<Derived, ReadOnlyAccessors> |
|||
: public internal::dense_xpr_base<Derived>::type |
|||
{ |
|||
public: |
|||
|
|||
typedef typename internal::dense_xpr_base<Derived>::type Base; |
|||
enum { |
|||
RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime, |
|||
ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime, |
|||
SizeAtCompileTime = Base::SizeAtCompileTime |
|||
}; |
|||
|
|||
typedef typename internal::traits<Derived>::StorageKind StorageKind; |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
typedef typename internal::traits<Derived>::Scalar Scalar; |
|||
typedef typename internal::packet_traits<Scalar>::type PacketScalar; |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
typedef typename internal::conditional< |
|||
bool(internal::is_lvalue<Derived>::value), |
|||
Scalar *, |
|||
const Scalar *>::type |
|||
PointerType; |
|||
|
|||
using Base::derived; |
|||
// using Base::RowsAtCompileTime; |
|||
// using Base::ColsAtCompileTime; |
|||
// using Base::SizeAtCompileTime; |
|||
using Base::MaxRowsAtCompileTime; |
|||
using Base::MaxColsAtCompileTime; |
|||
using Base::MaxSizeAtCompileTime; |
|||
using Base::IsVectorAtCompileTime; |
|||
using Base::Flags; |
|||
using Base::IsRowMajor; |
|||
|
|||
using Base::rows; |
|||
using Base::cols; |
|||
using Base::size; |
|||
using Base::coeff; |
|||
using Base::coeffRef; |
|||
using Base::lazyAssign; |
|||
using Base::eval; |
|||
|
|||
using Base::innerStride; |
|||
using Base::outerStride; |
|||
using Base::rowStride; |
|||
using Base::colStride; |
|||
|
|||
// bug 217 - compile error on ICC 11.1 |
|||
using Base::operator=; |
|||
|
|||
typedef typename Base::CoeffReturnType CoeffReturnType; |
|||
|
|||
inline Index rows() const { return m_rows.value(); } |
|||
inline Index cols() const { return m_cols.value(); } |
|||
|
|||
/** Returns a pointer to the first coefficient of the matrix or vector. |
|||
* |
|||
* \note When addressing this data, make sure to honor the strides returned by innerStride() and outerStride(). |
|||
* |
|||
* \sa innerStride(), outerStride() |
|||
*/ |
|||
inline const Scalar* data() const { return m_data; } |
|||
|
|||
inline const Scalar& coeff(Index row, Index col) const |
|||
{ |
|||
return m_data[col * colStride() + row * rowStride()]; |
|||
} |
|||
|
|||
inline const Scalar& coeff(Index index) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) |
|||
return m_data[index * innerStride()]; |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index row, Index col) const |
|||
{ |
|||
return this->m_data[col * colStride() + row * rowStride()]; |
|||
} |
|||
|
|||
inline const Scalar& coeffRef(Index index) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) |
|||
return this->m_data[index * innerStride()]; |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
return internal::ploadt<PacketScalar, LoadMode> |
|||
(m_data + (col * colStride() + row * rowStride())); |
|||
} |
|||
|
|||
template<int LoadMode> |
|||
inline PacketScalar packet(Index index) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) |
|||
return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride()); |
|||
} |
|||
|
|||
inline MapBase(PointerType data) : m_data(data), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) |
|||
checkSanity(); |
|||
} |
|||
|
|||
inline MapBase(PointerType data, Index size) |
|||
: m_data(data), |
|||
m_rows(RowsAtCompileTime == Dynamic ? size : Index(RowsAtCompileTime)), |
|||
m_cols(ColsAtCompileTime == Dynamic ? size : Index(ColsAtCompileTime)) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
|||
eigen_assert(size >= 0); |
|||
eigen_assert(data == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == size); |
|||
checkSanity(); |
|||
} |
|||
|
|||
inline MapBase(PointerType data, Index rows, Index cols) |
|||
: m_data(data), m_rows(rows), m_cols(cols) |
|||
{ |
|||
eigen_assert( (data == 0) |
|||
|| ( rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) |
|||
&& cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols))); |
|||
checkSanity(); |
|||
} |
|||
|
|||
protected: |
|||
|
|||
void checkSanity() const |
|||
{ |
|||
EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(internal::traits<Derived>::Flags&PacketAccessBit, |
|||
internal::inner_stride_at_compile_time<Derived>::ret==1), |
|||
PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1); |
|||
eigen_assert(EIGEN_IMPLIES(internal::traits<Derived>::Flags&AlignedBit, (size_t(m_data) % 16) == 0) |
|||
&& "data is not aligned"); |
|||
} |
|||
|
|||
PointerType m_data; |
|||
const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_rows; |
|||
const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_cols; |
|||
}; |
|||
|
|||
template<typename Derived> class MapBase<Derived, WriteAccessors> |
|||
: public MapBase<Derived, ReadOnlyAccessors> |
|||
{ |
|||
public: |
|||
|
|||
typedef MapBase<Derived, ReadOnlyAccessors> Base; |
|||
|
|||
typedef typename Base::Scalar Scalar; |
|||
typedef typename Base::PacketScalar PacketScalar; |
|||
typedef typename Base::Index Index; |
|||
typedef typename Base::PointerType PointerType; |
|||
|
|||
using Base::derived; |
|||
using Base::rows; |
|||
using Base::cols; |
|||
using Base::size; |
|||
using Base::coeff; |
|||
using Base::coeffRef; |
|||
|
|||
using Base::innerStride; |
|||
using Base::outerStride; |
|||
using Base::rowStride; |
|||
using Base::colStride; |
|||
|
|||
typedef typename internal::conditional< |
|||
internal::is_lvalue<Derived>::value, |
|||
Scalar, |
|||
const Scalar |
|||
>::type ScalarWithConstIfNotLvalue; |
|||
|
|||
inline const Scalar* data() const { return this->m_data; } |
|||
inline ScalarWithConstIfNotLvalue* data() { return this->m_data; } // no const-cast here so non-const-correct code will give a compile error |
|||
|
|||
inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col) |
|||
{ |
|||
return this->m_data[col * colStride() + row * rowStride()]; |
|||
} |
|||
|
|||
inline ScalarWithConstIfNotLvalue& coeffRef(Index index) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) |
|||
return this->m_data[index * innerStride()]; |
|||
} |
|||
|
|||
template<int StoreMode> |
|||
inline void writePacket(Index row, Index col, const PacketScalar& x) |
|||
{ |
|||
internal::pstoret<Scalar, PacketScalar, StoreMode> |
|||
(this->m_data + (col * colStride() + row * rowStride()), x); |
|||
} |
|||
|
|||
template<int StoreMode> |
|||
inline void writePacket(Index index, const PacketScalar& x) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) |
|||
internal::pstoret<Scalar, PacketScalar, StoreMode> |
|||
(this->m_data + index * innerStride(), x); |
|||
} |
|||
|
|||
explicit inline MapBase(PointerType data) : Base(data) {} |
|||
inline MapBase(PointerType data, Index size) : Base(data, size) {} |
|||
inline MapBase(PointerType data, Index rows, Index cols) : Base(data, rows, cols) {} |
|||
|
|||
Derived& operator=(const MapBase& other) |
|||
{ |
|||
Base::Base::operator=(other); |
|||
return derived(); |
|||
} |
|||
|
|||
using Base::Base::operator=; |
|||
}; |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_MAPBASE_H |
@ -0,0 +1,842 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_MATHFUNCTIONS_H |
|||
#define EIGEN_MATHFUNCTIONS_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
|
|||
/** \internal \struct global_math_functions_filtering_base |
|||
* |
|||
* What it does: |
|||
* Defines a typedef 'type' as follows: |
|||
* - if type T has a member typedef Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl, then |
|||
* global_math_functions_filtering_base<T>::type is a typedef for it. |
|||
* - otherwise, global_math_functions_filtering_base<T>::type is a typedef for T. |
|||
* |
|||
* How it's used: |
|||
* To allow to defined the global math functions (like sin...) in certain cases, like the Array expressions. |
|||
* When you do sin(array1+array2), the object array1+array2 has a complicated expression type, all what you want to know |
|||
* is that it inherits ArrayBase. So we implement a partial specialization of sin_impl for ArrayBase<Derived>. |
|||
* So we must make sure to use sin_impl<ArrayBase<Derived> > and not sin_impl<Derived>, otherwise our partial specialization |
|||
* won't be used. How does sin know that? That's exactly what global_math_functions_filtering_base tells it. |
|||
* |
|||
* How it's implemented: |
|||
* SFINAE in the style of enable_if. Highly susceptible of breaking compilers. With GCC, it sure does work, but if you replace |
|||
* the typename dummy by an integer template parameter, it doesn't work anymore! |
|||
*/ |
|||
|
|||
template<typename T, typename dummy = void> |
|||
struct global_math_functions_filtering_base |
|||
{ |
|||
typedef T type; |
|||
}; |
|||
|
|||
template<typename T> struct always_void { typedef void type; }; |
|||
|
|||
template<typename T> |
|||
struct global_math_functions_filtering_base |
|||
<T, |
|||
typename always_void<typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl>::type |
|||
> |
|||
{ |
|||
typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type; |
|||
}; |
|||
|
|||
#define EIGEN_MATHFUNC_IMPL(func, scalar) func##_impl<typename global_math_functions_filtering_base<scalar>::type> |
|||
#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename func##_retval<typename global_math_functions_filtering_base<scalar>::type>::type |
|||
|
|||
|
|||
/**************************************************************************** |
|||
* Implementation of real * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar> |
|||
struct real_impl |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
static inline RealScalar run(const Scalar& x) |
|||
{ |
|||
return x; |
|||
} |
|||
}; |
|||
|
|||
template<typename RealScalar> |
|||
struct real_impl<std::complex<RealScalar> > |
|||
{ |
|||
static inline RealScalar run(const std::complex<RealScalar>& x) |
|||
{ |
|||
using std::real; |
|||
return real(x); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct real_retval |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of imag * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar> |
|||
struct imag_impl |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
static inline RealScalar run(const Scalar&) |
|||
{ |
|||
return RealScalar(0); |
|||
} |
|||
}; |
|||
|
|||
template<typename RealScalar> |
|||
struct imag_impl<std::complex<RealScalar> > |
|||
{ |
|||
static inline RealScalar run(const std::complex<RealScalar>& x) |
|||
{ |
|||
using std::imag; |
|||
return imag(x); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct imag_retval |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of real_ref * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar> |
|||
struct real_ref_impl |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
static inline RealScalar& run(Scalar& x) |
|||
{ |
|||
return reinterpret_cast<RealScalar*>(&x)[0]; |
|||
} |
|||
static inline const RealScalar& run(const Scalar& x) |
|||
{ |
|||
return reinterpret_cast<const RealScalar*>(&x)[0]; |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct real_ref_retval |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real & type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x) |
|||
{ |
|||
return real_ref_impl<Scalar>::run(x); |
|||
} |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of imag_ref * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar, bool IsComplex> |
|||
struct imag_ref_default_impl |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
static inline RealScalar& run(Scalar& x) |
|||
{ |
|||
return reinterpret_cast<RealScalar*>(&x)[1]; |
|||
} |
|||
static inline const RealScalar& run(const Scalar& x) |
|||
{ |
|||
return reinterpret_cast<RealScalar*>(&x)[1]; |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct imag_ref_default_impl<Scalar, false> |
|||
{ |
|||
static inline Scalar run(Scalar&) |
|||
{ |
|||
return Scalar(0); |
|||
} |
|||
static inline const Scalar run(const Scalar&) |
|||
{ |
|||
return Scalar(0); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; |
|||
|
|||
template<typename Scalar> |
|||
struct imag_ref_retval |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real & type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x) |
|||
{ |
|||
return imag_ref_impl<Scalar>::run(x); |
|||
} |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of conj * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar> |
|||
struct conj_impl |
|||
{ |
|||
static inline Scalar run(const Scalar& x) |
|||
{ |
|||
return x; |
|||
} |
|||
}; |
|||
|
|||
template<typename RealScalar> |
|||
struct conj_impl<std::complex<RealScalar> > |
|||
{ |
|||
static inline std::complex<RealScalar> run(const std::complex<RealScalar>& x) |
|||
{ |
|||
using std::conj; |
|||
return conj(x); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct conj_retval |
|||
{ |
|||
typedef Scalar type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of abs * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar> |
|||
struct abs_impl |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
static inline RealScalar run(const Scalar& x) |
|||
{ |
|||
using std::abs; |
|||
return abs(x); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct abs_retval |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(abs, Scalar) abs(const Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(abs, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of abs2 * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar> |
|||
struct abs2_impl |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
static inline RealScalar run(const Scalar& x) |
|||
{ |
|||
return x*x; |
|||
} |
|||
}; |
|||
|
|||
template<typename RealScalar> |
|||
struct abs2_impl<std::complex<RealScalar> > |
|||
{ |
|||
static inline RealScalar run(const std::complex<RealScalar>& x) |
|||
{ |
|||
return real(x)*real(x) + imag(x)*imag(x); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct abs2_retval |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of norm1 * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar, bool IsComplex> |
|||
struct norm1_default_impl |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
static inline RealScalar run(const Scalar& x) |
|||
{ |
|||
return abs(real(x)) + abs(imag(x)); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct norm1_default_impl<Scalar, false> |
|||
{ |
|||
static inline Scalar run(const Scalar& x) |
|||
{ |
|||
return abs(x); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; |
|||
|
|||
template<typename Scalar> |
|||
struct norm1_retval |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of hypot * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar> |
|||
struct hypot_impl |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
static inline RealScalar run(const Scalar& x, const Scalar& y) |
|||
{ |
|||
using std::max; |
|||
using std::min; |
|||
RealScalar _x = abs(x); |
|||
RealScalar _y = abs(y); |
|||
RealScalar p = (max)(_x, _y); |
|||
RealScalar q = (min)(_x, _y); |
|||
RealScalar qp = q/p; |
|||
return p * sqrt(RealScalar(1) + qp*qp); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct hypot_retval |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of cast * |
|||
****************************************************************************/ |
|||
|
|||
template<typename OldType, typename NewType> |
|||
struct cast_impl |
|||
{ |
|||
static inline NewType run(const OldType& x) |
|||
{ |
|||
return static_cast<NewType>(x); |
|||
} |
|||
}; |
|||
|
|||
// here, for once, we're plainly returning NewType: we don't want cast to do weird things. |
|||
|
|||
template<typename OldType, typename NewType> |
|||
inline NewType cast(const OldType& x) |
|||
{ |
|||
return cast_impl<OldType, NewType>::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of sqrt * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar, bool IsInteger> |
|||
struct sqrt_default_impl |
|||
{ |
|||
static inline Scalar run(const Scalar& x) |
|||
{ |
|||
using std::sqrt; |
|||
return sqrt(x); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct sqrt_default_impl<Scalar, true> |
|||
{ |
|||
static inline Scalar run(const Scalar&) |
|||
{ |
|||
#ifdef EIGEN2_SUPPORT |
|||
eigen_assert(!NumTraits<Scalar>::IsInteger); |
|||
#else |
|||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) |
|||
#endif |
|||
return Scalar(0); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct sqrt_impl : sqrt_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; |
|||
|
|||
template<typename Scalar> |
|||
struct sqrt_retval |
|||
{ |
|||
typedef Scalar type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(sqrt, Scalar)::run(x); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of standard unary real functions (exp, log, sin, cos, ... * |
|||
****************************************************************************/ |
|||
|
|||
// This macro instanciate all the necessary template mechanism which is common to all unary real functions. |
|||
#define EIGEN_MATHFUNC_STANDARD_REAL_UNARY(NAME) \ |
|||
template<typename Scalar, bool IsInteger> struct NAME##_default_impl { \ |
|||
static inline Scalar run(const Scalar& x) { using std::NAME; return NAME(x); } \ |
|||
}; \ |
|||
template<typename Scalar> struct NAME##_default_impl<Scalar, true> { \ |
|||
static inline Scalar run(const Scalar&) { \ |
|||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) \ |
|||
return Scalar(0); \ |
|||
} \ |
|||
}; \ |
|||
template<typename Scalar> struct NAME##_impl \ |
|||
: NAME##_default_impl<Scalar, NumTraits<Scalar>::IsInteger> \ |
|||
{}; \ |
|||
template<typename Scalar> struct NAME##_retval { typedef Scalar type; }; \ |
|||
template<typename Scalar> \ |
|||
inline EIGEN_MATHFUNC_RETVAL(NAME, Scalar) NAME(const Scalar& x) { \ |
|||
return EIGEN_MATHFUNC_IMPL(NAME, Scalar)::run(x); \ |
|||
} |
|||
|
|||
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(exp) |
|||
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(log) |
|||
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(sin) |
|||
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(cos) |
|||
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(tan) |
|||
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(asin) |
|||
EIGEN_MATHFUNC_STANDARD_REAL_UNARY(acos) |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of atan2 * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar, bool IsInteger> |
|||
struct atan2_default_impl |
|||
{ |
|||
typedef Scalar retval; |
|||
static inline Scalar run(const Scalar& x, const Scalar& y) |
|||
{ |
|||
using std::atan2; |
|||
return atan2(x, y); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct atan2_default_impl<Scalar, true> |
|||
{ |
|||
static inline Scalar run(const Scalar&, const Scalar&) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) |
|||
return Scalar(0); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct atan2_impl : atan2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; |
|||
|
|||
template<typename Scalar> |
|||
struct atan2_retval |
|||
{ |
|||
typedef Scalar type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(atan2, Scalar) atan2(const Scalar& x, const Scalar& y) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(atan2, Scalar)::run(x, y); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of pow * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar, bool IsInteger> |
|||
struct pow_default_impl |
|||
{ |
|||
typedef Scalar retval; |
|||
static inline Scalar run(const Scalar& x, const Scalar& y) |
|||
{ |
|||
using std::pow; |
|||
return pow(x, y); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct pow_default_impl<Scalar, true> |
|||
{ |
|||
static inline Scalar run(Scalar x, Scalar y) |
|||
{ |
|||
Scalar res(1); |
|||
eigen_assert(!NumTraits<Scalar>::IsSigned || y >= 0); |
|||
if(y & 1) res *= x; |
|||
y >>= 1; |
|||
while(y) |
|||
{ |
|||
x *= x; |
|||
if(y&1) res *= x; |
|||
y >>= 1; |
|||
} |
|||
return res; |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct pow_impl : pow_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; |
|||
|
|||
template<typename Scalar> |
|||
struct pow_retval |
|||
{ |
|||
typedef Scalar type; |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of random * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar, |
|||
bool IsComplex, |
|||
bool IsInteger> |
|||
struct random_default_impl {}; |
|||
|
|||
template<typename Scalar> |
|||
struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; |
|||
|
|||
template<typename Scalar> |
|||
struct random_retval |
|||
{ |
|||
typedef Scalar type; |
|||
}; |
|||
|
|||
template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y); |
|||
template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(); |
|||
|
|||
template<typename Scalar> |
|||
struct random_default_impl<Scalar, false, false> |
|||
{ |
|||
static inline Scalar run(const Scalar& x, const Scalar& y) |
|||
{ |
|||
return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX); |
|||
} |
|||
static inline Scalar run() |
|||
{ |
|||
return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1)); |
|||
} |
|||
}; |
|||
|
|||
enum { |
|||
floor_log2_terminate, |
|||
floor_log2_move_up, |
|||
floor_log2_move_down, |
|||
floor_log2_bogus |
|||
}; |
|||
|
|||
template<unsigned int n, int lower, int upper> struct floor_log2_selector |
|||
{ |
|||
enum { middle = (lower + upper) / 2, |
|||
value = (upper <= lower + 1) ? int(floor_log2_terminate) |
|||
: (n < (1 << middle)) ? int(floor_log2_move_down) |
|||
: (n==0) ? int(floor_log2_bogus) |
|||
: int(floor_log2_move_up) |
|||
}; |
|||
}; |
|||
|
|||
template<unsigned int n, |
|||
int lower = 0, |
|||
int upper = sizeof(unsigned int) * CHAR_BIT - 1, |
|||
int selector = floor_log2_selector<n, lower, upper>::value> |
|||
struct floor_log2 {}; |
|||
|
|||
template<unsigned int n, int lower, int upper> |
|||
struct floor_log2<n, lower, upper, floor_log2_move_down> |
|||
{ |
|||
enum { value = floor_log2<n, lower, floor_log2_selector<n, lower, upper>::middle>::value }; |
|||
}; |
|||
|
|||
template<unsigned int n, int lower, int upper> |
|||
struct floor_log2<n, lower, upper, floor_log2_move_up> |
|||
{ |
|||
enum { value = floor_log2<n, floor_log2_selector<n, lower, upper>::middle, upper>::value }; |
|||
}; |
|||
|
|||
template<unsigned int n, int lower, int upper> |
|||
struct floor_log2<n, lower, upper, floor_log2_terminate> |
|||
{ |
|||
enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower }; |
|||
}; |
|||
|
|||
template<unsigned int n, int lower, int upper> |
|||
struct floor_log2<n, lower, upper, floor_log2_bogus> |
|||
{ |
|||
// no value, error at compile time |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct random_default_impl<Scalar, false, true> |
|||
{ |
|||
typedef typename NumTraits<Scalar>::NonInteger NonInteger; |
|||
|
|||
static inline Scalar run(const Scalar& x, const Scalar& y) |
|||
{ |
|||
return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1))); |
|||
} |
|||
|
|||
static inline Scalar run() |
|||
{ |
|||
#ifdef EIGEN_MAKING_DOCS |
|||
return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10)); |
|||
#else |
|||
enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value, |
|||
scalar_bits = sizeof(Scalar) * CHAR_BIT, |
|||
shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)) |
|||
}; |
|||
Scalar x = Scalar(std::rand() >> shift); |
|||
Scalar offset = NumTraits<Scalar>::IsSigned ? Scalar(1 << (rand_bits-1)) : Scalar(0); |
|||
return x - offset; |
|||
#endif |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct random_default_impl<Scalar, true, false> |
|||
{ |
|||
static inline Scalar run(const Scalar& x, const Scalar& y) |
|||
{ |
|||
return Scalar(random(real(x), real(y)), |
|||
random(imag(x), imag(y))); |
|||
} |
|||
static inline Scalar run() |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
return Scalar(random<RealScalar>(), random<RealScalar>()); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y) |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y); |
|||
} |
|||
|
|||
template<typename Scalar> |
|||
inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random() |
|||
{ |
|||
return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(); |
|||
} |
|||
|
|||
/**************************************************************************** |
|||
* Implementation of fuzzy comparisons * |
|||
****************************************************************************/ |
|||
|
|||
template<typename Scalar, |
|||
bool IsComplex, |
|||
bool IsInteger> |
|||
struct scalar_fuzzy_default_impl {}; |
|||
|
|||
template<typename Scalar> |
|||
struct scalar_fuzzy_default_impl<Scalar, false, false> |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
template<typename OtherScalar> |
|||
static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) |
|||
{ |
|||
return abs(x) <= abs(y) * prec; |
|||
} |
|||
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) |
|||
{ |
|||
using std::min; |
|||
return abs(x - y) <= (min)(abs(x), abs(y)) * prec; |
|||
} |
|||
static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec) |
|||
{ |
|||
return x <= y || isApprox(x, y, prec); |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct scalar_fuzzy_default_impl<Scalar, false, true> |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
template<typename OtherScalar> |
|||
static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&) |
|||
{ |
|||
return x == Scalar(0); |
|||
} |
|||
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&) |
|||
{ |
|||
return x == y; |
|||
} |
|||
static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&) |
|||
{ |
|||
return x <= y; |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct scalar_fuzzy_default_impl<Scalar, true, false> |
|||
{ |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
template<typename OtherScalar> |
|||
static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) |
|||
{ |
|||
return abs2(x) <= abs2(y) * prec * prec; |
|||
} |
|||
static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) |
|||
{ |
|||
using std::min; |
|||
return abs2(x - y) <= (min)(abs2(x), abs2(y)) * prec * prec; |
|||
} |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; |
|||
|
|||
template<typename Scalar, typename OtherScalar> |
|||
inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, |
|||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) |
|||
{ |
|||
return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision); |
|||
} |
|||
|
|||
template<typename Scalar> |
|||
inline bool isApprox(const Scalar& x, const Scalar& y, |
|||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) |
|||
{ |
|||
return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision); |
|||
} |
|||
|
|||
template<typename Scalar> |
|||
inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, |
|||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) |
|||
{ |
|||
return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision); |
|||
} |
|||
|
|||
/****************************************** |
|||
*** The special case of the bool type *** |
|||
******************************************/ |
|||
|
|||
template<> struct random_impl<bool> |
|||
{ |
|||
static inline bool run() |
|||
{ |
|||
return random<int>(0,1)==0 ? false : true; |
|||
} |
|||
}; |
|||
|
|||
template<> struct scalar_fuzzy_impl<bool> |
|||
{ |
|||
typedef bool RealScalar; |
|||
|
|||
template<typename OtherScalar> |
|||
static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&) |
|||
{ |
|||
return !x; |
|||
} |
|||
|
|||
static inline bool isApprox(bool x, bool y, bool) |
|||
{ |
|||
return x == y; |
|||
} |
|||
|
|||
static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&) |
|||
{ |
|||
return (!x) || y; |
|||
} |
|||
|
|||
}; |
|||
|
|||
/**************************************************************************** |
|||
* Special functions * |
|||
****************************************************************************/ |
|||
|
|||
// std::isfinite is non standard, so let's define our own version, |
|||
// even though it is not very efficient. |
|||
template<typename T> bool (isfinite)(const T& x) |
|||
{ |
|||
return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest(); |
|||
} |
|||
|
|||
} // end namespace internal |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_MATHFUNCTIONS_H |
@ -0,0 +1,511 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2006-2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_MATRIXBASE_H |
|||
#define EIGEN_MATRIXBASE_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class MatrixBase |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Base class for all dense matrices, vectors, and expressions |
|||
* |
|||
* This class is the base that is inherited by all matrix, vector, and related expression |
|||
* types. Most of the Eigen API is contained in this class, and its base classes. Other important |
|||
* classes for the Eigen API are Matrix, and VectorwiseOp. |
|||
* |
|||
* Note that some methods are defined in other modules such as the \ref LU_Module LU module |
|||
* for all functions related to matrix inversions. |
|||
* |
|||
* \tparam Derived is the derived type, e.g. a matrix type, or an expression, etc. |
|||
* |
|||
* When writing a function taking Eigen objects as argument, if you want your function |
|||
* to take as argument any matrix, vector, or expression, just let it take a |
|||
* MatrixBase argument. As an example, here is a function printFirstRow which, given |
|||
* a matrix, vector, or expression \a x, prints the first row of \a x. |
|||
* |
|||
* \code |
|||
template<typename Derived> |
|||
void printFirstRow(const Eigen::MatrixBase<Derived>& x) |
|||
{ |
|||
cout << x.row(0) << endl; |
|||
} |
|||
* \endcode |
|||
* |
|||
* This class can be extended with the help of the plugin mechanism described on the page |
|||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_MATRIXBASE_PLUGIN. |
|||
* |
|||
* \sa \ref TopicClassHierarchy |
|||
*/ |
|||
template<typename Derived> class MatrixBase |
|||
: public DenseBase<Derived> |
|||
{ |
|||
public: |
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
typedef MatrixBase StorageBaseType; |
|||
typedef typename internal::traits<Derived>::StorageKind StorageKind; |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
typedef typename internal::traits<Derived>::Scalar Scalar; |
|||
typedef typename internal::packet_traits<Scalar>::type PacketScalar; |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
|
|||
typedef DenseBase<Derived> Base; |
|||
using Base::RowsAtCompileTime; |
|||
using Base::ColsAtCompileTime; |
|||
using Base::SizeAtCompileTime; |
|||
using Base::MaxRowsAtCompileTime; |
|||
using Base::MaxColsAtCompileTime; |
|||
using Base::MaxSizeAtCompileTime; |
|||
using Base::IsVectorAtCompileTime; |
|||
using Base::Flags; |
|||
using Base::CoeffReadCost; |
|||
|
|||
using Base::derived; |
|||
using Base::const_cast_derived; |
|||
using Base::rows; |
|||
using Base::cols; |
|||
using Base::size; |
|||
using Base::coeff; |
|||
using Base::coeffRef; |
|||
using Base::lazyAssign; |
|||
using Base::eval; |
|||
using Base::operator+=; |
|||
using Base::operator-=; |
|||
using Base::operator*=; |
|||
using Base::operator/=; |
|||
|
|||
typedef typename Base::CoeffReturnType CoeffReturnType; |
|||
typedef typename Base::ConstTransposeReturnType ConstTransposeReturnType; |
|||
typedef typename Base::RowXpr RowXpr; |
|||
typedef typename Base::ColXpr ColXpr; |
|||
#endif // not EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
|
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** type of the equivalent square matrix */ |
|||
typedef Matrix<Scalar,EIGEN_SIZE_MAX(RowsAtCompileTime,ColsAtCompileTime), |
|||
EIGEN_SIZE_MAX(RowsAtCompileTime,ColsAtCompileTime)> SquareMatrixType; |
|||
#endif // not EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
/** \returns the size of the main diagonal, which is min(rows(),cols()). |
|||
* \sa rows(), cols(), SizeAtCompileTime. */ |
|||
inline Index diagonalSize() const { return (std::min)(rows(),cols()); } |
|||
|
|||
/** \brief The plain matrix type corresponding to this expression. |
|||
* |
|||
* This is not necessarily exactly the return type of eval(). In the case of plain matrices, |
|||
* the return type of eval() is a const reference to a matrix, not a matrix! It is however guaranteed |
|||
* that the return type of eval() is either PlainObject or const PlainObject&. |
|||
*/ |
|||
typedef Matrix<typename internal::traits<Derived>::Scalar, |
|||
internal::traits<Derived>::RowsAtCompileTime, |
|||
internal::traits<Derived>::ColsAtCompileTime, |
|||
AutoAlign | (internal::traits<Derived>::Flags&RowMajorBit ? RowMajor : ColMajor), |
|||
internal::traits<Derived>::MaxRowsAtCompileTime, |
|||
internal::traits<Derived>::MaxColsAtCompileTime |
|||
> PlainObject; |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** \internal Represents a matrix with all coefficients equal to one another*/ |
|||
typedef CwiseNullaryOp<internal::scalar_constant_op<Scalar>,Derived> ConstantReturnType; |
|||
/** \internal the return type of MatrixBase::adjoint() */ |
|||
typedef typename internal::conditional<NumTraits<Scalar>::IsComplex, |
|||
CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, ConstTransposeReturnType>, |
|||
ConstTransposeReturnType |
|||
>::type AdjointReturnType; |
|||
/** \internal Return type of eigenvalues() */ |
|||
typedef Matrix<std::complex<RealScalar>, internal::traits<Derived>::ColsAtCompileTime, 1, ColMajor> EigenvaluesReturnType; |
|||
/** \internal the return type of identity */ |
|||
typedef CwiseNullaryOp<internal::scalar_identity_op<Scalar>,Derived> IdentityReturnType; |
|||
/** \internal the return type of unit vectors */ |
|||
typedef Block<const CwiseNullaryOp<internal::scalar_identity_op<Scalar>, SquareMatrixType>, |
|||
internal::traits<Derived>::RowsAtCompileTime, |
|||
internal::traits<Derived>::ColsAtCompileTime> BasisReturnType; |
|||
#endif // not EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::MatrixBase |
|||
# include "../plugins/CommonCwiseUnaryOps.h" |
|||
# include "../plugins/CommonCwiseBinaryOps.h" |
|||
# include "../plugins/MatrixCwiseUnaryOps.h" |
|||
# include "../plugins/MatrixCwiseBinaryOps.h" |
|||
# ifdef EIGEN_MATRIXBASE_PLUGIN |
|||
# include EIGEN_MATRIXBASE_PLUGIN |
|||
# endif |
|||
#undef EIGEN_CURRENT_STORAGE_BASE_CLASS |
|||
|
|||
/** Special case of the template operator=, in order to prevent the compiler |
|||
* from generating a default operator= (issue hit with g++ 4.1) |
|||
*/ |
|||
Derived& operator=(const MatrixBase& other); |
|||
|
|||
// We cannot inherit here via Base::operator= since it is causing |
|||
// trouble with MSVC. |
|||
|
|||
template <typename OtherDerived> |
|||
Derived& operator=(const DenseBase<OtherDerived>& other); |
|||
|
|||
template <typename OtherDerived> |
|||
Derived& operator=(const EigenBase<OtherDerived>& other); |
|||
|
|||
template<typename OtherDerived> |
|||
Derived& operator=(const ReturnByValue<OtherDerived>& other); |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
template<typename ProductDerived, typename Lhs, typename Rhs> |
|||
Derived& lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other); |
|||
#endif // not EIGEN_PARSED_BY_DOXYGEN |
|||
|
|||
template<typename OtherDerived> |
|||
Derived& operator+=(const MatrixBase<OtherDerived>& other); |
|||
template<typename OtherDerived> |
|||
Derived& operator-=(const MatrixBase<OtherDerived>& other); |
|||
|
|||
template<typename OtherDerived> |
|||
const typename ProductReturnType<Derived,OtherDerived>::Type |
|||
operator*(const MatrixBase<OtherDerived> &other) const; |
|||
|
|||
template<typename OtherDerived> |
|||
const typename LazyProductReturnType<Derived,OtherDerived>::Type |
|||
lazyProduct(const MatrixBase<OtherDerived> &other) const; |
|||
|
|||
template<typename OtherDerived> |
|||
Derived& operator*=(const EigenBase<OtherDerived>& other); |
|||
|
|||
template<typename OtherDerived> |
|||
void applyOnTheLeft(const EigenBase<OtherDerived>& other); |
|||
|
|||
template<typename OtherDerived> |
|||
void applyOnTheRight(const EigenBase<OtherDerived>& other); |
|||
|
|||
template<typename DiagonalDerived> |
|||
const DiagonalProduct<Derived, DiagonalDerived, OnTheRight> |
|||
operator*(const DiagonalBase<DiagonalDerived> &diagonal) const; |
|||
|
|||
template<typename OtherDerived> |
|||
typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType |
|||
dot(const MatrixBase<OtherDerived>& other) const; |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
template<typename OtherDerived> |
|||
Scalar eigen2_dot(const MatrixBase<OtherDerived>& other) const; |
|||
#endif |
|||
|
|||
RealScalar squaredNorm() const; |
|||
RealScalar norm() const; |
|||
RealScalar stableNorm() const; |
|||
RealScalar blueNorm() const; |
|||
RealScalar hypotNorm() const; |
|||
const PlainObject normalized() const; |
|||
void normalize(); |
|||
|
|||
const AdjointReturnType adjoint() const; |
|||
void adjointInPlace(); |
|||
|
|||
typedef Diagonal<Derived> DiagonalReturnType; |
|||
DiagonalReturnType diagonal(); |
|||
typedef const Diagonal<const Derived> ConstDiagonalReturnType; |
|||
const ConstDiagonalReturnType diagonal() const; |
|||
|
|||
template<int Index> struct DiagonalIndexReturnType { typedef Diagonal<Derived,Index> Type; }; |
|||
template<int Index> struct ConstDiagonalIndexReturnType { typedef const Diagonal<const Derived,Index> Type; }; |
|||
|
|||
template<int Index> typename DiagonalIndexReturnType<Index>::Type diagonal(); |
|||
template<int Index> typename ConstDiagonalIndexReturnType<Index>::Type diagonal() const; |
|||
|
|||
// Note: The "MatrixBase::" prefixes are added to help MSVC9 to match these declarations with the later implementations. |
|||
// On the other hand they confuse MSVC8... |
|||
#if (defined _MSC_VER) && (_MSC_VER >= 1500) // 2008 or later |
|||
typename MatrixBase::template DiagonalIndexReturnType<Dynamic>::Type diagonal(Index index); |
|||
typename MatrixBase::template ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const; |
|||
#else |
|||
typename DiagonalIndexReturnType<Dynamic>::Type diagonal(Index index); |
|||
typename ConstDiagonalIndexReturnType<Dynamic>::Type diagonal(Index index) const; |
|||
#endif |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
template<unsigned int Mode> typename internal::eigen2_part_return_type<Derived, Mode>::type part(); |
|||
template<unsigned int Mode> const typename internal::eigen2_part_return_type<Derived, Mode>::type part() const; |
|||
|
|||
// huuuge hack. make Eigen2's matrix.part<Diagonal>() work in eigen3. Problem: Diagonal is now a class template instead |
|||
// of an integer constant. Solution: overload the part() method template wrt template parameters list. |
|||
template<template<typename T, int N> class U> |
|||
const DiagonalWrapper<ConstDiagonalReturnType> part() const |
|||
{ return diagonal().asDiagonal(); } |
|||
#endif // EIGEN2_SUPPORT |
|||
|
|||
template<unsigned int Mode> struct TriangularViewReturnType { typedef TriangularView<Derived, Mode> Type; }; |
|||
template<unsigned int Mode> struct ConstTriangularViewReturnType { typedef const TriangularView<const Derived, Mode> Type; }; |
|||
|
|||
template<unsigned int Mode> typename TriangularViewReturnType<Mode>::Type triangularView(); |
|||
template<unsigned int Mode> typename ConstTriangularViewReturnType<Mode>::Type triangularView() const; |
|||
|
|||
template<unsigned int UpLo> struct SelfAdjointViewReturnType { typedef SelfAdjointView<Derived, UpLo> Type; }; |
|||
template<unsigned int UpLo> struct ConstSelfAdjointViewReturnType { typedef const SelfAdjointView<const Derived, UpLo> Type; }; |
|||
|
|||
template<unsigned int UpLo> typename SelfAdjointViewReturnType<UpLo>::Type selfadjointView(); |
|||
template<unsigned int UpLo> typename ConstSelfAdjointViewReturnType<UpLo>::Type selfadjointView() const; |
|||
|
|||
const SparseView<Derived> sparseView(const Scalar& m_reference = Scalar(0), |
|||
typename NumTraits<Scalar>::Real m_epsilon = NumTraits<Scalar>::dummy_precision()) const; |
|||
static const IdentityReturnType Identity(); |
|||
static const IdentityReturnType Identity(Index rows, Index cols); |
|||
static const BasisReturnType Unit(Index size, Index i); |
|||
static const BasisReturnType Unit(Index i); |
|||
static const BasisReturnType UnitX(); |
|||
static const BasisReturnType UnitY(); |
|||
static const BasisReturnType UnitZ(); |
|||
static const BasisReturnType UnitW(); |
|||
|
|||
const DiagonalWrapper<const Derived> asDiagonal() const; |
|||
const PermutationWrapper<const Derived> asPermutation() const; |
|||
|
|||
Derived& setIdentity(); |
|||
Derived& setIdentity(Index rows, Index cols); |
|||
|
|||
bool isIdentity(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
bool isDiagonal(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
|
|||
bool isUpperTriangular(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
bool isLowerTriangular(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
|
|||
template<typename OtherDerived> |
|||
bool isOrthogonal(const MatrixBase<OtherDerived>& other, |
|||
RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
bool isUnitary(RealScalar prec = NumTraits<Scalar>::dummy_precision()) const; |
|||
|
|||
/** \returns true if each coefficients of \c *this and \a other are all exactly equal. |
|||
* \warning When using floating point scalar values you probably should rather use a |
|||
* fuzzy comparison such as isApprox() |
|||
* \sa isApprox(), operator!= */ |
|||
template<typename OtherDerived> |
|||
inline bool operator==(const MatrixBase<OtherDerived>& other) const |
|||
{ return cwiseEqual(other).all(); } |
|||
|
|||
/** \returns true if at least one pair of coefficients of \c *this and \a other are not exactly equal to each other. |
|||
* \warning When using floating point scalar values you probably should rather use a |
|||
* fuzzy comparison such as isApprox() |
|||
* \sa isApprox(), operator== */ |
|||
template<typename OtherDerived> |
|||
inline bool operator!=(const MatrixBase<OtherDerived>& other) const |
|||
{ return cwiseNotEqual(other).any(); } |
|||
|
|||
NoAlias<Derived,Eigen::MatrixBase > noalias(); |
|||
|
|||
inline const ForceAlignedAccess<Derived> forceAlignedAccess() const; |
|||
inline ForceAlignedAccess<Derived> forceAlignedAccess(); |
|||
template<bool Enable> inline typename internal::add_const_on_value_type<typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type>::type forceAlignedAccessIf() const; |
|||
template<bool Enable> inline typename internal::conditional<Enable,ForceAlignedAccess<Derived>,Derived&>::type forceAlignedAccessIf(); |
|||
|
|||
Scalar trace() const; |
|||
|
|||
/////////// Array module /////////// |
|||
|
|||
template<int p> RealScalar lpNorm() const; |
|||
|
|||
MatrixBase<Derived>& matrix() { return *this; } |
|||
const MatrixBase<Derived>& matrix() const { return *this; } |
|||
|
|||
/** \returns an \link ArrayBase Array \endlink expression of this matrix |
|||
* \sa ArrayBase::matrix() */ |
|||
ArrayWrapper<Derived> array() { return derived(); } |
|||
const ArrayWrapper<const Derived> array() const { return derived(); } |
|||
|
|||
/////////// LU module /////////// |
|||
|
|||
const FullPivLU<PlainObject> fullPivLu() const; |
|||
const PartialPivLU<PlainObject> partialPivLu() const; |
|||
|
|||
#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS |
|||
const LU<PlainObject> lu() const; |
|||
#endif |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
const LU<PlainObject> eigen2_lu() const; |
|||
#endif |
|||
|
|||
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS |
|||
const PartialPivLU<PlainObject> lu() const; |
|||
#endif |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
template<typename ResultType> |
|||
void computeInverse(MatrixBase<ResultType> *result) const { |
|||
*result = this->inverse(); |
|||
} |
|||
#endif |
|||
|
|||
const internal::inverse_impl<Derived> inverse() const; |
|||
template<typename ResultType> |
|||
void computeInverseAndDetWithCheck( |
|||
ResultType& inverse, |
|||
typename ResultType::Scalar& determinant, |
|||
bool& invertible, |
|||
const RealScalar& absDeterminantThreshold = NumTraits<Scalar>::dummy_precision() |
|||
) const; |
|||
template<typename ResultType> |
|||
void computeInverseWithCheck( |
|||
ResultType& inverse, |
|||
bool& invertible, |
|||
const RealScalar& absDeterminantThreshold = NumTraits<Scalar>::dummy_precision() |
|||
) const; |
|||
Scalar determinant() const; |
|||
|
|||
/////////// Cholesky module /////////// |
|||
|
|||
const LLT<PlainObject> llt() const; |
|||
const LDLT<PlainObject> ldlt() const; |
|||
|
|||
/////////// QR module /////////// |
|||
|
|||
const HouseholderQR<PlainObject> householderQr() const; |
|||
const ColPivHouseholderQR<PlainObject> colPivHouseholderQr() const; |
|||
const FullPivHouseholderQR<PlainObject> fullPivHouseholderQr() const; |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
const QR<PlainObject> qr() const; |
|||
#endif |
|||
|
|||
EigenvaluesReturnType eigenvalues() const; |
|||
RealScalar operatorNorm() const; |
|||
|
|||
/////////// SVD module /////////// |
|||
|
|||
JacobiSVD<PlainObject> jacobiSvd(unsigned int computationOptions = 0) const; |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
SVD<PlainObject> svd() const; |
|||
#endif |
|||
|
|||
/////////// Geometry module /////////// |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/// \internal helper struct to form the return type of the cross product |
|||
template<typename OtherDerived> struct cross_product_return_type { |
|||
typedef typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType Scalar; |
|||
typedef Matrix<Scalar,MatrixBase::RowsAtCompileTime,MatrixBase::ColsAtCompileTime> type; |
|||
}; |
|||
#endif // EIGEN_PARSED_BY_DOXYGEN |
|||
template<typename OtherDerived> |
|||
typename cross_product_return_type<OtherDerived>::type |
|||
cross(const MatrixBase<OtherDerived>& other) const; |
|||
template<typename OtherDerived> |
|||
PlainObject cross3(const MatrixBase<OtherDerived>& other) const; |
|||
PlainObject unitOrthogonal(void) const; |
|||
Matrix<Scalar,3,1> eulerAngles(Index a0, Index a1, Index a2) const; |
|||
|
|||
#if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS |
|||
ScalarMultipleReturnType operator*(const UniformScaling<Scalar>& s) const; |
|||
// put this as separate enum value to work around possible GCC 4.3 bug (?) |
|||
enum { HomogeneousReturnTypeDirection = ColsAtCompileTime==1?Vertical:Horizontal }; |
|||
typedef Homogeneous<Derived, HomogeneousReturnTypeDirection> HomogeneousReturnType; |
|||
HomogeneousReturnType homogeneous() const; |
|||
#endif |
|||
|
|||
enum { |
|||
SizeMinusOne = SizeAtCompileTime==Dynamic ? Dynamic : SizeAtCompileTime-1 |
|||
}; |
|||
typedef Block<const Derived, |
|||
internal::traits<Derived>::ColsAtCompileTime==1 ? SizeMinusOne : 1, |
|||
internal::traits<Derived>::ColsAtCompileTime==1 ? 1 : SizeMinusOne> ConstStartMinusOne; |
|||
typedef CwiseUnaryOp<internal::scalar_quotient1_op<typename internal::traits<Derived>::Scalar>, |
|||
const ConstStartMinusOne > HNormalizedReturnType; |
|||
|
|||
const HNormalizedReturnType hnormalized() const; |
|||
|
|||
////////// Householder module /////////// |
|||
|
|||
void makeHouseholderInPlace(Scalar& tau, RealScalar& beta); |
|||
template<typename EssentialPart> |
|||
void makeHouseholder(EssentialPart& essential, |
|||
Scalar& tau, RealScalar& beta) const; |
|||
template<typename EssentialPart> |
|||
void applyHouseholderOnTheLeft(const EssentialPart& essential, |
|||
const Scalar& tau, |
|||
Scalar* workspace); |
|||
template<typename EssentialPart> |
|||
void applyHouseholderOnTheRight(const EssentialPart& essential, |
|||
const Scalar& tau, |
|||
Scalar* workspace); |
|||
|
|||
///////// Jacobi module ///////// |
|||
|
|||
template<typename OtherScalar> |
|||
void applyOnTheLeft(Index p, Index q, const JacobiRotation<OtherScalar>& j); |
|||
template<typename OtherScalar> |
|||
void applyOnTheRight(Index p, Index q, const JacobiRotation<OtherScalar>& j); |
|||
|
|||
///////// MatrixFunctions module ///////// |
|||
|
|||
typedef typename internal::stem_function<Scalar>::type StemFunction; |
|||
const MatrixExponentialReturnValue<Derived> exp() const; |
|||
const MatrixFunctionReturnValue<Derived> matrixFunction(StemFunction f) const; |
|||
const MatrixFunctionReturnValue<Derived> cosh() const; |
|||
const MatrixFunctionReturnValue<Derived> sinh() const; |
|||
const MatrixFunctionReturnValue<Derived> cos() const; |
|||
const MatrixFunctionReturnValue<Derived> sin() const; |
|||
const MatrixSquareRootReturnValue<Derived> sqrt() const; |
|||
const MatrixLogarithmReturnValue<Derived> log() const; |
|||
|
|||
#ifdef EIGEN2_SUPPORT |
|||
template<typename ProductDerived, typename Lhs, typename Rhs> |
|||
Derived& operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0, |
|||
EvalBeforeAssigningBit>& other); |
|||
|
|||
template<typename ProductDerived, typename Lhs, typename Rhs> |
|||
Derived& operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0, |
|||
EvalBeforeAssigningBit>& other); |
|||
|
|||
/** \deprecated because .lazy() is deprecated |
|||
* Overloaded for cache friendly product evaluation */ |
|||
template<typename OtherDerived> |
|||
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeAssigningBit>& other) |
|||
{ return lazyAssign(other._expression()); } |
|||
|
|||
template<unsigned int Added> |
|||
const Flagged<Derived, Added, 0> marked() const; |
|||
const Flagged<Derived, 0, EvalBeforeAssigningBit> lazy() const; |
|||
|
|||
inline const Cwise<Derived> cwise() const; |
|||
inline Cwise<Derived> cwise(); |
|||
|
|||
VectorBlock<Derived> start(Index size); |
|||
const VectorBlock<const Derived> start(Index size) const; |
|||
VectorBlock<Derived> end(Index size); |
|||
const VectorBlock<const Derived> end(Index size) const; |
|||
template<int Size> VectorBlock<Derived,Size> start(); |
|||
template<int Size> const VectorBlock<const Derived,Size> start() const; |
|||
template<int Size> VectorBlock<Derived,Size> end(); |
|||
template<int Size> const VectorBlock<const Derived,Size> end() const; |
|||
|
|||
Minor<Derived> minor(Index row, Index col); |
|||
const Minor<Derived> minor(Index row, Index col) const; |
|||
#endif |
|||
|
|||
protected: |
|||
MatrixBase() : Base() {} |
|||
|
|||
private: |
|||
explicit MatrixBase(int); |
|||
MatrixBase(int,int); |
|||
template<typename OtherDerived> explicit MatrixBase(const MatrixBase<OtherDerived>&); |
|||
protected: |
|||
// mixing arrays and matrices is not legal |
|||
template<typename OtherDerived> Derived& operator+=(const ArrayBase<OtherDerived>& ) |
|||
{EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;} |
|||
// mixing arrays and matrices is not legal |
|||
template<typename OtherDerived> Derived& operator-=(const ArrayBase<OtherDerived>& ) |
|||
{EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;} |
|||
}; |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_MATRIXBASE_H |
@ -0,0 +1,125 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_NOALIAS_H |
|||
#define EIGEN_NOALIAS_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class NoAlias |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Pseudo expression providing an operator = assuming no aliasing |
|||
* |
|||
* \param ExpressionType the type of the object on which to do the lazy assignment |
|||
* |
|||
* This class represents an expression with special assignment operators |
|||
* assuming no aliasing between the target expression and the source expression. |
|||
* More precisely it alloas to bypass the EvalBeforeAssignBit flag of the source expression. |
|||
* It is the return type of MatrixBase::noalias() |
|||
* and most of the time this is the only way it is used. |
|||
* |
|||
* \sa MatrixBase::noalias() |
|||
*/ |
|||
template<typename ExpressionType, template <typename> class StorageBase> |
|||
class NoAlias |
|||
{ |
|||
typedef typename ExpressionType::Scalar Scalar; |
|||
public: |
|||
NoAlias(ExpressionType& expression) : m_expression(expression) {} |
|||
|
|||
/** Behaves like MatrixBase::lazyAssign(other) |
|||
* \sa MatrixBase::lazyAssign() */ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE ExpressionType& operator=(const StorageBase<OtherDerived>& other) |
|||
{ return internal::assign_selector<ExpressionType,OtherDerived,false>::run(m_expression,other.derived()); } |
|||
|
|||
/** \sa MatrixBase::operator+= */ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE ExpressionType& operator+=(const StorageBase<OtherDerived>& other) |
|||
{ |
|||
typedef SelfCwiseBinaryOp<internal::scalar_sum_op<Scalar>, ExpressionType, OtherDerived> SelfAdder; |
|||
SelfAdder tmp(m_expression); |
|||
typedef typename internal::nested<OtherDerived>::type OtherDerivedNested; |
|||
typedef typename internal::remove_all<OtherDerivedNested>::type _OtherDerivedNested; |
|||
internal::assign_selector<SelfAdder,_OtherDerivedNested,false>::run(tmp,OtherDerivedNested(other.derived())); |
|||
return m_expression; |
|||
} |
|||
|
|||
/** \sa MatrixBase::operator-= */ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE ExpressionType& operator-=(const StorageBase<OtherDerived>& other) |
|||
{ |
|||
typedef SelfCwiseBinaryOp<internal::scalar_difference_op<Scalar>, ExpressionType, OtherDerived> SelfAdder; |
|||
SelfAdder tmp(m_expression); |
|||
typedef typename internal::nested<OtherDerived>::type OtherDerivedNested; |
|||
typedef typename internal::remove_all<OtherDerivedNested>::type _OtherDerivedNested; |
|||
internal::assign_selector<SelfAdder,_OtherDerivedNested,false>::run(tmp,OtherDerivedNested(other.derived())); |
|||
return m_expression; |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
template<typename ProductDerived, typename Lhs, typename Rhs> |
|||
EIGEN_STRONG_INLINE ExpressionType& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other) |
|||
{ other.derived().addTo(m_expression); return m_expression; } |
|||
|
|||
template<typename ProductDerived, typename Lhs, typename Rhs> |
|||
EIGEN_STRONG_INLINE ExpressionType& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other) |
|||
{ other.derived().subTo(m_expression); return m_expression; } |
|||
|
|||
template<typename Lhs, typename Rhs, int NestingFlags> |
|||
EIGEN_STRONG_INLINE ExpressionType& operator+=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other) |
|||
{ return m_expression.derived() += CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); } |
|||
|
|||
template<typename Lhs, typename Rhs, int NestingFlags> |
|||
EIGEN_STRONG_INLINE ExpressionType& operator-=(const CoeffBasedProduct<Lhs,Rhs,NestingFlags>& other) |
|||
{ return m_expression.derived() -= CoeffBasedProduct<Lhs,Rhs,NestByRefBit>(other.lhs(), other.rhs()); } |
|||
#endif |
|||
|
|||
protected: |
|||
ExpressionType& m_expression; |
|||
}; |
|||
|
|||
/** \returns a pseudo expression of \c *this with an operator= assuming |
|||
* no aliasing between \c *this and the source expression. |
|||
* |
|||
* More precisely, noalias() allows to bypass the EvalBeforeAssignBit flag. |
|||
* Currently, even though several expressions may alias, only product |
|||
* expressions have this flag. Therefore, noalias() is only usefull when |
|||
* the source expression contains a matrix product. |
|||
* |
|||
* Here are some examples where noalias is usefull: |
|||
* \code |
|||
* D.noalias() = A * B; |
|||
* D.noalias() += A.transpose() * B; |
|||
* D.noalias() -= 2 * A * B.adjoint(); |
|||
* \endcode |
|||
* |
|||
* On the other hand the following example will lead to a \b wrong result: |
|||
* \code |
|||
* A.noalias() = A * B; |
|||
* \endcode |
|||
* because the result matrix A is also an operand of the matrix product. Therefore, |
|||
* there is no alternative than evaluating A * B in a temporary, that is the default |
|||
* behavior when you write: |
|||
* \code |
|||
* A = A * B; |
|||
* \endcode |
|||
* |
|||
* \sa class NoAlias |
|||
*/ |
|||
template<typename Derived> |
|||
NoAlias<Derived,MatrixBase> MatrixBase<Derived>::noalias() |
|||
{ |
|||
return derived(); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_NOALIAS_H |
@ -0,0 +1,687 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// Copyright (C) 2009-2011 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_PERMUTATIONMATRIX_H |
|||
#define EIGEN_PERMUTATIONMATRIX_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
template<int RowCol,typename IndicesType,typename MatrixType, typename StorageKind> class PermutedImpl; |
|||
|
|||
/** \class PermutationBase |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Base class for permutations |
|||
* |
|||
* \param Derived the derived class |
|||
* |
|||
* This class is the base class for all expressions representing a permutation matrix, |
|||
* internally stored as a vector of integers. |
|||
* The convention followed here is that if \f$ \sigma \f$ is a permutation, the corresponding permutation matrix |
|||
* \f$ P_\sigma \f$ is such that if \f$ (e_1,\ldots,e_p) \f$ is the canonical basis, we have: |
|||
* \f[ P_\sigma(e_i) = e_{\sigma(i)}. \f] |
|||
* This convention ensures that for any two permutations \f$ \sigma, \tau \f$, we have: |
|||
* \f[ P_{\sigma\circ\tau} = P_\sigma P_\tau. \f] |
|||
* |
|||
* Permutation matrices are square and invertible. |
|||
* |
|||
* Notice that in addition to the member functions and operators listed here, there also are non-member |
|||
* operator* to multiply any kind of permutation object with any kind of matrix expression (MatrixBase) |
|||
* on either side. |
|||
* |
|||
* \sa class PermutationMatrix, class PermutationWrapper |
|||
*/ |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename PermutationType, typename MatrixType, int Side, bool Transposed=false> |
|||
struct permut_matrix_product_retval; |
|||
template<typename PermutationType, typename MatrixType, int Side, bool Transposed=false> |
|||
struct permut_sparsematrix_product_retval; |
|||
enum PermPermProduct_t {PermPermProduct}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
template<typename Derived> |
|||
class PermutationBase : public EigenBase<Derived> |
|||
{ |
|||
typedef internal::traits<Derived> Traits; |
|||
typedef EigenBase<Derived> Base; |
|||
public: |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
typedef typename Traits::IndicesType IndicesType; |
|||
enum { |
|||
Flags = Traits::Flags, |
|||
CoeffReadCost = Traits::CoeffReadCost, |
|||
RowsAtCompileTime = Traits::RowsAtCompileTime, |
|||
ColsAtCompileTime = Traits::ColsAtCompileTime, |
|||
MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = Traits::MaxColsAtCompileTime |
|||
}; |
|||
typedef typename Traits::Scalar Scalar; |
|||
typedef typename Traits::Index Index; |
|||
typedef Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,0,MaxRowsAtCompileTime,MaxColsAtCompileTime> |
|||
DenseMatrixType; |
|||
typedef PermutationMatrix<IndicesType::SizeAtCompileTime,IndicesType::MaxSizeAtCompileTime,Index> |
|||
PlainPermutationType; |
|||
using Base::derived; |
|||
#endif |
|||
|
|||
/** Copies the other permutation into *this */ |
|||
template<typename OtherDerived> |
|||
Derived& operator=(const PermutationBase<OtherDerived>& other) |
|||
{ |
|||
indices() = other.indices(); |
|||
return derived(); |
|||
} |
|||
|
|||
/** Assignment from the Transpositions \a tr */ |
|||
template<typename OtherDerived> |
|||
Derived& operator=(const TranspositionsBase<OtherDerived>& tr) |
|||
{ |
|||
setIdentity(tr.size()); |
|||
for(Index k=size()-1; k>=0; --k) |
|||
applyTranspositionOnTheRight(k,tr.coeff(k)); |
|||
return derived(); |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** This is a special case of the templated operator=. Its purpose is to |
|||
* prevent a default operator= from hiding the templated operator=. |
|||
*/ |
|||
Derived& operator=(const PermutationBase& other) |
|||
{ |
|||
indices() = other.indices(); |
|||
return derived(); |
|||
} |
|||
#endif |
|||
|
|||
/** \returns the number of rows */ |
|||
inline Index rows() const { return indices().size(); } |
|||
|
|||
/** \returns the number of columns */ |
|||
inline Index cols() const { return indices().size(); } |
|||
|
|||
/** \returns the size of a side of the respective square matrix, i.e., the number of indices */ |
|||
inline Index size() const { return indices().size(); } |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
template<typename DenseDerived> |
|||
void evalTo(MatrixBase<DenseDerived>& other) const |
|||
{ |
|||
other.setZero(); |
|||
for (int i=0; i<rows();++i) |
|||
other.coeffRef(indices().coeff(i),i) = typename DenseDerived::Scalar(1); |
|||
} |
|||
#endif |
|||
|
|||
/** \returns a Matrix object initialized from this permutation matrix. Notice that it |
|||
* is inefficient to return this Matrix object by value. For efficiency, favor using |
|||
* the Matrix constructor taking EigenBase objects. |
|||
*/ |
|||
DenseMatrixType toDenseMatrix() const |
|||
{ |
|||
return derived(); |
|||
} |
|||
|
|||
/** const version of indices(). */ |
|||
const IndicesType& indices() const { return derived().indices(); } |
|||
/** \returns a reference to the stored array representing the permutation. */ |
|||
IndicesType& indices() { return derived().indices(); } |
|||
|
|||
/** Resizes to given size. |
|||
*/ |
|||
inline void resize(Index size) |
|||
{ |
|||
indices().resize(size); |
|||
} |
|||
|
|||
/** Sets *this to be the identity permutation matrix */ |
|||
void setIdentity() |
|||
{ |
|||
for(Index i = 0; i < size(); ++i) |
|||
indices().coeffRef(i) = i; |
|||
} |
|||
|
|||
/** Sets *this to be the identity permutation matrix of given size. |
|||
*/ |
|||
void setIdentity(Index size) |
|||
{ |
|||
resize(size); |
|||
setIdentity(); |
|||
} |
|||
|
|||
/** Multiplies *this by the transposition \f$(ij)\f$ on the left. |
|||
* |
|||
* \returns a reference to *this. |
|||
* |
|||
* \warning This is much slower than applyTranspositionOnTheRight(int,int): |
|||
* this has linear complexity and requires a lot of branching. |
|||
* |
|||
* \sa applyTranspositionOnTheRight(int,int) |
|||
*/ |
|||
Derived& applyTranspositionOnTheLeft(Index i, Index j) |
|||
{ |
|||
eigen_assert(i>=0 && j>=0 && i<size() && j<size()); |
|||
for(Index k = 0; k < size(); ++k) |
|||
{ |
|||
if(indices().coeff(k) == i) indices().coeffRef(k) = j; |
|||
else if(indices().coeff(k) == j) indices().coeffRef(k) = i; |
|||
} |
|||
return derived(); |
|||
} |
|||
|
|||
/** Multiplies *this by the transposition \f$(ij)\f$ on the right. |
|||
* |
|||
* \returns a reference to *this. |
|||
* |
|||
* This is a fast operation, it only consists in swapping two indices. |
|||
* |
|||
* \sa applyTranspositionOnTheLeft(int,int) |
|||
*/ |
|||
Derived& applyTranspositionOnTheRight(Index i, Index j) |
|||
{ |
|||
eigen_assert(i>=0 && j>=0 && i<size() && j<size()); |
|||
std::swap(indices().coeffRef(i), indices().coeffRef(j)); |
|||
return derived(); |
|||
} |
|||
|
|||
/** \returns the inverse permutation matrix. |
|||
* |
|||
* \note \note_try_to_help_rvo |
|||
*/ |
|||
inline Transpose<PermutationBase> inverse() const |
|||
{ return derived(); } |
|||
/** \returns the tranpose permutation matrix. |
|||
* |
|||
* \note \note_try_to_help_rvo |
|||
*/ |
|||
inline Transpose<PermutationBase> transpose() const |
|||
{ return derived(); } |
|||
|
|||
/**** multiplication helpers to hopefully get RVO ****/ |
|||
|
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
protected: |
|||
template<typename OtherDerived> |
|||
void assignTranspose(const PermutationBase<OtherDerived>& other) |
|||
{ |
|||
for (int i=0; i<rows();++i) indices().coeffRef(other.indices().coeff(i)) = i; |
|||
} |
|||
template<typename Lhs,typename Rhs> |
|||
void assignProduct(const Lhs& lhs, const Rhs& rhs) |
|||
{ |
|||
eigen_assert(lhs.cols() == rhs.rows()); |
|||
for (int i=0; i<rows();++i) indices().coeffRef(i) = lhs.indices().coeff(rhs.indices().coeff(i)); |
|||
} |
|||
#endif |
|||
|
|||
public: |
|||
|
|||
/** \returns the product permutation matrix. |
|||
* |
|||
* \note \note_try_to_help_rvo |
|||
*/ |
|||
template<typename Other> |
|||
inline PlainPermutationType operator*(const PermutationBase<Other>& other) const |
|||
{ return PlainPermutationType(internal::PermPermProduct, derived(), other.derived()); } |
|||
|
|||
/** \returns the product of a permutation with another inverse permutation. |
|||
* |
|||
* \note \note_try_to_help_rvo |
|||
*/ |
|||
template<typename Other> |
|||
inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other) const |
|||
{ return PlainPermutationType(internal::PermPermProduct, *this, other.eval()); } |
|||
|
|||
/** \returns the product of an inverse permutation with another permutation. |
|||
* |
|||
* \note \note_try_to_help_rvo |
|||
*/ |
|||
template<typename Other> friend |
|||
inline PlainPermutationType operator*(const Transpose<PermutationBase<Other> >& other, const PermutationBase& perm) |
|||
{ return PlainPermutationType(internal::PermPermProduct, other.eval(), perm); } |
|||
|
|||
protected: |
|||
|
|||
}; |
|||
|
|||
/** \class PermutationMatrix |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Permutation matrix |
|||
* |
|||
* \param SizeAtCompileTime the number of rows/cols, or Dynamic |
|||
* \param MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic. This optional parameter defaults to SizeAtCompileTime. Most of the time, you should not have to specify it. |
|||
* \param IndexType the interger type of the indices |
|||
* |
|||
* This class represents a permutation matrix, internally stored as a vector of integers. |
|||
* |
|||
* \sa class PermutationBase, class PermutationWrapper, class DiagonalMatrix |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType> |
|||
struct traits<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType> > |
|||
: traits<Matrix<IndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> > |
|||
{ |
|||
typedef IndexType Index; |
|||
typedef Matrix<IndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1> IndicesType; |
|||
}; |
|||
} |
|||
|
|||
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType> |
|||
class PermutationMatrix : public PermutationBase<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType> > |
|||
{ |
|||
typedef PermutationBase<PermutationMatrix> Base; |
|||
typedef internal::traits<PermutationMatrix> Traits; |
|||
public: |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
typedef typename Traits::IndicesType IndicesType; |
|||
#endif |
|||
|
|||
inline PermutationMatrix() |
|||
{} |
|||
|
|||
/** Constructs an uninitialized permutation matrix of given size. |
|||
*/ |
|||
inline PermutationMatrix(int size) : m_indices(size) |
|||
{} |
|||
|
|||
/** Copy constructor. */ |
|||
template<typename OtherDerived> |
|||
inline PermutationMatrix(const PermutationBase<OtherDerived>& other) |
|||
: m_indices(other.indices()) {} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** Standard copy constructor. Defined only to prevent a default copy constructor |
|||
* from hiding the other templated constructor */ |
|||
inline PermutationMatrix(const PermutationMatrix& other) : m_indices(other.indices()) {} |
|||
#endif |
|||
|
|||
/** Generic constructor from expression of the indices. The indices |
|||
* array has the meaning that the permutations sends each integer i to indices[i]. |
|||
* |
|||
* \warning It is your responsibility to check that the indices array that you passes actually |
|||
* describes a permutation, i.e., each value between 0 and n-1 occurs exactly once, where n is the |
|||
* array's size. |
|||
*/ |
|||
template<typename Other> |
|||
explicit inline PermutationMatrix(const MatrixBase<Other>& indices) : m_indices(indices) |
|||
{} |
|||
|
|||
/** Convert the Transpositions \a tr to a permutation matrix */ |
|||
template<typename Other> |
|||
explicit PermutationMatrix(const TranspositionsBase<Other>& tr) |
|||
: m_indices(tr.size()) |
|||
{ |
|||
*this = tr; |
|||
} |
|||
|
|||
/** Copies the other permutation into *this */ |
|||
template<typename Other> |
|||
PermutationMatrix& operator=(const PermutationBase<Other>& other) |
|||
{ |
|||
m_indices = other.indices(); |
|||
return *this; |
|||
} |
|||
|
|||
/** Assignment from the Transpositions \a tr */ |
|||
template<typename Other> |
|||
PermutationMatrix& operator=(const TranspositionsBase<Other>& tr) |
|||
{ |
|||
return Base::operator=(tr.derived()); |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** This is a special case of the templated operator=. Its purpose is to |
|||
* prevent a default operator= from hiding the templated operator=. |
|||
*/ |
|||
PermutationMatrix& operator=(const PermutationMatrix& other) |
|||
{ |
|||
m_indices = other.m_indices; |
|||
return *this; |
|||
} |
|||
#endif |
|||
|
|||
/** const version of indices(). */ |
|||
const IndicesType& indices() const { return m_indices; } |
|||
/** \returns a reference to the stored array representing the permutation. */ |
|||
IndicesType& indices() { return m_indices; } |
|||
|
|||
|
|||
/**** multiplication helpers to hopefully get RVO ****/ |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
template<typename Other> |
|||
PermutationMatrix(const Transpose<PermutationBase<Other> >& other) |
|||
: m_indices(other.nestedPermutation().size()) |
|||
{ |
|||
for (int i=0; i<m_indices.size();++i) m_indices.coeffRef(other.nestedPermutation().indices().coeff(i)) = i; |
|||
} |
|||
template<typename Lhs,typename Rhs> |
|||
PermutationMatrix(internal::PermPermProduct_t, const Lhs& lhs, const Rhs& rhs) |
|||
: m_indices(lhs.indices().size()) |
|||
{ |
|||
Base::assignProduct(lhs,rhs); |
|||
} |
|||
#endif |
|||
|
|||
protected: |
|||
|
|||
IndicesType m_indices; |
|||
}; |
|||
|
|||
|
|||
namespace internal { |
|||
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess> |
|||
struct traits<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> > |
|||
: traits<Matrix<IndexType,SizeAtCompileTime,SizeAtCompileTime,0,MaxSizeAtCompileTime,MaxSizeAtCompileTime> > |
|||
{ |
|||
typedef IndexType Index; |
|||
typedef Map<const Matrix<IndexType, SizeAtCompileTime, 1, 0, MaxSizeAtCompileTime, 1>, _PacketAccess> IndicesType; |
|||
}; |
|||
} |
|||
|
|||
template<int SizeAtCompileTime, int MaxSizeAtCompileTime, typename IndexType, int _PacketAccess> |
|||
class Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> |
|||
: public PermutationBase<Map<PermutationMatrix<SizeAtCompileTime, MaxSizeAtCompileTime, IndexType>,_PacketAccess> > |
|||
{ |
|||
typedef PermutationBase<Map> Base; |
|||
typedef internal::traits<Map> Traits; |
|||
public: |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
typedef typename Traits::IndicesType IndicesType; |
|||
typedef typename IndicesType::Scalar Index; |
|||
#endif |
|||
|
|||
inline Map(const Index* indices) |
|||
: m_indices(indices) |
|||
{} |
|||
|
|||
inline Map(const Index* indices, Index size) |
|||
: m_indices(indices,size) |
|||
{} |
|||
|
|||
/** Copies the other permutation into *this */ |
|||
template<typename Other> |
|||
Map& operator=(const PermutationBase<Other>& other) |
|||
{ return Base::operator=(other.derived()); } |
|||
|
|||
/** Assignment from the Transpositions \a tr */ |
|||
template<typename Other> |
|||
Map& operator=(const TranspositionsBase<Other>& tr) |
|||
{ return Base::operator=(tr.derived()); } |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
/** This is a special case of the templated operator=. Its purpose is to |
|||
* prevent a default operator= from hiding the templated operator=. |
|||
*/ |
|||
Map& operator=(const Map& other) |
|||
{ |
|||
m_indices = other.m_indices; |
|||
return *this; |
|||
} |
|||
#endif |
|||
|
|||
/** const version of indices(). */ |
|||
const IndicesType& indices() const { return m_indices; } |
|||
/** \returns a reference to the stored array representing the permutation. */ |
|||
IndicesType& indices() { return m_indices; } |
|||
|
|||
protected: |
|||
|
|||
IndicesType m_indices; |
|||
}; |
|||
|
|||
/** \class PermutationWrapper |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Class to view a vector of integers as a permutation matrix |
|||
* |
|||
* \param _IndicesType the type of the vector of integer (can be any compatible expression) |
|||
* |
|||
* This class allows to view any vector expression of integers as a permutation matrix. |
|||
* |
|||
* \sa class PermutationBase, class PermutationMatrix |
|||
*/ |
|||
|
|||
struct PermutationStorage {}; |
|||
|
|||
template<typename _IndicesType> class TranspositionsWrapper; |
|||
namespace internal { |
|||
template<typename _IndicesType> |
|||
struct traits<PermutationWrapper<_IndicesType> > |
|||
{ |
|||
typedef PermutationStorage StorageKind; |
|||
typedef typename _IndicesType::Scalar Scalar; |
|||
typedef typename _IndicesType::Scalar Index; |
|||
typedef _IndicesType IndicesType; |
|||
enum { |
|||
RowsAtCompileTime = _IndicesType::SizeAtCompileTime, |
|||
ColsAtCompileTime = _IndicesType::SizeAtCompileTime, |
|||
MaxRowsAtCompileTime = IndicesType::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = IndicesType::MaxColsAtCompileTime, |
|||
Flags = 0, |
|||
CoeffReadCost = _IndicesType::CoeffReadCost |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename _IndicesType> |
|||
class PermutationWrapper : public PermutationBase<PermutationWrapper<_IndicesType> > |
|||
{ |
|||
typedef PermutationBase<PermutationWrapper> Base; |
|||
typedef internal::traits<PermutationWrapper> Traits; |
|||
public: |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
typedef typename Traits::IndicesType IndicesType; |
|||
#endif |
|||
|
|||
inline PermutationWrapper(const IndicesType& indices) |
|||
: m_indices(indices) |
|||
{} |
|||
|
|||
/** const version of indices(). */ |
|||
const typename internal::remove_all<typename IndicesType::Nested>::type& |
|||
indices() const { return m_indices; } |
|||
|
|||
protected: |
|||
|
|||
typename IndicesType::Nested m_indices; |
|||
}; |
|||
|
|||
/** \returns the matrix with the permutation applied to the columns. |
|||
*/ |
|||
template<typename Derived, typename PermutationDerived> |
|||
inline const internal::permut_matrix_product_retval<PermutationDerived, Derived, OnTheRight> |
|||
operator*(const MatrixBase<Derived>& matrix, |
|||
const PermutationBase<PermutationDerived> &permutation) |
|||
{ |
|||
return internal::permut_matrix_product_retval |
|||
<PermutationDerived, Derived, OnTheRight> |
|||
(permutation.derived(), matrix.derived()); |
|||
} |
|||
|
|||
/** \returns the matrix with the permutation applied to the rows. |
|||
*/ |
|||
template<typename Derived, typename PermutationDerived> |
|||
inline const internal::permut_matrix_product_retval |
|||
<PermutationDerived, Derived, OnTheLeft> |
|||
operator*(const PermutationBase<PermutationDerived> &permutation, |
|||
const MatrixBase<Derived>& matrix) |
|||
{ |
|||
return internal::permut_matrix_product_retval |
|||
<PermutationDerived, Derived, OnTheLeft> |
|||
(permutation.derived(), matrix.derived()); |
|||
} |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename PermutationType, typename MatrixType, int Side, bool Transposed> |
|||
struct traits<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> > |
|||
{ |
|||
typedef typename MatrixType::PlainObject ReturnType; |
|||
}; |
|||
|
|||
template<typename PermutationType, typename MatrixType, int Side, bool Transposed> |
|||
struct permut_matrix_product_retval |
|||
: public ReturnByValue<permut_matrix_product_retval<PermutationType, MatrixType, Side, Transposed> > |
|||
{ |
|||
typedef typename remove_all<typename MatrixType::Nested>::type MatrixTypeNestedCleaned; |
|||
|
|||
permut_matrix_product_retval(const PermutationType& perm, const MatrixType& matrix) |
|||
: m_permutation(perm), m_matrix(matrix) |
|||
{} |
|||
|
|||
inline int rows() const { return m_matrix.rows(); } |
|||
inline int cols() const { return m_matrix.cols(); } |
|||
|
|||
template<typename Dest> inline void evalTo(Dest& dst) const |
|||
{ |
|||
const int n = Side==OnTheLeft ? rows() : cols(); |
|||
|
|||
if(is_same<MatrixTypeNestedCleaned,Dest>::value && extract_data(dst) == extract_data(m_matrix)) |
|||
{ |
|||
// apply the permutation inplace |
|||
Matrix<bool,PermutationType::RowsAtCompileTime,1,0,PermutationType::MaxRowsAtCompileTime> mask(m_permutation.size()); |
|||
mask.fill(false); |
|||
int r = 0; |
|||
while(r < m_permutation.size()) |
|||
{ |
|||
// search for the next seed |
|||
while(r<m_permutation.size() && mask[r]) r++; |
|||
if(r>=m_permutation.size()) |
|||
break; |
|||
// we got one, let's follow it until we are back to the seed |
|||
int k0 = r++; |
|||
int kPrev = k0; |
|||
mask.coeffRef(k0) = true; |
|||
for(int k=m_permutation.indices().coeff(k0); k!=k0; k=m_permutation.indices().coeff(k)) |
|||
{ |
|||
Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime>(dst, k) |
|||
.swap(Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime> |
|||
(dst,((Side==OnTheLeft) ^ Transposed) ? k0 : kPrev)); |
|||
|
|||
mask.coeffRef(k) = true; |
|||
kPrev = k; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for(int i = 0; i < n; ++i) |
|||
{ |
|||
Block<Dest, Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, Side==OnTheRight ? 1 : Dest::ColsAtCompileTime> |
|||
(dst, ((Side==OnTheLeft) ^ Transposed) ? m_permutation.indices().coeff(i) : i) |
|||
|
|||
= |
|||
|
|||
Block<const MatrixTypeNestedCleaned,Side==OnTheLeft ? 1 : MatrixType::RowsAtCompileTime,Side==OnTheRight ? 1 : MatrixType::ColsAtCompileTime> |
|||
(m_matrix, ((Side==OnTheRight) ^ Transposed) ? m_permutation.indices().coeff(i) : i); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected: |
|||
const PermutationType& m_permutation; |
|||
typename MatrixType::Nested m_matrix; |
|||
}; |
|||
|
|||
/* Template partial specialization for transposed/inverse permutations */ |
|||
|
|||
template<typename Derived> |
|||
struct traits<Transpose<PermutationBase<Derived> > > |
|||
: traits<Derived> |
|||
{}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
template<typename Derived> |
|||
class Transpose<PermutationBase<Derived> > |
|||
: public EigenBase<Transpose<PermutationBase<Derived> > > |
|||
{ |
|||
typedef Derived PermutationType; |
|||
typedef typename PermutationType::IndicesType IndicesType; |
|||
typedef typename PermutationType::PlainPermutationType PlainPermutationType; |
|||
public: |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
typedef internal::traits<PermutationType> Traits; |
|||
typedef typename Derived::DenseMatrixType DenseMatrixType; |
|||
enum { |
|||
Flags = Traits::Flags, |
|||
CoeffReadCost = Traits::CoeffReadCost, |
|||
RowsAtCompileTime = Traits::RowsAtCompileTime, |
|||
ColsAtCompileTime = Traits::ColsAtCompileTime, |
|||
MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = Traits::MaxColsAtCompileTime |
|||
}; |
|||
typedef typename Traits::Scalar Scalar; |
|||
#endif |
|||
|
|||
Transpose(const PermutationType& p) : m_permutation(p) {} |
|||
|
|||
inline int rows() const { return m_permutation.rows(); } |
|||
inline int cols() const { return m_permutation.cols(); } |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
template<typename DenseDerived> |
|||
void evalTo(MatrixBase<DenseDerived>& other) const |
|||
{ |
|||
other.setZero(); |
|||
for (int i=0; i<rows();++i) |
|||
other.coeffRef(i, m_permutation.indices().coeff(i)) = typename DenseDerived::Scalar(1); |
|||
} |
|||
#endif |
|||
|
|||
/** \return the equivalent permutation matrix */ |
|||
PlainPermutationType eval() const { return *this; } |
|||
|
|||
DenseMatrixType toDenseMatrix() const { return *this; } |
|||
|
|||
/** \returns the matrix with the inverse permutation applied to the columns. |
|||
*/ |
|||
template<typename OtherDerived> friend |
|||
inline const internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheRight, true> |
|||
operator*(const MatrixBase<OtherDerived>& matrix, const Transpose& trPerm) |
|||
{ |
|||
return internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheRight, true>(trPerm.m_permutation, matrix.derived()); |
|||
} |
|||
|
|||
/** \returns the matrix with the inverse permutation applied to the rows. |
|||
*/ |
|||
template<typename OtherDerived> |
|||
inline const internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheLeft, true> |
|||
operator*(const MatrixBase<OtherDerived>& matrix) const |
|||
{ |
|||
return internal::permut_matrix_product_retval<PermutationType, OtherDerived, OnTheLeft, true>(m_permutation, matrix.derived()); |
|||
} |
|||
|
|||
const PermutationType& nestedPermutation() const { return m_permutation; } |
|||
|
|||
protected: |
|||
const PermutationType& m_permutation; |
|||
}; |
|||
|
|||
template<typename Derived> |
|||
const PermutationWrapper<const Derived> MatrixBase<Derived>::asPermutation() const |
|||
{ |
|||
return derived(); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_PERMUTATIONMATRIX_H |
@ -0,0 +1,767 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com> |
|||
// |
|||
// This Source Code Form is subject to the terms of the Mozilla |
|||
// Public License v. 2.0. If a copy of the MPL was not distributed |
|||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|||
|
|||
#ifndef EIGEN_DENSESTORAGEBASE_H |
|||
#define EIGEN_DENSESTORAGEBASE_H |
|||
|
|||
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO |
|||
# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0); |
|||
#else |
|||
# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
#endif |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename Index> |
|||
EIGEN_ALWAYS_INLINE void check_rows_cols_for_overflow(Index rows, Index cols) |
|||
{ |
|||
// http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242 |
|||
// we assume Index is signed |
|||
Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed |
|||
bool error = (rows < 0 || cols < 0) ? true |
|||
: (rows == 0 || cols == 0) ? false |
|||
: (rows > max_index / cols); |
|||
if (error) |
|||
throw_std_bad_alloc(); |
|||
} |
|||
|
|||
template <typename Derived, typename OtherDerived = Derived, bool IsVector = bool(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl; |
|||
|
|||
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/** \class PlainObjectBase |
|||
* \brief %Dense storage base class for matrices and arrays. |
|||
* |
|||
* This class can be extended with the help of the plugin mechanism described on the page |
|||
* \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN. |
|||
* |
|||
* \sa \ref TopicClassHierarchy |
|||
*/ |
|||
#ifdef EIGEN_PARSED_BY_DOXYGEN |
|||
namespace internal { |
|||
|
|||
// this is a warkaround to doxygen not being able to understand the inheritence logic |
|||
// when it is hidden by the dense_xpr_base helper struct. |
|||
template<typename Derived> struct dense_xpr_base_dispatcher_for_doxygen;// : public MatrixBase<Derived> {}; |
|||
/** This class is just a workaround for Doxygen and it does not not actually exist. */ |
|||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> |
|||
struct dense_xpr_base_dispatcher_for_doxygen<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > |
|||
: public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {}; |
|||
/** This class is just a workaround for Doxygen and it does not not actually exist. */ |
|||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> |
|||
struct dense_xpr_base_dispatcher_for_doxygen<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > |
|||
: public ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {}; |
|||
|
|||
} // namespace internal |
|||
|
|||
template<typename Derived> |
|||
class PlainObjectBase : public internal::dense_xpr_base_dispatcher_for_doxygen<Derived> |
|||
#else |
|||
template<typename Derived> |
|||
class PlainObjectBase : public internal::dense_xpr_base<Derived>::type |
|||
#endif |
|||
{ |
|||
public: |
|||
enum { Options = internal::traits<Derived>::Options }; |
|||
typedef typename internal::dense_xpr_base<Derived>::type Base; |
|||
|
|||
typedef typename internal::traits<Derived>::StorageKind StorageKind; |
|||
typedef typename internal::traits<Derived>::Index Index; |
|||
typedef typename internal::traits<Derived>::Scalar Scalar; |
|||
typedef typename internal::packet_traits<Scalar>::type PacketScalar; |
|||
typedef typename NumTraits<Scalar>::Real RealScalar; |
|||
typedef Derived DenseType; |
|||
|
|||
using Base::RowsAtCompileTime; |
|||
using Base::ColsAtCompileTime; |
|||
using Base::SizeAtCompileTime; |
|||
using Base::MaxRowsAtCompileTime; |
|||
using Base::MaxColsAtCompileTime; |
|||
using Base::MaxSizeAtCompileTime; |
|||
using Base::IsVectorAtCompileTime; |
|||
using Base::Flags; |
|||
|
|||
template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map; |
|||
friend class Eigen::Map<Derived, Unaligned>; |
|||
typedef Eigen::Map<Derived, Unaligned> MapType; |
|||
friend class Eigen::Map<const Derived, Unaligned>; |
|||
typedef const Eigen::Map<const Derived, Unaligned> ConstMapType; |
|||
friend class Eigen::Map<Derived, Aligned>; |
|||
typedef Eigen::Map<Derived, Aligned> AlignedMapType; |
|||
friend class Eigen::Map<const Derived, Aligned>; |
|||
typedef const Eigen::Map<const Derived, Aligned> ConstAlignedMapType; |
|||
template<typename StrideType> struct StridedMapType { typedef Eigen::Map<Derived, Unaligned, StrideType> type; }; |
|||
template<typename StrideType> struct StridedConstMapType { typedef Eigen::Map<const Derived, Unaligned, StrideType> type; }; |
|||
template<typename StrideType> struct StridedAlignedMapType { typedef Eigen::Map<Derived, Aligned, StrideType> type; }; |
|||
template<typename StrideType> struct StridedConstAlignedMapType { typedef Eigen::Map<const Derived, Aligned, StrideType> type; }; |
|||
|
|||
protected: |
|||
DenseStorage<Scalar, Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime, Base::ColsAtCompileTime, Options> m_storage; |
|||
|
|||
public: |
|||
enum { NeedsToAlign = SizeAtCompileTime != Dynamic && (internal::traits<Derived>::Flags & AlignedBit) != 0 }; |
|||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) |
|||
|
|||
Base& base() { return *static_cast<Base*>(this); } |
|||
const Base& base() const { return *static_cast<const Base*>(this); } |
|||
|
|||
EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); } |
|||
EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); } |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const |
|||
{ |
|||
if(Flags & RowMajorBit) |
|||
return m_storage.data()[col + row * m_storage.cols()]; |
|||
else // column-major |
|||
return m_storage.data()[row + col * m_storage.rows()]; |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const |
|||
{ |
|||
return m_storage.data()[index]; |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) |
|||
{ |
|||
if(Flags & RowMajorBit) |
|||
return m_storage.data()[col + row * m_storage.cols()]; |
|||
else // column-major |
|||
return m_storage.data()[row + col * m_storage.rows()]; |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) |
|||
{ |
|||
return m_storage.data()[index]; |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar& coeffRef(Index row, Index col) const |
|||
{ |
|||
if(Flags & RowMajorBit) |
|||
return m_storage.data()[col + row * m_storage.cols()]; |
|||
else // column-major |
|||
return m_storage.data()[row + col * m_storage.rows()]; |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const |
|||
{ |
|||
return m_storage.data()[index]; |
|||
} |
|||
|
|||
/** \internal */ |
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
return internal::ploadt<PacketScalar, LoadMode> |
|||
(m_storage.data() + (Flags & RowMajorBit |
|||
? col + row * m_storage.cols() |
|||
: row + col * m_storage.rows())); |
|||
} |
|||
|
|||
/** \internal */ |
|||
template<int LoadMode> |
|||
EIGEN_STRONG_INLINE PacketScalar packet(Index index) const |
|||
{ |
|||
return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index); |
|||
} |
|||
|
|||
/** \internal */ |
|||
template<int StoreMode> |
|||
EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketScalar& x) |
|||
{ |
|||
internal::pstoret<Scalar, PacketScalar, StoreMode> |
|||
(m_storage.data() + (Flags & RowMajorBit |
|||
? col + row * m_storage.cols() |
|||
: row + col * m_storage.rows()), x); |
|||
} |
|||
|
|||
/** \internal */ |
|||
template<int StoreMode> |
|||
EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& x) |
|||
{ |
|||
internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x); |
|||
} |
|||
|
|||
/** \returns a const pointer to the data array of this matrix */ |
|||
EIGEN_STRONG_INLINE const Scalar *data() const |
|||
{ return m_storage.data(); } |
|||
|
|||
/** \returns a pointer to the data array of this matrix */ |
|||
EIGEN_STRONG_INLINE Scalar *data() |
|||
{ return m_storage.data(); } |
|||
|
|||
/** Resizes \c *this to a \a rows x \a cols matrix. |
|||
* |
|||
* This method is intended for dynamic-size matrices, although it is legal to call it on any |
|||
* matrix as long as fixed dimensions are left unchanged. If you only want to change the number |
|||
* of rows and/or of columns, you can use resize(NoChange_t, Index), resize(Index, NoChange_t). |
|||
* |
|||
* If the current number of coefficients of \c *this exactly matches the |
|||
* product \a rows * \a cols, then no memory allocation is performed and |
|||
* the current values are left unchanged. In all other cases, including |
|||
* shrinking, the data is reallocated and all previous values are lost. |
|||
* |
|||
* Example: \include Matrix_resize_int_int.cpp |
|||
* Output: \verbinclude Matrix_resize_int_int.out |
|||
* |
|||
* \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t) |
|||
*/ |
|||
EIGEN_STRONG_INLINE void resize(Index rows, Index cols) |
|||
{ |
|||
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO |
|||
internal::check_rows_cols_for_overflow(rows, cols); |
|||
Index size = rows*cols; |
|||
bool size_changed = size != this->size(); |
|||
m_storage.resize(size, rows, cols); |
|||
if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
#else |
|||
internal::check_rows_cols_for_overflow(rows, cols); |
|||
m_storage.resize(rows*cols, rows, cols); |
|||
#endif |
|||
} |
|||
|
|||
/** Resizes \c *this to a vector of length \a size |
|||
* |
|||
* \only_for_vectors. This method does not work for |
|||
* partially dynamic matrices when the static dimension is anything other |
|||
* than 1. For example it will not work with Matrix<double, 2, Dynamic>. |
|||
* |
|||
* Example: \include Matrix_resize_int.cpp |
|||
* Output: \verbinclude Matrix_resize_int.out |
|||
* |
|||
* \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t) |
|||
*/ |
|||
inline void resize(Index size) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase) |
|||
eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size); |
|||
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO |
|||
bool size_changed = size != this->size(); |
|||
#endif |
|||
if(RowsAtCompileTime == 1) |
|||
m_storage.resize(size, 1, size); |
|||
else |
|||
m_storage.resize(size, size, 1); |
|||
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO |
|||
if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
#endif |
|||
} |
|||
|
|||
/** Resizes the matrix, changing only the number of columns. For the parameter of type NoChange_t, just pass the special value \c NoChange |
|||
* as in the example below. |
|||
* |
|||
* Example: \include Matrix_resize_NoChange_int.cpp |
|||
* Output: \verbinclude Matrix_resize_NoChange_int.out |
|||
* |
|||
* \sa resize(Index,Index) |
|||
*/ |
|||
inline void resize(NoChange_t, Index cols) |
|||
{ |
|||
resize(rows(), cols); |
|||
} |
|||
|
|||
/** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special value \c NoChange |
|||
* as in the example below. |
|||
* |
|||
* Example: \include Matrix_resize_int_NoChange.cpp |
|||
* Output: \verbinclude Matrix_resize_int_NoChange.out |
|||
* |
|||
* \sa resize(Index,Index) |
|||
*/ |
|||
inline void resize(Index rows, NoChange_t) |
|||
{ |
|||
resize(rows, cols()); |
|||
} |
|||
|
|||
/** Resizes \c *this to have the same dimensions as \a other. |
|||
* Takes care of doing all the checking that's needed. |
|||
* |
|||
* Note that copying a row-vector into a vector (and conversely) is allowed. |
|||
* The resizing, if any, is then done in the appropriate way so that row-vectors |
|||
* remain row-vectors and vectors remain vectors. |
|||
*/ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other) |
|||
{ |
|||
const OtherDerived& other = _other.derived(); |
|||
internal::check_rows_cols_for_overflow(other.rows(), other.cols()); |
|||
const Index othersize = other.rows()*other.cols(); |
|||
if(RowsAtCompileTime == 1) |
|||
{ |
|||
eigen_assert(other.rows() == 1 || other.cols() == 1); |
|||
resize(1, othersize); |
|||
} |
|||
else if(ColsAtCompileTime == 1) |
|||
{ |
|||
eigen_assert(other.rows() == 1 || other.cols() == 1); |
|||
resize(othersize, 1); |
|||
} |
|||
else resize(other.rows(), other.cols()); |
|||
} |
|||
|
|||
/** Resizes the matrix to \a rows x \a cols while leaving old values untouched. |
|||
* |
|||
* The method is intended for matrices of dynamic size. If you only want to change the number |
|||
* of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or |
|||
* conservativeResize(Index, NoChange_t). |
|||
* |
|||
* Matrices are resized relative to the top-left element. In case values need to be |
|||
* appended to the matrix they will be uninitialized. |
|||
*/ |
|||
EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols) |
|||
{ |
|||
internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols); |
|||
} |
|||
|
|||
/** Resizes the matrix to \a rows x \a cols while leaving old values untouched. |
|||
* |
|||
* As opposed to conservativeResize(Index rows, Index cols), this version leaves |
|||
* the number of columns unchanged. |
|||
* |
|||
* In case the matrix is growing, new rows will be uninitialized. |
|||
*/ |
|||
EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t) |
|||
{ |
|||
// Note: see the comment in conservativeResize(Index,Index) |
|||
conservativeResize(rows, cols()); |
|||
} |
|||
|
|||
/** Resizes the matrix to \a rows x \a cols while leaving old values untouched. |
|||
* |
|||
* As opposed to conservativeResize(Index rows, Index cols), this version leaves |
|||
* the number of rows unchanged. |
|||
* |
|||
* In case the matrix is growing, new columns will be uninitialized. |
|||
*/ |
|||
EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols) |
|||
{ |
|||
// Note: see the comment in conservativeResize(Index,Index) |
|||
conservativeResize(rows(), cols); |
|||
} |
|||
|
|||
/** Resizes the vector to \a size while retaining old values. |
|||
* |
|||
* \only_for_vectors. This method does not work for |
|||
* partially dynamic matrices when the static dimension is anything other |
|||
* than 1. For example it will not work with Matrix<double, 2, Dynamic>. |
|||
* |
|||
* When values are appended, they will be uninitialized. |
|||
*/ |
|||
EIGEN_STRONG_INLINE void conservativeResize(Index size) |
|||
{ |
|||
internal::conservative_resize_like_impl<Derived>::run(*this, size); |
|||
} |
|||
|
|||
/** Resizes the matrix to \a rows x \a cols of \c other, while leaving old values untouched. |
|||
* |
|||
* The method is intended for matrices of dynamic size. If you only want to change the number |
|||
* of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or |
|||
* conservativeResize(Index, NoChange_t). |
|||
* |
|||
* Matrices are resized relative to the top-left element. In case values need to be |
|||
* appended to the matrix they will copied from \c other. |
|||
*/ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other) |
|||
{ |
|||
internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other); |
|||
} |
|||
|
|||
/** This is a special case of the templated operator=. Its purpose is to |
|||
* prevent a default operator= from hiding the templated operator=. |
|||
*/ |
|||
EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other) |
|||
{ |
|||
return _set(other); |
|||
} |
|||
|
|||
/** \sa MatrixBase::lazyAssign() */ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other) |
|||
{ |
|||
_resize_to_match(other); |
|||
return Base::lazyAssign(other.derived()); |
|||
} |
|||
|
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func) |
|||
{ |
|||
resize(func.rows(), func.cols()); |
|||
return Base::operator=(func); |
|||
} |
|||
|
|||
EIGEN_STRONG_INLINE explicit PlainObjectBase() : m_storage() |
|||
{ |
|||
// _check_template_params(); |
|||
// EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
} |
|||
|
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
// FIXME is it still needed ? |
|||
/** \internal */ |
|||
PlainObjectBase(internal::constructor_without_unaligned_array_assert) |
|||
: m_storage(internal::constructor_without_unaligned_array_assert()) |
|||
{ |
|||
// _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
} |
|||
#endif |
|||
|
|||
EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols) |
|||
: m_storage(size, rows, cols) |
|||
{ |
|||
// _check_template_params(); |
|||
// EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
} |
|||
|
|||
/** \copydoc MatrixBase::operator=(const EigenBase<OtherDerived>&) |
|||
*/ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other) |
|||
{ |
|||
_resize_to_match(other); |
|||
Base::operator=(other.derived()); |
|||
return this->derived(); |
|||
} |
|||
|
|||
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other) |
|||
: m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols()) |
|||
{ |
|||
_check_template_params(); |
|||
internal::check_rows_cols_for_overflow(other.derived().rows(), other.derived().cols()); |
|||
Base::operator=(other.derived()); |
|||
} |
|||
|
|||
/** \name Map |
|||
* These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects, |
|||
* while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned |
|||
* \a data pointers. |
|||
* |
|||
* \see class Map |
|||
*/ |
|||
//@{ |
|||
static inline ConstMapType Map(const Scalar* data) |
|||
{ return ConstMapType(data); } |
|||
static inline MapType Map(Scalar* data) |
|||
{ return MapType(data); } |
|||
static inline ConstMapType Map(const Scalar* data, Index size) |
|||
{ return ConstMapType(data, size); } |
|||
static inline MapType Map(Scalar* data, Index size) |
|||
{ return MapType(data, size); } |
|||
static inline ConstMapType Map(const Scalar* data, Index rows, Index cols) |
|||
{ return ConstMapType(data, rows, cols); } |
|||
static inline MapType Map(Scalar* data, Index rows, Index cols) |
|||
{ return MapType(data, rows, cols); } |
|||
|
|||
static inline ConstAlignedMapType MapAligned(const Scalar* data) |
|||
{ return ConstAlignedMapType(data); } |
|||
static inline AlignedMapType MapAligned(Scalar* data) |
|||
{ return AlignedMapType(data); } |
|||
static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size) |
|||
{ return ConstAlignedMapType(data, size); } |
|||
static inline AlignedMapType MapAligned(Scalar* data, Index size) |
|||
{ return AlignedMapType(data, size); } |
|||
static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) |
|||
{ return ConstAlignedMapType(data, rows, cols); } |
|||
static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) |
|||
{ return AlignedMapType(data, rows, cols); } |
|||
|
|||
template<int Outer, int Inner> |
|||
static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedMapType<Stride<Outer, Inner> >::type(data, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index size, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, size, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index size, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedMapType<Stride<Outer, Inner> >::type(data, size, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } |
|||
|
|||
template<int Outer, int Inner> |
|||
static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index size, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index size, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } |
|||
template<int Outer, int Inner> |
|||
static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) |
|||
{ return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); } |
|||
//@} |
|||
|
|||
using Base::setConstant; |
|||
Derived& setConstant(Index size, const Scalar& value); |
|||
Derived& setConstant(Index rows, Index cols, const Scalar& value); |
|||
|
|||
using Base::setZero; |
|||
Derived& setZero(Index size); |
|||
Derived& setZero(Index rows, Index cols); |
|||
|
|||
using Base::setOnes; |
|||
Derived& setOnes(Index size); |
|||
Derived& setOnes(Index rows, Index cols); |
|||
|
|||
using Base::setRandom; |
|||
Derived& setRandom(Index size); |
|||
Derived& setRandom(Index rows, Index cols); |
|||
|
|||
#ifdef EIGEN_PLAINOBJECTBASE_PLUGIN |
|||
#include EIGEN_PLAINOBJECTBASE_PLUGIN |
|||
#endif |
|||
|
|||
protected: |
|||
/** \internal Resizes *this in preparation for assigning \a other to it. |
|||
* Takes care of doing all the checking that's needed. |
|||
* |
|||
* Note that copying a row-vector into a vector (and conversely) is allowed. |
|||
* The resizing, if any, is then done in the appropriate way so that row-vectors |
|||
* remain row-vectors and vectors remain vectors. |
|||
*/ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other) |
|||
{ |
|||
#ifdef EIGEN_NO_AUTOMATIC_RESIZING |
|||
eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size()) |
|||
: (rows() == other.rows() && cols() == other.cols()))) |
|||
&& "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined"); |
|||
#else |
|||
resizeLike(other); |
|||
#endif |
|||
} |
|||
|
|||
/** |
|||
* \brief Copies the value of the expression \a other into \c *this with automatic resizing. |
|||
* |
|||
* *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized), |
|||
* it will be initialized. |
|||
* |
|||
* Note that copying a row-vector into a vector (and conversely) is allowed. |
|||
* The resizing, if any, is then done in the appropriate way so that row-vectors |
|||
* remain row-vectors and vectors remain vectors. |
|||
* |
|||
* \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias() |
|||
* |
|||
* \internal |
|||
*/ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other) |
|||
{ |
|||
_set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type()); |
|||
return this->derived(); |
|||
} |
|||
|
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); } |
|||
|
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); } |
|||
|
|||
/** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which |
|||
* is the case when creating a new matrix) so one can enforce lazy evaluation. |
|||
* |
|||
* \sa operator=(const MatrixBase<OtherDerived>&), _set() |
|||
*/ |
|||
template<typename OtherDerived> |
|||
EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other) |
|||
{ |
|||
// I don't think we need this resize call since the lazyAssign will anyways resize |
|||
// and lazyAssign will be called by the assign selector. |
|||
//_resize_to_match(other); |
|||
// the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because |
|||
// it wouldn't allow to copy a row-vector into a column-vector. |
|||
return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived()); |
|||
} |
|||
|
|||
template<typename T0, typename T1> |
|||
EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0) |
|||
{ |
|||
EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) && |
|||
bool(NumTraits<T1>::IsInteger), |
|||
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) |
|||
eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) |
|||
&& cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)); |
|||
internal::check_rows_cols_for_overflow(rows, cols); |
|||
m_storage.resize(rows*cols,rows,cols); |
|||
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED |
|||
} |
|||
template<typename T0, typename T1> |
|||
EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0) |
|||
{ |
|||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2) |
|||
m_storage.data()[0] = x; |
|||
m_storage.data()[1] = y; |
|||
} |
|||
|
|||
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> |
|||
friend struct internal::matrix_swap_impl; |
|||
|
|||
/** \internal generic implementation of swap for dense storage since for dynamic-sized matrices of same type it is enough to swap the |
|||
* data pointers. |
|||
*/ |
|||
template<typename OtherDerived> |
|||
void _swap(DenseBase<OtherDerived> const & other) |
|||
{ |
|||
enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic }; |
|||
internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.const_cast_derived()); |
|||
} |
|||
|
|||
public: |
|||
#ifndef EIGEN_PARSED_BY_DOXYGEN |
|||
static EIGEN_STRONG_INLINE void _check_template_params() |
|||
{ |
|||
EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) |
|||
&& EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0) |
|||
&& ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0)) |
|||
&& ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0)) |
|||
&& ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0)) |
|||
&& ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0)) |
|||
&& (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic) |
|||
&& (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic) |
|||
&& (Options & (DontAlign|RowMajor)) == Options), |
|||
INVALID_MATRIX_TEMPLATE_PARAMETERS) |
|||
} |
|||
#endif |
|||
|
|||
private: |
|||
enum { ThisConstantIsPrivateInPlainObjectBase }; |
|||
}; |
|||
|
|||
template <typename Derived, typename OtherDerived, bool IsVector> |
|||
struct internal::conservative_resize_like_impl |
|||
{ |
|||
typedef typename Derived::Index Index; |
|||
static void run(DenseBase<Derived>& _this, Index rows, Index cols) |
|||
{ |
|||
if (_this.rows() == rows && _this.cols() == cols) return; |
|||
EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) |
|||
|
|||
if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows |
|||
(!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns |
|||
{ |
|||
internal::check_rows_cols_for_overflow(rows, cols); |
|||
_this.derived().m_storage.conservativeResize(rows*cols,rows,cols); |
|||
} |
|||
else |
|||
{ |
|||
// The storage order does not allow us to use reallocation. |
|||
typename Derived::PlainObject tmp(rows,cols); |
|||
const Index common_rows = (std::min)(rows, _this.rows()); |
|||
const Index common_cols = (std::min)(cols, _this.cols()); |
|||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols); |
|||
_this.derived().swap(tmp); |
|||
} |
|||
} |
|||
|
|||
static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) |
|||
{ |
|||
if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; |
|||
|
|||
// Note: Here is space for improvement. Basically, for conservativeResize(Index,Index), |
|||
// neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the |
|||
// dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or |
|||
// conservativeResize(NoChange_t, Index cols). For these methods new static asserts like |
|||
// EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good. |
|||
EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived) |
|||
EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived) |
|||
|
|||
if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows |
|||
(!Derived::IsRowMajor && _this.rows() == other.rows()) ) // column-major and we change only the number of columns |
|||
{ |
|||
const Index new_rows = other.rows() - _this.rows(); |
|||
const Index new_cols = other.cols() - _this.cols(); |
|||
_this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols()); |
|||
if (new_rows>0) |
|||
_this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows); |
|||
else if (new_cols>0) |
|||
_this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols); |
|||
} |
|||
else |
|||
{ |
|||
// The storage order does not allow us to use reallocation. |
|||
typename Derived::PlainObject tmp(other); |
|||
const Index common_rows = (std::min)(tmp.rows(), _this.rows()); |
|||
const Index common_cols = (std::min)(tmp.cols(), _this.cols()); |
|||
tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols); |
|||
_this.derived().swap(tmp); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
namespace internal { |
|||
|
|||
template <typename Derived, typename OtherDerived> |
|||
struct conservative_resize_like_impl<Derived,OtherDerived,true> |
|||
{ |
|||
typedef typename Derived::Index Index; |
|||
static void run(DenseBase<Derived>& _this, Index size) |
|||
{ |
|||
const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size; |
|||
const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1; |
|||
_this.derived().m_storage.conservativeResize(size,new_rows,new_cols); |
|||
} |
|||
|
|||
static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) |
|||
{ |
|||
if (_this.rows() == other.rows() && _this.cols() == other.cols()) return; |
|||
|
|||
const Index num_new_elements = other.size() - _this.size(); |
|||
|
|||
const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows(); |
|||
const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1; |
|||
_this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols); |
|||
|
|||
if (num_new_elements > 0) |
|||
_this.tail(num_new_elements) = other.tail(num_new_elements); |
|||
} |
|||
}; |
|||
|
|||
template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> |
|||
struct matrix_swap_impl |
|||
{ |
|||
static inline void run(MatrixTypeA& a, MatrixTypeB& b) |
|||
{ |
|||
a.base().swap(b); |
|||
} |
|||
}; |
|||
|
|||
template<typename MatrixTypeA, typename MatrixTypeB> |
|||
struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true> |
|||
{ |
|||
static inline void run(MatrixTypeA& a, MatrixTypeB& b) |
|||
{ |
|||
static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage); |
|||
} |
|||
}; |
|||
|
|||
} // end namespace internal |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_DENSESTORAGEBASE_H |
@ -0,0 +1,98 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_PRODUCT_H |
|||
#define EIGEN_PRODUCT_H |
|||
|
|||
template<typename Lhs, typename Rhs> class Product; |
|||
template<typename Lhs, typename Rhs, typename StorageKind> class ProductImpl; |
|||
|
|||
/** \class Product |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of the product of two arbitrary matrices or vectors |
|||
* |
|||
* \param Lhs the type of the left-hand side expression |
|||
* \param Rhs the type of the right-hand side expression |
|||
* |
|||
* This class represents an expression of the product of two arbitrary matrices. |
|||
* |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename Lhs, typename Rhs> |
|||
struct traits<Product<Lhs, Rhs> > |
|||
{ |
|||
typedef MatrixXpr XprKind; |
|||
typedef typename remove_all<Lhs>::type LhsCleaned; |
|||
typedef typename remove_all<Rhs>::type RhsCleaned; |
|||
typedef typename scalar_product_traits<typename traits<LhsCleaned>::Scalar, typename traits<RhsCleaned>::Scalar>::ReturnType Scalar; |
|||
typedef typename promote_storage_type<typename traits<LhsCleaned>::StorageKind, |
|||
typename traits<RhsCleaned>::StorageKind>::ret StorageKind; |
|||
typedef typename promote_index_type<typename traits<LhsCleaned>::Index, |
|||
typename traits<RhsCleaned>::Index>::type Index; |
|||
enum { |
|||
RowsAtCompileTime = LhsCleaned::RowsAtCompileTime, |
|||
ColsAtCompileTime = RhsCleaned::ColsAtCompileTime, |
|||
MaxRowsAtCompileTime = LhsCleaned::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = RhsCleaned::MaxColsAtCompileTime, |
|||
Flags = (MaxRowsAtCompileTime==1 ? RowMajorBit : 0), // TODO should be no storage order |
|||
CoeffReadCost = 0 // TODO CoeffReadCost should not be part of the expression traits |
|||
}; |
|||
}; |
|||
} // end namespace internal |
|||
|
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
class Product : public ProductImpl<Lhs,Rhs,typename internal::promote_storage_type<typename internal::traits<Lhs>::StorageKind, |
|||
typename internal::traits<Rhs>::StorageKind>::ret> |
|||
{ |
|||
public: |
|||
|
|||
typedef typename ProductImpl< |
|||
Lhs, Rhs, |
|||
typename internal::promote_storage_type<typename Lhs::StorageKind, |
|||
typename Rhs::StorageKind>::ret>::Base Base; |
|||
EIGEN_GENERIC_PUBLIC_INTERFACE(Product) |
|||
|
|||
typedef typename Lhs::Nested LhsNested; |
|||
typedef typename Rhs::Nested RhsNested; |
|||
typedef typename internal::remove_all<LhsNested>::type LhsNestedCleaned; |
|||
typedef typename internal::remove_all<RhsNested>::type RhsNestedCleaned; |
|||
|
|||
Product(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs) |
|||
{ |
|||
eigen_assert(lhs.cols() == rhs.rows() |
|||
&& "invalid matrix product" |
|||
&& "if you wanted a coeff-wise or a dot product use the respective explicit functions"); |
|||
} |
|||
|
|||
inline Index rows() const { return m_lhs.rows(); } |
|||
inline Index cols() const { return m_rhs.cols(); } |
|||
|
|||
const LhsNestedCleaned& lhs() const { return m_lhs; } |
|||
const RhsNestedCleaned& rhs() const { return m_rhs; } |
|||
|
|||
protected: |
|||
|
|||
const LhsNested m_lhs; |
|||
const RhsNested m_rhs; |
|||
}; |
|||
|
|||
template<typename Lhs, typename Rhs> |
|||
class ProductImpl<Lhs,Rhs,Dense> : public internal::dense_xpr_base<Product<Lhs,Rhs> >::type |
|||
{ |
|||
typedef Product<Lhs, Rhs> Derived; |
|||
public: |
|||
|
|||
typedef typename internal::dense_xpr_base<Product<Lhs, Rhs> >::type Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Derived) |
|||
}; |
|||
|
|||
#endif // EIGEN_PRODUCT_H |
@ -0,0 +1,278 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_PRODUCTBASE_H |
|||
#define EIGEN_PRODUCTBASE_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class ProductBase |
|||
* \ingroup Core_Module |
|||
* |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename Derived, typename _Lhs, typename _Rhs> |
|||
struct traits<ProductBase<Derived,_Lhs,_Rhs> > |
|||
{ |
|||
typedef MatrixXpr XprKind; |
|||
typedef typename remove_all<_Lhs>::type Lhs; |
|||
typedef typename remove_all<_Rhs>::type Rhs; |
|||
typedef typename scalar_product_traits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar; |
|||
typedef typename promote_storage_type<typename traits<Lhs>::StorageKind, |
|||
typename traits<Rhs>::StorageKind>::ret StorageKind; |
|||
typedef typename promote_index_type<typename traits<Lhs>::Index, |
|||
typename traits<Rhs>::Index>::type Index; |
|||
enum { |
|||
RowsAtCompileTime = traits<Lhs>::RowsAtCompileTime, |
|||
ColsAtCompileTime = traits<Rhs>::ColsAtCompileTime, |
|||
MaxRowsAtCompileTime = traits<Lhs>::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = traits<Rhs>::MaxColsAtCompileTime, |
|||
Flags = (MaxRowsAtCompileTime==1 ? RowMajorBit : 0) |
|||
| EvalBeforeNestingBit | EvalBeforeAssigningBit | NestByRefBit, |
|||
// Note that EvalBeforeNestingBit and NestByRefBit |
|||
// are not used in practice because nested is overloaded for products |
|||
CoeffReadCost = 0 // FIXME why is it needed ? |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
#define EIGEN_PRODUCT_PUBLIC_INTERFACE(Derived) \ |
|||
typedef ProductBase<Derived, Lhs, Rhs > Base; \ |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Derived) \ |
|||
typedef typename Base::LhsNested LhsNested; \ |
|||
typedef typename Base::_LhsNested _LhsNested; \ |
|||
typedef typename Base::LhsBlasTraits LhsBlasTraits; \ |
|||
typedef typename Base::ActualLhsType ActualLhsType; \ |
|||
typedef typename Base::_ActualLhsType _ActualLhsType; \ |
|||
typedef typename Base::RhsNested RhsNested; \ |
|||
typedef typename Base::_RhsNested _RhsNested; \ |
|||
typedef typename Base::RhsBlasTraits RhsBlasTraits; \ |
|||
typedef typename Base::ActualRhsType ActualRhsType; \ |
|||
typedef typename Base::_ActualRhsType _ActualRhsType; \ |
|||
using Base::m_lhs; \ |
|||
using Base::m_rhs; |
|||
|
|||
template<typename Derived, typename Lhs, typename Rhs> |
|||
class ProductBase : public MatrixBase<Derived> |
|||
{ |
|||
public: |
|||
typedef MatrixBase<Derived> Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(ProductBase) |
|||
|
|||
typedef typename Lhs::Nested LhsNested; |
|||
typedef typename internal::remove_all<LhsNested>::type _LhsNested; |
|||
typedef internal::blas_traits<_LhsNested> LhsBlasTraits; |
|||
typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType; |
|||
typedef typename internal::remove_all<ActualLhsType>::type _ActualLhsType; |
|||
typedef typename internal::traits<Lhs>::Scalar LhsScalar; |
|||
|
|||
typedef typename Rhs::Nested RhsNested; |
|||
typedef typename internal::remove_all<RhsNested>::type _RhsNested; |
|||
typedef internal::blas_traits<_RhsNested> RhsBlasTraits; |
|||
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType; |
|||
typedef typename internal::remove_all<ActualRhsType>::type _ActualRhsType; |
|||
typedef typename internal::traits<Rhs>::Scalar RhsScalar; |
|||
|
|||
// Diagonal of a product: no need to evaluate the arguments because they are going to be evaluated only once |
|||
typedef CoeffBasedProduct<LhsNested, RhsNested, 0> FullyLazyCoeffBaseProductType; |
|||
|
|||
public: |
|||
|
|||
typedef typename Base::PlainObject PlainObject; |
|||
|
|||
ProductBase(const Lhs& lhs, const Rhs& rhs) |
|||
: m_lhs(lhs), m_rhs(rhs) |
|||
{ |
|||
eigen_assert(lhs.cols() == rhs.rows() |
|||
&& "invalid matrix product" |
|||
&& "if you wanted a coeff-wise or a dot product use the respective explicit functions"); |
|||
} |
|||
|
|||
inline Index rows() const { return m_lhs.rows(); } |
|||
inline Index cols() const { return m_rhs.cols(); } |
|||
|
|||
template<typename Dest> |
|||
inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst,Scalar(1)); } |
|||
|
|||
template<typename Dest> |
|||
inline void addTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(1)); } |
|||
|
|||
template<typename Dest> |
|||
inline void subTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(-1)); } |
|||
|
|||
template<typename Dest> |
|||
inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { derived().scaleAndAddTo(dst,alpha); } |
|||
|
|||
const _LhsNested& lhs() const { return m_lhs; } |
|||
const _RhsNested& rhs() const { return m_rhs; } |
|||
|
|||
// Implicit conversion to the nested type (trigger the evaluation of the product) |
|||
operator const PlainObject& () const |
|||
{ |
|||
m_result.resize(m_lhs.rows(), m_rhs.cols()); |
|||
derived().evalTo(m_result); |
|||
return m_result; |
|||
} |
|||
|
|||
const Diagonal<const FullyLazyCoeffBaseProductType,0> diagonal() const |
|||
{ return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); } |
|||
|
|||
template<int Index> |
|||
const Diagonal<FullyLazyCoeffBaseProductType,Index> diagonal() const |
|||
{ return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); } |
|||
|
|||
const Diagonal<FullyLazyCoeffBaseProductType,Dynamic> diagonal(Index index) const |
|||
{ return FullyLazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); } |
|||
|
|||
// restrict coeff accessors to 1x1 expressions. No need to care about mutators here since this isnt a Lvalue expression |
|||
typename Base::CoeffReturnType coeff(Index row, Index col) const |
|||
{ |
|||
#ifdef EIGEN2_SUPPORT |
|||
return lhs().row(row).cwiseProduct(rhs().col(col).transpose()).sum(); |
|||
#else |
|||
EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) |
|||
eigen_assert(this->rows() == 1 && this->cols() == 1); |
|||
Matrix<Scalar,1,1> result = *this; |
|||
return result.coeff(row,col); |
|||
#endif |
|||
} |
|||
|
|||
typename Base::CoeffReturnType coeff(Index i) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) |
|||
eigen_assert(this->rows() == 1 && this->cols() == 1); |
|||
Matrix<Scalar,1,1> result = *this; |
|||
return result.coeff(i); |
|||
} |
|||
|
|||
const Scalar& coeffRef(Index row, Index col) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) |
|||
eigen_assert(this->rows() == 1 && this->cols() == 1); |
|||
return derived().coeffRef(row,col); |
|||
} |
|||
|
|||
const Scalar& coeffRef(Index i) const |
|||
{ |
|||
EIGEN_STATIC_ASSERT_SIZE_1x1(Derived) |
|||
eigen_assert(this->rows() == 1 && this->cols() == 1); |
|||
return derived().coeffRef(i); |
|||
} |
|||
|
|||
protected: |
|||
|
|||
LhsNested m_lhs; |
|||
RhsNested m_rhs; |
|||
|
|||
mutable PlainObject m_result; |
|||
}; |
|||
|
|||
// here we need to overload the nested rule for products |
|||
// such that the nested type is a const reference to a plain matrix |
|||
namespace internal { |
|||
template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject> |
|||
struct nested<GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject> |
|||
{ |
|||
typedef PlainObject const& type; |
|||
}; |
|||
} |
|||
|
|||
template<typename NestedProduct> |
|||
class ScaledProduct; |
|||
|
|||
// Note that these two operator* functions are not defined as member |
|||
// functions of ProductBase, because, otherwise we would have to |
|||
// define all overloads defined in MatrixBase. Furthermore, Using |
|||
// "using Base::operator*" would not work with MSVC. |
|||
// |
|||
// Also note that here we accept any compatible scalar types |
|||
template<typename Derived,typename Lhs,typename Rhs> |
|||
const ScaledProduct<Derived> |
|||
operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::Scalar x) |
|||
{ return ScaledProduct<Derived>(prod.derived(), x); } |
|||
|
|||
template<typename Derived,typename Lhs,typename Rhs> |
|||
typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value, |
|||
const ScaledProduct<Derived> >::type |
|||
operator*(const ProductBase<Derived,Lhs,Rhs>& prod, typename Derived::RealScalar x) |
|||
{ return ScaledProduct<Derived>(prod.derived(), x); } |
|||
|
|||
|
|||
template<typename Derived,typename Lhs,typename Rhs> |
|||
const ScaledProduct<Derived> |
|||
operator*(typename Derived::Scalar x,const ProductBase<Derived,Lhs,Rhs>& prod) |
|||
{ return ScaledProduct<Derived>(prod.derived(), x); } |
|||
|
|||
template<typename Derived,typename Lhs,typename Rhs> |
|||
typename internal::enable_if<!internal::is_same<typename Derived::Scalar,typename Derived::RealScalar>::value, |
|||
const ScaledProduct<Derived> >::type |
|||
operator*(typename Derived::RealScalar x,const ProductBase<Derived,Lhs,Rhs>& prod) |
|||
{ return ScaledProduct<Derived>(prod.derived(), x); } |
|||
|
|||
namespace internal { |
|||
template<typename NestedProduct> |
|||
struct traits<ScaledProduct<NestedProduct> > |
|||
: traits<ProductBase<ScaledProduct<NestedProduct>, |
|||
typename NestedProduct::_LhsNested, |
|||
typename NestedProduct::_RhsNested> > |
|||
{ |
|||
typedef typename traits<NestedProduct>::StorageKind StorageKind; |
|||
}; |
|||
} |
|||
|
|||
template<typename NestedProduct> |
|||
class ScaledProduct |
|||
: public ProductBase<ScaledProduct<NestedProduct>, |
|||
typename NestedProduct::_LhsNested, |
|||
typename NestedProduct::_RhsNested> |
|||
{ |
|||
public: |
|||
typedef ProductBase<ScaledProduct<NestedProduct>, |
|||
typename NestedProduct::_LhsNested, |
|||
typename NestedProduct::_RhsNested> Base; |
|||
typedef typename Base::Scalar Scalar; |
|||
typedef typename Base::PlainObject PlainObject; |
|||
// EIGEN_PRODUCT_PUBLIC_INTERFACE(ScaledProduct) |
|||
|
|||
ScaledProduct(const NestedProduct& prod, Scalar x) |
|||
: Base(prod.lhs(),prod.rhs()), m_prod(prod), m_alpha(x) {} |
|||
|
|||
template<typename Dest> |
|||
inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst, Scalar(1)); } |
|||
|
|||
template<typename Dest> |
|||
inline void addTo(Dest& dst) const { scaleAndAddTo(dst, Scalar(1)); } |
|||
|
|||
template<typename Dest> |
|||
inline void subTo(Dest& dst) const { scaleAndAddTo(dst, Scalar(-1)); } |
|||
|
|||
template<typename Dest> |
|||
inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { m_prod.derived().scaleAndAddTo(dst,alpha * m_alpha); } |
|||
|
|||
const Scalar& alpha() const { return m_alpha; } |
|||
|
|||
protected: |
|||
const NestedProduct& m_prod; |
|||
Scalar m_alpha; |
|||
}; |
|||
|
|||
/** \internal |
|||
* Overloaded to perform an efficient C = (A*B).lazy() */ |
|||
template<typename Derived> |
|||
template<typename ProductDerived, typename Lhs, typename Rhs> |
|||
Derived& MatrixBase<Derived>::lazyAssign(const ProductBase<ProductDerived, Lhs,Rhs>& other) |
|||
{ |
|||
other.derived().evalTo(derived()); |
|||
return derived(); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_PRODUCTBASE_H |
@ -0,0 +1,152 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_RANDOM_H |
|||
#define EIGEN_RANDOM_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
namespace internal { |
|||
|
|||
template<typename Scalar> struct scalar_random_op { |
|||
EIGEN_EMPTY_STRUCT_CTOR(scalar_random_op) |
|||
template<typename Index> |
|||
inline const Scalar operator() (Index, Index = 0) const { return random<Scalar>(); } |
|||
}; |
|||
|
|||
template<typename Scalar> |
|||
struct functor_traits<scalar_random_op<Scalar> > |
|||
{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = false }; }; |
|||
|
|||
} // end namespace internal |
|||
|
|||
/** \returns a random matrix expression |
|||
* |
|||
* The parameters \a rows and \a cols are the number of rows and of columns of |
|||
* the returned matrix. Must be compatible with this MatrixBase type. |
|||
* |
|||
* This variant is meant to be used for dynamic-size matrix types. For fixed-size types, |
|||
* it is redundant to pass \a rows and \a cols as arguments, so Random() should be used |
|||
* instead. |
|||
* |
|||
* Example: \include MatrixBase_random_int_int.cpp |
|||
* Output: \verbinclude MatrixBase_random_int_int.out |
|||
* |
|||
* This expression has the "evaluate before nesting" flag so that it will be evaluated into |
|||
* a temporary matrix whenever it is nested in a larger expression. This prevents unexpected |
|||
* behavior with expressions involving random matrices. |
|||
* |
|||
* \sa MatrixBase::setRandom(), MatrixBase::Random(Index), MatrixBase::Random() |
|||
*/ |
|||
template<typename Derived> |
|||
inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived> |
|||
DenseBase<Derived>::Random(Index rows, Index cols) |
|||
{ |
|||
return NullaryExpr(rows, cols, internal::scalar_random_op<Scalar>()); |
|||
} |
|||
|
|||
/** \returns a random vector expression |
|||
* |
|||
* The parameter \a size is the size of the returned vector. |
|||
* Must be compatible with this MatrixBase type. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* This variant is meant to be used for dynamic-size vector types. For fixed-size types, |
|||
* it is redundant to pass \a size as argument, so Random() should be used |
|||
* instead. |
|||
* |
|||
* Example: \include MatrixBase_random_int.cpp |
|||
* Output: \verbinclude MatrixBase_random_int.out |
|||
* |
|||
* This expression has the "evaluate before nesting" flag so that it will be evaluated into |
|||
* a temporary vector whenever it is nested in a larger expression. This prevents unexpected |
|||
* behavior with expressions involving random matrices. |
|||
* |
|||
* \sa MatrixBase::setRandom(), MatrixBase::Random(Index,Index), MatrixBase::Random() |
|||
*/ |
|||
template<typename Derived> |
|||
inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived> |
|||
DenseBase<Derived>::Random(Index size) |
|||
{ |
|||
return NullaryExpr(size, internal::scalar_random_op<Scalar>()); |
|||
} |
|||
|
|||
/** \returns a fixed-size random matrix or vector expression |
|||
* |
|||
* This variant is only for fixed-size MatrixBase types. For dynamic-size types, you |
|||
* need to use the variants taking size arguments. |
|||
* |
|||
* Example: \include MatrixBase_random.cpp |
|||
* Output: \verbinclude MatrixBase_random.out |
|||
* |
|||
* This expression has the "evaluate before nesting" flag so that it will be evaluated into |
|||
* a temporary matrix whenever it is nested in a larger expression. This prevents unexpected |
|||
* behavior with expressions involving random matrices. |
|||
* |
|||
* \sa MatrixBase::setRandom(), MatrixBase::Random(Index,Index), MatrixBase::Random(Index) |
|||
*/ |
|||
template<typename Derived> |
|||
inline const CwiseNullaryOp<internal::scalar_random_op<typename internal::traits<Derived>::Scalar>, Derived> |
|||
DenseBase<Derived>::Random() |
|||
{ |
|||
return NullaryExpr(RowsAtCompileTime, ColsAtCompileTime, internal::scalar_random_op<Scalar>()); |
|||
} |
|||
|
|||
/** Sets all coefficients in this expression to random values. |
|||
* |
|||
* Example: \include MatrixBase_setRandom.cpp |
|||
* Output: \verbinclude MatrixBase_setRandom.out |
|||
* |
|||
* \sa class CwiseNullaryOp, setRandom(Index), setRandom(Index,Index) |
|||
*/ |
|||
template<typename Derived> |
|||
inline Derived& DenseBase<Derived>::setRandom() |
|||
{ |
|||
return *this = Random(rows(), cols()); |
|||
} |
|||
|
|||
/** Resizes to the given \a size, and sets all coefficients in this expression to random values. |
|||
* |
|||
* \only_for_vectors |
|||
* |
|||
* Example: \include Matrix_setRandom_int.cpp |
|||
* Output: \verbinclude Matrix_setRandom_int.out |
|||
* |
|||
* \sa MatrixBase::setRandom(), setRandom(Index,Index), class CwiseNullaryOp, MatrixBase::Random() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& |
|||
PlainObjectBase<Derived>::setRandom(Index size) |
|||
{ |
|||
resize(size); |
|||
return setRandom(); |
|||
} |
|||
|
|||
/** Resizes to the given size, and sets all coefficients in this expression to random values. |
|||
* |
|||
* \param rows the new number of rows |
|||
* \param cols the new number of columns |
|||
* |
|||
* Example: \include Matrix_setRandom_int_int.cpp |
|||
* Output: \verbinclude Matrix_setRandom_int_int.out |
|||
* |
|||
* \sa MatrixBase::setRandom(), setRandom(Index), class CwiseNullaryOp, MatrixBase::Random() |
|||
*/ |
|||
template<typename Derived> |
|||
EIGEN_STRONG_INLINE Derived& |
|||
PlainObjectBase<Derived>::setRandom(Index rows, Index cols) |
|||
{ |
|||
resize(rows, cols); |
|||
return setRandom(); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_RANDOM_H |
@ -0,0 +1,177 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_REPLICATE_H |
|||
#define EIGEN_REPLICATE_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** |
|||
* \class Replicate |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of the multiple replication of a matrix or vector |
|||
* |
|||
* \param MatrixType the type of the object we are replicating |
|||
* |
|||
* This class represents an expression of the multiple replication of a matrix or vector. |
|||
* It is the return type of DenseBase::replicate() and most of the time |
|||
* this is the only way it is used. |
|||
* |
|||
* \sa DenseBase::replicate() |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename MatrixType,int RowFactor,int ColFactor> |
|||
struct traits<Replicate<MatrixType,RowFactor,ColFactor> > |
|||
: traits<MatrixType> |
|||
{ |
|||
typedef typename MatrixType::Scalar Scalar; |
|||
typedef typename traits<MatrixType>::StorageKind StorageKind; |
|||
typedef typename traits<MatrixType>::XprKind XprKind; |
|||
enum { |
|||
Factor = (RowFactor==Dynamic || ColFactor==Dynamic) ? Dynamic : RowFactor*ColFactor |
|||
}; |
|||
typedef typename nested<MatrixType,Factor>::type MatrixTypeNested; |
|||
typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested; |
|||
enum { |
|||
RowsAtCompileTime = RowFactor==Dynamic || int(MatrixType::RowsAtCompileTime)==Dynamic |
|||
? Dynamic |
|||
: RowFactor * MatrixType::RowsAtCompileTime, |
|||
ColsAtCompileTime = ColFactor==Dynamic || int(MatrixType::ColsAtCompileTime)==Dynamic |
|||
? Dynamic |
|||
: ColFactor * MatrixType::ColsAtCompileTime, |
|||
//FIXME we don't propagate the max sizes !!! |
|||
MaxRowsAtCompileTime = RowsAtCompileTime, |
|||
MaxColsAtCompileTime = ColsAtCompileTime, |
|||
IsRowMajor = MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1 ? 1 |
|||
: MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1 ? 0 |
|||
: (MatrixType::Flags & RowMajorBit) ? 1 : 0, |
|||
Flags = (_MatrixTypeNested::Flags & HereditaryBits & ~RowMajorBit) | (IsRowMajor ? RowMajorBit : 0), |
|||
CoeffReadCost = _MatrixTypeNested::CoeffReadCost |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename MatrixType,int RowFactor,int ColFactor> class Replicate |
|||
: public internal::dense_xpr_base< Replicate<MatrixType,RowFactor,ColFactor> >::type |
|||
{ |
|||
typedef typename internal::traits<Replicate>::MatrixTypeNested MatrixTypeNested; |
|||
typedef typename internal::traits<Replicate>::_MatrixTypeNested _MatrixTypeNested; |
|||
public: |
|||
|
|||
typedef typename internal::dense_xpr_base<Replicate>::type Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Replicate) |
|||
|
|||
template<typename OriginalMatrixType> |
|||
inline explicit Replicate(const OriginalMatrixType& matrix) |
|||
: m_matrix(matrix), m_rowFactor(RowFactor), m_colFactor(ColFactor) |
|||
{ |
|||
EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value), |
|||
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE) |
|||
eigen_assert(RowFactor!=Dynamic && ColFactor!=Dynamic); |
|||
} |
|||
|
|||
template<typename OriginalMatrixType> |
|||
inline Replicate(const OriginalMatrixType& matrix, Index rowFactor, Index colFactor) |
|||
: m_matrix(matrix), m_rowFactor(rowFactor), m_colFactor(colFactor) |
|||
{ |
|||
EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value), |
|||
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE) |
|||
} |
|||
|
|||
inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); } |
|||
inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); } |
|||
|
|||
inline Scalar coeff(Index row, Index col) const |
|||
{ |
|||
// try to avoid using modulo; this is a pure optimization strategy |
|||
const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0 |
|||
: RowFactor==1 ? row |
|||
: row%m_matrix.rows(); |
|||
const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0 |
|||
: ColFactor==1 ? col |
|||
: col%m_matrix.cols(); |
|||
|
|||
return m_matrix.coeff(actual_row, actual_col); |
|||
} |
|||
template<int LoadMode> |
|||
inline PacketScalar packet(Index row, Index col) const |
|||
{ |
|||
const Index actual_row = internal::traits<MatrixType>::RowsAtCompileTime==1 ? 0 |
|||
: RowFactor==1 ? row |
|||
: row%m_matrix.rows(); |
|||
const Index actual_col = internal::traits<MatrixType>::ColsAtCompileTime==1 ? 0 |
|||
: ColFactor==1 ? col |
|||
: col%m_matrix.cols(); |
|||
|
|||
return m_matrix.template packet<LoadMode>(actual_row, actual_col); |
|||
} |
|||
|
|||
const _MatrixTypeNested& nestedExpression() const |
|||
{ |
|||
return m_matrix; |
|||
} |
|||
|
|||
protected: |
|||
MatrixTypeNested m_matrix; |
|||
const internal::variable_if_dynamic<Index, RowFactor> m_rowFactor; |
|||
const internal::variable_if_dynamic<Index, ColFactor> m_colFactor; |
|||
}; |
|||
|
|||
/** |
|||
* \return an expression of the replication of \c *this |
|||
* |
|||
* Example: \include MatrixBase_replicate.cpp |
|||
* Output: \verbinclude MatrixBase_replicate.out |
|||
* |
|||
* \sa VectorwiseOp::replicate(), DenseBase::replicate(Index,Index), class Replicate |
|||
*/ |
|||
template<typename Derived> |
|||
template<int RowFactor, int ColFactor> |
|||
inline const Replicate<Derived,RowFactor,ColFactor> |
|||
DenseBase<Derived>::replicate() const |
|||
{ |
|||
return Replicate<Derived,RowFactor,ColFactor>(derived()); |
|||
} |
|||
|
|||
/** |
|||
* \return an expression of the replication of \c *this |
|||
* |
|||
* Example: \include MatrixBase_replicate_int_int.cpp |
|||
* Output: \verbinclude MatrixBase_replicate_int_int.out |
|||
* |
|||
* \sa VectorwiseOp::replicate(), DenseBase::replicate<int,int>(), class Replicate |
|||
*/ |
|||
template<typename Derived> |
|||
inline const Replicate<Derived,Dynamic,Dynamic> |
|||
DenseBase<Derived>::replicate(Index rowFactor,Index colFactor) const |
|||
{ |
|||
return Replicate<Derived,Dynamic,Dynamic>(derived(),rowFactor,colFactor); |
|||
} |
|||
|
|||
/** |
|||
* \return an expression of the replication of each column (or row) of \c *this |
|||
* |
|||
* Example: \include DirectionWise_replicate_int.cpp |
|||
* Output: \verbinclude DirectionWise_replicate_int.out |
|||
* |
|||
* \sa VectorwiseOp::replicate(), DenseBase::replicate(), class Replicate |
|||
*/ |
|||
template<typename ExpressionType, int Direction> |
|||
const typename VectorwiseOp<ExpressionType,Direction>::ReplicateReturnType |
|||
VectorwiseOp<ExpressionType,Direction>::replicate(Index factor) const |
|||
{ |
|||
return typename VectorwiseOp<ExpressionType,Direction>::ReplicateReturnType |
|||
(_expression(),Direction==Vertical?factor:1,Direction==Horizontal?factor:1); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_REPLICATE_H |
@ -0,0 +1,162 @@ |
|||
// This file is part of Eigen, a lightweight C++ template library |
|||
// for linear algebra. |
|||
// |
|||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
|||
// |
|||
// 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_SELECT_H |
|||
#define EIGEN_SELECT_H |
|||
|
|||
namespace Eigen { |
|||
|
|||
/** \class Select |
|||
* \ingroup Core_Module |
|||
* |
|||
* \brief Expression of a coefficient wise version of the C++ ternary operator ?: |
|||
* |
|||
* \param ConditionMatrixType the type of the \em condition expression which must be a boolean matrix |
|||
* \param ThenMatrixType the type of the \em then expression |
|||
* \param ElseMatrixType the type of the \em else expression |
|||
* |
|||
* This class represents an expression of a coefficient wise version of the C++ ternary operator ?:. |
|||
* It is the return type of DenseBase::select() and most of the time this is the only way it is used. |
|||
* |
|||
* \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const |
|||
*/ |
|||
|
|||
namespace internal { |
|||
template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType> |
|||
struct traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> > |
|||
: traits<ThenMatrixType> |
|||
{ |
|||
typedef typename traits<ThenMatrixType>::Scalar Scalar; |
|||
typedef Dense StorageKind; |
|||
typedef typename traits<ThenMatrixType>::XprKind XprKind; |
|||
typedef typename ConditionMatrixType::Nested ConditionMatrixNested; |
|||
typedef typename ThenMatrixType::Nested ThenMatrixNested; |
|||
typedef typename ElseMatrixType::Nested ElseMatrixNested; |
|||
enum { |
|||
RowsAtCompileTime = ConditionMatrixType::RowsAtCompileTime, |
|||
ColsAtCompileTime = ConditionMatrixType::ColsAtCompileTime, |
|||
MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime, |
|||
MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime, |
|||
Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & HereditaryBits, |
|||
CoeffReadCost = traits<typename remove_all<ConditionMatrixNested>::type>::CoeffReadCost |
|||
+ EIGEN_SIZE_MAX(traits<typename remove_all<ThenMatrixNested>::type>::CoeffReadCost, |
|||
traits<typename remove_all<ElseMatrixNested>::type>::CoeffReadCost) |
|||
}; |
|||
}; |
|||
} |
|||
|
|||
template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType> |
|||
class Select : internal::no_assignment_operator, |
|||
public internal::dense_xpr_base< Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >::type |
|||
{ |
|||
public: |
|||
|
|||
typedef typename internal::dense_xpr_base<Select>::type Base; |
|||
EIGEN_DENSE_PUBLIC_INTERFACE(Select) |
|||
|
|||
Select(const ConditionMatrixType& conditionMatrix, |
|||
const ThenMatrixType& thenMatrix, |
|||
const ElseMatrixType& elseMatrix) |
|||
: m_condition(conditionMatrix), m_then(thenMatrix), m_else(elseMatrix) |
|||
{ |
|||
eigen_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows()); |
|||
eigen_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols()); |
|||
} |
|||
|
|||
Index rows() const { return m_condition.rows(); } |
|||
Index cols() const { return m_condition.cols(); } |
|||
|
|||
const Scalar coeff(Index i, Index j) const |
|||
{ |
|||
if (m_condition.coeff(i,j)) |
|||
return m_then.coeff(i,j); |
|||
else |
|||
return m_else.coeff(i,j); |
|||
} |
|||
|
|||
const Scalar coeff(Index i) const |
|||
{ |
|||
if (m_condition.coeff(i)) |
|||
return m_then.coeff(i); |
|||
else |
|||
return m_else.coeff(i); |
|||
} |
|||
|
|||
const ConditionMatrixType& conditionMatrix() const |
|||
{ |
|||
return m_condition; |
|||
} |
|||
|
|||
const ThenMatrixType& thenMatrix() const |
|||
{ |
|||
return m_then; |
|||
} |
|||
|
|||
const ElseMatrixType& elseMatrix() const |
|||
{ |
|||
return m_else; |
|||
} |
|||
|
|||
protected: |
|||
typename ConditionMatrixType::Nested m_condition; |
|||
typename ThenMatrixType::Nested m_then; |
|||
typename ElseMatrixType::Nested m_else; |
|||
}; |
|||
|
|||
|
|||
/** \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j) |
|||
* if \c *this(i,j), and \a elseMatrix(i,j) otherwise. |
|||
* |
|||
* Example: \include MatrixBase_select.cpp |
|||
* Output: \verbinclude MatrixBase_select.out |
|||
* |
|||
* \sa class Select |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename ThenDerived,typename ElseDerived> |
|||
inline const Select<Derived,ThenDerived,ElseDerived> |
|||
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix, |
|||
const DenseBase<ElseDerived>& elseMatrix) const |
|||
{ |
|||
return Select<Derived,ThenDerived,ElseDerived>(derived(), thenMatrix.derived(), elseMatrix.derived()); |
|||
} |
|||
|
|||
/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with |
|||
* the \em else expression being a scalar value. |
|||
* |
|||
* \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename ThenDerived> |
|||
inline const Select<Derived,ThenDerived, typename ThenDerived::ConstantReturnType> |
|||
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix, |
|||
typename ThenDerived::Scalar elseScalar) const |
|||
{ |
|||
return Select<Derived,ThenDerived,typename ThenDerived::ConstantReturnType>( |
|||
derived(), thenMatrix.derived(), ThenDerived::Constant(rows(),cols(),elseScalar)); |
|||
} |
|||
|
|||
/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with |
|||
* the \em then expression being a scalar value. |
|||
* |
|||
* \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select |
|||
*/ |
|||
template<typename Derived> |
|||
template<typename ElseDerived> |
|||
inline const Select<Derived, typename ElseDerived::ConstantReturnType, ElseDerived > |
|||
DenseBase<Derived>::select(typename ElseDerived::Scalar thenScalar, |
|||
const DenseBase<ElseDerived>& elseMatrix) const |
|||
{ |
|||
return Select<Derived,typename ElseDerived::ConstantReturnType,ElseDerived>( |
|||
derived(), ElseDerived::Constant(rows(),cols(),thenScalar), elseMatrix.derived()); |
|||
} |
|||
|
|||
} // end namespace Eigen |
|||
|
|||
#endif // EIGEN_SELECT_H |
Some files were not shown because too many files changed in this diff
Reference in new issue
xxxxxxxxxx