mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-10-06 00:30:10 -06:00
Eigen: Updated to version 3.3.4
git-svn-id: svn://ultimatepp.org/upp/trunk@11406 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
c91e77562d
commit
abf7bcb9db
337 changed files with 2347 additions and 44643 deletions
|
|
@ -1,5 +0,0 @@
|
|||
Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef EIGEN_ARRAY_MODULE_H
|
||||
#define EIGEN_ARRAY_MODULE_H
|
||||
|
||||
// include Core first to handle Eigen2 support macros
|
||||
#include "Core"
|
||||
|
||||
#ifndef EIGEN2_SUPPORT
|
||||
#error The Eigen/Array header does no longer exist in Eigen3. All that functionality has moved to Eigen/Core.
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_ARRAY_MODULE_H
|
||||
|
|
@ -43,8 +43,10 @@
|
|||
#else
|
||||
#define EIGEN_DEVICE_FUNC
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define EIGEN_DEVICE_FUNC
|
||||
|
||||
#endif
|
||||
|
||||
// When compiling CUDA device code with NVCC, pull in math functions from the
|
||||
|
|
@ -145,15 +147,11 @@
|
|||
#ifdef __FMA__
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#endif
|
||||
#if defined(__AVX512F__)
|
||||
#if defined(__AVX512F__) && defined(EIGEN_ENABLE_AVX512)
|
||||
#define EIGEN_VECTORIZE_AVX512
|
||||
#define EIGEN_VECTORIZE_AVX2
|
||||
#define EIGEN_VECTORIZE_AVX
|
||||
#define EIGEN_VECTORIZE_FMA
|
||||
#define EIGEN_VECTORIZE_SSE3
|
||||
#define EIGEN_VECTORIZE_SSSE3
|
||||
#define EIGEN_VECTORIZE_SSE4_1
|
||||
#define EIGEN_VECTORIZE_SSE4_2
|
||||
#ifdef __AVX512DQ__
|
||||
#define EIGEN_VECTORIZE_AVX512DQ
|
||||
#endif
|
||||
|
|
@ -285,15 +283,6 @@
|
|||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
#undef min
|
||||
#undef max
|
||||
#undef isnan
|
||||
#undef isinf
|
||||
#undef isfinite
|
||||
#include <SYCL/sycl.hpp>
|
||||
#endif
|
||||
|
||||
/** \brief Namespace containing all symbols from the %Eigen library. */
|
||||
namespace Eigen {
|
||||
|
||||
|
|
@ -332,12 +321,16 @@ inline static const char *SimdInstructionSetsInUse(void) {
|
|||
#error Eigen2-support is only available up to version 3.2. Please go to "http://eigen.tuxfamily.org/index.php?title=Eigen2" for further information
|
||||
#endif
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// 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
|
||||
|
|
@ -364,8 +357,6 @@ using std::ptrdiff_t;
|
|||
#include "src/Core/arch/SSE/PacketMath.h"
|
||||
#include "src/Core/arch/AVX/PacketMath.h"
|
||||
#include "src/Core/arch/AVX512/PacketMath.h"
|
||||
#include "src/Core/arch/SSE/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX/MathFunctions.h"
|
||||
#include "src/Core/arch/AVX512/MathFunctions.h"
|
||||
#elif defined EIGEN_VECTORIZE_AVX
|
||||
// Use AVX for floats and doubles, SSE for integers
|
||||
|
|
@ -418,6 +409,7 @@ using std::ptrdiff_t;
|
|||
// on CUDA devices
|
||||
#include "src/Core/arch/CUDA/Complex.h"
|
||||
|
||||
#include "src/Core/IO.h"
|
||||
#include "src/Core/DenseCoeffsBase.h"
|
||||
#include "src/Core/DenseBase.h"
|
||||
#include "src/Core/MatrixBase.h"
|
||||
|
|
@ -465,7 +457,6 @@ using std::ptrdiff_t;
|
|||
#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/GeneralProduct.h"
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
// 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 EIGEN2SUPPORT_H
|
||||
#define EIGEN2SUPPORT_H
|
||||
|
||||
#if (!defined(EIGEN2_SUPPORT)) || (!defined(EIGEN_CORE_H))
|
||||
#error Eigen2 support must be enabled by defining EIGEN2_SUPPORT before including any Eigen header
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_NO_EIGEN2_DEPRECATED_WARNING
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
|
||||
#warning "Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3. (Define EIGEN_NO_EIGEN2_DEPRECATED_WARNING to disable this warning)"
|
||||
#else
|
||||
#pragma message ("Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3. (Define EIGEN_NO_EIGEN2_DEPRECATED_WARNING to disable this warning)")
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_NO_EIGEN2_DEPRECATED_WARNING
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
/** \ingroup Support_modules
|
||||
* \defgroup Eigen2Support_Module Eigen2 support module
|
||||
*
|
||||
* \warning Eigen2 support is deprecated in Eigen 3.2.x and it will be removed in Eigen 3.3.
|
||||
*
|
||||
* This module provides a couple of deprecated functions improving the compatibility with Eigen2.
|
||||
*
|
||||
* To use it, define EIGEN2_SUPPORT before including any Eigen header
|
||||
* \code
|
||||
* #define EIGEN2_SUPPORT
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/Eigen2Support/Macros.h"
|
||||
#include "src/Eigen2Support/Memory.h"
|
||||
#include "src/Eigen2Support/Meta.h"
|
||||
#include "src/Eigen2Support/Lazy.h"
|
||||
#include "src/Eigen2Support/Cwise.h"
|
||||
#include "src/Eigen2Support/CwiseOperators.h"
|
||||
#include "src/Eigen2Support/TriangularSolver.h"
|
||||
#include "src/Eigen2Support/Block.h"
|
||||
#include "src/Eigen2Support/VectorBlock.h"
|
||||
#include "src/Eigen2Support/Minor.h"
|
||||
#include "src/Eigen2Support/MathFunctions.h"
|
||||
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
// Eigen2 used to include iostream
|
||||
#include<iostream>
|
||||
|
||||
#define EIGEN_USING_MATRIX_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_MATRIX_TYPEDEFS_FOR_TYPE(TypeSuffix) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \
|
||||
|
||||
#define EIGEN_USING_MATRIX_TYPEDEFS \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(i) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(f) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(d) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cf) \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cd)
|
||||
|
||||
#define USING_PART_OF_NAMESPACE_EIGEN \
|
||||
EIGEN_USING_MATRIX_TYPEDEFS \
|
||||
using Eigen::Matrix; \
|
||||
using Eigen::MatrixBase; \
|
||||
using Eigen::ei_random; \
|
||||
using Eigen::ei_real; \
|
||||
using Eigen::ei_imag; \
|
||||
using Eigen::ei_conj; \
|
||||
using Eigen::ei_abs; \
|
||||
using Eigen::ei_abs2; \
|
||||
using Eigen::ei_sqrt; \
|
||||
using Eigen::ei_exp; \
|
||||
using Eigen::ei_log; \
|
||||
using Eigen::ei_sin; \
|
||||
using Eigen::ei_cos;
|
||||
|
||||
#endif // EIGEN2SUPPORT_H
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef EIGEN_REGRESSION_MODULE_H
|
||||
#define EIGEN_REGRESSION_MODULE_H
|
||||
|
||||
#ifndef EIGEN2_SUPPORT
|
||||
#error LeastSquares is only available in Eigen2 support mode (define EIGEN2_SUPPORT)
|
||||
#endif
|
||||
|
||||
// exclude from normal eigen3-only documentation
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
|
||||
#include "Core"
|
||||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
#include "Eigenvalues"
|
||||
#include "Geometry"
|
||||
|
||||
/** \defgroup LeastSquares_Module LeastSquares module
|
||||
* This module provides linear regression and related features.
|
||||
*
|
||||
* \code
|
||||
* #include <Eigen/LeastSquares>
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
#include "src/Eigen2Support/LeastSquares.h"
|
||||
|
||||
#include "src/Core/util/ReenableStupidWarnings.h"
|
||||
|
||||
#endif // EIGEN2_SUPPORT
|
||||
|
||||
#endif // EIGEN_REGRESSION_MODULE_H
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
void *qMalloc(size_t size)
|
||||
void *qMalloc(std::size_t size)
|
||||
{
|
||||
return Eigen::internal::aligned_malloc(size);
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ void qFree(void *ptr)
|
|||
Eigen::internal::aligned_free(ptr);
|
||||
}
|
||||
|
||||
void *qRealloc(void *ptr, size_t size)
|
||||
void *qRealloc(void *ptr, std::size_t size)
|
||||
{
|
||||
void* newPtr = Eigen::internal::aligned_malloc(size);
|
||||
memcpy(newPtr, ptr, size);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@
|
|||
|
||||
#include "SparseCore"
|
||||
#include "OrderingMethods"
|
||||
#ifndef EIGEN_MPL2_ONLY
|
||||
#include "SparseCholesky"
|
||||
#endif
|
||||
#include "SparseLU"
|
||||
#include "SparseQR"
|
||||
#include "IterativeLinearSolvers"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include "Core"
|
||||
#include <deque>
|
||||
|
||||
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */
|
||||
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */
|
||||
|
||||
#define EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(...)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include "Core"
|
||||
#include <list>
|
||||
|
||||
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */
|
||||
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */
|
||||
|
||||
#define EIGEN_DEFINE_STL_LIST_SPECIALIZATION(...)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include "Core"
|
||||
#include <vector>
|
||||
|
||||
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */
|
||||
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && (EIGEN_MAX_STATIC_ALIGN_BYTES<=16) /* MSVC auto aligns up to 16 bytes in 64 bit builds */
|
||||
|
||||
#define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* LLt decomposition based on LAPACKE_?potrf function.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_LLT_MKL_H
|
||||
#define EIGEN_LLT_MKL_H
|
||||
|
||||
#include "Eigen/src/Core/util/MKL_support.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Scalar> struct mkl_llt;
|
||||
|
||||
#define EIGEN_MKL_LLT(EIGTYPE, MKLTYPE, MKLPREFIX) \
|
||||
template<> struct mkl_llt<EIGTYPE> \
|
||||
{ \
|
||||
template<typename MatrixType> \
|
||||
static inline typename MatrixType::Index potrf(MatrixType& m, char uplo) \
|
||||
{ \
|
||||
lapack_int matrix_order; \
|
||||
lapack_int size, lda, info, StorageOrder; \
|
||||
EIGTYPE* a; \
|
||||
eigen_assert(m.rows()==m.cols()); \
|
||||
/* Set up parameters for ?potrf */ \
|
||||
size = m.rows(); \
|
||||
StorageOrder = MatrixType::Flags&RowMajorBit?RowMajor:ColMajor; \
|
||||
matrix_order = StorageOrder==RowMajor ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \
|
||||
a = &(m.coeffRef(0,0)); \
|
||||
lda = m.outerStride(); \
|
||||
\
|
||||
info = LAPACKE_##MKLPREFIX##potrf( matrix_order, uplo, size, (MKLTYPE*)a, lda ); \
|
||||
info = (info==0) ? -1 : info>0 ? info-1 : size; \
|
||||
return info; \
|
||||
} \
|
||||
}; \
|
||||
template<> struct llt_inplace<EIGTYPE, Lower> \
|
||||
{ \
|
||||
template<typename MatrixType> \
|
||||
static typename MatrixType::Index blocked(MatrixType& m) \
|
||||
{ \
|
||||
return mkl_llt<EIGTYPE>::potrf(m, 'L'); \
|
||||
} \
|
||||
template<typename MatrixType, typename VectorType> \
|
||||
static typename MatrixType::Index rankUpdate(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) \
|
||||
{ return Eigen::internal::llt_rank_update_lower(mat, vec, sigma); } \
|
||||
}; \
|
||||
template<> struct llt_inplace<EIGTYPE, Upper> \
|
||||
{ \
|
||||
template<typename MatrixType> \
|
||||
static typename MatrixType::Index blocked(MatrixType& m) \
|
||||
{ \
|
||||
return mkl_llt<EIGTYPE>::potrf(m, 'U'); \
|
||||
} \
|
||||
template<typename MatrixType, typename VectorType> \
|
||||
static typename MatrixType::Index rankUpdate(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) \
|
||||
{ \
|
||||
Transpose<MatrixType> matt(mat); \
|
||||
return llt_inplace<EIGTYPE, Lower>::rankUpdate(matt, vec.conjugate(), sigma); \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_LLT(double, double, d)
|
||||
EIGEN_MKL_LLT(float, float, s)
|
||||
EIGEN_MKL_LLT(dcomplex, MKL_Complex16, z)
|
||||
EIGEN_MKL_LLT(scomplex, MKL_Complex8, c)
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_LLT_MKL_H
|
||||
|
|
@ -32,7 +32,7 @@ template<> struct cholmod_configure_matrix<std::complex<double> > {
|
|||
}
|
||||
};
|
||||
|
||||
// Other scalar types are not yet supported by Cholmod
|
||||
// Other scalar types are not yet suppotred by Cholmod
|
||||
// template<> struct cholmod_configure_matrix<float> {
|
||||
// template<typename CholmodType>
|
||||
// static void run(CholmodType& mat) {
|
||||
|
|
@ -124,9 +124,6 @@ cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Sca
|
|||
|
||||
if(UpLo==Upper) res.stype = 1;
|
||||
if(UpLo==Lower) res.stype = -1;
|
||||
// swap stype for rowmajor matrices (only works for real matrices)
|
||||
EIGEN_STATIC_ASSERT((_Options & RowMajorBit) == 0 || NumTraits<_Scalar>::IsComplex == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
|
||||
if(_Options & RowMajorBit) res.stype *=-1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -162,44 +159,6 @@ MappedSparseMatrix<Scalar,Flags,StorageIndex> viewAsEigen(cholmod_sparse& cm)
|
|||
static_cast<StorageIndex*>(cm.p), static_cast<StorageIndex*>(cm.i),static_cast<Scalar*>(cm.x) );
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
// template specializations for int and long that call the correct cholmod method
|
||||
|
||||
#define EIGEN_CHOLMOD_SPECIALIZE0(ret, name) \
|
||||
template<typename _StorageIndex> ret cm_ ## name (cholmod_common &Common) { return cholmod_ ## name (&Common); } \
|
||||
template<> ret cm_ ## name<long> (cholmod_common &Common) { return cholmod_l_ ## name (&Common); }
|
||||
|
||||
#define EIGEN_CHOLMOD_SPECIALIZE1(ret, name, t1, a1) \
|
||||
template<typename _StorageIndex> ret cm_ ## name (t1& a1, cholmod_common &Common) { return cholmod_ ## name (&a1, &Common); } \
|
||||
template<> ret cm_ ## name<long> (t1& a1, cholmod_common &Common) { return cholmod_l_ ## name (&a1, &Common); }
|
||||
|
||||
EIGEN_CHOLMOD_SPECIALIZE0(int, start)
|
||||
EIGEN_CHOLMOD_SPECIALIZE0(int, finish)
|
||||
|
||||
EIGEN_CHOLMOD_SPECIALIZE1(int, free_factor, cholmod_factor*, L)
|
||||
EIGEN_CHOLMOD_SPECIALIZE1(int, free_dense, cholmod_dense*, X)
|
||||
EIGEN_CHOLMOD_SPECIALIZE1(int, free_sparse, cholmod_sparse*, A)
|
||||
|
||||
EIGEN_CHOLMOD_SPECIALIZE1(cholmod_factor*, analyze, cholmod_sparse, A)
|
||||
|
||||
template<typename _StorageIndex> cholmod_dense* cm_solve (int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common &Common) { return cholmod_solve (sys, &L, &B, &Common); }
|
||||
template<> cholmod_dense* cm_solve<long> (int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common &Common) { return cholmod_l_solve (sys, &L, &B, &Common); }
|
||||
|
||||
template<typename _StorageIndex> cholmod_sparse* cm_spsolve (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_spsolve (sys, &L, &B, &Common); }
|
||||
template<> cholmod_sparse* cm_spsolve<long> (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_l_spsolve (sys, &L, &B, &Common); }
|
||||
|
||||
template<typename _StorageIndex>
|
||||
int cm_factorize_p (cholmod_sparse* A, double beta[2], _StorageIndex* fset, size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_factorize_p (A, beta, fset, fsize, L, &Common); }
|
||||
template<>
|
||||
int cm_factorize_p<long> (cholmod_sparse* A, double beta[2], long* fset, size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_l_factorize_p (A, beta, fset, fsize, L, &Common); }
|
||||
|
||||
#undef EIGEN_CHOLMOD_SPECIALIZE0
|
||||
#undef EIGEN_CHOLMOD_SPECIALIZE1
|
||||
|
||||
} // namespace internal
|
||||
|
||||
|
||||
enum CholmodMode {
|
||||
CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt
|
||||
};
|
||||
|
|
@ -236,7 +195,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
|
||||
internal::cm_start<StorageIndex>(m_cholmod);
|
||||
cholmod_start(&m_cholmod);
|
||||
}
|
||||
|
||||
explicit CholmodBase(const MatrixType& matrix)
|
||||
|
|
@ -244,15 +203,15 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY);
|
||||
m_shiftOffset[0] = m_shiftOffset[1] = 0.0;
|
||||
internal::cm_start<StorageIndex>(m_cholmod);
|
||||
cholmod_start(&m_cholmod);
|
||||
compute(matrix);
|
||||
}
|
||||
|
||||
~CholmodBase()
|
||||
{
|
||||
if(m_cholmodFactor)
|
||||
internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
|
||||
internal::cm_finish<StorageIndex>(m_cholmod);
|
||||
cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
|
||||
cholmod_finish(&m_cholmod);
|
||||
}
|
||||
|
||||
inline StorageIndex cols() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); }
|
||||
|
|
@ -260,7 +219,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||
|
||||
/** \brief Reports whether previous computation was successful.
|
||||
*
|
||||
* \returns \c Success if computation was successful,
|
||||
* \returns \c Success if computation was succesful,
|
||||
* \c NumericalIssue if the matrix.appears to be negative.
|
||||
*/
|
||||
ComputationInfo info() const
|
||||
|
|
@ -287,11 +246,11 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||
{
|
||||
if(m_cholmodFactor)
|
||||
{
|
||||
internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod);
|
||||
cholmod_free_factor(&m_cholmodFactor, &m_cholmod);
|
||||
m_cholmodFactor = 0;
|
||||
}
|
||||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
|
||||
m_cholmodFactor = internal::cm_analyze<StorageIndex>(A, m_cholmod);
|
||||
m_cholmodFactor = cholmod_analyze(&A, &m_cholmod);
|
||||
|
||||
this->m_isInitialized = true;
|
||||
this->m_info = Success;
|
||||
|
|
@ -309,7 +268,7 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||
{
|
||||
eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
|
||||
cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>());
|
||||
internal::cm_factorize_p<StorageIndex>(&A, m_shiftOffset, 0, 0, m_cholmodFactor, m_cholmod);
|
||||
cholmod_factorize_p(&A, m_shiftOffset, 0, 0, m_cholmodFactor, &m_cholmod);
|
||||
|
||||
// If the factorization failed, minor is the column at which it did. On success minor == n.
|
||||
this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue);
|
||||
|
|
@ -330,20 +289,19 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||
EIGEN_UNUSED_VARIABLE(size);
|
||||
eigen_assert(size==b.rows());
|
||||
|
||||
// Cholmod needs column-major storage without inner-stride, which corresponds to the default behavior of Ref.
|
||||
// Cholmod needs column-major stoarge without inner-stride, which corresponds to the default behavior of Ref.
|
||||
Ref<const Matrix<typename Rhs::Scalar,Dynamic,Dynamic,ColMajor> > b_ref(b.derived());
|
||||
|
||||
cholmod_dense b_cd = viewAsCholmod(b_ref);
|
||||
cholmod_dense* x_cd = internal::cm_solve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cd, m_cholmod);
|
||||
cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod);
|
||||
if(!x_cd)
|
||||
{
|
||||
this->m_info = NumericalIssue;
|
||||
return;
|
||||
}
|
||||
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
|
||||
// NOTE Actually, the copy can be avoided by calling cholmod_solve2 instead of cholmod_solve
|
||||
dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols());
|
||||
internal::cm_free_dense<StorageIndex>(x_cd, m_cholmod);
|
||||
cholmod_free_dense(&x_cd, &m_cholmod);
|
||||
}
|
||||
|
||||
/** \internal */
|
||||
|
|
@ -358,16 +316,15 @@ class CholmodBase : public SparseSolverBase<Derived>
|
|||
// note: cs stands for Cholmod Sparse
|
||||
Ref<SparseMatrix<typename RhsDerived::Scalar,ColMajor,typename RhsDerived::StorageIndex> > b_ref(b.const_cast_derived());
|
||||
cholmod_sparse b_cs = viewAsCholmod(b_ref);
|
||||
cholmod_sparse* x_cs = internal::cm_spsolve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cs, m_cholmod);
|
||||
cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod);
|
||||
if(!x_cs)
|
||||
{
|
||||
this->m_info = NumericalIssue;
|
||||
return;
|
||||
}
|
||||
// TODO optimize this copy by swapping when possible (be careful with alignment, etc.)
|
||||
// NOTE cholmod_spsolve in fact just calls the dense solver for blocks of 4 columns at a time (similar to Eigen's sparse solver)
|
||||
dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs);
|
||||
internal::cm_free_sparse<StorageIndex>(x_cs, m_cholmod);
|
||||
cholmod_free_sparse(&x_cs, &m_cholmod);
|
||||
}
|
||||
#endif // EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
|
|
|
|||
|
|
@ -231,10 +231,16 @@ class Array
|
|||
: Base(other)
|
||||
{ }
|
||||
|
||||
private:
|
||||
struct PrivateType {};
|
||||
public:
|
||||
|
||||
/** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Array(const EigenBase<OtherDerived> &other)
|
||||
EIGEN_STRONG_INLINE Array(const EigenBase<OtherDerived> &other,
|
||||
typename internal::enable_if<internal::is_convertible<typename OtherDerived::Scalar,Scalar>::value,
|
||||
PrivateType>::type = PrivateType())
|
||||
: Base(other.derived())
|
||||
{ }
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ template<typename Derived> class ArrayBase
|
|||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
|
||||
ArrayBase<Derived>::operator-=(const ArrayBase<OtherDerived> &other)
|
||||
{
|
||||
call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>());
|
||||
|
|
@ -188,7 +188,7 @@ ArrayBase<Derived>::operator-=(const ArrayBase<OtherDerived> &other)
|
|||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
|
||||
ArrayBase<Derived>::operator+=(const ArrayBase<OtherDerived>& other)
|
||||
{
|
||||
call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
|
||||
|
|
@ -201,7 +201,7 @@ ArrayBase<Derived>::operator+=(const ArrayBase<OtherDerived>& other)
|
|||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
|
||||
ArrayBase<Derived>::operator*=(const ArrayBase<OtherDerived>& other)
|
||||
{
|
||||
call_assignment(derived(), other.derived(), internal::mul_assign_op<Scalar,typename OtherDerived::Scalar>());
|
||||
|
|
@ -214,7 +214,7 @@ ArrayBase<Derived>::operator*=(const ArrayBase<OtherDerived>& other)
|
|||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived &
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived &
|
||||
ArrayBase<Derived>::operator/=(const ArrayBase<OtherDerived>& other)
|
||||
{
|
||||
call_assignment(derived(), other.derived(), internal::div_assign_op<Scalar,typename OtherDerived::Scalar>());
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ struct traits<ArrayWrapper<ExpressionType> >
|
|||
// Let's remove NestByRefBit
|
||||
enum {
|
||||
Flags0 = traits<typename remove_all<typename ExpressionType::Nested>::type >::Flags,
|
||||
Flags = Flags0 & ~NestByRefBit
|
||||
LvalueBitFlag = is_lvalue<ExpressionType>::value ? LvalueBit : 0,
|
||||
Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -129,7 +130,8 @@ struct traits<MatrixWrapper<ExpressionType> >
|
|||
// Let's remove NestByRefBit
|
||||
enum {
|
||||
Flags0 = traits<typename remove_all<typename ExpressionType::Nested>::type >::Flags,
|
||||
Flags = Flags0 & ~NestByRefBit
|
||||
LvalueBitFlag = is_lvalue<ExpressionType>::value ? LvalueBit : 0,
|
||||
Flags = (Flags0 & ~(NestByRefBit | LvalueBit)) | LvalueBitFlag
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -515,7 +515,7 @@ struct dense_assignment_loop<Kernel, LinearTraversal, CompleteUnrolling>
|
|||
template<typename Kernel>
|
||||
struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static inline void run(Kernel &kernel)
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
|
||||
{
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
typedef typename Kernel::PacketType PacketType;
|
||||
|
|
@ -563,7 +563,7 @@ struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
|
|||
template<typename Kernel>
|
||||
struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, InnerUnrolling>
|
||||
{
|
||||
EIGEN_DEVICE_FUNC static inline void run(Kernel &kernel)
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
|
||||
{
|
||||
typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
|
||||
typedef typename Kernel::PacketType PacketType;
|
||||
|
|
@ -701,6 +701,26 @@ protected:
|
|||
* Part 5 : Entry point for dense rectangular assignment
|
||||
***************************************************************************/
|
||||
|
||||
template<typename DstXprType,typename SrcXprType, typename Functor>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const Functor &/*func*/)
|
||||
{
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(dst);
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(src);
|
||||
eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
|
||||
}
|
||||
|
||||
template<typename DstXprType,typename SrcXprType, typename T1, typename T2>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const internal::assign_op<T1,T2> &/*func*/)
|
||||
{
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if(((dst.rows()!=dstRows) || (dst.cols()!=dstCols)))
|
||||
dst.resize(dstRows, dstCols);
|
||||
eigen_assert(dst.rows() == dstRows && dst.cols() == dstCols);
|
||||
}
|
||||
|
||||
template<typename DstXprType, typename SrcXprType, typename Functor>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src, const Functor &func)
|
||||
{
|
||||
|
|
@ -711,10 +731,7 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType
|
|||
|
||||
// NOTE To properly handle A = (A*A.transpose())/s with A rectangular,
|
||||
// we need to resize the destination after the source evaluator has been created.
|
||||
Index dstRows = src.rows();
|
||||
Index dstCols = src.cols();
|
||||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
resize_if_allowed(dst, src, func);
|
||||
|
||||
DstEvaluatorType dstEvaluator(dst);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,54 +14,56 @@ namespace Eigen {
|
|||
|
||||
namespace internal {
|
||||
|
||||
template<typename Derived, int UnrollCount, int Rows>
|
||||
template<typename Derived, int UnrollCount>
|
||||
struct all_unroller
|
||||
{
|
||||
typedef typename Derived::ExpressionTraits Traits;
|
||||
enum {
|
||||
col = (UnrollCount-1) / Rows,
|
||||
row = (UnrollCount-1) % Rows
|
||||
col = (UnrollCount-1) / Traits::RowsAtCompileTime,
|
||||
row = (UnrollCount-1) % Traits::RowsAtCompileTime
|
||||
};
|
||||
|
||||
static inline bool run(const Derived &mat)
|
||||
{
|
||||
return all_unroller<Derived, UnrollCount-1, Rows>::run(mat) && mat.coeff(row, col);
|
||||
return all_unroller<Derived, UnrollCount-1>::run(mat) && mat.coeff(row, col);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived, int Rows>
|
||||
struct all_unroller<Derived, 0, Rows>
|
||||
template<typename Derived>
|
||||
struct all_unroller<Derived, 0>
|
||||
{
|
||||
static inline bool run(const Derived &/*mat*/) { return true; }
|
||||
};
|
||||
|
||||
template<typename Derived, int Rows>
|
||||
struct all_unroller<Derived, Dynamic, Rows>
|
||||
template<typename Derived>
|
||||
struct all_unroller<Derived, Dynamic>
|
||||
{
|
||||
static inline bool run(const Derived &) { return false; }
|
||||
};
|
||||
|
||||
template<typename Derived, int UnrollCount, int Rows>
|
||||
template<typename Derived, int UnrollCount>
|
||||
struct any_unroller
|
||||
{
|
||||
typedef typename Derived::ExpressionTraits Traits;
|
||||
enum {
|
||||
col = (UnrollCount-1) / Rows,
|
||||
row = (UnrollCount-1) % Rows
|
||||
col = (UnrollCount-1) / Traits::RowsAtCompileTime,
|
||||
row = (UnrollCount-1) % Traits::RowsAtCompileTime
|
||||
};
|
||||
|
||||
static inline bool run(const Derived &mat)
|
||||
{
|
||||
return any_unroller<Derived, UnrollCount-1, Rows>::run(mat) || mat.coeff(row, col);
|
||||
return any_unroller<Derived, UnrollCount-1>::run(mat) || mat.coeff(row, col);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived, int Rows>
|
||||
struct any_unroller<Derived, 0, Rows>
|
||||
template<typename Derived>
|
||||
struct any_unroller<Derived, 0>
|
||||
{
|
||||
static inline bool run(const Derived & /*mat*/) { return false; }
|
||||
};
|
||||
|
||||
template<typename Derived, int Rows>
|
||||
struct any_unroller<Derived, Dynamic, Rows>
|
||||
template<typename Derived>
|
||||
struct any_unroller<Derived, Dynamic>
|
||||
{
|
||||
static inline bool run(const Derived &) { return false; }
|
||||
};
|
||||
|
|
@ -85,7 +87,7 @@ inline bool DenseBase<Derived>::all() const
|
|||
};
|
||||
Evaluator evaluator(derived());
|
||||
if(unroll)
|
||||
return internal::all_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic, internal::traits<Derived>::RowsAtCompileTime>::run(evaluator);
|
||||
return internal::all_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(evaluator);
|
||||
else
|
||||
{
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
|
|
@ -109,7 +111,7 @@ inline bool DenseBase<Derived>::any() const
|
|||
};
|
||||
Evaluator evaluator(derived());
|
||||
if(unroll)
|
||||
return internal::any_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic, internal::traits<Derived>::RowsAtCompileTime>::run(evaluator);
|
||||
return internal::any_unroller<Evaluator, unroll ? int(SizeAtCompileTime) : Dynamic>::run(evaluator);
|
||||
else
|
||||
{
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ struct evaluator<const T>
|
|||
// ---------- base class for all evaluators ----------
|
||||
|
||||
template<typename ExpressionType>
|
||||
struct evaluator_base
|
||||
struct evaluator_base : public noncopyable
|
||||
{
|
||||
// TODO that's not very nice to have to propagate all these traits. They are currently only needed to handle outer,inner indices.
|
||||
typedef traits<ExpressionType> ExpressionTraits;
|
||||
|
|
@ -114,14 +114,6 @@ struct evaluator_base
|
|||
enum {
|
||||
Alignment = 0
|
||||
};
|
||||
// noncopyable:
|
||||
// Don't make this class inherit noncopyable as this kills EBO (Empty Base Optimization)
|
||||
// and make complex evaluator much larger than then should do.
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE evaluator_base() {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ~evaluator_base() {}
|
||||
private:
|
||||
EIGEN_DEVICE_FUNC evaluator_base(const evaluator_base&);
|
||||
EIGEN_DEVICE_FUNC const evaluator_base& operator=(const evaluator_base&);
|
||||
};
|
||||
|
||||
// -------------------- Matrix and Array --------------------
|
||||
|
|
@ -131,27 +123,6 @@ private:
|
|||
// Here we directly specialize evaluator. This is not really a unary expression, and it is, by definition, dense,
|
||||
// so no need for more sophisticated dispatching.
|
||||
|
||||
// this helper permits to completely eliminate m_outerStride if it is known at compiletime.
|
||||
template<typename Scalar,int OuterStride> class plainobjectbase_evaluator_data {
|
||||
public:
|
||||
plainobjectbase_evaluator_data(const Scalar* ptr, Index outerStride) : data(ptr)
|
||||
{
|
||||
EIGEN_ONLY_USED_FOR_DEBUG(outerStride);
|
||||
eigen_internal_assert(outerStride==OuterStride);
|
||||
}
|
||||
Index outerStride() const { return OuterStride; }
|
||||
const Scalar *data;
|
||||
};
|
||||
|
||||
template<typename Scalar> class plainobjectbase_evaluator_data<Scalar,Dynamic> {
|
||||
public:
|
||||
plainobjectbase_evaluator_data(const Scalar* ptr, Index outerStride) : data(ptr), m_outerStride(outerStride) {}
|
||||
Index outerStride() const { return m_outerStride; }
|
||||
const Scalar *data;
|
||||
protected:
|
||||
Index m_outerStride;
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct evaluator<PlainObjectBase<Derived> >
|
||||
: evaluator_base<Derived>
|
||||
|
|
@ -170,21 +141,18 @@ struct evaluator<PlainObjectBase<Derived> >
|
|||
Flags = traits<Derived>::EvaluatorFlags,
|
||||
Alignment = traits<Derived>::Alignment
|
||||
};
|
||||
enum {
|
||||
// We do not need to know the outer stride for vectors
|
||||
OuterStrideAtCompileTime = IsVectorAtCompileTime ? 0
|
||||
: int(IsRowMajor) ? ColsAtCompileTime
|
||||
: RowsAtCompileTime
|
||||
};
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC evaluator()
|
||||
: m_d(0,OuterStrideAtCompileTime)
|
||||
: m_data(0),
|
||||
m_outerStride(IsVectorAtCompileTime ? 0
|
||||
: int(IsRowMajor) ? ColsAtCompileTime
|
||||
: RowsAtCompileTime)
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(const PlainObjectType& m)
|
||||
: m_d(m.data(),IsVectorAtCompileTime ? 0 : m.outerStride())
|
||||
: m_data(m.data()), m_outerStride(IsVectorAtCompileTime ? 0 : m.outerStride())
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
|
@ -193,30 +161,30 @@ struct evaluator<PlainObjectBase<Derived> >
|
|||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
if (IsRowMajor)
|
||||
return m_d.data[row * m_d.outerStride() + col];
|
||||
return m_data[row * m_outerStride.value() + col];
|
||||
else
|
||||
return m_d.data[row + col * m_d.outerStride()];
|
||||
return m_data[row + col * m_outerStride.value()];
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_d.data[index];
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
if (IsRowMajor)
|
||||
return const_cast<Scalar*>(m_d.data)[row * m_d.outerStride() + col];
|
||||
return const_cast<Scalar*>(m_data)[row * m_outerStride.value() + col];
|
||||
else
|
||||
return const_cast<Scalar*>(m_d.data)[row + col * m_d.outerStride()];
|
||||
return const_cast<Scalar*>(m_data)[row + col * m_outerStride.value()];
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index index)
|
||||
{
|
||||
return const_cast<Scalar*>(m_d.data)[index];
|
||||
return const_cast<Scalar*>(m_data)[index];
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
|
|
@ -224,16 +192,16 @@ struct evaluator<PlainObjectBase<Derived> >
|
|||
PacketType packet(Index row, Index col) const
|
||||
{
|
||||
if (IsRowMajor)
|
||||
return ploadt<PacketType, LoadMode>(m_d.data + row * m_d.outerStride() + col);
|
||||
return ploadt<PacketType, LoadMode>(m_data + row * m_outerStride.value() + col);
|
||||
else
|
||||
return ploadt<PacketType, LoadMode>(m_d.data + row + col * m_d.outerStride());
|
||||
return ploadt<PacketType, LoadMode>(m_data + row + col * m_outerStride.value());
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index index) const
|
||||
{
|
||||
return ploadt<PacketType, LoadMode>(m_d.data + index);
|
||||
return ploadt<PacketType, LoadMode>(m_data + index);
|
||||
}
|
||||
|
||||
template<int StoreMode,typename PacketType>
|
||||
|
|
@ -242,22 +210,26 @@ struct evaluator<PlainObjectBase<Derived> >
|
|||
{
|
||||
if (IsRowMajor)
|
||||
return pstoret<Scalar, PacketType, StoreMode>
|
||||
(const_cast<Scalar*>(m_d.data) + row * m_d.outerStride() + col, x);
|
||||
(const_cast<Scalar*>(m_data) + row * m_outerStride.value() + col, x);
|
||||
else
|
||||
return pstoret<Scalar, PacketType, StoreMode>
|
||||
(const_cast<Scalar*>(m_d.data) + row + col * m_d.outerStride(), x);
|
||||
(const_cast<Scalar*>(m_data) + row + col * m_outerStride.value(), x);
|
||||
}
|
||||
|
||||
template<int StoreMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
void writePacket(Index index, const PacketType& x)
|
||||
{
|
||||
return pstoret<Scalar, PacketType, StoreMode>(const_cast<Scalar*>(m_d.data) + index, x);
|
||||
return pstoret<Scalar, PacketType, StoreMode>(const_cast<Scalar*>(m_data) + index, x);
|
||||
}
|
||||
|
||||
protected:
|
||||
const Scalar *m_data;
|
||||
|
||||
plainobjectbase_evaluator_data<Scalar,OuterStrideAtCompileTime> m_d;
|
||||
// We do not need to know the outer stride for vectors
|
||||
variable_if_dynamic<Index, IsVectorAtCompileTime ? 0
|
||||
: int(IsRowMajor) ? ColsAtCompileTime
|
||||
: RowsAtCompileTime> m_outerStride;
|
||||
};
|
||||
|
||||
template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
|
||||
|
|
@ -555,7 +527,9 @@ struct unary_evaluator<CwiseUnaryOp<UnaryOp, ArgType>, IndexBased >
|
|||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
explicit unary_evaluator(const XprType& op) : m_d(op)
|
||||
explicit unary_evaluator(const XprType& op)
|
||||
: m_functor(op.functor()),
|
||||
m_argImpl(op.nestedExpression())
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<UnaryOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
|
|
@ -566,43 +540,32 @@ struct unary_evaluator<CwiseUnaryOp<UnaryOp, ArgType>, IndexBased >
|
|||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return m_d.func()(m_d.argImpl.coeff(row, col));
|
||||
return m_functor(m_argImpl.coeff(row, col));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_d.func()(m_d.argImpl.coeff(index));
|
||||
return m_functor(m_argImpl.coeff(index));
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index row, Index col) const
|
||||
{
|
||||
return m_d.func().packetOp(m_d.argImpl.template packet<LoadMode, PacketType>(row, col));
|
||||
return m_functor.packetOp(m_argImpl.template packet<LoadMode, PacketType>(row, col));
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index index) const
|
||||
{
|
||||
return m_d.func().packetOp(m_d.argImpl.template packet<LoadMode, PacketType>(index));
|
||||
return m_functor.packetOp(m_argImpl.template packet<LoadMode, PacketType>(index));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// this helper permits to completely eliminate the functor if it is empty
|
||||
class Data : private UnaryOp
|
||||
{
|
||||
public:
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Data(const XprType& xpr) : UnaryOp(xpr.functor()), argImpl(xpr.nestedExpression()) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const UnaryOp& func() const { return static_cast<const UnaryOp&>(*this); }
|
||||
evaluator<ArgType> argImpl;
|
||||
};
|
||||
|
||||
Data m_d;
|
||||
const UnaryOp m_functor;
|
||||
evaluator<ArgType> m_argImpl;
|
||||
};
|
||||
|
||||
// -------------------- CwiseTernaryOp --------------------
|
||||
|
|
@ -646,7 +609,11 @@ struct ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3>, IndexBased
|
|||
evaluator<Arg3>::Alignment)
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit ternary_evaluator(const XprType& xpr) : m_d(xpr)
|
||||
EIGEN_DEVICE_FUNC explicit ternary_evaluator(const XprType& xpr)
|
||||
: m_functor(xpr.functor()),
|
||||
m_arg1Impl(xpr.arg1()),
|
||||
m_arg2Impl(xpr.arg2()),
|
||||
m_arg3Impl(xpr.arg3())
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<TernaryOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
|
|
@ -657,47 +624,38 @@ struct ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3>, IndexBased
|
|||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return m_d.func()(m_d.arg1Impl.coeff(row, col), m_d.arg2Impl.coeff(row, col), m_d.arg3Impl.coeff(row, col));
|
||||
return m_functor(m_arg1Impl.coeff(row, col), m_arg2Impl.coeff(row, col), m_arg3Impl.coeff(row, col));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_d.func()(m_d.arg1Impl.coeff(index), m_d.arg2Impl.coeff(index), m_d.arg3Impl.coeff(index));
|
||||
return m_functor(m_arg1Impl.coeff(index), m_arg2Impl.coeff(index), m_arg3Impl.coeff(index));
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index row, Index col) const
|
||||
{
|
||||
return m_d.func().packetOp(m_d.arg1Impl.template packet<LoadMode,PacketType>(row, col),
|
||||
m_d.arg2Impl.template packet<LoadMode,PacketType>(row, col),
|
||||
m_d.arg3Impl.template packet<LoadMode,PacketType>(row, col));
|
||||
return m_functor.packetOp(m_arg1Impl.template packet<LoadMode,PacketType>(row, col),
|
||||
m_arg2Impl.template packet<LoadMode,PacketType>(row, col),
|
||||
m_arg3Impl.template packet<LoadMode,PacketType>(row, col));
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index index) const
|
||||
{
|
||||
return m_d.func().packetOp(m_d.arg1Impl.template packet<LoadMode,PacketType>(index),
|
||||
m_d.arg2Impl.template packet<LoadMode,PacketType>(index),
|
||||
m_d.arg3Impl.template packet<LoadMode,PacketType>(index));
|
||||
return m_functor.packetOp(m_arg1Impl.template packet<LoadMode,PacketType>(index),
|
||||
m_arg2Impl.template packet<LoadMode,PacketType>(index),
|
||||
m_arg3Impl.template packet<LoadMode,PacketType>(index));
|
||||
}
|
||||
|
||||
protected:
|
||||
// this helper permits to completely eliminate the functor if it is empty
|
||||
struct Data : private TernaryOp
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Data(const XprType& xpr) : TernaryOp(xpr.functor()), arg1Impl(xpr.arg1()), arg2Impl(xpr.arg2()), arg3Impl(xpr.arg3()) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const TernaryOp& func() const { return static_cast<const TernaryOp&>(*this); }
|
||||
evaluator<Arg1> arg1Impl;
|
||||
evaluator<Arg2> arg2Impl;
|
||||
evaluator<Arg3> arg3Impl;
|
||||
};
|
||||
|
||||
Data m_d;
|
||||
const TernaryOp m_functor;
|
||||
evaluator<Arg1> m_arg1Impl;
|
||||
evaluator<Arg2> m_arg2Impl;
|
||||
evaluator<Arg3> m_arg3Impl;
|
||||
};
|
||||
|
||||
// -------------------- CwiseBinaryOp --------------------
|
||||
|
|
@ -738,7 +696,10 @@ struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBase
|
|||
Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<Lhs>::Alignment,evaluator<Rhs>::Alignment)
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit binary_evaluator(const XprType& xpr) : m_d(xpr)
|
||||
EIGEN_DEVICE_FUNC explicit binary_evaluator(const XprType& xpr)
|
||||
: m_functor(xpr.functor()),
|
||||
m_lhsImpl(xpr.lhs()),
|
||||
m_rhsImpl(xpr.rhs())
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
|
|
@ -749,45 +710,35 @@ struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBase
|
|||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return m_d.func()(m_d.lhsImpl.coeff(row, col), m_d.rhsImpl.coeff(row, col));
|
||||
return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_d.func()(m_d.lhsImpl.coeff(index), m_d.rhsImpl.coeff(index));
|
||||
return m_functor(m_lhsImpl.coeff(index), m_rhsImpl.coeff(index));
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index row, Index col) const
|
||||
{
|
||||
return m_d.func().packetOp(m_d.lhsImpl.template packet<LoadMode,PacketType>(row, col),
|
||||
m_d.rhsImpl.template packet<LoadMode,PacketType>(row, col));
|
||||
return m_functor.packetOp(m_lhsImpl.template packet<LoadMode,PacketType>(row, col),
|
||||
m_rhsImpl.template packet<LoadMode,PacketType>(row, col));
|
||||
}
|
||||
|
||||
template<int LoadMode, typename PacketType>
|
||||
EIGEN_STRONG_INLINE
|
||||
PacketType packet(Index index) const
|
||||
{
|
||||
return m_d.func().packetOp(m_d.lhsImpl.template packet<LoadMode,PacketType>(index),
|
||||
m_d.rhsImpl.template packet<LoadMode,PacketType>(index));
|
||||
return m_functor.packetOp(m_lhsImpl.template packet<LoadMode,PacketType>(index),
|
||||
m_rhsImpl.template packet<LoadMode,PacketType>(index));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// this helper permits to completely eliminate the functor if it is empty
|
||||
struct Data : private BinaryOp
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Data(const XprType& xpr) : BinaryOp(xpr.functor()), lhsImpl(xpr.lhs()), rhsImpl(xpr.rhs()) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const BinaryOp& func() const { return static_cast<const BinaryOp&>(*this); }
|
||||
evaluator<Lhs> lhsImpl;
|
||||
evaluator<Rhs> rhsImpl;
|
||||
};
|
||||
|
||||
Data m_d;
|
||||
const BinaryOp m_functor;
|
||||
evaluator<Lhs> m_lhsImpl;
|
||||
evaluator<Rhs> m_rhsImpl;
|
||||
};
|
||||
|
||||
// -------------------- CwiseUnaryView --------------------
|
||||
|
|
@ -806,7 +757,9 @@ struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType>, IndexBased>
|
|||
Alignment = 0 // FIXME it is not very clear why alignment is necessarily lost...
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op) : m_d(op)
|
||||
EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op)
|
||||
: m_unaryOp(op.functor()),
|
||||
m_argImpl(op.nestedExpression())
|
||||
{
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<UnaryOp>::Cost);
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
|
|
@ -818,40 +771,30 @@ struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType>, IndexBased>
|
|||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return m_d.func()(m_d.argImpl.coeff(row, col));
|
||||
return m_unaryOp(m_argImpl.coeff(row, col));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_d.func()(m_d.argImpl.coeff(index));
|
||||
return m_unaryOp(m_argImpl.coeff(index));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
return m_d.func()(m_d.argImpl.coeffRef(row, col));
|
||||
return m_unaryOp(m_argImpl.coeffRef(row, col));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Scalar& coeffRef(Index index)
|
||||
{
|
||||
return m_d.func()(m_d.argImpl.coeffRef(index));
|
||||
return m_unaryOp(m_argImpl.coeffRef(index));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// this helper permits to completely eliminate the functor if it is empty
|
||||
struct Data : private UnaryOp
|
||||
{
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
Data(const XprType& xpr) : UnaryOp(xpr.functor()), argImpl(xpr.nestedExpression()) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
const UnaryOp& func() const { return static_cast<const UnaryOp&>(*this); }
|
||||
evaluator<ArgType> argImpl;
|
||||
};
|
||||
|
||||
Data m_d;
|
||||
const UnaryOp m_unaryOp;
|
||||
evaluator<ArgType> m_argImpl;
|
||||
};
|
||||
|
||||
// -------------------- Map --------------------
|
||||
|
|
@ -1613,9 +1556,7 @@ struct evaluator<Diagonal<ArgType, DiagIndex> >
|
|||
{ }
|
||||
|
||||
typedef typename XprType::Scalar Scalar;
|
||||
// FIXME having to check whether ArgType is sparse here i not very nice.
|
||||
typedef typename internal::conditional<!internal::is_same<typename ArgType::StorageKind,Sparse>::value,
|
||||
typename XprType::CoeffReturnType,Scalar>::type CoeffReturnType;
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
CoeffReturnType coeff(Index row, Index) const
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ struct traits<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
|
|||
typedef typename remove_reference<LhsNested>::type _LhsNested;
|
||||
typedef typename remove_reference<RhsNested>::type _RhsNested;
|
||||
enum {
|
||||
Flags = _LhsNested::Flags & RowMajorBit
|
||||
Flags = cwise_promote_storage_order<typename traits<Lhs>::StorageKind,typename traits<Rhs>::StorageKind,_LhsNested::Flags & RowMajorBit,_RhsNested::Flags & RowMajorBit>::value
|
||||
};
|
||||
};
|
||||
} // end namespace internal
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ class CwiseNullaryOp : public internal::dense_xpr_base< CwiseNullaryOp<NullaryOp
|
|||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomNullaryOp>
|
||||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
DenseBase<Derived>::NullaryExpr(Index rows, Index cols, const CustomNullaryOp& func)
|
||||
{
|
||||
return CwiseNullaryOp<CustomNullaryOp, PlainObject>(rows, cols, func);
|
||||
|
|
@ -150,7 +150,7 @@ DenseBase<Derived>::NullaryExpr(Index size, const CustomNullaryOp& func)
|
|||
*/
|
||||
template<typename Derived>
|
||||
template<typename CustomNullaryOp>
|
||||
EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CwiseNullaryOp<CustomNullaryOp, typename DenseBase<Derived>::PlainObject>
|
||||
DenseBase<Derived>::NullaryExpr(const CustomNullaryOp& func)
|
||||
{
|
||||
return CwiseNullaryOp<CustomNullaryOp, PlainObject>(RowsAtCompileTime, ColsAtCompileTime, func);
|
||||
|
|
@ -192,7 +192,7 @@ DenseBase<Derived>::Constant(Index rows, Index cols, const Scalar& value)
|
|||
* \sa class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC 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));
|
||||
|
|
@ -208,7 +208,7 @@ DenseBase<Derived>::Constant(Index size, const Scalar& value)
|
|||
* \sa class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
DenseBase<Derived>::Constant(const Scalar& value)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
|
|
@ -220,7 +220,7 @@ DenseBase<Derived>::Constant(const Scalar& value)
|
|||
* \sa LinSpaced(Index,Scalar,Scalar), setLinSpaced(Index,const Scalar&,const Scalar&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
|
|
@ -232,7 +232,7 @@ DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const
|
|||
* \sa LinSpaced(Scalar,Scalar)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
|
|
@ -264,7 +264,7 @@ DenseBase<Derived>::LinSpaced(Sequential_t, const Scalar& low, const Scalar& hig
|
|||
* \sa setLinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
EIGEN_DEVICE_FUNC 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)
|
||||
|
|
@ -276,7 +276,7 @@ DenseBase<Derived>::LinSpaced(Index size, const Scalar& low, const Scalar& high)
|
|||
* Special version for fixed size types which does not require the size parameter.
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::RandomAccessLinSpacedReturnType
|
||||
DenseBase<Derived>::LinSpaced(const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
|
|
@ -286,7 +286,7 @@ DenseBase<Derived>::LinSpaced(const Scalar& low, const Scalar& high)
|
|||
|
||||
/** \returns true if all coefficients in this matrix are approximately equal to \a val, to within precision \a prec */
|
||||
template<typename Derived>
|
||||
bool DenseBase<Derived>::isApproxToConstant
|
||||
EIGEN_DEVICE_FUNC bool DenseBase<Derived>::isApproxToConstant
|
||||
(const Scalar& val, const RealScalar& prec) const
|
||||
{
|
||||
typename internal::nested_eval<Derived,1>::type self(derived());
|
||||
|
|
@ -301,7 +301,7 @@ bool DenseBase<Derived>::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
|
||||
EIGEN_DEVICE_FUNC bool DenseBase<Derived>::isConstant
|
||||
(const Scalar& val, const RealScalar& prec) const
|
||||
{
|
||||
return isApproxToConstant(val, prec);
|
||||
|
|
@ -312,7 +312,7 @@ bool DenseBase<Derived>::isConstant
|
|||
* \sa setConstant(), Constant(), class CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& val)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& val)
|
||||
{
|
||||
setConstant(val);
|
||||
}
|
||||
|
|
@ -322,7 +322,7 @@ EIGEN_STRONG_INLINE void DenseBase<Derived>::fill(const Scalar& val)
|
|||
* \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& val)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& val)
|
||||
{
|
||||
return derived() = Constant(rows(), cols(), val);
|
||||
}
|
||||
|
|
@ -337,7 +337,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setConstant(const Scalar& val)
|
|||
* \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setConstant(Index size, const Scalar& val)
|
||||
{
|
||||
resize(size);
|
||||
|
|
@ -356,7 +356,7 @@ PlainObjectBase<Derived>::setConstant(Index size, const Scalar& val)
|
|||
* \sa MatrixBase::setConstant(const Scalar&), setConstant(Index,const Scalar&), class CwiseNullaryOp, MatrixBase::Constant(const Scalar&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& val)
|
||||
{
|
||||
resize(rows, cols);
|
||||
|
|
@ -380,7 +380,7 @@ PlainObjectBase<Derived>::setConstant(Index rows, Index cols, const Scalar& val)
|
|||
* \sa LinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return derived() = Derived::NullaryExpr(newSize, internal::linspaced_op<Scalar,PacketScalar>(low,high,newSize));
|
||||
|
|
@ -400,7 +400,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(Index newSize, con
|
|||
* \sa LinSpaced(Index,const Scalar&,const Scalar&), setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(const Scalar& low, const Scalar& high)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(const Scalar& low, const Scalar& high)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return setLinSpaced(size(), low, high);
|
||||
|
|
@ -423,7 +423,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setLinSpaced(const Scalar& low,
|
|||
* \sa Zero(), Zero(Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
DenseBase<Derived>::Zero(Index rows, Index cols)
|
||||
{
|
||||
return Constant(rows, cols, Scalar(0));
|
||||
|
|
@ -446,7 +446,7 @@ DenseBase<Derived>::Zero(Index rows, Index cols)
|
|||
* \sa Zero(), Zero(Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
DenseBase<Derived>::Zero(Index size)
|
||||
{
|
||||
return Constant(size, Scalar(0));
|
||||
|
|
@ -463,7 +463,7 @@ DenseBase<Derived>::Zero(Index size)
|
|||
* \sa Zero(Index), Zero(Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
DenseBase<Derived>::Zero()
|
||||
{
|
||||
return Constant(Scalar(0));
|
||||
|
|
@ -478,7 +478,7 @@ DenseBase<Derived>::Zero()
|
|||
* \sa class CwiseNullaryOp, Zero()
|
||||
*/
|
||||
template<typename Derived>
|
||||
bool DenseBase<Derived>::isZero(const RealScalar& prec) const
|
||||
EIGEN_DEVICE_FUNC bool DenseBase<Derived>::isZero(const RealScalar& prec) const
|
||||
{
|
||||
typename internal::nested_eval<Derived,1>::type self(derived());
|
||||
for(Index j = 0; j < cols(); ++j)
|
||||
|
|
@ -496,7 +496,7 @@ bool DenseBase<Derived>::isZero(const RealScalar& prec) const
|
|||
* \sa class CwiseNullaryOp, Zero()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero()
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero()
|
||||
{
|
||||
return setConstant(Scalar(0));
|
||||
}
|
||||
|
|
@ -511,7 +511,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setZero()
|
|||
* \sa DenseBase::setZero(), setZero(Index,Index), class CwiseNullaryOp, DenseBase::Zero()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setZero(Index newSize)
|
||||
{
|
||||
resize(newSize);
|
||||
|
|
@ -529,7 +529,7 @@ PlainObjectBase<Derived>::setZero(Index newSize)
|
|||
* \sa DenseBase::setZero(), setZero(Index), class CwiseNullaryOp, DenseBase::Zero()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setZero(Index rows, Index cols)
|
||||
{
|
||||
resize(rows, cols);
|
||||
|
|
@ -553,7 +553,7 @@ PlainObjectBase<Derived>::setZero(Index rows, Index cols)
|
|||
* \sa Ones(), Ones(Index), isOnes(), class Ones
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
DenseBase<Derived>::Ones(Index rows, Index cols)
|
||||
{
|
||||
return Constant(rows, cols, Scalar(1));
|
||||
|
|
@ -576,7 +576,7 @@ DenseBase<Derived>::Ones(Index rows, Index cols)
|
|||
* \sa Ones(), Ones(Index,Index), isOnes(), class Ones
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
DenseBase<Derived>::Ones(Index newSize)
|
||||
{
|
||||
return Constant(newSize, Scalar(1));
|
||||
|
|
@ -593,7 +593,7 @@ DenseBase<Derived>::Ones(Index newSize)
|
|||
* \sa Ones(Index), Ones(Index,Index), isOnes(), class Ones
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename DenseBase<Derived>::ConstantReturnType
|
||||
DenseBase<Derived>::Ones()
|
||||
{
|
||||
return Constant(Scalar(1));
|
||||
|
|
@ -608,7 +608,7 @@ DenseBase<Derived>::Ones()
|
|||
* \sa class CwiseNullaryOp, Ones()
|
||||
*/
|
||||
template<typename Derived>
|
||||
bool DenseBase<Derived>::isOnes
|
||||
EIGEN_DEVICE_FUNC bool DenseBase<Derived>::isOnes
|
||||
(const RealScalar& prec) const
|
||||
{
|
||||
return isApproxToConstant(Scalar(1), prec);
|
||||
|
|
@ -622,7 +622,7 @@ bool DenseBase<Derived>::isOnes
|
|||
* \sa class CwiseNullaryOp, Ones()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
|
||||
{
|
||||
return setConstant(Scalar(1));
|
||||
}
|
||||
|
|
@ -637,7 +637,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::setOnes()
|
|||
* \sa MatrixBase::setOnes(), setOnes(Index,Index), class CwiseNullaryOp, MatrixBase::Ones()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setOnes(Index newSize)
|
||||
{
|
||||
resize(newSize);
|
||||
|
|
@ -655,7 +655,7 @@ PlainObjectBase<Derived>::setOnes(Index newSize)
|
|||
* \sa MatrixBase::setOnes(), setOnes(Index), class CwiseNullaryOp, MatrixBase::Ones()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived&
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived&
|
||||
PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
|
||||
{
|
||||
resize(rows, cols);
|
||||
|
|
@ -679,7 +679,7 @@ PlainObjectBase<Derived>::setOnes(Index rows, Index cols)
|
|||
* \sa Identity(), setIdentity(), isIdentity()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
|
||||
EIGEN_DEVICE_FUNC 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>());
|
||||
|
|
@ -696,7 +696,7 @@ MatrixBase<Derived>::Identity(Index rows, Index cols)
|
|||
* \sa Identity(Index,Index), setIdentity(), isIdentity()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::IdentityReturnType
|
||||
MatrixBase<Derived>::Identity()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
|
|
@ -771,7 +771,7 @@ struct setIdentity_impl<Derived, true>
|
|||
* \sa class CwiseNullaryOp, Identity(), Identity(Index,Index), isIdentity()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
|
||||
{
|
||||
return internal::setIdentity_impl<Derived>::run(derived());
|
||||
}
|
||||
|
|
@ -787,7 +787,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity()
|
|||
* \sa MatrixBase::setIdentity(), class CwiseNullaryOp, MatrixBase::Identity()
|
||||
*/
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index cols)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index cols)
|
||||
{
|
||||
derived().resize(rows, cols);
|
||||
return setIdentity();
|
||||
|
|
@ -800,7 +800,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::setIdentity(Index rows, Index
|
|||
* \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 newSize, Index i)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index newSize, Index i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return BasisReturnType(SquareMatrixType::Identity(newSize,newSize), i);
|
||||
|
|
@ -815,7 +815,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
|
|||
* \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_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::Unit(Index i)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return BasisReturnType(SquareMatrixType::Identity(),i);
|
||||
|
|
@ -828,7 +828,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
|
|||
* \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()
|
||||
EIGEN_DEVICE_FUNC 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}^*)
|
||||
|
|
@ -838,7 +838,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
|
|||
* \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()
|
||||
EIGEN_DEVICE_FUNC 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}^*)
|
||||
|
|
@ -848,7 +848,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
|
|||
* \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()
|
||||
EIGEN_DEVICE_FUNC 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)
|
||||
|
|
@ -858,7 +858,7 @@ EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBa
|
|||
* \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()
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename MatrixBase<Derived>::BasisReturnType MatrixBase<Derived>::UnitW()
|
||||
{ return Derived::Unit(3); }
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ template<typename Derived> class DenseBase
|
|||
EIGEN_DEVICE_FUNC
|
||||
Derived& operator=(const ReturnByValue<OtherDerived>& func);
|
||||
|
||||
/** \ínternal
|
||||
/** \internal
|
||||
* Copies \a other into *this without evaluating other. \returns a reference to *this.
|
||||
* \deprecated */
|
||||
template<typename OtherDerived>
|
||||
|
|
@ -463,7 +463,17 @@ template<typename Derived> class DenseBase
|
|||
EIGEN_DEVICE_FUNC
|
||||
void visit(Visitor& func) const;
|
||||
|
||||
inline const WithFormat<Derived> format(const IOFormat& fmt) const;
|
||||
/** \returns a WithFormat proxy object allowing to print a matrix the with given
|
||||
* format \a fmt.
|
||||
*
|
||||
* See class IOFormat for some examples.
|
||||
*
|
||||
* \sa class IOFormat, class WithFormat
|
||||
*/
|
||||
inline const WithFormat<Derived> format(const IOFormat& fmt) const
|
||||
{
|
||||
return WithFormat<Derived>(derived(), fmt);
|
||||
}
|
||||
|
||||
/** \returns the unique coefficient of a 1x1 expression */
|
||||
EIGEN_DEVICE_FUNC
|
||||
|
|
@ -474,9 +484,9 @@ template<typename Derived> class DenseBase
|
|||
return derived().coeff(0,0);
|
||||
}
|
||||
|
||||
bool all() const;
|
||||
bool any() const;
|
||||
Index count() const;
|
||||
EIGEN_DEVICE_FUNC bool all() const;
|
||||
EIGEN_DEVICE_FUNC bool any() const;
|
||||
EIGEN_DEVICE_FUNC Index count() const;
|
||||
|
||||
typedef VectorwiseOp<Derived, Horizontal> RowwiseReturnType;
|
||||
typedef const VectorwiseOp<const Derived, Horizontal> ConstRowwiseReturnType;
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
#define EIGEN_MATRIXSTORAGE_H
|
||||
|
||||
#ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
|
||||
#define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN EIGEN_DENSE_STORAGE_CTOR_PLUGIN;
|
||||
#define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X) X; EIGEN_DENSE_STORAGE_CTOR_PLUGIN;
|
||||
#else
|
||||
#define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
|
||||
#define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(X)
|
||||
#endif
|
||||
|
||||
namespace Eigen {
|
||||
|
|
@ -184,12 +184,16 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
|
|||
{
|
||||
internal::plain_array<T,Size,_Options> m_data;
|
||||
public:
|
||||
EIGEN_DEVICE_FUNC DenseStorage() {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage() {
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size)
|
||||
}
|
||||
EIGEN_DEVICE_FUNC
|
||||
explicit DenseStorage(internal::constructor_without_unaligned_array_assert)
|
||||
: m_data(internal::constructor_without_unaligned_array_assert()) {}
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage(const DenseStorage& other) : m_data(other.m_data) {}
|
||||
DenseStorage(const DenseStorage& other) : m_data(other.m_data) {
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = Size)
|
||||
}
|
||||
EIGEN_DEVICE_FUNC
|
||||
DenseStorage& operator=(const DenseStorage& other)
|
||||
{
|
||||
|
|
@ -197,7 +201,7 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt
|
|||
return *this;
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) {
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
eigen_internal_assert(size==rows*cols && rows==_Rows && cols==_Cols);
|
||||
EIGEN_UNUSED_VARIABLE(size);
|
||||
EIGEN_UNUSED_VARIABLE(rows);
|
||||
|
|
@ -343,7 +347,7 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
|
|||
EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index 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
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
eigen_internal_assert(size==rows*cols && rows>=0 && cols >=0);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(const DenseStorage& other)
|
||||
|
|
@ -351,6 +355,7 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
|
|||
, m_rows(other.m_rows)
|
||||
, m_cols(other.m_cols)
|
||||
{
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_rows*m_cols)
|
||||
internal::smart_copy(other.m_data, other.m_data+other.m_rows*other.m_cols, m_data);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
|
|
@ -403,7 +408,7 @@ template<typename T, int _Options> class DenseStorage<T, Dynamic, Dynamic, Dynam
|
|||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
}
|
||||
m_rows = rows;
|
||||
m_cols = cols;
|
||||
|
|
@ -422,7 +427,7 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
|
|||
explicit DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_cols(0) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_cols(cols)
|
||||
{
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
eigen_internal_assert(size==rows*cols && rows==_Rows && cols >=0);
|
||||
EIGEN_UNUSED_VARIABLE(rows);
|
||||
}
|
||||
|
|
@ -430,6 +435,7 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
|
|||
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(_Rows*other.m_cols))
|
||||
, m_cols(other.m_cols)
|
||||
{
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_cols*_Rows)
|
||||
internal::smart_copy(other.m_data, other.m_data+_Rows*m_cols, m_data);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
|
|
@ -477,7 +483,7 @@ template<typename T, int _Rows, int _Options> class DenseStorage<T, Dynamic, _Ro
|
|||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
}
|
||||
m_cols = cols;
|
||||
}
|
||||
|
|
@ -495,7 +501,7 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
|
|||
explicit DenseStorage(internal::constructor_without_unaligned_array_assert) : m_data(0), m_rows(0) {}
|
||||
EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) : m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size)), m_rows(rows)
|
||||
{
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
eigen_internal_assert(size==rows*cols && rows>=0 && cols == _Cols);
|
||||
EIGEN_UNUSED_VARIABLE(cols);
|
||||
}
|
||||
|
|
@ -503,6 +509,7 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
|
|||
: m_data(internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(other.m_rows*_Cols))
|
||||
, m_rows(other.m_rows)
|
||||
{
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN(Index size = m_rows*_Cols)
|
||||
internal::smart_copy(other.m_data, other.m_data+other.m_rows*_Cols, m_data);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC DenseStorage& operator=(const DenseStorage& other)
|
||||
|
|
@ -550,7 +557,7 @@ template<typename T, int _Cols, int _Options> class DenseStorage<T, Dynamic, Dyn
|
|||
m_data = internal::conditional_aligned_new_auto<T,(_Options&DontAlign)==0>(size);
|
||||
else
|
||||
m_data = 0;
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN
|
||||
EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
|
||||
}
|
||||
m_rows = rows;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Eigen {
|
|||
* \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.
|
||||
* You can also use DynamicIndex so the index can be set at runtime.
|
||||
*
|
||||
* The matrix is not required to be square.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ struct dot_nocheck<T, U, true>
|
|||
|
||||
} // end namespace internal
|
||||
|
||||
/** \returns the dot product of *this with other.
|
||||
/** \fn MatrixBase::dot
|
||||
* \returns the dot product of *this with other.
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
namespace Eigen {
|
||||
|
||||
/** \class EigenBase
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor MatrixBase(T).
|
||||
*
|
||||
|
|
@ -128,6 +129,7 @@ template<typename Derived> struct EigenBase
|
|||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
Derived& DenseBase<Derived>::operator=(const EigenBase<OtherDerived> &other)
|
||||
{
|
||||
call_assignment(derived(), other.derived());
|
||||
|
|
@ -136,6 +138,7 @@ Derived& DenseBase<Derived>::operator=(const EigenBase<OtherDerived> &other)
|
|||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
Derived& DenseBase<Derived>::operator+=(const EigenBase<OtherDerived> &other)
|
||||
{
|
||||
call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar,typename OtherDerived::Scalar>());
|
||||
|
|
@ -144,6 +147,7 @@ Derived& DenseBase<Derived>::operator+=(const EigenBase<OtherDerived> &other)
|
|||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
Derived& DenseBase<Derived>::operator-=(const EigenBase<OtherDerived> &other)
|
||||
{
|
||||
call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar,typename OtherDerived::Scalar>());
|
||||
|
|
|
|||
|
|
@ -1,140 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 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_FLAGGED_H
|
||||
#define EIGEN_FLAGGED_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \class Flagged
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* \brief Expression with modified flags
|
||||
*
|
||||
* \param ExpressionType the type of the object of which we are modifying the flags
|
||||
* \param Added the flags added to the expression
|
||||
* \param Removed the flags removed from the expression (has priority over Added).
|
||||
*
|
||||
* This class represents an expression whose flags have been modified.
|
||||
* It is the return type of MatrixBase::flagged()
|
||||
* and most of the time this is the only way it is used.
|
||||
*
|
||||
* \sa MatrixBase::flagged()
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed>
|
||||
struct traits<Flagged<ExpressionType, Added, Removed> > : traits<ExpressionType>
|
||||
{
|
||||
enum { Flags = (ExpressionType::Flags | Added) & ~Removed };
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged
|
||||
: public MatrixBase<Flagged<ExpressionType, Added, Removed> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef MatrixBase<Flagged> Base;
|
||||
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Flagged)
|
||||
typedef typename internal::conditional<internal::must_nest_by_value<ExpressionType>::ret,
|
||||
ExpressionType, const ExpressionType&>::type ExpressionTypeNested;
|
||||
typedef typename ExpressionType::InnerIterator InnerIterator;
|
||||
|
||||
inline Flagged(const ExpressionType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
inline Index rows() const { return m_matrix.rows(); }
|
||||
inline Index cols() const { return m_matrix.cols(); }
|
||||
inline Index outerStride() const { return m_matrix.outerStride(); }
|
||||
inline Index innerStride() const { return m_matrix.innerStride(); }
|
||||
|
||||
inline CoeffReturnType coeff(Index row, Index col) const
|
||||
{
|
||||
return m_matrix.coeff(row, col);
|
||||
}
|
||||
|
||||
inline CoeffReturnType coeff(Index index) const
|
||||
{
|
||||
return m_matrix.coeff(index);
|
||||
}
|
||||
|
||||
inline const Scalar& coeffRef(Index row, Index col) const
|
||||
{
|
||||
return m_matrix.const_cast_derived().coeffRef(row, col);
|
||||
}
|
||||
|
||||
inline const Scalar& coeffRef(Index index) const
|
||||
{
|
||||
return m_matrix.const_cast_derived().coeffRef(index);
|
||||
}
|
||||
|
||||
inline Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
return m_matrix.const_cast_derived().coeffRef(row, col);
|
||||
}
|
||||
|
||||
inline Scalar& coeffRef(Index index)
|
||||
{
|
||||
return m_matrix.const_cast_derived().coeffRef(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline const PacketScalar packet(Index row, Index col) const
|
||||
{
|
||||
return m_matrix.template packet<LoadMode>(row, col);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index row, Index col, const PacketScalar& x)
|
||||
{
|
||||
m_matrix.const_cast_derived().template writePacket<LoadMode>(row, col, x);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline const PacketScalar packet(Index index) const
|
||||
{
|
||||
return m_matrix.template packet<LoadMode>(index);
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
inline void writePacket(Index index, const PacketScalar& x)
|
||||
{
|
||||
m_matrix.const_cast_derived().template writePacket<LoadMode>(index, x);
|
||||
}
|
||||
|
||||
const ExpressionType& _expression() const { return m_matrix; }
|
||||
|
||||
template<typename OtherDerived>
|
||||
typename ExpressionType::PlainObject solveTriangular(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
void solveTriangularInPlace(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
};
|
||||
|
||||
/** \returns an expression of *this with added and removed flags
|
||||
*
|
||||
* This is mostly for internal use.
|
||||
*
|
||||
* \sa class Flagged
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<unsigned int Added,unsigned int Removed>
|
||||
inline const Flagged<Derived, Added, Removed>
|
||||
DenseBase<Derived>::flagged() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_FLAGGED_H
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -61,7 +61,6 @@ struct default_packet_traits
|
|||
HasSqrt = 0,
|
||||
HasRsqrt = 0,
|
||||
HasExp = 0,
|
||||
HasExpm1 = 0,
|
||||
HasLog = 0,
|
||||
HasLog1p = 0,
|
||||
HasLog10 = 0,
|
||||
|
|
@ -231,7 +230,7 @@ pload1(const typename unpacket_traits<Packet>::type *a) { return pset1<Packet>(
|
|||
* duplicated to form: {from[0],from[0],from[1],from[1],from[2],from[2],from[3],from[3]}
|
||||
* Currently, this function is only used for scalar * complex products.
|
||||
*/
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet
|
||||
ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
|
||||
|
||||
/** \internal \returns a packet with elements of \a *from quadrupled.
|
||||
|
|
@ -279,7 +278,7 @@ inline void pbroadcast2(const typename unpacket_traits<Packet>::type *a,
|
|||
}
|
||||
|
||||
/** \internal \brief Returns a packet with coefficients (a,a+1,...,a+packet_size-1). */
|
||||
template<typename Packet> inline Packet
|
||||
template<typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet
|
||||
plset(const typename unpacket_traits<Packet>::type& a) { return a; }
|
||||
|
||||
/** \internal copy the packet \a from to \a *to, \a to must be 16 bytes aligned */
|
||||
|
|
@ -402,10 +401,6 @@ Packet ptanh(const Packet& a) { using std::tanh; return tanh(a); }
|
|||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet pexp(const Packet& a) { using std::exp; return exp(a); }
|
||||
|
||||
/** \internal \returns the expm1 of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet pexpm1(const Packet& a) { return numext::expm1(a); }
|
||||
|
||||
/** \internal \returns the log of \a a (coeff-wise) */
|
||||
template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
|
||||
Packet plog(const Packet& a) { using std::log; return log(a); }
|
||||
|
|
@ -487,7 +482,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pstoret(Scalar* to, const Packet& fro
|
|||
* by the current computation.
|
||||
*/
|
||||
template<typename Packet, int LoadMode>
|
||||
inline Packet ploadt_ro(const typename unpacket_traits<Packet>::type* from)
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet ploadt_ro(const typename unpacket_traits<Packet>::type* from)
|
||||
{
|
||||
return ploadt<Packet, LoadMode>(from);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ namespace Eigen
|
|||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erf,scalar_erf_op,error function,\sa ArrayBase::erf)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(erfc,scalar_erfc_op,complement error function,\sa ArrayBase::erfc)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(exp,scalar_exp_op,exponential,\sa ArrayBase::exp)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(expm1,scalar_expm1_op,exponential of a value minus 1,\sa ArrayBase::expm1)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log,scalar_log_op,natural logarithm,\sa Eigen::log10 DOXCOMMA ArrayBase::log)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log1p,scalar_log1p_op,natural logarithm of 1 plus the value,\sa ArrayBase::log1p)
|
||||
EIGEN_ARRAY_DECLARE_GLOBAL_UNARY(log10,scalar_log10_op,base 10 logarithm,\sa Eigen::log DOXCOMMA ArrayBase::log)
|
||||
|
|
|
|||
|
|
@ -109,20 +109,6 @@ class WithFormat
|
|||
IOFormat m_format;
|
||||
};
|
||||
|
||||
/** \returns a WithFormat proxy object allowing to print a matrix the with given
|
||||
* format \a fmt.
|
||||
*
|
||||
* See class IOFormat for some examples.
|
||||
*
|
||||
* \sa class IOFormat, class WithFormat
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const WithFormat<Derived>
|
||||
DenseBase<Derived>::format(const IOFormat& fmt) const
|
||||
{
|
||||
return WithFormat<Derived>(derived(), fmt);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
// NOTE: This helper is kept for backward compatibility with previous code specializing
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
// TODO this should better be moved to NumTraits
|
||||
#define EIGEN_PI 3.141592653589793238462643383279502884197169399375105820974944592307816406L
|
||||
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// On WINCE, std::abs is defined for int only, so let's defined our own overloads:
|
||||
|
|
@ -412,7 +413,7 @@ inline NewType cast(const OldType& x)
|
|||
static inline Scalar run(const Scalar& x)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
|
||||
EIGEN_USING_STD_MATH(round);
|
||||
using std::round;
|
||||
return round(x);
|
||||
}
|
||||
};
|
||||
|
|
@ -481,55 +482,6 @@ struct arg_retval
|
|||
typedef typename NumTraits<Scalar>::Real type;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Implementation of expm1 *
|
||||
****************************************************************************/
|
||||
|
||||
// This implementation is based on GSL Math's expm1.
|
||||
namespace std_fallback {
|
||||
// fallback expm1 implementation in case there is no expm1(Scalar) function in namespace of Scalar,
|
||||
// or that there is no suitable std::expm1 function available. Implementation
|
||||
// attributed to Kahan. See: http://www.plunk.org/~hatch/rightway.php.
|
||||
template<typename Scalar>
|
||||
EIGEN_DEVICE_FUNC inline Scalar expm1(const Scalar& x) {
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
EIGEN_USING_STD_MATH(exp);
|
||||
Scalar u = exp(x);
|
||||
if (u == Scalar(1)) {
|
||||
return x;
|
||||
}
|
||||
Scalar um1 = u - RealScalar(1);
|
||||
if (um1 == Scalar(-1)) {
|
||||
return RealScalar(-1);
|
||||
}
|
||||
|
||||
EIGEN_USING_STD_MATH(log);
|
||||
return (u - RealScalar(1)) * x / log(u);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
struct expm1_impl {
|
||||
static inline Scalar run(const Scalar& x)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
using std::expm1;
|
||||
#endif
|
||||
using std_fallback::expm1;
|
||||
return expm1(x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Scalar>
|
||||
struct expm1_retval
|
||||
{
|
||||
typedef Scalar type;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Implementation of log1p *
|
||||
****************************************************************************/
|
||||
|
|
@ -688,7 +640,7 @@ template<typename Scalar>
|
|||
struct random_default_impl<Scalar, false, true>
|
||||
{
|
||||
static inline Scalar run(const Scalar& x, const Scalar& y)
|
||||
{
|
||||
{
|
||||
typedef typename conditional<NumTraits<Scalar>::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX;
|
||||
if(y<x)
|
||||
return x;
|
||||
|
|
@ -874,7 +826,7 @@ template<typename T> T generic_fast_tanh_float(const T& a_x);
|
|||
|
||||
namespace numext {
|
||||
|
||||
#if !defined(__CUDA_ARCH__) && !defined(__SYCL_DEVICE_ONLY__)
|
||||
#ifndef __CUDA_ARCH__
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y)
|
||||
|
|
@ -890,84 +842,6 @@ EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y)
|
|||
EIGEN_USING_STD_MATH(max);
|
||||
return max EIGEN_NOT_A_MACRO (x,y);
|
||||
}
|
||||
|
||||
|
||||
#elif defined(__SYCL_DEVICE_ONLY__)
|
||||
template<typename T>
|
||||
EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y)
|
||||
{
|
||||
|
||||
return y < x ? y : x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y)
|
||||
{
|
||||
|
||||
return x < y ? y : x;
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE int mini(const int& x, const int& y)
|
||||
{
|
||||
return cl::sycl::min(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE int maxi(const int& x, const int& y)
|
||||
{
|
||||
return cl::sycl::max(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE unsigned int mini(const unsigned int& x, const unsigned int& y)
|
||||
{
|
||||
return cl::sycl::min(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE unsigned int maxi(const unsigned int& x, const unsigned int& y)
|
||||
{
|
||||
return cl::sycl::max(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE long mini(const long & x, const long & y)
|
||||
{
|
||||
return cl::sycl::min(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE long maxi(const long & x, const long & y)
|
||||
{
|
||||
return cl::sycl::max(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE unsigned long mini(const unsigned long& x, const unsigned long& y)
|
||||
{
|
||||
return cl::sycl::min(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE unsigned long maxi(const unsigned long& x, const unsigned long& y)
|
||||
{
|
||||
return cl::sycl::max(x,y);
|
||||
}
|
||||
|
||||
|
||||
EIGEN_ALWAYS_INLINE float mini(const float& x, const float& y)
|
||||
{
|
||||
return cl::sycl::fmin(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE float maxi(const float& x, const float& y)
|
||||
{
|
||||
return cl::sycl::fmax(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE double mini(const double& x, const double& y)
|
||||
{
|
||||
return cl::sycl::fmin(x,y);
|
||||
}
|
||||
|
||||
EIGEN_ALWAYS_INLINE double maxi(const double& x, const double& y)
|
||||
{
|
||||
return cl::sycl::fmax(x,y);
|
||||
}
|
||||
|
||||
#else
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
|
|
@ -1080,11 +954,6 @@ inline EIGEN_MATHFUNC_RETVAL(log1p, Scalar) log1p(const Scalar& x)
|
|||
return EIGEN_MATHFUNC_IMPL(log1p, Scalar)::run(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float log1p(float x) { return cl::sycl::log1p(x); }
|
||||
EIGEN_ALWAYS_INLINE double log1p(double x) { return cl::sycl::log1p(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float log1p(const float &x) { return ::log1pf(x); }
|
||||
|
|
@ -1100,24 +969,10 @@ inline typename internal::pow_impl<ScalarX,ScalarY>::result_type pow(const Scala
|
|||
return internal::pow_impl<ScalarX,ScalarY>::run(x, y);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float pow(float x, float y) { return cl::sycl::pow(x, y); }
|
||||
EIGEN_ALWAYS_INLINE double pow(double x, double y) { return cl::sycl::pow(x, y); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
template<typename T> EIGEN_DEVICE_FUNC bool (isnan) (const T &x) { return internal::isnan_impl(x); }
|
||||
template<typename T> EIGEN_DEVICE_FUNC bool (isinf) (const T &x) { return internal::isinf_impl(x); }
|
||||
template<typename T> EIGEN_DEVICE_FUNC bool (isfinite)(const T &x) { return internal::isfinite_impl(x); }
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float isnan(float x) { return cl::sycl::isnan(x); }
|
||||
EIGEN_ALWAYS_INLINE double isnan(double x) { return cl::sycl::isnan(x); }
|
||||
EIGEN_ALWAYS_INLINE float isinf(float x) { return cl::sycl::isinf(x); }
|
||||
EIGEN_ALWAYS_INLINE double isinf(double x) { return cl::sycl::isinf(x); }
|
||||
EIGEN_ALWAYS_INLINE float isfinite(float x) { return cl::sycl::isfinite(x); }
|
||||
EIGEN_ALWAYS_INLINE double isfinite(double x) { return cl::sycl::isfinite(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
template<typename Scalar>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline EIGEN_MATHFUNC_RETVAL(round, Scalar) round(const Scalar& x)
|
||||
|
|
@ -1125,11 +980,6 @@ inline EIGEN_MATHFUNC_RETVAL(round, Scalar) round(const Scalar& x)
|
|||
return EIGEN_MATHFUNC_IMPL(round, Scalar)::run(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float round(float x) { return cl::sycl::round(x); }
|
||||
EIGEN_ALWAYS_INLINE double round(double x) { return cl::sycl::round(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
T (floor)(const T& x)
|
||||
|
|
@ -1138,11 +988,6 @@ T (floor)(const T& x)
|
|||
return floor(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float floor(float x) { return cl::sycl::floor(x); }
|
||||
EIGEN_ALWAYS_INLINE double floor(double x) { return cl::sycl::floor(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float floor(const float &x) { return ::floorf(x); }
|
||||
|
|
@ -1159,11 +1004,6 @@ T (ceil)(const T& x)
|
|||
return ceil(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float ceil(float x) { return cl::sycl::ceil(x); }
|
||||
EIGEN_ALWAYS_INLINE double ceil(double x) { return cl::sycl::ceil(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float ceil(const float &x) { return ::ceilf(x); }
|
||||
|
|
@ -1204,11 +1044,6 @@ T sqrt(const T &x)
|
|||
return sqrt(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float sqrt(float x) { return cl::sycl::sqrt(x); }
|
||||
EIGEN_ALWAYS_INLINE double sqrt(double x) { return cl::sycl::sqrt(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
T log(const T &x) {
|
||||
|
|
@ -1216,12 +1051,6 @@ T log(const T &x) {
|
|||
return log(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float log(float x) { return cl::sycl::log(x); }
|
||||
EIGEN_ALWAYS_INLINE double log(double x) { return cl::sycl::log(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float log(const float &x) { return ::logf(x); }
|
||||
|
|
@ -1232,11 +1061,19 @@ double log(const double &x) { return ::log(x); }
|
|||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
typename NumTraits<T>::Real abs(const T &x) {
|
||||
typename internal::enable_if<NumTraits<T>::IsSigned || NumTraits<T>::IsComplex,typename NumTraits<T>::Real>::type
|
||||
abs(const T &x) {
|
||||
EIGEN_USING_STD_MATH(abs);
|
||||
return abs(x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
typename internal::enable_if<!(NumTraits<T>::IsSigned || NumTraits<T>::IsComplex),typename NumTraits<T>::Real>::type
|
||||
abs(const T &x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float abs(float x) { return cl::sycl::fabs(x); }
|
||||
EIGEN_ALWAYS_INLINE double abs(double x) { return cl::sycl::fabs(x); }
|
||||
|
|
@ -1267,11 +1104,6 @@ T exp(const T &x) {
|
|||
return exp(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float exp(float x) { return cl::sycl::exp(x); }
|
||||
EIGEN_ALWAYS_INLINE double exp(double x) { return cl::sycl::exp(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float exp(const float &x) { return ::expf(x); }
|
||||
|
|
@ -1280,26 +1112,6 @@ template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
|||
double exp(const double &x) { return ::exp(x); }
|
||||
#endif
|
||||
|
||||
template<typename Scalar>
|
||||
EIGEN_DEVICE_FUNC
|
||||
inline EIGEN_MATHFUNC_RETVAL(expm1, Scalar) expm1(const Scalar& x)
|
||||
{
|
||||
return EIGEN_MATHFUNC_IMPL(expm1, Scalar)::run(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float expm1(float x) { return cl::sycl::expm1(x); }
|
||||
EIGEN_ALWAYS_INLINE double expm1(double x) { return cl::sycl::expm1(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float expm1(const float &x) { return ::expm1f(x); }
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
double expm1(const double &x) { return ::expm1(x); }
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
T cos(const T &x) {
|
||||
|
|
@ -1307,11 +1119,6 @@ T cos(const T &x) {
|
|||
return cos(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float cos(float x) { return cl::sycl::cos(x); }
|
||||
EIGEN_ALWAYS_INLINE double cos(double x) { return cl::sycl::cos(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float cos(const float &x) { return ::cosf(x); }
|
||||
|
|
@ -1327,11 +1134,6 @@ T sin(const T &x) {
|
|||
return sin(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float sin(float x) { return cl::sycl::sin(x); }
|
||||
EIGEN_ALWAYS_INLINE double sin(double x) { return cl::sycl::sin(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float sin(const float &x) { return ::sinf(x); }
|
||||
|
|
@ -1347,11 +1149,6 @@ T tan(const T &x) {
|
|||
return tan(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float tan(float x) { return cl::sycl::tan(x); }
|
||||
EIGEN_ALWAYS_INLINE double tan(double x) { return cl::sycl::tan(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float tan(const float &x) { return ::tanf(x); }
|
||||
|
|
@ -1367,11 +1164,6 @@ T acos(const T &x) {
|
|||
return acos(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float acos(float x) { return cl::sycl::acos(x); }
|
||||
EIGEN_ALWAYS_INLINE double acos(double x) { return cl::sycl::acos(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float acos(const float &x) { return ::acosf(x); }
|
||||
|
|
@ -1387,11 +1179,6 @@ T asin(const T &x) {
|
|||
return asin(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float asin(float x) { return cl::sycl::asin(x); }
|
||||
EIGEN_ALWAYS_INLINE double asin(double x) { return cl::sycl::asin(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float asin(const float &x) { return ::asinf(x); }
|
||||
|
|
@ -1407,11 +1194,6 @@ T atan(const T &x) {
|
|||
return atan(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float atan(float x) { return cl::sycl::atan(x); }
|
||||
EIGEN_ALWAYS_INLINE double atan(double x) { return cl::sycl::atan(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float atan(const float &x) { return ::atanf(x); }
|
||||
|
|
@ -1428,11 +1210,6 @@ T cosh(const T &x) {
|
|||
return cosh(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float cosh(float x) { return cl::sycl::cosh(x); }
|
||||
EIGEN_ALWAYS_INLINE double cosh(double x) { return cl::sycl::cosh(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float cosh(const float &x) { return ::coshf(x); }
|
||||
|
|
@ -1448,11 +1225,6 @@ T sinh(const T &x) {
|
|||
return sinh(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float sinh(float x) { return cl::sycl::sinh(x); }
|
||||
EIGEN_ALWAYS_INLINE double sinh(double x) { return cl::sycl::sinh(x); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float sinh(const float &x) { return ::sinhf(x); }
|
||||
|
|
@ -1468,10 +1240,7 @@ T tanh(const T &x) {
|
|||
return tanh(x);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float tanh(float x) { return cl::sycl::tanh(x); }
|
||||
EIGEN_ALWAYS_INLINE double tanh(double x) { return cl::sycl::tanh(x); }
|
||||
#elif (!defined(__CUDACC__)) && EIGEN_FAST_MATH
|
||||
#if (!defined(__CUDACC__)) && EIGEN_FAST_MATH
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
float tanh(float x) { return internal::generic_fast_tanh_float(x); }
|
||||
#endif
|
||||
|
|
@ -1491,11 +1260,6 @@ T fmod(const T& a, const T& b) {
|
|||
return fmod(a, b);
|
||||
}
|
||||
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
EIGEN_ALWAYS_INLINE float fmod(float x, float y) { return cl::sycl::fmod(x, y); }
|
||||
EIGEN_ALWAYS_INLINE double fmod(double x, double y) { return cl::sycl::fmod(x, y); }
|
||||
#endif // defined(__SYCL_DEVICE_ONLY__)
|
||||
|
||||
#ifdef __CUDACC__
|
||||
template <>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
|
|
@ -1638,13 +1402,13 @@ template<> struct random_impl<bool>
|
|||
template<> struct scalar_fuzzy_impl<bool>
|
||||
{
|
||||
typedef bool RealScalar;
|
||||
|
||||
|
||||
template<typename OtherScalar> EIGEN_DEVICE_FUNC
|
||||
static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&)
|
||||
{
|
||||
return !x;
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline bool isApprox(bool x, bool y, bool)
|
||||
{
|
||||
|
|
@ -1656,10 +1420,10 @@ template<> struct scalar_fuzzy_impl<bool>
|
|||
{
|
||||
return (!x) || y;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ template<typename Derived> class MatrixBase
|
|||
* fuzzy comparison such as isApprox()
|
||||
* \sa isApprox(), operator!= */
|
||||
template<typename OtherDerived>
|
||||
inline bool operator==(const MatrixBase<OtherDerived>& other) const
|
||||
EIGEN_DEVICE_FUNC 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.
|
||||
|
|
@ -302,7 +302,7 @@ template<typename Derived> class MatrixBase
|
|||
* fuzzy comparison such as isApprox()
|
||||
* \sa isApprox(), operator== */
|
||||
template<typename OtherDerived>
|
||||
inline bool operator!=(const MatrixBase<OtherDerived>& other) const
|
||||
EIGEN_DEVICE_FUNC inline bool operator!=(const MatrixBase<OtherDerived>& other) const
|
||||
{ return cwiseNotEqual(other).any(); }
|
||||
|
||||
NoAlias<Derived,Eigen::MatrixBase > noalias();
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ struct default_digits10_impl<T,false,true> // Integer
|
|||
* and to \c 0 otherwise.
|
||||
* \li Enum values ReadCost, AddCost and MulCost representing a rough estimate of the number of CPU cycles needed
|
||||
* to by move / add / mul instructions respectively, assuming the data is already stored in CPU registers.
|
||||
* Stay vague here. No need to do architecture-specific stuff. If you don't know what this means, just use \c Eigen::HugeCost.
|
||||
* Stay vague here. No need to do architecture-specific stuff.
|
||||
* \li An enum value \a IsSigned. It is equal to \c 1 if \a T is a signed type and to 0 if \a T is unsigned.
|
||||
* \li An enum value \a RequireInitialization. It is equal to \c 1 if the constructor of the numeric type \a T must
|
||||
* be called, and to 0 if it is safe not to call it. Default is 0 if \a T is an arithmetic type, and 1 otherwise.
|
||||
|
|
@ -215,6 +215,8 @@ struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
|
|||
static inline RealScalar epsilon() { return NumTraits<RealScalar>::epsilon(); }
|
||||
EIGEN_DEVICE_FUNC
|
||||
static inline RealScalar dummy_precision() { return NumTraits<RealScalar>::dummy_precision(); }
|
||||
|
||||
static inline int digits10() { return NumTraits<Scalar>::digits10(); }
|
||||
};
|
||||
|
||||
template<> struct NumTraits<std::string>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ template<> struct check_rows_cols_for_overflow<Dynamic> {
|
|||
{
|
||||
// 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
|
||||
Index max_index = (std::size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed
|
||||
bool error = (rows == 0 || cols == 0) ? false
|
||||
: (rows > max_index / cols);
|
||||
if (error)
|
||||
|
|
@ -58,6 +58,28 @@ template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct m
|
|||
|
||||
} // end namespace internal
|
||||
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
namespace doxygen {
|
||||
|
||||
// This is a workaround to doxygen not being able to understand the inheritance logic
|
||||
// when it is hidden by the dense_xpr_base helper struct.
|
||||
// Moreover, doxygen fails to include members that are not documented in the declaration body of
|
||||
// MatrixBase if we inherits MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >,
|
||||
// this is why we simply inherits MatrixBase, though this does not make sense.
|
||||
|
||||
/** This class is just a workaround for Doxygen and it does not not actually exist. */
|
||||
template<typename Derived> struct dense_xpr_base_dispatcher;
|
||||
/** 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<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
: public MatrixBase {};
|
||||
/** 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<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
: public ArrayBase {};
|
||||
|
||||
} // namespace doxygen
|
||||
|
||||
/** \class PlainObjectBase
|
||||
* \ingroup Core_Module
|
||||
* \brief %Dense storage base class for matrices and arrays.
|
||||
|
|
@ -65,26 +87,10 @@ template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct m
|
|||
* This class can be extended with the help of the plugin mechanism described on the page
|
||||
* \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_PLAINOBJECTBASE_PLUGIN.
|
||||
*
|
||||
* \tparam Derived is the derived type, e.g., a Matrix or Array
|
||||
*
|
||||
* \sa \ref TopicClassHierarchy
|
||||
*/
|
||||
#ifdef EIGEN_PARSED_BY_DOXYGEN
|
||||
namespace doxygen {
|
||||
|
||||
// this is a workaround to doxygen not being able to understand the inheritance logic
|
||||
// when it is hidden by the dense_xpr_base helper struct.
|
||||
/** This class is just a workaround for Doxygen and it does not not actually exist. */
|
||||
template<typename Derived> struct dense_xpr_base_dispatcher;
|
||||
/** 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<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<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
: public ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
|
||||
|
||||
} // namespace doxygen
|
||||
|
||||
template<typename Derived>
|
||||
class PlainObjectBase : public doxygen::dense_xpr_base_dispatcher<Derived>
|
||||
#else
|
||||
|
|
@ -554,7 +560,8 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||
|
||||
public:
|
||||
|
||||
/** \copydoc DenseBase::operator=(const EigenBase<OtherDerived>&)
|
||||
/** \brief Copies the generic expression \a other into *this.
|
||||
* \copydetails DenseBase::operator=(const EigenBase<OtherDerived> &other)
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
|
|
@ -805,6 +812,13 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||
this->_set_noalias(other);
|
||||
}
|
||||
|
||||
// Initialize an arbitrary matrix from an object convertible to the Derived type.
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE void _init1(const Derived& other){
|
||||
this->_set_noalias(other);
|
||||
}
|
||||
|
||||
// Initialize an arbitrary matrix from a generic Eigen expression
|
||||
template<typename T, typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
|
|
@ -827,7 +841,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||
this->derived() = r;
|
||||
}
|
||||
|
||||
// For fixed -size arrays:
|
||||
// For fixed-size Array<Scalar,...>
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE void _init1(const Scalar& val0,
|
||||
|
|
@ -839,6 +853,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
|||
Base::setConstant(val0);
|
||||
}
|
||||
|
||||
// For fixed-size Array<Index,...>
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE void _init1(const Index& val0,
|
||||
|
|
|
|||
|
|
@ -1,290 +0,0 @@
|
|||
// 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:
|
||||
|
||||
#ifndef EIGEN_NO_MALLOC
|
||||
typedef typename Base::PlainObject BasePlainObject;
|
||||
typedef Matrix<Scalar,RowsAtCompileTime==1?1:Dynamic,ColsAtCompileTime==1?1:Dynamic,BasePlainObject::Options> DynPlainObject;
|
||||
typedef typename internal::conditional<(BasePlainObject::SizeAtCompileTime==Dynamic) || (BasePlainObject::SizeAtCompileTime*int(sizeof(Scalar)) < int(EIGEN_STACK_ALLOCATION_LIMIT)),
|
||||
BasePlainObject, DynPlainObject>::type PlainObject;
|
||||
#else
|
||||
typedef typename Base::PlainObject PlainObject;
|
||||
#endif
|
||||
|
||||
ProductBase(const Lhs& a_lhs, const Rhs& a_rhs)
|
||||
: m_lhs(a_lhs), m_rhs(a_rhs)
|
||||
{
|
||||
eigen_assert(a_lhs.cols() == a_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, const 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 typename GeneralProduct<Lhs,Rhs,Mode>::PlainObject const& type;
|
||||
};
|
||||
template<typename Lhs, typename Rhs, int Mode, int N, typename PlainObject>
|
||||
struct nested<const GeneralProduct<Lhs,Rhs,Mode>, N, PlainObject>
|
||||
{
|
||||
typedef typename GeneralProduct<Lhs,Rhs,Mode>::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, const 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, const typename Derived::RealScalar& x)
|
||||
{ return ScaledProduct<Derived>(prod.derived(), x); }
|
||||
|
||||
|
||||
template<typename Derived,typename Lhs,typename Rhs>
|
||||
const ScaledProduct<Derived>
|
||||
operator*(const 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*(const 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, const 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, const Scalar& a_alpha) const { m_prod.derived().scaleAndAddTo(dst,a_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
|
||||
|
|
@ -207,6 +207,12 @@ struct evaluator_assume_aliasing<CwiseBinaryOp<internal::scalar_sum_op<typename
|
|||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename OtherXpr, typename Lhs, typename Rhs>
|
||||
struct evaluator_assume_aliasing<CwiseBinaryOp<internal::scalar_difference_op<typename OtherXpr::Scalar,typename Product<Lhs,Rhs,DefaultProduct>::Scalar>, const OtherXpr,
|
||||
const Product<Lhs,Rhs,DefaultProduct> >, DenseShape > {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename DstXprType, typename OtherXpr, typename ProductType, typename Func1, typename Func2>
|
||||
struct assignment_from_xpr_op_product
|
||||
{
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ public:
|
|||
* Implementation of MatrixBase methods
|
||||
***************************************************************************/
|
||||
|
||||
/** This is the const version of MatrixBase::selfadjointView() */
|
||||
template<typename Derived>
|
||||
template<unsigned int UpLo>
|
||||
typename MatrixBase<Derived>::template ConstSelfAdjointViewReturnType<UpLo>::Type
|
||||
|
|
@ -327,6 +328,15 @@ MatrixBase<Derived>::selfadjointView() const
|
|||
return typename ConstSelfAdjointViewReturnType<UpLo>::Type(derived());
|
||||
}
|
||||
|
||||
/** \returns an expression of a symmetric/self-adjoint view extracted from the upper or lower triangular part of the current matrix
|
||||
*
|
||||
* The parameter \a UpLo can be either \c #Upper or \c #Lower
|
||||
*
|
||||
* Example: \include MatrixBase_selfadjointView.cpp
|
||||
* Output: \verbinclude MatrixBase_selfadjointView.out
|
||||
*
|
||||
* \sa class SelfAdjointView
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<unsigned int UpLo>
|
||||
typename MatrixBase<Derived>::template SelfAdjointViewReturnType<UpLo>::Type
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Eigen {
|
|||
// TODO generalize the scalar type of 'other'
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator*=(const Scalar& other)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator*=(const Scalar& other)
|
||||
{
|
||||
typedef typename Derived::PlainObject PlainObject;
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::mul_assign_op<Scalar,Scalar>());
|
||||
|
|
@ -23,7 +23,7 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator*=(const Scalar& other)
|
|||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator+=(const Scalar& other)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator+=(const Scalar& other)
|
||||
{
|
||||
typedef typename Derived::PlainObject PlainObject;
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::add_assign_op<Scalar,Scalar>());
|
||||
|
|
@ -31,7 +31,7 @@ EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator+=(const Scalar& other)
|
|||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator-=(const Scalar& other)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator-=(const Scalar& other)
|
||||
{
|
||||
typedef typename Derived::PlainObject PlainObject;
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::sub_assign_op<Scalar,Scalar>());
|
||||
|
|
@ -39,7 +39,7 @@ EIGEN_STRONG_INLINE Derived& ArrayBase<Derived>::operator-=(const Scalar& other)
|
|||
}
|
||||
|
||||
template<typename Derived>
|
||||
EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator/=(const Scalar& other)
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator/=(const Scalar& other)
|
||||
{
|
||||
typedef typename Derived::PlainObject PlainObject;
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(),cols(),other), internal::div_assign_op<Scalar,Scalar>());
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ template<typename Decomposition, typename RhsType,typename StorageKind> struct s
|
|||
template<typename Decomposition, typename RhsType>
|
||||
struct solve_traits<Decomposition,RhsType,Dense>
|
||||
{
|
||||
typedef Matrix<typename RhsType::Scalar,
|
||||
typedef typename make_proper_matrix_type<typename RhsType::Scalar,
|
||||
Decomposition::ColsAtCompileTime,
|
||||
RhsType::ColsAtCompileTime,
|
||||
RhsType::PlainObject::Options,
|
||||
Decomposition::MaxColsAtCompileTime,
|
||||
RhsType::MaxColsAtCompileTime> PlainObject;
|
||||
RhsType::MaxColsAtCompileTime>::type PlainObject;
|
||||
};
|
||||
|
||||
template<typename Decomposition, typename RhsType>
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ struct triangular_solver_selector<Lhs,Rhs,OnTheRight,Mode,CompleteUnrolling,1> {
|
|||
* TriangularView methods
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
template<int Side, typename OtherDerived>
|
||||
void TriangularViewImpl<MatrixType,Mode,Dense>::solveInPlace(const MatrixBase<OtherDerived>& _other) const
|
||||
|
|
@ -188,6 +189,7 @@ TriangularViewImpl<Derived,Mode,Dense>::solve(const MatrixBase<Other>& other) co
|
|||
{
|
||||
return internal::triangular_solve_retval<Side,TriangularViewType,Other>(derived(), other.derived());
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
|
|
|||
|
|
@ -170,7 +170,8 @@ MatrixBase<Derived>::stableNorm() const
|
|||
enum {
|
||||
CanAlign = ( (int(DerivedCopyClean::Flags)&DirectAccessBit)
|
||||
|| (int(internal::evaluator<DerivedCopyClean>::Alignment)>0) // FIXME Alignment)>0 might not be enough
|
||||
) && (blockSize*sizeof(Scalar)*2<EIGEN_STACK_ALLOCATION_LIMIT) // ifwe cannot allocate on the stack, then let's not bother about this optimization
|
||||
) && (blockSize*sizeof(Scalar)*2<EIGEN_STACK_ALLOCATION_LIMIT)
|
||||
&& (EIGEN_MAX_STATIC_ALIGN_BYTES>0) // if we cannot allocate on the stack, then let's not bother about this optimization
|
||||
};
|
||||
typedef typename internal::conditional<CanAlign, Ref<const Matrix<Scalar,Dynamic,1,0,blockSize,1>, internal::evaluator<DerivedCopyClean>::Alignment>,
|
||||
typename DerivedCopyClean::ConstSegmentReturnType>::type SegmentWrapper;
|
||||
|
|
|
|||
|
|
@ -470,6 +470,8 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularViewImpl<_Mat
|
|||
* \a Side==OnTheLeft (the default), or the right-inverse-multiply \a other * inverse(\c *this) if
|
||||
* \a Side==OnTheRight.
|
||||
*
|
||||
* Note that the template parameter \c Side can be ommitted, in which case \c Side==OnTheLeft
|
||||
*
|
||||
* The matrix \c *this must be triangular and invertible (i.e., all the coefficients of the
|
||||
* diagonal must be non zero). It works as a forward (resp. backward) substitution if \c *this
|
||||
* is an upper (resp. lower) triangular matrix.
|
||||
|
|
@ -495,6 +497,8 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularViewImpl<_Mat
|
|||
* \warning The parameter is only marked 'const' to make the C++ compiler accept a temporary expression here.
|
||||
* This function will const_cast it, so constness isn't honored here.
|
||||
*
|
||||
* Note that the template parameter \c Side can be ommitted, in which case \c Side==OnTheLeft
|
||||
*
|
||||
* See TriangularView:solve() for the details.
|
||||
*/
|
||||
template<int Side, typename OtherDerived>
|
||||
|
|
@ -539,13 +543,14 @@ template<typename _MatrixType, unsigned int _Mode> class TriangularViewImpl<_Mat
|
|||
|
||||
template<typename ProductType>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha);
|
||||
EIGEN_STRONG_INLINE TriangularViewType& _assignProduct(const ProductType& prod, const Scalar& alpha, bool beta);
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* Implementation of triangular evaluation/assignment
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
// FIXME should we keep that possibility
|
||||
template<typename MatrixType, unsigned int Mode>
|
||||
template<typename OtherDerived>
|
||||
|
|
@ -583,6 +588,7 @@ void TriangularViewImpl<MatrixType, Mode, Dense>::lazyAssign(const TriangularBas
|
|||
eigen_assert(Mode == int(OtherDerived::Mode));
|
||||
internal::call_assignment_no_alias(derived(), other.derived());
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
* Implementation of TriangularBase methods
|
||||
|
|
@ -944,8 +950,7 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,DefaultProduct>, internal::assign_
|
|||
if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
|
||||
dst.resize(dstRows, dstCols);
|
||||
|
||||
dst.setZero();
|
||||
dst._assignProduct(src, 1);
|
||||
dst._assignProduct(src, 1, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -956,7 +961,7 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,DefaultProduct>, internal::add_ass
|
|||
typedef Product<Lhs,Rhs,DefaultProduct> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<Scalar,typename SrcXprType::Scalar> &)
|
||||
{
|
||||
dst._assignProduct(src, 1);
|
||||
dst._assignProduct(src, 1, 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -967,7 +972,7 @@ struct Assignment<DstXprType, Product<Lhs,Rhs,DefaultProduct>, internal::sub_ass
|
|||
typedef Product<Lhs,Rhs,DefaultProduct> SrcXprType;
|
||||
static void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<Scalar,typename SrcXprType::Scalar> &)
|
||||
{
|
||||
dst._assignProduct(src, -1);
|
||||
dst._assignProduct(src, -1, 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -194,7 +194,8 @@ struct functor_traits<max_coeff_visitor<Scalar> > {
|
|||
|
||||
} // end namespace internal
|
||||
|
||||
/** \returns the minimum of all coefficients of *this and puts in *row and *col its location.
|
||||
/** \fn DenseBase<Derived>::minCoeff(IndexType* rowId, IndexType* colId) const
|
||||
* \returns the minimum of all coefficients of *this and puts in *row and *col its location.
|
||||
* \warning the result is undefined if \c *this contains NaN.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(Index*), DenseBase::maxCoeff(Index*,Index*), DenseBase::visit(), DenseBase::minCoeff()
|
||||
|
|
@ -230,7 +231,8 @@ DenseBase<Derived>::minCoeff(IndexType* index) const
|
|||
return minVisitor.res;
|
||||
}
|
||||
|
||||
/** \returns the maximum of all coefficients of *this and puts in *row and *col its location.
|
||||
/** \fn DenseBase<Derived>::maxCoeff(IndexType* rowId, IndexType* colId) const
|
||||
* \returns the maximum of all coefficients of *this and puts in *row and *col its location.
|
||||
* \warning the result is undefined if \c *this contains NaN.
|
||||
*
|
||||
* \sa DenseBase::minCoeff(IndexType*,IndexType*), DenseBase::visit(), DenseBase::maxCoeff()
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ template<> struct packet_traits<float> : default_packet_traits
|
|||
HasLog = 1,
|
||||
#endif
|
||||
HasExp = 1,
|
||||
HasSqrt = EIGEN_FAST_MATH,
|
||||
HasRsqrt = EIGEN_FAST_MATH,
|
||||
HasSqrt = 1,
|
||||
HasRsqrt = 1,
|
||||
#endif
|
||||
HasDiv = 1
|
||||
};
|
||||
|
|
@ -75,7 +75,7 @@ template<> struct packet_traits<double> : default_packet_traits
|
|||
size = 8,
|
||||
HasHalfPacket = 1,
|
||||
#if EIGEN_GNUC_AT_LEAST(5, 3)
|
||||
HasSqrt = EIGEN_FAST_MATH,
|
||||
HasSqrt = 1,
|
||||
HasRsqrt = EIGEN_FAST_MATH,
|
||||
#endif
|
||||
HasDiv = 1
|
||||
|
|
@ -461,21 +461,53 @@ EIGEN_STRONG_INLINE Packet16i ploadu<Packet16i>(const int* from) {
|
|||
// {a0, a0 a1, a1, a2, a2, a3, a3, a4, a4, a5, a5, a6, a6, a7, a7}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f ploaddup<Packet16f>(const float* from) {
|
||||
__m256i low_half = _mm256_load_si256(reinterpret_cast<const __m256i*>(from));
|
||||
__m512 even_elements = _mm512_castsi512_ps(_mm512_cvtepu32_epi64(low_half));
|
||||
__m512 pairs = _mm512_permute_ps(even_elements, _MM_SHUFFLE(2, 2, 0, 0));
|
||||
return pairs;
|
||||
Packet8f lane0 = _mm256_broadcast_ps((const __m128*)(const void*)from);
|
||||
// mimic an "inplace" permutation of the lower 128bits using a blend
|
||||
lane0 = _mm256_blend_ps(
|
||||
lane0, _mm256_castps128_ps256(_mm_permute_ps(
|
||||
_mm256_castps256_ps128(lane0), _MM_SHUFFLE(1, 0, 1, 0))),
|
||||
15);
|
||||
// then we can perform a consistent permutation on the global register to get
|
||||
// everything in shape:
|
||||
lane0 = _mm256_permute_ps(lane0, _MM_SHUFFLE(3, 3, 2, 2));
|
||||
|
||||
Packet8f lane1 = _mm256_broadcast_ps((const __m128*)(const void*)(from + 4));
|
||||
// mimic an "inplace" permutation of the lower 128bits using a blend
|
||||
lane1 = _mm256_blend_ps(
|
||||
lane1, _mm256_castps128_ps256(_mm_permute_ps(
|
||||
_mm256_castps256_ps128(lane1), _MM_SHUFFLE(1, 0, 1, 0))),
|
||||
15);
|
||||
// then we can perform a consistent permutation on the global register to get
|
||||
// everything in shape:
|
||||
lane1 = _mm256_permute_ps(lane1, _MM_SHUFFLE(3, 3, 2, 2));
|
||||
|
||||
#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
Packet16f res = _mm512_undefined_ps();
|
||||
return _mm512_insertf32x8(res, lane0, 0);
|
||||
return _mm512_insertf32x8(res, lane1, 1);
|
||||
return res;
|
||||
#else
|
||||
Packet16f res = _mm512_undefined_ps();
|
||||
res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane0, 0), 0);
|
||||
res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane0, 1), 1);
|
||||
res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane1, 0), 2);
|
||||
res = _mm512_insertf32x4(res, _mm256_extractf128_ps(lane1, 1), 3);
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
// Loads 4 doubles from memory a returns the packet {a0, a0 a1, a1, a2, a2, a3,
|
||||
// a3}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8d ploaddup<Packet8d>(const double* from) {
|
||||
__m512d x = _mm512_setzero_pd();
|
||||
x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[0]), 0);
|
||||
x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[1]), 1);
|
||||
x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[2]), 2);
|
||||
x = _mm512_insertf64x2(x, _mm_loaddup_pd(&from[3]), 3);
|
||||
return x;
|
||||
Packet4d lane0 = _mm256_broadcast_pd((const __m128d*)(const void*)from);
|
||||
lane0 = _mm256_permute_pd(lane0, 3 << 2);
|
||||
|
||||
Packet4d lane1 = _mm256_broadcast_pd((const __m128d*)(const void*)(from + 2));
|
||||
lane1 = _mm256_permute_pd(lane1, 3 << 2);
|
||||
|
||||
Packet8d res = _mm512_undefined_pd();
|
||||
res = _mm512_insertf64x4(res, lane0, 0);
|
||||
return _mm512_insertf64x4(res, lane1, 1);
|
||||
}
|
||||
|
||||
// Loads 4 floats from memory a returns the packet
|
||||
|
|
@ -493,11 +525,11 @@ EIGEN_STRONG_INLINE Packet16f ploadquad<Packet16f>(const float* from) {
|
|||
// {a0, a0 a0, a0, a1, a1, a1, a1}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8d ploadquad<Packet8d>(const double* from) {
|
||||
__m128d tmp0 = _mm_load_pd1(from);
|
||||
__m256d lane0 = _mm256_broadcastsd_pd(tmp0);
|
||||
__m128d tmp1 = _mm_load_pd1(from + 1);
|
||||
__m256d lane1 = _mm256_broadcastsd_pd(tmp1);
|
||||
__m512d tmp = _mm512_undefined_pd();
|
||||
Packet8d tmp = _mm512_undefined_pd();
|
||||
Packet2d tmp0 = _mm_load_pd1(from);
|
||||
Packet2d tmp1 = _mm_load_pd1(from + 1);
|
||||
Packet4d lane0 = _mm256_broadcastsd_pd(tmp0);
|
||||
Packet4d lane1 = _mm256_broadcastsd_pd(tmp1);
|
||||
tmp = _mm512_insertf64x4(tmp, lane0, 0);
|
||||
return _mm512_insertf64x4(tmp, lane1, 1);
|
||||
}
|
||||
|
|
@ -628,8 +660,8 @@ EIGEN_STRONG_INLINE Packet8d pabs(const Packet8d& a) {
|
|||
#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
// AVX512F does not define _mm512_extractf32x8_ps to extract _m256 from _m512
|
||||
#define EIGEN_EXTRACT_8f_FROM_16f(INPUT, OUTPUT) \
|
||||
__m256 OUTPUT##_0 = _mm512_extractf32x8_ps(INPUT, 0); \
|
||||
__m256 OUTPUT##_1 = _mm512_extractf32x8_ps(INPUT, 1)
|
||||
__m256 OUTPUT##_0 = _mm512_extractf32x8_ps(INPUT, 0) __m256 OUTPUT##_1 = \
|
||||
_mm512_extractf32x8_ps(INPUT, 1)
|
||||
#else
|
||||
#define EIGEN_EXTRACT_8f_FROM_16f(INPUT, OUTPUT) \
|
||||
__m256 OUTPUT##_0 = _mm256_insertf128_ps( \
|
||||
|
|
@ -719,7 +751,7 @@ vecs)
|
|||
blend1 = _mm256_blend_ps(sum1, sum2, 0xcc);
|
||||
blend2 = _mm256_blend_ps(sum3, sum4, 0xcc);
|
||||
|
||||
final = _mm256_add_ps(final, _mm256_blend_ps(blend1, blend2, 0xf0));
|
||||
final = padd(final, _mm256_blend_ps(blend1, blend2, 0xf0));
|
||||
|
||||
hsum1 = _mm256_hadd_ps(vecs8_0, vecs9_0);
|
||||
hsum2 = _mm256_hadd_ps(vecs10_0, vecs11_0);
|
||||
|
|
@ -769,7 +801,7 @@ vecs)
|
|||
blend1 = _mm256_blend_ps(sum1, sum2, 0xcc);
|
||||
blend2 = _mm256_blend_ps(sum3, sum4, 0xcc);
|
||||
|
||||
final_1 = _mm256_add_ps(final_1, _mm256_blend_ps(blend1, blend2, 0xf0));
|
||||
final_1 = padd(final_1, _mm256_blend_ps(blend1, blend2, 0xf0));
|
||||
|
||||
__m512 final_output;
|
||||
|
||||
|
|
@ -819,7 +851,7 @@ template<> EIGEN_STRONG_INLINE Packet8d preduxp<Packet8d>(const Packet8d* vecs)
|
|||
tmp1 = _mm256_hadd_pd(vecs2_1, vecs3_1);
|
||||
tmp1 = _mm256_add_pd(tmp1, _mm256_permute2f128_pd(tmp1, tmp1, 1));
|
||||
|
||||
final_0 = _mm256_add_pd(final_0, _mm256_blend_pd(tmp0, tmp1, 0xC));
|
||||
final_0 = padd(final_0, _mm256_blend_pd(tmp0, tmp1, 0xC));
|
||||
|
||||
tmp0 = _mm256_hadd_pd(vecs4_0, vecs5_0);
|
||||
tmp0 = _mm256_add_pd(tmp0, _mm256_permute2f128_pd(tmp0, tmp0, 1));
|
||||
|
|
@ -835,7 +867,7 @@ template<> EIGEN_STRONG_INLINE Packet8d preduxp<Packet8d>(const Packet8d* vecs)
|
|||
tmp1 = _mm256_hadd_pd(vecs6_1, vecs7_1);
|
||||
tmp1 = _mm256_add_pd(tmp1, _mm256_permute2f128_pd(tmp1, tmp1, 1));
|
||||
|
||||
final_1 = _mm256_add_pd(final_1, _mm256_blend_pd(tmp0, tmp1, 0xC));
|
||||
final_1 = padd(final_1, _mm256_blend_pd(tmp0, tmp1, 0xC));
|
||||
|
||||
__m512d final_output = _mm512_insertf64x4(final_output, final_0, 0);
|
||||
|
||||
|
|
@ -844,52 +876,55 @@ template<> EIGEN_STRONG_INLINE Packet8d preduxp<Packet8d>(const Packet8d* vecs)
|
|||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux<Packet16f>(const Packet16f& a) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
__m256 lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
__m256 lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
Packet8f x = _mm256_add_ps(lane0, lane1);
|
||||
return predux<Packet8f>(x);
|
||||
//#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
#if 0
|
||||
Packet8f lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
Packet8f lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
Packet8f sum = padd(lane0, lane1);
|
||||
Packet8f tmp0 = _mm256_hadd_ps(sum, _mm256_permute2f128_ps(a, a, 1));
|
||||
tmp0 = _mm256_hadd_ps(tmp0, tmp0);
|
||||
return pfirst(_mm256_hadd_ps(tmp0, tmp0));
|
||||
#else
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 sum = _mm_add_ps(_mm_add_ps(lane0, lane1), _mm_add_ps(lane2, lane3));
|
||||
Packet4f lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
Packet4f lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
Packet4f lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
Packet4f lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
Packet4f sum = padd(padd(lane0, lane1), padd(lane2, lane3));
|
||||
sum = _mm_hadd_ps(sum, sum);
|
||||
sum = _mm_hadd_ps(sum, _mm_permute_ps(sum, 1));
|
||||
return _mm_cvtss_f32(sum);
|
||||
return pfirst(sum);
|
||||
#endif
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d sum = _mm256_add_pd(lane0, lane1);
|
||||
__m256d tmp0 = _mm256_hadd_pd(sum, _mm256_permute2f128_pd(sum, sum, 1));
|
||||
return _mm_cvtsd_f64(_mm256_castpd256_pd128(_mm256_hadd_pd(tmp0, tmp0)));
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
Packet4d sum = padd(lane0, lane1);
|
||||
Packet4d tmp0 = _mm256_hadd_pd(sum, _mm256_permute2f128_pd(sum, sum, 1));
|
||||
return pfirst(_mm256_hadd_pd(tmp0, tmp0));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f predux_downto4<Packet16f>(const Packet16f& a) {
|
||||
#ifdef EIGEN_VECTORIZE_AVX512DQ
|
||||
__m256 lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
__m256 lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
return _mm256_add_ps(lane0, lane1);
|
||||
Packet8f lane0 = _mm512_extractf32x8_ps(a, 0);
|
||||
Packet8f lane1 = _mm512_extractf32x8_ps(a, 1);
|
||||
return padd(lane0, lane1);
|
||||
#else
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 sum0 = _mm_add_ps(lane0, lane2);
|
||||
__m128 sum1 = _mm_add_ps(lane1, lane3);
|
||||
Packet4f lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
Packet4f lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
Packet4f lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
Packet4f lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
Packet4f sum0 = padd(lane0, lane2);
|
||||
Packet4f sum1 = padd(lane1, lane3);
|
||||
return _mm256_insertf128_ps(_mm256_castps128_ps256(sum0), sum1, 1);
|
||||
#endif
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4d predux_downto4<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d res = _mm256_add_pd(lane0, lane1);
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
Packet4d res = padd(lane0, lane1);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -904,59 +939,58 @@ EIGEN_STRONG_INLINE float predux_mul<Packet16f>(const Packet16f& a) {
|
|||
res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1))));
|
||||
#else
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 res = pmul(pmul(lane0, lane1), pmul(lane2, lane3));
|
||||
Packet4f lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
Packet4f lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
Packet4f lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
Packet4f lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
Packet4f res = pmul(pmul(lane0, lane1), pmul(lane2, lane3));
|
||||
res = pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
return pfirst(pmul(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1))));
|
||||
#endif
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_mul<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d res = pmul(lane0, lane1);
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
Packet4d res = pmul(lane0, lane1);
|
||||
res = pmul(res, _mm256_permute2f128_pd(res, res, 1));
|
||||
return pfirst(pmul(res, _mm256_shuffle_pd(res, res, 1)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_min<Packet16f>(const Packet16f& a) {
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 res = _mm_min_ps(_mm_min_ps(lane0, lane1), _mm_min_ps(lane2, lane3));
|
||||
Packet4f lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
Packet4f lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
Packet4f lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
Packet4f lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
Packet4f res = _mm_min_ps(_mm_min_ps(lane0, lane1), _mm_min_ps(lane2, lane3));
|
||||
res = _mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
return pfirst(_mm_min_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1))));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_min<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d res = _mm256_min_pd(lane0, lane1);
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
Packet4d res = _mm256_min_pd(lane0, lane1);
|
||||
res = _mm256_min_pd(res, _mm256_permute2f128_pd(res, res, 1));
|
||||
return pfirst(_mm256_min_pd(res, _mm256_shuffle_pd(res, res, 1)));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float predux_max<Packet16f>(const Packet16f& a) {
|
||||
__m128 lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
__m128 lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
__m128 lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
__m128 lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
__m128 res = _mm_max_ps(_mm_max_ps(lane0, lane1), _mm_max_ps(lane2, lane3));
|
||||
Packet4f lane0 = _mm512_extractf32x4_ps(a, 0);
|
||||
Packet4f lane1 = _mm512_extractf32x4_ps(a, 1);
|
||||
Packet4f lane2 = _mm512_extractf32x4_ps(a, 2);
|
||||
Packet4f lane3 = _mm512_extractf32x4_ps(a, 3);
|
||||
Packet4f res = _mm_max_ps(_mm_max_ps(lane0, lane1), _mm_max_ps(lane2, lane3));
|
||||
res = _mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 3, 2)));
|
||||
return pfirst(_mm_max_ps(res, _mm_permute_ps(res, _MM_SHUFFLE(0, 0, 0, 1))));
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double predux_max<Packet8d>(const Packet8d& a) {
|
||||
__m256d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
__m256d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
__m256d res = _mm256_max_pd(lane0, lane1);
|
||||
Packet4d lane0 = _mm512_extractf64x4_pd(a, 0);
|
||||
Packet4d lane1 = _mm512_extractf64x4_pd(a, 1);
|
||||
Packet4d res = _mm256_max_pd(lane0, lane1);
|
||||
res = _mm256_max_pd(res, _mm256_permute2f128_pd(res, res, 1));
|
||||
return pfirst(_mm256_max_pd(res, _mm256_shuffle_pd(res, res, 1)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type;
|
|||
template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from)
|
||||
{
|
||||
Packet2cf res;
|
||||
if((ptrdiff_t(&from) % 16) == 0)
|
||||
if((std::ptrdiff_t(&from) % 16) == 0)
|
||||
res.v = pload<Packet4f>((const float *)&from);
|
||||
else
|
||||
res.v = ploadu<Packet4f>((const float *)&from);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ static Packet16uc p16uc_DUPLICATE32_HI = { 0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7 };
|
|||
#define _EIGEN_MASK_ALIGNMENT 0xfffffff0
|
||||
#endif
|
||||
|
||||
#define _EIGEN_ALIGNED_PTR(x) ((ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT)
|
||||
#define _EIGEN_ALIGNED_PTR(x) ((std::ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT)
|
||||
|
||||
// Handle endianness properly while loading constants
|
||||
// Define global static constants:
|
||||
|
|
@ -450,15 +450,15 @@ template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from)
|
|||
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
||||
{
|
||||
Packet4f p;
|
||||
if((ptrdiff_t(from) % 16) == 0) p = pload<Packet4f>(from);
|
||||
else p = ploadu<Packet4f>(from);
|
||||
if((std::ptrdiff_t(from) % 16) == 0) p = pload<Packet4f>(from);
|
||||
else p = ploadu<Packet4f>(from);
|
||||
return vec_perm(p, p, p16uc_DUPLICATE32_HI);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
|
||||
{
|
||||
Packet4i p;
|
||||
if((ptrdiff_t(from) % 16) == 0) p = pload<Packet4i>(from);
|
||||
else p = ploadu<Packet4i>(from);
|
||||
if((std::ptrdiff_t(from) % 16) == 0) p = pload<Packet4i>(from);
|
||||
else p = ploadu<Packet4i>(from);
|
||||
return vec_perm(p, p, p16uc_DUPLICATE32_HI);
|
||||
}
|
||||
|
||||
|
|
@ -935,8 +935,8 @@ template<> EIGEN_STRONG_INLINE Packet2d ploadu<Packet2d>(const double* from)
|
|||
template<> EIGEN_STRONG_INLINE Packet2d ploaddup<Packet2d>(const double* from)
|
||||
{
|
||||
Packet2d p;
|
||||
if((ptrdiff_t(from) % 16) == 0) p = pload<Packet2d>(from);
|
||||
else p = ploadu<Packet2d>(from);
|
||||
if((std::ptrdiff_t(from) % 16) == 0) p = pload<Packet2d>(from);
|
||||
else p = ploadu<Packet2d>(from);
|
||||
return vec_splat_dbl<0>(p);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// "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
|
||||
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
|
@ -53,7 +53,7 @@ namespace half_impl {
|
|||
|
||||
// Make our own __half definition that is similar to CUDA's.
|
||||
struct __half {
|
||||
EIGEN_DEVICE_FUNC __half() : x(0) {}
|
||||
EIGEN_DEVICE_FUNC __half() {}
|
||||
explicit EIGEN_DEVICE_FUNC __half(unsigned short raw) : x(raw) {}
|
||||
unsigned short x;
|
||||
};
|
||||
|
|
@ -386,18 +386,11 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half abs(const half& a) {
|
|||
return result;
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half exp(const half& a) {
|
||||
#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 530
|
||||
return half(hexp(a));
|
||||
#else
|
||||
return half(::expf(float(a)));
|
||||
#endif
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half expm1(const half& a) {
|
||||
return half(numext::expm1(float(a)));
|
||||
return half(::expf(float(a)));
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log(const half& a) {
|
||||
#if defined(EIGEN_HAS_CUDA_FP16) && defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 530
|
||||
return half(::hlog(a));
|
||||
return Eigen::half(::hlog(a));
|
||||
#else
|
||||
return half(::logf(float(a)));
|
||||
#endif
|
||||
|
|
@ -409,11 +402,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half log10(const half& a) {
|
|||
return half(::log10f(float(a)));
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half sqrt(const half& a) {
|
||||
#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 530
|
||||
return half(hsqrt(a));
|
||||
#else
|
||||
return half(::sqrtf(float(a)));
|
||||
#endif
|
||||
return half(::sqrtf(float(a)));
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half pow(const half& a, const half& b) {
|
||||
return half(::powf(float(a), float(b)));
|
||||
|
|
@ -431,18 +420,10 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half tanh(const half& a) {
|
|||
return half(::tanhf(float(a)));
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half floor(const half& a) {
|
||||
#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 300
|
||||
return half(hfloor(a));
|
||||
#else
|
||||
return half(::floorf(float(a)));
|
||||
#endif
|
||||
}
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half ceil(const half& a) {
|
||||
#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 300
|
||||
return half(hceil(a));
|
||||
#else
|
||||
return half(::ceilf(float(a)));
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half (min)(const half& a, const half& b) {
|
||||
|
|
@ -493,9 +474,59 @@ template<> struct is_arithmetic<half> { enum { value = true }; };
|
|||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct numeric_limits<Eigen::half> {
|
||||
static const bool is_specialized = true;
|
||||
static const bool is_signed = true;
|
||||
static const bool is_integer = false;
|
||||
static const bool is_exact = false;
|
||||
static const bool has_infinity = true;
|
||||
static const bool has_quiet_NaN = true;
|
||||
static const bool has_signaling_NaN = true;
|
||||
static const float_denorm_style has_denorm = denorm_present;
|
||||
static const bool has_denorm_loss = false;
|
||||
static const std::float_round_style round_style = std::round_to_nearest;
|
||||
static const bool is_iec559 = false;
|
||||
static const bool is_bounded = false;
|
||||
static const bool is_modulo = false;
|
||||
static const int digits = 11;
|
||||
static const int digits10 = 2;
|
||||
//static const int max_digits10 = ;
|
||||
static const int radix = 2;
|
||||
static const int min_exponent = -13;
|
||||
static const int min_exponent10 = -4;
|
||||
static const int max_exponent = 16;
|
||||
static const int max_exponent10 = 4;
|
||||
static const bool traps = true;
|
||||
static const bool tinyness_before = false;
|
||||
|
||||
static Eigen::half (min)() { return Eigen::half_impl::raw_uint16_to_half(0x400); }
|
||||
static Eigen::half lowest() { return Eigen::half_impl::raw_uint16_to_half(0xfbff); }
|
||||
static Eigen::half (max)() { return Eigen::half_impl::raw_uint16_to_half(0x7bff); }
|
||||
static Eigen::half epsilon() { return Eigen::half_impl::raw_uint16_to_half(0x0800); }
|
||||
static Eigen::half round_error() { return Eigen::half(0.5); }
|
||||
static Eigen::half infinity() { return Eigen::half_impl::raw_uint16_to_half(0x7c00); }
|
||||
static Eigen::half quiet_NaN() { return Eigen::half_impl::raw_uint16_to_half(0x7e00); }
|
||||
static Eigen::half signaling_NaN() { return Eigen::half_impl::raw_uint16_to_half(0x7e00); }
|
||||
static Eigen::half denorm_min() { return Eigen::half_impl::raw_uint16_to_half(0x1); }
|
||||
};
|
||||
}
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<> struct NumTraits<Eigen::half>
|
||||
: GenericNumTraits<Eigen::half>
|
||||
{
|
||||
enum {
|
||||
IsSigned = true,
|
||||
IsInteger = false,
|
||||
IsComplex = false,
|
||||
RequireInitialization = false
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Eigen::half epsilon() {
|
||||
return half_impl::raw_uint16_to_half(0x0800);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,18 +56,6 @@ double2 pexp<double2>(const double2& a)
|
|||
return make_double2(exp(a.x), exp(a.y));
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
float4 pexpm1<float4>(const float4& a)
|
||||
{
|
||||
return make_float4(expm1f(a.x), expm1f(a.y), expm1f(a.z), expm1f(a.w));
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
double2 pexpm1<double2>(const double2& a)
|
||||
{
|
||||
return make_double2(expm1(a.x), expm1(a.y));
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||
float4 psqrt<float4>(const float4& a)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ template<> EIGEN_DEVICE_FUNC inline double2 pabs<double2>(const double2& a) {
|
|||
|
||||
EIGEN_DEVICE_FUNC inline void
|
||||
ptranspose(PacketBlock<float4,4>& kernel) {
|
||||
double tmp = kernel.packet[0].y;
|
||||
float tmp = kernel.packet[0].y;
|
||||
kernel.packet[0].y = kernel.packet[1].x;
|
||||
kernel.packet[1].x = tmp;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ template<> struct packet_traits<Eigen::half> : default_packet_traits
|
|||
HasSqrt = 1,
|
||||
HasRsqrt = 1,
|
||||
HasExp = 1,
|
||||
HasExpm1 = 1,
|
||||
HasLog = 1,
|
||||
HasLog1p = 1
|
||||
};
|
||||
|
|
@ -276,14 +275,6 @@ template<> __device__ EIGEN_STRONG_INLINE half2 plog1p<half2>(const half2& a) {
|
|||
return __floats2half2_rn(r1, r2);
|
||||
}
|
||||
|
||||
template<> __device__ EIGEN_STRONG_INLINE half2 pexpm1<half2>(const half2& a) {
|
||||
float a1 = __low2float(a);
|
||||
float a2 = __high2float(a);
|
||||
float r1 = expm1f(a1);
|
||||
float r2 = expm1f(a2);
|
||||
return __floats2half2_rn(r1, r2);
|
||||
}
|
||||
|
||||
#if defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000 && defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 530
|
||||
|
||||
template<> __device__ EIGEN_STRONG_INLINE
|
||||
|
|
|
|||
|
|
@ -46,19 +46,22 @@ typedef uint32x4_t Packet4ui;
|
|||
const Packet4f p4f_##NAME = pset1<Packet4f>(X)
|
||||
|
||||
#define _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(NAME,X) \
|
||||
const Packet4f p4f_##NAME = vreinterpretq_f32_u32(pset1<int>(X))
|
||||
const Packet4f p4f_##NAME = vreinterpretq_f32_u32(pset1<int32_t>(X))
|
||||
|
||||
#define _EIGEN_DECLARE_CONST_Packet4i(NAME,X) \
|
||||
const Packet4i p4i_##NAME = pset1<Packet4i>(X)
|
||||
|
||||
// arm64 does have the pld instruction. If available, let's trust the __builtin_prefetch built-in function
|
||||
// which available on LLVM and GCC (at least)
|
||||
#if EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC
|
||||
#if EIGEN_ARCH_ARM64
|
||||
// __builtin_prefetch tends to do nothing on ARM64 compilers because the
|
||||
// prefetch instructions there are too detailed for __builtin_prefetch to map
|
||||
// meaningfully to them.
|
||||
#define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__("prfm pldl1keep, [%[addr]]\n" ::[addr] "r"(ADDR) : );
|
||||
#elif EIGEN_HAS_BUILTIN(__builtin_prefetch) || EIGEN_COMP_GNUC
|
||||
#define EIGEN_ARM_PREFETCH(ADDR) __builtin_prefetch(ADDR);
|
||||
#elif defined __pld
|
||||
#define EIGEN_ARM_PREFETCH(ADDR) __pld(ADDR)
|
||||
#elif !EIGEN_ARCH_ARM64
|
||||
#define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ( " pld [%[addr]]\n" :: [addr] "r" (ADDR) : "cc" );
|
||||
#elif EIGEN_ARCH_ARM32
|
||||
#define EIGEN_ARM_PREFETCH(ADDR) __asm__ __volatile__ ("pld [%[addr]]\n" :: [addr] "r" (ADDR) : );
|
||||
#else
|
||||
// by default no explicit prefetching
|
||||
#define EIGEN_ARM_PREFETCH(ADDR)
|
||||
|
|
@ -83,7 +86,7 @@ template<> struct packet_traits<float> : default_packet_traits
|
|||
HasSqrt = 0
|
||||
};
|
||||
};
|
||||
template<> struct packet_traits<int> : default_packet_traits
|
||||
template<> struct packet_traits<int32_t> : default_packet_traits
|
||||
{
|
||||
typedef Packet4i type;
|
||||
typedef Packet4i half; // Packet2i intrinsics not implemented yet
|
||||
|
|
@ -105,19 +108,19 @@ EIGEN_STRONG_INLINE void vst1q_f32(float* to, float32x4_t from) { ::vst1q
|
|||
EIGEN_STRONG_INLINE void vst1_f32 (float* to, float32x2_t from) { ::vst1_f32 ((float32_t*)to,from); }
|
||||
#endif
|
||||
|
||||
template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4, alignment=Aligned16}; typedef Packet4f half; };
|
||||
template<> struct unpacket_traits<Packet4i> { typedef int type; enum {size=4, alignment=Aligned16}; typedef Packet4i half; };
|
||||
template<> struct unpacket_traits<Packet4f> { typedef float type; enum {size=4, alignment=Aligned16}; typedef Packet4f half; };
|
||||
template<> struct unpacket_traits<Packet4i> { typedef int32_t type; enum {size=4, alignment=Aligned16}; typedef Packet4i half; };
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pset1<Packet4f>(const float& from) { return vdupq_n_f32(from); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int& from) { return vdupq_n_s32(from); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pset1<Packet4i>(const int32_t& from) { return vdupq_n_s32(from); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f plset<Packet4f>(const float& a)
|
||||
{
|
||||
const float32_t f[] = {0, 1, 2, 3};
|
||||
const float f[] = {0, 1, 2, 3};
|
||||
Packet4f countdown = vld1q_f32(f);
|
||||
return vaddq_f32(pset1<Packet4f>(a), countdown);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet4i plset<Packet4i>(const int& a)
|
||||
template<> EIGEN_STRONG_INLINE Packet4i plset<Packet4i>(const int32_t& a)
|
||||
{
|
||||
const int32_t i[] = {0, 1, 2, 3};
|
||||
Packet4i countdown = vld1q_s32(i);
|
||||
|
|
@ -240,20 +243,20 @@ template<> EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, con
|
|||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pandnot<Packet4i>(const Packet4i& a, const Packet4i& b) { return vbicq_s32(a,b); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_f32(from); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_s32(from); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_f32(from); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int32_t* from) { EIGEN_DEBUG_ALIGNED_LOAD return vld1q_s32(from); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_f32(from); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_s32(from); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4f ploadu<Packet4f>(const float* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_f32(from); }
|
||||
template<> EIGEN_STRONG_INLINE Packet4i ploadu<Packet4i>(const int32_t* from) { EIGEN_DEBUG_UNALIGNED_LOAD return vld1q_s32(from); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
||||
template<> EIGEN_STRONG_INLINE Packet4f ploaddup<Packet4f>(const float* from)
|
||||
{
|
||||
float32x2_t lo, hi;
|
||||
lo = vld1_dup_f32(from);
|
||||
hi = vld1_dup_f32(from+1);
|
||||
return vcombine_f32(lo, hi);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
|
||||
template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int32_t* from)
|
||||
{
|
||||
int32x2_t lo, hi;
|
||||
lo = vld1_dup_s32(from);
|
||||
|
|
@ -261,11 +264,11 @@ template<> EIGEN_STRONG_INLINE Packet4i ploaddup<Packet4i>(const int* from)
|
|||
return vcombine_s32(lo, hi);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE void pstore<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_f32(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_s32(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void pstore<float> (float* to, const Packet4f& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_f32(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void pstore<int32_t>(int32_t* to, const Packet4i& from) { EIGEN_DEBUG_ALIGNED_STORE vst1q_s32(to, from); }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<float>(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<int>(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<float> (float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_f32(to, from); }
|
||||
template<> EIGEN_STRONG_INLINE void pstoreu<int32_t>(int32_t* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE vst1q_s32(to, from); }
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const float* from, Index stride)
|
||||
{
|
||||
|
|
@ -276,7 +279,7 @@ template<> EIGEN_DEVICE_FUNC inline Packet4f pgather<float, Packet4f>(const floa
|
|||
res = vsetq_lane_f32(from[3*stride], res, 3);
|
||||
return res;
|
||||
}
|
||||
template<> EIGEN_DEVICE_FUNC inline Packet4i pgather<int, Packet4i>(const int* from, Index stride)
|
||||
template<> EIGEN_DEVICE_FUNC inline Packet4i pgather<int32_t, Packet4i>(const int32_t* from, Index stride)
|
||||
{
|
||||
Packet4i res = pset1<Packet4i>(0);
|
||||
res = vsetq_lane_s32(from[0*stride], res, 0);
|
||||
|
|
@ -293,7 +296,7 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter<float, Packet4f>(float* to, co
|
|||
to[stride*2] = vgetq_lane_f32(from, 2);
|
||||
to[stride*3] = vgetq_lane_f32(from, 3);
|
||||
}
|
||||
template<> EIGEN_DEVICE_FUNC inline void pscatter<int, Packet4i>(int* to, const Packet4i& from, Index stride)
|
||||
template<> EIGEN_DEVICE_FUNC inline void pscatter<int32_t, Packet4i>(int32_t* to, const Packet4i& from, Index stride)
|
||||
{
|
||||
to[stride*0] = vgetq_lane_s32(from, 0);
|
||||
to[stride*1] = vgetq_lane_s32(from, 1);
|
||||
|
|
@ -301,12 +304,12 @@ template<> EIGEN_DEVICE_FUNC inline void pscatter<int, Packet4i>(int* to, const
|
|||
to[stride*3] = vgetq_lane_s32(from, 3);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) { EIGEN_ARM_PREFETCH(addr); }
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<int>(const int* addr) { EIGEN_ARM_PREFETCH(addr); }
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<float> (const float* addr) { EIGEN_ARM_PREFETCH(addr); }
|
||||
template<> EIGEN_STRONG_INLINE void prefetch<int32_t>(const int32_t* addr) { EIGEN_ARM_PREFETCH(addr); }
|
||||
|
||||
// FIXME only store the 2 first elements ?
|
||||
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; }
|
||||
template<> EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) { int EIGEN_ALIGN16 x[4]; vst1q_s32(x, a); return x[0]; }
|
||||
template<> EIGEN_STRONG_INLINE float pfirst<Packet4f>(const Packet4f& a) { float EIGEN_ALIGN16 x[4]; vst1q_f32(x, a); return x[0]; }
|
||||
template<> EIGEN_STRONG_INLINE int32_t pfirst<Packet4i>(const Packet4i& a) { int32_t EIGEN_ALIGN16 x[4]; vst1q_s32(x, a); return x[0]; }
|
||||
|
||||
template<> EIGEN_STRONG_INLINE Packet4f preverse(const Packet4f& a) {
|
||||
float32x2_t a_lo, a_hi;
|
||||
|
|
@ -361,7 +364,7 @@ template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
|
|||
return sum;
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
|
||||
template<> EIGEN_STRONG_INLINE int32_t predux<Packet4i>(const Packet4i& a)
|
||||
{
|
||||
int32x2_t a_lo, a_hi, sum;
|
||||
|
||||
|
|
@ -408,7 +411,7 @@ template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
|
|||
|
||||
return vget_lane_f32(prod, 0);
|
||||
}
|
||||
template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
|
||||
template<> EIGEN_STRONG_INLINE int32_t predux_mul<Packet4i>(const Packet4i& a)
|
||||
{
|
||||
int32x2_t a_lo, a_hi, prod;
|
||||
|
||||
|
|
@ -436,7 +439,7 @@ template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
|
|||
return vget_lane_f32(min, 0);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
|
||||
template<> EIGEN_STRONG_INLINE int32_t predux_min<Packet4i>(const Packet4i& a)
|
||||
{
|
||||
int32x2_t a_lo, a_hi, min;
|
||||
|
||||
|
|
@ -461,7 +464,7 @@ template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
|
|||
return vget_lane_f32(max, 0);
|
||||
}
|
||||
|
||||
template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
|
||||
template<> EIGEN_STRONG_INLINE int32_t predux_max<Packet4i>(const Packet4i& a)
|
||||
{
|
||||
int32x2_t a_lo, a_hi, max;
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ static Packet16uc p16uc_DUPLICATE32_HI = { 0,1,2,3, 0,1,2,3, 4,5,6,7, 4,5,6,7 };
|
|||
// Mask alignment
|
||||
#define _EIGEN_MASK_ALIGNMENT 0xfffffffffffffff0
|
||||
|
||||
#define _EIGEN_ALIGNED_PTR(x) ((ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT)
|
||||
#define _EIGEN_ALIGNED_PTR(x) ((std::ptrdiff_t)(x) & _EIGEN_MASK_ALIGNMENT)
|
||||
|
||||
// Handle endianness properly while loading constants
|
||||
// Define global static constants:
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ template<typename DstScalar,typename SrcScalar> struct assign_op {
|
|||
{ internal::pstoret<DstScalar,Packet,Alignment>(a,b); }
|
||||
};
|
||||
|
||||
// Empty overload for void type (used by PermutationMatrix
|
||||
// Empty overload for void type (used by PermutationMatrix)
|
||||
template<typename DstScalar> struct assign_op<DstScalar,void> {};
|
||||
|
||||
template<typename DstScalar,typename SrcScalar>
|
||||
|
|
|
|||
|
|
@ -44,16 +44,16 @@ struct linspaced_op_impl<Scalar,Packet,/*IsInteger*/false>
|
|||
{
|
||||
linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) :
|
||||
m_low(low), m_high(high), m_size1(num_steps==1 ? 1 : num_steps-1), m_step(num_steps==1 ? Scalar() : (high-low)/Scalar(num_steps-1)),
|
||||
m_interPacket(plset<Packet>(0)),
|
||||
m_flip(numext::abs(high)<numext::abs(low))
|
||||
{}
|
||||
|
||||
template<typename IndexType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (IndexType i) const {
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
if(m_flip)
|
||||
return (i==0)? m_low : (m_high - (m_size1-i)*m_step);
|
||||
return (i==0)? m_low : (m_high - RealScalar(m_size1-i)*m_step);
|
||||
else
|
||||
return (i==m_size1)? m_high : (m_low + i*m_step);
|
||||
return (i==m_size1)? m_high : (m_low + RealScalar(i)*m_step);
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
|
|
@ -63,7 +63,7 @@ struct linspaced_op_impl<Scalar,Packet,/*IsInteger*/false>
|
|||
// [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
|
||||
if(m_flip)
|
||||
{
|
||||
Packet pi = padd(pset1<Packet>(Scalar(i-m_size1)),m_interPacket);
|
||||
Packet pi = plset<Packet>(Scalar(i-m_size1));
|
||||
Packet res = padd(pset1<Packet>(m_high), pmul(pset1<Packet>(m_step), pi));
|
||||
if(i==0)
|
||||
res = pinsertfirst(res, m_low);
|
||||
|
|
@ -71,7 +71,7 @@ struct linspaced_op_impl<Scalar,Packet,/*IsInteger*/false>
|
|||
}
|
||||
else
|
||||
{
|
||||
Packet pi = padd(pset1<Packet>(Scalar(i)),m_interPacket);
|
||||
Packet pi = plset<Packet>(Scalar(i));
|
||||
Packet res = padd(pset1<Packet>(m_low), pmul(pset1<Packet>(m_step), pi));
|
||||
if(i==m_size1-unpacket_traits<Packet>::size+1)
|
||||
res = pinsertlast(res, m_high);
|
||||
|
|
@ -83,7 +83,6 @@ struct linspaced_op_impl<Scalar,Packet,/*IsInteger*/false>
|
|||
const Scalar m_high;
|
||||
const Index m_size1;
|
||||
const Scalar m_step;
|
||||
const Packet m_interPacket;
|
||||
const bool m_flip;
|
||||
};
|
||||
|
||||
|
|
@ -93,8 +92,8 @@ struct linspaced_op_impl<Scalar,Packet,/*IsInteger*/true>
|
|||
linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) :
|
||||
m_low(low),
|
||||
m_multiplier((high-low)/convert_index<Scalar>(num_steps<=1 ? 1 : num_steps-1)),
|
||||
m_divisor(convert_index<Scalar>(num_steps+high-low)/(high-low+1)),
|
||||
m_use_divisor((high+1)<(low+num_steps))
|
||||
m_divisor(convert_index<Scalar>((high>=low?num_steps:-num_steps)+(high-low))/((numext::abs(high-low)+1)==0?1:(numext::abs(high-low)+1))),
|
||||
m_use_divisor(num_steps>1 && (numext::abs(high-low)+1)<num_steps)
|
||||
{}
|
||||
|
||||
template<typename IndexType>
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ template<typename T>
|
|||
struct functor_traits<std::not_equal_to<T> >
|
||||
{ enum { Cost = 1, PacketAccess = false }; };
|
||||
|
||||
#if(__cplusplus < 201103L)
|
||||
#if (__cplusplus < 201103L) && (EIGEN_COMP_MSVC <= 1900)
|
||||
// std::binder* are deprecated since c++11 and will be removed in c++17
|
||||
template<typename T>
|
||||
struct functor_traits<std::binder2nd<T> >
|
||||
|
|
|
|||
|
|
@ -262,26 +262,6 @@ struct functor_traits<scalar_exp_op<Scalar> > {
|
|||
};
|
||||
};
|
||||
|
||||
/** \internal
|
||||
*
|
||||
* \brief Template functor to compute the exponential of a scalar - 1.
|
||||
*
|
||||
* \sa class CwiseUnaryOp, ArrayBase::expm1()
|
||||
*/
|
||||
template<typename Scalar> struct scalar_expm1_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_expm1_op)
|
||||
EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::expm1(a); }
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pexpm1(a); }
|
||||
};
|
||||
template <typename Scalar>
|
||||
struct functor_traits<scalar_expm1_op<Scalar> > {
|
||||
enum {
|
||||
PacketAccess = packet_traits<Scalar>::HasExpm1,
|
||||
Cost = functor_traits<scalar_exp_op<Scalar> >::Cost // TODO measure cost of expm1
|
||||
};
|
||||
};
|
||||
|
||||
/** \internal
|
||||
*
|
||||
* \brief Template functor to compute the logarithm of a scalar
|
||||
|
|
@ -698,13 +678,7 @@ struct functor_traits<scalar_ceil_op<Scalar> >
|
|||
template<typename Scalar> struct scalar_isnan_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_isnan_op)
|
||||
typedef bool result_type;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const {
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
return numext::isnan(a);
|
||||
#else
|
||||
return (numext::isnan)(a);
|
||||
#endif
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isnan)(a); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct functor_traits<scalar_isnan_op<Scalar> >
|
||||
|
|
@ -722,13 +696,7 @@ struct functor_traits<scalar_isnan_op<Scalar> >
|
|||
template<typename Scalar> struct scalar_isinf_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_isinf_op)
|
||||
typedef bool result_type;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const {
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
return numext::isinf(a);
|
||||
#else
|
||||
return (numext::isinf)(a);
|
||||
#endif
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isinf)(a); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct functor_traits<scalar_isinf_op<Scalar> >
|
||||
|
|
@ -746,13 +714,7 @@ struct functor_traits<scalar_isinf_op<Scalar> >
|
|||
template<typename Scalar> struct scalar_isfinite_op {
|
||||
EIGEN_EMPTY_STRUCT_CTOR(scalar_isfinite_op)
|
||||
typedef bool result_type;
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const {
|
||||
#if defined(__SYCL_DEVICE_ONLY__)
|
||||
return numext::isfinite(a);
|
||||
#else
|
||||
return (numext::isfinite)(a);
|
||||
#endif
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isfinite)(a); }
|
||||
};
|
||||
template<typename Scalar>
|
||||
struct functor_traits<scalar_isfinite_op<Scalar> >
|
||||
|
|
|
|||
|
|
@ -1,476 +0,0 @@
|
|||
// 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-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_COEFFBASED_PRODUCT_H
|
||||
#define EIGEN_COEFFBASED_PRODUCT_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/*********************************************************************************
|
||||
* Coefficient based product implementation.
|
||||
* It is designed for the following use cases:
|
||||
* - small fixed sizes
|
||||
* - lazy products
|
||||
*********************************************************************************/
|
||||
|
||||
/* Since the all the dimensions of the product are small, here we can rely
|
||||
* on the generic Assign mechanism to evaluate the product per coeff (or packet).
|
||||
*
|
||||
* Note that here the inner-loops should always be unrolled.
|
||||
*/
|
||||
|
||||
template<int Traversal, int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct product_coeff_impl;
|
||||
|
||||
template<int StorageOrder, int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl;
|
||||
|
||||
template<typename LhsNested, typename RhsNested, int NestingFlags>
|
||||
struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
|
||||
{
|
||||
typedef MatrixXpr XprKind;
|
||||
typedef typename remove_all<LhsNested>::type _LhsNested;
|
||||
typedef typename remove_all<RhsNested>::type _RhsNested;
|
||||
typedef typename scalar_product_traits<typename _LhsNested::Scalar, typename _RhsNested::Scalar>::ReturnType Scalar;
|
||||
typedef typename promote_storage_type<typename traits<_LhsNested>::StorageKind,
|
||||
typename traits<_RhsNested>::StorageKind>::ret StorageKind;
|
||||
typedef typename promote_index_type<typename traits<_LhsNested>::Index,
|
||||
typename traits<_RhsNested>::Index>::type Index;
|
||||
|
||||
enum {
|
||||
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
|
||||
RhsCoeffReadCost = _RhsNested::CoeffReadCost,
|
||||
LhsFlags = _LhsNested::Flags,
|
||||
RhsFlags = _RhsNested::Flags,
|
||||
|
||||
RowsAtCompileTime = _LhsNested::RowsAtCompileTime,
|
||||
ColsAtCompileTime = _RhsNested::ColsAtCompileTime,
|
||||
InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime),
|
||||
|
||||
MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime,
|
||||
|
||||
LhsRowMajor = LhsFlags & RowMajorBit,
|
||||
RhsRowMajor = RhsFlags & RowMajorBit,
|
||||
|
||||
SameType = is_same<typename _LhsNested::Scalar,typename _RhsNested::Scalar>::value,
|
||||
|
||||
CanVectorizeRhs = RhsRowMajor && (RhsFlags & PacketAccessBit)
|
||||
&& (ColsAtCompileTime == Dynamic
|
||||
|| ( (ColsAtCompileTime % packet_traits<Scalar>::size) == 0
|
||||
&& (RhsFlags&AlignedBit)
|
||||
)
|
||||
),
|
||||
|
||||
CanVectorizeLhs = (!LhsRowMajor) && (LhsFlags & PacketAccessBit)
|
||||
&& (RowsAtCompileTime == Dynamic
|
||||
|| ( (RowsAtCompileTime % packet_traits<Scalar>::size) == 0
|
||||
&& (LhsFlags&AlignedBit)
|
||||
)
|
||||
),
|
||||
|
||||
EvalToRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
|
||||
: (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
|
||||
: (RhsRowMajor && !CanVectorizeLhs),
|
||||
|
||||
Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & ~RowMajorBit)
|
||||
| (EvalToRowMajor ? RowMajorBit : 0)
|
||||
| NestingFlags
|
||||
| (LhsFlags & RhsFlags & AlignedBit)
|
||||
// TODO enable vectorization for mixed types
|
||||
| (SameType && (CanVectorizeLhs || CanVectorizeRhs) ? PacketAccessBit : 0),
|
||||
|
||||
CoeffReadCost = InnerSize == Dynamic ? Dynamic
|
||||
: InnerSize == 0 ? 0
|
||||
: InnerSize * (NumTraits<Scalar>::MulCost + LhsCoeffReadCost + RhsCoeffReadCost)
|
||||
+ (InnerSize - 1) * NumTraits<Scalar>::AddCost,
|
||||
|
||||
/* CanVectorizeInner deserves special explanation. It does not affect the product flags. It is not used outside
|
||||
* of Product. If the Product itself is not a packet-access expression, there is still a chance that the inner
|
||||
* loop of the product might be vectorized. This is the meaning of CanVectorizeInner. Since it doesn't affect
|
||||
* the Flags, it is safe to make this value depend on ActualPacketAccessBit, that doesn't affect the ABI.
|
||||
*/
|
||||
CanVectorizeInner = SameType
|
||||
&& LhsRowMajor
|
||||
&& (!RhsRowMajor)
|
||||
&& (LhsFlags & RhsFlags & ActualPacketAccessBit)
|
||||
&& (LhsFlags & RhsFlags & AlignedBit)
|
||||
&& (InnerSize % packet_traits<Scalar>::size == 0)
|
||||
};
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
template<typename LhsNested, typename RhsNested, int NestingFlags>
|
||||
class CoeffBasedProduct
|
||||
: internal::no_assignment_operator,
|
||||
public MatrixBase<CoeffBasedProduct<LhsNested, RhsNested, NestingFlags> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef MatrixBase<CoeffBasedProduct> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(CoeffBasedProduct)
|
||||
typedef typename Base::PlainObject PlainObject;
|
||||
|
||||
private:
|
||||
|
||||
typedef typename internal::traits<CoeffBasedProduct>::_LhsNested _LhsNested;
|
||||
typedef typename internal::traits<CoeffBasedProduct>::_RhsNested _RhsNested;
|
||||
|
||||
enum {
|
||||
PacketSize = internal::packet_traits<Scalar>::size,
|
||||
InnerSize = internal::traits<CoeffBasedProduct>::InnerSize,
|
||||
Unroll = CoeffReadCost != Dynamic && CoeffReadCost <= EIGEN_UNROLLING_LIMIT,
|
||||
CanVectorizeInner = internal::traits<CoeffBasedProduct>::CanVectorizeInner
|
||||
};
|
||||
|
||||
typedef internal::product_coeff_impl<CanVectorizeInner ? InnerVectorizedTraversal : DefaultTraversal,
|
||||
Unroll ? InnerSize : Dynamic,
|
||||
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
|
||||
|
||||
typedef CoeffBasedProduct<LhsNested,RhsNested,NestByRefBit> LazyCoeffBasedProductType;
|
||||
|
||||
public:
|
||||
|
||||
inline CoeffBasedProduct(const CoeffBasedProduct& other)
|
||||
: Base(), m_lhs(other.m_lhs), m_rhs(other.m_rhs)
|
||||
{}
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
inline CoeffBasedProduct(const Lhs& lhs, const Rhs& rhs)
|
||||
: m_lhs(lhs), m_rhs(rhs)
|
||||
{
|
||||
// we don't allow taking products of matrices of different real types, as that wouldn't be vectorizable.
|
||||
// We still allow to mix T and complex<T>.
|
||||
EIGEN_STATIC_ASSERT((internal::scalar_product_traits<typename Lhs::RealScalar, typename Rhs::RealScalar>::Defined),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
eigen_assert(lhs.cols() == rhs.rows()
|
||||
&& "invalid matrix product"
|
||||
&& "if you wanted a coeff-wise or a dot product use the respective explicit functions");
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); }
|
||||
EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); }
|
||||
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(Index row, Index col) const
|
||||
{
|
||||
Scalar res;
|
||||
ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Allow index-based non-packet access. It is impossible though to allow index-based packed access,
|
||||
* which is why we don't set the LinearAccessBit.
|
||||
*/
|
||||
EIGEN_STRONG_INLINE const Scalar coeff(Index index) const
|
||||
{
|
||||
Scalar res;
|
||||
const Index row = RowsAtCompileTime == 1 ? 0 : index;
|
||||
const Index col = RowsAtCompileTime == 1 ? index : 0;
|
||||
ScalarCoeffImpl::run(row, col, m_lhs, m_rhs, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<int LoadMode>
|
||||
EIGEN_STRONG_INLINE const PacketScalar packet(Index row, Index col) const
|
||||
{
|
||||
PacketScalar res;
|
||||
internal::product_packet_impl<Flags&RowMajorBit ? RowMajor : ColMajor,
|
||||
Unroll ? InnerSize : Dynamic,
|
||||
_LhsNested, _RhsNested, PacketScalar, LoadMode>
|
||||
::run(row, col, m_lhs, m_rhs, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
// Implicit conversion to the nested type (trigger the evaluation of the product)
|
||||
EIGEN_STRONG_INLINE operator const PlainObject& () const
|
||||
{
|
||||
m_result.lazyAssign(*this);
|
||||
return m_result;
|
||||
}
|
||||
|
||||
const _LhsNested& lhs() const { return m_lhs; }
|
||||
const _RhsNested& rhs() const { return m_rhs; }
|
||||
|
||||
const Diagonal<const LazyCoeffBasedProductType,0> diagonal() const
|
||||
{ return reinterpret_cast<const LazyCoeffBasedProductType&>(*this); }
|
||||
|
||||
template<int DiagonalIndex>
|
||||
const Diagonal<const LazyCoeffBasedProductType,DiagonalIndex> diagonal() const
|
||||
{ return reinterpret_cast<const LazyCoeffBasedProductType&>(*this); }
|
||||
|
||||
const Diagonal<const LazyCoeffBasedProductType,Dynamic> diagonal(Index index) const
|
||||
{ return reinterpret_cast<const LazyCoeffBasedProductType&>(*this).diagonal(index); }
|
||||
|
||||
protected:
|
||||
typename internal::add_const_on_value_type<LhsNested>::type m_lhs;
|
||||
typename internal::add_const_on_value_type<RhsNested>::type m_rhs;
|
||||
|
||||
mutable PlainObject m_result;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// here we need to overload the nested rule for products
|
||||
// such that the nested type is a const reference to a plain matrix
|
||||
template<typename Lhs, typename Rhs, int N, typename PlainObject>
|
||||
struct nested<CoeffBasedProduct<Lhs,Rhs,EvalBeforeNestingBit|EvalBeforeAssigningBit>, N, PlainObject>
|
||||
{
|
||||
typedef PlainObject const& type;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* Normal product .coeff() implementation (with meta-unrolling)
|
||||
***************************************************************************/
|
||||
|
||||
/**************************************
|
||||
*** Scalar path - no vectorization ***
|
||||
**************************************/
|
||||
|
||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct product_coeff_impl<DefaultTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||
{
|
||||
product_coeff_impl<DefaultTraversal, UnrollingIndex-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, res);
|
||||
res += lhs.coeff(row, UnrollingIndex-1) * rhs.coeff(UnrollingIndex-1, col);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct product_coeff_impl<DefaultTraversal, 1, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||
{
|
||||
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct product_coeff_impl<DefaultTraversal, 0, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, RetScalar &res)
|
||||
{
|
||||
res = RetScalar(0);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct product_coeff_impl<DefaultTraversal, Dynamic, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar& res)
|
||||
{
|
||||
res = (lhs.row(row).transpose().cwiseProduct( rhs.col(col) )).sum();
|
||||
}
|
||||
};
|
||||
|
||||
/*******************************************
|
||||
*** Scalar path with inner vectorization ***
|
||||
*******************************************/
|
||||
|
||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet>
|
||||
struct product_coeff_vectorized_unroller
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
enum { PacketSize = packet_traits<typename Lhs::Scalar>::size };
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
|
||||
{
|
||||
product_coeff_vectorized_unroller<UnrollingIndex-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres);
|
||||
pres = padd(pres, pmul( lhs.template packet<Aligned>(row, UnrollingIndex) , rhs.template packet<Aligned>(UnrollingIndex, col) ));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename Packet>
|
||||
struct product_coeff_vectorized_unroller<0, Lhs, Rhs, Packet>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres)
|
||||
{
|
||||
pres = pmul(lhs.template packet<Aligned>(row, 0) , rhs.template packet<Aligned>(0, col));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct product_coeff_impl<InnerVectorizedTraversal, 0, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, RetScalar &res)
|
||||
{
|
||||
res = 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct product_coeff_impl<InnerVectorizedTraversal, UnrollingIndex, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
typedef typename Lhs::PacketScalar Packet;
|
||||
typedef typename Lhs::Index Index;
|
||||
enum { PacketSize = packet_traits<typename Lhs::Scalar>::size };
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
|
||||
{
|
||||
Packet pres;
|
||||
product_coeff_vectorized_unroller<UnrollingIndex-PacketSize, Lhs, Rhs, Packet>::run(row, col, lhs, rhs, pres);
|
||||
res = predux(pres);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, int LhsRows = Lhs::RowsAtCompileTime, int RhsCols = Rhs::ColsAtCompileTime>
|
||||
struct product_coeff_vectorized_dyn_selector
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
res = lhs.row(row).transpose().cwiseProduct(rhs.col(col)).sum();
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE the 3 following specializations are because taking .col(0) on a vector is a bit slower
|
||||
// NOTE maybe they are now useless since we have a specialization for Block<Matrix>
|
||||
template<typename Lhs, typename Rhs, int RhsCols>
|
||||
struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,RhsCols>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
res = lhs.transpose().cwiseProduct(rhs.col(col)).sum();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, int LhsRows>
|
||||
struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,LhsRows,1>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
res = lhs.row(row).transpose().cwiseProduct(rhs).sum();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
res = lhs.transpose().cwiseProduct(rhs).sum();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||
struct product_coeff_impl<InnerVectorizedTraversal, Dynamic, Lhs, Rhs, RetScalar>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||
{
|
||||
product_coeff_vectorized_dyn_selector<Lhs,Rhs>::run(row, col, lhs, rhs, res);
|
||||
}
|
||||
};
|
||||
|
||||
/*******************
|
||||
*** Packet path ***
|
||||
*******************/
|
||||
|
||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl<RowMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
||||
{
|
||||
product_packet_impl<RowMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res);
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, UnrollingIndex-1)), rhs.template packet<LoadMode>(UnrollingIndex-1, col), res);
|
||||
}
|
||||
};
|
||||
|
||||
template<int UnrollingIndex, typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl<ColMajor, UnrollingIndex, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
||||
{
|
||||
product_packet_impl<ColMajor, UnrollingIndex-1, Lhs, Rhs, Packet, LoadMode>::run(row, col, lhs, rhs, res);
|
||||
res = pmadd(lhs.template packet<LoadMode>(row, UnrollingIndex-1), pset1<Packet>(rhs.coeff(UnrollingIndex-1, col)), res);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl<RowMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
||||
{
|
||||
res = pmul(pset1<Packet>(lhs.coeff(row, 0)),rhs.template packet<LoadMode>(0, col));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl<ColMajor, 1, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res)
|
||||
{
|
||||
res = pmul(lhs.template packet<LoadMode>(row, 0), pset1<Packet>(rhs.coeff(0, col)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl<RowMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Packet &res)
|
||||
{
|
||||
res = pset1<Packet>(0);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl<ColMajor, 0, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& /*lhs*/, const Rhs& /*rhs*/, Packet &res)
|
||||
{
|
||||
res = pset1<Packet>(0);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl<RowMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res)
|
||||
{
|
||||
res = pset1<Packet>(0);
|
||||
for(Index i = 0; i < lhs.cols(); ++i)
|
||||
res = pmadd(pset1<Packet>(lhs.coeff(row, i)), rhs.template packet<LoadMode>(i, col), res);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs, typename Packet, int LoadMode>
|
||||
struct product_packet_impl<ColMajor, Dynamic, Lhs, Rhs, Packet, LoadMode>
|
||||
{
|
||||
typedef typename Lhs::Index Index;
|
||||
static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res)
|
||||
{
|
||||
res = pset1<Packet>(0);
|
||||
for(Index i = 0; i < lhs.cols(); ++i)
|
||||
res = pmadd(lhs.template packet<LoadMode>(row, i), pset1<Packet>(rhs.coeff(i, col)), res);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_COEFFBASED_PRODUCT_H
|
||||
|
|
@ -83,8 +83,8 @@ static void run(Index rows, Index cols, Index depth,
|
|||
if(info)
|
||||
{
|
||||
// this is the parallel version!
|
||||
Index tid = omp_get_thread_num();
|
||||
Index threads = omp_get_num_threads();
|
||||
int tid = omp_get_thread_num();
|
||||
int threads = omp_get_num_threads();
|
||||
|
||||
LhsScalar* blockA = blocking.blockA();
|
||||
eigen_internal_assert(blockA!=0);
|
||||
|
|
@ -116,9 +116,9 @@ static void run(Index rows, Index cols, Index depth,
|
|||
info[tid].sync = k;
|
||||
|
||||
// Computes C_i += A' * B' per A'_i
|
||||
for(Index shift=0; shift<threads; ++shift)
|
||||
for(int shift=0; shift<threads; ++shift)
|
||||
{
|
||||
Index i = (tid+shift)%threads;
|
||||
int i = (tid+shift)%threads;
|
||||
|
||||
// At this point we have to make sure that A'_i has been updated by the thread i,
|
||||
// we use testAndSetOrdered to mimic a volatile access.
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ struct tribb_kernel
|
|||
ResMapper res(_res, resStride);
|
||||
gebp_kernel<LhsScalar, RhsScalar, Index, ResMapper, mr, nr, ConjLhs, ConjRhs> gebp_kernel;
|
||||
|
||||
Matrix<ResScalar,BlockSize,BlockSize,ColMajor> buffer;
|
||||
Matrix<ResScalar,BlockSize,BlockSize,ColMajor> buffer((internal::constructor_without_unaligned_array_assert()));
|
||||
|
||||
// let's process the block per panel of actual_mc x BlockSize,
|
||||
// again, each is split into three parts, etc.
|
||||
|
|
@ -199,7 +199,7 @@ struct general_product_to_triangular_selector;
|
|||
template<typename MatrixType, typename ProductType, int UpLo>
|
||||
struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,true>
|
||||
{
|
||||
static void run(MatrixType& mat, const ProductType& prod, const typename MatrixType::Scalar& alpha)
|
||||
static void run(MatrixType& mat, const ProductType& prod, const typename MatrixType::Scalar& alpha, bool beta)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
|
|
@ -217,6 +217,9 @@ struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,true>
|
|||
|
||||
Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs().derived()) * RhsBlasTraits::extractScalarFactor(prod.rhs().derived());
|
||||
|
||||
if(!beta)
|
||||
mat.template triangularView<UpLo>().setZero();
|
||||
|
||||
enum {
|
||||
StorageOrder = (internal::traits<MatrixType>::Flags&RowMajorBit) ? RowMajor : ColMajor,
|
||||
UseLhsDirectly = _ActualLhs::InnerStrideAtCompileTime==1,
|
||||
|
|
@ -244,7 +247,7 @@ struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,true>
|
|||
template<typename MatrixType, typename ProductType, int UpLo>
|
||||
struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,false>
|
||||
{
|
||||
static void run(MatrixType& mat, const ProductType& prod, const typename MatrixType::Scalar& alpha)
|
||||
static void run(MatrixType& mat, const ProductType& prod, const typename MatrixType::Scalar& alpha, bool beta)
|
||||
{
|
||||
typedef typename internal::remove_all<typename ProductType::LhsNested>::type Lhs;
|
||||
typedef internal::blas_traits<Lhs> LhsBlasTraits;
|
||||
|
|
@ -260,13 +263,19 @@ struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,false>
|
|||
|
||||
typename ProductType::Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs().derived()) * RhsBlasTraits::extractScalarFactor(prod.rhs().derived());
|
||||
|
||||
if(!beta)
|
||||
mat.template triangularView<UpLo>().setZero();
|
||||
|
||||
enum {
|
||||
IsRowMajor = (internal::traits<MatrixType>::Flags&RowMajorBit) ? 1 : 0,
|
||||
LhsIsRowMajor = _ActualLhs::Flags&RowMajorBit ? 1 : 0,
|
||||
RhsIsRowMajor = _ActualRhs::Flags&RowMajorBit ? 1 : 0
|
||||
RhsIsRowMajor = _ActualRhs::Flags&RowMajorBit ? 1 : 0,
|
||||
SkipDiag = (UpLo&(UnitDiag|ZeroDiag))!=0
|
||||
};
|
||||
|
||||
Index size = mat.cols();
|
||||
if(SkipDiag)
|
||||
size--;
|
||||
Index depth = actualLhs.cols();
|
||||
|
||||
typedef internal::gemm_blocking_space<IsRowMajor ? RowMajor : ColMajor,typename Lhs::Scalar,typename Rhs::Scalar,
|
||||
|
|
@ -277,20 +286,22 @@ struct general_product_to_triangular_selector<MatrixType,ProductType,UpLo,false>
|
|||
internal::general_matrix_matrix_triangular_product<Index,
|
||||
typename Lhs::Scalar, LhsIsRowMajor ? RowMajor : ColMajor, LhsBlasTraits::NeedToConjugate,
|
||||
typename Rhs::Scalar, RhsIsRowMajor ? RowMajor : ColMajor, RhsBlasTraits::NeedToConjugate,
|
||||
IsRowMajor ? RowMajor : ColMajor, UpLo>
|
||||
IsRowMajor ? RowMajor : ColMajor, UpLo&(Lower|Upper)>
|
||||
::run(size, depth,
|
||||
&actualLhs.coeffRef(0,0), actualLhs.outerStride(), &actualRhs.coeffRef(0,0), actualRhs.outerStride(),
|
||||
mat.data(), mat.outerStride(), actualAlpha, blocking);
|
||||
&actualLhs.coeffRef(SkipDiag&&(UpLo&Lower)==Lower ? 1 : 0,0), actualLhs.outerStride(),
|
||||
&actualRhs.coeffRef(0,SkipDiag&&(UpLo&Upper)==Upper ? 1 : 0), actualRhs.outerStride(),
|
||||
mat.data() + (SkipDiag ? (bool(IsRowMajor) != ((UpLo&Lower)==Lower) ? 1 : mat.outerStride() ) : 0), mat.outerStride(), actualAlpha, blocking);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType, unsigned int UpLo>
|
||||
template<typename ProductType>
|
||||
TriangularView<MatrixType,UpLo>& TriangularViewImpl<MatrixType,UpLo,Dense>::_assignProduct(const ProductType& prod, const Scalar& alpha)
|
||||
TriangularView<MatrixType,UpLo>& TriangularViewImpl<MatrixType,UpLo,Dense>::_assignProduct(const ProductType& prod, const Scalar& alpha, bool beta)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((UpLo&UnitDiag)==0, WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED);
|
||||
eigen_assert(derived().nestedExpression().rows() == prod.rows() && derived().cols() == prod.cols());
|
||||
|
||||
general_product_to_triangular_selector<MatrixType, ProductType, UpLo, internal::traits<ProductType>::InnerSize==1>::run(derived().nestedExpression().const_cast_derived(), prod, alpha);
|
||||
general_product_to_triangular_selector<MatrixType, ProductType, UpLo, internal::traits<ProductType>::InnerSize==1>::run(derived().nestedExpression().const_cast_derived(), prod, alpha, beta);
|
||||
|
||||
return derived();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ struct general_matrix_matrix_triangular_product<Index,Scalar,LhsStorageOrder,Con
|
|||
static EIGEN_STRONG_INLINE void run(Index size, Index depth,const Scalar* lhs, Index lhsStride, \
|
||||
const Scalar* rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha, level3_blocking<Scalar, Scalar>& blocking) \
|
||||
{ \
|
||||
if (lhs==rhs) { \
|
||||
if ( lhs==rhs && ((UpLo&(Lower|Upper)==UpLo)) ) { \
|
||||
general_matrix_matrix_rankupdate<Index,Scalar,LhsStorageOrder,ConjugateLhs,ColMajor,UpLo> \
|
||||
::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha,blocking); \
|
||||
} else { \
|
||||
|
|
|
|||
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* Level 3 BLAS SYRK/HERK implementation.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_MKL_H
|
||||
#define EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_MKL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename Index, typename Scalar, int AStorageOrder, bool ConjugateA, int ResStorageOrder, int UpLo>
|
||||
struct general_matrix_matrix_rankupdate :
|
||||
general_matrix_matrix_triangular_product<
|
||||
Index,Scalar,AStorageOrder,ConjugateA,Scalar,AStorageOrder,ConjugateA,ResStorageOrder,UpLo,BuiltIn> {};
|
||||
|
||||
|
||||
// try to go to BLAS specialization
|
||||
#define EIGEN_MKL_RANKUPDATE_SPECIALIZE(Scalar) \
|
||||
template <typename Index, int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs, int UpLo> \
|
||||
struct general_matrix_matrix_triangular_product<Index,Scalar,LhsStorageOrder,ConjugateLhs, \
|
||||
Scalar,RhsStorageOrder,ConjugateRhs,ColMajor,UpLo,Specialized> { \
|
||||
static EIGEN_STRONG_INLINE void run(Index size, Index depth,const Scalar* lhs, Index lhsStride, \
|
||||
const Scalar* rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha) \
|
||||
{ \
|
||||
if (lhs==rhs) { \
|
||||
general_matrix_matrix_rankupdate<Index,Scalar,LhsStorageOrder,ConjugateLhs,ColMajor,UpLo> \
|
||||
::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha); \
|
||||
} else { \
|
||||
general_matrix_matrix_triangular_product<Index, \
|
||||
Scalar, LhsStorageOrder, ConjugateLhs, \
|
||||
Scalar, RhsStorageOrder, ConjugateRhs, \
|
||||
ColMajor, UpLo, BuiltIn> \
|
||||
::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_RANKUPDATE_SPECIALIZE(double)
|
||||
//EIGEN_MKL_RANKUPDATE_SPECIALIZE(dcomplex)
|
||||
EIGEN_MKL_RANKUPDATE_SPECIALIZE(float)
|
||||
//EIGEN_MKL_RANKUPDATE_SPECIALIZE(scomplex)
|
||||
|
||||
// SYRK for float/double
|
||||
#define EIGEN_MKL_RANKUPDATE_R(EIGTYPE, MKLTYPE, MKLFUNC) \
|
||||
template <typename Index, int AStorageOrder, bool ConjugateA, int UpLo> \
|
||||
struct general_matrix_matrix_rankupdate<Index,EIGTYPE,AStorageOrder,ConjugateA,ColMajor,UpLo> { \
|
||||
enum { \
|
||||
IsLower = (UpLo&Lower) == Lower, \
|
||||
LowUp = IsLower ? Lower : Upper, \
|
||||
conjA = ((AStorageOrder==ColMajor) && ConjugateA) ? 1 : 0 \
|
||||
}; \
|
||||
static EIGEN_STRONG_INLINE void run(Index size, Index depth,const EIGTYPE* lhs, Index lhsStride, \
|
||||
const EIGTYPE* rhs, Index rhsStride, EIGTYPE* res, Index resStride, EIGTYPE alpha) \
|
||||
{ \
|
||||
/* typedef Matrix<EIGTYPE, Dynamic, Dynamic, RhsStorageOrder> MatrixRhs;*/ \
|
||||
\
|
||||
MKL_INT lda=lhsStride, ldc=resStride, n=size, k=depth; \
|
||||
char uplo=(IsLower) ? 'L' : 'U', trans=(AStorageOrder==RowMajor) ? 'T':'N'; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
\
|
||||
/* Set alpha_ & beta_ */ \
|
||||
assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(beta_, EIGTYPE(1)); \
|
||||
MKLFUNC(&uplo, &trans, &n, &k, &alpha_, lhs, &lda, &beta_, res, &ldc); \
|
||||
} \
|
||||
};
|
||||
|
||||
// HERK for complex data
|
||||
#define EIGEN_MKL_RANKUPDATE_C(EIGTYPE, MKLTYPE, RTYPE, MKLFUNC) \
|
||||
template <typename Index, int AStorageOrder, bool ConjugateA, int UpLo> \
|
||||
struct general_matrix_matrix_rankupdate<Index,EIGTYPE,AStorageOrder,ConjugateA,ColMajor,UpLo> { \
|
||||
enum { \
|
||||
IsLower = (UpLo&Lower) == Lower, \
|
||||
LowUp = IsLower ? Lower : Upper, \
|
||||
conjA = (((AStorageOrder==ColMajor) && ConjugateA) || ((AStorageOrder==RowMajor) && !ConjugateA)) ? 1 : 0 \
|
||||
}; \
|
||||
static EIGEN_STRONG_INLINE void run(Index size, Index depth,const EIGTYPE* lhs, Index lhsStride, \
|
||||
const EIGTYPE* rhs, Index rhsStride, EIGTYPE* res, Index resStride, EIGTYPE alpha) \
|
||||
{ \
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, AStorageOrder> MatrixType; \
|
||||
\
|
||||
MKL_INT lda=lhsStride, ldc=resStride, n=size, k=depth; \
|
||||
char uplo=(IsLower) ? 'L' : 'U', trans=(AStorageOrder==RowMajor) ? 'C':'N'; \
|
||||
RTYPE alpha_, beta_; \
|
||||
const EIGTYPE* a_ptr; \
|
||||
\
|
||||
/* Set alpha_ & beta_ */ \
|
||||
/* assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(alpha_, alpha); */\
|
||||
/* assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(beta_, EIGTYPE(1));*/ \
|
||||
alpha_ = alpha.real(); \
|
||||
beta_ = 1.0; \
|
||||
/* Copy with conjugation in some cases*/ \
|
||||
MatrixType a; \
|
||||
if (conjA) { \
|
||||
Map<const MatrixType, 0, OuterStride<> > mapA(lhs,n,k,OuterStride<>(lhsStride)); \
|
||||
a = mapA.conjugate(); \
|
||||
lda = a.outerStride(); \
|
||||
a_ptr = a.data(); \
|
||||
} else a_ptr=lhs; \
|
||||
MKLFUNC(&uplo, &trans, &n, &k, &alpha_, (MKLTYPE*)a_ptr, &lda, &beta_, (MKLTYPE*)res, &ldc); \
|
||||
} \
|
||||
};
|
||||
|
||||
|
||||
EIGEN_MKL_RANKUPDATE_R(double, double, dsyrk)
|
||||
EIGEN_MKL_RANKUPDATE_R(float, float, ssyrk)
|
||||
|
||||
//EIGEN_MKL_RANKUPDATE_C(dcomplex, MKL_Complex16, double, zherk)
|
||||
//EIGEN_MKL_RANKUPDATE_C(scomplex, MKL_Complex8, double, cherk)
|
||||
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_MKL_H
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* General matrix-matrix product functionality based on ?GEMM.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_GENERAL_MATRIX_MATRIX_MKL_H
|
||||
#define EIGEN_GENERAL_MATRIX_MATRIX_MKL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/**********************************************************************
|
||||
* This file implements general matrix-matrix multiplication using BLAS
|
||||
* gemm function via partial specialization of
|
||||
* general_matrix_matrix_product::run(..) method for float, double,
|
||||
* std::complex<float> and std::complex<double> types
|
||||
**********************************************************************/
|
||||
|
||||
// gemm specialization
|
||||
|
||||
#define GEMM_SPECIALIZATION(EIGTYPE, EIGPREFIX, MKLTYPE, MKLPREFIX) \
|
||||
template< \
|
||||
typename Index, \
|
||||
int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs> \
|
||||
struct general_matrix_matrix_product<Index,EIGTYPE,LhsStorageOrder,ConjugateLhs,EIGTYPE,RhsStorageOrder,ConjugateRhs,ColMajor> \
|
||||
{ \
|
||||
static void run(Index rows, Index cols, Index depth, \
|
||||
const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsStride, \
|
||||
EIGTYPE* res, Index resStride, \
|
||||
EIGTYPE alpha, \
|
||||
level3_blocking<EIGTYPE, EIGTYPE>& /*blocking*/, \
|
||||
GemmParallelInfo<Index>* /*info = 0*/) \
|
||||
{ \
|
||||
using std::conj; \
|
||||
\
|
||||
char transa, transb; \
|
||||
MKL_INT m, n, k, lda, ldb, ldc; \
|
||||
const EIGTYPE *a, *b; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
MatrixX##EIGPREFIX a_tmp, b_tmp; \
|
||||
EIGTYPE myone(1);\
|
||||
\
|
||||
/* Set transpose options */ \
|
||||
transa = (LhsStorageOrder==RowMajor) ? ((ConjugateLhs) ? 'C' : 'T') : 'N'; \
|
||||
transb = (RhsStorageOrder==RowMajor) ? ((ConjugateRhs) ? 'C' : 'T') : 'N'; \
|
||||
\
|
||||
/* Set m, n, k */ \
|
||||
m = (MKL_INT)rows; \
|
||||
n = (MKL_INT)cols; \
|
||||
k = (MKL_INT)depth; \
|
||||
\
|
||||
/* Set alpha_ & beta_ */ \
|
||||
assign_scalar_eig2mkl(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl(beta_, myone); \
|
||||
\
|
||||
/* Set lda, ldb, ldc */ \
|
||||
lda = (MKL_INT)lhsStride; \
|
||||
ldb = (MKL_INT)rhsStride; \
|
||||
ldc = (MKL_INT)resStride; \
|
||||
\
|
||||
/* Set a, b, c */ \
|
||||
if ((LhsStorageOrder==ColMajor) && (ConjugateLhs)) { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > lhs(_lhs,m,k,OuterStride<>(lhsStride)); \
|
||||
a_tmp = lhs.conjugate(); \
|
||||
a = a_tmp.data(); \
|
||||
lda = a_tmp.outerStride(); \
|
||||
} else a = _lhs; \
|
||||
\
|
||||
if ((RhsStorageOrder==ColMajor) && (ConjugateRhs)) { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > rhs(_rhs,k,n,OuterStride<>(rhsStride)); \
|
||||
b_tmp = rhs.conjugate(); \
|
||||
b = b_tmp.data(); \
|
||||
ldb = b_tmp.outerStride(); \
|
||||
} else b = _rhs; \
|
||||
\
|
||||
MKLPREFIX##gemm(&transa, &transb, &m, &n, &k, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \
|
||||
}};
|
||||
|
||||
GEMM_SPECIALIZATION(double, d, double, d)
|
||||
GEMM_SPECIALIZATION(float, f, float, s)
|
||||
GEMM_SPECIALIZATION(dcomplex, cd, MKL_Complex16, z)
|
||||
GEMM_SPECIALIZATION(scomplex, cf, MKL_Complex8, c)
|
||||
|
||||
} // end namespase internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_GENERAL_MATRIX_MATRIX_MKL_H
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008-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
|
||||
|
|
@ -15,8 +15,10 @@ namespace Eigen {
|
|||
namespace internal {
|
||||
|
||||
/* Optimized col-major matrix * vector product:
|
||||
* This algorithm processes the matrix per vertical panels,
|
||||
* which are then processed horizontaly per chunck of 8*PacketSize x 1 vertical segments.
|
||||
* This algorithm processes 4 columns at onces that allows to both reduce
|
||||
* the number of load/stores of the result by a factor 4 and to reduce
|
||||
* the instruction dependency. Moreover, we know that all bands have the
|
||||
* same alignment pattern.
|
||||
*
|
||||
* Mixing type logic: C += alpha * A * B
|
||||
* | A | B |alpha| comments
|
||||
|
|
@ -25,7 +27,33 @@ namespace internal {
|
|||
* |cplx |real |cplx | invalid, the caller has to do tmp: = A * B; C += alpha*tmp
|
||||
* |cplx |real |real | optimal case, vectorization possible via real-cplx mul
|
||||
*
|
||||
* Accesses to the matrix coefficients follow the following logic:
|
||||
*
|
||||
* - if all columns have the same alignment then
|
||||
* - if the columns have the same alignment as the result vector, then easy! (-> AllAligned case)
|
||||
* - otherwise perform unaligned loads only (-> NoneAligned case)
|
||||
* - otherwise
|
||||
* - if even columns have the same alignment then
|
||||
* // odd columns are guaranteed to have the same alignment too
|
||||
* - if even or odd columns have the same alignment as the result, then
|
||||
* // for a register size of 2 scalars, this is guarantee to be the case (e.g., SSE with double)
|
||||
* - perform half aligned and half unaligned loads (-> EvenAligned case)
|
||||
* - otherwise perform unaligned loads only (-> NoneAligned case)
|
||||
* - otherwise, if the register size is 4 scalars (e.g., SSE with float) then
|
||||
* - one over 4 consecutive columns is guaranteed to be aligned with the result vector,
|
||||
* perform simple aligned loads for this column and aligned loads plus re-alignment for the other. (-> FirstAligned case)
|
||||
* // this re-alignment is done by the palign function implemented for SSE in Eigen/src/Core/arch/SSE/PacketMath.h
|
||||
* - otherwise,
|
||||
* // if we get here, this means the register size is greater than 4 (e.g., AVX with floats),
|
||||
* // we currently fall back to the NoneAligned case
|
||||
*
|
||||
* The same reasoning apply for the transposed case.
|
||||
*
|
||||
* The last case (PacketSize>4) could probably be improved by generalizing the FirstAligned case, but since we do not support AVX yet...
|
||||
* One might also wonder why in the EvenAligned case we perform unaligned loads instead of using the aligned-loads plus re-alignment
|
||||
* strategy as in the FirstAligned case. The reason is that we observed that unaligned loads on a 8 byte boundary are not too slow
|
||||
* compared to unaligned loads on a 4 byte boundary.
|
||||
*
|
||||
*/
|
||||
template<typename Index, typename LhsScalar, typename LhsMapper, bool ConjugateLhs, typename RhsScalar, typename RhsMapper, bool ConjugateRhs, int Version>
|
||||
struct general_matrix_vector_product<Index,LhsScalar,LhsMapper,ColMajor,ConjugateLhs,RhsScalar,RhsMapper,ConjugateRhs,Version>
|
||||
|
|
@ -59,145 +87,238 @@ EIGEN_DONT_INLINE static void run(
|
|||
template<typename Index, typename LhsScalar, typename LhsMapper, bool ConjugateLhs, typename RhsScalar, typename RhsMapper, bool ConjugateRhs, int Version>
|
||||
EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,LhsMapper,ColMajor,ConjugateLhs,RhsScalar,RhsMapper,ConjugateRhs,Version>::run(
|
||||
Index rows, Index cols,
|
||||
const LhsMapper& alhs,
|
||||
const LhsMapper& lhs,
|
||||
const RhsMapper& rhs,
|
||||
ResScalar* res, Index resIncr,
|
||||
RhsScalar alpha)
|
||||
{
|
||||
EIGEN_UNUSED_VARIABLE(resIncr);
|
||||
eigen_internal_assert(resIncr==1);
|
||||
#ifdef _EIGEN_ACCUMULATE_PACKETS
|
||||
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
|
||||
#endif
|
||||
#define _EIGEN_ACCUMULATE_PACKETS(Alignment0,Alignment13,Alignment2) \
|
||||
pstore(&res[j], \
|
||||
padd(pload<ResPacket>(&res[j]), \
|
||||
padd( \
|
||||
padd(pcj.pmul(lhs0.template load<LhsPacket, Alignment0>(j), ptmp0), \
|
||||
pcj.pmul(lhs1.template load<LhsPacket, Alignment13>(j), ptmp1)), \
|
||||
padd(pcj.pmul(lhs2.template load<LhsPacket, Alignment2>(j), ptmp2), \
|
||||
pcj.pmul(lhs3.template load<LhsPacket, Alignment13>(j), ptmp3)) )))
|
||||
|
||||
// The following copy tells the compiler that lhs's attributes are not modified outside this function
|
||||
// This helps GCC to generate propoer code.
|
||||
LhsMapper lhs(alhs);
|
||||
typedef typename LhsMapper::VectorMapper LhsScalars;
|
||||
|
||||
conj_helper<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> cj;
|
||||
conj_helper<LhsPacket,RhsPacket,ConjugateLhs,ConjugateRhs> pcj;
|
||||
if(ConjugateRhs)
|
||||
alpha = numext::conj(alpha);
|
||||
|
||||
enum { AllAligned = 0, EvenAligned, FirstAligned, NoneAligned };
|
||||
const Index columnsAtOnce = 4;
|
||||
const Index peels = 2;
|
||||
const Index LhsPacketAlignedMask = LhsPacketSize-1;
|
||||
const Index ResPacketAlignedMask = ResPacketSize-1;
|
||||
// const Index PeelAlignedMask = ResPacketSize*peels-1;
|
||||
const Index size = rows;
|
||||
|
||||
const Index lhsStride = lhs.stride();
|
||||
// TODO: for padded aligned inputs, we could enable aligned reads
|
||||
enum { LhsAlignment = Unaligned };
|
||||
|
||||
const Index n8 = rows-8*ResPacketSize+1;
|
||||
const Index n4 = rows-4*ResPacketSize+1;
|
||||
const Index n3 = rows-3*ResPacketSize+1;
|
||||
const Index n2 = rows-2*ResPacketSize+1;
|
||||
const Index n1 = rows-1*ResPacketSize+1;
|
||||
// How many coeffs of the result do we have to skip to be aligned.
|
||||
// Here we assume data are at least aligned on the base scalar type.
|
||||
Index alignedStart = internal::first_default_aligned(res,size);
|
||||
Index alignedSize = ResPacketSize>1 ? alignedStart + ((size-alignedStart) & ~ResPacketAlignedMask) : 0;
|
||||
const Index peeledSize = alignedSize - RhsPacketSize*peels - RhsPacketSize + 1;
|
||||
|
||||
// TODO: improve the following heuristic:
|
||||
const Index block_cols = cols<128 ? cols : (lhsStride*sizeof(LhsScalar)<32000?16:4);
|
||||
ResPacket palpha = pset1<ResPacket>(alpha);
|
||||
const Index alignmentStep = LhsPacketSize>1 ? (LhsPacketSize - lhsStride % LhsPacketSize) & LhsPacketAlignedMask : 0;
|
||||
Index alignmentPattern = alignmentStep==0 ? AllAligned
|
||||
: alignmentStep==(LhsPacketSize/2) ? EvenAligned
|
||||
: FirstAligned;
|
||||
|
||||
for(Index j2=0; j2<cols; j2+=block_cols)
|
||||
// we cannot assume the first element is aligned because of sub-matrices
|
||||
const Index lhsAlignmentOffset = lhs.firstAligned(size);
|
||||
|
||||
// find how many columns do we have to skip to be aligned with the result (if possible)
|
||||
Index skipColumns = 0;
|
||||
// if the data cannot be aligned (TODO add some compile time tests when possible, e.g. for floats)
|
||||
if( (lhsAlignmentOffset < 0) || (lhsAlignmentOffset == size) || (UIntPtr(res)%sizeof(ResScalar)) )
|
||||
{
|
||||
Index jend = numext::mini(j2+block_cols,cols);
|
||||
Index i=0;
|
||||
for(; i<n8; i+=ResPacketSize*8)
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0)),
|
||||
c1 = pset1<ResPacket>(ResScalar(0)),
|
||||
c2 = pset1<ResPacket>(ResScalar(0)),
|
||||
c3 = pset1<ResPacket>(ResScalar(0)),
|
||||
c4 = pset1<ResPacket>(ResScalar(0)),
|
||||
c5 = pset1<ResPacket>(ResScalar(0)),
|
||||
c6 = pset1<ResPacket>(ResScalar(0)),
|
||||
c7 = pset1<ResPacket>(ResScalar(0));
|
||||
alignedSize = 0;
|
||||
alignedStart = 0;
|
||||
alignmentPattern = NoneAligned;
|
||||
}
|
||||
else if(LhsPacketSize > 4)
|
||||
{
|
||||
// TODO: extend the code to support aligned loads whenever possible when LhsPacketSize > 4.
|
||||
// Currently, it seems to be better to perform unaligned loads anyway
|
||||
alignmentPattern = NoneAligned;
|
||||
}
|
||||
else if (LhsPacketSize>1)
|
||||
{
|
||||
// eigen_internal_assert(size_t(firstLhs+lhsAlignmentOffset)%sizeof(LhsPacket)==0 || size<LhsPacketSize);
|
||||
|
||||
for(Index j=j2; j<jend; j+=1)
|
||||
{
|
||||
RhsPacket b0 = pset1<RhsPacket>(rhs(j,0));
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*0,j),b0,c0);
|
||||
c1 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*1,j),b0,c1);
|
||||
c2 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*2,j),b0,c2);
|
||||
c3 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*3,j),b0,c3);
|
||||
c4 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*4,j),b0,c4);
|
||||
c5 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*5,j),b0,c5);
|
||||
c6 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*6,j),b0,c6);
|
||||
c7 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*7,j),b0,c7);
|
||||
}
|
||||
pstoreu(res+i+ResPacketSize*0, pmadd(c0,palpha,ploadu<ResPacket>(res+i+ResPacketSize*0)));
|
||||
pstoreu(res+i+ResPacketSize*1, pmadd(c1,palpha,ploadu<ResPacket>(res+i+ResPacketSize*1)));
|
||||
pstoreu(res+i+ResPacketSize*2, pmadd(c2,palpha,ploadu<ResPacket>(res+i+ResPacketSize*2)));
|
||||
pstoreu(res+i+ResPacketSize*3, pmadd(c3,palpha,ploadu<ResPacket>(res+i+ResPacketSize*3)));
|
||||
pstoreu(res+i+ResPacketSize*4, pmadd(c4,palpha,ploadu<ResPacket>(res+i+ResPacketSize*4)));
|
||||
pstoreu(res+i+ResPacketSize*5, pmadd(c5,palpha,ploadu<ResPacket>(res+i+ResPacketSize*5)));
|
||||
pstoreu(res+i+ResPacketSize*6, pmadd(c6,palpha,ploadu<ResPacket>(res+i+ResPacketSize*6)));
|
||||
pstoreu(res+i+ResPacketSize*7, pmadd(c7,palpha,ploadu<ResPacket>(res+i+ResPacketSize*7)));
|
||||
while (skipColumns<LhsPacketSize &&
|
||||
alignedStart != ((lhsAlignmentOffset + alignmentStep*skipColumns)%LhsPacketSize))
|
||||
++skipColumns;
|
||||
if (skipColumns==LhsPacketSize)
|
||||
{
|
||||
// nothing can be aligned, no need to skip any column
|
||||
alignmentPattern = NoneAligned;
|
||||
skipColumns = 0;
|
||||
}
|
||||
if(i<n4)
|
||||
else
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0)),
|
||||
c1 = pset1<ResPacket>(ResScalar(0)),
|
||||
c2 = pset1<ResPacket>(ResScalar(0)),
|
||||
c3 = pset1<ResPacket>(ResScalar(0));
|
||||
|
||||
for(Index j=j2; j<jend; j+=1)
|
||||
{
|
||||
RhsPacket b0 = pset1<RhsPacket>(rhs(j,0));
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*0,j),b0,c0);
|
||||
c1 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*1,j),b0,c1);
|
||||
c2 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*2,j),b0,c2);
|
||||
c3 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*3,j),b0,c3);
|
||||
}
|
||||
pstoreu(res+i+ResPacketSize*0, pmadd(c0,palpha,ploadu<ResPacket>(res+i+ResPacketSize*0)));
|
||||
pstoreu(res+i+ResPacketSize*1, pmadd(c1,palpha,ploadu<ResPacket>(res+i+ResPacketSize*1)));
|
||||
pstoreu(res+i+ResPacketSize*2, pmadd(c2,palpha,ploadu<ResPacket>(res+i+ResPacketSize*2)));
|
||||
pstoreu(res+i+ResPacketSize*3, pmadd(c3,palpha,ploadu<ResPacket>(res+i+ResPacketSize*3)));
|
||||
|
||||
i+=ResPacketSize*4;
|
||||
skipColumns = (std::min)(skipColumns,cols);
|
||||
// note that the skiped columns are processed later.
|
||||
}
|
||||
if(i<n3)
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0)),
|
||||
c1 = pset1<ResPacket>(ResScalar(0)),
|
||||
c2 = pset1<ResPacket>(ResScalar(0));
|
||||
|
||||
for(Index j=j2; j<jend; j+=1)
|
||||
{
|
||||
RhsPacket b0 = pset1<RhsPacket>(rhs(j,0));
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*0,j),b0,c0);
|
||||
c1 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*1,j),b0,c1);
|
||||
c2 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*2,j),b0,c2);
|
||||
}
|
||||
pstoreu(res+i+ResPacketSize*0, pmadd(c0,palpha,ploadu<ResPacket>(res+i+ResPacketSize*0)));
|
||||
pstoreu(res+i+ResPacketSize*1, pmadd(c1,palpha,ploadu<ResPacket>(res+i+ResPacketSize*1)));
|
||||
pstoreu(res+i+ResPacketSize*2, pmadd(c2,palpha,ploadu<ResPacket>(res+i+ResPacketSize*2)));
|
||||
/* eigen_internal_assert( (alignmentPattern==NoneAligned)
|
||||
|| (skipColumns + columnsAtOnce >= cols)
|
||||
|| LhsPacketSize > size
|
||||
|| (size_t(firstLhs+alignedStart+lhsStride*skipColumns)%sizeof(LhsPacket))==0);*/
|
||||
}
|
||||
else if(Vectorizable)
|
||||
{
|
||||
alignedStart = 0;
|
||||
alignedSize = size;
|
||||
alignmentPattern = AllAligned;
|
||||
}
|
||||
|
||||
i+=ResPacketSize*3;
|
||||
}
|
||||
if(i<n2)
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0)),
|
||||
c1 = pset1<ResPacket>(ResScalar(0));
|
||||
const Index offset1 = (FirstAligned && alignmentStep==1)?3:1;
|
||||
const Index offset3 = (FirstAligned && alignmentStep==1)?1:3;
|
||||
|
||||
for(Index j=j2; j<jend; j+=1)
|
||||
{
|
||||
RhsPacket b0 = pset1<RhsPacket>(rhs(j,0));
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*0,j),b0,c0);
|
||||
c1 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+LhsPacketSize*1,j),b0,c1);
|
||||
}
|
||||
pstoreu(res+i+ResPacketSize*0, pmadd(c0,palpha,ploadu<ResPacket>(res+i+ResPacketSize*0)));
|
||||
pstoreu(res+i+ResPacketSize*1, pmadd(c1,palpha,ploadu<ResPacket>(res+i+ResPacketSize*1)));
|
||||
i+=ResPacketSize*2;
|
||||
}
|
||||
if(i<n1)
|
||||
Index columnBound = ((cols-skipColumns)/columnsAtOnce)*columnsAtOnce + skipColumns;
|
||||
for (Index i=skipColumns; i<columnBound; i+=columnsAtOnce)
|
||||
{
|
||||
RhsPacket ptmp0 = pset1<RhsPacket>(alpha*rhs(i, 0)),
|
||||
ptmp1 = pset1<RhsPacket>(alpha*rhs(i+offset1, 0)),
|
||||
ptmp2 = pset1<RhsPacket>(alpha*rhs(i+2, 0)),
|
||||
ptmp3 = pset1<RhsPacket>(alpha*rhs(i+offset3, 0));
|
||||
|
||||
// this helps a lot generating better binary code
|
||||
const LhsScalars lhs0 = lhs.getVectorMapper(0, i+0), lhs1 = lhs.getVectorMapper(0, i+offset1),
|
||||
lhs2 = lhs.getVectorMapper(0, i+2), lhs3 = lhs.getVectorMapper(0, i+offset3);
|
||||
|
||||
if (Vectorizable)
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0));
|
||||
for(Index j=j2; j<jend; j+=1)
|
||||
/* explicit vectorization */
|
||||
// process initial unaligned coeffs
|
||||
for (Index j=0; j<alignedStart; ++j)
|
||||
{
|
||||
RhsPacket b0 = pset1<RhsPacket>(rhs(j,0));
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+0,j),b0,c0);
|
||||
res[j] = cj.pmadd(lhs0(j), pfirst(ptmp0), res[j]);
|
||||
res[j] = cj.pmadd(lhs1(j), pfirst(ptmp1), res[j]);
|
||||
res[j] = cj.pmadd(lhs2(j), pfirst(ptmp2), res[j]);
|
||||
res[j] = cj.pmadd(lhs3(j), pfirst(ptmp3), res[j]);
|
||||
}
|
||||
pstoreu(res+i+ResPacketSize*0, pmadd(c0,palpha,ploadu<ResPacket>(res+i+ResPacketSize*0)));
|
||||
i+=ResPacketSize;
|
||||
}
|
||||
for(;i<rows;++i)
|
||||
|
||||
if (alignedSize>alignedStart)
|
||||
{
|
||||
switch(alignmentPattern)
|
||||
{
|
||||
case AllAligned:
|
||||
for (Index j = alignedStart; j<alignedSize; j+=ResPacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(Aligned,Aligned,Aligned);
|
||||
break;
|
||||
case EvenAligned:
|
||||
for (Index j = alignedStart; j<alignedSize; j+=ResPacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(Aligned,Unaligned,Aligned);
|
||||
break;
|
||||
case FirstAligned:
|
||||
{
|
||||
Index j = alignedStart;
|
||||
if(peels>1)
|
||||
{
|
||||
LhsPacket A00, A01, A02, A03, A10, A11, A12, A13;
|
||||
ResPacket T0, T1;
|
||||
|
||||
A01 = lhs1.template load<LhsPacket, Aligned>(alignedStart-1);
|
||||
A02 = lhs2.template load<LhsPacket, Aligned>(alignedStart-2);
|
||||
A03 = lhs3.template load<LhsPacket, Aligned>(alignedStart-3);
|
||||
|
||||
for (; j<peeledSize; j+=peels*ResPacketSize)
|
||||
{
|
||||
A11 = lhs1.template load<LhsPacket, Aligned>(j-1+LhsPacketSize); palign<1>(A01,A11);
|
||||
A12 = lhs2.template load<LhsPacket, Aligned>(j-2+LhsPacketSize); palign<2>(A02,A12);
|
||||
A13 = lhs3.template load<LhsPacket, Aligned>(j-3+LhsPacketSize); palign<3>(A03,A13);
|
||||
|
||||
A00 = lhs0.template load<LhsPacket, Aligned>(j);
|
||||
A10 = lhs0.template load<LhsPacket, Aligned>(j+LhsPacketSize);
|
||||
T0 = pcj.pmadd(A00, ptmp0, pload<ResPacket>(&res[j]));
|
||||
T1 = pcj.pmadd(A10, ptmp0, pload<ResPacket>(&res[j+ResPacketSize]));
|
||||
|
||||
T0 = pcj.pmadd(A01, ptmp1, T0);
|
||||
A01 = lhs1.template load<LhsPacket, Aligned>(j-1+2*LhsPacketSize); palign<1>(A11,A01);
|
||||
T0 = pcj.pmadd(A02, ptmp2, T0);
|
||||
A02 = lhs2.template load<LhsPacket, Aligned>(j-2+2*LhsPacketSize); palign<2>(A12,A02);
|
||||
T0 = pcj.pmadd(A03, ptmp3, T0);
|
||||
pstore(&res[j],T0);
|
||||
A03 = lhs3.template load<LhsPacket, Aligned>(j-3+2*LhsPacketSize); palign<3>(A13,A03);
|
||||
T1 = pcj.pmadd(A11, ptmp1, T1);
|
||||
T1 = pcj.pmadd(A12, ptmp2, T1);
|
||||
T1 = pcj.pmadd(A13, ptmp3, T1);
|
||||
pstore(&res[j+ResPacketSize],T1);
|
||||
}
|
||||
}
|
||||
for (; j<alignedSize; j+=ResPacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(Aligned,Unaligned,Unaligned);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
for (Index j = alignedStart; j<alignedSize; j+=ResPacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(Unaligned,Unaligned,Unaligned);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // end explicit vectorization
|
||||
|
||||
/* process remaining coeffs (or all if there is no explicit vectorization) */
|
||||
for (Index j=alignedSize; j<size; ++j)
|
||||
{
|
||||
ResScalar c0(0);
|
||||
for(Index j=j2; j<jend; j+=1)
|
||||
c0 += cj.pmul(lhs(i,j), rhs(j,0));
|
||||
res[i] += alpha*c0;
|
||||
res[j] = cj.pmadd(lhs0(j), pfirst(ptmp0), res[j]);
|
||||
res[j] = cj.pmadd(lhs1(j), pfirst(ptmp1), res[j]);
|
||||
res[j] = cj.pmadd(lhs2(j), pfirst(ptmp2), res[j]);
|
||||
res[j] = cj.pmadd(lhs3(j), pfirst(ptmp3), res[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// process remaining first and last columns (at most columnsAtOnce-1)
|
||||
Index end = cols;
|
||||
Index start = columnBound;
|
||||
do
|
||||
{
|
||||
for (Index k=start; k<end; ++k)
|
||||
{
|
||||
RhsPacket ptmp0 = pset1<RhsPacket>(alpha*rhs(k, 0));
|
||||
const LhsScalars lhs0 = lhs.getVectorMapper(0, k);
|
||||
|
||||
if (Vectorizable)
|
||||
{
|
||||
/* explicit vectorization */
|
||||
// process first unaligned result's coeffs
|
||||
for (Index j=0; j<alignedStart; ++j)
|
||||
res[j] += cj.pmul(lhs0(j), pfirst(ptmp0));
|
||||
// process aligned result's coeffs
|
||||
if (lhs0.template aligned<LhsPacket>(alignedStart))
|
||||
for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
|
||||
pstore(&res[i], pcj.pmadd(lhs0.template load<LhsPacket, Aligned>(i), ptmp0, pload<ResPacket>(&res[i])));
|
||||
else
|
||||
for (Index i = alignedStart;i<alignedSize;i+=ResPacketSize)
|
||||
pstore(&res[i], pcj.pmadd(lhs0.template load<LhsPacket, Unaligned>(i), ptmp0, pload<ResPacket>(&res[i])));
|
||||
}
|
||||
|
||||
// process remaining scalars (or all if no explicit vectorization)
|
||||
for (Index i=alignedSize; i<size; ++i)
|
||||
res[i] += cj.pmul(lhs0(i), pfirst(ptmp0));
|
||||
}
|
||||
if (skipColumns)
|
||||
{
|
||||
start = 0;
|
||||
end = skipColumns;
|
||||
skipColumns = 0;
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while(Vectorizable);
|
||||
#undef _EIGEN_ACCUMULATE_PACKETS
|
||||
}
|
||||
|
||||
/* Optimized row-major matrix * vector product:
|
||||
|
|
@ -242,160 +363,253 @@ EIGEN_DONT_INLINE static void run(
|
|||
template<typename Index, typename LhsScalar, typename LhsMapper, bool ConjugateLhs, typename RhsScalar, typename RhsMapper, bool ConjugateRhs, int Version>
|
||||
EIGEN_DONT_INLINE void general_matrix_vector_product<Index,LhsScalar,LhsMapper,RowMajor,ConjugateLhs,RhsScalar,RhsMapper,ConjugateRhs,Version>::run(
|
||||
Index rows, Index cols,
|
||||
const LhsMapper& alhs,
|
||||
const LhsMapper& lhs,
|
||||
const RhsMapper& rhs,
|
||||
ResScalar* res, Index resIncr,
|
||||
ResScalar alpha)
|
||||
{
|
||||
// The following copy tells the compiler that lhs's attributes are not modified outside this function
|
||||
// This helps GCC to generate propoer code.
|
||||
LhsMapper lhs(alhs);
|
||||
|
||||
eigen_internal_assert(rhs.stride()==1);
|
||||
|
||||
#ifdef _EIGEN_ACCUMULATE_PACKETS
|
||||
#error _EIGEN_ACCUMULATE_PACKETS has already been defined
|
||||
#endif
|
||||
|
||||
#define _EIGEN_ACCUMULATE_PACKETS(Alignment0,Alignment13,Alignment2) {\
|
||||
RhsPacket b = rhs.getVectorMapper(j, 0).template load<RhsPacket, Aligned>(0); \
|
||||
ptmp0 = pcj.pmadd(lhs0.template load<LhsPacket, Alignment0>(j), b, ptmp0); \
|
||||
ptmp1 = pcj.pmadd(lhs1.template load<LhsPacket, Alignment13>(j), b, ptmp1); \
|
||||
ptmp2 = pcj.pmadd(lhs2.template load<LhsPacket, Alignment2>(j), b, ptmp2); \
|
||||
ptmp3 = pcj.pmadd(lhs3.template load<LhsPacket, Alignment13>(j), b, ptmp3); }
|
||||
|
||||
conj_helper<LhsScalar,RhsScalar,ConjugateLhs,ConjugateRhs> cj;
|
||||
conj_helper<LhsPacket,RhsPacket,ConjugateLhs,ConjugateRhs> pcj;
|
||||
|
||||
// TODO: fine tune the following heuristic. The rationale is that if the matrix is very large,
|
||||
// processing 8 rows at once might be counter productive wrt cache.
|
||||
const Index n8 = lhs.stride()*sizeof(LhsScalar)>32000 ? 0 : rows-7;
|
||||
const Index n4 = rows-3;
|
||||
const Index n2 = rows-1;
|
||||
typedef typename LhsMapper::VectorMapper LhsScalars;
|
||||
|
||||
// TODO: for padded aligned inputs, we could enable aligned reads
|
||||
enum { LhsAlignment = Unaligned };
|
||||
enum { AllAligned=0, EvenAligned=1, FirstAligned=2, NoneAligned=3 };
|
||||
const Index rowsAtOnce = 4;
|
||||
const Index peels = 2;
|
||||
const Index RhsPacketAlignedMask = RhsPacketSize-1;
|
||||
const Index LhsPacketAlignedMask = LhsPacketSize-1;
|
||||
const Index depth = cols;
|
||||
const Index lhsStride = lhs.stride();
|
||||
|
||||
Index i=0;
|
||||
for(; i<n8; i+=8)
|
||||
// How many coeffs of the result do we have to skip to be aligned.
|
||||
// Here we assume data are at least aligned on the base scalar type
|
||||
// if that's not the case then vectorization is discarded, see below.
|
||||
Index alignedStart = rhs.firstAligned(depth);
|
||||
Index alignedSize = RhsPacketSize>1 ? alignedStart + ((depth-alignedStart) & ~RhsPacketAlignedMask) : 0;
|
||||
const Index peeledSize = alignedSize - RhsPacketSize*peels - RhsPacketSize + 1;
|
||||
|
||||
const Index alignmentStep = LhsPacketSize>1 ? (LhsPacketSize - lhsStride % LhsPacketSize) & LhsPacketAlignedMask : 0;
|
||||
Index alignmentPattern = alignmentStep==0 ? AllAligned
|
||||
: alignmentStep==(LhsPacketSize/2) ? EvenAligned
|
||||
: FirstAligned;
|
||||
|
||||
// we cannot assume the first element is aligned because of sub-matrices
|
||||
const Index lhsAlignmentOffset = lhs.firstAligned(depth);
|
||||
const Index rhsAlignmentOffset = rhs.firstAligned(rows);
|
||||
|
||||
// find how many rows do we have to skip to be aligned with rhs (if possible)
|
||||
Index skipRows = 0;
|
||||
// if the data cannot be aligned (TODO add some compile time tests when possible, e.g. for floats)
|
||||
if( (sizeof(LhsScalar)!=sizeof(RhsScalar)) ||
|
||||
(lhsAlignmentOffset < 0) || (lhsAlignmentOffset == depth) ||
|
||||
(rhsAlignmentOffset < 0) || (rhsAlignmentOffset == rows) )
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0)),
|
||||
c1 = pset1<ResPacket>(ResScalar(0)),
|
||||
c2 = pset1<ResPacket>(ResScalar(0)),
|
||||
c3 = pset1<ResPacket>(ResScalar(0)),
|
||||
c4 = pset1<ResPacket>(ResScalar(0)),
|
||||
c5 = pset1<ResPacket>(ResScalar(0)),
|
||||
c6 = pset1<ResPacket>(ResScalar(0)),
|
||||
c7 = pset1<ResPacket>(ResScalar(0));
|
||||
|
||||
Index j=0;
|
||||
for(; j+LhsPacketSize<=cols; j+=LhsPacketSize)
|
||||
{
|
||||
RhsPacket b0 = rhs.template load<RhsPacket, Unaligned>(j,0);
|
||||
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+0,j),b0,c0);
|
||||
c1 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+1,j),b0,c1);
|
||||
c2 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+2,j),b0,c2);
|
||||
c3 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+3,j),b0,c3);
|
||||
c4 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+4,j),b0,c4);
|
||||
c5 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+5,j),b0,c5);
|
||||
c6 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+6,j),b0,c6);
|
||||
c7 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+7,j),b0,c7);
|
||||
}
|
||||
ResScalar cc0 = predux(c0);
|
||||
ResScalar cc1 = predux(c1);
|
||||
ResScalar cc2 = predux(c2);
|
||||
ResScalar cc3 = predux(c3);
|
||||
ResScalar cc4 = predux(c4);
|
||||
ResScalar cc5 = predux(c5);
|
||||
ResScalar cc6 = predux(c6);
|
||||
ResScalar cc7 = predux(c7);
|
||||
for(; j<cols; ++j)
|
||||
{
|
||||
RhsScalar b0 = rhs(j,0);
|
||||
|
||||
cc0 += cj.pmul(lhs(i+0,j), b0);
|
||||
cc1 += cj.pmul(lhs(i+1,j), b0);
|
||||
cc2 += cj.pmul(lhs(i+2,j), b0);
|
||||
cc3 += cj.pmul(lhs(i+3,j), b0);
|
||||
cc4 += cj.pmul(lhs(i+4,j), b0);
|
||||
cc5 += cj.pmul(lhs(i+5,j), b0);
|
||||
cc6 += cj.pmul(lhs(i+6,j), b0);
|
||||
cc7 += cj.pmul(lhs(i+7,j), b0);
|
||||
}
|
||||
res[(i+0)*resIncr] += alpha*cc0;
|
||||
res[(i+1)*resIncr] += alpha*cc1;
|
||||
res[(i+2)*resIncr] += alpha*cc2;
|
||||
res[(i+3)*resIncr] += alpha*cc3;
|
||||
res[(i+4)*resIncr] += alpha*cc4;
|
||||
res[(i+5)*resIncr] += alpha*cc5;
|
||||
res[(i+6)*resIncr] += alpha*cc6;
|
||||
res[(i+7)*resIncr] += alpha*cc7;
|
||||
alignedSize = 0;
|
||||
alignedStart = 0;
|
||||
alignmentPattern = NoneAligned;
|
||||
}
|
||||
for(; i<n4; i+=4)
|
||||
else if(LhsPacketSize > 4)
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0)),
|
||||
c1 = pset1<ResPacket>(ResScalar(0)),
|
||||
c2 = pset1<ResPacket>(ResScalar(0)),
|
||||
c3 = pset1<ResPacket>(ResScalar(0));
|
||||
|
||||
Index j=0;
|
||||
for(; j+LhsPacketSize<=cols; j+=LhsPacketSize)
|
||||
{
|
||||
RhsPacket b0 = rhs.template load<RhsPacket, Unaligned>(j,0);
|
||||
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+0,j),b0,c0);
|
||||
c1 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+1,j),b0,c1);
|
||||
c2 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+2,j),b0,c2);
|
||||
c3 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+3,j),b0,c3);
|
||||
}
|
||||
ResScalar cc0 = predux(c0);
|
||||
ResScalar cc1 = predux(c1);
|
||||
ResScalar cc2 = predux(c2);
|
||||
ResScalar cc3 = predux(c3);
|
||||
for(; j<cols; ++j)
|
||||
{
|
||||
RhsScalar b0 = rhs(j,0);
|
||||
|
||||
cc0 += cj.pmul(lhs(i+0,j), b0);
|
||||
cc1 += cj.pmul(lhs(i+1,j), b0);
|
||||
cc2 += cj.pmul(lhs(i+2,j), b0);
|
||||
cc3 += cj.pmul(lhs(i+3,j), b0);
|
||||
}
|
||||
res[(i+0)*resIncr] += alpha*cc0;
|
||||
res[(i+1)*resIncr] += alpha*cc1;
|
||||
res[(i+2)*resIncr] += alpha*cc2;
|
||||
res[(i+3)*resIncr] += alpha*cc3;
|
||||
// TODO: extend the code to support aligned loads whenever possible when LhsPacketSize > 4.
|
||||
alignmentPattern = NoneAligned;
|
||||
}
|
||||
for(; i<n2; i+=2)
|
||||
else if (LhsPacketSize>1)
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0)),
|
||||
c1 = pset1<ResPacket>(ResScalar(0));
|
||||
// eigen_internal_assert(size_t(firstLhs+lhsAlignmentOffset)%sizeof(LhsPacket)==0 || depth<LhsPacketSize);
|
||||
|
||||
Index j=0;
|
||||
for(; j+LhsPacketSize<=cols; j+=LhsPacketSize)
|
||||
while (skipRows<LhsPacketSize &&
|
||||
alignedStart != ((lhsAlignmentOffset + alignmentStep*skipRows)%LhsPacketSize))
|
||||
++skipRows;
|
||||
if (skipRows==LhsPacketSize)
|
||||
{
|
||||
RhsPacket b0 = rhs.template load<RhsPacket, Unaligned>(j,0);
|
||||
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+0,j),b0,c0);
|
||||
c1 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i+1,j),b0,c1);
|
||||
// nothing can be aligned, no need to skip any column
|
||||
alignmentPattern = NoneAligned;
|
||||
skipRows = 0;
|
||||
}
|
||||
ResScalar cc0 = predux(c0);
|
||||
ResScalar cc1 = predux(c1);
|
||||
for(; j<cols; ++j)
|
||||
else
|
||||
{
|
||||
RhsScalar b0 = rhs(j,0);
|
||||
|
||||
cc0 += cj.pmul(lhs(i+0,j), b0);
|
||||
cc1 += cj.pmul(lhs(i+1,j), b0);
|
||||
skipRows = (std::min)(skipRows,Index(rows));
|
||||
// note that the skiped columns are processed later.
|
||||
}
|
||||
res[(i+0)*resIncr] += alpha*cc0;
|
||||
res[(i+1)*resIncr] += alpha*cc1;
|
||||
/* eigen_internal_assert( alignmentPattern==NoneAligned
|
||||
|| LhsPacketSize==1
|
||||
|| (skipRows + rowsAtOnce >= rows)
|
||||
|| LhsPacketSize > depth
|
||||
|| (size_t(firstLhs+alignedStart+lhsStride*skipRows)%sizeof(LhsPacket))==0);*/
|
||||
}
|
||||
for(; i<rows; ++i)
|
||||
else if(Vectorizable)
|
||||
{
|
||||
ResPacket c0 = pset1<ResPacket>(ResScalar(0));
|
||||
Index j=0;
|
||||
for(; j+LhsPacketSize<=cols; j+=LhsPacketSize)
|
||||
{
|
||||
RhsPacket b0 = rhs.template load<RhsPacket,Unaligned>(j,0);
|
||||
c0 = pcj.pmadd(lhs.template load<LhsPacket,LhsAlignment>(i,j),b0,c0);
|
||||
}
|
||||
ResScalar cc0 = predux(c0);
|
||||
for(; j<cols; ++j)
|
||||
{
|
||||
cc0 += cj.pmul(lhs(i,j), rhs(j,0));
|
||||
}
|
||||
res[i*resIncr] += alpha*cc0;
|
||||
alignedStart = 0;
|
||||
alignedSize = depth;
|
||||
alignmentPattern = AllAligned;
|
||||
}
|
||||
|
||||
const Index offset1 = (FirstAligned && alignmentStep==1)?3:1;
|
||||
const Index offset3 = (FirstAligned && alignmentStep==1)?1:3;
|
||||
|
||||
Index rowBound = ((rows-skipRows)/rowsAtOnce)*rowsAtOnce + skipRows;
|
||||
for (Index i=skipRows; i<rowBound; i+=rowsAtOnce)
|
||||
{
|
||||
// FIXME: what is the purpose of this EIGEN_ALIGN_DEFAULT ??
|
||||
EIGEN_ALIGN_MAX ResScalar tmp0 = ResScalar(0);
|
||||
ResScalar tmp1 = ResScalar(0), tmp2 = ResScalar(0), tmp3 = ResScalar(0);
|
||||
|
||||
// this helps the compiler generating good binary code
|
||||
const LhsScalars lhs0 = lhs.getVectorMapper(i+0, 0), lhs1 = lhs.getVectorMapper(i+offset1, 0),
|
||||
lhs2 = lhs.getVectorMapper(i+2, 0), lhs3 = lhs.getVectorMapper(i+offset3, 0);
|
||||
|
||||
if (Vectorizable)
|
||||
{
|
||||
/* explicit vectorization */
|
||||
ResPacket ptmp0 = pset1<ResPacket>(ResScalar(0)), ptmp1 = pset1<ResPacket>(ResScalar(0)),
|
||||
ptmp2 = pset1<ResPacket>(ResScalar(0)), ptmp3 = pset1<ResPacket>(ResScalar(0));
|
||||
|
||||
// process initial unaligned coeffs
|
||||
// FIXME this loop get vectorized by the compiler !
|
||||
for (Index j=0; j<alignedStart; ++j)
|
||||
{
|
||||
RhsScalar b = rhs(j, 0);
|
||||
tmp0 += cj.pmul(lhs0(j),b); tmp1 += cj.pmul(lhs1(j),b);
|
||||
tmp2 += cj.pmul(lhs2(j),b); tmp3 += cj.pmul(lhs3(j),b);
|
||||
}
|
||||
|
||||
if (alignedSize>alignedStart)
|
||||
{
|
||||
switch(alignmentPattern)
|
||||
{
|
||||
case AllAligned:
|
||||
for (Index j = alignedStart; j<alignedSize; j+=RhsPacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(Aligned,Aligned,Aligned);
|
||||
break;
|
||||
case EvenAligned:
|
||||
for (Index j = alignedStart; j<alignedSize; j+=RhsPacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(Aligned,Unaligned,Aligned);
|
||||
break;
|
||||
case FirstAligned:
|
||||
{
|
||||
Index j = alignedStart;
|
||||
if (peels>1)
|
||||
{
|
||||
/* Here we proccess 4 rows with with two peeled iterations to hide
|
||||
* the overhead of unaligned loads. Moreover unaligned loads are handled
|
||||
* using special shift/move operations between the two aligned packets
|
||||
* overlaping the desired unaligned packet. This is *much* more efficient
|
||||
* than basic unaligned loads.
|
||||
*/
|
||||
LhsPacket A01, A02, A03, A11, A12, A13;
|
||||
A01 = lhs1.template load<LhsPacket, Aligned>(alignedStart-1);
|
||||
A02 = lhs2.template load<LhsPacket, Aligned>(alignedStart-2);
|
||||
A03 = lhs3.template load<LhsPacket, Aligned>(alignedStart-3);
|
||||
|
||||
for (; j<peeledSize; j+=peels*RhsPacketSize)
|
||||
{
|
||||
RhsPacket b = rhs.getVectorMapper(j, 0).template load<RhsPacket, Aligned>(0);
|
||||
A11 = lhs1.template load<LhsPacket, Aligned>(j-1+LhsPacketSize); palign<1>(A01,A11);
|
||||
A12 = lhs2.template load<LhsPacket, Aligned>(j-2+LhsPacketSize); palign<2>(A02,A12);
|
||||
A13 = lhs3.template load<LhsPacket, Aligned>(j-3+LhsPacketSize); palign<3>(A03,A13);
|
||||
|
||||
ptmp0 = pcj.pmadd(lhs0.template load<LhsPacket, Aligned>(j), b, ptmp0);
|
||||
ptmp1 = pcj.pmadd(A01, b, ptmp1);
|
||||
A01 = lhs1.template load<LhsPacket, Aligned>(j-1+2*LhsPacketSize); palign<1>(A11,A01);
|
||||
ptmp2 = pcj.pmadd(A02, b, ptmp2);
|
||||
A02 = lhs2.template load<LhsPacket, Aligned>(j-2+2*LhsPacketSize); palign<2>(A12,A02);
|
||||
ptmp3 = pcj.pmadd(A03, b, ptmp3);
|
||||
A03 = lhs3.template load<LhsPacket, Aligned>(j-3+2*LhsPacketSize); palign<3>(A13,A03);
|
||||
|
||||
b = rhs.getVectorMapper(j+RhsPacketSize, 0).template load<RhsPacket, Aligned>(0);
|
||||
ptmp0 = pcj.pmadd(lhs0.template load<LhsPacket, Aligned>(j+LhsPacketSize), b, ptmp0);
|
||||
ptmp1 = pcj.pmadd(A11, b, ptmp1);
|
||||
ptmp2 = pcj.pmadd(A12, b, ptmp2);
|
||||
ptmp3 = pcj.pmadd(A13, b, ptmp3);
|
||||
}
|
||||
}
|
||||
for (; j<alignedSize; j+=RhsPacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(Aligned,Unaligned,Unaligned);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
for (Index j = alignedStart; j<alignedSize; j+=RhsPacketSize)
|
||||
_EIGEN_ACCUMULATE_PACKETS(Unaligned,Unaligned,Unaligned);
|
||||
break;
|
||||
}
|
||||
tmp0 += predux(ptmp0);
|
||||
tmp1 += predux(ptmp1);
|
||||
tmp2 += predux(ptmp2);
|
||||
tmp3 += predux(ptmp3);
|
||||
}
|
||||
} // end explicit vectorization
|
||||
|
||||
// process remaining coeffs (or all if no explicit vectorization)
|
||||
// FIXME this loop get vectorized by the compiler !
|
||||
for (Index j=alignedSize; j<depth; ++j)
|
||||
{
|
||||
RhsScalar b = rhs(j, 0);
|
||||
tmp0 += cj.pmul(lhs0(j),b); tmp1 += cj.pmul(lhs1(j),b);
|
||||
tmp2 += cj.pmul(lhs2(j),b); tmp3 += cj.pmul(lhs3(j),b);
|
||||
}
|
||||
res[i*resIncr] += alpha*tmp0;
|
||||
res[(i+offset1)*resIncr] += alpha*tmp1;
|
||||
res[(i+2)*resIncr] += alpha*tmp2;
|
||||
res[(i+offset3)*resIncr] += alpha*tmp3;
|
||||
}
|
||||
|
||||
// process remaining first and last rows (at most columnsAtOnce-1)
|
||||
Index end = rows;
|
||||
Index start = rowBound;
|
||||
do
|
||||
{
|
||||
for (Index i=start; i<end; ++i)
|
||||
{
|
||||
EIGEN_ALIGN_MAX ResScalar tmp0 = ResScalar(0);
|
||||
ResPacket ptmp0 = pset1<ResPacket>(tmp0);
|
||||
const LhsScalars lhs0 = lhs.getVectorMapper(i, 0);
|
||||
// process first unaligned result's coeffs
|
||||
// FIXME this loop get vectorized by the compiler !
|
||||
for (Index j=0; j<alignedStart; ++j)
|
||||
tmp0 += cj.pmul(lhs0(j), rhs(j, 0));
|
||||
|
||||
if (alignedSize>alignedStart)
|
||||
{
|
||||
// process aligned rhs coeffs
|
||||
if (lhs0.template aligned<LhsPacket>(alignedStart))
|
||||
for (Index j = alignedStart;j<alignedSize;j+=RhsPacketSize)
|
||||
ptmp0 = pcj.pmadd(lhs0.template load<LhsPacket, Aligned>(j), rhs.getVectorMapper(j, 0).template load<RhsPacket, Aligned>(0), ptmp0);
|
||||
else
|
||||
for (Index j = alignedStart;j<alignedSize;j+=RhsPacketSize)
|
||||
ptmp0 = pcj.pmadd(lhs0.template load<LhsPacket, Unaligned>(j), rhs.getVectorMapper(j, 0).template load<RhsPacket, Aligned>(0), ptmp0);
|
||||
tmp0 += predux(ptmp0);
|
||||
}
|
||||
|
||||
// process remaining scalars
|
||||
// FIXME this loop get vectorized by the compiler !
|
||||
for (Index j=alignedSize; j<depth; ++j)
|
||||
tmp0 += cj.pmul(lhs0(j), rhs(j, 0));
|
||||
res[i*resIncr] += alpha*tmp0;
|
||||
}
|
||||
if (skipRows)
|
||||
{
|
||||
start = 0;
|
||||
end = skipRows;
|
||||
skipRows = 0;
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while(Vectorizable);
|
||||
|
||||
#undef _EIGEN_ACCUMULATE_PACKETS
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
|
|
|||
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* General matrix-vector product functionality based on ?GEMV.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_GENERAL_MATRIX_VECTOR_MKL_H
|
||||
#define EIGEN_GENERAL_MATRIX_VECTOR_MKL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/**********************************************************************
|
||||
* This file implements general matrix-vector multiplication using BLAS
|
||||
* gemv function via partial specialization of
|
||||
* general_matrix_vector_product::run(..) method for float, double,
|
||||
* std::complex<float> and std::complex<double> types
|
||||
**********************************************************************/
|
||||
|
||||
// gemv specialization
|
||||
|
||||
template<typename Index, typename LhsScalar, int LhsStorageOrder, bool ConjugateLhs, typename RhsScalar, bool ConjugateRhs>
|
||||
struct general_matrix_vector_product_gemv :
|
||||
general_matrix_vector_product<Index,LhsScalar,LhsStorageOrder,ConjugateLhs,RhsScalar,ConjugateRhs,BuiltIn> {};
|
||||
|
||||
#define EIGEN_MKL_GEMV_SPECIALIZE(Scalar) \
|
||||
template<typename Index, bool ConjugateLhs, bool ConjugateRhs> \
|
||||
struct general_matrix_vector_product<Index,Scalar,ColMajor,ConjugateLhs,Scalar,ConjugateRhs,Specialized> { \
|
||||
static void run( \
|
||||
Index rows, Index cols, \
|
||||
const Scalar* lhs, Index lhsStride, \
|
||||
const Scalar* rhs, Index rhsIncr, \
|
||||
Scalar* res, Index resIncr, Scalar alpha) \
|
||||
{ \
|
||||
if (ConjugateLhs) { \
|
||||
general_matrix_vector_product<Index,Scalar,ColMajor,ConjugateLhs,Scalar,ConjugateRhs,BuiltIn>::run( \
|
||||
rows, cols, lhs, lhsStride, rhs, rhsIncr, res, resIncr, alpha); \
|
||||
} else { \
|
||||
general_matrix_vector_product_gemv<Index,Scalar,ColMajor,ConjugateLhs,Scalar,ConjugateRhs>::run( \
|
||||
rows, cols, lhs, lhsStride, rhs, rhsIncr, res, resIncr, alpha); \
|
||||
} \
|
||||
} \
|
||||
}; \
|
||||
template<typename Index, bool ConjugateLhs, bool ConjugateRhs> \
|
||||
struct general_matrix_vector_product<Index,Scalar,RowMajor,ConjugateLhs,Scalar,ConjugateRhs,Specialized> { \
|
||||
static void run( \
|
||||
Index rows, Index cols, \
|
||||
const Scalar* lhs, Index lhsStride, \
|
||||
const Scalar* rhs, Index rhsIncr, \
|
||||
Scalar* res, Index resIncr, Scalar alpha) \
|
||||
{ \
|
||||
general_matrix_vector_product_gemv<Index,Scalar,RowMajor,ConjugateLhs,Scalar,ConjugateRhs>::run( \
|
||||
rows, cols, lhs, lhsStride, rhs, rhsIncr, res, resIncr, alpha); \
|
||||
} \
|
||||
}; \
|
||||
|
||||
EIGEN_MKL_GEMV_SPECIALIZE(double)
|
||||
EIGEN_MKL_GEMV_SPECIALIZE(float)
|
||||
EIGEN_MKL_GEMV_SPECIALIZE(dcomplex)
|
||||
EIGEN_MKL_GEMV_SPECIALIZE(scomplex)
|
||||
|
||||
#define EIGEN_MKL_GEMV_SPECIALIZATION(EIGTYPE,MKLTYPE,MKLPREFIX) \
|
||||
template<typename Index, int LhsStorageOrder, bool ConjugateLhs, bool ConjugateRhs> \
|
||||
struct general_matrix_vector_product_gemv<Index,EIGTYPE,LhsStorageOrder,ConjugateLhs,EIGTYPE,ConjugateRhs> \
|
||||
{ \
|
||||
typedef Matrix<EIGTYPE,Dynamic,1,ColMajor> GEMVVector;\
|
||||
\
|
||||
static void run( \
|
||||
Index rows, Index cols, \
|
||||
const EIGTYPE* lhs, Index lhsStride, \
|
||||
const EIGTYPE* rhs, Index rhsIncr, \
|
||||
EIGTYPE* res, Index resIncr, EIGTYPE alpha) \
|
||||
{ \
|
||||
MKL_INT m=rows, n=cols, lda=lhsStride, incx=rhsIncr, incy=resIncr; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
const EIGTYPE *x_ptr, myone(1); \
|
||||
char trans=(LhsStorageOrder==ColMajor) ? 'N' : (ConjugateLhs) ? 'C' : 'T'; \
|
||||
if (LhsStorageOrder==RowMajor) { \
|
||||
m=cols; \
|
||||
n=rows; \
|
||||
}\
|
||||
assign_scalar_eig2mkl(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl(beta_, myone); \
|
||||
GEMVVector x_tmp; \
|
||||
if (ConjugateRhs) { \
|
||||
Map<const GEMVVector, 0, InnerStride<> > map_x(rhs,cols,1,InnerStride<>(incx)); \
|
||||
x_tmp=map_x.conjugate(); \
|
||||
x_ptr=x_tmp.data(); \
|
||||
incx=1; \
|
||||
} else x_ptr=rhs; \
|
||||
MKLPREFIX##gemv(&trans, &m, &n, &alpha_, (const MKLTYPE*)lhs, &lda, (const MKLTYPE*)x_ptr, &incx, &beta_, (MKLTYPE*)res, &incy); \
|
||||
}\
|
||||
};
|
||||
|
||||
EIGEN_MKL_GEMV_SPECIALIZATION(double, double, d)
|
||||
EIGEN_MKL_GEMV_SPECIALIZATION(float, float, s)
|
||||
EIGEN_MKL_GEMV_SPECIALIZATION(dcomplex, MKL_Complex16, z)
|
||||
EIGEN_MKL_GEMV_SPECIALIZATION(scomplex, MKL_Complex8, c)
|
||||
|
||||
} // end namespase internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_GENERAL_MATRIX_VECTOR_MKL_H
|
||||
|
|
@ -75,7 +75,7 @@ template<typename Index> struct GemmParallelInfo
|
|||
{
|
||||
GemmParallelInfo() : sync(-1), users(0), lhs_start(0), lhs_length(0) {}
|
||||
|
||||
int volatile sync;
|
||||
Index volatile sync;
|
||||
int volatile users;
|
||||
|
||||
Index lhs_start;
|
||||
|
|
@ -104,13 +104,14 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, Index depth,
|
|||
// - the sizes are large enough
|
||||
|
||||
// compute the maximal number of threads from the size of the product:
|
||||
// FIXME this has to be fine tuned
|
||||
// This first heuristic takes into account that the product kernel is fully optimized when working with nr columns at once.
|
||||
Index size = transpose ? rows : cols;
|
||||
Index pb_max_threads = std::max<Index>(1,size / 32);
|
||||
Index pb_max_threads = std::max<Index>(1,size / Functor::Traits::nr);
|
||||
|
||||
// compute the maximal number of threads from the total amount of work:
|
||||
double work = static_cast<double>(rows) * static_cast<double>(cols) *
|
||||
static_cast<double>(depth);
|
||||
double kMinTaskSize = 50000; // Heuristic.
|
||||
double kMinTaskSize = 50000; // FIXME improve this heuristic.
|
||||
pb_max_threads = std::max<Index>(1, std::min<Index>(pb_max_threads, work / kMinTaskSize));
|
||||
|
||||
// compute the number of threads we are going to use
|
||||
|
|
|
|||
|
|
@ -1,295 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* Self adjoint matrix * matrix product functionality based on ?SYMM/?HEMM.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_SELFADJOINT_MATRIX_MATRIX_MKL_H
|
||||
#define EIGEN_SELFADJOINT_MATRIX_MATRIX_MKL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
/* Optimized selfadjoint matrix * matrix (?SYMM/?HEMM) product */
|
||||
|
||||
#define EIGEN_MKL_SYMM_L(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \
|
||||
template <typename Index, \
|
||||
int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs> \
|
||||
struct product_selfadjoint_matrix<EIGTYPE,Index,LhsStorageOrder,true,ConjugateLhs,RhsStorageOrder,false,ConjugateRhs,ColMajor> \
|
||||
{\
|
||||
\
|
||||
static void run( \
|
||||
Index rows, Index cols, \
|
||||
const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsStride, \
|
||||
EIGTYPE* res, Index resStride, \
|
||||
EIGTYPE alpha) \
|
||||
{ \
|
||||
char side='L', uplo='L'; \
|
||||
MKL_INT m, n, lda, ldb, ldc; \
|
||||
const EIGTYPE *a, *b; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
MatrixX##EIGPREFIX b_tmp; \
|
||||
EIGTYPE myone(1);\
|
||||
\
|
||||
/* Set transpose options */ \
|
||||
/* Set m, n, k */ \
|
||||
m = (MKL_INT)rows; \
|
||||
n = (MKL_INT)cols; \
|
||||
\
|
||||
/* Set alpha_ & beta_ */ \
|
||||
assign_scalar_eig2mkl(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl(beta_, myone); \
|
||||
\
|
||||
/* Set lda, ldb, ldc */ \
|
||||
lda = (MKL_INT)lhsStride; \
|
||||
ldb = (MKL_INT)rhsStride; \
|
||||
ldc = (MKL_INT)resStride; \
|
||||
\
|
||||
/* Set a, b, c */ \
|
||||
if (LhsStorageOrder==RowMajor) uplo='U'; \
|
||||
a = _lhs; \
|
||||
\
|
||||
if (RhsStorageOrder==RowMajor) { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > rhs(_rhs,n,m,OuterStride<>(rhsStride)); \
|
||||
b_tmp = rhs.adjoint(); \
|
||||
b = b_tmp.data(); \
|
||||
ldb = b_tmp.outerStride(); \
|
||||
} else b = _rhs; \
|
||||
\
|
||||
MKLPREFIX##symm(&side, &uplo, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \
|
||||
\
|
||||
} \
|
||||
};
|
||||
|
||||
|
||||
#define EIGEN_MKL_HEMM_L(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \
|
||||
template <typename Index, \
|
||||
int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs> \
|
||||
struct product_selfadjoint_matrix<EIGTYPE,Index,LhsStorageOrder,true,ConjugateLhs,RhsStorageOrder,false,ConjugateRhs,ColMajor> \
|
||||
{\
|
||||
static void run( \
|
||||
Index rows, Index cols, \
|
||||
const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsStride, \
|
||||
EIGTYPE* res, Index resStride, \
|
||||
EIGTYPE alpha) \
|
||||
{ \
|
||||
char side='L', uplo='L'; \
|
||||
MKL_INT m, n, lda, ldb, ldc; \
|
||||
const EIGTYPE *a, *b; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
MatrixX##EIGPREFIX b_tmp; \
|
||||
Matrix<EIGTYPE, Dynamic, Dynamic, LhsStorageOrder> a_tmp; \
|
||||
EIGTYPE myone(1); \
|
||||
\
|
||||
/* Set transpose options */ \
|
||||
/* Set m, n, k */ \
|
||||
m = (MKL_INT)rows; \
|
||||
n = (MKL_INT)cols; \
|
||||
\
|
||||
/* Set alpha_ & beta_ */ \
|
||||
assign_scalar_eig2mkl(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl(beta_, myone); \
|
||||
\
|
||||
/* Set lda, ldb, ldc */ \
|
||||
lda = (MKL_INT)lhsStride; \
|
||||
ldb = (MKL_INT)rhsStride; \
|
||||
ldc = (MKL_INT)resStride; \
|
||||
\
|
||||
/* Set a, b, c */ \
|
||||
if (((LhsStorageOrder==ColMajor) && ConjugateLhs) || ((LhsStorageOrder==RowMajor) && (!ConjugateLhs))) { \
|
||||
Map<const Matrix<EIGTYPE, Dynamic, Dynamic, LhsStorageOrder>, 0, OuterStride<> > lhs(_lhs,m,m,OuterStride<>(lhsStride)); \
|
||||
a_tmp = lhs.conjugate(); \
|
||||
a = a_tmp.data(); \
|
||||
lda = a_tmp.outerStride(); \
|
||||
} else a = _lhs; \
|
||||
if (LhsStorageOrder==RowMajor) uplo='U'; \
|
||||
\
|
||||
if (RhsStorageOrder==ColMajor && (!ConjugateRhs)) { \
|
||||
b = _rhs; } \
|
||||
else { \
|
||||
if (RhsStorageOrder==ColMajor && ConjugateRhs) { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > rhs(_rhs,m,n,OuterStride<>(rhsStride)); \
|
||||
b_tmp = rhs.conjugate(); \
|
||||
} else \
|
||||
if (ConjugateRhs) { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > rhs(_rhs,n,m,OuterStride<>(rhsStride)); \
|
||||
b_tmp = rhs.adjoint(); \
|
||||
} else { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > rhs(_rhs,n,m,OuterStride<>(rhsStride)); \
|
||||
b_tmp = rhs.transpose(); \
|
||||
} \
|
||||
b = b_tmp.data(); \
|
||||
ldb = b_tmp.outerStride(); \
|
||||
} \
|
||||
\
|
||||
MKLPREFIX##hemm(&side, &uplo, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \
|
||||
\
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_SYMM_L(double, double, d, d)
|
||||
EIGEN_MKL_SYMM_L(float, float, f, s)
|
||||
EIGEN_MKL_HEMM_L(dcomplex, MKL_Complex16, cd, z)
|
||||
EIGEN_MKL_HEMM_L(scomplex, MKL_Complex8, cf, c)
|
||||
|
||||
|
||||
/* Optimized matrix * selfadjoint matrix (?SYMM/?HEMM) product */
|
||||
|
||||
#define EIGEN_MKL_SYMM_R(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \
|
||||
template <typename Index, \
|
||||
int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs> \
|
||||
struct product_selfadjoint_matrix<EIGTYPE,Index,LhsStorageOrder,false,ConjugateLhs,RhsStorageOrder,true,ConjugateRhs,ColMajor> \
|
||||
{\
|
||||
\
|
||||
static void run( \
|
||||
Index rows, Index cols, \
|
||||
const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsStride, \
|
||||
EIGTYPE* res, Index resStride, \
|
||||
EIGTYPE alpha) \
|
||||
{ \
|
||||
char side='R', uplo='L'; \
|
||||
MKL_INT m, n, lda, ldb, ldc; \
|
||||
const EIGTYPE *a, *b; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
MatrixX##EIGPREFIX b_tmp; \
|
||||
EIGTYPE myone(1);\
|
||||
\
|
||||
/* Set m, n, k */ \
|
||||
m = (MKL_INT)rows; \
|
||||
n = (MKL_INT)cols; \
|
||||
\
|
||||
/* Set alpha_ & beta_ */ \
|
||||
assign_scalar_eig2mkl(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl(beta_, myone); \
|
||||
\
|
||||
/* Set lda, ldb, ldc */ \
|
||||
lda = (MKL_INT)rhsStride; \
|
||||
ldb = (MKL_INT)lhsStride; \
|
||||
ldc = (MKL_INT)resStride; \
|
||||
\
|
||||
/* Set a, b, c */ \
|
||||
if (RhsStorageOrder==RowMajor) uplo='U'; \
|
||||
a = _rhs; \
|
||||
\
|
||||
if (LhsStorageOrder==RowMajor) { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > lhs(_lhs,n,m,OuterStride<>(rhsStride)); \
|
||||
b_tmp = lhs.adjoint(); \
|
||||
b = b_tmp.data(); \
|
||||
ldb = b_tmp.outerStride(); \
|
||||
} else b = _lhs; \
|
||||
\
|
||||
MKLPREFIX##symm(&side, &uplo, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \
|
||||
\
|
||||
} \
|
||||
};
|
||||
|
||||
|
||||
#define EIGEN_MKL_HEMM_R(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \
|
||||
template <typename Index, \
|
||||
int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs> \
|
||||
struct product_selfadjoint_matrix<EIGTYPE,Index,LhsStorageOrder,false,ConjugateLhs,RhsStorageOrder,true,ConjugateRhs,ColMajor> \
|
||||
{\
|
||||
static void run( \
|
||||
Index rows, Index cols, \
|
||||
const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsStride, \
|
||||
EIGTYPE* res, Index resStride, \
|
||||
EIGTYPE alpha) \
|
||||
{ \
|
||||
char side='R', uplo='L'; \
|
||||
MKL_INT m, n, lda, ldb, ldc; \
|
||||
const EIGTYPE *a, *b; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
MatrixX##EIGPREFIX b_tmp; \
|
||||
Matrix<EIGTYPE, Dynamic, Dynamic, RhsStorageOrder> a_tmp; \
|
||||
EIGTYPE myone(1); \
|
||||
\
|
||||
/* Set m, n, k */ \
|
||||
m = (MKL_INT)rows; \
|
||||
n = (MKL_INT)cols; \
|
||||
\
|
||||
/* Set alpha_ & beta_ */ \
|
||||
assign_scalar_eig2mkl(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl(beta_, myone); \
|
||||
\
|
||||
/* Set lda, ldb, ldc */ \
|
||||
lda = (MKL_INT)rhsStride; \
|
||||
ldb = (MKL_INT)lhsStride; \
|
||||
ldc = (MKL_INT)resStride; \
|
||||
\
|
||||
/* Set a, b, c */ \
|
||||
if (((RhsStorageOrder==ColMajor) && ConjugateRhs) || ((RhsStorageOrder==RowMajor) && (!ConjugateRhs))) { \
|
||||
Map<const Matrix<EIGTYPE, Dynamic, Dynamic, RhsStorageOrder>, 0, OuterStride<> > rhs(_rhs,n,n,OuterStride<>(rhsStride)); \
|
||||
a_tmp = rhs.conjugate(); \
|
||||
a = a_tmp.data(); \
|
||||
lda = a_tmp.outerStride(); \
|
||||
} else a = _rhs; \
|
||||
if (RhsStorageOrder==RowMajor) uplo='U'; \
|
||||
\
|
||||
if (LhsStorageOrder==ColMajor && (!ConjugateLhs)) { \
|
||||
b = _lhs; } \
|
||||
else { \
|
||||
if (LhsStorageOrder==ColMajor && ConjugateLhs) { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > lhs(_lhs,m,n,OuterStride<>(lhsStride)); \
|
||||
b_tmp = lhs.conjugate(); \
|
||||
} else \
|
||||
if (ConjugateLhs) { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > lhs(_lhs,n,m,OuterStride<>(lhsStride)); \
|
||||
b_tmp = lhs.adjoint(); \
|
||||
} else { \
|
||||
Map<const MatrixX##EIGPREFIX, 0, OuterStride<> > lhs(_lhs,n,m,OuterStride<>(lhsStride)); \
|
||||
b_tmp = lhs.transpose(); \
|
||||
} \
|
||||
b = b_tmp.data(); \
|
||||
ldb = b_tmp.outerStride(); \
|
||||
} \
|
||||
\
|
||||
MKLPREFIX##hemm(&side, &uplo, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_SYMM_R(double, double, d, d)
|
||||
EIGEN_MKL_SYMM_R(float, float, f, s)
|
||||
EIGEN_MKL_HEMM_R(dcomplex, MKL_Complex16, cd, z)
|
||||
EIGEN_MKL_HEMM_R(scomplex, MKL_Complex8, cf, c)
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_SELFADJOINT_MATRIX_MATRIX_MKL_H
|
||||
|
|
@ -83,10 +83,10 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||
Scalar t3(0);
|
||||
Packet ptmp3 = pset1<Packet>(t3);
|
||||
|
||||
size_t starti = FirstTriangular ? 0 : j+2;
|
||||
size_t endi = FirstTriangular ? j : size;
|
||||
size_t alignedStart = (starti) + internal::first_default_aligned(&res[starti], endi-starti);
|
||||
size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize);
|
||||
Index starti = FirstTriangular ? 0 : j+2;
|
||||
Index endi = FirstTriangular ? j : size;
|
||||
Index alignedStart = (starti) + internal::first_default_aligned(&res[starti], endi-starti);
|
||||
Index alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize);
|
||||
|
||||
res[j] += cjd.pmul(numext::real(A0[j]), t0);
|
||||
res[j+1] += cjd.pmul(numext::real(A1[j+1]), t1);
|
||||
|
|
@ -101,7 +101,7 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||
t2 += cj1.pmul(A0[j+1], rhs[j+1]);
|
||||
}
|
||||
|
||||
for (size_t i=starti; i<alignedStart; ++i)
|
||||
for (Index i=starti; i<alignedStart; ++i)
|
||||
{
|
||||
res[i] += cj0.pmul(A0[i], t0) + cj0.pmul(A1[i],t1);
|
||||
t2 += cj1.pmul(A0[i], rhs[i]);
|
||||
|
|
@ -113,7 +113,7 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||
const Scalar* EIGEN_RESTRICT a1It = A1 + alignedStart;
|
||||
const Scalar* EIGEN_RESTRICT rhsIt = rhs + alignedStart;
|
||||
Scalar* EIGEN_RESTRICT resIt = res + alignedStart;
|
||||
for (size_t i=alignedStart; i<alignedEnd; i+=PacketSize)
|
||||
for (Index i=alignedStart; i<alignedEnd; i+=PacketSize)
|
||||
{
|
||||
Packet A0i = ploadu<Packet>(a0It); a0It += PacketSize;
|
||||
Packet A1i = ploadu<Packet>(a1It); a1It += PacketSize;
|
||||
|
|
@ -125,7 +125,7 @@ EIGEN_DONT_INLINE void selfadjoint_matrix_vector_product<Scalar,Index,StorageOrd
|
|||
ptmp3 = pcj1.pmadd(A1i, Bi, ptmp3);
|
||||
pstore(resIt,Xi); resIt += PacketSize;
|
||||
}
|
||||
for (size_t i=alignedEnd; i<endi; i++)
|
||||
for (Index i=alignedEnd; i<endi; i++)
|
||||
{
|
||||
res[i] += cj0.pmul(A0[i], t0) + cj0.pmul(A1[i],t1);
|
||||
t2 += cj1.pmul(A0[i], rhs[i]);
|
||||
|
|
|
|||
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* Selfadjoint matrix-vector product functionality based on ?SYMV/HEMV.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_SELFADJOINT_MATRIX_VECTOR_MKL_H
|
||||
#define EIGEN_SELFADJOINT_MATRIX_VECTOR_MKL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/**********************************************************************
|
||||
* This file implements selfadjoint matrix-vector multiplication using BLAS
|
||||
**********************************************************************/
|
||||
|
||||
// symv/hemv specialization
|
||||
|
||||
template<typename Scalar, typename Index, int StorageOrder, int UpLo, bool ConjugateLhs, bool ConjugateRhs>
|
||||
struct selfadjoint_matrix_vector_product_symv :
|
||||
selfadjoint_matrix_vector_product<Scalar,Index,StorageOrder,UpLo,ConjugateLhs,ConjugateRhs,BuiltIn> {};
|
||||
|
||||
#define EIGEN_MKL_SYMV_SPECIALIZE(Scalar) \
|
||||
template<typename Index, int StorageOrder, int UpLo, bool ConjugateLhs, bool ConjugateRhs> \
|
||||
struct selfadjoint_matrix_vector_product<Scalar,Index,StorageOrder,UpLo,ConjugateLhs,ConjugateRhs,Specialized> { \
|
||||
static void run( \
|
||||
Index size, const Scalar* lhs, Index lhsStride, \
|
||||
const Scalar* _rhs, Index rhsIncr, Scalar* res, Scalar alpha) { \
|
||||
enum {\
|
||||
IsColMajor = StorageOrder==ColMajor \
|
||||
}; \
|
||||
if (IsColMajor == ConjugateLhs) {\
|
||||
selfadjoint_matrix_vector_product<Scalar,Index,StorageOrder,UpLo,ConjugateLhs,ConjugateRhs,BuiltIn>::run( \
|
||||
size, lhs, lhsStride, _rhs, rhsIncr, res, alpha); \
|
||||
} else {\
|
||||
selfadjoint_matrix_vector_product_symv<Scalar,Index,StorageOrder,UpLo,ConjugateLhs,ConjugateRhs>::run( \
|
||||
size, lhs, lhsStride, _rhs, rhsIncr, res, alpha); \
|
||||
}\
|
||||
} \
|
||||
}; \
|
||||
|
||||
EIGEN_MKL_SYMV_SPECIALIZE(double)
|
||||
EIGEN_MKL_SYMV_SPECIALIZE(float)
|
||||
EIGEN_MKL_SYMV_SPECIALIZE(dcomplex)
|
||||
EIGEN_MKL_SYMV_SPECIALIZE(scomplex)
|
||||
|
||||
#define EIGEN_MKL_SYMV_SPECIALIZATION(EIGTYPE,MKLTYPE,MKLFUNC) \
|
||||
template<typename Index, int StorageOrder, int UpLo, bool ConjugateLhs, bool ConjugateRhs> \
|
||||
struct selfadjoint_matrix_vector_product_symv<EIGTYPE,Index,StorageOrder,UpLo,ConjugateLhs,ConjugateRhs> \
|
||||
{ \
|
||||
typedef Matrix<EIGTYPE,Dynamic,1,ColMajor> SYMVVector;\
|
||||
\
|
||||
static void run( \
|
||||
Index size, const EIGTYPE* lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* res, EIGTYPE alpha) \
|
||||
{ \
|
||||
enum {\
|
||||
IsRowMajor = StorageOrder==RowMajor ? 1 : 0, \
|
||||
IsLower = UpLo == Lower ? 1 : 0 \
|
||||
}; \
|
||||
MKL_INT n=size, lda=lhsStride, incx=rhsIncr, incy=1; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
const EIGTYPE *x_ptr, myone(1); \
|
||||
char uplo=(IsRowMajor) ? (IsLower ? 'U' : 'L') : (IsLower ? 'L' : 'U'); \
|
||||
assign_scalar_eig2mkl(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl(beta_, myone); \
|
||||
SYMVVector x_tmp; \
|
||||
if (ConjugateRhs) { \
|
||||
Map<const SYMVVector, 0, InnerStride<> > map_x(_rhs,size,1,InnerStride<>(incx)); \
|
||||
x_tmp=map_x.conjugate(); \
|
||||
x_ptr=x_tmp.data(); \
|
||||
incx=1; \
|
||||
} else x_ptr=_rhs; \
|
||||
MKLFUNC(&uplo, &n, &alpha_, (const MKLTYPE*)lhs, &lda, (const MKLTYPE*)x_ptr, &incx, &beta_, (MKLTYPE*)res, &incy); \
|
||||
}\
|
||||
};
|
||||
|
||||
EIGEN_MKL_SYMV_SPECIALIZATION(double, double, dsymv)
|
||||
EIGEN_MKL_SYMV_SPECIALIZATION(float, float, ssymv)
|
||||
EIGEN_MKL_SYMV_SPECIALIZATION(dcomplex, MKL_Complex16, zhemv)
|
||||
EIGEN_MKL_SYMV_SPECIALIZATION(scomplex, MKL_Complex8, chemv)
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_SELFADJOINT_MATRIX_VECTOR_MKL_H
|
||||
|
|
@ -137,7 +137,7 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix<Scalar,Index,Mode,true,
|
|||
ei_declare_aligned_stack_constructed_variable(Scalar, blockA, sizeA, blocking.blockA());
|
||||
ei_declare_aligned_stack_constructed_variable(Scalar, blockB, sizeB, blocking.blockB());
|
||||
|
||||
Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,LhsStorageOrder> triangularBuffer;
|
||||
Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,LhsStorageOrder> triangularBuffer((internal::constructor_without_unaligned_array_assert()));
|
||||
triangularBuffer.setZero();
|
||||
if((Mode&ZeroDiag)==ZeroDiag)
|
||||
triangularBuffer.diagonal().setZero();
|
||||
|
|
@ -284,7 +284,7 @@ EIGEN_DONT_INLINE void product_triangular_matrix_matrix<Scalar,Index,Mode,false,
|
|||
ei_declare_aligned_stack_constructed_variable(Scalar, blockA, sizeA, blocking.blockA());
|
||||
ei_declare_aligned_stack_constructed_variable(Scalar, blockB, sizeB, blocking.blockB());
|
||||
|
||||
Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,RhsStorageOrder> triangularBuffer;
|
||||
Matrix<Scalar,SmallPanelWidth,SmallPanelWidth,RhsStorageOrder> triangularBuffer((internal::constructor_without_unaligned_array_assert()));
|
||||
triangularBuffer.setZero();
|
||||
if((Mode&ZeroDiag)==ZeroDiag)
|
||||
triangularBuffer.diagonal().setZero();
|
||||
|
|
|
|||
|
|
@ -1,309 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* Triangular matrix * matrix product functionality based on ?TRMM.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_TRIANGULAR_MATRIX_MATRIX_MKL_H
|
||||
#define EIGEN_TRIANGULAR_MATRIX_MATRIX_MKL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
|
||||
template <typename Scalar, typename Index,
|
||||
int Mode, bool LhsIsTriangular,
|
||||
int LhsStorageOrder, bool ConjugateLhs,
|
||||
int RhsStorageOrder, bool ConjugateRhs,
|
||||
int ResStorageOrder>
|
||||
struct product_triangular_matrix_matrix_trmm :
|
||||
product_triangular_matrix_matrix<Scalar,Index,Mode,
|
||||
LhsIsTriangular,LhsStorageOrder,ConjugateLhs,
|
||||
RhsStorageOrder, ConjugateRhs, ResStorageOrder, BuiltIn> {};
|
||||
|
||||
|
||||
// try to go to BLAS specialization
|
||||
#define EIGEN_MKL_TRMM_SPECIALIZE(Scalar, LhsIsTriangular) \
|
||||
template <typename Index, int Mode, \
|
||||
int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs> \
|
||||
struct product_triangular_matrix_matrix<Scalar,Index, Mode, LhsIsTriangular, \
|
||||
LhsStorageOrder,ConjugateLhs, RhsStorageOrder,ConjugateRhs,ColMajor,Specialized> { \
|
||||
static inline void run(Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride,\
|
||||
const Scalar* _rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha, level3_blocking<Scalar,Scalar>& blocking) { \
|
||||
product_triangular_matrix_matrix_trmm<Scalar,Index,Mode, \
|
||||
LhsIsTriangular,LhsStorageOrder,ConjugateLhs, \
|
||||
RhsStorageOrder, ConjugateRhs, ColMajor>::run( \
|
||||
_rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_TRMM_SPECIALIZE(double, true)
|
||||
EIGEN_MKL_TRMM_SPECIALIZE(double, false)
|
||||
EIGEN_MKL_TRMM_SPECIALIZE(dcomplex, true)
|
||||
EIGEN_MKL_TRMM_SPECIALIZE(dcomplex, false)
|
||||
EIGEN_MKL_TRMM_SPECIALIZE(float, true)
|
||||
EIGEN_MKL_TRMM_SPECIALIZE(float, false)
|
||||
EIGEN_MKL_TRMM_SPECIALIZE(scomplex, true)
|
||||
EIGEN_MKL_TRMM_SPECIALIZE(scomplex, false)
|
||||
|
||||
// implements col-major += alpha * op(triangular) * op(general)
|
||||
#define EIGEN_MKL_TRMM_L(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \
|
||||
template <typename Index, int Mode, \
|
||||
int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs> \
|
||||
struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,true, \
|
||||
LhsStorageOrder,ConjugateLhs,RhsStorageOrder,ConjugateRhs,ColMajor> \
|
||||
{ \
|
||||
enum { \
|
||||
IsLower = (Mode&Lower) == Lower, \
|
||||
SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1, \
|
||||
IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \
|
||||
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
|
||||
LowUp = IsLower ? Lower : Upper, \
|
||||
conjA = ((LhsStorageOrder==ColMajor) && ConjugateLhs) ? 1 : 0 \
|
||||
}; \
|
||||
\
|
||||
static void run( \
|
||||
Index _rows, Index _cols, Index _depth, \
|
||||
const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsStride, \
|
||||
EIGTYPE* res, Index resStride, \
|
||||
EIGTYPE alpha, level3_blocking<EIGTYPE,EIGTYPE>& blocking) \
|
||||
{ \
|
||||
Index diagSize = (std::min)(_rows,_depth); \
|
||||
Index rows = IsLower ? _rows : diagSize; \
|
||||
Index depth = IsLower ? diagSize : _depth; \
|
||||
Index cols = _cols; \
|
||||
\
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, LhsStorageOrder> MatrixLhs; \
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, RhsStorageOrder> MatrixRhs; \
|
||||
\
|
||||
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
||||
if (rows != depth) { \
|
||||
\
|
||||
int nthr = mkl_domain_get_max_threads(EIGEN_MKL_DOMAIN_BLAS); \
|
||||
\
|
||||
if (((nthr==1) && (((std::max)(rows,depth)-diagSize)/(double)diagSize < 0.5))) { \
|
||||
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
||||
product_triangular_matrix_matrix<EIGTYPE,Index,Mode,true, \
|
||||
LhsStorageOrder,ConjugateLhs, RhsStorageOrder, ConjugateRhs, ColMajor, BuiltIn>::run( \
|
||||
_rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \
|
||||
/*std::cout << "TRMM_L: A is not square! Go to Eigen TRMM implementation!\n";*/ \
|
||||
} else { \
|
||||
/* Make sense to call GEMM */ \
|
||||
Map<const MatrixLhs, 0, OuterStride<> > lhsMap(_lhs,rows,depth,OuterStride<>(lhsStride)); \
|
||||
MatrixLhs aa_tmp=lhsMap.template triangularView<Mode>(); \
|
||||
MKL_INT aStride = aa_tmp.outerStride(); \
|
||||
gemm_blocking_space<ColMajor,EIGTYPE,EIGTYPE,Dynamic,Dynamic,Dynamic> gemm_blocking(_rows,_cols,_depth); \
|
||||
general_matrix_matrix_product<Index,EIGTYPE,LhsStorageOrder,ConjugateLhs,EIGTYPE,RhsStorageOrder,ConjugateRhs,ColMajor>::run( \
|
||||
rows, cols, depth, aa_tmp.data(), aStride, _rhs, rhsStride, res, resStride, alpha, gemm_blocking, 0); \
|
||||
\
|
||||
/*std::cout << "TRMM_L: A is not square! Go to MKL GEMM implementation! " << nthr<<" \n";*/ \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
char side = 'L', transa, uplo, diag = 'N'; \
|
||||
EIGTYPE *b; \
|
||||
const EIGTYPE *a; \
|
||||
MKL_INT m, n, lda, ldb; \
|
||||
MKLTYPE alpha_; \
|
||||
\
|
||||
/* Set alpha_*/ \
|
||||
assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(alpha_, alpha); \
|
||||
\
|
||||
/* Set m, n */ \
|
||||
m = (MKL_INT)diagSize; \
|
||||
n = (MKL_INT)cols; \
|
||||
\
|
||||
/* Set trans */ \
|
||||
transa = (LhsStorageOrder==RowMajor) ? ((ConjugateLhs) ? 'C' : 'T') : 'N'; \
|
||||
\
|
||||
/* Set b, ldb */ \
|
||||
Map<const MatrixRhs, 0, OuterStride<> > rhs(_rhs,depth,cols,OuterStride<>(rhsStride)); \
|
||||
MatrixX##EIGPREFIX b_tmp; \
|
||||
\
|
||||
if (ConjugateRhs) b_tmp = rhs.conjugate(); else b_tmp = rhs; \
|
||||
b = b_tmp.data(); \
|
||||
ldb = b_tmp.outerStride(); \
|
||||
\
|
||||
/* Set uplo */ \
|
||||
uplo = IsLower ? 'L' : 'U'; \
|
||||
if (LhsStorageOrder==RowMajor) uplo = (uplo == 'L') ? 'U' : 'L'; \
|
||||
/* Set a, lda */ \
|
||||
Map<const MatrixLhs, 0, OuterStride<> > lhs(_lhs,rows,depth,OuterStride<>(lhsStride)); \
|
||||
MatrixLhs a_tmp; \
|
||||
\
|
||||
if ((conjA!=0) || (SetDiag==0)) { \
|
||||
if (conjA) a_tmp = lhs.conjugate(); else a_tmp = lhs; \
|
||||
if (IsZeroDiag) \
|
||||
a_tmp.diagonal().setZero(); \
|
||||
else if (IsUnitDiag) \
|
||||
a_tmp.diagonal().setOnes();\
|
||||
a = a_tmp.data(); \
|
||||
lda = a_tmp.outerStride(); \
|
||||
} else { \
|
||||
a = _lhs; \
|
||||
lda = lhsStride; \
|
||||
} \
|
||||
/*std::cout << "TRMM_L: A is square! Go to MKL TRMM implementation! \n";*/ \
|
||||
/* call ?trmm*/ \
|
||||
MKLPREFIX##trmm(&side, &uplo, &transa, &diag, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (MKLTYPE*)b, &ldb); \
|
||||
\
|
||||
/* Add op(a_triangular)*b into res*/ \
|
||||
Map<MatrixX##EIGPREFIX, 0, OuterStride<> > res_tmp(res,rows,cols,OuterStride<>(resStride)); \
|
||||
res_tmp=res_tmp+b_tmp; \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_TRMM_L(double, double, d, d)
|
||||
EIGEN_MKL_TRMM_L(dcomplex, MKL_Complex16, cd, z)
|
||||
EIGEN_MKL_TRMM_L(float, float, f, s)
|
||||
EIGEN_MKL_TRMM_L(scomplex, MKL_Complex8, cf, c)
|
||||
|
||||
// implements col-major += alpha * op(general) * op(triangular)
|
||||
#define EIGEN_MKL_TRMM_R(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \
|
||||
template <typename Index, int Mode, \
|
||||
int LhsStorageOrder, bool ConjugateLhs, \
|
||||
int RhsStorageOrder, bool ConjugateRhs> \
|
||||
struct product_triangular_matrix_matrix_trmm<EIGTYPE,Index,Mode,false, \
|
||||
LhsStorageOrder,ConjugateLhs,RhsStorageOrder,ConjugateRhs,ColMajor> \
|
||||
{ \
|
||||
enum { \
|
||||
IsLower = (Mode&Lower) == Lower, \
|
||||
SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1, \
|
||||
IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \
|
||||
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
|
||||
LowUp = IsLower ? Lower : Upper, \
|
||||
conjA = ((RhsStorageOrder==ColMajor) && ConjugateRhs) ? 1 : 0 \
|
||||
}; \
|
||||
\
|
||||
static void run( \
|
||||
Index _rows, Index _cols, Index _depth, \
|
||||
const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsStride, \
|
||||
EIGTYPE* res, Index resStride, \
|
||||
EIGTYPE alpha, level3_blocking<EIGTYPE,EIGTYPE>& blocking) \
|
||||
{ \
|
||||
Index diagSize = (std::min)(_cols,_depth); \
|
||||
Index rows = _rows; \
|
||||
Index depth = IsLower ? _depth : diagSize; \
|
||||
Index cols = IsLower ? diagSize : _cols; \
|
||||
\
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, LhsStorageOrder> MatrixLhs; \
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, RhsStorageOrder> MatrixRhs; \
|
||||
\
|
||||
/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \
|
||||
if (cols != depth) { \
|
||||
\
|
||||
int nthr = mkl_domain_get_max_threads(EIGEN_MKL_DOMAIN_BLAS); \
|
||||
\
|
||||
if ((nthr==1) && (((std::max)(cols,depth)-diagSize)/(double)diagSize < 0.5)) { \
|
||||
/* Most likely no benefit to call TRMM or GEMM from MKL*/ \
|
||||
product_triangular_matrix_matrix<EIGTYPE,Index,Mode,false, \
|
||||
LhsStorageOrder,ConjugateLhs, RhsStorageOrder, ConjugateRhs, ColMajor, BuiltIn>::run( \
|
||||
_rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha, blocking); \
|
||||
/*std::cout << "TRMM_R: A is not square! Go to Eigen TRMM implementation!\n";*/ \
|
||||
} else { \
|
||||
/* Make sense to call GEMM */ \
|
||||
Map<const MatrixRhs, 0, OuterStride<> > rhsMap(_rhs,depth,cols, OuterStride<>(rhsStride)); \
|
||||
MatrixRhs aa_tmp=rhsMap.template triangularView<Mode>(); \
|
||||
MKL_INT aStride = aa_tmp.outerStride(); \
|
||||
gemm_blocking_space<ColMajor,EIGTYPE,EIGTYPE,Dynamic,Dynamic,Dynamic> gemm_blocking(_rows,_cols,_depth); \
|
||||
general_matrix_matrix_product<Index,EIGTYPE,LhsStorageOrder,ConjugateLhs,EIGTYPE,RhsStorageOrder,ConjugateRhs,ColMajor>::run( \
|
||||
rows, cols, depth, _lhs, lhsStride, aa_tmp.data(), aStride, res, resStride, alpha, gemm_blocking, 0); \
|
||||
\
|
||||
/*std::cout << "TRMM_R: A is not square! Go to MKL GEMM implementation! " << nthr<<" \n";*/ \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
char side = 'R', transa, uplo, diag = 'N'; \
|
||||
EIGTYPE *b; \
|
||||
const EIGTYPE *a; \
|
||||
MKL_INT m, n, lda, ldb; \
|
||||
MKLTYPE alpha_; \
|
||||
\
|
||||
/* Set alpha_*/ \
|
||||
assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(alpha_, alpha); \
|
||||
\
|
||||
/* Set m, n */ \
|
||||
m = (MKL_INT)rows; \
|
||||
n = (MKL_INT)diagSize; \
|
||||
\
|
||||
/* Set trans */ \
|
||||
transa = (RhsStorageOrder==RowMajor) ? ((ConjugateRhs) ? 'C' : 'T') : 'N'; \
|
||||
\
|
||||
/* Set b, ldb */ \
|
||||
Map<const MatrixLhs, 0, OuterStride<> > lhs(_lhs,rows,depth,OuterStride<>(lhsStride)); \
|
||||
MatrixX##EIGPREFIX b_tmp; \
|
||||
\
|
||||
if (ConjugateLhs) b_tmp = lhs.conjugate(); else b_tmp = lhs; \
|
||||
b = b_tmp.data(); \
|
||||
ldb = b_tmp.outerStride(); \
|
||||
\
|
||||
/* Set uplo */ \
|
||||
uplo = IsLower ? 'L' : 'U'; \
|
||||
if (RhsStorageOrder==RowMajor) uplo = (uplo == 'L') ? 'U' : 'L'; \
|
||||
/* Set a, lda */ \
|
||||
Map<const MatrixRhs, 0, OuterStride<> > rhs(_rhs,depth,cols, OuterStride<>(rhsStride)); \
|
||||
MatrixRhs a_tmp; \
|
||||
\
|
||||
if ((conjA!=0) || (SetDiag==0)) { \
|
||||
if (conjA) a_tmp = rhs.conjugate(); else a_tmp = rhs; \
|
||||
if (IsZeroDiag) \
|
||||
a_tmp.diagonal().setZero(); \
|
||||
else if (IsUnitDiag) \
|
||||
a_tmp.diagonal().setOnes();\
|
||||
a = a_tmp.data(); \
|
||||
lda = a_tmp.outerStride(); \
|
||||
} else { \
|
||||
a = _rhs; \
|
||||
lda = rhsStride; \
|
||||
} \
|
||||
/*std::cout << "TRMM_R: A is square! Go to MKL TRMM implementation! \n";*/ \
|
||||
/* call ?trmm*/ \
|
||||
MKLPREFIX##trmm(&side, &uplo, &transa, &diag, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (MKLTYPE*)b, &ldb); \
|
||||
\
|
||||
/* Add op(a_triangular)*b into res*/ \
|
||||
Map<MatrixX##EIGPREFIX, 0, OuterStride<> > res_tmp(res,rows,cols,OuterStride<>(resStride)); \
|
||||
res_tmp=res_tmp+b_tmp; \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_TRMM_R(double, double, d, d)
|
||||
EIGEN_MKL_TRMM_R(dcomplex, MKL_Complex16, cd, z)
|
||||
EIGEN_MKL_TRMM_R(float, float, f, s)
|
||||
EIGEN_MKL_TRMM_R(scomplex, MKL_Complex8, cf, c)
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_TRIANGULAR_MATRIX_MATRIX_MKL_H
|
||||
|
|
@ -1,247 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* Triangular matrix-vector product functionality based on ?TRMV.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_TRIANGULAR_MATRIX_VECTOR_MKL_H
|
||||
#define EIGEN_TRIANGULAR_MATRIX_VECTOR_MKL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/**********************************************************************
|
||||
* This file implements triangular matrix-vector multiplication using BLAS
|
||||
**********************************************************************/
|
||||
|
||||
// trmv/hemv specialization
|
||||
|
||||
template<typename Index, int Mode, typename LhsScalar, bool ConjLhs, typename RhsScalar, bool ConjRhs, int StorageOrder>
|
||||
struct triangular_matrix_vector_product_trmv :
|
||||
triangular_matrix_vector_product<Index,Mode,LhsScalar,ConjLhs,RhsScalar,ConjRhs,StorageOrder,BuiltIn> {};
|
||||
|
||||
#define EIGEN_MKL_TRMV_SPECIALIZE(Scalar) \
|
||||
template<typename Index, int Mode, bool ConjLhs, bool ConjRhs> \
|
||||
struct triangular_matrix_vector_product<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,ColMajor,Specialized> { \
|
||||
static void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \
|
||||
const Scalar* _rhs, Index rhsIncr, Scalar* _res, Index resIncr, Scalar alpha) { \
|
||||
triangular_matrix_vector_product_trmv<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,ColMajor>::run( \
|
||||
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
|
||||
} \
|
||||
}; \
|
||||
template<typename Index, int Mode, bool ConjLhs, bool ConjRhs> \
|
||||
struct triangular_matrix_vector_product<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,RowMajor,Specialized> { \
|
||||
static void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \
|
||||
const Scalar* _rhs, Index rhsIncr, Scalar* _res, Index resIncr, Scalar alpha) { \
|
||||
triangular_matrix_vector_product_trmv<Index,Mode,Scalar,ConjLhs,Scalar,ConjRhs,RowMajor>::run( \
|
||||
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_TRMV_SPECIALIZE(double)
|
||||
EIGEN_MKL_TRMV_SPECIALIZE(float)
|
||||
EIGEN_MKL_TRMV_SPECIALIZE(dcomplex)
|
||||
EIGEN_MKL_TRMV_SPECIALIZE(scomplex)
|
||||
|
||||
// implements col-major: res += alpha * op(triangular) * vector
|
||||
#define EIGEN_MKL_TRMV_CM(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \
|
||||
template<typename Index, int Mode, bool ConjLhs, bool ConjRhs> \
|
||||
struct triangular_matrix_vector_product_trmv<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,ConjRhs,ColMajor> { \
|
||||
enum { \
|
||||
IsLower = (Mode&Lower) == Lower, \
|
||||
SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1, \
|
||||
IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \
|
||||
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
|
||||
LowUp = IsLower ? Lower : Upper \
|
||||
}; \
|
||||
static void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha) \
|
||||
{ \
|
||||
if (ConjLhs || IsZeroDiag) { \
|
||||
triangular_matrix_vector_product<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,ConjRhs,ColMajor,BuiltIn>::run( \
|
||||
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
|
||||
return; \
|
||||
}\
|
||||
Index size = (std::min)(_rows,_cols); \
|
||||
Index rows = IsLower ? _rows : size; \
|
||||
Index cols = IsLower ? size : _cols; \
|
||||
\
|
||||
typedef VectorX##EIGPREFIX VectorRhs; \
|
||||
EIGTYPE *x, *y;\
|
||||
\
|
||||
/* Set x*/ \
|
||||
Map<const VectorRhs, 0, InnerStride<> > rhs(_rhs,cols,InnerStride<>(rhsIncr)); \
|
||||
VectorRhs x_tmp; \
|
||||
if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \
|
||||
x = x_tmp.data(); \
|
||||
\
|
||||
/* Square part handling */\
|
||||
\
|
||||
char trans, uplo, diag; \
|
||||
MKL_INT m, n, lda, incx, incy; \
|
||||
EIGTYPE const *a; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(beta_, EIGTYPE(1)); \
|
||||
\
|
||||
/* Set m, n */ \
|
||||
n = (MKL_INT)size; \
|
||||
lda = lhsStride; \
|
||||
incx = 1; \
|
||||
incy = resIncr; \
|
||||
\
|
||||
/* Set uplo, trans and diag*/ \
|
||||
trans = 'N'; \
|
||||
uplo = IsLower ? 'L' : 'U'; \
|
||||
diag = IsUnitDiag ? 'U' : 'N'; \
|
||||
\
|
||||
/* call ?TRMV*/ \
|
||||
MKLPREFIX##trmv(&uplo, &trans, &diag, &n, (const MKLTYPE*)_lhs, &lda, (MKLTYPE*)x, &incx); \
|
||||
\
|
||||
/* Add op(a_tr)rhs into res*/ \
|
||||
MKLPREFIX##axpy(&n, &alpha_,(const MKLTYPE*)x, &incx, (MKLTYPE*)_res, &incy); \
|
||||
/* Non-square case - doesn't fit to MKL ?TRMV. Fall to default triangular product*/ \
|
||||
if (size<(std::max)(rows,cols)) { \
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic> MatrixLhs; \
|
||||
if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \
|
||||
x = x_tmp.data(); \
|
||||
if (size<rows) { \
|
||||
y = _res + size*resIncr; \
|
||||
a = _lhs + size; \
|
||||
m = rows-size; \
|
||||
n = size; \
|
||||
} \
|
||||
else { \
|
||||
x += size; \
|
||||
y = _res; \
|
||||
a = _lhs + size*lda; \
|
||||
m = size; \
|
||||
n = cols-size; \
|
||||
} \
|
||||
MKLPREFIX##gemv(&trans, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)x, &incx, &beta_, (MKLTYPE*)y, &incy); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_TRMV_CM(double, double, d, d)
|
||||
EIGEN_MKL_TRMV_CM(dcomplex, MKL_Complex16, cd, z)
|
||||
EIGEN_MKL_TRMV_CM(float, float, f, s)
|
||||
EIGEN_MKL_TRMV_CM(scomplex, MKL_Complex8, cf, c)
|
||||
|
||||
// implements row-major: res += alpha * op(triangular) * vector
|
||||
#define EIGEN_MKL_TRMV_RM(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \
|
||||
template<typename Index, int Mode, bool ConjLhs, bool ConjRhs> \
|
||||
struct triangular_matrix_vector_product_trmv<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,ConjRhs,RowMajor> { \
|
||||
enum { \
|
||||
IsLower = (Mode&Lower) == Lower, \
|
||||
SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1, \
|
||||
IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \
|
||||
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
|
||||
LowUp = IsLower ? Lower : Upper \
|
||||
}; \
|
||||
static void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \
|
||||
const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha) \
|
||||
{ \
|
||||
if (IsZeroDiag) { \
|
||||
triangular_matrix_vector_product<Index,Mode,EIGTYPE,ConjLhs,EIGTYPE,ConjRhs,RowMajor,BuiltIn>::run( \
|
||||
_rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \
|
||||
return; \
|
||||
}\
|
||||
Index size = (std::min)(_rows,_cols); \
|
||||
Index rows = IsLower ? _rows : size; \
|
||||
Index cols = IsLower ? size : _cols; \
|
||||
\
|
||||
typedef VectorX##EIGPREFIX VectorRhs; \
|
||||
EIGTYPE *x, *y;\
|
||||
\
|
||||
/* Set x*/ \
|
||||
Map<const VectorRhs, 0, InnerStride<> > rhs(_rhs,cols,InnerStride<>(rhsIncr)); \
|
||||
VectorRhs x_tmp; \
|
||||
if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \
|
||||
x = x_tmp.data(); \
|
||||
\
|
||||
/* Square part handling */\
|
||||
\
|
||||
char trans, uplo, diag; \
|
||||
MKL_INT m, n, lda, incx, incy; \
|
||||
EIGTYPE const *a; \
|
||||
MKLTYPE alpha_, beta_; \
|
||||
assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(alpha_, alpha); \
|
||||
assign_scalar_eig2mkl<MKLTYPE, EIGTYPE>(beta_, EIGTYPE(1)); \
|
||||
\
|
||||
/* Set m, n */ \
|
||||
n = (MKL_INT)size; \
|
||||
lda = lhsStride; \
|
||||
incx = 1; \
|
||||
incy = resIncr; \
|
||||
\
|
||||
/* Set uplo, trans and diag*/ \
|
||||
trans = ConjLhs ? 'C' : 'T'; \
|
||||
uplo = IsLower ? 'U' : 'L'; \
|
||||
diag = IsUnitDiag ? 'U' : 'N'; \
|
||||
\
|
||||
/* call ?TRMV*/ \
|
||||
MKLPREFIX##trmv(&uplo, &trans, &diag, &n, (const MKLTYPE*)_lhs, &lda, (MKLTYPE*)x, &incx); \
|
||||
\
|
||||
/* Add op(a_tr)rhs into res*/ \
|
||||
MKLPREFIX##axpy(&n, &alpha_,(const MKLTYPE*)x, &incx, (MKLTYPE*)_res, &incy); \
|
||||
/* Non-square case - doesn't fit to MKL ?TRMV. Fall to default triangular product*/ \
|
||||
if (size<(std::max)(rows,cols)) { \
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic> MatrixLhs; \
|
||||
if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \
|
||||
x = x_tmp.data(); \
|
||||
if (size<rows) { \
|
||||
y = _res + size*resIncr; \
|
||||
a = _lhs + size*lda; \
|
||||
m = rows-size; \
|
||||
n = size; \
|
||||
} \
|
||||
else { \
|
||||
x += size; \
|
||||
y = _res; \
|
||||
a = _lhs + size; \
|
||||
m = size; \
|
||||
n = cols-size; \
|
||||
} \
|
||||
MKLPREFIX##gemv(&trans, &n, &m, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)x, &incx, &beta_, (MKLTYPE*)y, &incy); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_TRMV_RM(double, double, d, d)
|
||||
EIGEN_MKL_TRMV_RM(dcomplex, MKL_Complex16, cd, z)
|
||||
EIGEN_MKL_TRMV_RM(float, float, f, s)
|
||||
EIGEN_MKL_TRMV_RM(scomplex, MKL_Complex8, cf, c)
|
||||
|
||||
} // end namespase internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_TRIANGULAR_MATRIX_VECTOR_MKL_H
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
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
|
||||
* Triangular matrix * matrix product functionality based on ?TRMM.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef EIGEN_TRIANGULAR_SOLVER_MATRIX_MKL_H
|
||||
#define EIGEN_TRIANGULAR_SOLVER_MATRIX_MKL_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// implements LeftSide op(triangular)^-1 * general
|
||||
#define EIGEN_MKL_TRSM_L(EIGTYPE, MKLTYPE, MKLPREFIX) \
|
||||
template <typename Index, int Mode, bool Conjugate, int TriStorageOrder> \
|
||||
struct triangular_solve_matrix<EIGTYPE,Index,OnTheLeft,Mode,Conjugate,TriStorageOrder,ColMajor> \
|
||||
{ \
|
||||
enum { \
|
||||
IsLower = (Mode&Lower) == Lower, \
|
||||
IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \
|
||||
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
|
||||
conjA = ((TriStorageOrder==ColMajor) && Conjugate) ? 1 : 0 \
|
||||
}; \
|
||||
static void run( \
|
||||
Index size, Index otherSize, \
|
||||
const EIGTYPE* _tri, Index triStride, \
|
||||
EIGTYPE* _other, Index otherStride, level3_blocking<EIGTYPE,EIGTYPE>& /*blocking*/) \
|
||||
{ \
|
||||
MKL_INT m = size, n = otherSize, lda, ldb; \
|
||||
char side = 'L', uplo, diag='N', transa; \
|
||||
/* Set alpha_ */ \
|
||||
MKLTYPE alpha; \
|
||||
EIGTYPE myone(1); \
|
||||
assign_scalar_eig2mkl(alpha, myone); \
|
||||
ldb = otherStride;\
|
||||
\
|
||||
const EIGTYPE *a; \
|
||||
/* Set trans */ \
|
||||
transa = (TriStorageOrder==RowMajor) ? ((Conjugate) ? 'C' : 'T') : 'N'; \
|
||||
/* Set uplo */ \
|
||||
uplo = IsLower ? 'L' : 'U'; \
|
||||
if (TriStorageOrder==RowMajor) uplo = (uplo == 'L') ? 'U' : 'L'; \
|
||||
/* Set a, lda */ \
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, TriStorageOrder> MatrixTri; \
|
||||
Map<const MatrixTri, 0, OuterStride<> > tri(_tri,size,size,OuterStride<>(triStride)); \
|
||||
MatrixTri a_tmp; \
|
||||
\
|
||||
if (conjA) { \
|
||||
a_tmp = tri.conjugate(); \
|
||||
a = a_tmp.data(); \
|
||||
lda = a_tmp.outerStride(); \
|
||||
} else { \
|
||||
a = _tri; \
|
||||
lda = triStride; \
|
||||
} \
|
||||
if (IsUnitDiag) diag='U'; \
|
||||
/* call ?trsm*/ \
|
||||
MKLPREFIX##trsm(&side, &uplo, &transa, &diag, &m, &n, &alpha, (const MKLTYPE*)a, &lda, (MKLTYPE*)_other, &ldb); \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_TRSM_L(double, double, d)
|
||||
EIGEN_MKL_TRSM_L(dcomplex, MKL_Complex16, z)
|
||||
EIGEN_MKL_TRSM_L(float, float, s)
|
||||
EIGEN_MKL_TRSM_L(scomplex, MKL_Complex8, c)
|
||||
|
||||
|
||||
// implements RightSide general * op(triangular)^-1
|
||||
#define EIGEN_MKL_TRSM_R(EIGTYPE, MKLTYPE, MKLPREFIX) \
|
||||
template <typename Index, int Mode, bool Conjugate, int TriStorageOrder> \
|
||||
struct triangular_solve_matrix<EIGTYPE,Index,OnTheRight,Mode,Conjugate,TriStorageOrder,ColMajor> \
|
||||
{ \
|
||||
enum { \
|
||||
IsLower = (Mode&Lower) == Lower, \
|
||||
IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \
|
||||
IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \
|
||||
conjA = ((TriStorageOrder==ColMajor) && Conjugate) ? 1 : 0 \
|
||||
}; \
|
||||
static void run( \
|
||||
Index size, Index otherSize, \
|
||||
const EIGTYPE* _tri, Index triStride, \
|
||||
EIGTYPE* _other, Index otherStride, level3_blocking<EIGTYPE,EIGTYPE>& /*blocking*/) \
|
||||
{ \
|
||||
MKL_INT m = otherSize, n = size, lda, ldb; \
|
||||
char side = 'R', uplo, diag='N', transa; \
|
||||
/* Set alpha_ */ \
|
||||
MKLTYPE alpha; \
|
||||
EIGTYPE myone(1); \
|
||||
assign_scalar_eig2mkl(alpha, myone); \
|
||||
ldb = otherStride;\
|
||||
\
|
||||
const EIGTYPE *a; \
|
||||
/* Set trans */ \
|
||||
transa = (TriStorageOrder==RowMajor) ? ((Conjugate) ? 'C' : 'T') : 'N'; \
|
||||
/* Set uplo */ \
|
||||
uplo = IsLower ? 'L' : 'U'; \
|
||||
if (TriStorageOrder==RowMajor) uplo = (uplo == 'L') ? 'U' : 'L'; \
|
||||
/* Set a, lda */ \
|
||||
typedef Matrix<EIGTYPE, Dynamic, Dynamic, TriStorageOrder> MatrixTri; \
|
||||
Map<const MatrixTri, 0, OuterStride<> > tri(_tri,size,size,OuterStride<>(triStride)); \
|
||||
MatrixTri a_tmp; \
|
||||
\
|
||||
if (conjA) { \
|
||||
a_tmp = tri.conjugate(); \
|
||||
a = a_tmp.data(); \
|
||||
lda = a_tmp.outerStride(); \
|
||||
} else { \
|
||||
a = _tri; \
|
||||
lda = triStride; \
|
||||
} \
|
||||
if (IsUnitDiag) diag='U'; \
|
||||
/* call ?trsm*/ \
|
||||
MKLPREFIX##trsm(&side, &uplo, &transa, &diag, &m, &n, &alpha, (const MKLTYPE*)a, &lda, (MKLTYPE*)_other, &ldb); \
|
||||
/*std::cout << "TRMS_L specialization!\n";*/ \
|
||||
} \
|
||||
};
|
||||
|
||||
EIGEN_MKL_TRSM_R(double, double, d)
|
||||
EIGEN_MKL_TRSM_R(dcomplex, MKL_Complex16, z)
|
||||
EIGEN_MKL_TRSM_R(float, float, s)
|
||||
EIGEN_MKL_TRSM_R(scomplex, MKL_Complex8, c)
|
||||
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_TRIANGULAR_SOLVER_MATRIX_MKL_H
|
||||
|
|
@ -222,11 +222,6 @@ class blas_data_mapper {
|
|||
return ploadt<Packet, AlignmentType>(&operator()(i, j));
|
||||
}
|
||||
|
||||
template <typename PacketT, int AlignmentT>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE PacketT load(Index i, Index j) const {
|
||||
return ploadt<PacketT, AlignmentT>(&operator()(i, j));
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE HalfPacket loadHalfPacket(Index i, Index j) const {
|
||||
return ploadt<HalfPacket, AlignmentType>(&operator()(i, j));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#ifdef _MSC_VER
|
||||
// 4100 - unreferenced formal parameter (occurred e.g. in aligned_allocator::destroy(pointer p))
|
||||
// 4101 - unreferenced local variable
|
||||
// 4127 - conditional expression is constant
|
||||
// 4181 - qualifier applied to reference type ignored
|
||||
// 4211 - nonstandard extension used : redefined extern to static
|
||||
// 4244 - 'argument' : conversion from 'type1' to 'type2', possible loss of data
|
||||
|
|
@ -19,7 +20,7 @@
|
|||
#ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS
|
||||
#pragma warning( push )
|
||||
#endif
|
||||
#pragma warning( disable : 4100 4101 4181 4211 4244 4273 4324 4503 4512 4522 4700 4714 4717 4800)
|
||||
#pragma warning( disable : 4100 4101 4127 4181 4211 4244 4273 4324 4503 4512 4522 4700 4714 4717 4800)
|
||||
|
||||
#elif defined __INTEL_COMPILER
|
||||
// 2196 - routine is both "inline" and "noinline" ("noinline" assumed)
|
||||
|
|
@ -41,9 +42,6 @@
|
|||
#pragma clang diagnostic push
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wconstant-logical-operand"
|
||||
#if __clang_major__ >= 3 && __clang_minor__ >= 5
|
||||
#pragma clang diagnostic ignored "-Wabsolute-value"
|
||||
#endif
|
||||
|
||||
#elif defined __GNUC__ && __GNUC__>=6
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#define EIGEN_WORLD_VERSION 3
|
||||
#define EIGEN_MAJOR_VERSION 3
|
||||
#define EIGEN_MINOR_VERSION 90
|
||||
#define EIGEN_MINOR_VERSION 4
|
||||
|
||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||
|
|
@ -80,8 +80,8 @@
|
|||
// 2015 14 1900
|
||||
// "15" 15 1900
|
||||
|
||||
/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC
|
||||
#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC)
|
||||
/// \internal EIGEN_COMP_MSVC_STRICT set to 1 if the compiler is really Microsoft Visual C++ and not ,e.g., ICC or clang-cl
|
||||
#if EIGEN_COMP_MSVC && !(EIGEN_COMP_ICC || EIGEN_COMP_LLVM || EIGEN_COMP_CLANG)
|
||||
#define EIGEN_COMP_MSVC_STRICT _MSC_VER
|
||||
#else
|
||||
#define EIGEN_COMP_MSVC_STRICT 0
|
||||
|
|
@ -356,7 +356,7 @@
|
|||
#define EIGEN_MAX_CPP_VER 99
|
||||
#endif
|
||||
|
||||
#if EIGEN_MAX_CPP_VER>=11 && defined(__cplusplus) && (__cplusplus >= 201103L)
|
||||
#if EIGEN_MAX_CPP_VER>=11 && (defined(__cplusplus) && (__cplusplus >= 201103L) || EIGEN_COMP_MSVC >= 1900)
|
||||
#define EIGEN_HAS_CXX11 1
|
||||
#else
|
||||
#define EIGEN_HAS_CXX11 0
|
||||
|
|
@ -380,8 +380,7 @@
|
|||
#if EIGEN_MAX_CPP_VER>=11 && \
|
||||
((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)) \
|
||||
|| (defined(__GNUC__) && defined(_GLIBCXX_USE_C99)) \
|
||||
|| (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) \
|
||||
|| (EIGEN_COMP_MSVC >= 1900) || defined(__SYCL_DEVICE_ONLY__))
|
||||
|| (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)))
|
||||
#define EIGEN_HAS_C99_MATH 1
|
||||
#else
|
||||
#define EIGEN_HAS_C99_MATH 0
|
||||
|
|
@ -400,12 +399,10 @@
|
|||
// Does the compiler support variadic templates?
|
||||
#ifndef EIGEN_HAS_VARIADIC_TEMPLATES
|
||||
#if EIGEN_MAX_CPP_VER>=11 && (__cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900) \
|
||||
&& (!defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000) )
|
||||
&& ( !defined(__NVCC__) || !EIGEN_ARCH_ARM_OR_ARM64 || (defined __CUDACC_VER__ && __CUDACC_VER__ >= 80000) )
|
||||
// ^^ Disable the use of variadic templates when compiling with versions of nvcc older than 8.0 on ARM devices:
|
||||
// this prevents nvcc from crashing when compiling Eigen on Tegra X1
|
||||
#define EIGEN_HAS_VARIADIC_TEMPLATES 1
|
||||
#elif EIGEN_MAX_CPP_VER>=11 && (__cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900) && defined(__SYCL_DEVICE_ONLY__)
|
||||
#define EIGEN_HAS_VARIADIC_TEMPLATES 1
|
||||
#else
|
||||
#define EIGEN_HAS_VARIADIC_TEMPLATES 0
|
||||
#endif
|
||||
|
|
@ -414,14 +411,13 @@
|
|||
// Does the compiler fully support const expressions? (as in c++14)
|
||||
#ifndef EIGEN_HAS_CONSTEXPR
|
||||
|
||||
#if defined(__CUDACC__)
|
||||
#ifdef __CUDACC__
|
||||
// Const expressions are supported provided that c++11 is enabled and we're using either clang or nvcc 7.5 or above
|
||||
#if EIGEN_MAX_CPP_VER>=14 && (__cplusplus > 199711L && defined(__CUDACC_VER__) && (EIGEN_COMP_CLANG || __CUDACC_VER__ >= 70500))
|
||||
#define EIGEN_HAS_CONSTEXPR 1
|
||||
#endif
|
||||
#elif EIGEN_MAX_CPP_VER>=14 && (__has_feature(cxx_relaxed_constexpr) || (defined(__cplusplus) && __cplusplus >= 201402L) || \
|
||||
(EIGEN_GNUC_AT_LEAST(4,8) && (__cplusplus > 199711L)) || \
|
||||
(EIGEN_COMP_CLANG >= 306 && (__cplusplus > 199711L)))
|
||||
(EIGEN_GNUC_AT_LEAST(4,8) && (__cplusplus > 199711L)))
|
||||
#define EIGEN_HAS_CONSTEXPR 1
|
||||
#endif
|
||||
|
||||
|
|
@ -628,14 +624,6 @@ namespace Eigen {
|
|||
#endif
|
||||
|
||||
|
||||
#if EIGEN_COMP_MSVC
|
||||
// NOTE MSVC often gives C4127 warnings with compiletime if statements. See bug 1362.
|
||||
// This workaround is ugly, but it does the job.
|
||||
# define EIGEN_CONST_CONDITIONAL(cond) (void)0, cond
|
||||
#else
|
||||
# define EIGEN_CONST_CONDITIONAL(cond) cond
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// Static and dynamic alignment control
|
||||
//
|
||||
|
|
@ -824,7 +812,7 @@ namespace Eigen {
|
|||
// just an empty macro !
|
||||
#define EIGEN_EMPTY
|
||||
|
||||
#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || __CUDACC_VER__) // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324)
|
||||
#if EIGEN_COMP_MSVC_STRICT && (EIGEN_COMP_MSVC < 1900 || defined(__CUDACC_VER__)) // for older MSVC versions, as well as 1900 && CUDA 8, using the base operator is sufficient (cf Bugs 1000, 1324)
|
||||
#define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
|
||||
using Base::operator =;
|
||||
#elif EIGEN_COMP_CLANG // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ EIGEN_DEVICE_FUNC inline void check_that_malloc_is_allowed()
|
|||
/** \internal Allocates \a size bytes. The returned pointer is guaranteed to have 16 or 32 bytes alignment depending on the requirements.
|
||||
* On allocation error, the returned pointer is null, and std::bad_alloc is thrown.
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC inline void* aligned_malloc(size_t size)
|
||||
EIGEN_DEVICE_FUNC inline void* aligned_malloc(std::size_t size)
|
||||
{
|
||||
check_that_malloc_is_allowed();
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ EIGEN_DEVICE_FUNC inline void aligned_free(void *ptr)
|
|||
* \brief Reallocates an aligned block of memory.
|
||||
* \throws std::bad_alloc on allocation failure
|
||||
*/
|
||||
inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
|
||||
inline void* aligned_realloc(void *ptr, std::size_t new_size, std::size_t old_size)
|
||||
{
|
||||
EIGEN_UNUSED_VARIABLE(old_size);
|
||||
|
||||
|
|
@ -209,12 +209,12 @@ inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
|
|||
/** \internal Allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
|
||||
* On allocation error, the returned pointer is null, and a std::bad_alloc is thrown.
|
||||
*/
|
||||
template<bool Align> EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(size_t size)
|
||||
template<bool Align> EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc(std::size_t size)
|
||||
{
|
||||
return aligned_malloc(size);
|
||||
}
|
||||
|
||||
template<> EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc<false>(size_t size)
|
||||
template<> EIGEN_DEVICE_FUNC inline void* conditional_aligned_malloc<false>(std::size_t size)
|
||||
{
|
||||
check_that_malloc_is_allowed();
|
||||
|
||||
|
|
@ -235,12 +235,12 @@ template<> EIGEN_DEVICE_FUNC inline void conditional_aligned_free<false>(void *p
|
|||
std::free(ptr);
|
||||
}
|
||||
|
||||
template<bool Align> inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
|
||||
template<bool Align> inline void* conditional_aligned_realloc(void* ptr, std::size_t new_size, std::size_t old_size)
|
||||
{
|
||||
return aligned_realloc(ptr, new_size, old_size);
|
||||
}
|
||||
|
||||
template<> inline void* conditional_aligned_realloc<false>(void* ptr, size_t new_size, size_t)
|
||||
template<> inline void* conditional_aligned_realloc<false>(void* ptr, std::size_t new_size, std::size_t)
|
||||
{
|
||||
return std::realloc(ptr, new_size);
|
||||
}
|
||||
|
|
@ -252,7 +252,7 @@ template<> inline void* conditional_aligned_realloc<false>(void* ptr, size_t new
|
|||
/** \internal Destructs the elements of an array.
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T *ptr, size_t size)
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T *ptr, std::size_t size)
|
||||
{
|
||||
// always destruct an array starting from the end.
|
||||
if(ptr)
|
||||
|
|
@ -262,9 +262,9 @@ template<typename T> EIGEN_DEVICE_FUNC inline void destruct_elements_of_array(T
|
|||
/** \internal Constructs the elements of an array.
|
||||
* The \a size parameter tells on how many objects to call the constructor of T.
|
||||
*/
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *ptr, size_t size)
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *ptr, std::size_t size)
|
||||
{
|
||||
size_t i;
|
||||
std::size_t i;
|
||||
EIGEN_TRY
|
||||
{
|
||||
for (i = 0; i < size; ++i) ::new (ptr + i) T;
|
||||
|
|
@ -283,9 +283,9 @@ template<typename T> EIGEN_DEVICE_FUNC inline T* construct_elements_of_array(T *
|
|||
*****************************************************************************/
|
||||
|
||||
template<typename T>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(size_t size)
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(std::size_t size)
|
||||
{
|
||||
if(size > size_t(-1) / sizeof(T))
|
||||
if(size > std::size_t(-1) / sizeof(T))
|
||||
throw_std_bad_alloc();
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void check_size_for_overflow(size_t size)
|
|||
* On allocation error, the returned pointer is undefined, but a std::bad_alloc is thrown.
|
||||
* The default constructor of T is called.
|
||||
*/
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* aligned_new(size_t size)
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline T* aligned_new(std::size_t size)
|
||||
{
|
||||
check_size_for_overflow<T>(size);
|
||||
T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size));
|
||||
|
|
@ -309,7 +309,7 @@ template<typename T> EIGEN_DEVICE_FUNC inline T* aligned_new(size_t size)
|
|||
return result;
|
||||
}
|
||||
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(size_t size)
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_new(std::size_t size)
|
||||
{
|
||||
check_size_for_overflow<T>(size);
|
||||
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
|
||||
|
|
@ -328,7 +328,7 @@ template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned
|
|||
/** \internal Deletes objects constructed with aligned_new
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, size_t size)
|
||||
template<typename T> EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, std::size_t size)
|
||||
{
|
||||
destruct_elements_of_array<T>(ptr, size);
|
||||
aligned_free(ptr);
|
||||
|
|
@ -337,13 +337,13 @@ template<typename T> EIGEN_DEVICE_FUNC inline void aligned_delete(T *ptr, size_t
|
|||
/** \internal Deletes objects constructed with conditional_aligned_new
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline void conditional_aligned_delete(T *ptr, size_t size)
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline void conditional_aligned_delete(T *ptr, std::size_t size)
|
||||
{
|
||||
destruct_elements_of_array<T>(ptr, size);
|
||||
conditional_aligned_free<Align>(ptr);
|
||||
}
|
||||
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_realloc_new(T* pts, size_t new_size, size_t old_size)
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_realloc_new(T* pts, std::size_t new_size, std::size_t old_size)
|
||||
{
|
||||
check_size_for_overflow<T>(new_size);
|
||||
check_size_for_overflow<T>(old_size);
|
||||
|
|
@ -366,7 +366,7 @@ template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned
|
|||
}
|
||||
|
||||
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_new_auto(size_t size)
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned_new_auto(std::size_t size)
|
||||
{
|
||||
if(size==0)
|
||||
return 0; // short-cut. Also fixes Bug 884
|
||||
|
|
@ -387,7 +387,7 @@ template<typename T, bool Align> EIGEN_DEVICE_FUNC inline T* conditional_aligned
|
|||
return result;
|
||||
}
|
||||
|
||||
template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(T* pts, size_t new_size, size_t old_size)
|
||||
template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(T* pts, std::size_t new_size, std::size_t old_size)
|
||||
{
|
||||
check_size_for_overflow<T>(new_size);
|
||||
check_size_for_overflow<T>(old_size);
|
||||
|
|
@ -409,7 +409,7 @@ template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(
|
|||
return result;
|
||||
}
|
||||
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline void conditional_aligned_delete_auto(T *ptr, size_t size)
|
||||
template<typename T, bool Align> EIGEN_DEVICE_FUNC inline void conditional_aligned_delete_auto(T *ptr, std::size_t size)
|
||||
{
|
||||
if(NumTraits<T>::RequireInitialization)
|
||||
destruct_elements_of_array<T>(ptr, size);
|
||||
|
|
@ -561,7 +561,7 @@ template<typename T> class aligned_stack_memory_handler : noncopyable
|
|||
* In this case, the buffer elements will also be destructed when this handler will be destructed.
|
||||
* Finally, if \a dealloc is true, then the pointer \a ptr is freed.
|
||||
**/
|
||||
aligned_stack_memory_handler(T* ptr, size_t size, bool dealloc)
|
||||
aligned_stack_memory_handler(T* ptr, std::size_t size, bool dealloc)
|
||||
: m_ptr(ptr), m_size(size), m_deallocate(dealloc)
|
||||
{
|
||||
if(NumTraits<T>::RequireInitialization && m_ptr)
|
||||
|
|
@ -576,7 +576,7 @@ template<typename T> class aligned_stack_memory_handler : noncopyable
|
|||
}
|
||||
protected:
|
||||
T* m_ptr;
|
||||
size_t m_size;
|
||||
std::size_t m_size;
|
||||
bool m_deallocate;
|
||||
};
|
||||
|
||||
|
|
@ -655,15 +655,15 @@ template<typename T> void swap(scoped_array<T> &a,scoped_array<T> &b)
|
|||
|
||||
#if EIGEN_MAX_ALIGN_BYTES!=0
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
||||
void* operator new(size_t size, const std::nothrow_t&) EIGEN_NO_THROW { \
|
||||
void* operator new(std::size_t size, const std::nothrow_t&) EIGEN_NO_THROW { \
|
||||
EIGEN_TRY { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \
|
||||
EIGEN_CATCH (...) { return 0; } \
|
||||
}
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
|
||||
void *operator new(size_t size) { \
|
||||
void *operator new(std::size_t size) { \
|
||||
return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
} \
|
||||
void *operator new[](size_t size) { \
|
||||
void *operator new[](std::size_t size) { \
|
||||
return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
} \
|
||||
void operator delete(void * ptr) EIGEN_NO_THROW { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
|
|
@ -673,8 +673,8 @@ template<typename T> void swap(scoped_array<T> &a,scoped_array<T> &b)
|
|||
/* in-place new and delete. since (at least afaik) there is no actual */ \
|
||||
/* memory allocated we can safely let the default implementation handle */ \
|
||||
/* this particular case. */ \
|
||||
static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
|
||||
static void *operator new[](size_t size, void* ptr) { return ::operator new[](size,ptr); } \
|
||||
static void *operator new(std::size_t size, void *ptr) { return ::operator new(size,ptr); } \
|
||||
static void *operator new[](std::size_t size, void* ptr) { return ::operator new[](size,ptr); } \
|
||||
void operator delete(void * memory, void *ptr) EIGEN_NO_THROW { return ::operator delete(memory,ptr); } \
|
||||
void operator delete[](void * memory, void *ptr) EIGEN_NO_THROW { return ::operator delete[](memory,ptr); } \
|
||||
/* nothrow-new (returns zero instead of std::bad_alloc) */ \
|
||||
|
|
@ -713,7 +713,7 @@ template<class T>
|
|||
class aligned_allocator : public std::allocator<T>
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
|
|
|||
|
|
@ -532,6 +532,15 @@ template <typename B, typename Functor> struct cwise_promote_s
|
|||
template <typename Functor> struct cwise_promote_storage_type<Sparse,Dense,Functor> { typedef Sparse ret; };
|
||||
template <typename Functor> struct cwise_promote_storage_type<Dense,Sparse,Functor> { typedef Sparse ret; };
|
||||
|
||||
template <typename LhsKind, typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order {
|
||||
enum { value = LhsOrder };
|
||||
};
|
||||
|
||||
template <typename LhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<LhsKind,Sparse,LhsOrder,RhsOrder> { enum { value = RhsOrder }; };
|
||||
template <typename RhsKind, int LhsOrder, int RhsOrder> struct cwise_promote_storage_order<Sparse,RhsKind,LhsOrder,RhsOrder> { enum { value = LhsOrder }; };
|
||||
template <int Order> struct cwise_promote_storage_order<Sparse,Sparse,Order,Order> { enum { value = Order }; };
|
||||
|
||||
|
||||
/** \internal Specify the "storage kind" of multiplying an expression of kind A with kind B.
|
||||
* The template parameter ProductTag permits to specialize the resulting storage kind wrt to
|
||||
* some compile-time properties of the product: GemmProduct, GemvProduct, OuterProduct, InnerProduct.
|
||||
|
|
@ -629,7 +638,7 @@ struct plain_constant_type
|
|||
template<typename ExpressionType>
|
||||
struct is_lvalue
|
||||
{
|
||||
enum { value = !bool(is_const<ExpressionType>::value) &&
|
||||
enum { value = (!bool(is_const<ExpressionType>::value)) &&
|
||||
bool(traits<ExpressionType>::Flags & LvalueBit) };
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,126 +0,0 @@
|
|||
// 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_BLOCK2_H
|
||||
#define EIGEN_BLOCK2_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \returns a dynamic-size expression of a corner of *this.
|
||||
*
|
||||
* \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight,
|
||||
* \a Eigen::BottomLeft, \a Eigen::BottomRight.
|
||||
* \param cRows the number of rows in the corner
|
||||
* \param cCols the number of columns in the corner
|
||||
*
|
||||
* Example: \include MatrixBase_corner_enum_int_int.cpp
|
||||
* Output: \verbinclude MatrixBase_corner_enum_int_int.out
|
||||
*
|
||||
* \note Even though the returned expression has dynamic size, in the case
|
||||
* when it is applied to a fixed-size matrix, it inherits a fixed maximal size,
|
||||
* which means that evaluating it does not cause a dynamic memory allocation.
|
||||
*
|
||||
* \sa class Block, block(Index,Index,Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Block<Derived> DenseBase<Derived>
|
||||
::corner(CornerType type, Index cRows, Index cCols)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
eigen_assert(false && "Bad corner type.");
|
||||
case TopLeft:
|
||||
return Block<Derived>(derived(), 0, 0, cRows, cCols);
|
||||
case TopRight:
|
||||
return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols);
|
||||
case BottomLeft:
|
||||
return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols);
|
||||
case BottomRight:
|
||||
return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
|
||||
}
|
||||
}
|
||||
|
||||
/** This is the const version of corner(CornerType, Index, Index).*/
|
||||
template<typename Derived>
|
||||
inline const Block<Derived>
|
||||
DenseBase<Derived>::corner(CornerType type, Index cRows, Index cCols) const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
eigen_assert(false && "Bad corner type.");
|
||||
case TopLeft:
|
||||
return Block<Derived>(derived(), 0, 0, cRows, cCols);
|
||||
case TopRight:
|
||||
return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols);
|
||||
case BottomLeft:
|
||||
return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols);
|
||||
case BottomRight:
|
||||
return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols);
|
||||
}
|
||||
}
|
||||
|
||||
/** \returns a fixed-size expression of a corner of *this.
|
||||
*
|
||||
* \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight,
|
||||
* \a Eigen::BottomLeft, \a Eigen::BottomRight.
|
||||
*
|
||||
* The template parameters CRows and CCols arethe number of rows and columns in the corner.
|
||||
*
|
||||
* Example: \include MatrixBase_template_int_int_corner_enum.cpp
|
||||
* Output: \verbinclude MatrixBase_template_int_int_corner_enum.out
|
||||
*
|
||||
* \sa class Block, block(Index,Index,Index,Index)
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<int CRows, int CCols>
|
||||
inline Block<Derived, CRows, CCols>
|
||||
DenseBase<Derived>::corner(CornerType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
eigen_assert(false && "Bad corner type.");
|
||||
case TopLeft:
|
||||
return Block<Derived, CRows, CCols>(derived(), 0, 0);
|
||||
case TopRight:
|
||||
return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
|
||||
case BottomLeft:
|
||||
return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
|
||||
case BottomRight:
|
||||
return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
|
||||
}
|
||||
}
|
||||
|
||||
/** This is the const version of corner<int, int>(CornerType).*/
|
||||
template<typename Derived>
|
||||
template<int CRows, int CCols>
|
||||
inline const Block<Derived, CRows, CCols>
|
||||
DenseBase<Derived>::corner(CornerType type) const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
eigen_assert(false && "Bad corner type.");
|
||||
case TopLeft:
|
||||
return Block<Derived, CRows, CCols>(derived(), 0, 0);
|
||||
case TopRight:
|
||||
return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols);
|
||||
case BottomLeft:
|
||||
return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0);
|
||||
case BottomRight:
|
||||
return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_BLOCK2_H
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
// 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) 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_H
|
||||
#define EIGEN_CWISE_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise binary operation */
|
||||
#define EIGEN_CWISE_BINOP_RETURN_TYPE(OP) \
|
||||
CwiseBinaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType, OtherDerived>
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise unary operation */
|
||||
#define EIGEN_CWISE_UNOP_RETURN_TYPE(OP) \
|
||||
CwiseUnaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType>
|
||||
|
||||
/** \internal
|
||||
* convenient macro to defined the return type of a cwise comparison to a scalar */
|
||||
#define EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(OP) \
|
||||
CwiseBinaryOp<OP<typename internal::traits<ExpressionType>::Scalar>, ExpressionType, \
|
||||
typename ExpressionType::ConstantReturnType >
|
||||
|
||||
/** \class Cwise
|
||||
*
|
||||
* \brief Pseudo expression providing additional coefficient-wise operations
|
||||
*
|
||||
* \param ExpressionType the type of the object on which to do coefficient-wise operations
|
||||
*
|
||||
* This class represents an expression with additional coefficient-wise features.
|
||||
* It is the return type of MatrixBase::cwise()
|
||||
* and most of the time this is the only way it is used.
|
||||
*
|
||||
* Example: \include MatrixBase_cwise_const.cpp
|
||||
* Output: \verbinclude MatrixBase_cwise_const.out
|
||||
*
|
||||
* 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_CWISE_PLUGIN.
|
||||
*
|
||||
* \sa MatrixBase::cwise() const, MatrixBase::cwise()
|
||||
*/
|
||||
template<typename ExpressionType> class Cwise
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename internal::traits<ExpressionType>::Scalar Scalar;
|
||||
typedef typename internal::conditional<internal::must_nest_by_value<ExpressionType>::ret,
|
||||
ExpressionType, const ExpressionType&>::type ExpressionTypeNested;
|
||||
typedef CwiseUnaryOp<internal::scalar_add_op<Scalar>, ExpressionType> ScalarAddReturnType;
|
||||
|
||||
inline Cwise(const ExpressionType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
/** \internal */
|
||||
inline const ExpressionType& _expression() const { return m_matrix; }
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)
|
||||
operator*(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
|
||||
operator/(const MatrixBase<OtherDerived> &other) const;
|
||||
|
||||
/** \deprecated ArrayBase::min() */
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)
|
||||
(min)(const MatrixBase<OtherDerived> &other) const
|
||||
{ return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_min_op)(_expression(), other.derived()); }
|
||||
|
||||
/** \deprecated ArrayBase::max() */
|
||||
template<typename OtherDerived>
|
||||
const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)
|
||||
(max)(const MatrixBase<OtherDerived> &other) const
|
||||
{ return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_max_op)(_expression(), other.derived()); }
|
||||
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs_op) abs() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs2_op) abs2() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_square_op) square() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cube_op) cube() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_inverse_op) inverse() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sqrt_op) sqrt() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_exp_op) exp() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_log_op) log() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cos_op) cos() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sin_op) sin() const;
|
||||
const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op) pow(const Scalar& exponent) const;
|
||||
|
||||
const ScalarAddReturnType
|
||||
operator+(const Scalar& scalar) const;
|
||||
|
||||
/** \relates Cwise */
|
||||
friend const ScalarAddReturnType
|
||||
operator+(const Scalar& scalar, const Cwise& mat)
|
||||
{ return mat + scalar; }
|
||||
|
||||
ExpressionType& operator+=(const Scalar& scalar);
|
||||
|
||||
const ScalarAddReturnType
|
||||
operator-(const Scalar& scalar) const;
|
||||
|
||||
ExpressionType& operator-=(const Scalar& scalar);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& operator*=(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& operator/=(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
|
||||
operator<(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
|
||||
operator<=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
|
||||
operator>(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
|
||||
operator>=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
|
||||
operator==(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
template<typename OtherDerived> const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
|
||||
operator!=(const MatrixBase<OtherDerived>& other) const;
|
||||
|
||||
// comparisons to a scalar value
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
|
||||
operator<(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
|
||||
operator<=(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
|
||||
operator>(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
|
||||
operator>=(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
|
||||
operator==(Scalar s) const;
|
||||
|
||||
const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
|
||||
operator!=(Scalar s) const;
|
||||
|
||||
// allow to extend Cwise outside Eigen
|
||||
#ifdef EIGEN_CWISE_PLUGIN
|
||||
#include EIGEN_CWISE_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
};
|
||||
|
||||
|
||||
/** \returns a Cwise wrapper of *this providing additional coefficient-wise operations
|
||||
*
|
||||
* Example: \include MatrixBase_cwise_const.cpp
|
||||
* Output: \verbinclude MatrixBase_cwise_const.out
|
||||
*
|
||||
* \sa class Cwise, cwise()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const Cwise<Derived> MatrixBase<Derived>::cwise() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \returns a Cwise wrapper of *this providing additional coefficient-wise operations
|
||||
*
|
||||
* Example: \include MatrixBase_cwise.cpp
|
||||
* Output: \verbinclude MatrixBase_cwise.out
|
||||
*
|
||||
* \sa class Cwise, cwise() const
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Cwise<Derived> MatrixBase<Derived>::cwise()
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_CWISE_H
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
// 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_ARRAY_CWISE_OPERATORS_H
|
||||
#define EIGEN_ARRAY_CWISE_OPERATORS_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/***************************************************************************
|
||||
* The following functions were defined in Core
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/** \deprecated ArrayBase::abs() */
|
||||
template<typename ExpressionType>
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs_op)
|
||||
Cwise<ExpressionType>::abs() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::abs2() */
|
||||
template<typename ExpressionType>
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_abs2_op)
|
||||
Cwise<ExpressionType>::abs2() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::exp() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_exp_op)
|
||||
Cwise<ExpressionType>::exp() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::log() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_log_op)
|
||||
Cwise<ExpressionType>::log() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator*() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)
|
||||
Cwise<ExpressionType>::operator*(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_PRODUCT_RETURN_TYPE(ExpressionType,OtherDerived)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator/() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE const EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)
|
||||
Cwise<ExpressionType>::operator/(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator*=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator*=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this * other;
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator/=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator/=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this / other;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* The following functions were defined in Array
|
||||
***************************************************************************/
|
||||
|
||||
// -- unary operators --
|
||||
|
||||
/** \deprecated ArrayBase::sqrt() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sqrt_op)
|
||||
Cwise<ExpressionType>::sqrt() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::cos() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cos_op)
|
||||
Cwise<ExpressionType>::cos() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
|
||||
/** \deprecated ArrayBase::sin() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_sin_op)
|
||||
Cwise<ExpressionType>::sin() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
|
||||
/** \deprecated ArrayBase::log() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op)
|
||||
Cwise<ExpressionType>::pow(const Scalar& exponent) const
|
||||
{
|
||||
return EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_pow_op)(_expression(), internal::scalar_pow_op<Scalar>(exponent));
|
||||
}
|
||||
|
||||
|
||||
/** \deprecated ArrayBase::inverse() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_inverse_op)
|
||||
Cwise<ExpressionType>::inverse() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::square() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_square_op)
|
||||
Cwise<ExpressionType>::square() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::cube() */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_UNOP_RETURN_TYPE(internal::scalar_cube_op)
|
||||
Cwise<ExpressionType>::cube() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
|
||||
// -- binary operators --
|
||||
|
||||
/** \deprecated ArrayBase::operator<() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)
|
||||
Cwise<ExpressionType>::operator<(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::less)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::<=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)
|
||||
Cwise<ExpressionType>::operator<=(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::less_equal)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator>() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)
|
||||
Cwise<ExpressionType>::operator>(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator>=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)
|
||||
Cwise<ExpressionType>::operator>=(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::greater_equal)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator==() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)
|
||||
Cwise<ExpressionType>::operator==(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::equal_to)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator!=() */
|
||||
template<typename ExpressionType>
|
||||
template<typename OtherDerived>
|
||||
inline const EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)
|
||||
Cwise<ExpressionType>::operator!=(const MatrixBase<OtherDerived> &other) const
|
||||
{
|
||||
return EIGEN_CWISE_BINOP_RETURN_TYPE(std::not_equal_to)(_expression(), other.derived());
|
||||
}
|
||||
|
||||
// comparisons to scalar value
|
||||
|
||||
/** \deprecated ArrayBase::operator<(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)
|
||||
Cwise<ExpressionType>::operator<(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator<=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)
|
||||
Cwise<ExpressionType>::operator<=(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::less_equal)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator>(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)
|
||||
Cwise<ExpressionType>::operator>(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator>=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)
|
||||
Cwise<ExpressionType>::operator>=(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::greater_equal)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator==(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)
|
||||
Cwise<ExpressionType>::operator==(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::equal_to)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator!=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)
|
||||
Cwise<ExpressionType>::operator!=(Scalar s) const
|
||||
{
|
||||
return EIGEN_CWISE_COMP_TO_SCALAR_RETURN_TYPE(std::not_equal_to)(_expression(),
|
||||
typename ExpressionType::ConstantReturnType(_expression().rows(), _expression().cols(), s));
|
||||
}
|
||||
|
||||
// scalar addition
|
||||
|
||||
/** \deprecated ArrayBase::operator+(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const typename Cwise<ExpressionType>::ScalarAddReturnType
|
||||
Cwise<ExpressionType>::operator+(const Scalar& scalar) const
|
||||
{
|
||||
return typename Cwise<ExpressionType>::ScalarAddReturnType(m_matrix, internal::scalar_add_op<Scalar>(scalar));
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator+=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator+=(const Scalar& scalar)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this + scalar;
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator-(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline const typename Cwise<ExpressionType>::ScalarAddReturnType
|
||||
Cwise<ExpressionType>::operator-(const Scalar& scalar) const
|
||||
{
|
||||
return *this + (-scalar);
|
||||
}
|
||||
|
||||
/** \deprecated ArrayBase::operator-=(Scalar) */
|
||||
template<typename ExpressionType>
|
||||
inline ExpressionType& Cwise<ExpressionType>::operator-=(const Scalar& scalar)
|
||||
{
|
||||
return m_matrix.const_cast_derived() = *this - scalar;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ARRAY_CWISE_OPERATORS_H
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
* \nonstableyet
|
||||
*
|
||||
* \class AlignedBox
|
||||
*
|
||||
* \brief An axis aligned box
|
||||
*
|
||||
* \param _Scalar the type of the scalar coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
*
|
||||
* This class represents an axis aligned box as a pair of the minimal and maximal corners.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class AlignedBox
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
|
||||
/** Default constructor initializing a null box. */
|
||||
inline AlignedBox()
|
||||
{ if (AmbientDimAtCompileTime!=Dynamic) setNull(); }
|
||||
|
||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
||||
inline explicit AlignedBox(int _dim) : m_min(_dim), m_max(_dim)
|
||||
{ setNull(); }
|
||||
|
||||
/** Constructs a box with extremities \a _min and \a _max. */
|
||||
inline AlignedBox(const VectorType& _min, const VectorType& _max) : m_min(_min), m_max(_max) {}
|
||||
|
||||
/** Constructs a box containing a single point \a p. */
|
||||
inline explicit AlignedBox(const VectorType& p) : m_min(p), m_max(p) {}
|
||||
|
||||
~AlignedBox() {}
|
||||
|
||||
/** \returns the dimension in which the box holds */
|
||||
inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : AmbientDimAtCompileTime; }
|
||||
|
||||
/** \returns true if the box is null, i.e, empty. */
|
||||
inline bool isNull() const { return (m_min.cwise() > m_max).any(); }
|
||||
|
||||
/** Makes \c *this a null/empty box. */
|
||||
inline void setNull()
|
||||
{
|
||||
m_min.setConstant( (std::numeric_limits<Scalar>::max)());
|
||||
m_max.setConstant(-(std::numeric_limits<Scalar>::max)());
|
||||
}
|
||||
|
||||
/** \returns the minimal corner */
|
||||
inline const VectorType& (min)() const { return m_min; }
|
||||
/** \returns a non const reference to the minimal corner */
|
||||
inline VectorType& (min)() { return m_min; }
|
||||
/** \returns the maximal corner */
|
||||
inline const VectorType& (max)() const { return m_max; }
|
||||
/** \returns a non const reference to the maximal corner */
|
||||
inline VectorType& (max)() { return m_max; }
|
||||
|
||||
/** \returns true if the point \a p is inside the box \c *this. */
|
||||
inline bool contains(const VectorType& p) const
|
||||
{ return (m_min.cwise()<=p).all() && (p.cwise()<=m_max).all(); }
|
||||
|
||||
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
||||
inline bool contains(const AlignedBox& b) const
|
||||
{ return (m_min.cwise()<=(b.min)()).all() && ((b.max)().cwise()<=m_max).all(); }
|
||||
|
||||
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
|
||||
inline AlignedBox& extend(const VectorType& p)
|
||||
{ m_min = (m_min.cwise().min)(p); m_max = (m_max.cwise().max)(p); return *this; }
|
||||
|
||||
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
|
||||
inline AlignedBox& extend(const AlignedBox& b)
|
||||
{ m_min = (m_min.cwise().min)(b.m_min); m_max = (m_max.cwise().max)(b.m_max); return *this; }
|
||||
|
||||
/** Clamps \c *this by the box \a b and returns a reference to \c *this. */
|
||||
inline AlignedBox& clamp(const AlignedBox& b)
|
||||
{ m_min = (m_min.cwise().max)(b.m_min); m_max = (m_max.cwise().min)(b.m_max); return *this; }
|
||||
|
||||
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
|
||||
inline AlignedBox& translate(const VectorType& t)
|
||||
{ m_min += t; m_max += t; return *this; }
|
||||
|
||||
/** \returns the squared distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa exteriorDistance()
|
||||
*/
|
||||
inline Scalar squaredExteriorDistance(const VectorType& p) const;
|
||||
|
||||
/** \returns the distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa squaredExteriorDistance()
|
||||
*/
|
||||
inline Scalar exteriorDistance(const VectorType& p) const
|
||||
{ return ei_sqrt(squaredExteriorDistance(p)); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{
|
||||
m_min = (other.min)().template cast<Scalar>();
|
||||
m_max = (other.max)().template cast<Scalar>();
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const AlignedBox& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_min, m_max;
|
||||
};
|
||||
|
||||
template<typename Scalar,int AmbiantDim>
|
||||
inline Scalar AlignedBox<Scalar,AmbiantDim>::squaredExteriorDistance(const VectorType& p) const
|
||||
{
|
||||
Scalar dist2(0);
|
||||
Scalar aux;
|
||||
for (int k=0; k<dim(); ++k)
|
||||
{
|
||||
if ((aux = (p[k]-m_min[k]))<Scalar(0))
|
||||
dist2 += aux*aux;
|
||||
else if ( (aux = (m_max[k]-p[k]))<Scalar(0))
|
||||
dist2 += aux*aux;
|
||||
}
|
||||
return dist2;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
#ifndef EIGEN2_GEOMETRY_MODULE_H
|
||||
#define EIGEN2_GEOMETRY_MODULE_H
|
||||
|
||||
#include <limits>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
|
||||
#include "RotationBase.h"
|
||||
#include "Rotation2D.h"
|
||||
#include "Quaternion.h"
|
||||
#include "AngleAxis.h"
|
||||
#include "Transform.h"
|
||||
#include "Translation.h"
|
||||
#include "Scaling.h"
|
||||
#include "AlignedBox.h"
|
||||
#include "Hyperplane.h"
|
||||
#include "ParametrizedLine.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define RotationBase eigen2_RotationBase
|
||||
#define Rotation2D eigen2_Rotation2D
|
||||
#define Rotation2Df eigen2_Rotation2Df
|
||||
#define Rotation2Dd eigen2_Rotation2Dd
|
||||
|
||||
#define Quaternion eigen2_Quaternion
|
||||
#define Quaternionf eigen2_Quaternionf
|
||||
#define Quaterniond eigen2_Quaterniond
|
||||
|
||||
#define AngleAxis eigen2_AngleAxis
|
||||
#define AngleAxisf eigen2_AngleAxisf
|
||||
#define AngleAxisd eigen2_AngleAxisd
|
||||
|
||||
#define Transform eigen2_Transform
|
||||
#define Transform2f eigen2_Transform2f
|
||||
#define Transform2d eigen2_Transform2d
|
||||
#define Transform3f eigen2_Transform3f
|
||||
#define Transform3d eigen2_Transform3d
|
||||
|
||||
#define Translation eigen2_Translation
|
||||
#define Translation2f eigen2_Translation2f
|
||||
#define Translation2d eigen2_Translation2d
|
||||
#define Translation3f eigen2_Translation3f
|
||||
#define Translation3d eigen2_Translation3d
|
||||
|
||||
#define Scaling eigen2_Scaling
|
||||
#define Scaling2f eigen2_Scaling2f
|
||||
#define Scaling2d eigen2_Scaling2d
|
||||
#define Scaling3f eigen2_Scaling3f
|
||||
#define Scaling3d eigen2_Scaling3d
|
||||
|
||||
#define AlignedBox eigen2_AlignedBox
|
||||
|
||||
#define Hyperplane eigen2_Hyperplane
|
||||
#define ParametrizedLine eigen2_ParametrizedLine
|
||||
|
||||
#define ei_toRotationMatrix eigen2_ei_toRotationMatrix
|
||||
#define ei_quaternion_assign_impl eigen2_ei_quaternion_assign_impl
|
||||
#define ei_transform_product_impl eigen2_ei_transform_product_impl
|
||||
|
||||
#include "RotationBase.h"
|
||||
#include "Rotation2D.h"
|
||||
#include "Quaternion.h"
|
||||
#include "AngleAxis.h"
|
||||
#include "Transform.h"
|
||||
#include "Translation.h"
|
||||
#include "Scaling.h"
|
||||
#include "AlignedBox.h"
|
||||
#include "Hyperplane.h"
|
||||
#include "ParametrizedLine.h"
|
||||
|
||||
#undef ei_toRotationMatrix
|
||||
#undef ei_quaternion_assign_impl
|
||||
#undef ei_transform_product_impl
|
||||
|
||||
#undef RotationBase
|
||||
#undef Rotation2D
|
||||
#undef Rotation2Df
|
||||
#undef Rotation2Dd
|
||||
|
||||
#undef Quaternion
|
||||
#undef Quaternionf
|
||||
#undef Quaterniond
|
||||
|
||||
#undef AngleAxis
|
||||
#undef AngleAxisf
|
||||
#undef AngleAxisd
|
||||
|
||||
#undef Transform
|
||||
#undef Transform2f
|
||||
#undef Transform2d
|
||||
#undef Transform3f
|
||||
#undef Transform3d
|
||||
|
||||
#undef Translation
|
||||
#undef Translation2f
|
||||
#undef Translation2d
|
||||
#undef Translation3f
|
||||
#undef Translation3d
|
||||
|
||||
#undef Scaling
|
||||
#undef Scaling2f
|
||||
#undef Scaling2d
|
||||
#undef Scaling3f
|
||||
#undef Scaling3d
|
||||
|
||||
#undef AlignedBox
|
||||
|
||||
#undef Hyperplane
|
||||
#undef ParametrizedLine
|
||||
|
||||
#endif // EIGEN2_GEOMETRY_MODULE_H
|
||||
|
|
@ -1,214 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class AngleAxis
|
||||
*
|
||||
* \brief Represents a 3D rotation as a rotation angle around an arbitrary 3D axis
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
*
|
||||
* The following two typedefs are provided for convenience:
|
||||
* \li \c AngleAxisf for \c float
|
||||
* \li \c AngleAxisd for \c double
|
||||
*
|
||||
* \addexample AngleAxisForEuler \label How to define a rotation from Euler-angles
|
||||
*
|
||||
* Combined with MatrixBase::Unit{X,Y,Z}, AngleAxis can be used to easily
|
||||
* mimic Euler-angles. Here is an example:
|
||||
* \include AngleAxis_mimic_euler.cpp
|
||||
* Output: \verbinclude AngleAxis_mimic_euler.out
|
||||
*
|
||||
* \note This class is not aimed to be used to store a rotation transformation,
|
||||
* but rather to make easier the creation of other rotation (Quaternion, rotation Matrix)
|
||||
* and transformation objects.
|
||||
*
|
||||
* \sa class Quaternion, class Transform, MatrixBase::UnitX()
|
||||
*/
|
||||
|
||||
template<typename _Scalar> struct ei_traits<AngleAxis<_Scalar> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
};
|
||||
|
||||
template<typename _Scalar>
|
||||
class AngleAxis : public RotationBase<AngleAxis<_Scalar>,3>
|
||||
{
|
||||
typedef RotationBase<AngleAxis<_Scalar>,3> Base;
|
||||
|
||||
public:
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
enum { Dim = 3 };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef Quaternion<Scalar> QuaternionType;
|
||||
|
||||
protected:
|
||||
|
||||
Vector3 m_axis;
|
||||
Scalar m_angle;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
AngleAxis() {}
|
||||
/** Constructs and initialize the angle-axis rotation from an \a angle in radian
|
||||
* and an \a axis which must be normalized. */
|
||||
template<typename Derived>
|
||||
inline AngleAxis(Scalar angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {}
|
||||
/** Constructs and initialize the angle-axis rotation from a quaternion \a q. */
|
||||
inline AngleAxis(const QuaternionType& q) { *this = q; }
|
||||
/** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */
|
||||
template<typename Derived>
|
||||
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
||||
|
||||
Scalar angle() const { return m_angle; }
|
||||
Scalar& angle() { return m_angle; }
|
||||
|
||||
const Vector3& axis() const { return m_axis; }
|
||||
Vector3& axis() { return m_axis; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline QuaternionType operator* (const AngleAxis& other) const
|
||||
{ return QuaternionType(*this) * QuaternionType(other); }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline QuaternionType operator* (const QuaternionType& other) const
|
||||
{ return QuaternionType(*this) * other; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
friend inline QuaternionType operator* (const QuaternionType& a, const AngleAxis& b)
|
||||
{ return a * QuaternionType(b); }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Matrix3 operator* (const Matrix3& other) const
|
||||
{ return toRotationMatrix() * other; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline friend Matrix3 operator* (const Matrix3& a, const AngleAxis& b)
|
||||
{ return a * b.toRotationMatrix(); }
|
||||
|
||||
/** Applies rotation to vector */
|
||||
inline Vector3 operator* (const Vector3& other) const
|
||||
{ return toRotationMatrix() * other; }
|
||||
|
||||
/** \returns the inverse rotation, i.e., an angle-axis with opposite rotation angle */
|
||||
AngleAxis inverse() const
|
||||
{ return AngleAxis(-m_angle, m_axis); }
|
||||
|
||||
AngleAxis& operator=(const QuaternionType& q);
|
||||
template<typename Derived>
|
||||
AngleAxis& operator=(const MatrixBase<Derived>& m);
|
||||
|
||||
template<typename Derived>
|
||||
AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix3 toRotationMatrix(void) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
|
||||
{
|
||||
m_axis = other.axis().template cast<Scalar>();
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const AngleAxis& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_axis.isApprox(other.m_axis, prec) && ei_isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision angle-axis type */
|
||||
typedef AngleAxis<float> AngleAxisf;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision angle-axis type */
|
||||
typedef AngleAxis<double> AngleAxisd;
|
||||
|
||||
/** Set \c *this from a quaternion.
|
||||
* The axis is normalized.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionType& q)
|
||||
{
|
||||
Scalar n2 = q.vec().squaredNorm();
|
||||
if (n2 < precision<Scalar>()*precision<Scalar>())
|
||||
{
|
||||
m_angle = 0;
|
||||
m_axis << 1, 0, 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = 2*std::acos(q.w());
|
||||
m_axis = q.vec() / ei_sqrt(n2);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set \c *this from a 3x3 rotation matrix \a mat.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
// Since a direct conversion would not be really faster,
|
||||
// let's use the robust Quaternion implementation:
|
||||
return *this = QuaternionType(mat);
|
||||
}
|
||||
|
||||
/** Constructs and \returns an equivalent 3x3 rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
typename AngleAxis<Scalar>::Matrix3
|
||||
AngleAxis<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
Matrix3 res;
|
||||
Vector3 sin_axis = ei_sin(m_angle) * m_axis;
|
||||
Scalar c = ei_cos(m_angle);
|
||||
Vector3 cos1_axis = (Scalar(1)-c) * m_axis;
|
||||
|
||||
Scalar tmp;
|
||||
tmp = cos1_axis.x() * m_axis.y();
|
||||
res.coeffRef(0,1) = tmp - sin_axis.z();
|
||||
res.coeffRef(1,0) = tmp + sin_axis.z();
|
||||
|
||||
tmp = cos1_axis.x() * m_axis.z();
|
||||
res.coeffRef(0,2) = tmp + sin_axis.y();
|
||||
res.coeffRef(2,0) = tmp - sin_axis.y();
|
||||
|
||||
tmp = cos1_axis.y() * m_axis.z();
|
||||
res.coeffRef(1,2) = tmp - sin_axis.x();
|
||||
res.coeffRef(2,1) = tmp + sin_axis.x();
|
||||
|
||||
res.diagonal() = (cos1_axis.cwise() * m_axis).cwise() + c;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,254 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Hyperplane
|
||||
*
|
||||
* \brief A hyperplane
|
||||
*
|
||||
* A hyperplane is an affine subspace of dimension n-1 in a space of dimension n.
|
||||
* For example, a hyperplane in a plane is a line; a hyperplane in 3-space is a plane.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
* Notice that the dimension of the hyperplane is _AmbientDim-1.
|
||||
*
|
||||
* This class represents an hyperplane as the zero set of the implicit equation
|
||||
* \f$ n \cdot x + d = 0 \f$ where \f$ n \f$ is a unit normal vector of the plane (linear part)
|
||||
* and \f$ d \f$ is the distance (offset) to the origin.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class Hyperplane
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
typedef Matrix<Scalar,int(AmbientDimAtCompileTime)==Dynamic
|
||||
? Dynamic
|
||||
: int(AmbientDimAtCompileTime)+1,1> Coefficients;
|
||||
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline Hyperplane() {}
|
||||
|
||||
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit Hyperplane(int _dim) : m_coeffs(_dim+1) {}
|
||||
|
||||
/** Construct a plane from its normal \a n and a point \a e onto the plane.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, const VectorType& e)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = -e.eigen2_dot(n);
|
||||
}
|
||||
|
||||
/** Constructs a plane from its normal \a n and distance to the origin \a d
|
||||
* such that the algebraic equation of the plane is \f$ n \cdot x + d = 0 \f$.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, Scalar d)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = d;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the two points. If the dimension of the ambient space
|
||||
* is greater than 2, then there isn't uniqueness, so an arbitrary choice is made.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1)
|
||||
{
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p1 - p0).unitOrthogonal();
|
||||
result.offset() = -result.normal().eigen2_dot(p0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the three points. The dimension of the ambient space
|
||||
* is required to be exactly 3.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1, const VectorType& p2)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p2 - p0).cross(p1 - p0).normalized();
|
||||
result.offset() = -result.normal().eigen2_dot(p0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the parametrized line \a parametrized.
|
||||
* If the dimension of the ambient space is greater than 2, then there isn't uniqueness,
|
||||
* so an arbitrary choice is made.
|
||||
*/
|
||||
// FIXME to be consitent with the rest this could be implemented as a static Through function ??
|
||||
explicit Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
|
||||
{
|
||||
normal() = parametrized.direction().unitOrthogonal();
|
||||
offset() = -normal().eigen2_dot(parametrized.origin());
|
||||
}
|
||||
|
||||
~Hyperplane() {}
|
||||
|
||||
/** \returns the dimension in which the plane holds */
|
||||
inline int dim() const { return int(AmbientDimAtCompileTime)==Dynamic ? m_coeffs.size()-1 : int(AmbientDimAtCompileTime); }
|
||||
|
||||
/** normalizes \c *this */
|
||||
void normalize(void)
|
||||
{
|
||||
m_coeffs /= normal().norm();
|
||||
}
|
||||
|
||||
/** \returns the signed distance between the plane \c *this and a point \a p.
|
||||
* \sa absDistance()
|
||||
*/
|
||||
inline Scalar signedDistance(const VectorType& p) const { return p.eigen2_dot(normal()) + offset(); }
|
||||
|
||||
/** \returns the absolute distance between the plane \c *this and a point \a p.
|
||||
* \sa signedDistance()
|
||||
*/
|
||||
inline Scalar absDistance(const VectorType& p) const { return ei_abs(signedDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the plane \c *this.
|
||||
*/
|
||||
inline VectorType projection(const VectorType& p) const { return p - signedDistance(p) * normal(); }
|
||||
|
||||
/** \returns a constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline const NormalReturnType normal() const { return NormalReturnType(*const_cast<Coefficients*>(&m_coeffs),0,0,dim(),1); }
|
||||
|
||||
/** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline NormalReturnType normal() { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns the distance to the origin, which is also the "constant term" of the implicit equation
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline const Scalar& offset() const { return m_coeffs.coeff(dim()); }
|
||||
|
||||
/** \returns a non-constant reference to the distance to the origin, which is also the constant part
|
||||
* of the implicit equation */
|
||||
inline Scalar& offset() { return m_coeffs(dim()); }
|
||||
|
||||
/** \returns a constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
/** \returns a non-constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** \returns the intersection of *this with \a other.
|
||||
*
|
||||
* \warning The ambient space must be a plane, i.e. have dimension 2, so that \c *this and \a other are lines.
|
||||
*
|
||||
* \note If \a other is approximately parallel to *this, this method will return any point on *this.
|
||||
*/
|
||||
VectorType intersection(const Hyperplane& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
||||
// since the line equations ax+by=c are normalized with a^2+b^2=1, the following tests
|
||||
// whether the two lines are approximately parallel.
|
||||
if(ei_isMuchSmallerThan(det, Scalar(1)))
|
||||
{ // special case where the two lines are approximately parallel. Pick any point on the first line.
|
||||
if(ei_abs(coeffs().coeff(1))>ei_abs(coeffs().coeff(0)))
|
||||
return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
|
||||
else
|
||||
return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
|
||||
}
|
||||
else
|
||||
{ // general case
|
||||
Scalar invdet = Scalar(1) / det;
|
||||
return VectorType(invdet*(coeffs().coeff(1)*other.coeffs().coeff(2)-other.coeffs().coeff(1)*coeffs().coeff(2)),
|
||||
invdet*(other.coeffs().coeff(0)*coeffs().coeff(2)-coeffs().coeff(0)*other.coeffs().coeff(2)));
|
||||
}
|
||||
}
|
||||
|
||||
/** Applies the transformation matrix \a mat to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* \param mat the Dim x Dim transformation matrix
|
||||
* \param traits specifies whether the matrix \a mat represents an Isometry
|
||||
* or a more generic Affine transformation. The default is Affine.
|
||||
*/
|
||||
template<typename XprType>
|
||||
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||
{
|
||||
if (traits==Affine)
|
||||
normal() = mat.inverse().transpose() * normal();
|
||||
else if (traits==Isometry)
|
||||
normal() = mat * normal();
|
||||
else
|
||||
{
|
||||
ei_assert("invalid traits value in Hyperplane::transform()");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies the transformation \a t to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* \param t the transformation of dimension Dim
|
||||
* \param traits specifies whether the transformation \a t represents an Isometry
|
||||
* or a more generic Affine transformation. The default is Affine.
|
||||
* Other kind of transformations are not supported.
|
||||
*/
|
||||
inline Hyperplane& transform(const Transform<Scalar,AmbientDimAtCompileTime>& t,
|
||||
TransformTraits traits = Affine)
|
||||
{
|
||||
transform(t.linear(), traits);
|
||||
offset() -= t.translation().eigen2_dot(normal());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Hyperplane(const Hyperplane<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Hyperplane& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class ParametrizedLine
|
||||
*
|
||||
* \brief A parametrized line
|
||||
*
|
||||
* A parametrized line is defined by an origin point \f$ \mathbf{o} \f$ and a unit
|
||||
* direction vector \f$ \mathbf{d} \f$ such that the line corresponds to
|
||||
* the set \f$ l(t) = \mathbf{o} + t \mathbf{d} \f$, \f$ l \in \mathbf{R} \f$.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class ParametrizedLine
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline ParametrizedLine() {}
|
||||
|
||||
/** Constructs a dynamic-size line with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit ParametrizedLine(int _dim) : m_origin(_dim), m_direction(_dim) {}
|
||||
|
||||
/** Initializes a parametrized line of direction \a direction and origin \a origin.
|
||||
* \warning the vector direction is assumed to be normalized.
|
||||
*/
|
||||
ParametrizedLine(const VectorType& origin, const VectorType& direction)
|
||||
: m_origin(origin), m_direction(direction) {}
|
||||
|
||||
explicit ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
|
||||
|
||||
/** Constructs a parametrized line going from \a p0 to \a p1. */
|
||||
static inline ParametrizedLine Through(const VectorType& p0, const VectorType& p1)
|
||||
{ return ParametrizedLine(p0, (p1-p0).normalized()); }
|
||||
|
||||
~ParametrizedLine() {}
|
||||
|
||||
/** \returns the dimension in which the line holds */
|
||||
inline int dim() const { return m_direction.size(); }
|
||||
|
||||
const VectorType& origin() const { return m_origin; }
|
||||
VectorType& origin() { return m_origin; }
|
||||
|
||||
const VectorType& direction() const { return m_direction; }
|
||||
VectorType& direction() { return m_direction; }
|
||||
|
||||
/** \returns the squared distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa distance()
|
||||
*/
|
||||
RealScalar squaredDistance(const VectorType& p) const
|
||||
{
|
||||
VectorType diff = p-origin();
|
||||
return (diff - diff.eigen2_dot(direction())* direction()).squaredNorm();
|
||||
}
|
||||
/** \returns the distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa squaredDistance()
|
||||
*/
|
||||
RealScalar distance(const VectorType& p) const { return ei_sqrt(squaredDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the line \c *this. */
|
||||
VectorType projection(const VectorType& p) const
|
||||
{ return origin() + (p-origin()).eigen2_dot(direction()) * direction(); }
|
||||
|
||||
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane);
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit ParametrizedLine(const ParametrizedLine<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{
|
||||
m_origin = other.origin().template cast<Scalar>();
|
||||
m_direction = other.direction().template cast<Scalar>();
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const ParametrizedLine& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_origin, m_direction;
|
||||
};
|
||||
|
||||
/** Constructs a parametrized line from a 2D hyperplane
|
||||
*
|
||||
* \warning the ambient space must have dimension 2 such that the hyperplane actually describes a line
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
inline ParametrizedLine<_Scalar, _AmbientDim>::ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim>& hyperplane)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
direction() = hyperplane.normal().unitOrthogonal();
|
||||
origin() = -hyperplane.normal()*hyperplane.offset();
|
||||
}
|
||||
|
||||
/** \returns the parameter value of the intersection between \c *this and the given hyperplane
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim>::intersection(const Hyperplane<_Scalar, _AmbientDim>& hyperplane)
|
||||
{
|
||||
return -(hyperplane.offset()+origin().eigen2_dot(hyperplane.normal()))
|
||||
/(direction().eigen2_dot(hyperplane.normal()));
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,495 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename Other,
|
||||
int OtherRows=Other::RowsAtCompileTime,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct ei_quaternion_assign_impl;
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Quaternion
|
||||
*
|
||||
* \brief The quaternion class used to represent 3D orientations and rotations
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
*
|
||||
* This class represents a quaternion \f$ w+xi+yj+zk \f$ that is a convenient representation of
|
||||
* orientations and rotations of objects in three dimensions. Compared to other representations
|
||||
* like Euler angles or 3x3 matrices, quatertions offer the following advantages:
|
||||
* \li \b compact storage (4 scalars)
|
||||
* \li \b efficient to compose (28 flops),
|
||||
* \li \b stable spherical interpolation
|
||||
*
|
||||
* The following two typedefs are provided for convenience:
|
||||
* \li \c Quaternionf for \c float
|
||||
* \li \c Quaterniond for \c double
|
||||
*
|
||||
* \sa class AngleAxis, class Transform
|
||||
*/
|
||||
|
||||
template<typename _Scalar> struct ei_traits<Quaternion<_Scalar> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
};
|
||||
|
||||
template<typename _Scalar>
|
||||
class Quaternion : public RotationBase<Quaternion<_Scalar>,3>
|
||||
{
|
||||
typedef RotationBase<Quaternion<_Scalar>,3> Base;
|
||||
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,4)
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
/** the type of the Coefficients 4-vector */
|
||||
typedef Matrix<Scalar, 4, 1> Coefficients;
|
||||
/** the type of a 3D vector */
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
/** the equivalent rotation matrix type */
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
/** the equivalent angle-axis type */
|
||||
typedef AngleAxis<Scalar> AngleAxisType;
|
||||
|
||||
/** \returns the \c x coefficient */
|
||||
inline Scalar x() const { return m_coeffs.coeff(0); }
|
||||
/** \returns the \c y coefficient */
|
||||
inline Scalar y() const { return m_coeffs.coeff(1); }
|
||||
/** \returns the \c z coefficient */
|
||||
inline Scalar z() const { return m_coeffs.coeff(2); }
|
||||
/** \returns the \c w coefficient */
|
||||
inline Scalar w() const { return m_coeffs.coeff(3); }
|
||||
|
||||
/** \returns a reference to the \c x coefficient */
|
||||
inline Scalar& x() { return m_coeffs.coeffRef(0); }
|
||||
/** \returns a reference to the \c y coefficient */
|
||||
inline Scalar& y() { return m_coeffs.coeffRef(1); }
|
||||
/** \returns a reference to the \c z coefficient */
|
||||
inline Scalar& z() { return m_coeffs.coeffRef(2); }
|
||||
/** \returns a reference to the \c w coefficient */
|
||||
inline Scalar& w() { return m_coeffs.coeffRef(3); }
|
||||
|
||||
/** \returns a read-only vector expression of the imaginary part (x,y,z) */
|
||||
inline const Block<const Coefficients,3,1> vec() const { return m_coeffs.template start<3>(); }
|
||||
|
||||
/** \returns a vector expression of the imaginary part (x,y,z) */
|
||||
inline Block<Coefficients,3,1> vec() { return m_coeffs.template start<3>(); }
|
||||
|
||||
/** \returns a read-only vector expression of the coefficients (x,y,z,w) */
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
/** \returns a vector expression of the coefficients (x,y,z,w) */
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** Default constructor leaving the quaternion uninitialized. */
|
||||
inline Quaternion() {}
|
||||
|
||||
/** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
|
||||
* its four coefficients \a w, \a x, \a y and \a z.
|
||||
*
|
||||
* \warning Note the order of the arguments: the real \a w coefficient first,
|
||||
* while internally the coefficients are stored in the following order:
|
||||
* [\c x, \c y, \c z, \c w]
|
||||
*/
|
||||
inline Quaternion(Scalar w, Scalar x, Scalar y, Scalar z)
|
||||
{ m_coeffs << x, y, z, w; }
|
||||
|
||||
/** Copy constructor */
|
||||
inline Quaternion(const Quaternion& other) { m_coeffs = other.m_coeffs; }
|
||||
|
||||
/** Constructs and initializes a quaternion from the angle-axis \a aa */
|
||||
explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
|
||||
|
||||
/** Constructs and initializes a quaternion from either:
|
||||
* - a rotation matrix expression,
|
||||
* - a 4D vector expression representing quaternion coefficients.
|
||||
* \sa operator=(MatrixBase<Derived>)
|
||||
*/
|
||||
template<typename Derived>
|
||||
explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
|
||||
|
||||
Quaternion& operator=(const Quaternion& other);
|
||||
Quaternion& operator=(const AngleAxisType& aa);
|
||||
template<typename Derived>
|
||||
Quaternion& operator=(const MatrixBase<Derived>& m);
|
||||
|
||||
/** \returns a quaternion representing an identity rotation
|
||||
* \sa MatrixBase::Identity()
|
||||
*/
|
||||
static inline Quaternion Identity() { return Quaternion(1, 0, 0, 0); }
|
||||
|
||||
/** \sa Quaternion::Identity(), MatrixBase::setIdentity()
|
||||
*/
|
||||
inline Quaternion& setIdentity() { m_coeffs << 0, 0, 0, 1; return *this; }
|
||||
|
||||
/** \returns the squared norm of the quaternion's coefficients
|
||||
* \sa Quaternion::norm(), MatrixBase::squaredNorm()
|
||||
*/
|
||||
inline Scalar squaredNorm() const { return m_coeffs.squaredNorm(); }
|
||||
|
||||
/** \returns the norm of the quaternion's coefficients
|
||||
* \sa Quaternion::squaredNorm(), MatrixBase::norm()
|
||||
*/
|
||||
inline Scalar norm() const { return m_coeffs.norm(); }
|
||||
|
||||
/** Normalizes the quaternion \c *this
|
||||
* \sa normalized(), MatrixBase::normalize() */
|
||||
inline void normalize() { m_coeffs.normalize(); }
|
||||
/** \returns a normalized version of \c *this
|
||||
* \sa normalize(), MatrixBase::normalized() */
|
||||
inline Quaternion normalized() const { return Quaternion(m_coeffs.normalized()); }
|
||||
|
||||
/** \returns the dot product of \c *this and \a other
|
||||
* Geometrically speaking, the dot product of two unit quaternions
|
||||
* corresponds to the cosine of half the angle between the two rotations.
|
||||
* \sa angularDistance()
|
||||
*/
|
||||
inline Scalar eigen2_dot(const Quaternion& other) const { return m_coeffs.eigen2_dot(other.m_coeffs); }
|
||||
|
||||
inline Scalar angularDistance(const Quaternion& other) const;
|
||||
|
||||
Matrix3 toRotationMatrix(void) const;
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
Quaternion& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
|
||||
|
||||
inline Quaternion operator* (const Quaternion& q) const;
|
||||
inline Quaternion& operator*= (const Quaternion& q);
|
||||
|
||||
Quaternion inverse(void) const;
|
||||
Quaternion conjugate(void) const;
|
||||
|
||||
Quaternion slerp(Scalar t, const Quaternion& other) const;
|
||||
|
||||
template<typename Derived>
|
||||
Vector3 operator* (const MatrixBase<Derived>& vec) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Quaternion,Quaternion<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Quaternion,Quaternion<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Quaternion(const Quaternion<OtherScalarType>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Quaternion& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
protected:
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision quaternion type */
|
||||
typedef Quaternion<float> Quaternionf;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision quaternion type */
|
||||
typedef Quaternion<double> Quaterniond;
|
||||
|
||||
// Generic Quaternion * Quaternion product
|
||||
template<typename Scalar> inline Quaternion<Scalar>
|
||||
ei_quaternion_product(const Quaternion<Scalar>& a, const Quaternion<Scalar>& b)
|
||||
{
|
||||
return Quaternion<Scalar>
|
||||
(
|
||||
a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
|
||||
a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
|
||||
a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
|
||||
a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
|
||||
);
|
||||
}
|
||||
|
||||
/** \returns the concatenation of two rotations as a quaternion-quaternion product */
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar> Quaternion<Scalar>::operator* (const Quaternion& other) const
|
||||
{
|
||||
return ei_quaternion_product(*this,other);
|
||||
}
|
||||
|
||||
/** \sa operator*(Quaternion) */
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator*= (const Quaternion& other)
|
||||
{
|
||||
return (*this = *this * other);
|
||||
}
|
||||
|
||||
/** Rotation of a vector by a quaternion.
|
||||
* \remarks If the quaternion is used to rotate several points (>1)
|
||||
* then it is much more efficient to first convert it to a 3x3 Matrix.
|
||||
* Comparison of the operation cost for n transformations:
|
||||
* - Quaternion: 30n
|
||||
* - Via a Matrix3: 24 + 15n
|
||||
*/
|
||||
template <typename Scalar>
|
||||
template<typename Derived>
|
||||
inline typename Quaternion<Scalar>::Vector3
|
||||
Quaternion<Scalar>::operator* (const MatrixBase<Derived>& v) const
|
||||
{
|
||||
// Note that this algorithm comes from the optimization by hand
|
||||
// of the conversion to a Matrix followed by a Matrix/Vector product.
|
||||
// It appears to be much faster than the common algorithm found
|
||||
// in the litterature (30 versus 39 flops). It also requires two
|
||||
// Vector3 as temporaries.
|
||||
Vector3 uv;
|
||||
uv = 2 * this->vec().cross(v);
|
||||
return v + this->w() * uv + this->vec().cross(uv);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const Quaternion& other)
|
||||
{
|
||||
m_coeffs = other.m_coeffs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set \c *this from an angle-axis \a aa and returns a reference to \c *this
|
||||
*/
|
||||
template<typename Scalar>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const AngleAxisType& aa)
|
||||
{
|
||||
Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
|
||||
this->w() = ei_cos(ha);
|
||||
this->vec() = ei_sin(ha) * aa.axis();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set \c *this from the expression \a xpr:
|
||||
* - if \a xpr is a 4x1 vector, then \a xpr is assumed to be a quaternion
|
||||
* - if \a xpr is a 3x3 matrix, then \a xpr is assumed to be rotation matrix
|
||||
* and \a xpr is converted to a quaternion
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::operator=(const MatrixBase<Derived>& xpr)
|
||||
{
|
||||
ei_quaternion_assign_impl<Derived>::run(*this, xpr.derived());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Convert the quaternion to a 3x3 rotation matrix */
|
||||
template<typename Scalar>
|
||||
inline typename Quaternion<Scalar>::Matrix3
|
||||
Quaternion<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
// NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
|
||||
// if not inlined then the cost of the return by value is huge ~ +35%,
|
||||
// however, not inlining this function is an order of magnitude slower, so
|
||||
// it has to be inlined, and so the return by value is not an issue
|
||||
Matrix3 res;
|
||||
|
||||
const Scalar tx = Scalar(2)*this->x();
|
||||
const Scalar ty = Scalar(2)*this->y();
|
||||
const Scalar tz = Scalar(2)*this->z();
|
||||
const Scalar twx = tx*this->w();
|
||||
const Scalar twy = ty*this->w();
|
||||
const Scalar twz = tz*this->w();
|
||||
const Scalar txx = tx*this->x();
|
||||
const Scalar txy = ty*this->x();
|
||||
const Scalar txz = tz*this->x();
|
||||
const Scalar tyy = ty*this->y();
|
||||
const Scalar tyz = tz*this->y();
|
||||
const Scalar tzz = tz*this->z();
|
||||
|
||||
res.coeffRef(0,0) = Scalar(1)-(tyy+tzz);
|
||||
res.coeffRef(0,1) = txy-twz;
|
||||
res.coeffRef(0,2) = txz+twy;
|
||||
res.coeffRef(1,0) = txy+twz;
|
||||
res.coeffRef(1,1) = Scalar(1)-(txx+tzz);
|
||||
res.coeffRef(1,2) = tyz-twx;
|
||||
res.coeffRef(2,0) = txz-twy;
|
||||
res.coeffRef(2,1) = tyz+twx;
|
||||
res.coeffRef(2,2) = Scalar(1)-(txx+tyy);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Sets *this to be a quaternion representing a rotation sending the vector \a a to the vector \a b.
|
||||
*
|
||||
* \returns a reference to *this.
|
||||
*
|
||||
* Note that the two input vectors do \b not have to be normalized.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived1, typename Derived2>
|
||||
inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||
{
|
||||
Vector3 v0 = a.normalized();
|
||||
Vector3 v1 = b.normalized();
|
||||
Scalar c = v0.eigen2_dot(v1);
|
||||
|
||||
// if dot == 1, vectors are the same
|
||||
if (ei_isApprox(c,Scalar(1)))
|
||||
{
|
||||
// set to identity
|
||||
this->w() = 1; this->vec().setZero();
|
||||
return *this;
|
||||
}
|
||||
// if dot == -1, vectors are opposites
|
||||
if (ei_isApprox(c,Scalar(-1)))
|
||||
{
|
||||
this->vec() = v0.unitOrthogonal();
|
||||
this->w() = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3 axis = v0.cross(v1);
|
||||
Scalar s = ei_sqrt((Scalar(1)+c)*Scalar(2));
|
||||
Scalar invs = Scalar(1)/s;
|
||||
this->vec() = axis * invs;
|
||||
this->w() = s * Scalar(0.5);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns the multiplicative inverse of \c *this
|
||||
* Note that in most cases, i.e., if you simply want the opposite rotation,
|
||||
* and/or the quaternion is normalized, then it is enough to use the conjugate.
|
||||
*
|
||||
* \sa Quaternion::conjugate()
|
||||
*/
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar> Quaternion<Scalar>::inverse() const
|
||||
{
|
||||
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
|
||||
Scalar n2 = this->squaredNorm();
|
||||
if (n2 > 0)
|
||||
return Quaternion(conjugate().coeffs() / n2);
|
||||
else
|
||||
{
|
||||
// return an invalid result to flag the error
|
||||
return Quaternion(Coefficients::Zero());
|
||||
}
|
||||
}
|
||||
|
||||
/** \returns the conjugate of the \c *this which is equal to the multiplicative inverse
|
||||
* if the quaternion is normalized.
|
||||
* The conjugate of a quaternion represents the opposite rotation.
|
||||
*
|
||||
* \sa Quaternion::inverse()
|
||||
*/
|
||||
template <typename Scalar>
|
||||
inline Quaternion<Scalar> Quaternion<Scalar>::conjugate() const
|
||||
{
|
||||
return Quaternion(this->w(),-this->x(),-this->y(),-this->z());
|
||||
}
|
||||
|
||||
/** \returns the angle (in radian) between two rotations
|
||||
* \sa eigen2_dot()
|
||||
*/
|
||||
template <typename Scalar>
|
||||
inline Scalar Quaternion<Scalar>::angularDistance(const Quaternion& other) const
|
||||
{
|
||||
double d = ei_abs(this->eigen2_dot(other));
|
||||
if (d>=1.0)
|
||||
return 0;
|
||||
return Scalar(2) * std::acos(d);
|
||||
}
|
||||
|
||||
/** \returns the spherical linear interpolation between the two quaternions
|
||||
* \c *this and \a other at the parameter \a t
|
||||
*/
|
||||
template <typename Scalar>
|
||||
Quaternion<Scalar> Quaternion<Scalar>::slerp(Scalar t, const Quaternion& other) const
|
||||
{
|
||||
static const Scalar one = Scalar(1) - machine_epsilon<Scalar>();
|
||||
Scalar d = this->eigen2_dot(other);
|
||||
Scalar absD = ei_abs(d);
|
||||
|
||||
Scalar scale0;
|
||||
Scalar scale1;
|
||||
|
||||
if (absD>=one)
|
||||
{
|
||||
scale0 = Scalar(1) - t;
|
||||
scale1 = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
// theta is the angle between the 2 quaternions
|
||||
Scalar theta = std::acos(absD);
|
||||
Scalar sinTheta = ei_sin(theta);
|
||||
|
||||
scale0 = ei_sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
||||
scale1 = ei_sin( ( t * theta) ) / sinTheta;
|
||||
if (d<0)
|
||||
scale1 = -scale1;
|
||||
}
|
||||
|
||||
return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
|
||||
}
|
||||
|
||||
// set from a rotation matrix
|
||||
template<typename Other>
|
||||
struct ei_quaternion_assign_impl<Other,3,3>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
static inline void run(Quaternion<Scalar>& q, const Other& mat)
|
||||
{
|
||||
// This algorithm comes from "Quaternion Calculus and Fast Animation",
|
||||
// Ken Shoemake, 1987 SIGGRAPH course notes
|
||||
Scalar t = mat.trace();
|
||||
if (t > 0)
|
||||
{
|
||||
t = ei_sqrt(t + Scalar(1.0));
|
||||
q.w() = Scalar(0.5)*t;
|
||||
t = Scalar(0.5)/t;
|
||||
q.x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t;
|
||||
q.y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t;
|
||||
q.z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
if (mat.coeff(1,1) > mat.coeff(0,0))
|
||||
i = 1;
|
||||
if (mat.coeff(2,2) > mat.coeff(i,i))
|
||||
i = 2;
|
||||
int j = (i+1)%3;
|
||||
int k = (j+1)%3;
|
||||
|
||||
t = ei_sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0));
|
||||
q.coeffs().coeffRef(i) = Scalar(0.5) * t;
|
||||
t = Scalar(0.5)/t;
|
||||
q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t;
|
||||
q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t;
|
||||
q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// set from a vector of coefficients assumed to be a quaternion
|
||||
template<typename Other>
|
||||
struct ei_quaternion_assign_impl<Other,4,1>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
static inline void run(Quaternion<Scalar>& q, const Other& vec)
|
||||
{
|
||||
q.coeffs() = vec;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Rotation2D
|
||||
*
|
||||
* \brief Represents a rotation/orientation in a 2 dimensional space.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
*
|
||||
* This class is equivalent to a single scalar representing a counter clock wise rotation
|
||||
* as a single angle in radian. It provides some additional features such as the automatic
|
||||
* conversion from/to a 2x2 rotation matrix. Moreover this class aims to provide a similar
|
||||
* interface to Quaternion in order to facilitate the writing of generic algorithms
|
||||
* dealing with rotations.
|
||||
*
|
||||
* \sa class Quaternion, class Transform
|
||||
*/
|
||||
template<typename _Scalar> struct ei_traits<Rotation2D<_Scalar> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
};
|
||||
|
||||
template<typename _Scalar>
|
||||
class Rotation2D : public RotationBase<Rotation2D<_Scalar>,2>
|
||||
{
|
||||
typedef RotationBase<Rotation2D<_Scalar>,2> Base;
|
||||
|
||||
public:
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
enum { Dim = 2 };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
typedef Matrix<Scalar,2,1> Vector2;
|
||||
typedef Matrix<Scalar,2,2> Matrix2;
|
||||
|
||||
protected:
|
||||
|
||||
Scalar m_angle;
|
||||
|
||||
public:
|
||||
|
||||
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
|
||||
inline Rotation2D(Scalar a) : m_angle(a) {}
|
||||
|
||||
/** \returns the rotation angle */
|
||||
inline Scalar angle() const { return m_angle; }
|
||||
|
||||
/** \returns a read-write reference to the rotation angle */
|
||||
inline Scalar& angle() { return m_angle; }
|
||||
|
||||
/** \returns the inverse rotation */
|
||||
inline Rotation2D inverse() const { return -m_angle; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D operator*(const Rotation2D& other) const
|
||||
{ return m_angle + other.m_angle; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D& operator*=(const Rotation2D& other)
|
||||
{ return m_angle += other.m_angle; return *this; }
|
||||
|
||||
/** Applies the rotation to a 2D vector */
|
||||
Vector2 operator* (const Vector2& vec) const
|
||||
{ return toRotationMatrix() * vec; }
|
||||
|
||||
template<typename Derived>
|
||||
Rotation2D& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix2 toRotationMatrix(void) const;
|
||||
|
||||
/** \returns the spherical interpolation between \c *this and \a other using
|
||||
* parameter \a t. It is in fact equivalent to a linear interpolation.
|
||||
*/
|
||||
inline Rotation2D slerp(Scalar t, const Rotation2D& other) const
|
||||
{ return m_angle * (1-t) + other.angle() * t; }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
|
||||
{
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Rotation2D& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return ei_isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision 2D rotation type */
|
||||
typedef Rotation2D<float> Rotation2Df;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision 2D rotation type */
|
||||
typedef Rotation2D<double> Rotation2Dd;
|
||||
|
||||
/** Set \c *this from a 2x2 rotation matrix \a mat.
|
||||
* In other words, this function extract the rotation angle
|
||||
* from the rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime==2 && Derived::ColsAtCompileTime==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_angle = ei_atan2(mat.coeff(1,0), mat.coeff(0,0));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Constructs and \returns an equivalent 2x2 rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
typename Rotation2D<Scalar>::Matrix2
|
||||
Rotation2D<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
Scalar sinA = ei_sin(m_angle);
|
||||
Scalar cosA = ei_cos(m_angle);
|
||||
return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// this file aims to contains the various representations of rotation/orientation
|
||||
// in 2D and 3D space excepted Matrix and Quaternion.
|
||||
|
||||
/** \class RotationBase
|
||||
*
|
||||
* \brief Common base class for compact rotation representations
|
||||
*
|
||||
* \param Derived is the derived type, i.e., a rotation type
|
||||
* \param _Dim the dimension of the space
|
||||
*/
|
||||
template<typename Derived, int _Dim>
|
||||
class RotationBase
|
||||
{
|
||||
public:
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef typename ei_traits<Derived>::Scalar Scalar;
|
||||
|
||||
/** corresponding linear transformation matrix type */
|
||||
typedef Matrix<Scalar,Dim,Dim> RotationMatrixType;
|
||||
|
||||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
|
||||
/** \returns an equivalent rotation matrix */
|
||||
inline RotationMatrixType toRotationMatrix() const { return derived().toRotationMatrix(); }
|
||||
|
||||
/** \returns the inverse rotation */
|
||||
inline Derived inverse() const { return derived().inverse(); }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a translation \a t */
|
||||
inline Transform<Scalar,Dim> operator*(const Translation<Scalar,Dim>& t) const
|
||||
{ return toRotationMatrix() * t; }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a scaling \a s */
|
||||
inline RotationMatrixType operator*(const Scaling<Scalar,Dim>& s) const
|
||||
{ return toRotationMatrix() * s; }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with an affine transformation \a t */
|
||||
inline Transform<Scalar,Dim> operator*(const Transform<Scalar,Dim>& t) const
|
||||
{ return toRotationMatrix() * t; }
|
||||
};
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* Constructs a Dim x Dim rotation matrix from the rotation \a r
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
*this = r.toRotationMatrix();
|
||||
}
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* Set a Dim x Dim rotation matrix from the rotation \a r
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
return *this = r.toRotationMatrix();
|
||||
}
|
||||
|
||||
/** \internal
|
||||
*
|
||||
* Helper function to return an arbitrary rotation object to a rotation matrix.
|
||||
*
|
||||
* \param Scalar the numeric type of the matrix coefficients
|
||||
* \param Dim the dimension of the current space
|
||||
*
|
||||
* It returns a Dim x Dim fixed size matrix.
|
||||
*
|
||||
* Default specializations are provided for:
|
||||
* - any scalar type (2D),
|
||||
* - any matrix expression,
|
||||
* - any type based on RotationBase (e.g., Quaternion, AngleAxis, Rotation2D)
|
||||
*
|
||||
* Currently ei_toRotationMatrix is only used by Transform.
|
||||
*
|
||||
* \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
static inline Matrix<Scalar,2,2> ei_toRotationMatrix(const Scalar& s)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return Rotation2D<Scalar>(s).toRotationMatrix();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, typename OtherDerived>
|
||||
static inline Matrix<Scalar,Dim,Dim> ei_toRotationMatrix(const RotationBase<OtherDerived,Dim>& r)
|
||||
{
|
||||
return r.toRotationMatrix();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, typename OtherDerived>
|
||||
static inline const MatrixBase<OtherDerived>& ei_toRotationMatrix(const MatrixBase<OtherDerived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim,
|
||||
YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return mat;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Scaling
|
||||
*
|
||||
* \brief Represents a possibly non uniform scaling transformation
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
* \param _Dim the dimension of the space, can be a compile time value or Dynamic
|
||||
*
|
||||
* \note This class is not aimed to be used to store a scaling transformation,
|
||||
* but rather to make easier the constructions and updates of Transform objects.
|
||||
*
|
||||
* \sa class Translation, class Transform
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Scaling
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim)
|
||||
/** dimension of the space */
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
/** corresponding vector type */
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
/** corresponding linear transformation matrix type */
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
|
||||
/** corresponding translation type */
|
||||
typedef Translation<Scalar,Dim> TranslationType;
|
||||
/** corresponding affine transformation type */
|
||||
typedef Transform<Scalar,Dim> TransformType;
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_coeffs;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
Scaling() {}
|
||||
/** Constructs and initialize a uniform scaling transformation */
|
||||
explicit inline Scaling(const Scalar& s) { m_coeffs.setConstant(s); }
|
||||
/** 2D only */
|
||||
inline Scaling(const Scalar& sx, const Scalar& sy)
|
||||
{
|
||||
ei_assert(Dim==2);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
}
|
||||
/** 3D only */
|
||||
inline Scaling(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
{
|
||||
ei_assert(Dim==3);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
m_coeffs.z() = sz;
|
||||
}
|
||||
/** Constructs and initialize the scaling transformation from a vector of scaling coefficients */
|
||||
explicit inline Scaling(const VectorType& coeffs) : m_coeffs(coeffs) {}
|
||||
|
||||
const VectorType& coeffs() const { return m_coeffs; }
|
||||
VectorType& coeffs() { return m_coeffs; }
|
||||
|
||||
/** Concatenates two scaling */
|
||||
inline Scaling operator* (const Scaling& other) const
|
||||
{ return Scaling(coeffs().cwise() * other.coeffs()); }
|
||||
|
||||
/** Concatenates a scaling and a translation */
|
||||
inline TransformType operator* (const TranslationType& t) const;
|
||||
|
||||
/** Concatenates a scaling and an affine transformation */
|
||||
inline TransformType operator* (const TransformType& t) const;
|
||||
|
||||
/** Concatenates a scaling and a linear transformation matrix */
|
||||
// TODO returns an expression
|
||||
inline LinearMatrixType operator* (const LinearMatrixType& other) const
|
||||
{ return coeffs().asDiagonal() * other; }
|
||||
|
||||
/** Concatenates a linear transformation matrix and a scaling */
|
||||
// TODO returns an expression
|
||||
friend inline LinearMatrixType operator* (const LinearMatrixType& other, const Scaling& s)
|
||||
{ return other * s.coeffs().asDiagonal(); }
|
||||
|
||||
template<typename Derived>
|
||||
inline LinearMatrixType operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{ return *this * r.toRotationMatrix(); }
|
||||
|
||||
/** Applies scaling to vector */
|
||||
inline VectorType operator* (const VectorType& other) const
|
||||
{ return coeffs().asDiagonal() * other; }
|
||||
|
||||
/** \returns the inverse scaling */
|
||||
inline Scaling inverse() const
|
||||
{ return Scaling(coeffs().cwise().inverse()); }
|
||||
|
||||
inline Scaling& operator=(const Scaling& other)
|
||||
{
|
||||
m_coeffs = other.m_coeffs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Scaling(const Scaling<OtherScalarType,Dim>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Scaling& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Scaling<float, 2> Scaling2f;
|
||||
typedef Scaling<double,2> Scaling2d;
|
||||
typedef Scaling<float, 3> Scaling3f;
|
||||
typedef Scaling<double,3> Scaling3d;
|
||||
//@}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Scaling<Scalar,Dim>::TransformType
|
||||
Scaling<Scalar,Dim>::operator* (const TranslationType& t) const
|
||||
{
|
||||
TransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear().diagonal() = coeffs();
|
||||
res.translation() = m_coeffs.cwise() * t.vector();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Scaling<Scalar,Dim>::TransformType
|
||||
Scaling<Scalar,Dim>::operator* (const TransformType& t) const
|
||||
{
|
||||
TransformType res = t;
|
||||
res.prescale(m_coeffs);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,786 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// Note that we have to pass Dim and HDim because it is not allowed to use a template
|
||||
// parameter to define a template specialization. To be more precise, in the following
|
||||
// specializations, it is not allowed to use Dim+1 instead of HDim.
|
||||
template< typename Other,
|
||||
int Dim,
|
||||
int HDim,
|
||||
int OtherRows=Other::RowsAtCompileTime,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct ei_transform_product_impl;
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Transform
|
||||
*
|
||||
* \brief Represents an homogeneous transformation in a N dimensional space
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _Dim the dimension of the space
|
||||
*
|
||||
* The homography is internally represented and stored as a (Dim+1)^2 matrix which
|
||||
* is available through the matrix() method.
|
||||
*
|
||||
* Conversion methods from/to Qt's QMatrix and QTransform are available if the
|
||||
* preprocessor token EIGEN_QT_SUPPORT is defined.
|
||||
*
|
||||
* \sa class Matrix, class Quaternion
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Transform
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
|
||||
enum {
|
||||
Dim = _Dim, ///< space dimension in which the transformation holds
|
||||
HDim = _Dim+1 ///< size of a respective homogeneous vector
|
||||
};
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
/** type of the matrix used to represent the transformation */
|
||||
typedef Matrix<Scalar,HDim,HDim> MatrixType;
|
||||
/** type of the matrix used to represent the linear part of the transformation */
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
|
||||
/** type of read/write reference to the linear part of the transformation */
|
||||
typedef Block<MatrixType,Dim,Dim> LinearPart;
|
||||
/** type of read/write reference to the linear part of the transformation */
|
||||
typedef const Block<const MatrixType,Dim,Dim> ConstLinearPart;
|
||||
/** type of a vector */
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
/** type of a read/write reference to the translation part of the rotation */
|
||||
typedef Block<MatrixType,Dim,1> TranslationPart;
|
||||
/** type of a read/write reference to the translation part of the rotation */
|
||||
typedef const Block<const MatrixType,Dim,1> ConstTranslationPart;
|
||||
/** corresponding translation type */
|
||||
typedef Translation<Scalar,Dim> TranslationType;
|
||||
/** corresponding scaling transformation type */
|
||||
typedef Scaling<Scalar,Dim> ScalingType;
|
||||
|
||||
protected:
|
||||
|
||||
MatrixType m_matrix;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization of the coefficients. */
|
||||
inline Transform() { }
|
||||
|
||||
inline Transform(const Transform& other)
|
||||
{
|
||||
m_matrix = other.m_matrix;
|
||||
}
|
||||
|
||||
inline explicit Transform(const TranslationType& t) { *this = t; }
|
||||
inline explicit Transform(const ScalingType& s) { *this = s; }
|
||||
template<typename Derived>
|
||||
inline explicit Transform(const RotationBase<Derived, Dim>& r) { *this = r; }
|
||||
|
||||
inline Transform& operator=(const Transform& other)
|
||||
{ m_matrix = other.m_matrix; return *this; }
|
||||
|
||||
template<typename OtherDerived, bool BigMatrix> // MSVC 2005 will commit suicide if BigMatrix has a default value
|
||||
struct construct_from_matrix
|
||||
{
|
||||
static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
transform->matrix() = other;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename OtherDerived> struct construct_from_matrix<OtherDerived, true>
|
||||
{
|
||||
static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
transform->linear() = other;
|
||||
transform->translation().setZero();
|
||||
transform->matrix()(Dim,Dim) = Scalar(1);
|
||||
transform->matrix().template block<1,Dim>(Dim,0).setZero();
|
||||
}
|
||||
};
|
||||
|
||||
/** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */
|
||||
template<typename OtherDerived>
|
||||
inline explicit Transform(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other);
|
||||
}
|
||||
|
||||
/** Set \c *this from a (Dim+1)^2 matrix. */
|
||||
template<typename OtherDerived>
|
||||
inline Transform& operator=(const MatrixBase<OtherDerived>& other)
|
||||
{ m_matrix = other; return *this; }
|
||||
|
||||
#ifdef EIGEN_QT_SUPPORT
|
||||
inline Transform(const QMatrix& other);
|
||||
inline Transform& operator=(const QMatrix& other);
|
||||
inline QMatrix toQMatrix(void) const;
|
||||
inline Transform(const QTransform& other);
|
||||
inline Transform& operator=(const QTransform& other);
|
||||
inline QTransform toQTransform(void) const;
|
||||
#endif
|
||||
|
||||
/** shortcut for m_matrix(row,col);
|
||||
* \sa MatrixBase::operaror(int,int) const */
|
||||
inline Scalar operator() (int row, int col) const { return m_matrix(row,col); }
|
||||
/** shortcut for m_matrix(row,col);
|
||||
* \sa MatrixBase::operaror(int,int) */
|
||||
inline Scalar& operator() (int row, int col) { return m_matrix(row,col); }
|
||||
|
||||
/** \returns a read-only expression of the transformation matrix */
|
||||
inline const MatrixType& matrix() const { return m_matrix; }
|
||||
/** \returns a writable expression of the transformation matrix */
|
||||
inline MatrixType& matrix() { return m_matrix; }
|
||||
|
||||
/** \returns a read-only expression of the linear (linear) part of the transformation */
|
||||
inline ConstLinearPart linear() const { return m_matrix.template block<Dim,Dim>(0,0); }
|
||||
/** \returns a writable expression of the linear (linear) part of the transformation */
|
||||
inline LinearPart linear() { return m_matrix.template block<Dim,Dim>(0,0); }
|
||||
|
||||
/** \returns a read-only expression of the translation vector of the transformation */
|
||||
inline ConstTranslationPart translation() const { return m_matrix.template block<Dim,1>(0,Dim); }
|
||||
/** \returns a writable expression of the translation vector of the transformation */
|
||||
inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
|
||||
|
||||
/** \returns an expression of the product between the transform \c *this and a matrix expression \a other
|
||||
*
|
||||
* The right hand side \a other might be either:
|
||||
* \li a vector of size Dim,
|
||||
* \li an homogeneous vector of size Dim+1,
|
||||
* \li a transformation matrix of size Dim+1 x Dim+1.
|
||||
*/
|
||||
// note: this function is defined here because some compilers cannot find the respective declaration
|
||||
template<typename OtherDerived>
|
||||
inline const typename ei_transform_product_impl<OtherDerived,_Dim,_Dim+1>::ResultType
|
||||
operator * (const MatrixBase<OtherDerived> &other) const
|
||||
{ return ei_transform_product_impl<OtherDerived,Dim,HDim>::run(*this,other.derived()); }
|
||||
|
||||
/** \returns the product expression of a transformation matrix \a a times a transform \a b
|
||||
* The transformation matrix \a a must have a Dim+1 x Dim+1 sizes. */
|
||||
template<typename OtherDerived>
|
||||
friend inline const typename ProductReturnType<OtherDerived,MatrixType>::Type
|
||||
operator * (const MatrixBase<OtherDerived> &a, const Transform &b)
|
||||
{ return a.derived() * b.matrix(); }
|
||||
|
||||
/** Contatenates two transformations */
|
||||
inline const Transform
|
||||
operator * (const Transform& other) const
|
||||
{ return Transform(m_matrix * other.matrix()); }
|
||||
|
||||
/** \sa MatrixBase::setIdentity() */
|
||||
void setIdentity() { m_matrix.setIdentity(); }
|
||||
static const typename MatrixType::IdentityReturnType Identity()
|
||||
{
|
||||
return MatrixType::Identity();
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& scale(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& prescale(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
inline Transform& scale(Scalar s);
|
||||
inline Transform& prescale(Scalar s);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& translate(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
|
||||
|
||||
template<typename RotationType>
|
||||
inline Transform& rotate(const RotationType& rotation);
|
||||
|
||||
template<typename RotationType>
|
||||
inline Transform& prerotate(const RotationType& rotation);
|
||||
|
||||
Transform& shear(Scalar sx, Scalar sy);
|
||||
Transform& preshear(Scalar sx, Scalar sy);
|
||||
|
||||
inline Transform& operator=(const TranslationType& t);
|
||||
inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
|
||||
inline Transform operator*(const TranslationType& t) const;
|
||||
|
||||
inline Transform& operator=(const ScalingType& t);
|
||||
inline Transform& operator*=(const ScalingType& s) { return scale(s.coeffs()); }
|
||||
inline Transform operator*(const ScalingType& s) const;
|
||||
friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t)
|
||||
{
|
||||
Transform res = t;
|
||||
res.matrix().row(Dim) = t.matrix().row(Dim);
|
||||
res.matrix().template block<Dim,HDim>(0,0) = (mat * t.matrix().template block<Dim,HDim>(0,0)).lazy();
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline Transform& operator=(const RotationBase<Derived,Dim>& r);
|
||||
template<typename Derived>
|
||||
inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
|
||||
template<typename Derived>
|
||||
inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
|
||||
|
||||
LinearMatrixType rotation() const;
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
|
||||
|
||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||
Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
|
||||
|
||||
inline const MatrixType inverse(TransformTraits traits = Affine) const;
|
||||
|
||||
/** \returns a const pointer to the column major internal matrix */
|
||||
const Scalar* data() const { return m_matrix.data(); }
|
||||
/** \returns a non-const pointer to the column major internal matrix */
|
||||
Scalar* data() { return m_matrix.data(); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Transform(const Transform<OtherScalarType,Dim>& other)
|
||||
{ m_matrix = other.matrix().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_matrix.isApprox(other.m_matrix, prec); }
|
||||
|
||||
#ifdef EIGEN_TRANSFORM_PLUGIN
|
||||
#include EIGEN_TRANSFORM_PLUGIN
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<float,2> Transform2f;
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<float,3> Transform3f;
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<double,2> Transform2d;
|
||||
/** \ingroup Geometry_Module */
|
||||
typedef Transform<double,3> Transform3d;
|
||||
|
||||
/**************************
|
||||
*** Optional QT support ***
|
||||
**************************/
|
||||
|
||||
#ifdef EIGEN_QT_SUPPORT
|
||||
/** Initialises \c *this from a QMatrix assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>::Transform(const QMatrix& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
/** Set \c *this from a QMatrix assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QMatrix& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix << other.m11(), other.m21(), other.dx(),
|
||||
other.m12(), other.m22(), other.dy(),
|
||||
0, 0, 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns a QMatrix from \c *this assuming the dimension is 2.
|
||||
*
|
||||
* \warning this convertion might loss data if \c *this is not affine
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
QMatrix Transform<Scalar,Dim>::toQMatrix(void) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
|
||||
m_matrix.coeff(0,1), m_matrix.coeff(1,1),
|
||||
m_matrix.coeff(0,2), m_matrix.coeff(1,2));
|
||||
}
|
||||
|
||||
/** Initialises \c *this from a QTransform assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>::Transform(const QTransform& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
/** Set \c *this from a QTransform assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix << other.m11(), other.m21(), other.dx(),
|
||||
other.m12(), other.m22(), other.dy(),
|
||||
other.m13(), other.m23(), other.m33();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns a QTransform from \c *this assuming the dimension is 2.
|
||||
*
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
QTransform Transform<Scalar,Dim>::toQTransform(void) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
|
||||
m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
|
||||
m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
*** Procedural API ***
|
||||
*********************/
|
||||
|
||||
/** Applies on the right the non uniform scale transformation represented
|
||||
* by the vector \a other to \c *this and returns a reference to \c *this.
|
||||
* \sa prescale()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::scale(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
linear() = (linear() * other.asDiagonal()).lazy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the right a uniform scale of a factor \a c to \c *this
|
||||
* and returns a reference to \c *this.
|
||||
* \sa prescale(Scalar)
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::scale(Scalar s)
|
||||
{
|
||||
linear() *= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left the non uniform scale transformation represented
|
||||
* by the vector \a other to \c *this and returns a reference to \c *this.
|
||||
* \sa scale()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::prescale(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
m_matrix.template block<Dim,HDim>(0,0) = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0)).lazy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left a uniform scale of a factor \a c to \c *this
|
||||
* and returns a reference to \c *this.
|
||||
* \sa scale(Scalar)
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::prescale(Scalar s)
|
||||
{
|
||||
m_matrix.template corner<Dim,HDim>(TopLeft) *= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the right the translation matrix represented by the vector \a other
|
||||
* to \c *this and returns a reference to \c *this.
|
||||
* \sa pretranslate()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::translate(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
translation() += linear() * other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left the translation matrix represented by the vector \a other
|
||||
* to \c *this and returns a reference to \c *this.
|
||||
* \sa translate()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::pretranslate(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
|
||||
translation() += other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the right the rotation represented by the rotation \a rotation
|
||||
* to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* The template parameter \a RotationType is the type of the rotation which
|
||||
* must be known by ei_toRotationMatrix<>.
|
||||
*
|
||||
* Natively supported types includes:
|
||||
* - any scalar (2D),
|
||||
* - a Dim x Dim matrix expression,
|
||||
* - a Quaternion (3D),
|
||||
* - a AngleAxis (3D)
|
||||
*
|
||||
* This mechanism is easily extendable to support user types such as Euler angles,
|
||||
* or a pair of Quaternion for 4D rotations.
|
||||
*
|
||||
* \sa rotate(Scalar), class Quaternion, class AngleAxis, prerotate(RotationType)
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename RotationType>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::rotate(const RotationType& rotation)
|
||||
{
|
||||
linear() *= ei_toRotationMatrix<Scalar,Dim>(rotation);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left the rotation represented by the rotation \a rotation
|
||||
* to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* See rotate() for further details.
|
||||
*
|
||||
* \sa rotate()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename RotationType>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::prerotate(const RotationType& rotation)
|
||||
{
|
||||
m_matrix.template block<Dim,HDim>(0,0) = ei_toRotationMatrix<Scalar,Dim>(rotation)
|
||||
* m_matrix.template block<Dim,HDim>(0,0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the right the shear transformation represented
|
||||
* by the vector \a other to \c *this and returns a reference to \c *this.
|
||||
* \warning 2D only.
|
||||
* \sa preshear()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::shear(Scalar sx, Scalar sy)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
VectorType tmp = linear().col(0)*sy + linear().col(1);
|
||||
linear() << linear().col(0) + linear().col(1)*sx, tmp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies on the left the shear transformation represented
|
||||
* by the vector \a other to \c *this and returns a reference to \c *this.
|
||||
* \warning 2D only.
|
||||
* \sa shear()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
*** Scaling, Translation and Rotation compatibility ***
|
||||
******************************************************/
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const TranslationType& t)
|
||||
{
|
||||
linear().setIdentity();
|
||||
translation() = t.vector();
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const TranslationType& t) const
|
||||
{
|
||||
Transform res = *this;
|
||||
res.translate(t.vector());
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const ScalingType& s)
|
||||
{
|
||||
m_matrix.setZero();
|
||||
linear().diagonal() = s.coeffs();
|
||||
m_matrix.coeffRef(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType& s) const
|
||||
{
|
||||
Transform res = *this;
|
||||
res.scale(s.coeffs());
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const RotationBase<Derived,Dim>& r)
|
||||
{
|
||||
linear() = ei_toRotationMatrix<Scalar,Dim>(r);
|
||||
translation().setZero();
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix.coeffRef(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename Derived>
|
||||
inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{
|
||||
Transform res = *this;
|
||||
res.rotate(r.derived());
|
||||
return res;
|
||||
}
|
||||
|
||||
/************************
|
||||
*** Special functions ***
|
||||
************************/
|
||||
|
||||
/** \returns the rotation part of the transformation
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeRotationScaling(), computeScalingRotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
typename Transform<Scalar,Dim>::LinearMatrixType
|
||||
Transform<Scalar,Dim>::rotation() const
|
||||
{
|
||||
LinearMatrixType result;
|
||||
computeRotationScaling(&result, (LinearMatrixType*)0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeScalingRotation(), rotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename RotationMatrixType, typename ScalingMatrixType>
|
||||
void Transform<Scalar,Dim>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
|
||||
{
|
||||
JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU|ComputeFullV);
|
||||
Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, Dim, 1> sv(svd.singularValues());
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling)
|
||||
{
|
||||
scaling->noalias() = svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint();
|
||||
}
|
||||
if(rotation)
|
||||
{
|
||||
LinearMatrixType m(svd.matrixU());
|
||||
m.col(0) /= x;
|
||||
rotation->noalias() = m * svd.matrixV().adjoint();
|
||||
}
|
||||
}
|
||||
|
||||
/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
|
||||
* not necessarily positive.
|
||||
*
|
||||
* If either pointer is zero, the corresponding computation is skipped.
|
||||
*
|
||||
* \nonstableyet
|
||||
*
|
||||
* \svd_module
|
||||
*
|
||||
* \sa computeRotationScaling(), rotation(), class SVD
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename ScalingMatrixType, typename RotationMatrixType>
|
||||
void Transform<Scalar,Dim>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
|
||||
{
|
||||
JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU|ComputeFullV);
|
||||
Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
|
||||
Matrix<Scalar, Dim, 1> sv(svd.singularValues());
|
||||
sv.coeffRef(0) *= x;
|
||||
if(scaling)
|
||||
{
|
||||
scaling->noalias() = svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint();
|
||||
}
|
||||
if(rotation)
|
||||
{
|
||||
LinearMatrixType m(svd.matrixU());
|
||||
m.col(0) /= x;
|
||||
rotation->noalias() = m * svd.matrixV().adjoint();
|
||||
}
|
||||
}
|
||||
|
||||
/** Convenient method to set \c *this from a position, orientation and scale
|
||||
* of a 3D object.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
|
||||
Transform<Scalar,Dim>&
|
||||
Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
|
||||
const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
|
||||
{
|
||||
linear() = ei_toRotationMatrix<Scalar,Dim>(orientation);
|
||||
linear() *= scale.asDiagonal();
|
||||
translation() = position;
|
||||
m_matrix.template block<1,Dim>(Dim,0).setZero();
|
||||
m_matrix(Dim,Dim) = Scalar(1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \nonstableyet
|
||||
*
|
||||
* \returns the inverse transformation matrix according to some given knowledge
|
||||
* on \c *this.
|
||||
*
|
||||
* \param traits allows to optimize the inversion process when the transformion
|
||||
* is known to be not a general transformation. The possible values are:
|
||||
* - Projective if the transformation is not necessarily affine, i.e., if the
|
||||
* last row is not guaranteed to be [0 ... 0 1]
|
||||
* - Affine is the default, the last row is assumed to be [0 ... 0 1]
|
||||
* - Isometry if the transformation is only a concatenations of translations
|
||||
* and rotations.
|
||||
*
|
||||
* \warning unless \a traits is always set to NoShear or NoScaling, this function
|
||||
* requires the generic inverse method of MatrixBase defined in the LU module. If
|
||||
* you forget to include this module, then you will get hard to debug linking errors.
|
||||
*
|
||||
* \sa MatrixBase::inverse()
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
inline const typename Transform<Scalar,Dim>::MatrixType
|
||||
Transform<Scalar,Dim>::inverse(TransformTraits traits) const
|
||||
{
|
||||
if (traits == Projective)
|
||||
{
|
||||
return m_matrix.inverse();
|
||||
}
|
||||
else
|
||||
{
|
||||
MatrixType res;
|
||||
if (traits == Affine)
|
||||
{
|
||||
res.template corner<Dim,Dim>(TopLeft) = linear().inverse();
|
||||
}
|
||||
else if (traits == Isometry)
|
||||
{
|
||||
res.template corner<Dim,Dim>(TopLeft) = linear().transpose();
|
||||
}
|
||||
else
|
||||
{
|
||||
ei_assert("invalid traits value in Transform::inverse()");
|
||||
}
|
||||
// translation and remaining parts
|
||||
res.template corner<Dim,1>(TopRight) = - res.template corner<Dim,Dim>(TopLeft) * translation();
|
||||
res.template corner<1,Dim>(BottomLeft).setZero();
|
||||
res.coeffRef(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
*** Specializations of operator* with a MatrixBase ***
|
||||
*****************************************************/
|
||||
|
||||
template<typename Other, int Dim, int HDim>
|
||||
struct ei_transform_product_impl<Other,Dim,HDim, HDim,HDim>
|
||||
{
|
||||
typedef Transform<typename Other::Scalar,Dim> TransformType;
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
|
||||
static ResultType run(const TransformType& tr, const Other& other)
|
||||
{ return tr.matrix() * other; }
|
||||
};
|
||||
|
||||
template<typename Other, int Dim, int HDim>
|
||||
struct ei_transform_product_impl<Other,Dim,HDim, Dim,Dim>
|
||||
{
|
||||
typedef Transform<typename Other::Scalar,Dim> TransformType;
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
typedef TransformType ResultType;
|
||||
static ResultType run(const TransformType& tr, const Other& other)
|
||||
{
|
||||
TransformType res;
|
||||
res.translation() = tr.translation();
|
||||
res.matrix().row(Dim) = tr.matrix().row(Dim);
|
||||
res.linear() = (tr.linear() * other).lazy();
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Other, int Dim, int HDim>
|
||||
struct ei_transform_product_impl<Other,Dim,HDim, HDim,1>
|
||||
{
|
||||
typedef Transform<typename Other::Scalar,Dim> TransformType;
|
||||
typedef typename TransformType::MatrixType MatrixType;
|
||||
typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
|
||||
static ResultType run(const TransformType& tr, const Other& other)
|
||||
{ return tr.matrix() * other; }
|
||||
};
|
||||
|
||||
template<typename Other, int Dim, int HDim>
|
||||
struct ei_transform_product_impl<Other,Dim,HDim, Dim,1>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
typedef Transform<Scalar,Dim> TransformType;
|
||||
typedef Matrix<Scalar,Dim,1> ResultType;
|
||||
static ResultType run(const TransformType& tr, const Other& other)
|
||||
{ return ((tr.linear() * other) + tr.translation())
|
||||
* (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); }
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.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/.
|
||||
|
||||
// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Translation
|
||||
*
|
||||
* \brief Represents a translation transformation
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
* \param _Dim the dimension of the space, can be a compile time value or Dynamic
|
||||
*
|
||||
* \note This class is not aimed to be used to store a translation transformation,
|
||||
* but rather to make easier the constructions and updates of Transform objects.
|
||||
*
|
||||
* \sa class Scaling, class Transform
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Translation
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim)
|
||||
/** dimension of the space */
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
/** corresponding vector type */
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
/** corresponding linear transformation matrix type */
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
|
||||
/** corresponding scaling transformation type */
|
||||
typedef Scaling<Scalar,Dim> ScalingType;
|
||||
/** corresponding affine transformation type */
|
||||
typedef Transform<Scalar,Dim> TransformType;
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_coeffs;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
Translation() {}
|
||||
/** */
|
||||
inline Translation(const Scalar& sx, const Scalar& sy)
|
||||
{
|
||||
ei_assert(Dim==2);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
}
|
||||
/** */
|
||||
inline Translation(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
{
|
||||
ei_assert(Dim==3);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
m_coeffs.z() = sz;
|
||||
}
|
||||
/** Constructs and initialize the scaling transformation from a vector of scaling coefficients */
|
||||
explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {}
|
||||
|
||||
const VectorType& vector() const { return m_coeffs; }
|
||||
VectorType& vector() { return m_coeffs; }
|
||||
|
||||
/** Concatenates two translation */
|
||||
inline Translation operator* (const Translation& other) const
|
||||
{ return Translation(m_coeffs + other.m_coeffs); }
|
||||
|
||||
/** Concatenates a translation and a scaling */
|
||||
inline TransformType operator* (const ScalingType& other) const;
|
||||
|
||||
/** Concatenates a translation and a linear transformation */
|
||||
inline TransformType operator* (const LinearMatrixType& linear) const;
|
||||
|
||||
template<typename Derived>
|
||||
inline TransformType operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{ return *this * r.toRotationMatrix(); }
|
||||
|
||||
/** Concatenates a linear transformation and a translation */
|
||||
// its a nightmare to define a templated friend function outside its declaration
|
||||
friend inline TransformType operator* (const LinearMatrixType& linear, const Translation& t)
|
||||
{
|
||||
TransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear() = linear;
|
||||
res.translation() = linear * t.m_coeffs;
|
||||
res.matrix().row(Dim).setZero();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Concatenates a translation and an affine transformation */
|
||||
inline TransformType operator* (const TransformType& t) const;
|
||||
|
||||
/** Applies translation to vector */
|
||||
inline VectorType operator* (const VectorType& other) const
|
||||
{ return m_coeffs + other; }
|
||||
|
||||
/** \returns the inverse translation (opposite) */
|
||||
Translation inverse() const { return Translation(-m_coeffs); }
|
||||
|
||||
Translation& operator=(const Translation& other)
|
||||
{
|
||||
m_coeffs = other.m_coeffs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Translation(const Translation<OtherScalarType,Dim>& other)
|
||||
{ m_coeffs = other.vector().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
bool isApprox(const Translation& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Translation<float, 2> Translation2f;
|
||||
typedef Translation<double,2> Translation2d;
|
||||
typedef Translation<float, 3> Translation3f;
|
||||
typedef Translation<double,3> Translation3d;
|
||||
//@}
|
||||
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Translation<Scalar,Dim>::TransformType
|
||||
Translation<Scalar,Dim>::operator* (const ScalingType& other) const
|
||||
{
|
||||
TransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear().diagonal() = other.coeffs();
|
||||
res.translation() = m_coeffs;
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Translation<Scalar,Dim>::TransformType
|
||||
Translation<Scalar,Dim>::operator* (const LinearMatrixType& linear) const
|
||||
{
|
||||
TransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear() = linear;
|
||||
res.translation() = m_coeffs;
|
||||
res.matrix().row(Dim).setZero();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Translation<Scalar,Dim>::TransformType
|
||||
Translation<Scalar,Dim>::operator* (const TransformType& t) const
|
||||
{
|
||||
TransformType res = t;
|
||||
res.pretranslate(m_coeffs);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 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 EIGEN2_LU_H
|
||||
#define EIGEN2_LU_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename MatrixType>
|
||||
class LU : public FullPivLU<MatrixType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
typedef Matrix<int, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> IntRowVectorType;
|
||||
typedef Matrix<int, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> IntColVectorType;
|
||||
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime, MatrixType::Options, 1, MatrixType::MaxColsAtCompileTime> RowVectorType;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1, MatrixType::Options, MatrixType::MaxRowsAtCompileTime, 1> ColVectorType;
|
||||
|
||||
typedef Matrix<typename MatrixType::Scalar,
|
||||
MatrixType::ColsAtCompileTime, // the number of rows in the "kernel matrix" is the number of cols of the original matrix
|
||||
// so that the product "matrix * kernel = zero" makes sense
|
||||
Dynamic, // we don't know at compile-time the dimension of the kernel
|
||||
MatrixType::Options,
|
||||
MatrixType::MaxColsAtCompileTime, // see explanation for 2nd template parameter
|
||||
MatrixType::MaxColsAtCompileTime // the kernel is a subspace of the domain space, whose dimension is the number
|
||||
// of columns of the original matrix
|
||||
> KernelResultType;
|
||||
|
||||
typedef Matrix<typename MatrixType::Scalar,
|
||||
MatrixType::RowsAtCompileTime, // the image is a subspace of the destination space, whose dimension is the number
|
||||
// of rows of the original matrix
|
||||
Dynamic, // we don't know at compile time the dimension of the image (the rank)
|
||||
MatrixType::Options,
|
||||
MatrixType::MaxRowsAtCompileTime, // the image matrix will consist of columns from the original matrix,
|
||||
MatrixType::MaxColsAtCompileTime // so it has the same number of rows and at most as many columns.
|
||||
> ImageResultType;
|
||||
|
||||
typedef FullPivLU<MatrixType> Base;
|
||||
|
||||
template<typename T>
|
||||
explicit LU(const T& t) : Base(t), m_originalMatrix(t) {}
|
||||
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
|
||||
{
|
||||
*result = static_cast<const Base*>(this)->solve(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename ResultType>
|
||||
inline void computeInverse(ResultType *result) const
|
||||
{
|
||||
solve(MatrixType::Identity(this->rows(), this->cols()), result);
|
||||
}
|
||||
|
||||
template<typename KernelMatrixType>
|
||||
void computeKernel(KernelMatrixType *result) const
|
||||
{
|
||||
*result = static_cast<const Base*>(this)->kernel();
|
||||
}
|
||||
|
||||
template<typename ImageMatrixType>
|
||||
void computeImage(ImageMatrixType *result) const
|
||||
{
|
||||
*result = static_cast<const Base*>(this)->image(m_originalMatrix);
|
||||
}
|
||||
|
||||
const ImageResultType image() const
|
||||
{
|
||||
return static_cast<const Base*>(this)->image(m_originalMatrix);
|
||||
}
|
||||
|
||||
const MatrixType& m_originalMatrix;
|
||||
};
|
||||
|
||||
#if EIGEN2_SUPPORT_STAGE < STAGE20_RESOLVE_API_CONFLICTS
|
||||
/** \lu_module
|
||||
*
|
||||
* Synonym of partialPivLu().
|
||||
*
|
||||
* \return the partial-pivoting LU decomposition of \c *this.
|
||||
*
|
||||
* \sa class PartialPivLU
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const LU<typename MatrixBase<Derived>::PlainObject>
|
||||
MatrixBase<Derived>::lu() const
|
||||
{
|
||||
return LU<PlainObject>(eval());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN2_SUPPORT
|
||||
/** \lu_module
|
||||
*
|
||||
* Synonym of partialPivLu().
|
||||
*
|
||||
* \return the partial-pivoting LU decomposition of \c *this.
|
||||
*
|
||||
* \sa class PartialPivLU
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const LU<typename MatrixBase<Derived>::PlainObject>
|
||||
MatrixBase<Derived>::eigen2_lu() const
|
||||
{
|
||||
return LU<PlainObject>(eval());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_LU_H
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 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_LAZY_H
|
||||
#define EIGEN_LAZY_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \deprecated it is only used by lazy() which is deprecated
|
||||
*
|
||||
* \returns an expression of *this with added flags
|
||||
*
|
||||
* Example: \include MatrixBase_marked.cpp
|
||||
* Output: \verbinclude MatrixBase_marked.out
|
||||
*
|
||||
* \sa class Flagged, extract(), part()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<unsigned int Added>
|
||||
inline const Flagged<Derived, Added, 0>
|
||||
MatrixBase<Derived>::marked() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \deprecated use MatrixBase::noalias()
|
||||
*
|
||||
* \returns an expression of *this with the EvalBeforeAssigningBit flag removed.
|
||||
*
|
||||
* Example: \include MatrixBase_lazy.cpp
|
||||
* Output: \verbinclude MatrixBase_lazy.out
|
||||
*
|
||||
* \sa class Flagged, marked()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline const Flagged<Derived, 0, EvalBeforeAssigningBit>
|
||||
MatrixBase<Derived>::lazy() const
|
||||
{
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
/** \internal
|
||||
* Overloaded to perform an efficient C += (A*B).lazy() */
|
||||
template<typename Derived>
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
Derived& MatrixBase<Derived>::operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
|
||||
EvalBeforeAssigningBit>& other)
|
||||
{
|
||||
other._expression().derived().addTo(derived()); return derived();
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* Overloaded to perform an efficient C -= (A*B).lazy() */
|
||||
template<typename Derived>
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
Derived& MatrixBase<Derived>::operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0,
|
||||
EvalBeforeAssigningBit>& other)
|
||||
{
|
||||
other._expression().derived().subTo(derived()); return derived();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_LAZY_H
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
// 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>
|
||||
//
|
||||
// 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 EIGEN2_LEASTSQUARES_H
|
||||
#define EIGEN2_LEASTSQUARES_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \ingroup LeastSquares_Module
|
||||
*
|
||||
* \leastsquares_module
|
||||
*
|
||||
* For a set of points, this function tries to express
|
||||
* one of the coords as a linear (affine) function of the other coords.
|
||||
*
|
||||
* This is best explained by an example. This function works in full
|
||||
* generality, for points in a space of arbitrary dimension, and also over
|
||||
* the complex numbers, but for this example we will work in dimension 3
|
||||
* over the real numbers (doubles).
|
||||
*
|
||||
* So let us work with the following set of 5 points given by their
|
||||
* \f$(x,y,z)\f$ coordinates:
|
||||
* @code
|
||||
Vector3d points[5];
|
||||
points[0] = Vector3d( 3.02, 6.89, -4.32 );
|
||||
points[1] = Vector3d( 2.01, 5.39, -3.79 );
|
||||
points[2] = Vector3d( 2.41, 6.01, -4.01 );
|
||||
points[3] = Vector3d( 2.09, 5.55, -3.86 );
|
||||
points[4] = Vector3d( 2.58, 6.32, -4.10 );
|
||||
* @endcode
|
||||
* Suppose that we want to express the second coordinate (\f$y\f$) as a linear
|
||||
* expression in \f$x\f$ and \f$z\f$, that is,
|
||||
* \f[ y=ax+bz+c \f]
|
||||
* for some constants \f$a,b,c\f$. Thus, we want to find the best possible
|
||||
* constants \f$a,b,c\f$ so that the plane of equation \f$y=ax+bz+c\f$ fits
|
||||
* best the five above points. To do that, call this function as follows:
|
||||
* @code
|
||||
Vector3d coeffs; // will store the coefficients a, b, c
|
||||
linearRegression(
|
||||
5,
|
||||
&points,
|
||||
&coeffs,
|
||||
1 // the coord to express as a function of
|
||||
// the other ones. 0 means x, 1 means y, 2 means z.
|
||||
);
|
||||
* @endcode
|
||||
* Now the vector \a coeffs is approximately
|
||||
* \f$( 0.495 , -1.927 , -2.906 )\f$.
|
||||
* Thus, we get \f$a=0.495, b = -1.927, c = -2.906\f$. Let us check for
|
||||
* instance how near points[0] is from the plane of equation \f$y=ax+bz+c\f$.
|
||||
* Looking at the coords of points[0], we see that:
|
||||
* \f[ax+bz+c = 0.495 * 3.02 + (-1.927) * (-4.32) + (-2.906) = 6.91.\f]
|
||||
* On the other hand, we have \f$y=6.89\f$. We see that the values
|
||||
* \f$6.91\f$ and \f$6.89\f$
|
||||
* are near, so points[0] is very near the plane of equation \f$y=ax+bz+c\f$.
|
||||
*
|
||||
* Let's now describe precisely the parameters:
|
||||
* @param numPoints the number of points
|
||||
* @param points the array of pointers to the points on which to perform the linear regression
|
||||
* @param result pointer to the vector in which to store the result.
|
||||
This vector must be of the same type and size as the
|
||||
data points. The meaning of its coords is as follows.
|
||||
For brevity, let \f$n=Size\f$,
|
||||
\f$r_i=result[i]\f$,
|
||||
and \f$f=funcOfOthers\f$. Denote by
|
||||
\f$x_0,\ldots,x_{n-1}\f$
|
||||
the n coordinates in the n-dimensional space.
|
||||
Then the resulting equation is:
|
||||
\f[ x_f = r_0 x_0 + \cdots + r_{f-1}x_{f-1}
|
||||
+ r_{f+1}x_{f+1} + \cdots + r_{n-1}x_{n-1} + r_n. \f]
|
||||
* @param funcOfOthers Determines which coord to express as a function of the
|
||||
others. Coords are numbered starting from 0, so that a
|
||||
value of 0 means \f$x\f$, 1 means \f$y\f$,
|
||||
2 means \f$z\f$, ...
|
||||
*
|
||||
* \sa fitHyperplane()
|
||||
*/
|
||||
template<typename VectorType>
|
||||
void linearRegression(int numPoints,
|
||||
VectorType **points,
|
||||
VectorType *result,
|
||||
int funcOfOthers )
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
typedef Hyperplane<Scalar, VectorType::SizeAtCompileTime> HyperplaneType;
|
||||
const int size = points[0]->size();
|
||||
result->resize(size);
|
||||
HyperplaneType h(size);
|
||||
fitHyperplane(numPoints, points, &h);
|
||||
for(int i = 0; i < funcOfOthers; i++)
|
||||
result->coeffRef(i) = - h.coeffs()[i] / h.coeffs()[funcOfOthers];
|
||||
for(int i = funcOfOthers; i < size; i++)
|
||||
result->coeffRef(i) = - h.coeffs()[i+1] / h.coeffs()[funcOfOthers];
|
||||
}
|
||||
|
||||
/** \ingroup LeastSquares_Module
|
||||
*
|
||||
* \leastsquares_module
|
||||
*
|
||||
* This function is quite similar to linearRegression(), so we refer to the
|
||||
* documentation of this function and only list here the differences.
|
||||
*
|
||||
* The main difference from linearRegression() is that this function doesn't
|
||||
* take a \a funcOfOthers argument. Instead, it finds a general equation
|
||||
* of the form
|
||||
* \f[ r_0 x_0 + \cdots + r_{n-1}x_{n-1} + r_n = 0, \f]
|
||||
* where \f$n=Size\f$, \f$r_i=retCoefficients[i]\f$, and we denote by
|
||||
* \f$x_0,\ldots,x_{n-1}\f$ the n coordinates in the n-dimensional space.
|
||||
*
|
||||
* Thus, the vector \a retCoefficients has size \f$n+1\f$, which is another
|
||||
* difference from linearRegression().
|
||||
*
|
||||
* In practice, this function performs an hyper-plane fit in a total least square sense
|
||||
* via the following steps:
|
||||
* 1 - center the data to the mean
|
||||
* 2 - compute the covariance matrix
|
||||
* 3 - pick the eigenvector corresponding to the smallest eigenvalue of the covariance matrix
|
||||
* The ratio of the smallest eigenvalue and the second one gives us a hint about the relevance
|
||||
* of the solution. This value is optionally returned in \a soundness.
|
||||
*
|
||||
* \sa linearRegression()
|
||||
*/
|
||||
template<typename VectorType, typename HyperplaneType>
|
||||
void fitHyperplane(int numPoints,
|
||||
VectorType **points,
|
||||
HyperplaneType *result,
|
||||
typename NumTraits<typename VectorType::Scalar>::Real* soundness = 0)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
typedef Matrix<Scalar,VectorType::SizeAtCompileTime,VectorType::SizeAtCompileTime> CovMatrixType;
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType)
|
||||
ei_assert(numPoints >= 1);
|
||||
int size = points[0]->size();
|
||||
ei_assert(size+1 == result->coeffs().size());
|
||||
|
||||
// compute the mean of the data
|
||||
VectorType mean = VectorType::Zero(size);
|
||||
for(int i = 0; i < numPoints; ++i)
|
||||
mean += *(points[i]);
|
||||
mean /= numPoints;
|
||||
|
||||
// compute the covariance matrix
|
||||
CovMatrixType covMat = CovMatrixType::Zero(size, size);
|
||||
for(int i = 0; i < numPoints; ++i)
|
||||
{
|
||||
VectorType diff = (*(points[i]) - mean).conjugate();
|
||||
covMat += diff * diff.adjoint();
|
||||
}
|
||||
|
||||
// now we just have to pick the eigen vector with smallest eigen value
|
||||
SelfAdjointEigenSolver<CovMatrixType> eig(covMat);
|
||||
result->normal() = eig.eigenvectors().col(0);
|
||||
if (soundness)
|
||||
*soundness = eig.eigenvalues().coeff(0)/eig.eigenvalues().coeff(1);
|
||||
|
||||
// let's compute the constant coefficient such that the
|
||||
// plane pass trough the mean point:
|
||||
result->offset() = - (result->normal().cwise()* mean).sum();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_LEASTSQUARES_H
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 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 EIGEN2_MACROS_H
|
||||
#define EIGEN2_MACROS_H
|
||||
|
||||
#define ei_assert eigen_assert
|
||||
#define ei_internal_assert eigen_internal_assert
|
||||
|
||||
#define EIGEN_ALIGN_128 EIGEN_ALIGN16
|
||||
|
||||
#define EIGEN_ARCH_WANTS_ALIGNMENT EIGEN_ALIGN_STATICALLY
|
||||
|
||||
#endif // EIGEN2_MACROS_H
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 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 EIGEN2_MATH_FUNCTIONS_H
|
||||
#define EIGEN2_MATH_FUNCTIONS_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename T> inline typename NumTraits<T>::Real ei_real(const T& x) { return numext::real(x); }
|
||||
template<typename T> inline typename NumTraits<T>::Real ei_imag(const T& x) { return numext::imag(x); }
|
||||
template<typename T> inline T ei_conj(const T& x) { return numext::conj(x); }
|
||||
template<typename T> inline typename NumTraits<T>::Real ei_abs (const T& x) { using std::abs; return abs(x); }
|
||||
template<typename T> inline typename NumTraits<T>::Real ei_abs2(const T& x) { return numext::abs2(x); }
|
||||
template<typename T> inline T ei_sqrt(const T& x) { using std::sqrt; return sqrt(x); }
|
||||
template<typename T> inline T ei_exp (const T& x) { using std::exp; return exp(x); }
|
||||
template<typename T> inline T ei_log (const T& x) { using std::log; return log(x); }
|
||||
template<typename T> inline T ei_sin (const T& x) { using std::sin; return sin(x); }
|
||||
template<typename T> inline T ei_cos (const T& x) { using std::cos; return cos(x); }
|
||||
template<typename T> inline T ei_atan2(const T& x,const T& y) { using std::atan2; return atan2(x,y); }
|
||||
template<typename T> inline T ei_pow (const T& x,const T& y) { return numext::pow(x,y); }
|
||||
template<typename T> inline T ei_random () { return internal::random<T>(); }
|
||||
template<typename T> inline T ei_random (const T& x, const T& y) { return internal::random(x, y); }
|
||||
|
||||
template<typename T> inline T precision () { return NumTraits<T>::dummy_precision(); }
|
||||
template<typename T> inline T machine_epsilon () { return NumTraits<T>::epsilon(); }
|
||||
|
||||
|
||||
template<typename Scalar, typename OtherScalar>
|
||||
inline bool ei_isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
|
||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
||||
{
|
||||
return internal::isMuchSmallerThan(x, y, precision);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
inline bool ei_isApprox(const Scalar& x, const Scalar& y,
|
||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
||||
{
|
||||
return internal::isApprox(x, y, precision);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
inline bool ei_isApproxOrLessThan(const Scalar& x, const Scalar& y,
|
||||
typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
|
||||
{
|
||||
return internal::isApproxOrLessThan(x, y, precision);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_MATH_FUNCTIONS_H
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 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 EIGEN2_MEMORY_H
|
||||
#define EIGEN2_MEMORY_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
inline void* ei_aligned_malloc(size_t size) { return internal::aligned_malloc(size); }
|
||||
inline void ei_aligned_free(void *ptr) { internal::aligned_free(ptr); }
|
||||
inline void* ei_aligned_realloc(void *ptr, size_t new_size, size_t old_size) { return internal::aligned_realloc(ptr, new_size, old_size); }
|
||||
inline void* ei_handmade_aligned_malloc(size_t size) { return internal::handmade_aligned_malloc(size); }
|
||||
inline void ei_handmade_aligned_free(void *ptr) { internal::handmade_aligned_free(ptr); }
|
||||
|
||||
template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
|
||||
{
|
||||
return internal::conditional_aligned_malloc<Align>(size);
|
||||
}
|
||||
template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
|
||||
{
|
||||
internal::conditional_aligned_free<Align>(ptr);
|
||||
}
|
||||
template<bool Align> inline void* ei_conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
|
||||
{
|
||||
return internal::conditional_aligned_realloc<Align>(ptr, new_size, old_size);
|
||||
}
|
||||
|
||||
template<typename T> inline T* ei_aligned_new(size_t size)
|
||||
{
|
||||
return internal::aligned_new<T>(size);
|
||||
}
|
||||
template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
|
||||
{
|
||||
return internal::aligned_delete(ptr, size);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_MACROS_H
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 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 EIGEN2_META_H
|
||||
#define EIGEN2_META_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename T>
|
||||
struct ei_traits : internal::traits<T>
|
||||
{};
|
||||
|
||||
struct ei_meta_true { enum { ret = 1 }; };
|
||||
struct ei_meta_false { enum { ret = 0 }; };
|
||||
|
||||
template<bool Condition, typename Then, typename Else>
|
||||
struct ei_meta_if { typedef Then ret; };
|
||||
|
||||
template<typename Then, typename Else>
|
||||
struct ei_meta_if <false, Then, Else> { typedef Else ret; };
|
||||
|
||||
template<typename T, typename U> struct ei_is_same_type { enum { ret = 0 }; };
|
||||
template<typename T> struct ei_is_same_type<T,T> { enum { ret = 1 }; };
|
||||
|
||||
template<typename T> struct ei_unref { typedef T type; };
|
||||
template<typename T> struct ei_unref<T&> { typedef T type; };
|
||||
|
||||
template<typename T> struct ei_unpointer { typedef T type; };
|
||||
template<typename T> struct ei_unpointer<T*> { typedef T type; };
|
||||
template<typename T> struct ei_unpointer<T*const> { typedef T type; };
|
||||
|
||||
template<typename T> struct ei_unconst { typedef T type; };
|
||||
template<typename T> struct ei_unconst<const T> { typedef T type; };
|
||||
template<typename T> struct ei_unconst<T const &> { typedef T & type; };
|
||||
template<typename T> struct ei_unconst<T const *> { typedef T * type; };
|
||||
|
||||
template<typename T> struct ei_cleantype { typedef T type; };
|
||||
template<typename T> struct ei_cleantype<const T> { typedef typename ei_cleantype<T>::type type; };
|
||||
template<typename T> struct ei_cleantype<const T&> { typedef typename ei_cleantype<T>::type type; };
|
||||
template<typename T> struct ei_cleantype<T&> { typedef typename ei_cleantype<T>::type type; };
|
||||
template<typename T> struct ei_cleantype<const T*> { typedef typename ei_cleantype<T>::type type; };
|
||||
template<typename T> struct ei_cleantype<T*> { typedef typename ei_cleantype<T>::type type; };
|
||||
|
||||
/** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
|
||||
* Usage example: \code ei_meta_sqrt<1023>::ret \endcode
|
||||
*/
|
||||
template<int Y,
|
||||
int InfX = 0,
|
||||
int SupX = ((Y==1) ? 1 : Y/2),
|
||||
bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
|
||||
// use ?: instead of || just to shut up a stupid gcc 4.3 warning
|
||||
class ei_meta_sqrt
|
||||
{
|
||||
enum {
|
||||
MidX = (InfX+SupX)/2,
|
||||
TakeInf = MidX*MidX > Y ? 1 : 0,
|
||||
NewInf = int(TakeInf) ? InfX : int(MidX),
|
||||
NewSup = int(TakeInf) ? int(MidX) : SupX
|
||||
};
|
||||
public:
|
||||
enum { ret = ei_meta_sqrt<Y,NewInf,NewSup>::ret };
|
||||
};
|
||||
|
||||
template<int Y, int InfX, int SupX>
|
||||
class ei_meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_META_H
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
// 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>
|
||||
//
|
||||
// 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_MINOR_H
|
||||
#define EIGEN_MINOR_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/**
|
||||
* \class Minor
|
||||
*
|
||||
* \brief Expression of a minor
|
||||
*
|
||||
* \param MatrixType the type of the object in which we are taking a minor
|
||||
*
|
||||
* This class represents an expression of a minor. It is the return
|
||||
* type of MatrixBase::minor() and most of the time this is the only way it
|
||||
* is used.
|
||||
*
|
||||
* \sa MatrixBase::minor()
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
template<typename MatrixType>
|
||||
struct traits<Minor<MatrixType> >
|
||||
: traits<MatrixType>
|
||||
{
|
||||
typedef typename nested<MatrixType>::type MatrixTypeNested;
|
||||
typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
|
||||
typedef typename MatrixType::StorageKind StorageKind;
|
||||
enum {
|
||||
RowsAtCompileTime = (MatrixType::RowsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::RowsAtCompileTime) - 1 : Dynamic,
|
||||
ColsAtCompileTime = (MatrixType::ColsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::ColsAtCompileTime) - 1 : Dynamic,
|
||||
MaxRowsAtCompileTime = (MatrixType::MaxRowsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::MaxRowsAtCompileTime) - 1 : Dynamic,
|
||||
MaxColsAtCompileTime = (MatrixType::MaxColsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::MaxColsAtCompileTime) - 1 : Dynamic,
|
||||
Flags = _MatrixTypeNested::Flags & (HereditaryBits | LvalueBit),
|
||||
CoeffReadCost = _MatrixTypeNested::CoeffReadCost // minor is used typically on tiny matrices,
|
||||
// where loops are unrolled and the 'if' evaluates at compile time
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template<typename MatrixType> class Minor
|
||||
: public MatrixBase<Minor<MatrixType> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef MatrixBase<Minor> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Minor)
|
||||
|
||||
inline Minor(const MatrixType& matrix,
|
||||
Index row, Index col)
|
||||
: m_matrix(matrix), m_row(row), m_col(col)
|
||||
{
|
||||
eigen_assert(row >= 0 && row < matrix.rows()
|
||||
&& col >= 0 && col < matrix.cols());
|
||||
}
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Minor)
|
||||
|
||||
inline Index rows() const { return m_matrix.rows() - 1; }
|
||||
inline Index cols() const { return m_matrix.cols() - 1; }
|
||||
|
||||
inline Scalar& coeffRef(Index row, Index col)
|
||||
{
|
||||
return m_matrix.const_cast_derived().coeffRef(row + (row >= m_row), col + (col >= m_col));
|
||||
}
|
||||
|
||||
inline const Scalar coeff(Index row, Index col) const
|
||||
{
|
||||
return m_matrix.coeff(row + (row >= m_row), col + (col >= m_col));
|
||||
}
|
||||
|
||||
protected:
|
||||
const typename MatrixType::Nested m_matrix;
|
||||
const Index m_row, m_col;
|
||||
};
|
||||
|
||||
/**
|
||||
* \return an expression of the (\a row, \a col)-minor of *this,
|
||||
* i.e. an expression constructed from *this by removing the specified
|
||||
* row and column.
|
||||
*
|
||||
* Example: \include MatrixBase_minor.cpp
|
||||
* Output: \verbinclude MatrixBase_minor.out
|
||||
*
|
||||
* \sa class Minor
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Minor<Derived>
|
||||
MatrixBase<Derived>::minor(Index row, Index col)
|
||||
{
|
||||
return Minor<Derived>(derived(), row, col);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the const version of minor(). */
|
||||
template<typename Derived>
|
||||
inline const Minor<Derived>
|
||||
MatrixBase<Derived>::minor(Index row, Index col) const
|
||||
{
|
||||
return Minor<Derived>(derived(), row, col);
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_MINOR_H
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 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 EIGEN2_QR_H
|
||||
#define EIGEN2_QR_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename MatrixType>
|
||||
class QR : public HouseholderQR<MatrixType>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef HouseholderQR<MatrixType> Base;
|
||||
typedef Block<const MatrixType, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> MatrixRBlockType;
|
||||
|
||||
QR() : Base() {}
|
||||
|
||||
template<typename T>
|
||||
explicit QR(const T& t) : Base(t) {}
|
||||
|
||||
template<typename OtherDerived, typename ResultType>
|
||||
bool solve(const MatrixBase<OtherDerived>& b, ResultType *result) const
|
||||
{
|
||||
*result = static_cast<const Base*>(this)->solve(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
MatrixType matrixQ(void) const {
|
||||
MatrixType ret = MatrixType::Identity(this->rows(), this->cols());
|
||||
ret = this->householderQ() * ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool isFullRank() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
const TriangularView<MatrixRBlockType, UpperTriangular>
|
||||
matrixR(void) const
|
||||
{
|
||||
int cols = this->cols();
|
||||
return MatrixRBlockType(this->matrixQR(), 0, 0, cols, cols).template triangularView<UpperTriangular>();
|
||||
}
|
||||
};
|
||||
|
||||
/** \return the QR decomposition of \c *this.
|
||||
*
|
||||
* \sa class QR
|
||||
*/
|
||||
template<typename Derived>
|
||||
const QR<typename MatrixBase<Derived>::PlainObject>
|
||||
MatrixBase<Derived>::qr() const
|
||||
{
|
||||
return QR<PlainObject>(eval());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN2_QR_H
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue