Remove assumption of std::complex for complex scalar types.

This commit is contained in:
Antonio Sanchez
2025-02-12 11:21:44 -08:00
parent 6b4881ad48
commit 22cd7307dd
21 changed files with 273 additions and 115 deletions

View File

@@ -15,7 +15,7 @@
namespace Eigen {
template <bool NeedUprade>
template <bool IsReal>
struct MakeComplex {
template <typename T>
EIGEN_DEVICE_FUNC T operator()(const T& val) const {
@@ -26,16 +26,8 @@ struct MakeComplex {
template <>
struct MakeComplex<true> {
template <typename T>
EIGEN_DEVICE_FUNC std::complex<T> operator()(const T& val) const {
return std::complex<T>(val, 0);
}
};
template <>
struct MakeComplex<false> {
template <typename T>
EIGEN_DEVICE_FUNC std::complex<T> operator()(const std::complex<T>& val) const {
return val;
EIGEN_DEVICE_FUNC internal::make_complex_t<T> operator()(const T& val) const {
return internal::make_complex_t<T>(val, T(0));
}
};
@@ -49,17 +41,17 @@ struct PartOf {
template <>
struct PartOf<RealPart> {
template <typename T>
T operator()(const std::complex<T>& val) const {
return val.real();
template <typename T, typename EnableIf = std::enable_if_t<NumTraits<T>::IsComplex>>
typename NumTraits<T>::Real operator()(const T& val) const {
return Eigen::numext::real(val);
}
};
template <>
struct PartOf<ImagPart> {
template <typename T>
T operator()(const std::complex<T>& val) const {
return val.imag();
template <typename T, typename EnableIf = std::enable_if_t<NumTraits<T>::IsComplex>>
typename NumTraits<T>::Real operator()(const T& val) const {
return Eigen::numext::imag(val);
}
};
@@ -67,8 +59,9 @@ namespace internal {
template <typename FFT, typename XprType, int FFTResultType, int FFTDir>
struct traits<TensorFFTOp<FFT, XprType, FFTResultType, FFTDir> > : public traits<XprType> {
typedef traits<XprType> XprTraits;
typedef typename NumTraits<typename XprTraits::Scalar>::Real RealScalar;
typedef typename std::complex<RealScalar> ComplexScalar;
typedef typename XprTraits::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef make_complex_t<Scalar> ComplexScalar;
typedef typename XprTraits::Scalar InputScalar;
typedef std::conditional_t<FFTResultType == RealPart || FFTResultType == ImagPart, RealScalar, ComplexScalar>
OutputScalar;
@@ -109,7 +102,7 @@ class TensorFFTOp : public TensorBase<TensorFFTOp<FFT, XprType, FFTResultType, F
public:
typedef typename Eigen::internal::traits<TensorFFTOp>::Scalar Scalar;
typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
typedef typename std::complex<RealScalar> ComplexScalar;
typedef internal::make_complex_t<Scalar> ComplexScalar;
typedef std::conditional_t<FFTResultType == RealPart || FFTResultType == ImagPart, RealScalar, ComplexScalar>
OutputScalar;
typedef OutputScalar CoeffReturnType;
@@ -137,7 +130,7 @@ struct TensorEvaluator<const TensorFFTOp<FFT, ArgType, FFTResultType, FFTDir>, D
typedef DSizes<Index, NumDims> Dimensions;
typedef typename XprType::Scalar Scalar;
typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
typedef typename std::complex<RealScalar> ComplexScalar;
typedef internal::make_complex_t<Scalar> ComplexScalar;
typedef typename TensorEvaluator<ArgType, Device>::Dimensions InputDimensions;
typedef internal::traits<XprType> XprTraits;
typedef typename XprTraits::Scalar InputScalar;

View File

@@ -111,12 +111,13 @@ class DGMRES : public IterativeSolverBase<DGMRES<MatrixType_, Preconditioner_> >
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::StorageIndex StorageIndex;
typedef typename MatrixType::RealScalar RealScalar;
typedef internal::make_complex_t<Scalar> ComplexScalar;
typedef Preconditioner_ Preconditioner;
typedef Matrix<Scalar, Dynamic, Dynamic> DenseMatrix;
typedef Matrix<RealScalar, Dynamic, Dynamic> DenseRealMatrix;
typedef Matrix<Scalar, Dynamic, 1> DenseVector;
typedef Matrix<RealScalar, Dynamic, 1> DenseRealVector;
typedef Matrix<std::complex<RealScalar>, Dynamic, 1> ComplexVector;
typedef Matrix<ComplexScalar, Dynamic, 1> ComplexVector;
/** Default constructor. */
DGMRES()
@@ -389,15 +390,15 @@ inline typename DGMRES<MatrixType_, Preconditioner_>::ComplexVector DGMRES<Matri
Index j = 0;
while (j < it - 1) {
if (T(j + 1, j) == Scalar(0)) {
eig(j) = std::complex<RealScalar>(T(j, j), RealScalar(0));
eig(j) = ComplexScalar(T(j, j), RealScalar(0));
j++;
} else {
eig(j) = std::complex<RealScalar>(T(j, j), T(j + 1, j));
eig(j + 1) = std::complex<RealScalar>(T(j, j + 1), T(j + 1, j + 1));
eig(j) = ComplexScalar(T(j, j), T(j + 1, j));
eig(j + 1) = ComplexScalar(T(j, j + 1), T(j + 1, j + 1));
j++;
}
}
if (j < it - 1) eig(j) = std::complex<RealScalar>(T(j, j), RealScalar(0));
if (j < it - 1) eig(j) = ComplexScalar(T(j, j), RealScalar(0));
return eig;
}

View File

@@ -23,8 +23,10 @@ namespace internal {
*
* This struct is used by CwiseUnaryOp to scale a matrix by \f$ 2^{-s} \f$.
*/
template <typename RealScalar>
template <typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
struct MatrixExponentialScalingOp {
using RealScalar = typename NumTraits<Scalar>::Real;
/** \brief Constructor.
*
* \param[in] squarings The integer \f$ s \f$ in this document.
@@ -35,20 +37,30 @@ struct MatrixExponentialScalingOp {
*
* \param[in,out] x The scalar to be scaled, becoming \f$ 2^{-s} x \f$.
*/
inline const RealScalar operator()(const RealScalar& x) const {
inline const Scalar operator()(const Scalar& x) const {
using std::ldexp;
return ldexp(x, -m_squarings);
return Scalar(ldexp(Eigen::numext::real(x), -m_squarings), ldexp(Eigen::numext::imag(x), -m_squarings));
}
typedef std::complex<RealScalar> ComplexScalar;
private:
int m_squarings;
};
template <typename Scalar>
struct MatrixExponentialScalingOp<Scalar, /*IsComplex=*/false> {
/** \brief Constructor.
*
* \param[in] squarings The integer \f$ s \f$ in this document.
*/
MatrixExponentialScalingOp(int squarings) : m_squarings(squarings) {}
/** \brief Scale a matrix coefficient.
*
* \param[in,out] x The scalar to be scaled, becoming \f$ 2^{-s} x \f$.
*/
inline const ComplexScalar operator()(const ComplexScalar& x) const {
inline const Scalar operator()(const Scalar& x) const {
using std::ldexp;
return ComplexScalar(ldexp(x.real(), -m_squarings), ldexp(x.imag(), -m_squarings));
return ldexp(x, -m_squarings);
}
private:
@@ -220,6 +232,7 @@ struct matrix_exp_computeUV {
template <typename MatrixType>
struct matrix_exp_computeUV<MatrixType, float> {
using Scalar = typename traits<MatrixType>::Scalar;
template <typename ArgType>
static void run(const ArgType& arg, MatrixType& U, MatrixType& V, int& squarings) {
using std::frexp;
@@ -234,7 +247,7 @@ struct matrix_exp_computeUV<MatrixType, float> {
const float maxnorm = 3.925724783138660f;
frexp(l1norm / maxnorm, &squarings);
if (squarings < 0) squarings = 0;
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<float>(squarings));
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<Scalar>(squarings));
matrix_exp_pade7(A, U, V);
}
}
@@ -242,12 +255,12 @@ struct matrix_exp_computeUV<MatrixType, float> {
template <typename MatrixType>
struct matrix_exp_computeUV<MatrixType, double> {
typedef typename NumTraits<typename traits<MatrixType>::Scalar>::Real RealScalar;
using Scalar = typename traits<MatrixType>::Scalar;
template <typename ArgType>
static void run(const ArgType& arg, MatrixType& U, MatrixType& V, int& squarings) {
using std::frexp;
using std::pow;
const RealScalar l1norm = arg.cwiseAbs().colwise().sum().maxCoeff();
const double l1norm = arg.cwiseAbs().colwise().sum().maxCoeff();
squarings = 0;
if (l1norm < 1.495585217958292e-002) {
matrix_exp_pade3(arg, U, V);
@@ -258,10 +271,10 @@ struct matrix_exp_computeUV<MatrixType, double> {
} else if (l1norm < 2.097847961257068e+000) {
matrix_exp_pade9(arg, U, V);
} else {
const RealScalar maxnorm = 5.371920351148152;
const double maxnorm = 5.371920351148152;
frexp(l1norm / maxnorm, &squarings);
if (squarings < 0) squarings = 0;
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<RealScalar>(squarings));
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<Scalar>(squarings));
matrix_exp_pade13(A, U, V);
}
}
@@ -271,6 +284,7 @@ template <typename MatrixType>
struct matrix_exp_computeUV<MatrixType, long double> {
template <typename ArgType>
static void run(const ArgType& arg, MatrixType& U, MatrixType& V, int& squarings) {
using Scalar = typename traits<MatrixType>::Scalar;
#if LDBL_MANT_DIG == 53 // double precision
matrix_exp_computeUV<MatrixType, double>::run(arg, U, V, squarings);
@@ -295,7 +309,7 @@ struct matrix_exp_computeUV<MatrixType, long double> {
const long double maxnorm = 4.0246098906697353063L;
frexp(l1norm / maxnorm, &squarings);
if (squarings < 0) squarings = 0;
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<long double>(squarings));
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<Scalar>(squarings));
matrix_exp_pade13(A, U, V);
}
@@ -315,7 +329,7 @@ struct matrix_exp_computeUV<MatrixType, long double> {
const long double maxnorm = 3.2579440895405400856599663723517L;
frexp(l1norm / maxnorm, &squarings);
if (squarings < 0) squarings = 0;
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<long double>(squarings));
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<Scalar>(squarings));
matrix_exp_pade17(A, U, V);
}
@@ -335,7 +349,7 @@ struct matrix_exp_computeUV<MatrixType, long double> {
const long double maxnorm = 2.884233277829519311757165057717815L;
frexp(l1norm / maxnorm, &squarings);
if (squarings < 0) squarings = 0;
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<long double>(squarings));
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<Scalar>(squarings));
matrix_exp_pade17(A, U, V);
}
@@ -382,9 +396,7 @@ template <typename ArgType, typename ResultType>
void matrix_exp_compute(const ArgType& arg, ResultType& result, false_type) // default
{
typedef typename ArgType::PlainObject MatrixType;
typedef typename traits<MatrixType>::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef typename std::complex<RealScalar> ComplexScalar;
typedef make_complex_t<typename traits<MatrixType>::Scalar> ComplexScalar;
result = arg.matrixFunction(internal::stem_function_exp<ComplexScalar>);
}

View File

@@ -382,7 +382,7 @@ struct matrix_function_compute<MatrixType, 0> {
static const int Rows = Traits::RowsAtCompileTime, Cols = Traits::ColsAtCompileTime;
static const int MaxRows = Traits::MaxRowsAtCompileTime, MaxCols = Traits::MaxColsAtCompileTime;
typedef std::complex<Scalar> ComplexScalar;
typedef internal::make_complex_t<Scalar> ComplexScalar;
typedef Matrix<ComplexScalar, Rows, Cols, 0, MaxRows, MaxCols> ComplexMatrix;
ComplexMatrix CA = A.template cast<ComplexScalar>();
@@ -476,7 +476,7 @@ class MatrixFunctionReturnValue : public ReturnByValue<MatrixFunctionReturnValue
typedef typename internal::nested_eval<Derived, 10>::type NestedEvalType;
typedef internal::remove_all_t<NestedEvalType> NestedEvalTypeClean;
typedef internal::traits<NestedEvalTypeClean> Traits;
typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar;
typedef internal::make_complex_t<Scalar> ComplexScalar;
typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0, Traits::RowsAtCompileTime, Traits::ColsAtCompileTime>
DynMatrixType;

View File

@@ -330,7 +330,7 @@ class MatrixLogarithmReturnValue : public ReturnByValue<MatrixLogarithmReturnVal
typedef typename internal::nested_eval<Derived, 10>::type DerivedEvalType;
typedef internal::remove_all_t<DerivedEvalType> DerivedEvalTypeClean;
typedef internal::traits<DerivedEvalTypeClean> Traits;
typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar;
typedef internal::make_complex_t<Scalar> ComplexScalar;
typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0, Traits::RowsAtCompileTime, Traits::ColsAtCompileTime>
DynMatrixType;
typedef internal::MatrixLogarithmAtomic<DynMatrixType> AtomicType;

View File

@@ -91,7 +91,7 @@ class MatrixPowerAtomic : internal::noncopyable {
enum { RowsAtCompileTime = MatrixType::RowsAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef std::complex<RealScalar> ComplexScalar;
typedef internal::make_complex_t<Scalar> ComplexScalar;
typedef Block<MatrixType, Dynamic, Dynamic> ResultType;
const MatrixType& m_A;
@@ -380,7 +380,7 @@ class MatrixPower : internal::noncopyable {
Index cols() const { return m_A.cols(); }
private:
typedef std::complex<RealScalar> ComplexScalar;
typedef internal::make_complex_t<Scalar> ComplexScalar;
typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime>
ComplexMatrix;
@@ -628,7 +628,7 @@ template <typename Derived>
class MatrixComplexPowerReturnValue : public ReturnByValue<MatrixComplexPowerReturnValue<Derived> > {
public:
typedef typename Derived::PlainObject PlainObject;
typedef typename std::complex<typename Derived::RealScalar> ComplexScalar;
typedef internal::make_complex_t<typename Derived::Scalar> ComplexScalar;
/**
* \brief Constructor.
@@ -685,7 +685,7 @@ const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(const RealScalar&
}
template <typename Derived>
const MatrixComplexPowerReturnValue<Derived> MatrixBase<Derived>::pow(const std::complex<RealScalar>& p) const {
const MatrixComplexPowerReturnValue<Derived> MatrixBase<Derived>::pow(const internal::make_complex_t<Scalar>& p) const {
return MatrixComplexPowerReturnValue<Derived>(derived(), p);
}

View File

@@ -35,7 +35,7 @@ class PolynomialSolverBase {
typedef Scalar_ Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef std::complex<RealScalar> RootType;
typedef internal::make_complex_t<Scalar> RootType;
typedef Matrix<RootType, Deg_, 1> RootsType;
typedef DenseIndex Index;
@@ -308,7 +308,7 @@ class PolynomialSolver : public PolynomialSolverBase<Scalar_, Deg_> {
typedef std::conditional_t<NumTraits<Scalar>::IsComplex, ComplexEigenSolver<CompanionMatrixType>,
EigenSolver<CompanionMatrixType> >
EigenSolverType;
typedef std::conditional_t<NumTraits<Scalar>::IsComplex, Scalar, std::complex<Scalar> > ComplexScalar;
typedef internal::make_complex_t<Scalar_> ComplexScalar;
public:
/** Computes the complex roots of a new polynomial. */