mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-01-18 17:31:19 +01:00
Merge branch eigen:master into master
This commit is contained in:
@@ -100,15 +100,28 @@ endif()
|
||||
# Version Info.
|
||||
#==============================================================================
|
||||
|
||||
# Automatically parse the version number from header files.
|
||||
file(READ "${PROJECT_SOURCE_DIR}/Eigen/src/Core/util/Macros.h" _eigen_version_header)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen_world_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_WORLD_VERSION "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen_major_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_MAJOR_VERSION "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen_minor_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_MINOR_VERSION "${CMAKE_MATCH_1}")
|
||||
set(EIGEN_VERSION_NUMBER ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})
|
||||
# If version information is not provided, automatically parse the version number
|
||||
# from header files.
|
||||
file(READ "${PROJECT_SOURCE_DIR}/Eigen/Version" _eigen_version_header)
|
||||
if (NOT DEFINED EIGEN_WORLD_VERSION)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen_world_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_WORLD_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
if (NOT DEFINED EIGEN_MAJOR_VERSION)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen_major_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_MAJOR_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
if (NOT DEFINED EIGEN_MINOR_VERSION)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen_minor_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_MINOR_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
if (NOT DEFINED EIGEN_PATCH_VERSION)
|
||||
string(REGEX MATCH "define[ \t]+EIGEN_PATCH_VERSION[ \t]+([0-9]+)" _eigen_patch_version_match "${_eigen_version_header}")
|
||||
set(EIGEN_PATCH_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
if (NOT DEFINED EIGEN_PRERELEASE_VERSION)
|
||||
set(EIGEN_PRERELEASE_VERSION "dev")
|
||||
endif()
|
||||
|
||||
# If we are in a git repo, extract a changeset.
|
||||
if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/.git)
|
||||
@@ -119,16 +132,32 @@ endif()
|
||||
|
||||
# extract the git rev number from the git output...
|
||||
if(EIGEN_GIT_OUTPUT)
|
||||
string(REGEX MATCH "^([0-9;a-f]+).*" EIGEN_GIT_CHANGESET_MATCH "${EIGEN_GIT_OUTPUT}")
|
||||
set(EIGEN_GIT_REVNUM "${CMAKE_MATCH_1}")
|
||||
string(REGEX MATCH "^([0-9;a-f]+).*" EIGEN_GIT_CHANGESET_MATCH "${EIGEN_GIT_OUTPUT}")
|
||||
set(EIGEN_GIT_REVNUM "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
#...and show it next to the version number
|
||||
if(EIGEN_GIT_REVNUM)
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER} (git rev ${EIGEN_GIT_REVNUM})")
|
||||
|
||||
if (NOT DEFINED EIGEN_BUILD_VERSION AND DEFINED EIGEN_GIT_REVNUM)
|
||||
string(SUBSTRING "${EIGEN_GIT_REVNUM}" 0 8 EIGEN_BUILD_VERSION)
|
||||
else()
|
||||
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
|
||||
set(EIGEN_BUILD_VERSION "")
|
||||
endif()
|
||||
|
||||
# The EIGEN_VERSION_NUMBER must be of the form <major.minor.patch>.
|
||||
# The EIGEN_VERSION_STRING can contain the preprelease/build strings.
|
||||
set(EIGEN_VERSION_NUMBER "${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION}.${EIGEN_PATCH_VERSION}")
|
||||
set(EIGEN_VERSION_STRING "${EIGEN_VERSION_NUMBER}")
|
||||
if (NOT "x${EIGEN_PRERELEASE_VERSION}" STREQUAL "x")
|
||||
set(EIGEN_VERSION_STRING "${EIGEN_VERSION_STRING}-${EIGEN_PRERELEASE_VERSION}")
|
||||
endif()
|
||||
if (NOT "x${EIGEN_BUILD_VERSION}" STREQUAL "x")
|
||||
set(EIGEN_VERSION_STRING "${EIGEN_VERSION_STRING}+${EIGEN_BUILD_VERSION}")
|
||||
endif()
|
||||
|
||||
|
||||
# Generate version file.
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Version.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/Eigen/Version")
|
||||
|
||||
#==============================================================================
|
||||
# Install Path Configuration.
|
||||
#==============================================================================
|
||||
@@ -176,11 +205,6 @@ endforeach()
|
||||
# Eigen Library.
|
||||
#==============================================================================
|
||||
|
||||
set ( EIGEN_VERSION_STRING ${EIGEN_VERSION_NUMBER} )
|
||||
set ( EIGEN_VERSION_MAJOR ${EIGEN_WORLD_VERSION} )
|
||||
set ( EIGEN_VERSION_MINOR ${EIGEN_MAJOR_VERSION} )
|
||||
set ( EIGEN_VERSION_PATCH ${EIGEN_MINOR_VERSION} )
|
||||
|
||||
# Alias Eigen_*_DIR to Eigen3_*_DIR:
|
||||
set(Eigen_SOURCE_DIR ${Eigen3_SOURCE_DIR})
|
||||
set(Eigen_BINARY_DIR ${Eigen3_BINARY_DIR})
|
||||
@@ -193,6 +217,9 @@ target_include_directories (eigen INTERFACE
|
||||
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
|
||||
)
|
||||
|
||||
# Eigen requires at least C++14
|
||||
target_compile_features (eigen INTERFACE cxx_std_14)
|
||||
|
||||
# Export as title case Eigen
|
||||
set_target_properties (eigen PROPERTIES EXPORT_NAME Eigen)
|
||||
|
||||
@@ -212,6 +239,9 @@ if(EIGEN_BUILD_PKGCONFIG)
|
||||
endif()
|
||||
|
||||
install(DIRECTORY Eigen DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel)
|
||||
# Replace the "Version" header file with the generated one.
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/Eigen/Version
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/ COMPONENT Devel)
|
||||
|
||||
install(TARGETS eigen EXPORT Eigen3Targets)
|
||||
|
||||
@@ -787,5 +817,5 @@ if(PROJECT_IS_TOP_LEVEL)
|
||||
endif()
|
||||
|
||||
message(STATUS "")
|
||||
message(STATUS "Configured Eigen ${EIGEN_VERSION_NUMBER}")
|
||||
message(STATUS "Configured Eigen ${EIGEN_VERSION_STRING}")
|
||||
message(STATUS "")
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#ifndef EIGEN_CORE_MODULE_H
|
||||
#define EIGEN_CORE_MODULE_H
|
||||
|
||||
// Eigen version information.
|
||||
#include "Version"
|
||||
|
||||
// first thing Eigen does: stop the compiler from reporting useless warnings.
|
||||
#include "src/Core/util/DisableStupidWarnings.h"
|
||||
|
||||
@@ -103,6 +106,11 @@
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
// for std::bit_cast()
|
||||
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
#include <bit>
|
||||
#endif
|
||||
|
||||
// for outputting debug info
|
||||
#ifdef EIGEN_DEBUG_ASSIGN
|
||||
#include <iostream>
|
||||
@@ -319,6 +327,7 @@ using std::ptrdiff_t;
|
||||
#include "src/Core/Product.h"
|
||||
#include "src/Core/CoreEvaluators.h"
|
||||
#include "src/Core/AssignEvaluator.h"
|
||||
#include "src/Core/RealView.h"
|
||||
#include "src/Core/Assign.h"
|
||||
|
||||
#include "src/Core/ArrayBase.h"
|
||||
|
||||
14
Eigen/Version
Normal file
14
Eigen/Version
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef EIGEN_VERSION_H
|
||||
#define EIGEN_VERSION_H
|
||||
|
||||
// The "WORLD" version will forever remain "3" for the "Eigen3" library.
|
||||
#define EIGEN_WORLD_VERSION 3
|
||||
// As of Eigen3 5.0.0, we have moved to Semantic Versioning (semver.org).
|
||||
#define EIGEN_MAJOR_VERSION 5
|
||||
#define EIGEN_MINOR_VERSION 0
|
||||
#define EIGEN_PATCH_VERSION 0
|
||||
#define EIGEN_PRERELEASE_VERSION "dev"
|
||||
#define EIGEN_BUILD_VERSION "master"
|
||||
#define EIGEN_VERSION_STRING "5.0.0-dev+master"
|
||||
|
||||
#endif // EIGEN_VERSION_H
|
||||
@@ -1565,50 +1565,6 @@ struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAc
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------- Select --------------------
|
||||
// NOTE shall we introduce a ternary_evaluator?
|
||||
|
||||
// TODO enable vectorization for Select
|
||||
template <typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
|
||||
struct evaluator<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType>>
|
||||
: evaluator_base<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType>> {
|
||||
typedef Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> XprType;
|
||||
enum {
|
||||
CoeffReadCost = evaluator<ConditionMatrixType>::CoeffReadCost +
|
||||
plain_enum_max(evaluator<ThenMatrixType>::CoeffReadCost, evaluator<ElseMatrixType>::CoeffReadCost),
|
||||
|
||||
Flags = (unsigned int)evaluator<ThenMatrixType>::Flags & evaluator<ElseMatrixType>::Flags & HereditaryBits,
|
||||
|
||||
Alignment = plain_enum_min(evaluator<ThenMatrixType>::Alignment, evaluator<ElseMatrixType>::Alignment)
|
||||
};
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit evaluator(const XprType& select)
|
||||
: m_conditionImpl(select.conditionMatrix()), m_thenImpl(select.thenMatrix()), m_elseImpl(select.elseMatrix()) {
|
||||
EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
|
||||
}
|
||||
|
||||
typedef typename XprType::CoeffReturnType CoeffReturnType;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const {
|
||||
if (m_conditionImpl.coeff(row, col))
|
||||
return m_thenImpl.coeff(row, col);
|
||||
else
|
||||
return m_elseImpl.coeff(row, col);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const {
|
||||
if (m_conditionImpl.coeff(index))
|
||||
return m_thenImpl.coeff(index);
|
||||
else
|
||||
return m_elseImpl.coeff(index);
|
||||
}
|
||||
|
||||
protected:
|
||||
evaluator<ConditionMatrixType> m_conditionImpl;
|
||||
evaluator<ThenMatrixType> m_thenImpl;
|
||||
evaluator<ElseMatrixType> m_elseImpl;
|
||||
};
|
||||
|
||||
// -------------------- Replicate --------------------
|
||||
|
||||
template <typename ArgType, int RowFactor, int ColFactor>
|
||||
|
||||
@@ -235,8 +235,7 @@ DenseBase<Derived>::Constant(const Scalar& value) {
|
||||
* \sa LinSpaced(Index,const Scalar&, const Scalar&), setLinSpaced(Index,const Scalar&,const Scalar&)
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC 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)
|
||||
return DenseBase<Derived>::NullaryExpr(size, internal::linspaced_op<Scalar>(low, high, size));
|
||||
@@ -247,8 +246,7 @@ DenseBase<Derived>::LinSpaced(Sequential_t, Index size, const Scalar& low, const
|
||||
* \sa LinSpaced(const Scalar&, const Scalar&)
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC 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)
|
||||
EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
|
||||
|
||||
@@ -306,12 +306,12 @@ class DenseBase
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Constant(Index size, const Scalar& value);
|
||||
EIGEN_DEVICE_FUNC static const ConstantReturnType Constant(const Scalar& value);
|
||||
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t, Index size,
|
||||
const Scalar& low,
|
||||
const Scalar& high);
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t,
|
||||
const Scalar& low,
|
||||
const Scalar& high);
|
||||
EIGEN_DEPRECATED_WITH_REASON("The method may result in accuracy loss. Use .EqualSpaced() instead.")
|
||||
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t, Index size, const Scalar& low,
|
||||
const Scalar& high);
|
||||
EIGEN_DEPRECATED_WITH_REASON("The method may result in accuracy loss. Use .EqualSpaced() instead.")
|
||||
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Sequential_t, const Scalar& low,
|
||||
const Scalar& high);
|
||||
|
||||
EIGEN_DEVICE_FUNC static const RandomAccessLinSpacedReturnType LinSpaced(Index size, const Scalar& low,
|
||||
const Scalar& high);
|
||||
@@ -367,7 +367,12 @@ class DenseBase
|
||||
EIGEN_DEVICE_FUNC inline bool allFinite() const;
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const Scalar& other);
|
||||
template <bool Enable = !internal::is_same<Scalar, RealScalar>::value, typename = std::enable_if_t<Enable>>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*=(const RealScalar& other);
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const Scalar& other);
|
||||
template <bool Enable = !internal::is_same<Scalar, RealScalar>::value, typename = std::enable_if_t<Enable>>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator/=(const RealScalar& other);
|
||||
|
||||
typedef internal::add_const_on_value_type_t<typename internal::eval<Derived>::type> EvalReturnType;
|
||||
/** \returns the matrix or vector obtained by evaluating this expression.
|
||||
@@ -597,6 +602,13 @@ class DenseBase
|
||||
inline const_iterator end() const;
|
||||
inline const_iterator cend() const;
|
||||
|
||||
using RealViewReturnType = std::conditional_t<NumTraits<Scalar>::IsComplex, RealView<Derived>, Derived&>;
|
||||
using ConstRealViewReturnType =
|
||||
std::conditional_t<NumTraits<Scalar>::IsComplex, RealView<const Derived>, const Derived&>;
|
||||
|
||||
EIGEN_DEVICE_FUNC RealViewReturnType realView();
|
||||
EIGEN_DEVICE_FUNC ConstRealViewReturnType realView() const;
|
||||
|
||||
#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::DenseBase
|
||||
#define EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL
|
||||
#define EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(COND)
|
||||
|
||||
@@ -78,8 +78,9 @@ template <typename Xpr>
|
||||
struct eigen_fill_impl<Xpr, /*use_fill*/ true> {
|
||||
using Scalar = typename Xpr::Scalar;
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const Scalar& val) {
|
||||
const Scalar val_copy = val;
|
||||
using std::fill_n;
|
||||
fill_n(dst.data(), dst.size(), val);
|
||||
fill_n(dst.data(), dst.size(), val_copy);
|
||||
}
|
||||
template <typename SrcXpr>
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const SrcXpr& src) {
|
||||
|
||||
@@ -253,6 +253,12 @@ struct preinterpret_generic<Packet, Packet, true> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet run(const Packet& a) { return a; }
|
||||
};
|
||||
|
||||
template <typename ComplexPacket>
|
||||
struct preinterpret_generic<typename unpacket_traits<ComplexPacket>::as_real, ComplexPacket, false> {
|
||||
using RealPacket = typename unpacket_traits<ComplexPacket>::as_real;
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE RealPacket run(const ComplexPacket& a) { return a.v; }
|
||||
};
|
||||
|
||||
/** \internal \returns reinterpret_cast<Target>(a) */
|
||||
template <typename Target, typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Target preinterpret(const Packet& a) {
|
||||
@@ -1344,20 +1350,20 @@ struct pmadd_impl {
|
||||
template <typename Scalar>
|
||||
struct pmadd_impl<Scalar, std::enable_if_t<is_scalar<Scalar>::value && NumTraits<Scalar>::IsSigned>> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pmadd(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::fma(a, b, c);
|
||||
return numext::madd<Scalar>(a, b, c);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pmsub(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::fma(a, b, Scalar(-c));
|
||||
return numext::madd<Scalar>(a, b, Scalar(-c));
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pnmadd(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::fma(Scalar(-a), b, c);
|
||||
return numext::madd<Scalar>(Scalar(-a), b, c);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar pnmsub(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return -Scalar(numext::fma(a, b, c));
|
||||
return -Scalar(numext::madd<Scalar>(a, b, c));
|
||||
}
|
||||
};
|
||||
|
||||
// FMA instructions.
|
||||
// Multiply-add instructions.
|
||||
/** \internal \returns a * b + c (coeff-wise) */
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC inline Packet pmadd(const Packet& a, const Packet& b, const Packet& c) {
|
||||
|
||||
@@ -308,6 +308,12 @@ struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased>
|
||||
const XprType& m_xpr;
|
||||
};
|
||||
|
||||
// Catch assignments to an IndexedView.
|
||||
template <typename ArgType, typename RowIndices, typename ColIndices>
|
||||
struct evaluator_assume_aliasing<IndexedView<ArgType, RowIndices, ColIndices>> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -941,23 +941,43 @@ struct nearest_integer_impl<Scalar, true> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_trunc(const Scalar& x) { return x; }
|
||||
};
|
||||
|
||||
// Extra namespace to prevent leaking std::fma into Eigen::internal.
|
||||
namespace has_fma_detail {
|
||||
|
||||
template <typename T, typename EnableIf = void>
|
||||
struct has_fma_impl : public std::false_type {};
|
||||
|
||||
using std::fma;
|
||||
|
||||
template <typename T>
|
||||
struct has_fma_impl<
|
||||
T, std::enable_if_t<std::is_same<T, decltype(fma(std::declval<T>(), std::declval<T>(), std::declval<T>()))>::value>>
|
||||
: public std::true_type {};
|
||||
|
||||
} // namespace has_fma_detail
|
||||
|
||||
template <typename T>
|
||||
struct has_fma : public has_fma_detail::has_fma_impl<T> {};
|
||||
|
||||
// Default implementation.
|
||||
template <typename Scalar, typename Enable = void>
|
||||
template <typename T, typename Enable = void>
|
||||
struct fma_impl {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return a * b + c;
|
||||
static_assert(has_fma<T>::value, "No function fma(...) for type. Please provide an implementation.");
|
||||
};
|
||||
|
||||
// STD or ADL version if it exists.
|
||||
template <typename T>
|
||||
struct fma_impl<T, std::enable_if_t<has_fma<T>::value>> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T run(const T& a, const T& b, const T& c) {
|
||||
using std::fma;
|
||||
return fma(a, b, c);
|
||||
}
|
||||
};
|
||||
|
||||
// ADL version if it exists.
|
||||
template <typename T>
|
||||
struct fma_impl<
|
||||
T,
|
||||
std::enable_if_t<std::is_same<T, decltype(fma(std::declval<T>(), std::declval<T>(), std::declval<T>()))>::value>> {
|
||||
static T run(const T& a, const T& b, const T& c) { return fma(a, b, c); }
|
||||
};
|
||||
|
||||
#if defined(EIGEN_GPUCC)
|
||||
template <>
|
||||
struct has_fma<float> : public true_type {};
|
||||
|
||||
template <>
|
||||
struct fma_impl<float, void> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float run(const float& a, const float& b, const float& c) {
|
||||
@@ -965,6 +985,9 @@ struct fma_impl<float, void> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct has_fma<double> : public true_type {};
|
||||
|
||||
template <>
|
||||
struct fma_impl<double, void> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE double run(const double& a, const double& b, const double& c) {
|
||||
@@ -973,6 +996,24 @@ struct fma_impl<double, void> {
|
||||
};
|
||||
#endif
|
||||
|
||||
// Basic multiply-add.
|
||||
template <typename Scalar, typename EnableIf = void>
|
||||
struct madd_impl {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) {
|
||||
return x * y + z;
|
||||
}
|
||||
};
|
||||
|
||||
// Use FMA if there is a single CPU instruction.
|
||||
#ifdef EIGEN_VECTORIZE_FMA
|
||||
template <typename Scalar>
|
||||
struct madd_impl<Scalar, std::enable_if_t<has_fma<Scalar>::value>> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) {
|
||||
return fma_impl<Scalar>::run(x, y, z);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1886,15 +1927,18 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar arithmetic_shift_right(const Scalar
|
||||
return bit_cast<Scalar, SignedScalar>(bit_cast<SignedScalar, Scalar>(a) >> n);
|
||||
}
|
||||
|
||||
// Use std::fma if available.
|
||||
using std::fma;
|
||||
|
||||
// Otherwise, rely on template implementation.
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar fma(const Scalar& x, const Scalar& y, const Scalar& z) {
|
||||
return internal::fma_impl<Scalar>::run(x, y, z);
|
||||
}
|
||||
|
||||
// Multiply-add.
|
||||
template <typename Scalar>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar madd(const Scalar& x, const Scalar& y, const Scalar& z) {
|
||||
return internal::madd_impl<Scalar>::run(x, y, z);
|
||||
}
|
||||
|
||||
} // end namespace numext
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -373,12 +373,14 @@ class MatrixBase : public DenseBase<Derived> {
|
||||
template <int Options = 0>
|
||||
inline JacobiSVD<PlainObject, Options> jacobiSvd() const;
|
||||
template <int Options = 0>
|
||||
EIGEN_DEPRECATED inline JacobiSVD<PlainObject, Options> jacobiSvd(unsigned int computationOptions) const;
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using method's template parameter.")
|
||||
inline JacobiSVD<PlainObject, Options> jacobiSvd(unsigned int computationOptions) const;
|
||||
|
||||
template <int Options = 0>
|
||||
inline BDCSVD<PlainObject, Options> bdcSvd() const;
|
||||
template <int Options = 0>
|
||||
EIGEN_DEPRECATED inline BDCSVD<PlainObject, Options> bdcSvd(unsigned int computationOptions) const;
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using method's template parameter.")
|
||||
inline BDCSVD<PlainObject, Options> bdcSvd(unsigned int computationOptions) const;
|
||||
|
||||
/////////// Geometry module ///////////
|
||||
|
||||
@@ -391,7 +393,8 @@ class MatrixBase : public DenseBase<Derived> {
|
||||
|
||||
EIGEN_DEVICE_FUNC inline PlainObject unitOrthogonal(void) const;
|
||||
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline Matrix<Scalar, 3, 1> eulerAngles(Index a0, Index a1, Index a2) const;
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .canonicalEulerAngles() instead.")
|
||||
EIGEN_DEVICE_FUNC inline Matrix<Scalar, 3, 1> eulerAngles(Index a0, Index a1, Index a2) const;
|
||||
|
||||
EIGEN_DEVICE_FUNC inline Matrix<Scalar, 3, 1> canonicalEulerAngles(Index a0, Index a1, Index a2) const;
|
||||
|
||||
|
||||
@@ -95,9 +95,22 @@ struct default_max_digits10_impl<T, false, true> // Integer
|
||||
} // end namespace internal
|
||||
|
||||
namespace numext {
|
||||
/** \internal bit-wise cast without changing the underlying bit representation. */
|
||||
|
||||
// TODO: Replace by std::bit_cast (available in C++20)
|
||||
/** \internal bit-wise cast without changing the underlying bit representation. */
|
||||
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
template <typename Tgt, typename Src>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr Tgt bit_cast(const Src& src) {
|
||||
return std::bit_cast<Tgt>(src);
|
||||
}
|
||||
#elif EIGEN_HAS_BUILTIN(__builtin_bit_cast)
|
||||
template <typename Tgt, typename Src>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC constexpr Tgt bit_cast(const Src& src) {
|
||||
EIGEN_STATIC_ASSERT(std::is_trivially_copyable<Src>::value, THIS_TYPE_IS_NOT_SUPPORTED)
|
||||
EIGEN_STATIC_ASSERT(std::is_trivially_copyable<Tgt>::value, THIS_TYPE_IS_NOT_SUPPORTED)
|
||||
EIGEN_STATIC_ASSERT(sizeof(Src) == sizeof(Tgt), THIS_TYPE_IS_NOT_SUPPORTED)
|
||||
return __builtin_bit_cast(Tgt, src);
|
||||
}
|
||||
#else
|
||||
template <typename Tgt, typename Src>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) {
|
||||
// The behaviour of memcpy is not specified for non-trivially copyable types
|
||||
@@ -113,6 +126,7 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) {
|
||||
memcpy(static_cast<void*>(&tgt), static_cast<const void*>(&staged), sizeof(Tgt));
|
||||
return tgt;
|
||||
}
|
||||
#endif
|
||||
} // namespace numext
|
||||
|
||||
// clang-format off
|
||||
|
||||
@@ -468,17 +468,17 @@ class PermutationWrapper : public PermutationBase<PermutationWrapper<IndicesType
|
||||
/** \returns the matrix with the permutation applied to the columns.
|
||||
*/
|
||||
template <typename MatrixDerived, typename PermutationDerived>
|
||||
EIGEN_DEVICE_FUNC const Product<MatrixDerived, PermutationDerived, AliasFreeProduct> operator*(
|
||||
EIGEN_DEVICE_FUNC const Product<MatrixDerived, PermutationDerived, DefaultProduct> operator*(
|
||||
const MatrixBase<MatrixDerived>& matrix, const PermutationBase<PermutationDerived>& permutation) {
|
||||
return Product<MatrixDerived, PermutationDerived, AliasFreeProduct>(matrix.derived(), permutation.derived());
|
||||
return Product<MatrixDerived, PermutationDerived, DefaultProduct>(matrix.derived(), permutation.derived());
|
||||
}
|
||||
|
||||
/** \returns the matrix with the permutation applied to the rows.
|
||||
*/
|
||||
template <typename PermutationDerived, typename MatrixDerived>
|
||||
EIGEN_DEVICE_FUNC const Product<PermutationDerived, MatrixDerived, AliasFreeProduct> operator*(
|
||||
EIGEN_DEVICE_FUNC const Product<PermutationDerived, MatrixDerived, DefaultProduct> operator*(
|
||||
const PermutationBase<PermutationDerived>& permutation, const MatrixBase<MatrixDerived>& matrix) {
|
||||
return Product<PermutationDerived, MatrixDerived, AliasFreeProduct>(permutation.derived(), matrix.derived());
|
||||
return Product<PermutationDerived, MatrixDerived, DefaultProduct>(permutation.derived(), matrix.derived());
|
||||
}
|
||||
|
||||
template <typename PermutationType>
|
||||
@@ -520,16 +520,16 @@ class InverseImpl<PermutationType, PermutationStorage> : public EigenBase<Invers
|
||||
/** \returns the matrix with the inverse permutation applied to the columns.
|
||||
*/
|
||||
template <typename OtherDerived>
|
||||
friend const Product<OtherDerived, InverseType, AliasFreeProduct> operator*(const MatrixBase<OtherDerived>& matrix,
|
||||
const InverseType& trPerm) {
|
||||
return Product<OtherDerived, InverseType, AliasFreeProduct>(matrix.derived(), trPerm.derived());
|
||||
friend const Product<OtherDerived, InverseType, DefaultProduct> operator*(const MatrixBase<OtherDerived>& matrix,
|
||||
const InverseType& trPerm) {
|
||||
return Product<OtherDerived, InverseType, DefaultProduct>(matrix.derived(), trPerm.derived());
|
||||
}
|
||||
|
||||
/** \returns the matrix with the inverse permutation applied to the rows.
|
||||
*/
|
||||
template <typename OtherDerived>
|
||||
const Product<InverseType, OtherDerived, AliasFreeProduct> operator*(const MatrixBase<OtherDerived>& matrix) const {
|
||||
return Product<InverseType, OtherDerived, AliasFreeProduct>(derived(), matrix.derived());
|
||||
const Product<InverseType, OtherDerived, DefaultProduct> operator*(const MatrixBase<OtherDerived>& matrix) const {
|
||||
return Product<InverseType, OtherDerived, DefaultProduct>(derived(), matrix.derived());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -131,8 +131,15 @@ struct random_longdouble_impl {
|
||||
uint64_t randomBits[2];
|
||||
long double result = 2.0L;
|
||||
memcpy(&randomBits, &result, Size);
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
randomBits[0] |= getRandomBits<uint64_t>(numLowBits);
|
||||
randomBits[1] |= getRandomBits<uint64_t>(numHighBits);
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
randomBits[0] |= getRandomBits<uint64_t>(numHighBits);
|
||||
randomBits[1] |= getRandomBits<uint64_t>(numLowBits);
|
||||
#else
|
||||
#error Unexpected or undefined __BYTE_ORDER__
|
||||
#endif
|
||||
memcpy(&result, &randomBits, Size);
|
||||
result -= 3.0L;
|
||||
return result;
|
||||
|
||||
250
Eigen/src/Core/RealView.h
Normal file
250
Eigen/src/Core/RealView.h
Normal file
@@ -0,0 +1,250 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2025 Charlie Schlosser <cs.schlosser@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_REALVIEW_H
|
||||
#define EIGEN_REALVIEW_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Vectorized assignment to RealView requires array-oriented access to the real and imaginary components.
|
||||
// From https://en.cppreference.com/w/cpp/numeric/complex.html:
|
||||
// For any pointer to an element of an array of std::complex<T> named p and any valid array index i,
|
||||
// reinterpret_cast<T*>(p)[2 * i] is the real part of the complex number p[i], and
|
||||
// reinterpret_cast<T*>(p)[2 * i + 1] is the imaginary part of the complex number p[i].
|
||||
|
||||
template <typename ComplexScalar>
|
||||
struct complex_array_access : std::false_type {};
|
||||
template <>
|
||||
struct complex_array_access<std::complex<float>> : std::true_type {};
|
||||
template <>
|
||||
struct complex_array_access<std::complex<double>> : std::true_type {};
|
||||
template <>
|
||||
struct complex_array_access<std::complex<long double>> : std::true_type {};
|
||||
|
||||
template <typename Xpr>
|
||||
struct traits<RealView<Xpr>> : public traits<Xpr> {
|
||||
template <typename T>
|
||||
static constexpr int double_size(T size, bool times_two) {
|
||||
int size_as_int = int(size);
|
||||
if (size_as_int == Dynamic) return Dynamic;
|
||||
return times_two ? (2 * size_as_int) : size_as_int;
|
||||
}
|
||||
using Base = traits<Xpr>;
|
||||
using ComplexScalar = typename Base::Scalar;
|
||||
using Scalar = typename NumTraits<ComplexScalar>::Real;
|
||||
static constexpr int ActualDirectAccessBit = complex_array_access<ComplexScalar>::value ? DirectAccessBit : 0;
|
||||
static constexpr int ActualPacketAccessBit = packet_traits<Scalar>::Vectorizable ? PacketAccessBit : 0;
|
||||
static constexpr int FlagMask =
|
||||
ActualDirectAccessBit | ActualPacketAccessBit | HereditaryBits | LinearAccessBit | LvalueBit;
|
||||
static constexpr int BaseFlags = int(evaluator<Xpr>::Flags) | int(Base::Flags);
|
||||
static constexpr int Flags = BaseFlags & FlagMask;
|
||||
static constexpr bool IsRowMajor = Flags & RowMajorBit;
|
||||
static constexpr int RowsAtCompileTime = double_size(Base::RowsAtCompileTime, !IsRowMajor);
|
||||
static constexpr int ColsAtCompileTime = double_size(Base::ColsAtCompileTime, IsRowMajor);
|
||||
static constexpr int SizeAtCompileTime = size_at_compile_time(RowsAtCompileTime, ColsAtCompileTime);
|
||||
static constexpr int MaxRowsAtCompileTime = double_size(Base::MaxRowsAtCompileTime, !IsRowMajor);
|
||||
static constexpr int MaxColsAtCompileTime = double_size(Base::MaxColsAtCompileTime, IsRowMajor);
|
||||
static constexpr int MaxSizeAtCompileTime = size_at_compile_time(MaxRowsAtCompileTime, MaxColsAtCompileTime);
|
||||
static constexpr int OuterStrideAtCompileTime = double_size(outer_stride_at_compile_time<Xpr>::ret, true);
|
||||
static constexpr int InnerStrideAtCompileTime = inner_stride_at_compile_time<Xpr>::ret;
|
||||
};
|
||||
|
||||
template <typename Xpr>
|
||||
struct evaluator<RealView<Xpr>> : private evaluator<Xpr> {
|
||||
using BaseEvaluator = evaluator<Xpr>;
|
||||
using XprType = RealView<Xpr>;
|
||||
using ExpressionTraits = traits<XprType>;
|
||||
using ComplexScalar = typename ExpressionTraits::ComplexScalar;
|
||||
using ComplexCoeffReturnType = typename BaseEvaluator::CoeffReturnType;
|
||||
using Scalar = typename ExpressionTraits::Scalar;
|
||||
|
||||
static constexpr bool IsRowMajor = ExpressionTraits::IsRowMajor;
|
||||
static constexpr int Flags = ExpressionTraits::Flags;
|
||||
static constexpr int CoeffReadCost = BaseEvaluator::CoeffReadCost;
|
||||
static constexpr int Alignment = BaseEvaluator::Alignment;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit evaluator(XprType realView) : BaseEvaluator(realView.m_xpr) {}
|
||||
|
||||
template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<!Enable>>
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index row, Index col) const {
|
||||
ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
|
||||
Index p = (IsRowMajor ? col : row) & 1;
|
||||
return p ? numext::real(cscalar) : numext::imag(cscalar);
|
||||
}
|
||||
|
||||
template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<Enable>>
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const {
|
||||
ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
|
||||
Index p = (IsRowMajor ? col : row) & 1;
|
||||
return reinterpret_cast<const Scalar(&)[2]>(cscalar)[p];
|
||||
}
|
||||
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) {
|
||||
ComplexScalar& cscalar = BaseEvaluator::coeffRef(IsRowMajor ? row : row / 2, IsRowMajor ? col / 2 : col);
|
||||
Index p = (IsRowMajor ? col : row) & 1;
|
||||
return reinterpret_cast<Scalar(&)[2]>(cscalar)[p];
|
||||
}
|
||||
|
||||
template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<!Enable>>
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar coeff(Index index) const {
|
||||
ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(index / 2);
|
||||
Index p = index & 1;
|
||||
return p ? numext::real(cscalar) : numext::imag(cscalar);
|
||||
}
|
||||
|
||||
template <bool Enable = std::is_reference<ComplexCoeffReturnType>::value, typename = std::enable_if_t<Enable>>
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const {
|
||||
ComplexCoeffReturnType cscalar = BaseEvaluator::coeff(index / 2);
|
||||
Index p = index & 1;
|
||||
return reinterpret_cast<const Scalar(&)[2]>(cscalar)[p];
|
||||
}
|
||||
|
||||
constexpr EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) {
|
||||
ComplexScalar& cscalar = BaseEvaluator::coeffRef(index / 2);
|
||||
Index p = index & 1;
|
||||
return reinterpret_cast<Scalar(&)[2]>(cscalar)[p];
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const {
|
||||
constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
|
||||
using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
|
||||
EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
|
||||
MISSING COMPATIBLE COMPLEX PACKET TYPE)
|
||||
eigen_assert(((IsRowMajor ? col : row) % 2 == 0) && "the inner index must be even");
|
||||
|
||||
Index crow = IsRowMajor ? row : row / 2;
|
||||
Index ccol = IsRowMajor ? col / 2 : col;
|
||||
ComplexPacket cpacket = BaseEvaluator::template packet<LoadMode, ComplexPacket>(crow, ccol);
|
||||
return preinterpret<PacketType, ComplexPacket>(cpacket);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packet(Index index) const {
|
||||
constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
|
||||
using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
|
||||
EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
|
||||
MISSING COMPATIBLE COMPLEX PACKET TYPE)
|
||||
eigen_assert((index % 2 == 0) && "the index must be even");
|
||||
|
||||
Index cindex = index / 2;
|
||||
ComplexPacket cpacket = BaseEvaluator::template packet<LoadMode, ComplexPacket>(cindex);
|
||||
return preinterpret<PacketType, ComplexPacket>(cpacket);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index row, Index col, Index begin, Index count) const {
|
||||
constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
|
||||
using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
|
||||
EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
|
||||
MISSING COMPATIBLE COMPLEX PACKET TYPE)
|
||||
eigen_assert(((IsRowMajor ? col : row) % 2 == 0) && "the inner index must be even");
|
||||
eigen_assert((begin % 2 == 0) && (count % 2 == 0) && "begin and count must be even");
|
||||
|
||||
Index crow = IsRowMajor ? row : row / 2;
|
||||
Index ccol = IsRowMajor ? col / 2 : col;
|
||||
Index cbegin = begin / 2;
|
||||
Index ccount = count / 2;
|
||||
ComplexPacket cpacket = BaseEvaluator::template packetSegment<LoadMode, ComplexPacket>(crow, ccol, cbegin, ccount);
|
||||
return preinterpret<PacketType, ComplexPacket>(cpacket);
|
||||
}
|
||||
|
||||
template <int LoadMode, typename PacketType>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketType packetSegment(Index index, Index begin, Index count) const {
|
||||
constexpr int RealPacketSize = unpacket_traits<PacketType>::size;
|
||||
using ComplexPacket = typename find_packet_by_size<ComplexScalar, RealPacketSize / 2>::type;
|
||||
EIGEN_STATIC_ASSERT((find_packet_by_size<ComplexScalar, RealPacketSize / 2>::value),
|
||||
MISSING COMPATIBLE COMPLEX PACKET TYPE)
|
||||
eigen_assert((index % 2 == 0) && "the index must be even");
|
||||
eigen_assert((begin % 2 == 0) && (count % 2 == 0) && "begin and count must be even");
|
||||
|
||||
Index cindex = index / 2;
|
||||
Index cbegin = begin / 2;
|
||||
Index ccount = count / 2;
|
||||
ComplexPacket cpacket = BaseEvaluator::template packetSegment<LoadMode, ComplexPacket>(cindex, cbegin, ccount);
|
||||
return preinterpret<PacketType, ComplexPacket>(cpacket);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename Xpr>
|
||||
class RealView : public internal::dense_xpr_base<RealView<Xpr>>::type {
|
||||
using ExpressionTraits = internal::traits<RealView>;
|
||||
EIGEN_STATIC_ASSERT(NumTraits<typename Xpr::Scalar>::IsComplex, SCALAR MUST BE COMPLEX)
|
||||
public:
|
||||
using Scalar = typename ExpressionTraits::Scalar;
|
||||
using Nested = RealView;
|
||||
|
||||
EIGEN_DEVICE_FUNC explicit RealView(Xpr& xpr) : m_xpr(xpr) {}
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return Xpr::IsRowMajor ? m_xpr.rows() : 2 * m_xpr.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return Xpr::IsRowMajor ? 2 * m_xpr.cols() : m_xpr.cols(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index size() const noexcept { return 2 * m_xpr.size(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index innerStride() const noexcept { return m_xpr.innerStride(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index outerStride() const noexcept { return 2 * m_xpr.outerStride(); }
|
||||
EIGEN_DEVICE_FUNC void resize(Index rows, Index cols) {
|
||||
m_xpr.resize(Xpr::IsRowMajor ? rows : rows / 2, Xpr::IsRowMajor ? cols / 2 : cols);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC void resize(Index size) { m_xpr.resize(size / 2); }
|
||||
EIGEN_DEVICE_FUNC Scalar* data() { return reinterpret_cast<Scalar*>(m_xpr.data()); }
|
||||
EIGEN_DEVICE_FUNC const Scalar* data() const { return reinterpret_cast<const Scalar*>(m_xpr.data()); }
|
||||
|
||||
EIGEN_DEVICE_FUNC RealView(const RealView&) = default;
|
||||
|
||||
EIGEN_DEVICE_FUNC RealView& operator=(const RealView& other);
|
||||
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC RealView& operator=(const RealView<OtherDerived>& other);
|
||||
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC RealView& operator=(const DenseBase<OtherDerived>& other);
|
||||
|
||||
protected:
|
||||
friend struct internal::evaluator<RealView<Xpr>>;
|
||||
Xpr& m_xpr;
|
||||
};
|
||||
|
||||
template <typename Xpr>
|
||||
EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const RealView& other) {
|
||||
internal::call_assignment(*this, other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Xpr>
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const RealView<OtherDerived>& other) {
|
||||
internal::call_assignment(*this, other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Xpr>
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC RealView<Xpr>& RealView<Xpr>::operator=(const DenseBase<OtherDerived>& other) {
|
||||
internal::call_assignment(*this, other.derived());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC typename DenseBase<Derived>::RealViewReturnType DenseBase<Derived>::realView() {
|
||||
return RealViewReturnType(derived());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC typename DenseBase<Derived>::ConstRealViewReturnType DenseBase<Derived>::realView() const {
|
||||
return ConstRealViewReturnType(derived());
|
||||
}
|
||||
|
||||
} // namespace Eigen
|
||||
|
||||
#endif // EIGEN_REALVIEW_H
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \class Select
|
||||
/** \typedef Select
|
||||
* \ingroup Core_Module
|
||||
*
|
||||
* \brief Expression of a coefficient wise version of the C++ ternary operator ?:
|
||||
@@ -24,73 +24,16 @@ namespace Eigen {
|
||||
* \tparam ThenMatrixType the type of the \em then expression
|
||||
* \tparam ElseMatrixType the type of the \em else expression
|
||||
*
|
||||
* This class represents an expression of a coefficient wise version of the C++ ternary operator ?:.
|
||||
* This type represents an expression of a coefficient wise version of the C++ ternary operator ?:.
|
||||
* It is the return type of DenseBase::select() and most of the time this is the only way it is used.
|
||||
*
|
||||
* \sa DenseBase::select(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
template <typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
|
||||
struct traits<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> > : traits<ThenMatrixType> {
|
||||
typedef typename traits<ThenMatrixType>::Scalar Scalar;
|
||||
typedef Dense StorageKind;
|
||||
typedef typename traits<ThenMatrixType>::XprKind XprKind;
|
||||
typedef typename ConditionMatrixType::Nested ConditionMatrixNested;
|
||||
typedef typename ThenMatrixType::Nested ThenMatrixNested;
|
||||
typedef typename ElseMatrixType::Nested ElseMatrixNested;
|
||||
enum {
|
||||
RowsAtCompileTime = ConditionMatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = ConditionMatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = ConditionMatrixType::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ConditionMatrixType::MaxColsAtCompileTime,
|
||||
Flags = (unsigned int)ThenMatrixType::Flags & ElseMatrixType::Flags & RowMajorBit
|
||||
};
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
template <typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
|
||||
class Select : public internal::dense_xpr_base<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >::type,
|
||||
internal::no_assignment_operator {
|
||||
public:
|
||||
typedef typename internal::dense_xpr_base<Select>::type Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Select)
|
||||
|
||||
inline EIGEN_DEVICE_FUNC Select(const ConditionMatrixType& a_conditionMatrix, const ThenMatrixType& a_thenMatrix,
|
||||
const ElseMatrixType& a_elseMatrix)
|
||||
: m_condition(a_conditionMatrix), m_then(a_thenMatrix), m_else(a_elseMatrix) {
|
||||
eigen_assert(m_condition.rows() == m_then.rows() && m_condition.rows() == m_else.rows());
|
||||
eigen_assert(m_condition.cols() == m_then.cols() && m_condition.cols() == m_else.cols());
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC constexpr Index rows() const noexcept { return m_condition.rows(); }
|
||||
EIGEN_DEVICE_FUNC constexpr Index cols() const noexcept { return m_condition.cols(); }
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const Scalar coeff(Index i, Index j) const {
|
||||
if (m_condition.coeff(i, j))
|
||||
return m_then.coeff(i, j);
|
||||
else
|
||||
return m_else.coeff(i, j);
|
||||
}
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const Scalar coeff(Index i) const {
|
||||
if (m_condition.coeff(i))
|
||||
return m_then.coeff(i);
|
||||
else
|
||||
return m_else.coeff(i);
|
||||
}
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const ConditionMatrixType& conditionMatrix() const { return m_condition; }
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const ThenMatrixType& thenMatrix() const { return m_then; }
|
||||
|
||||
inline EIGEN_DEVICE_FUNC const ElseMatrixType& elseMatrix() const { return m_else; }
|
||||
|
||||
protected:
|
||||
typename ConditionMatrixType::Nested m_condition;
|
||||
typename ThenMatrixType::Nested m_then;
|
||||
typename ElseMatrixType::Nested m_else;
|
||||
};
|
||||
using Select = CwiseTernaryOp<internal::scalar_boolean_select_op<typename DenseBase<ThenMatrixType>::Scalar,
|
||||
typename DenseBase<ElseMatrixType>::Scalar,
|
||||
typename DenseBase<ConditionMatrixType>::Scalar>,
|
||||
ThenMatrixType, ElseMatrixType, ConditionMatrixType>;
|
||||
|
||||
/** \returns a matrix where each coefficient (i,j) is equal to \a thenMatrix(i,j)
|
||||
* if \c *this(i,j) != Scalar(0), and \a elseMatrix(i,j) otherwise.
|
||||
@@ -98,7 +41,7 @@ class Select : public internal::dense_xpr_base<Select<ConditionMatrixType, ThenM
|
||||
* Example: \include MatrixBase_select.cpp
|
||||
* Output: \verbinclude MatrixBase_select.out
|
||||
*
|
||||
* \sa DenseBase::bitwiseSelect(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&)
|
||||
* \sa typedef Select
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename ThenDerived, typename ElseDerived>
|
||||
@@ -107,15 +50,12 @@ inline EIGEN_DEVICE_FUNC CwiseTernaryOp<
|
||||
typename DenseBase<Derived>::Scalar>,
|
||||
ThenDerived, ElseDerived, Derived>
|
||||
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix, const DenseBase<ElseDerived>& elseMatrix) const {
|
||||
using Op = internal::scalar_boolean_select_op<typename DenseBase<ThenDerived>::Scalar,
|
||||
typename DenseBase<ElseDerived>::Scalar, Scalar>;
|
||||
return CwiseTernaryOp<Op, ThenDerived, ElseDerived, Derived>(thenMatrix.derived(), elseMatrix.derived(), derived(),
|
||||
Op());
|
||||
return Select<Derived, ThenDerived, ElseDerived>(thenMatrix.derived(), elseMatrix.derived(), derived());
|
||||
}
|
||||
/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with
|
||||
* the \em else expression being a scalar value.
|
||||
*
|
||||
* \sa DenseBase::booleanSelect(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select
|
||||
* \sa typedef Select
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename ThenDerived>
|
||||
@@ -126,15 +66,13 @@ inline EIGEN_DEVICE_FUNC CwiseTernaryOp<
|
||||
DenseBase<Derived>::select(const DenseBase<ThenDerived>& thenMatrix,
|
||||
const typename DenseBase<ThenDerived>::Scalar& elseScalar) const {
|
||||
using ElseConstantType = typename DenseBase<ThenDerived>::ConstantReturnType;
|
||||
using Op = internal::scalar_boolean_select_op<typename DenseBase<ThenDerived>::Scalar,
|
||||
typename DenseBase<ThenDerived>::Scalar, Scalar>;
|
||||
return CwiseTernaryOp<Op, ThenDerived, ElseConstantType, Derived>(
|
||||
thenMatrix.derived(), ElseConstantType(rows(), cols(), elseScalar), derived(), Op());
|
||||
return Select<Derived, ThenDerived, ElseConstantType>(thenMatrix.derived(),
|
||||
ElseConstantType(rows(), cols(), elseScalar), derived());
|
||||
}
|
||||
/** Version of DenseBase::select(const DenseBase&, const DenseBase&) with
|
||||
* the \em then expression being a scalar value.
|
||||
*
|
||||
* \sa DenseBase::booleanSelect(const DenseBase<ThenDerived>&, const DenseBase<ElseDerived>&) const, class Select
|
||||
* \sa typedef Select
|
||||
*/
|
||||
template <typename Derived>
|
||||
template <typename ElseDerived>
|
||||
@@ -145,10 +83,8 @@ inline EIGEN_DEVICE_FUNC CwiseTernaryOp<
|
||||
DenseBase<Derived>::select(const typename DenseBase<ElseDerived>::Scalar& thenScalar,
|
||||
const DenseBase<ElseDerived>& elseMatrix) const {
|
||||
using ThenConstantType = typename DenseBase<ElseDerived>::ConstantReturnType;
|
||||
using Op = internal::scalar_boolean_select_op<typename DenseBase<ElseDerived>::Scalar,
|
||||
typename DenseBase<ElseDerived>::Scalar, Scalar>;
|
||||
return CwiseTernaryOp<Op, ThenConstantType, ElseDerived, Derived>(ThenConstantType(rows(), cols(), thenScalar),
|
||||
elseMatrix.derived(), derived(), Op());
|
||||
return Select<Derived, ThenConstantType, ElseDerived>(ThenConstantType(rows(), cols(), thenScalar),
|
||||
elseMatrix.derived(), derived());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -15,19 +15,33 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// TODO generalize the scalar type of 'other'
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator*=(const Scalar& other) {
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other),
|
||||
internal::mul_assign_op<Scalar, Scalar>());
|
||||
using ConstantExpr = typename internal::plain_constant_type<Derived, Scalar>::type;
|
||||
using Op = internal::mul_assign_op<Scalar>;
|
||||
internal::call_assignment(derived(), ConstantExpr(rows(), cols(), other), Op());
|
||||
return derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
template <bool Enable, typename>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator*=(const RealScalar& other) {
|
||||
realView() *= other;
|
||||
return derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator/=(const Scalar& other) {
|
||||
internal::call_assignment(this->derived(), PlainObject::Constant(rows(), cols(), other),
|
||||
internal::div_assign_op<Scalar, Scalar>());
|
||||
using ConstantExpr = typename internal::plain_constant_type<Derived, Scalar>::type;
|
||||
using Op = internal::div_assign_op<Scalar>;
|
||||
internal::call_assignment(derived(), ConstantExpr(rows(), cols(), other), Op());
|
||||
return derived();
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
template <bool Enable, typename>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator/=(const RealScalar& other) {
|
||||
realView() /= other;
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,22 @@ struct member_redux {
|
||||
const BinaryOp& binaryFunc() const { return m_functor; }
|
||||
const BinaryOp m_functor;
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct scalar_replace_zero_with_one_op {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& x) const {
|
||||
return numext::is_exactly_zero(x) ? Scalar(1) : x;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& x) const {
|
||||
return pselect(pcmp_eq(x, pzero(x)), pset1<Packet>(Scalar(1)), x);
|
||||
}
|
||||
};
|
||||
template <typename Scalar>
|
||||
struct functor_traits<scalar_replace_zero_with_one_op<Scalar>> {
|
||||
enum { Cost = 1, PacketAccess = packet_traits<Scalar>::HasCmp };
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/** \class VectorwiseOp
|
||||
@@ -190,9 +206,7 @@ class VectorwiseOp {
|
||||
public:
|
||||
typedef typename ExpressionType::Scalar Scalar;
|
||||
typedef typename ExpressionType::RealScalar RealScalar;
|
||||
typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
|
||||
typedef typename internal::ref_selector<ExpressionType>::non_const_type ExpressionTypeNested;
|
||||
typedef internal::remove_all_t<ExpressionTypeNested> ExpressionTypeNestedCleaned;
|
||||
typedef internal::remove_all_t<ExpressionType> ExpressionTypeCleaned;
|
||||
|
||||
template <template <typename OutScalar, typename InputScalar> class Functor, typename ReturnScalar = Scalar>
|
||||
struct ReturnType {
|
||||
@@ -331,7 +345,7 @@ class VectorwiseOp {
|
||||
|
||||
typedef typename ReturnType<internal::member_minCoeff>::Type MinCoeffReturnType;
|
||||
typedef typename ReturnType<internal::member_maxCoeff>::Type MaxCoeffReturnType;
|
||||
typedef PartialReduxExpr<const CwiseUnaryOp<internal::scalar_abs2_op<Scalar>, const ExpressionTypeNestedCleaned>,
|
||||
typedef PartialReduxExpr<const CwiseUnaryOp<internal::scalar_abs2_op<Scalar>, const ExpressionTypeCleaned>,
|
||||
internal::member_sum<RealScalar, RealScalar>, Direction>
|
||||
SquaredNormReturnType;
|
||||
typedef CwiseUnaryOp<internal::scalar_sqrt_op<RealScalar>, const SquaredNormReturnType> NormReturnType;
|
||||
@@ -582,7 +596,7 @@ class VectorwiseOp {
|
||||
/** Returns the expression of the sum of the vector \a other to each subvector of \c *this */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
|
||||
CwiseBinaryOp<internal::scalar_sum_op<Scalar, typename OtherDerived::Scalar>, const ExpressionTypeNestedCleaned,
|
||||
CwiseBinaryOp<internal::scalar_sum_op<Scalar, typename OtherDerived::Scalar>, const ExpressionTypeCleaned,
|
||||
const typename ExtendedType<OtherDerived>::Type>
|
||||
operator+(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
@@ -593,7 +607,7 @@ class VectorwiseOp {
|
||||
/** Returns the expression of the difference between each subvector of \c *this and the vector \a other */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_difference_op<Scalar, typename OtherDerived::Scalar>,
|
||||
const ExpressionTypeNestedCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
const ExpressionTypeCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
operator-(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived)
|
||||
@@ -604,7 +618,7 @@ class VectorwiseOp {
|
||||
* by the corresponding subvector of \c *this */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_product_op<Scalar, typename OtherDerived::Scalar>,
|
||||
const ExpressionTypeNestedCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
const ExpressionTypeCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
operator*(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
|
||||
@@ -616,7 +630,7 @@ class VectorwiseOp {
|
||||
* subvector of \c *this by the vector \a other */
|
||||
template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_quotient_op<Scalar, typename OtherDerived::Scalar>,
|
||||
const ExpressionTypeNestedCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
const ExpressionTypeCleaned, const typename ExtendedType<OtherDerived>::Type>
|
||||
operator/(const DenseBase<OtherDerived>& other) const {
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
|
||||
EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType)
|
||||
@@ -624,18 +638,28 @@ class VectorwiseOp {
|
||||
return m_matrix / extendedTo(other.derived());
|
||||
}
|
||||
|
||||
using Normalized_NonzeroNormType =
|
||||
CwiseUnaryOp<internal::scalar_replace_zero_with_one_op<Scalar>, const NormReturnType>;
|
||||
using NormalizedReturnType = CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const ExpressionTypeCleaned,
|
||||
const typename OppositeExtendedType<Normalized_NonzeroNormType>::Type>;
|
||||
|
||||
/** \returns an expression where each column (or row) of the referenced matrix are normalized.
|
||||
* The referenced matrix is \b not modified.
|
||||
*
|
||||
* \warning If the input columns (or rows) are too small (i.e., their norm equals to 0), they remain unchanged in the
|
||||
* resulting expression.
|
||||
*
|
||||
* \sa MatrixBase::normalized(), normalize()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC CwiseBinaryOp<internal::scalar_quotient_op<Scalar>, const ExpressionTypeNestedCleaned,
|
||||
const typename OppositeExtendedType<NormReturnType>::Type>
|
||||
normalized() const {
|
||||
return m_matrix.cwiseQuotient(extendedToOpposite(this->norm()));
|
||||
EIGEN_DEVICE_FUNC NormalizedReturnType normalized() const {
|
||||
return m_matrix.cwiseQuotient(extendedToOpposite(Normalized_NonzeroNormType(this->norm())));
|
||||
}
|
||||
|
||||
/** Normalize in-place each row or columns of the referenced matrix.
|
||||
* \sa MatrixBase::normalize(), normalized()
|
||||
*
|
||||
* \warning If the input columns (or rows) are too small (i.e., their norm equals to 0), they are left unchanged.
|
||||
*
|
||||
* \sa MatrixBase::normalized(), normalize()
|
||||
*/
|
||||
EIGEN_DEVICE_FUNC void normalize() { m_matrix = this->normalized(); }
|
||||
|
||||
@@ -679,7 +703,7 @@ class VectorwiseOp {
|
||||
|
||||
protected:
|
||||
EIGEN_DEVICE_FUNC Index redux_length() const { return Direction == Vertical ? m_matrix.rows() : m_matrix.cols(); }
|
||||
ExpressionTypeNested m_matrix;
|
||||
ExpressionType& m_matrix;
|
||||
};
|
||||
|
||||
// const colwise moved to DenseBase.h due to CUDA compiler bug
|
||||
|
||||
@@ -793,6 +793,12 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 nextafter(const bfloat16& from, c
|
||||
return numext::bit_cast<bfloat16>(from_bits);
|
||||
}
|
||||
|
||||
// Specialize multiply-add to match packet operations and reduce conversions to/from float.
|
||||
template<>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::bfloat16 madd<Eigen::bfloat16>(const Eigen::bfloat16& x, const Eigen::bfloat16& y, const Eigen::bfloat16& z) {
|
||||
return Eigen::bfloat16(static_cast<float>(x) * static_cast<float>(y) + static_cast<float>(z));
|
||||
}
|
||||
|
||||
} // namespace numext
|
||||
} // namespace Eigen
|
||||
|
||||
|
||||
@@ -955,6 +955,12 @@ EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC uint16_t bit_cast<uint16_t, Eigen::half>(c
|
||||
return Eigen::half_impl::raw_half_as_uint16(src);
|
||||
}
|
||||
|
||||
// Specialize multiply-add to match packet operations and reduce conversions to/from float.
|
||||
template<>
|
||||
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half madd<Eigen::half>(const Eigen::half& x, const Eigen::half& y, const Eigen::half& z) {
|
||||
return Eigen::half(static_cast<float>(x) * static_cast<float>(y) + static_cast<float>(z));
|
||||
}
|
||||
|
||||
} // namespace numext
|
||||
} // namespace Eigen
|
||||
|
||||
|
||||
@@ -399,9 +399,26 @@ EIGEN_STRONG_INLINE Packet8f pnegate(const Packet8f& a) {
|
||||
return pnegate_hvx(a);
|
||||
}
|
||||
|
||||
template <HVXPacketSize T>
|
||||
EIGEN_STRONG_INLINE HVXPacket<T> ptrue_hvx(const HVXPacket<T>& a) {
|
||||
return HVXPacket<T>::Create(Q6_V_vsplat_R(0x3f800000));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet32f ptrue(const Packet32f& a) {
|
||||
return ptrue_hvx(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16f ptrue(const Packet16f& a) {
|
||||
return ptrue_hvx(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet8f ptrue(const Packet8f& a) {
|
||||
return ptrue_hvx(a);
|
||||
}
|
||||
|
||||
template <HVXPacketSize T>
|
||||
EIGEN_STRONG_INLINE HVXPacket<T> pcmp_le_hvx(const HVXPacket<T>& a, const HVXPacket<T>& b) {
|
||||
HVX_Vector v_true = Q6_V_vsplat_R(0x3f800000);
|
||||
HVX_Vector v_true = ptrue(a).Get();
|
||||
HVX_VectorPred pred = Q6_Q_vcmp_gt_VsfVsf(a.Get(), b.Get());
|
||||
return HVXPacket<T>::Create(Q6_V_vmux_QVV(pred, Q6_V_vzero(), v_true));
|
||||
}
|
||||
@@ -420,7 +437,7 @@ EIGEN_STRONG_INLINE Packet8f pcmp_le(const Packet8f& a, const Packet8f& b) {
|
||||
|
||||
template <HVXPacketSize T>
|
||||
EIGEN_STRONG_INLINE HVXPacket<T> pcmp_eq_hvx(const HVXPacket<T>& a, const HVXPacket<T>& b) {
|
||||
HVX_Vector v_true = Q6_V_vsplat_R(0x3f800000);
|
||||
HVX_Vector v_true = ptrue(a).Get();
|
||||
HVX_VectorPred pred = Q6_Q_vcmp_eq_VwVw(a.Get(), b.Get());
|
||||
return HVXPacket<T>::Create(Q6_V_vmux_QVV(pred, v_true, Q6_V_vzero()));
|
||||
}
|
||||
@@ -439,7 +456,7 @@ EIGEN_STRONG_INLINE Packet8f pcmp_eq(const Packet8f& a, const Packet8f& b) {
|
||||
|
||||
template <HVXPacketSize T>
|
||||
EIGEN_STRONG_INLINE HVXPacket<T> pcmp_lt_hvx(const HVXPacket<T>& a, const HVXPacket<T>& b) {
|
||||
HVX_Vector v_true = Q6_V_vsplat_R(0x3f800000);
|
||||
HVX_Vector v_true = ptrue(a).Get();
|
||||
HVX_VectorPred pred = Q6_Q_vcmp_gt_VsfVsf(b.Get(), a.Get());
|
||||
return HVXPacket<T>::Create(Q6_V_vmux_QVV(pred, v_true, Q6_V_vzero()));
|
||||
}
|
||||
@@ -458,7 +475,7 @@ EIGEN_STRONG_INLINE Packet8f pcmp_lt(const Packet8f& a, const Packet8f& b) {
|
||||
|
||||
template <HVXPacketSize T>
|
||||
EIGEN_STRONG_INLINE HVXPacket<T> pcmp_lt_or_nan_hvx(const HVXPacket<T>& a, const HVXPacket<T>& b) {
|
||||
HVX_Vector v_true = Q6_V_vsplat_R(0x3f800000);
|
||||
HVX_Vector v_true = ptrue(a).Get();
|
||||
HVX_VectorPred pred = Q6_Q_vcmp_gt_VsfVsf(b.Get(), a.Get());
|
||||
return HVXPacket<T>::Create(Q6_V_vmux_QVV(pred, v_true, Q6_V_vzero()));
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ struct packet_traits<bool> : default_packet_traits {
|
||||
AlignedOnScalar = 1,
|
||||
size = 16,
|
||||
|
||||
HasCmp = 1, // note -- only pcmp_eq is defined
|
||||
HasCmp = 1,
|
||||
HasShift = 0,
|
||||
HasAbs = 0,
|
||||
HasAbs2 = 0,
|
||||
@@ -883,7 +883,14 @@ template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui pandnot<Packet4ui>(const Packet4ui& a, const Packet4ui& b) {
|
||||
return _mm_andnot_si128(b, a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16b pandnot<Packet16b>(const Packet16b& a, const Packet16b& b) {
|
||||
return _mm_andnot_si128(b, a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16b pcmp_lt(const Packet16b& a, const Packet16b& b) {
|
||||
return _mm_andnot_si128(a, b);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pcmp_le(const Packet4f& a, const Packet4f& b) {
|
||||
return _mm_cmple_ps(a, b);
|
||||
@@ -963,6 +970,10 @@ EIGEN_STRONG_INLINE Packet16b pcmp_eq(const Packet16b& a, const Packet16b& b) {
|
||||
return _mm_and_si128(_mm_cmpeq_epi8(a, b), kBoolMask);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet16b pcmp_le(const Packet16b& a, const Packet16b& b) {
|
||||
return por(pcmp_lt(a, b), pcmp_eq(a, b));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4ui pcmp_eq(const Packet4ui& a, const Packet4ui& b) {
|
||||
return _mm_cmpeq_epi32(a, b);
|
||||
}
|
||||
@@ -2026,38 +2037,38 @@ EIGEN_STRONG_INLINE Packet2d pblend(const Selector<2>& ifPacket, const Packet2d&
|
||||
}
|
||||
|
||||
// Scalar path for pmadd with FMA to ensure consistency with vectorized path.
|
||||
#ifdef EIGEN_VECTORIZE_FMA
|
||||
#if defined(EIGEN_VECTORIZE_FMA)
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float pmadd(const float& a, const float& b, const float& c) {
|
||||
return ::fmaf(a, b, c);
|
||||
return std::fmaf(a, b, c);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double pmadd(const double& a, const double& b, const double& c) {
|
||||
return ::fma(a, b, c);
|
||||
return std::fma(a, b, c);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float pmsub(const float& a, const float& b, const float& c) {
|
||||
return ::fmaf(a, b, -c);
|
||||
return std::fmaf(a, b, -c);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double pmsub(const double& a, const double& b, const double& c) {
|
||||
return ::fma(a, b, -c);
|
||||
return std::fma(a, b, -c);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float pnmadd(const float& a, const float& b, const float& c) {
|
||||
return ::fmaf(-a, b, c);
|
||||
return std::fmaf(-a, b, c);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double pnmadd(const double& a, const double& b, const double& c) {
|
||||
return ::fma(-a, b, c);
|
||||
return std::fma(-a, b, c);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE float pnmsub(const float& a, const float& b, const float& c) {
|
||||
return ::fmaf(-a, b, -c);
|
||||
return std::fmaf(-a, b, -c);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE double pnmsub(const double& a, const double& b, const double& c) {
|
||||
return ::fma(-a, b, -c);
|
||||
return std::fma(-a, b, -c);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace internal {
|
||||
|
||||
#if !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ >= 12)
|
||||
inline Packet4ui p4ui_CONJ_XOR() {
|
||||
return {0x00000000, 0x80000000, 0x00000000, 0x80000000}; // vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO);
|
||||
return Packet4ui {0x00000000, 0x80000000, 0x00000000, 0x80000000}; // vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -178,7 +178,7 @@ EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) {
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) {
|
||||
return Packet1cd((Packet2d)vec_xor((Packet2d)a.v, (Packet2d)p2ul_CONJ_XOR2));
|
||||
return Packet1cd((Packet2d)vec_xor((Packet2d)a.v, (Packet2d)p2ul_CONJ_XOR2()));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet1cd pmul<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
|
||||
@@ -257,8 +257,27 @@ EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1c
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet1cd plog<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
|
||||
return plog_complex(a, b);
|
||||
EIGEN_STRONG_INLINE Packet1cd psqrt<Packet1cd>(const Packet1cd& a) {
|
||||
return psqrt_complex<Packet1cd>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2cf psqrt<Packet2cf>(const Packet2cf& a) {
|
||||
return psqrt_complex<Packet2cf>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet1cd plog<Packet1cd>(const Packet1cd& a) {
|
||||
return plog_complex<Packet1cd>(a);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2cf plog<Packet2cf>(const Packet2cf& a) {
|
||||
return plog_complex<Packet2cf>(a);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2cf pexp<Packet2cf>(const Packet2cf& a) {
|
||||
return pexp_complex(a);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet1cd pcplxflip /*<Packet1cd>*/ (const Packet1cd& x) {
|
||||
@@ -437,16 +456,6 @@ EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2c
|
||||
return pdiv_complex(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2cf plog<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
|
||||
return plog_complex(a, b);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2cf pexp<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
|
||||
return pexp_complex(a, b);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE Packet2cf pcplxflip /*<Packet2cf>*/ (const Packet2cf& x) {
|
||||
Packet2cf res;
|
||||
res.cd[0] = pcplxflip(x.cd[0]);
|
||||
|
||||
@@ -23,6 +23,20 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(atanh, Packet2d)
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(log, Packet2d)
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(log2, Packet2d)
|
||||
EIGEN_DOUBLE_PACKET_FUNCTION(tanh, Packet2d)
|
||||
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(atanh, Packet4f)
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(log, Packet4f)
|
||||
EIGEN_FLOAT_PACKET_FUNCTION(log2, Packet4f)
|
||||
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(atan, Packet2d)
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(atan, Packet4f)
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(exp2, Packet2d)
|
||||
EIGEN_GENERIC_PACKET_FUNCTION(exp2, Packet4f)
|
||||
|
||||
#if !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ >= 12)
|
||||
static EIGEN_DECLARE_CONST_Packet4f(1, 1.0f);
|
||||
static EIGEN_DECLARE_CONST_Packet4f(half, 0.5f);
|
||||
@@ -170,7 +184,7 @@ EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet4f pexp<Packet4f>(cons
|
||||
y = padd(y, p4f_1);
|
||||
|
||||
// build 2^n
|
||||
emm0 = (Packet4i){(int)fx[0], (int)fx[1], (int)fx[2], (int)fx[3]};
|
||||
emm0 = Packet4i{(int)fx[0], (int)fx[1], (int)fx[2], (int)fx[3]};
|
||||
emm0 = emm0 + p4i_0x7f;
|
||||
emm0 = emm0 << reinterpret_cast<Packet4i>(p4i_23);
|
||||
|
||||
|
||||
@@ -251,6 +251,7 @@ struct unpacket_traits<Packet4f> {
|
||||
masked_store_available = false
|
||||
};
|
||||
typedef Packet4f half;
|
||||
typedef Packet4i integer_packet;
|
||||
};
|
||||
template <>
|
||||
struct unpacket_traits<Packet2d> {
|
||||
@@ -263,6 +264,7 @@ struct unpacket_traits<Packet2d> {
|
||||
masked_store_available = false
|
||||
};
|
||||
typedef Packet2d half;
|
||||
typedef Packet2l integer_packet;
|
||||
};
|
||||
|
||||
/* Forward declaration */
|
||||
@@ -314,38 +316,36 @@ inline std::ostream& operator<<(std::ostream& s, const Packet4f& v) {
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4i pload<Packet4i>(const int* from) {
|
||||
// FIXME: No intrinsic yet
|
||||
EIGEN_DEBUG_ALIGNED_LOAD
|
||||
Packet* vfrom;
|
||||
vfrom = (Packet*)from;
|
||||
return vfrom->v4i;
|
||||
return vec_xl(0, from);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pload<Packet2d>(const double* from) {
|
||||
// FIXME: No intrinsic yet
|
||||
EIGEN_DEBUG_ALIGNED_LOAD
|
||||
Packet* vfrom;
|
||||
vfrom = (Packet*)from;
|
||||
return vfrom->v2d;
|
||||
return vec_xl(0, from);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstore<int>(int* to, const Packet4i& from) {
|
||||
// FIXME: No intrinsic yet
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
Packet* vto;
|
||||
vto = (Packet*)to;
|
||||
vto->v4i = from;
|
||||
vec_xst(from, 0, to);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstore<double>(double* to, const Packet2d& from) {
|
||||
// FIXME: No intrinsic yet
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
Packet* vto;
|
||||
vto = (Packet*)to;
|
||||
vto->v2d = from;
|
||||
vec_xst(from, 0, to);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pfrexp<Packet4f>(const Packet4f& a, Packet4f& exponent) {
|
||||
return pfrexp_generic(a, exponent);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pfrexp<Packet2d>(const Packet2d& a, Packet2d& exponent) {
|
||||
return pfrexp_generic(a, exponent);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -541,7 +541,8 @@ EIGEN_STRONG_INLINE Packet2d pandnot<Packet2d>(const Packet2d& a, const Packet2d
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pround<Packet2d>(const Packet2d& a) {
|
||||
return vec_round(a);
|
||||
/* Uses non-default rounding for vec_round */
|
||||
return __builtin_s390_vfidb(a, 0, 1);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pceil<Packet2d>(const Packet2d& a) {
|
||||
@@ -591,6 +592,45 @@ EIGEN_STRONG_INLINE void prefetch<double>(const double* addr) {
|
||||
EIGEN_ZVECTOR_PREFETCH(addr);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet2l parithmetic_shift_right(const Packet2l& a) {
|
||||
return Packet2l { parithmetic_shift_right<N>(a[0]), parithmetic_shift_right<N>(a[1]) };
|
||||
}
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet4i parithmetic_shift_right(const Packet4i& a) {
|
||||
return Packet4i {
|
||||
parithmetic_shift_right<N>(a[0]),
|
||||
parithmetic_shift_right<N>(a[1]),
|
||||
parithmetic_shift_right<N>(a[2]),
|
||||
parithmetic_shift_right<N>(a[3]) };
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet2l plogical_shift_right(const Packet2l& a) {
|
||||
return Packet2l { plogical_shift_right<N>(a[0]), plogical_shift_right<N>(a[1]) };
|
||||
}
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet4i plogical_shift_right(const Packet4i& a) {
|
||||
return Packet4i {
|
||||
plogical_shift_right<N>(a[0]),
|
||||
plogical_shift_right<N>(a[1]),
|
||||
plogical_shift_right<N>(a[2]),
|
||||
plogical_shift_right<N>(a[3]) };
|
||||
}
|
||||
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet2l plogical_shift_left(const Packet2l& a) {
|
||||
return Packet2l { plogical_shift_left<N>(a[0]), plogical_shift_left<N>(a[1]) };
|
||||
}
|
||||
template <int N>
|
||||
EIGEN_STRONG_INLINE Packet4i plogical_shift_left(const Packet4i& a) {
|
||||
return Packet4i {
|
||||
plogical_shift_left<N>(a[0]),
|
||||
plogical_shift_left<N>(a[1]),
|
||||
plogical_shift_left<N>(a[2]),
|
||||
plogical_shift_left<N>(a[3]) };
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE int pfirst<Packet4i>(const Packet4i& a) {
|
||||
EIGEN_ALIGN16 int x[4];
|
||||
@@ -907,8 +947,8 @@ EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, const Packet4f
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pround<Packet4f>(const Packet4f& a) {
|
||||
Packet4f res;
|
||||
res.v4f[0] = vec_round(a.v4f[0]);
|
||||
res.v4f[1] = vec_round(a.v4f[1]);
|
||||
res.v4f[0] = generic_round(a.v4f[0]);
|
||||
res.v4f[1] = generic_round(a.v4f[1]);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1068,20 +1108,14 @@ Packet4f EIGEN_STRONG_INLINE pcmp_eq<Packet4f>(const Packet4f& a, const Packet4f
|
||||
#else
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pload<Packet4f>(const float* from) {
|
||||
// FIXME: No intrinsic yet
|
||||
EIGEN_DEBUG_ALIGNED_LOAD
|
||||
Packet* vfrom;
|
||||
vfrom = (Packet*)from;
|
||||
return vfrom->v4f;
|
||||
return vec_xl(0, from);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void pstore<float>(float* to, const Packet4f& from) {
|
||||
// FIXME: No intrinsic yet
|
||||
EIGEN_DEBUG_ALIGNED_STORE
|
||||
Packet* vto;
|
||||
vto = (Packet*)to;
|
||||
vto->v4f = from;
|
||||
vec_xst(from, 0, to);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1172,7 +1206,8 @@ EIGEN_STRONG_INLINE Packet4f pandnot<Packet4f>(const Packet4f& a, const Packet4f
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pround<Packet4f>(const Packet4f& a) {
|
||||
return vec_round(a);
|
||||
/* Uses non-default rounding for vec_round */
|
||||
return __builtin_s390_vfisb(a, 0, 1);
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pceil<Packet4f>(const Packet4f& a) {
|
||||
@@ -1263,6 +1298,28 @@ EIGEN_STRONG_INLINE Packet4f pblend(const Selector<4>& ifPacket, const Packet4f&
|
||||
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pldexp<Packet4f>(const Packet4f& a, const Packet4f& exponent) {
|
||||
return pldexp_generic(a, exponent);
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pldexp<Packet2d>(const Packet2d& a, const Packet2d& exponent) {
|
||||
// Clamp exponent to [-2099, 2099]
|
||||
const Packet2d max_exponent = pset1<Packet2d>(2099.0);
|
||||
const Packet2l e = pcast<Packet2d, Packet2l>(pmin(pmax(exponent, pnegate(max_exponent)), max_exponent));
|
||||
|
||||
// Split 2^e into four factors and multiply:
|
||||
const Packet2l bias = {1023, 1023};
|
||||
Packet2l b = plogical_shift_right<2>(e); // floor(e/4)
|
||||
Packet2d c = reinterpret_cast<Packet2d>(plogical_shift_left<52>(b + bias));
|
||||
Packet2d out = pmul(pmul(pmul(a, c), c), c); // a * 2^(3b)
|
||||
b = psub(psub(psub(e, b), b), b); // e - 3b
|
||||
c = reinterpret_cast<Packet2d>(plogical_shift_left<52>(b + bias)); // 2^(e - 3b)
|
||||
out = pmul(out, c); // a * 2^e
|
||||
return out;
|
||||
}
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE void prefetch<float>(const float* addr) {
|
||||
EIGEN_ZVECTOR_PREFETCH(addr);
|
||||
@@ -1280,6 +1337,75 @@ EIGEN_STRONG_INLINE Packet4f plset<Packet4f>(const float& a) {
|
||||
return padd<Packet4f>(pset1<Packet4f>(a), p4f_COUNTDOWN);
|
||||
}
|
||||
|
||||
#if !defined(vec_float) || !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ < 13)
|
||||
#pragma GCC warning \
|
||||
"float->int and int->float conversion is simulated. compile for z15 for improved performance"
|
||||
template <>
|
||||
struct cast_impl<Packet4i, Packet4f> {
|
||||
EIGEN_DEVICE_FUNC static inline Packet4f run(const Packet4i& a) {
|
||||
return Packet4f{float(a[0]), float(a[1]), float(a[2]), float(a[3]) };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct cast_impl<Packet4f, Packet4i> {
|
||||
EIGEN_DEVICE_FUNC static inline Packet4i run(const Packet4f& a) {
|
||||
return Packet4i{int(a[0]), int(a[1]), int(a[2]), int(a[3]) };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct cast_impl<Packet2l, Packet2d> {
|
||||
EIGEN_DEVICE_FUNC static inline Packet2d run(const Packet2l& a) {
|
||||
return Packet2d{double(a[0]), double(a[1]) };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct cast_impl<Packet2d, Packet2l> {
|
||||
EIGEN_DEVICE_FUNC static inline Packet2l run(const Packet2d& a) {
|
||||
return Packet2l{(long long)(a[0]), (long long)(a[1]) };
|
||||
}
|
||||
};
|
||||
#else
|
||||
template <>
|
||||
struct cast_impl<Packet4i, Packet4f> {
|
||||
EIGEN_DEVICE_FUNC static inline Packet4f run(const Packet4i& a) {
|
||||
return vec_float(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct cast_impl<Packet4f, Packet4i> {
|
||||
EIGEN_DEVICE_FUNC static inline Packet4i run(const Packet4f& a) {
|
||||
return vec_signed(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct cast_impl<Packet2l, Packet2d> {
|
||||
EIGEN_DEVICE_FUNC static inline Packet2d run(const Packet2l& a) {
|
||||
return vec_double(a);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct cast_impl<Packet2d, Packet2l> {
|
||||
EIGEN_DEVICE_FUNC static inline Packet2l run(const Packet2d& a) {
|
||||
return vec_signed(a);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet4f pset1frombits<Packet4f>(uint32_t from) {
|
||||
return pset1<Packet4f>(Eigen::numext::bit_cast<float>(from));
|
||||
}
|
||||
template <>
|
||||
EIGEN_STRONG_INLINE Packet2d pset1frombits<Packet2d>(uint64_t from) {
|
||||
return pset1<Packet2d>(Eigen::numext::bit_cast<double>(from));
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
@@ -47,7 +47,7 @@ inline void manage_multi_threading(Action action, int* v);
|
||||
// Public APIs.
|
||||
|
||||
/** Must be call first when calling Eigen from multiple threads */
|
||||
EIGEN_DEPRECATED inline void initParallel() {}
|
||||
EIGEN_DEPRECATED_WITH_REASON("Initialization is no longer needed.") inline void initParallel() {}
|
||||
|
||||
/** \returns the max number of threads reserved for Eigen
|
||||
* \sa setNbThreads */
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
#define EIGEN_VECTORIZE_SSE4_2
|
||||
#endif
|
||||
#ifdef __AVX__
|
||||
#ifndef EIGEN_USE_SYCL
|
||||
#if !defined(EIGEN_USE_SYCL) && !EIGEN_COMP_EMSCRIPTEN
|
||||
#define EIGEN_VECTORIZE_AVX
|
||||
#endif
|
||||
#define EIGEN_VECTORIZE_SSE3
|
||||
|
||||
@@ -171,6 +171,8 @@ template <typename MatrixType, unsigned int Mode>
|
||||
class TriangularView;
|
||||
template <typename MatrixType, unsigned int Mode>
|
||||
class SelfAdjointView;
|
||||
template <typename Derived>
|
||||
class RealView;
|
||||
template <typename MatrixType>
|
||||
class SparseView;
|
||||
template <typename ExpressionType>
|
||||
@@ -397,8 +399,6 @@ template <typename Scalar_, int Rows_, int Cols_,
|
||||
: EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION),
|
||||
int MaxRows_ = Rows_, int MaxCols_ = Cols_>
|
||||
class Array;
|
||||
template <typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
|
||||
class Select;
|
||||
template <typename MatrixType, typename BinaryOp, int Direction>
|
||||
class PartialReduxExpr;
|
||||
template <typename ExpressionType, int Direction>
|
||||
|
||||
@@ -17,13 +17,9 @@
|
||||
// Eigen version and basic defaults
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
#define EIGEN_WORLD_VERSION 3
|
||||
#define EIGEN_MAJOR_VERSION 4
|
||||
#define EIGEN_MINOR_VERSION 90
|
||||
|
||||
#define EIGEN_VERSION_AT_LEAST(x, y, z) \
|
||||
(EIGEN_WORLD_VERSION > x || \
|
||||
(EIGEN_WORLD_VERSION >= x && (EIGEN_MAJOR_VERSION > y || (EIGEN_MAJOR_VERSION >= y && EIGEN_MINOR_VERSION >= z))))
|
||||
(EIGEN_MAJOR_VERSION > x || \
|
||||
(EIGEN_MAJOR_VERSION >= x && (EIGEN_MINOR_VERSION > y || (EIGEN_MINOR_VERSION >= y && EIGEN_PATCH_VERSION >= z))))
|
||||
|
||||
#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
|
||||
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION Eigen::RowMajor
|
||||
@@ -944,6 +940,18 @@
|
||||
#define EIGEN_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_NO_DEPRECATED_WARNING
|
||||
#if EIGEN_COMP_GNUC
|
||||
#define EIGEN_DEPRECATED_WITH_REASON(message) __attribute__((deprecated(message)))
|
||||
#elif EIGEN_COMP_MSVC
|
||||
#define EIGEN_DEPRECATED_WITH_REASON(message) __declspec(deprecated(message))
|
||||
#else
|
||||
#define EIGEN_DEPRECATED_WITH_REASON(message)
|
||||
#endif
|
||||
#else
|
||||
#define EIGEN_DEPRECATED_WITH_REASON(message)
|
||||
#endif
|
||||
|
||||
#if EIGEN_COMP_GNUC
|
||||
#define EIGEN_UNUSED __attribute__((unused))
|
||||
#else
|
||||
|
||||
@@ -28,7 +28,8 @@ class Serializer;
|
||||
|
||||
// Specialization for POD types.
|
||||
template <typename T>
|
||||
class Serializer<T, typename std::enable_if_t<std::is_trivial<T>::value && std::is_standard_layout<T>::value>> {
|
||||
class Serializer<T,
|
||||
typename std::enable_if_t<std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value>> {
|
||||
public:
|
||||
/**
|
||||
* Determines the required size of the serialization buffer for a value.
|
||||
|
||||
@@ -409,7 +409,7 @@ inline void RealSchur<MatrixType>::computeShift(Index iu, Index iter, Scalar& ex
|
||||
shiftInfo.coeffRef(2) = m_matT.coeff(iu, iu - 1) * m_matT.coeff(iu - 1, iu);
|
||||
|
||||
// Alternate exceptional shifting strategy every 16 iterations.
|
||||
if (iter % 16 == 0) {
|
||||
if (iter > 0 && iter % 16 == 0) {
|
||||
// Wilkinson's original ad hoc shift
|
||||
if (iter % 32 != 0) {
|
||||
exshift += shiftInfo.coeff(0);
|
||||
|
||||
@@ -133,8 +133,8 @@ EIGEN_DEVICE_FUNC inline Matrix<typename MatrixBase<Derived>::Scalar, 3, 1> Matr
|
||||
* \sa class AngleAxis
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline Matrix<typename MatrixBase<Derived>::Scalar, 3, 1>
|
||||
MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const {
|
||||
EIGEN_DEVICE_FUNC inline Matrix<typename MatrixBase<Derived>::Scalar, 3, 1> MatrixBase<Derived>::eulerAngles(
|
||||
Index a0, Index a1, Index a2) const {
|
||||
/* Implemented from Graphics Gems IV */
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived, 3, 3)
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ class KLU : public SparseSolverBase<KLU<MatrixType_> > {
|
||||
factorize_impl();
|
||||
}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -182,7 +182,7 @@ class KLU : public SparseSolverBase<KLU<MatrixType_> > {
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the pattern anylysis has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the pattern anylysis has been performed.
|
||||
*
|
||||
* \sa analyzePattern(), compute()
|
||||
*/
|
||||
|
||||
@@ -147,7 +147,7 @@ class PardisoImpl : public SparseSolverBase<Derived> {
|
||||
* See the PARDISO manual to know how to use it. */
|
||||
ParameterType& pardisoParameterArray() { return m_iparm; }
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -157,7 +157,7 @@ class PardisoImpl : public SparseSolverBase<Derived> {
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed.
|
||||
*
|
||||
* \sa analyzePattern()
|
||||
*/
|
||||
|
||||
@@ -155,7 +155,8 @@ class BDCSVD : public SVDBase<BDCSVD<MatrixType_, Options_> > {
|
||||
* \deprecated Will be removed in the next major Eigen version. Options should
|
||||
* be specified in the \a Options template parameter.
|
||||
*/
|
||||
EIGEN_DEPRECATED BDCSVD(Index rows, Index cols, unsigned int computationOptions) : m_algoswap(16), m_numIters(0) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using the class template parameter.")
|
||||
BDCSVD(Index rows, Index cols, unsigned int computationOptions) : m_algoswap(16), m_numIters(0) {
|
||||
internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, rows, cols);
|
||||
allocate(rows, cols, computationOptions);
|
||||
}
|
||||
@@ -183,8 +184,8 @@ class BDCSVD : public SVDBase<BDCSVD<MatrixType_, Options_> > {
|
||||
* be specified in the \a Options template parameter.
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEPRECATED BDCSVD(const MatrixBase<Derived>& matrix, unsigned int computationOptions)
|
||||
: m_algoswap(16), m_numIters(0) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using the class template parameter.")
|
||||
BDCSVD(const MatrixBase<Derived>& matrix, unsigned int computationOptions) : m_algoswap(16), m_numIters(0) {
|
||||
internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
|
||||
compute_impl(matrix, computationOptions);
|
||||
}
|
||||
@@ -211,7 +212,8 @@ class BDCSVD : public SVDBase<BDCSVD<MatrixType_, Options_> > {
|
||||
* be specified in the \a Options template parameter.
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEPRECATED BDCSVD& compute(const MatrixBase<Derived>& matrix, unsigned int computationOptions) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using the class template parameter.")
|
||||
BDCSVD& compute(const MatrixBase<Derived>& matrix, unsigned int computationOptions) {
|
||||
internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, matrix.rows(), matrix.cols());
|
||||
return compute_impl(matrix, computationOptions);
|
||||
}
|
||||
|
||||
@@ -555,7 +555,8 @@ class JacobiSVD : public SVDBase<JacobiSVD<MatrixType_, Options_> > {
|
||||
* \deprecated Will be removed in the next major Eigen version. Options should
|
||||
* be specified in the \a Options template parameter.
|
||||
*/
|
||||
EIGEN_DEPRECATED JacobiSVD(Index rows, Index cols, unsigned int computationOptions) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using the class template parameter.")
|
||||
JacobiSVD(Index rows, Index cols, unsigned int computationOptions) {
|
||||
internal::check_svd_options_assertions<MatrixType, Options>(computationOptions, rows, cols);
|
||||
allocate(rows, cols, computationOptions);
|
||||
}
|
||||
@@ -610,7 +611,8 @@ class JacobiSVD : public SVDBase<JacobiSVD<MatrixType_, Options_> > {
|
||||
* be specified in the \a Options template parameter.
|
||||
*/
|
||||
template <typename Derived>
|
||||
EIGEN_DEPRECATED JacobiSVD& compute(const MatrixBase<Derived>& matrix, unsigned int computationOptions) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Options should be specified using the class template parameter.")
|
||||
JacobiSVD& compute(const MatrixBase<Derived>& matrix, unsigned int computationOptions) {
|
||||
internal::check_svd_options_assertions<MatrixBase<Derived>, Options>(m_computationOptions, matrix.rows(),
|
||||
matrix.cols());
|
||||
return compute_impl(matrix, computationOptions);
|
||||
|
||||
@@ -406,7 +406,7 @@ class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<MatrixType_, U
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -416,7 +416,7 @@ class SimplicialLLT : public SimplicialCholeskyBase<SimplicialLLT<MatrixType_, U
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed.
|
||||
*
|
||||
* \sa analyzePattern()
|
||||
*/
|
||||
@@ -494,7 +494,7 @@ class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<MatrixType_,
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -504,7 +504,7 @@ class SimplicialLDLT : public SimplicialCholeskyBase<SimplicialLDLT<MatrixType_,
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed.
|
||||
*
|
||||
* \sa analyzePattern()
|
||||
*/
|
||||
@@ -575,7 +575,7 @@ class SimplicialNonHermitianLLT
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -585,7 +585,7 @@ class SimplicialNonHermitianLLT
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed.
|
||||
*
|
||||
* \sa analyzePattern()
|
||||
*/
|
||||
@@ -664,7 +664,7 @@ class SimplicialNonHermitianLDLT
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -674,7 +674,7 @@ class SimplicialNonHermitianLDLT
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed.
|
||||
*
|
||||
* \sa analyzePattern()
|
||||
*/
|
||||
@@ -742,7 +742,7 @@ class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<Matr
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -757,7 +757,7 @@ class SimplicialCholesky : public SimplicialCholeskyBase<SimplicialCholesky<Matr
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed.
|
||||
*
|
||||
* \sa analyzePattern()
|
||||
*/
|
||||
|
||||
@@ -36,10 +36,10 @@ inline typename internal::traits<Derived>::Scalar SparseMatrixBase<Derived>::dot
|
||||
Scalar res1(0);
|
||||
Scalar res2(0);
|
||||
for (; i; ++i) {
|
||||
res1 = numext::fma(numext::conj(i.value()), other.coeff(i.index()), res1);
|
||||
res1 = numext::madd<Scalar>(numext::conj(i.value()), other.coeff(i.index()), res1);
|
||||
++i;
|
||||
if (i) {
|
||||
res2 = numext::fma(numext::conj(i.value()), other.coeff(i.index()), res2);
|
||||
res2 = numext::madd<Scalar>(numext::conj(i.value()), other.coeff(i.index()), res2);
|
||||
}
|
||||
}
|
||||
return res1 + res2;
|
||||
@@ -67,7 +67,7 @@ inline typename internal::traits<Derived>::Scalar SparseMatrixBase<Derived>::dot
|
||||
Scalar res(0);
|
||||
while (i && j) {
|
||||
if (i.index() == j.index()) {
|
||||
res = numext::fma(numext::conj(i.value()), j.value(), res);
|
||||
res = numext::madd<Scalar>(numext::conj(i.value()), j.value(), res);
|
||||
++i;
|
||||
++j;
|
||||
} else if (i.index() < j.index())
|
||||
|
||||
@@ -1130,7 +1130,11 @@ void set_from_triplets(const InputIterator& begin, const InputIterator& end, Spa
|
||||
using TransposedSparseMatrix =
|
||||
SparseMatrix<typename SparseMatrixType::Scalar, IsRowMajor ? ColMajor : RowMajor, StorageIndex>;
|
||||
|
||||
if (begin == end) return;
|
||||
if (begin == end) {
|
||||
// Clear out existing data (if any).
|
||||
mat.setZero();
|
||||
return;
|
||||
}
|
||||
|
||||
// There are two strategies to consider for constructing a matrix from unordered triplets:
|
||||
// A) construct the 'mat' in its native storage order and sort in-place (less memory); or,
|
||||
|
||||
@@ -224,33 +224,87 @@ class SparseMatrixBase : public EigenBase<Derived> {
|
||||
public:
|
||||
#ifndef EIGEN_NO_IO
|
||||
friend std::ostream& operator<<(std::ostream& s, const SparseMatrixBase& m) {
|
||||
typedef typename Derived::Nested Nested;
|
||||
typedef internal::remove_all_t<Nested> NestedCleaned;
|
||||
using Nested = typename Derived::Nested;
|
||||
using NestedCleaned = typename internal::remove_all<Nested>::type;
|
||||
|
||||
/// For converting `0's` to the matrices numerical type
|
||||
using Scalar = typename Derived::Scalar;
|
||||
|
||||
if (Flags & RowMajorBit) {
|
||||
Nested nm(m.derived());
|
||||
internal::evaluator<NestedCleaned> thisEval(nm);
|
||||
|
||||
// compute global width
|
||||
std::size_t width = 0;
|
||||
{
|
||||
std::ostringstream ss0;
|
||||
ss0.copyfmt(s);
|
||||
ss0 << Scalar(0);
|
||||
width = ss0.str().size();
|
||||
for (Index row = 0; row < nm.outerSize(); ++row) {
|
||||
for (typename internal::evaluator<NestedCleaned>::InnerIterator it(thisEval, row); it; ++it) {
|
||||
std::ostringstream ss;
|
||||
ss.copyfmt(s);
|
||||
ss << it.value();
|
||||
|
||||
const std::size_t potential_width = ss.str().size();
|
||||
if (potential_width > width) width = potential_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Index row = 0; row < nm.outerSize(); ++row) {
|
||||
Index col = 0;
|
||||
for (typename internal::evaluator<NestedCleaned>::InnerIterator it(thisEval, row); it; ++it) {
|
||||
for (; col < it.index(); ++col) s << "0 ";
|
||||
for (; col < it.index(); ++col) {
|
||||
s.width(width);
|
||||
s << Scalar(0) << " ";
|
||||
}
|
||||
s.width(width);
|
||||
s << it.value() << " ";
|
||||
++col;
|
||||
}
|
||||
for (; col < m.cols(); ++col) s << "0 ";
|
||||
for (; col < m.cols(); ++col) {
|
||||
s.width(width);
|
||||
s << Scalar(0) << " ";
|
||||
}
|
||||
s << std::endl;
|
||||
}
|
||||
} else {
|
||||
Nested nm(m.derived());
|
||||
internal::evaluator<NestedCleaned> thisEval(nm);
|
||||
if (m.cols() == 1) {
|
||||
// compute local width (single col)
|
||||
std::size_t width = 0;
|
||||
{
|
||||
std::ostringstream ss0;
|
||||
ss0.copyfmt(s);
|
||||
ss0 << Scalar(0);
|
||||
width = ss0.str().size();
|
||||
for (typename internal::evaluator<NestedCleaned>::InnerIterator it(thisEval, 0); it; ++it) {
|
||||
std::ostringstream ss;
|
||||
ss.copyfmt(s);
|
||||
ss << it.value();
|
||||
|
||||
const std::size_t potential_width = ss.str().size();
|
||||
if (potential_width > width) width = potential_width;
|
||||
}
|
||||
}
|
||||
|
||||
Index row = 0;
|
||||
for (typename internal::evaluator<NestedCleaned>::InnerIterator it(thisEval, 0); it; ++it) {
|
||||
for (; row < it.index(); ++row) s << "0" << std::endl;
|
||||
for (; row < it.index(); ++row) {
|
||||
s.width(width);
|
||||
s << Scalar(0) << std::endl;
|
||||
}
|
||||
s.width(width);
|
||||
s << it.value() << std::endl;
|
||||
++row;
|
||||
}
|
||||
for (; row < m.rows(); ++row) s << "0" << std::endl;
|
||||
for (; row < m.rows(); ++row) {
|
||||
s.width(width);
|
||||
s << Scalar(0) << std::endl;
|
||||
}
|
||||
} else {
|
||||
SparseMatrix<Scalar, RowMajorBit, StorageIndex> trans = m;
|
||||
s << static_cast<const SparseMatrixBase<SparseMatrix<Scalar, RowMajorBit, StorageIndex> >&>(trans);
|
||||
|
||||
@@ -354,40 +354,40 @@ class SparseVector : public SparseCompressedBase<SparseVector<Scalar_, Options_,
|
||||
|
||||
public:
|
||||
/** \internal \deprecated use setZero() and reserve() */
|
||||
EIGEN_DEPRECATED void startFill(Index reserve) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .setZero() and .reserve() instead.") void startFill(Index reserve) {
|
||||
setZero();
|
||||
m_data.reserve(reserve);
|
||||
}
|
||||
|
||||
/** \internal \deprecated use insertBack(Index,Index) */
|
||||
EIGEN_DEPRECATED Scalar& fill(Index r, Index c) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .insertBack() instead.") Scalar& fill(Index r, Index c) {
|
||||
eigen_assert(r == 0 || c == 0);
|
||||
return fill(IsColVector ? r : c);
|
||||
}
|
||||
|
||||
/** \internal \deprecated use insertBack(Index) */
|
||||
EIGEN_DEPRECATED Scalar& fill(Index i) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .insertBack() instead.") Scalar& fill(Index i) {
|
||||
m_data.append(0, i);
|
||||
return m_data.value(m_data.size() - 1);
|
||||
}
|
||||
|
||||
/** \internal \deprecated use insert(Index,Index) */
|
||||
EIGEN_DEPRECATED Scalar& fillrand(Index r, Index c) {
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .insert() instead.") Scalar& fillrand(Index r, Index c) {
|
||||
eigen_assert(r == 0 || c == 0);
|
||||
return fillrand(IsColVector ? r : c);
|
||||
}
|
||||
|
||||
/** \internal \deprecated use insert(Index) */
|
||||
EIGEN_DEPRECATED Scalar& fillrand(Index i) { return insert(i); }
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .insert() instead.") Scalar& fillrand(Index i) { return insert(i); }
|
||||
|
||||
/** \internal \deprecated use finalize() */
|
||||
EIGEN_DEPRECATED void endFill() {}
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .finalize() instead.") void endFill() {}
|
||||
|
||||
// These two functions were here in the 3.1 release, so let's keep them in case some code rely on them.
|
||||
/** \internal \deprecated use data() */
|
||||
EIGEN_DEPRECATED Storage& _data() { return m_data; }
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .data() instead.") Storage& _data() { return m_data; }
|
||||
/** \internal \deprecated use data() */
|
||||
EIGEN_DEPRECATED const Storage& _data() const { return m_data; }
|
||||
EIGEN_DEPRECATED_WITH_REASON("Use .data() instead.") const Storage& _data() const { return m_data; }
|
||||
|
||||
#ifdef EIGEN_SPARSEVECTOR_PLUGIN
|
||||
#include EIGEN_SPARSEVECTOR_PLUGIN
|
||||
|
||||
@@ -41,7 +41,7 @@ struct sparse_solve_triangular_selector<Lhs, Rhs, Mode, Lower, RowMajor> {
|
||||
lastVal = it.value();
|
||||
lastIndex = it.index();
|
||||
if (lastIndex == i) break;
|
||||
tmp = numext::fma(-lastVal, other.coeff(lastIndex, col), tmp);
|
||||
tmp = numext::madd<Scalar>(-lastVal, other.coeff(lastIndex, col), tmp);
|
||||
}
|
||||
if (Mode & UnitDiag)
|
||||
other.coeffRef(i, col) = tmp;
|
||||
@@ -75,7 +75,7 @@ struct sparse_solve_triangular_selector<Lhs, Rhs, Mode, Upper, RowMajor> {
|
||||
} else if (it && it.index() == i)
|
||||
++it;
|
||||
for (; it; ++it) {
|
||||
tmp = numext::fma(-it.value(), other.coeff(it.index(), col), tmp);
|
||||
tmp = numext::madd<Scalar>(-it.value(), other.coeff(it.index(), col), tmp);
|
||||
}
|
||||
|
||||
if (Mode & UnitDiag)
|
||||
@@ -108,7 +108,7 @@ struct sparse_solve_triangular_selector<Lhs, Rhs, Mode, Lower, ColMajor> {
|
||||
}
|
||||
if (it && it.index() == i) ++it;
|
||||
for (; it; ++it) {
|
||||
other.coeffRef(it.index(), col) = numext::fma(-tmp, it.value(), other.coeffRef(it.index(), col));
|
||||
other.coeffRef(it.index(), col) = numext::madd<Scalar>(-tmp, it.value(), other.coeffRef(it.index(), col));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,7 @@ struct sparse_solve_triangular_selector<Lhs, Rhs, Mode, Upper, ColMajor> {
|
||||
}
|
||||
LhsIterator it(lhsEval, i);
|
||||
for (; it && it.index() < i; ++it) {
|
||||
other.coeffRef(it.index(), col) = numext::fma(-tmp, it.value(), other.coeffRef(it.index(), col));
|
||||
other.coeffRef(it.index(), col) = numext::madd<Scalar>(-tmp, it.value(), other.coeffRef(it.index(), col));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,11 +220,11 @@ struct sparse_solve_triangular_sparse_selector<Lhs, Rhs, Mode, UpLo, ColMajor> {
|
||||
if (IsLower) {
|
||||
if (it.index() == i) ++it;
|
||||
for (; it; ++it) {
|
||||
tempVector.coeffRef(it.index()) = numext::fma(-ci, it.value(), tempVector.coeffRef(it.index()));
|
||||
tempVector.coeffRef(it.index()) = numext::madd<Scalar>(-ci, it.value(), tempVector.coeffRef(it.index()));
|
||||
}
|
||||
} else {
|
||||
for (; it && it.index() < i; ++it) {
|
||||
tempVector.coeffRef(it.index()) = numext::fma(-ci, it.value(), tempVector.coeffRef(it.index()));
|
||||
tempVector.coeffRef(it.index()) = numext::madd<Scalar>(-ci, it.value(), tempVector.coeffRef(it.index()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ class SuperLUBase : public SparseSolverBase<Derived> {
|
||||
derived().factorize(matrix);
|
||||
}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -473,7 +473,7 @@ class SuperLU : public SuperLUBase<MatrixType_, SuperLU<MatrixType_> > {
|
||||
|
||||
~SuperLU() {}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -487,7 +487,7 @@ class SuperLU : public SuperLUBase<MatrixType_, SuperLU<MatrixType_> > {
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed.
|
||||
*
|
||||
* \sa analyzePattern()
|
||||
*/
|
||||
@@ -781,7 +781,7 @@ class SuperILU : public SuperLUBase<MatrixType_, SuperILU<MatrixType_> > {
|
||||
|
||||
~SuperILU() {}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -791,7 +791,7 @@ class SuperILU : public SuperLUBase<MatrixType_, SuperILU<MatrixType_> > {
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed.
|
||||
*
|
||||
* \sa analyzePattern()
|
||||
*/
|
||||
|
||||
@@ -381,7 +381,7 @@ class UmfPackLU : public SparseSolverBase<UmfPackLU<MatrixType_> > {
|
||||
factorize_impl();
|
||||
}
|
||||
|
||||
/** Performs a symbolic decomposition on the sparcity of \a matrix.
|
||||
/** Performs a symbolic decomposition on the sparsity of \a matrix.
|
||||
*
|
||||
* This function is particularly useful when solving for several problems having the same structure.
|
||||
*
|
||||
@@ -425,7 +425,7 @@ class UmfPackLU : public SparseSolverBase<UmfPackLU<MatrixType_> > {
|
||||
|
||||
/** Performs a numeric decomposition of \a matrix
|
||||
*
|
||||
* The given matrix must has the same sparcity than the matrix on which the pattern anylysis has been performed.
|
||||
* The given matrix must has the same sparsity than the matrix on which the pattern anylysis has been performed.
|
||||
*
|
||||
* \sa analyzePattern(), compute()
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@ set(EigenBlas_SRCS single.cpp double.cpp complex_single.cpp complex_double.cpp
|
||||
|
||||
set(EIGEN_BLAS_TARGETS "")
|
||||
|
||||
add_library(eigen_blas_static ${EigenBlas_SRCS})
|
||||
add_library(eigen_blas_static STATIC ${EigenBlas_SRCS})
|
||||
list(APPEND EIGEN_BLAS_TARGETS eigen_blas_static)
|
||||
|
||||
if (EIGEN_BUILD_SHARED_LIBS)
|
||||
|
||||
13
blas/blas.h
13
blas/blas.h
@@ -464,6 +464,19 @@ void BLASFUNC(zher2m)(const char *, const char *, const char *, const int *, con
|
||||
void BLASFUNC(xher2m)(const char *, const char *, const char *, const int *, const int *, const double *,
|
||||
const double *, const int *, const double *, const int *, const double *, double *, const int *);
|
||||
|
||||
void BLASFUNC(sgemmtr)(const char *, const char *, const char *, const int *, const int *, const float *, const float *,
|
||||
const int *, const float *, const int *, const float *, float *, const int *);
|
||||
void BLASFUNC(dgemmtr)(const char *, const char *, const char *, const int *, const int *, const double *,
|
||||
const double *, const int *, const double *, const int *, const double *, double *, const int *);
|
||||
void BLASFUNC(qgemmtr)(const char *, const char *, const char *, const int *, const int *, const double *,
|
||||
const double *, const int *, const double *, const int *, const double *, double *, const int *);
|
||||
void BLASFUNC(cgemmtr)(const char *, const char *, const char *, const int *, const int *, const float *, const float *,
|
||||
const int *, const float *, const int *, const float *, float *, const int *);
|
||||
void BLASFUNC(zgemmtr)(const char *, const char *, const char *, const int *, const int *, const double *,
|
||||
const double *, const int *, const double *, const int *, const double *, double *, const int *);
|
||||
void BLASFUNC(xgemmtr)(const char *, const char *, const char *, const int *, const int *, const double *,
|
||||
const double *, const int *, const double *, const int *, const double *, double *, const int *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,15 +6,12 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include <iostream>
|
||||
#include "common.h"
|
||||
|
||||
EIGEN_BLAS_FUNC(gemm)
|
||||
(const char *opa, const char *opb, const int *m, const int *n, const int *k, const RealScalar *palpha,
|
||||
const RealScalar *pa, const int *lda, const RealScalar *pb, const int *ldb, const RealScalar *pbeta, RealScalar *pc,
|
||||
const int *ldc) {
|
||||
// std::cerr << "in gemm " << *opa << " " << *opb << " " << *m << " " << *n << " " << *k << " " << *lda << " " <<
|
||||
// *ldb << " " << *ldc << " " << *palpha << " " << *pbeta << "\n";
|
||||
using Eigen::ColMajor;
|
||||
using Eigen::DenseIndex;
|
||||
using Eigen::Dynamic;
|
||||
@@ -97,11 +94,141 @@ EIGEN_BLAS_FUNC(gemm)
|
||||
func[code](*m, *n, *k, a, *lda, b, *ldb, c, 1, *ldc, alpha, blocking, 0);
|
||||
}
|
||||
|
||||
EIGEN_BLAS_FUNC(gemmtr)
|
||||
(const char *uplo, const char *opa, const char *opb, const int *n, const int *k, const RealScalar *palpha,
|
||||
const RealScalar *pa, const int *lda, const RealScalar *pb, const int *ldb, const RealScalar *pbeta, RealScalar *pc,
|
||||
const int *ldc) {
|
||||
using Eigen::ColMajor;
|
||||
using Eigen::DenseIndex;
|
||||
using Eigen::Dynamic;
|
||||
using Eigen::Lower;
|
||||
using Eigen::RowMajor;
|
||||
using Eigen::Upper;
|
||||
typedef void (*functype)(DenseIndex, DenseIndex, const Scalar *, DenseIndex, const Scalar *, DenseIndex, Scalar *,
|
||||
DenseIndex, DenseIndex, const Scalar &, Eigen::internal::level3_blocking<Scalar, Scalar> &);
|
||||
static const functype func[24] = {
|
||||
// Upper-triangular result.
|
||||
// array index: NOTR | (NOTR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, ColMajor, false, Scalar, ColMajor,
|
||||
false, ColMajor, 1, Upper>::run),
|
||||
// array index: TR | (NOTR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, false, Scalar, ColMajor,
|
||||
false, ColMajor, 1, Upper>::run),
|
||||
// array index: ADJ | (NOTR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, Conj, Scalar, ColMajor,
|
||||
false, ColMajor, 1, Upper>::run),
|
||||
0,
|
||||
// array index: NOTR | (TR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, ColMajor, false, Scalar, RowMajor,
|
||||
false, ColMajor, 1, Upper>::run),
|
||||
// array index: TR | (TR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, false, Scalar, RowMajor,
|
||||
false, ColMajor, 1, Upper>::run),
|
||||
// array index: ADJ | (TR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, Conj, Scalar, RowMajor,
|
||||
false, ColMajor, 1, Upper>::run),
|
||||
0,
|
||||
// array index: NOTR | (ADJ << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, ColMajor, false, Scalar, RowMajor,
|
||||
Conj, ColMajor, 1, Upper>::run),
|
||||
// array index: TR | (ADJ << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, false, Scalar, RowMajor,
|
||||
Conj, ColMajor, 1, Upper>::run),
|
||||
// array index: ADJ | (ADJ << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, Conj, Scalar, RowMajor,
|
||||
Conj, ColMajor, 1, Upper>::run),
|
||||
0,
|
||||
|
||||
// Lower-triangular result.
|
||||
// array index: NOTR | (NOTR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, ColMajor, false, Scalar, ColMajor,
|
||||
false, ColMajor, 1, Lower>::run),
|
||||
// array index: TR | (NOTR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, false, Scalar, ColMajor,
|
||||
false, ColMajor, 1, Lower>::run),
|
||||
// array index: ADJ | (NOTR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, Conj, Scalar, ColMajor,
|
||||
false, ColMajor, 1, Lower>::run),
|
||||
0,
|
||||
// array index: NOTR | (TR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, ColMajor, false, Scalar, RowMajor,
|
||||
false, ColMajor, 1, Lower>::run),
|
||||
// array index: TR | (TR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, false, Scalar, RowMajor,
|
||||
false, ColMajor, 1, Lower>::run),
|
||||
// array index: ADJ | (TR << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, Conj, Scalar, RowMajor,
|
||||
false, ColMajor, 1, Lower>::run),
|
||||
0,
|
||||
// array index: NOTR | (ADJ << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, ColMajor, false, Scalar, RowMajor,
|
||||
Conj, ColMajor, 1, Lower>::run),
|
||||
// array index: TR | (ADJ << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, false, Scalar, RowMajor,
|
||||
Conj, ColMajor, 1, Lower>::run),
|
||||
// array index: ADJ | (ADJ << 2)
|
||||
(Eigen::internal::general_matrix_matrix_triangular_product<DenseIndex, Scalar, RowMajor, Conj, Scalar, RowMajor,
|
||||
Conj, ColMajor, 1, Lower>::run),
|
||||
0,
|
||||
};
|
||||
|
||||
const Scalar *a = reinterpret_cast<const Scalar *>(pa);
|
||||
const Scalar *b = reinterpret_cast<const Scalar *>(pb);
|
||||
Scalar *c = reinterpret_cast<Scalar *>(pc);
|
||||
Scalar alpha = *reinterpret_cast<const Scalar *>(palpha);
|
||||
Scalar beta = *reinterpret_cast<const Scalar *>(pbeta);
|
||||
|
||||
int info = 0;
|
||||
if (UPLO(*uplo) == INVALID)
|
||||
info = 1;
|
||||
else if (OP(*opa) == INVALID)
|
||||
info = 2;
|
||||
else if (OP(*opb) == INVALID)
|
||||
info = 3;
|
||||
else if (*n < 0)
|
||||
info = 4;
|
||||
else if (*k < 0)
|
||||
info = 5;
|
||||
else if (*lda < std::max(1, (OP(*opa) == NOTR) ? *n : *k))
|
||||
info = 8;
|
||||
else if (*ldb < std::max(1, (OP(*opb) == NOTR) ? *k : *n))
|
||||
info = 10;
|
||||
else if (*ldc < std::max(1, *n))
|
||||
info = 13;
|
||||
if (info) return xerbla_(SCALAR_SUFFIX_UP "GEMMTR ", &info);
|
||||
|
||||
if (*n == 0) return;
|
||||
|
||||
const int upper = (UPLO(*uplo) == UP);
|
||||
|
||||
if (beta != Scalar(1)) {
|
||||
if (beta == Scalar(0)) {
|
||||
if (upper) {
|
||||
matrix(c, *n, *n, *ldc).triangularView<Eigen::Upper>().setZero();
|
||||
} else {
|
||||
matrix(c, *n, *n, *ldc).triangularView<Eigen::Lower>().setZero();
|
||||
}
|
||||
} else {
|
||||
if (upper) {
|
||||
matrix(c, *n, *n, *ldc).triangularView<Eigen::Upper>() *= beta;
|
||||
} else {
|
||||
matrix(c, *n, *n, *ldc).triangularView<Eigen::Lower>() *= beta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*k == 0) return;
|
||||
|
||||
Eigen::internal::gemm_blocking_space<ColMajor, Scalar, Scalar, Dynamic, Dynamic, Dynamic> blocking(*n, *n, *k, 1,
|
||||
false);
|
||||
|
||||
int code = OP(*opa) | (OP(*opb) << 2) + (UPLO(*uplo) * 12);
|
||||
func[code](*n, *k, a, *lda, b, *ldb, c, 1, *ldc, alpha, blocking);
|
||||
}
|
||||
|
||||
EIGEN_BLAS_FUNC(trsm)
|
||||
(const char *side, const char *uplo, const char *opa, const char *diag, const int *m, const int *n,
|
||||
const RealScalar *palpha, const RealScalar *pa, const int *lda, RealScalar *pb, const int *ldb) {
|
||||
// std::cerr << "in trsm " << *side << " " << *uplo << " " << *opa << " " << *diag << " " << *m << "," << *n << " "
|
||||
// << *palpha << " " << *lda << " " << *ldb<< "\n";
|
||||
using Eigen::ColMajor;
|
||||
using Eigen::DenseIndex;
|
||||
using Eigen::Dynamic;
|
||||
@@ -240,8 +367,6 @@ EIGEN_BLAS_FUNC(trsm)
|
||||
EIGEN_BLAS_FUNC(trmm)
|
||||
(const char *side, const char *uplo, const char *opa, const char *diag, const int *m, const int *n,
|
||||
const RealScalar *palpha, const RealScalar *pa, const int *lda, RealScalar *pb, const int *ldb) {
|
||||
// std::cerr << "in trmm " << *side << " " << *uplo << " " << *opa << " " << *diag << " " << *m << " " << *n << " "
|
||||
// << *lda << " " << *ldb << " " << *palpha << "\n";
|
||||
using Eigen::ColMajor;
|
||||
using Eigen::DenseIndex;
|
||||
using Eigen::Dynamic;
|
||||
@@ -381,8 +506,6 @@ EIGEN_BLAS_FUNC(trmm)
|
||||
EIGEN_BLAS_FUNC(symm)
|
||||
(const char *side, const char *uplo, const int *m, const int *n, const RealScalar *palpha, const RealScalar *pa,
|
||||
const int *lda, const RealScalar *pb, const int *ldb, const RealScalar *pbeta, RealScalar *pc, const int *ldc) {
|
||||
// std::cerr << "in symm " << *side << " " << *uplo << " " << *m << "x" << *n << " lda:" << *lda << " ldb:" << *ldb
|
||||
// << " ldc:" << *ldc << " alpha:" << *palpha << " beta:" << *pbeta << "\n";
|
||||
const Scalar *a = reinterpret_cast<const Scalar *>(pa);
|
||||
const Scalar *b = reinterpret_cast<const Scalar *>(pb);
|
||||
Scalar *c = reinterpret_cast<Scalar *>(pc);
|
||||
@@ -472,8 +595,6 @@ EIGEN_BLAS_FUNC(symm)
|
||||
EIGEN_BLAS_FUNC(syrk)
|
||||
(const char *uplo, const char *op, const int *n, const int *k, const RealScalar *palpha, const RealScalar *pa,
|
||||
const int *lda, const RealScalar *pbeta, RealScalar *pc, const int *ldc) {
|
||||
// std::cerr << "in syrk " << *uplo << " " << *op << " " << *n << " " << *k << " " << *palpha << " " << *lda << " "
|
||||
// << *pbeta << " " << *ldc << "\n";
|
||||
using Eigen::ColMajor;
|
||||
using Eigen::DenseIndex;
|
||||
using Eigen::Dynamic;
|
||||
@@ -577,9 +698,6 @@ EIGEN_BLAS_FUNC(syr2k)
|
||||
Scalar alpha = *reinterpret_cast<const Scalar *>(palpha);
|
||||
Scalar beta = *reinterpret_cast<const Scalar *>(pbeta);
|
||||
|
||||
// std::cerr << "in syr2k " << *uplo << " " << *op << " " << *n << " " << *k << " " << alpha << " " << *lda << " "
|
||||
// << *ldb << " " << beta << " " << *ldc << "\n";
|
||||
|
||||
int info = 0;
|
||||
if (UPLO(*uplo) == INVALID)
|
||||
info = 1;
|
||||
@@ -647,9 +765,6 @@ EIGEN_BLAS_FUNC(hemm)
|
||||
Scalar alpha = *reinterpret_cast<const Scalar *>(palpha);
|
||||
Scalar beta = *reinterpret_cast<const Scalar *>(pbeta);
|
||||
|
||||
// std::cerr << "in hemm " << *side << " " << *uplo << " " << *m << " " << *n << " " << alpha << " " << *lda << " "
|
||||
// << beta << " " << *ldc << "\n";
|
||||
|
||||
int info = 0;
|
||||
if (SIDE(*side) == INVALID)
|
||||
info = 1;
|
||||
@@ -719,8 +834,6 @@ RowMajor,true,Conj, ColMajor, 1>
|
||||
EIGEN_BLAS_FUNC(herk)
|
||||
(const char *uplo, const char *op, const int *n, const int *k, const RealScalar *palpha, const RealScalar *pa,
|
||||
const int *lda, const RealScalar *pbeta, RealScalar *pc, const int *ldc) {
|
||||
// std::cerr << "in herk " << *uplo << " " << *op << " " << *n << " " << *k << " " << *palpha << " " << *lda << " "
|
||||
// << *pbeta << " " << *ldc << "\n";
|
||||
using Eigen::ColMajor;
|
||||
using Eigen::DenseIndex;
|
||||
using Eigen::Dynamic;
|
||||
@@ -754,9 +867,6 @@ EIGEN_BLAS_FUNC(herk)
|
||||
RealScalar alpha = *palpha;
|
||||
RealScalar beta = *pbeta;
|
||||
|
||||
// std::cerr << "in herk " << *uplo << " " << *op << " " << *n << " " << *k << " " << alpha << " " << *lda << " " <<
|
||||
// beta << " " << *ldc << "\n";
|
||||
|
||||
int info = 0;
|
||||
if (UPLO(*uplo) == INVALID)
|
||||
info = 1;
|
||||
@@ -810,9 +920,6 @@ EIGEN_BLAS_FUNC(her2k)
|
||||
Scalar alpha = *reinterpret_cast<const Scalar *>(palpha);
|
||||
RealScalar beta = *pbeta;
|
||||
|
||||
// std::cerr << "in her2k " << *uplo << " " << *op << " " << *n << " " << *k << " " << alpha << " " << *lda << " "
|
||||
// << *ldb << " " << beta << " " << *ldc << "\n";
|
||||
|
||||
int info = 0;
|
||||
if (UPLO(*uplo) == INVALID)
|
||||
info = 1;
|
||||
@@ -875,4 +982,4 @@ EIGEN_BLAS_FUNC(her2k)
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ISCOMPLEX
|
||||
#endif
|
||||
|
||||
@@ -108,7 +108,7 @@ build:linux:docs:
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"
|
||||
|
||||
|
||||
@@ -144,10 +144,8 @@ build:linux:docs:
|
||||
-DEIGEN_CUDA_COMPUTE_ARCH=${EIGEN_CI_CUDA_COMPUTE_ARCH}
|
||||
-DEIGEN_TEST_CUDA_CLANG=${EIGEN_CI_TEST_CUDA_CLANG}
|
||||
tags:
|
||||
- eigen-runner
|
||||
- linux
|
||||
# Requires intel runner for cuda docker image support.
|
||||
- x86-64
|
||||
# Build on regular linux to limit GPU cost.
|
||||
- saas-linux-2xlarge-amd64
|
||||
|
||||
# NVidia no longer provides docker images < CUDA 11.0.3.
|
||||
# # GCC-7, CUDA-9.2
|
||||
@@ -228,10 +226,6 @@ build:linux:rocm-latest:gcc-10:
|
||||
EIGEN_CI_CXX_COMPILER: g++-10
|
||||
EIGEN_CI_BUILD_TARGET: buildtests_gpu
|
||||
EIGEN_CI_ADDITIONAL_ARGS: -DEIGEN_TEST_HIP=on
|
||||
tags:
|
||||
- eigen-runner
|
||||
- linux
|
||||
- x86-64
|
||||
|
||||
######## Arm ###################################################################
|
||||
|
||||
@@ -343,6 +337,8 @@ build:linux:cross:x86-64:gcc-10:default:smoketest:
|
||||
EIGEN_CI_BUILD_TARGET: buildsmoketests
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
|
||||
build:linux:cross:x86-64:clang-12:default:smoketest:
|
||||
extends: build:linux:cross:x86-64:clang-12:default
|
||||
@@ -350,3 +346,5 @@ build:linux:cross:x86-64:clang-12:default:smoketest:
|
||||
EIGEN_CI_BUILD_TARGET: buildsmoketests
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
|
||||
@@ -9,8 +9,7 @@ deploy:tag:nightly:
|
||||
- git tag -f nightly $CI_COMMIT_SHORT_SHA
|
||||
- git push -f $EIGEN_CI_GIT_PUSH_URL tag nightly
|
||||
tags:
|
||||
- linux
|
||||
- eigen-runner
|
||||
- saas-linux-small-amd64
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
@@ -33,11 +32,10 @@ deploy:docs:
|
||||
paths:
|
||||
- public
|
||||
tags:
|
||||
- eigen-runner
|
||||
- linux
|
||||
- saas-linux-small-amd64
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
|
||||
- if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
variables:
|
||||
PAGES_PREFIX: docs-$CI_COMMIT_REF_NAME
|
||||
|
||||
@@ -202,10 +202,7 @@ test:linux:x86-64:clang-12:avx512dq:unsupported:
|
||||
variables:
|
||||
EIGEN_CI_CTEST_LABEL: gpu
|
||||
tags:
|
||||
- eigen-runner
|
||||
- linux
|
||||
- x86-64
|
||||
- cuda
|
||||
- saas-linux-medium-amd64-gpu-standard
|
||||
|
||||
# NVidia no longer provides docker images < CUDA 11.0.3.
|
||||
# # GCC-7, CUDA-9.2
|
||||
@@ -441,6 +438,8 @@ test:linux:x86-64:gcc-10:default:smoketest:
|
||||
EIGEN_CI_CTEST_LABEL: smoketest
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
|
||||
test:linux:x86-64:clang-12:default:smoketest:
|
||||
extends: .test:linux:x86-64:clang-12:default
|
||||
@@ -449,3 +448,5 @@ test:linux:x86-64:clang-12:default:smoketest:
|
||||
EIGEN_CI_CTEST_LABEL: smoketest
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
tags:
|
||||
- saas-linux-small-amd64
|
||||
|
||||
@@ -453,6 +453,9 @@ macro(ei_set_sitename)
|
||||
endmacro()
|
||||
|
||||
macro(ei_get_compilerver VAR)
|
||||
if (NOT CMAKE_CXX_COMPILER_ID)
|
||||
set(CMAKE_CXX_COMPILER_ID "<unknown>")
|
||||
endif()
|
||||
if(MSVC)
|
||||
set(${VAR} "${CMAKE_CXX_COMPILER_VERSION}")
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "PGI")
|
||||
|
||||
14
cmake/Version.in
Normal file
14
cmake/Version.in
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef EIGEN_VERSION_H
|
||||
#define EIGEN_VERSION_H
|
||||
|
||||
// The "WORLD" version will forever remain "3" for the "Eigen3" library.
|
||||
#define EIGEN_WORLD_VERSION 3
|
||||
// As of Eigen3 5.0.0, we have moved to Semantic Versioning (semver.org).
|
||||
#define EIGEN_MAJOR_VERSION ${EIGEN_MAJOR_VERSION}
|
||||
#define EIGEN_MINOR_VERSION ${EIGEN_MINOR_VERSION}
|
||||
#define EIGEN_PATCH_VERSION ${EIGEN_PATCH_VERSION}
|
||||
#define EIGEN_PRERELEASE_VERSION "${EIGEN_PRERELEASE_VERSION}"
|
||||
#define EIGEN_BUILD_VERSION "${EIGEN_BUILD_VERSION}"
|
||||
#define EIGEN_VERSION_STRING "${EIGEN_VERSION_STRING}"
|
||||
|
||||
#endif // EIGEN_VERSION_H
|
||||
@@ -1,6 +1,6 @@
|
||||
# Doxyfile 1.13.0
|
||||
PROJECT_NAME = ${EIGEN_DOXY_PROJECT_NAME}
|
||||
PROJECT_NUMBER = ${EIGEN_VERSION}
|
||||
PROJECT_NUMBER = ${EIGEN_VERSION_STRING}
|
||||
PROJECT_LOGO = ${Eigen_SOURCE_DIR}/doc/Eigen_Silly_Professor_64x64.png
|
||||
OUTPUT_DIRECTORY = ${Eigen_BINARY_DIR}/doc${EIGEN_DOXY_OUTPUT_DIRECTORY_SUFFIX}
|
||||
FULL_PATH_NAMES = YES
|
||||
|
||||
@@ -178,7 +178,7 @@ For direct methods, the solution are computed at the machine precision. Sometime
|
||||
\section BenchmarkRoutine
|
||||
Most of the time, all you need is to know how much time it will take to solve your system, and hopefully, what is the most suitable solver. In Eigen, we provide a benchmark routine that can be used for this purpose. It is very easy to use. In the build directory, navigate to `bench/spbench` and compile the routine by typing `make spbenchsolver`. Run it with `--help` option to get the list of all available options. Basically, the matrices to test should be in <a href="http://math.nist.gov/MatrixMarket/formats.html">MatrixMarket Coordinate format</a>, and the routine returns the statistics from all available solvers in Eigen.
|
||||
|
||||
To export your matrices and right-hand-side vectors in the matrix-market format, you can the the unsupported SparseExtra module:
|
||||
To export your matrices and right-hand-side vectors in the matrix-market format, you can use the unsupported SparseExtra module:
|
||||
\code
|
||||
#include <unsupported/Eigen/SparseExtra>
|
||||
...
|
||||
|
||||
@@ -97,7 +97,7 @@ endif()
|
||||
|
||||
set(EIGEN_LAPACK_TARGETS "")
|
||||
|
||||
add_library(eigen_lapack_static ${EigenLapack_SRCS} ${ReferenceLapack_SRCS})
|
||||
add_library(eigen_lapack_static STATIC ${EigenLapack_SRCS} ${ReferenceLapack_SRCS})
|
||||
list(APPEND EIGEN_LAPACK_TARGETS eigen_lapack_static)
|
||||
|
||||
if (EIGEN_BUILD_SHARED_LIBS)
|
||||
|
||||
@@ -734,7 +734,7 @@ void comparisons(const ArrayType& m) {
|
||||
VERIFY_IS_CWISE_EQUAL(m1.abs().cwiseLessOrEqual(NumTraits<Scalar>::highest()), bool_true);
|
||||
VERIFY_IS_CWISE_EQUAL(m1.abs().cwiseGreaterOrEqual(Scalar(0)), bool_true);
|
||||
|
||||
// test Select
|
||||
// test select
|
||||
VERIFY_IS_APPROX((m1 < m2).select(m1, m2), m1.cwiseMin(m2));
|
||||
VERIFY_IS_APPROX((m1 > m2).select(m1, m2), m1.cwiseMax(m2));
|
||||
Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff()) / Scalar(2);
|
||||
|
||||
@@ -120,7 +120,7 @@ void comparisons(const MatrixType& m) {
|
||||
VERIFY((m1.array() == m1(r, c)).any());
|
||||
VERIFY(m1.cwiseEqual(m1(r, c)).any());
|
||||
|
||||
// test Select
|
||||
// test select
|
||||
VERIFY_IS_APPROX((m1.array() < m2.array()).select(m1, m2), m1.cwiseMin(m2));
|
||||
VERIFY_IS_APPROX((m1.array() > m2.array()).select(m1, m2), m1.cwiseMax(m2));
|
||||
Scalar mid = m1.cwiseAbs().minCoeff() / Scalar(2) + m1.cwiseAbs().maxCoeff() / Scalar(2);
|
||||
|
||||
@@ -340,7 +340,7 @@ EIGEN_DECLARE_TEST(evaluators) {
|
||||
matXcd_ref.imag() = mat2;
|
||||
VERIFY_IS_APPROX(matXcd, matXcd_ref);
|
||||
|
||||
// test Select
|
||||
// test select
|
||||
VERIFY_IS_APPROX_EVALUATOR(aX, (aXsrc > 0).select(aXsrc, -aXsrc));
|
||||
|
||||
// test Replicate
|
||||
|
||||
@@ -840,11 +840,21 @@ void check_tutorial_examples() {
|
||||
}
|
||||
}
|
||||
|
||||
void check_aliasing() {
|
||||
Eigen::Vector<float, 5> z = {0.0f, 1.1f, 2.2f, 3.3f, 4.4f};
|
||||
std::vector<int> left_indices = {0, 1, 3, 4};
|
||||
std::vector<int> right_indices = {1, 3, 4, 0};
|
||||
z(left_indices) = z(right_indices);
|
||||
Eigen::Vector<float, 5> expected = {1.1f, 3.3f, 2.2f, 4.4f, 0.0f};
|
||||
VERIFY_IS_EQUAL(z, expected);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(indexed_view) {
|
||||
for (int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1(check_indexed_view());
|
||||
}
|
||||
CALL_SUBTEST_1(check_tutorial_examples());
|
||||
CALL_SUBTEST_1(check_aliasing());
|
||||
|
||||
// static checks of some internals:
|
||||
STATIC_CHECK((internal::is_valid_index_type<int>::value));
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
@@ -44,16 +44,16 @@ template <typename Scalar>
|
||||
struct madd_impl<Scalar,
|
||||
std::enable_if_t<Eigen::internal::is_scalar<Scalar>::value && Eigen::NumTraits<Scalar>::IsSigned>> {
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar madd(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::fma(a, b, c);
|
||||
return numext::madd(a, b, c);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar msub(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::fma(a, b, Scalar(-c));
|
||||
return numext::madd(a, b, Scalar(-c));
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar nmadd(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return numext::fma(Scalar(-a), b, c);
|
||||
return numext::madd(Scalar(-a), b, c);
|
||||
}
|
||||
static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Scalar nmsub(const Scalar& a, const Scalar& b, const Scalar& c) {
|
||||
return -Scalar(numext::fma(a, b, c));
|
||||
return -Scalar(numext::madd(a, b, c));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ void permutationmatrices(const MatrixType& m) {
|
||||
RightTranspositionsType rt(rv);
|
||||
MatrixType m_permuted = MatrixType::Random(rows, cols);
|
||||
|
||||
VERIFY_EVALUATION_COUNT(m_permuted = lp * m_original * rp, 1); // 1 temp for sub expression "lp * m_original"
|
||||
VERIFY_EVALUATION_COUNT(m_permuted.noalias() = lp * m_original * rp,
|
||||
1); // 1 temp for sub expression "lp * m_original"
|
||||
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = 0; j < cols; j++) VERIFY_IS_APPROX(m_permuted(lv(i), j), m_original(i, rv(j)));
|
||||
@@ -50,7 +51,7 @@ void permutationmatrices(const MatrixType& m) {
|
||||
VERIFY_IS_APPROX(m_permuted, lm * m_original * rm);
|
||||
|
||||
m_permuted = m_original;
|
||||
VERIFY_EVALUATION_COUNT(m_permuted = lp * m_permuted * rp, 1);
|
||||
VERIFY_EVALUATION_COUNT(m_permuted.noalias() = lp * m_permuted * rp, 1);
|
||||
VERIFY_IS_APPROX(m_permuted, lm * m_original * rm);
|
||||
|
||||
LeftPermutationType lpi;
|
||||
@@ -169,6 +170,26 @@ void bug890() {
|
||||
VERIFY_IS_APPROX(v1, (P.inverse() * rhs).eval());
|
||||
}
|
||||
|
||||
void test_aliasing() {
|
||||
// Bug #2869.
|
||||
auto P = Eigen::PermutationMatrix<4>{Eigen::Vector4i{0, 2, 3, 1}};
|
||||
{
|
||||
Eigen::Vector<float, 5> z = {0.0f, 1.1f, 2.2f, 3.3f, 4.4f};
|
||||
Eigen::Vector<float, 5> expected = z;
|
||||
z.tail<4>() = P * z.head<4>();
|
||||
expected.tail<4>() = (P * expected.head<4>()).eval();
|
||||
VERIFY_IS_APPROX(z, expected);
|
||||
}
|
||||
|
||||
{
|
||||
// Obfuscate the aliasing in the RHS expression.
|
||||
Eigen::Vector4f a = {1.1f, 2.2f, 3.3f, 4.4f};
|
||||
Eigen::Vector4f expected = P * (a + Eigen::Vector4f::Zero()).cwiseSqrt();
|
||||
a = P * (a + Eigen::Vector4f::Zero()).cwiseSqrt();
|
||||
VERIFY_IS_APPROX(a, expected);
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(permutationmatrices) {
|
||||
for (int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1(permutationmatrices(Matrix<float, 1, 1>()));
|
||||
@@ -182,4 +203,5 @@ EIGEN_DECLARE_TEST(permutationmatrices) {
|
||||
MatrixXcf(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
|
||||
}
|
||||
CALL_SUBTEST_5(bug890<double>());
|
||||
CALL_SUBTEST_4(test_aliasing());
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ template <typename Scalar, typename V1, typename V2>
|
||||
Scalar ref_dot_product(const V1& v1, const V2& v2) {
|
||||
Scalar out = Scalar(0);
|
||||
for (Index i = 0; i < v1.size(); ++i) {
|
||||
out = Eigen::numext::fma(v1[i], v2[i], out);
|
||||
out = Eigen::numext::madd(v1[i], v2[i], out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -254,8 +254,6 @@ void product(const MatrixType& m) {
|
||||
// inner product
|
||||
{
|
||||
Scalar x = square2.row(c) * square2.col(c2);
|
||||
// NOTE: FMA is necessary here in the reference to ensure accuracy for
|
||||
// large vector sizes and float16/bfloat16 types.
|
||||
Scalar y = ref_dot_product<Scalar>(square2.row(c), square2.col(c2));
|
||||
VERIFY_IS_APPROX(x, y);
|
||||
}
|
||||
|
||||
110
test/realview.cpp
Normal file
110
test/realview.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2025 The Eigen Authors
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template <typename T>
|
||||
void test_realview(const T&) {
|
||||
using Scalar = typename T::Scalar;
|
||||
using RealScalar = typename NumTraits<Scalar>::Real;
|
||||
|
||||
constexpr Index minRows = T::RowsAtCompileTime == Dynamic ? 1 : T::RowsAtCompileTime;
|
||||
constexpr Index maxRows = T::MaxRowsAtCompileTime == Dynamic ? (EIGEN_TEST_MAX_SIZE / 2) : T::MaxRowsAtCompileTime;
|
||||
constexpr Index minCols = T::ColsAtCompileTime == Dynamic ? 1 : T::ColsAtCompileTime;
|
||||
constexpr Index maxCols = T::MaxColsAtCompileTime == Dynamic ? (EIGEN_TEST_MAX_SIZE / 2) : T::MaxColsAtCompileTime;
|
||||
|
||||
constexpr Index rowFactor = (NumTraits<Scalar>::IsComplex && !T::IsRowMajor) ? 2 : 1;
|
||||
constexpr Index colFactor = (NumTraits<Scalar>::IsComplex && T::IsRowMajor) ? 2 : 1;
|
||||
constexpr Index sizeFactor = NumTraits<Scalar>::IsComplex ? 2 : 1;
|
||||
|
||||
Index rows = internal::random<Index>(minRows, maxRows);
|
||||
Index cols = internal::random<Index>(minCols, maxCols);
|
||||
|
||||
T A(rows, cols), B, C;
|
||||
|
||||
VERIFY(A.realView().rows() == rowFactor * A.rows());
|
||||
VERIFY(A.realView().cols() == colFactor * A.cols());
|
||||
VERIFY(A.realView().size() == sizeFactor * A.size());
|
||||
|
||||
RealScalar alpha = internal::random(RealScalar(1), RealScalar(2));
|
||||
A.setRandom();
|
||||
|
||||
VERIFY_IS_APPROX(A.matrix().squaredNorm(), A.realView().matrix().squaredNorm());
|
||||
|
||||
// test re-sizing realView during assignment
|
||||
B.realView() = A.realView();
|
||||
VERIFY_IS_APPROX(A, B);
|
||||
VERIFY_IS_APPROX(A.realView(), B.realView());
|
||||
|
||||
// B = A * alpha
|
||||
for (Index r = 0; r < rows; r++) {
|
||||
for (Index c = 0; c < cols; c++) {
|
||||
B.coeffRef(r, c) = A.coeff(r, c) * Scalar(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
VERIFY_IS_APPROX(B.realView(), A.realView() * alpha);
|
||||
C = A;
|
||||
C.realView() *= alpha;
|
||||
VERIFY_IS_APPROX(B, C);
|
||||
|
||||
alpha = internal::random(RealScalar(1), RealScalar(2));
|
||||
A.setRandom();
|
||||
|
||||
// B = A / alpha
|
||||
for (Index r = 0; r < rows; r++) {
|
||||
for (Index c = 0; c < cols; c++) {
|
||||
B.coeffRef(r, c) = A.coeff(r, c) / Scalar(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
VERIFY_IS_APPROX(B.realView(), A.realView() / alpha);
|
||||
C = A;
|
||||
C.realView() /= alpha;
|
||||
VERIFY_IS_APPROX(B, C);
|
||||
}
|
||||
|
||||
template <typename Scalar, int Rows, int Cols, int MaxRows = Rows, int MaxCols = Cols>
|
||||
void test_realview_driver() {
|
||||
// if Rows == 1, don't test ColMajor as it is not a valid array
|
||||
using ColMajorMatrixType = Matrix<Scalar, Rows, Cols, Rows == 1 ? RowMajor : ColMajor, MaxRows, MaxCols>;
|
||||
using ColMajorArrayType = Array<Scalar, Rows, Cols, Rows == 1 ? RowMajor : ColMajor, MaxRows, MaxCols>;
|
||||
// if Cols == 1, don't test RowMajor as it is not a valid array
|
||||
using RowMajorMatrixType = Matrix<Scalar, Rows, Cols, Cols == 1 ? ColMajor : RowMajor, MaxRows, MaxCols>;
|
||||
using RowMajorArrayType = Array<Scalar, Rows, Cols, Cols == 1 ? ColMajor : RowMajor, MaxRows, MaxCols>;
|
||||
test_realview(ColMajorMatrixType());
|
||||
test_realview(ColMajorArrayType());
|
||||
test_realview(RowMajorMatrixType());
|
||||
test_realview(RowMajorArrayType());
|
||||
}
|
||||
|
||||
template <int Rows, int Cols, int MaxRows = Rows, int MaxCols = Cols>
|
||||
void test_realview_driver_complex() {
|
||||
test_realview_driver<float, Rows, Cols, MaxRows, MaxCols>();
|
||||
test_realview_driver<std::complex<float>, Rows, Cols, MaxRows, MaxCols>();
|
||||
test_realview_driver<double, Rows, Cols, MaxRows, MaxCols>();
|
||||
test_realview_driver<std::complex<double>, Rows, Cols, MaxRows, MaxCols>();
|
||||
test_realview_driver<long double, Rows, Cols, MaxRows, MaxCols>();
|
||||
test_realview_driver<std::complex<long double>, Rows, Cols, MaxRows, MaxCols>();
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(realview) {
|
||||
for (int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1((test_realview_driver_complex<Dynamic, Dynamic, Dynamic, Dynamic>()));
|
||||
CALL_SUBTEST_2((test_realview_driver_complex<Dynamic, Dynamic, 17, Dynamic>()));
|
||||
CALL_SUBTEST_3((test_realview_driver_complex<Dynamic, Dynamic, Dynamic, 19>()));
|
||||
CALL_SUBTEST_4((test_realview_driver_complex<Dynamic, Dynamic, 17, 19>()));
|
||||
CALL_SUBTEST_5((test_realview_driver_complex<17, Dynamic, 17, Dynamic>()));
|
||||
CALL_SUBTEST_6((test_realview_driver_complex<Dynamic, 19, Dynamic, 19>()));
|
||||
CALL_SUBTEST_7((test_realview_driver_complex<17, 19, 17, 19>()));
|
||||
CALL_SUBTEST_8((test_realview_driver_complex<Dynamic, 1>()));
|
||||
CALL_SUBTEST_9((test_realview_driver_complex<1, Dynamic>()));
|
||||
CALL_SUBTEST_10((test_realview_driver_complex<1, 1>()));
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,8 @@ void vectorwiseop_matrix(const MatrixType& m) {
|
||||
RealColVectorType rcres;
|
||||
RealRowVectorType rrres;
|
||||
|
||||
Scalar small_scalar = (std::numeric_limits<RealScalar>::min)();
|
||||
|
||||
// test broadcast assignment
|
||||
m2 = m1;
|
||||
m2.colwise() = colvec;
|
||||
@@ -171,18 +173,26 @@ void vectorwiseop_matrix(const MatrixType& m) {
|
||||
VERIFY_IS_APPROX(m1.cwiseAbs().colwise().sum().x(), m1.col(0).cwiseAbs().sum());
|
||||
|
||||
// test normalized
|
||||
m2 = m1.colwise().normalized();
|
||||
VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
|
||||
m2 = m1.rowwise().normalized();
|
||||
VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
|
||||
m2 = m1;
|
||||
m2.col(c).fill(small_scalar);
|
||||
m3 = m2.colwise().normalized();
|
||||
for (Index k = 0; k < cols; ++k) VERIFY_IS_APPROX(m3.col(k), m2.col(k).normalized());
|
||||
m2 = m1;
|
||||
m2.row(r).setZero();
|
||||
m3 = m2.rowwise().normalized();
|
||||
for (Index k = 0; k < rows; ++k) VERIFY_IS_APPROX(m3.row(k), m2.row(k).normalized());
|
||||
|
||||
// test normalize
|
||||
m2 = m1;
|
||||
m2.colwise().normalize();
|
||||
VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
|
||||
m2.col(c).setZero();
|
||||
m3 = m2;
|
||||
m3.colwise().normalize();
|
||||
for (Index k = 0; k < cols; ++k) VERIFY_IS_APPROX(m3.col(k), m2.col(k).normalized());
|
||||
m2 = m1;
|
||||
m2.rowwise().normalize();
|
||||
VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
|
||||
m2.row(r).fill(small_scalar);
|
||||
m3 = m2;
|
||||
m3.rowwise().normalize();
|
||||
for (Index k = 0; k < rows; ++k) VERIFY_IS_APPROX(m3.row(k), m2.row(k).normalized());
|
||||
|
||||
// test with partial reduction of products
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> m1m1 = m1 * m1.transpose();
|
||||
|
||||
@@ -296,6 +296,23 @@ void checkOptimalTraversal() {
|
||||
checkOptimalTraversal_impl<UnrollRowMajor, true>(UnrollRowMajor(Rows, Cols));
|
||||
checkOptimalTraversal_impl<DynamicColMajor, true>(DynamicColMajor(rows, cols));
|
||||
checkOptimalTraversal_impl<DynamicRowMajor, true>(DynamicRowMajor(rows, cols));
|
||||
|
||||
const Eigen::Array<bool, Eigen::Dynamic, 1> a = Eigen::Array<bool, 2, 1>{false, true};
|
||||
Eigen::Index i = -1;
|
||||
|
||||
VERIFY(!a.minCoeff(&i));
|
||||
VERIFY(i == 0);
|
||||
|
||||
VERIFY(!(!a).minCoeff(&i));
|
||||
VERIFY(i == 1);
|
||||
|
||||
Eigen::Index j = -1;
|
||||
|
||||
VERIFY(a.maxCoeff(&j));
|
||||
VERIFY(j == 1);
|
||||
|
||||
VERIFY((!a).maxCoeff(&j));
|
||||
VERIFY(j == 0);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(visitor) {
|
||||
|
||||
@@ -700,8 +700,8 @@ struct TensorContractionEvaluatorBase {
|
||||
typedef std::remove_const_t<typename EvalRightArgType::Scalar> RhsScalar;
|
||||
typedef TensorEvaluator<EvalLeftArgType, Device> LeftEvaluator;
|
||||
typedef TensorEvaluator<EvalRightArgType, Device> RightEvaluator;
|
||||
const Index lhs_packet_size = internal::unpacket_traits<typename LeftEvaluator::PacketReturnType>::size;
|
||||
const Index rhs_packet_size = internal::unpacket_traits<typename RightEvaluator::PacketReturnType>::size;
|
||||
const int lhs_packet_size = internal::unpacket_traits<typename LeftEvaluator::PacketReturnType>::size;
|
||||
const int rhs_packet_size = internal::unpacket_traits<typename RightEvaluator::PacketReturnType>::size;
|
||||
const int lhs_alignment = LeftEvaluator::IsAligned ? Aligned : Unaligned;
|
||||
const int rhs_alignment = RightEvaluator::IsAligned ? Aligned : Unaligned;
|
||||
typedef internal::TensorContractionInputMapper<LhsScalar, Index, internal::Lhs, LeftEvaluator, left_nocontract_t,
|
||||
@@ -770,8 +770,8 @@ struct TensorContractionEvaluatorBase {
|
||||
typedef TensorEvaluator<EvalLeftArgType, Device> LeftEvaluator;
|
||||
typedef TensorEvaluator<EvalRightArgType, Device> RightEvaluator;
|
||||
|
||||
const Index lhs_packet_size = internal::unpacket_traits<typename LeftEvaluator::PacketReturnType>::size;
|
||||
const Index rhs_packet_size = internal::unpacket_traits<typename RightEvaluator::PacketReturnType>::size;
|
||||
const int lhs_packet_size = internal::unpacket_traits<typename LeftEvaluator::PacketReturnType>::size;
|
||||
const int rhs_packet_size = internal::unpacket_traits<typename RightEvaluator::PacketReturnType>::size;
|
||||
|
||||
typedef internal::TensorContractionInputMapper<LhsScalar, Index, internal::Lhs, LeftEvaluator, left_nocontract_t,
|
||||
contract_t, lhs_packet_size, lhs_inner_dim_contiguous, false,
|
||||
|
||||
Reference in New Issue
Block a user