diff --git a/.gitlab/issue_templates/Bug Report.md b/.gitlab/issue_templates/Bug Report.md index 0c49b0fe3..523b6114f 100644 --- a/.gitlab/issue_templates/Bug Report.md +++ b/.gitlab/issue_templates/Bug Report.md @@ -1,42 +1,37 @@ +Before opening a new issue, please search for keywords in the existing [list of issues](https://gitlab.com/libeigen/eigen/-/issues?state=opened) to verify it isn't a duplicate. +--> ### Summary ### Environment - + - **Operating System** : Windows/Linux - **Architecture** : x64/Arm64/PowerPC ... -- **Eigen Version** : 3.3.9 -- **Compiler Version** : Gcc7.0 +- **Eigen Version** : 5.0.0 +- **Compiler Version** : gcc-12.0 - **Compile Flags** : -O3 -march=native - **Vector Extension** : SSE/AVX/NEON ... ### Minimal Example - +You can also link to [godbolt](https://godbolt.org). Note that you need to click +the "Share" button in the top right-hand corner of the godbolt page to get the share link +instead of the URL in your browser address bar. +--> ```cpp -//show your code here +// Insert your code here. ``` -### Steps to reproduce - +### Steps to reproduce the issue + 1. first step 2. second step @@ -49,21 +44,16 @@ on how to create a good minimal example. --> ### Relevant logs - + - -### Warning Messages - - - -### Benchmark scripts and results +### [Optional] Benchmark scripts and results ### Anything else that might help - - -- [ ] Have a plan to fix this issue. +- last known working/first broken version (release number or commit hash). +--> diff --git a/.gitlab/issue_templates/Feature Request.md b/.gitlab/issue_templates/Feature Request.md index 2c6f908af..952660089 100644 --- a/.gitlab/issue_templates/Feature Request.md +++ b/.gitlab/issue_templates/Feature Request.md @@ -1,6 +1,13 @@ + + ### Describe the feature you would like to be implemented. -### Would such a feature be useful for other users? Why? +### Why Would such a feature be useful for other users? ### Any hints on how to implement the requested feature? diff --git a/.gitlab/merge_request_templates/Merge Request Template.md b/.gitlab/merge_request_templates/Merge Request Template.md deleted file mode 100644 index 3fe963afa..000000000 --- a/.gitlab/merge_request_templates/Merge Request Template.md +++ /dev/null @@ -1,26 +0,0 @@ - - -### Reference issue - - -### What does this implement/fix? - - -### Additional information - diff --git a/.gitlab/merge_request_templates/Merge Request.md b/.gitlab/merge_request_templates/Merge Request.md new file mode 100644 index 000000000..78deebfa3 --- /dev/null +++ b/.gitlab/merge_request_templates/Merge Request.md @@ -0,0 +1,30 @@ + + +### Description + + +%{first_multiline_commit} + +### Reference issue + + +### Additional information + diff --git a/CMakeLists.txt b/CMakeLists.txt index 928da3d9d..36912bcde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,13 +63,8 @@ option(EIGEN_LEAVE_TEST_IN_ALL_TARGET "Leaves tests in the all target, needed by option(EIGEN_BUILD_BLAS "Toggles the building of the Eigen Blas library" ${PROJECT_IS_TOP_LEVEL}) option(EIGEN_BUILD_LAPACK "Toggles the building of the included Eigen LAPACK library" ${PROJECT_IS_TOP_LEVEL}) if (EIGEN_BUILD_BLAS OR EIGEN_BUILD_LAPACK) - # BLAS and LAPACK currently need a fortran compiler. - include(CMakeDetermineFortranCompiler) - if (NOT CMAKE_Fortran_COMPILER) - set(EIGEN_BUILD_BLAS OFF) - set(EIGEN_BUILD_LAPACK OFF) - else() - # Determine if we should build shared libraries for BLAS/LAPACK on this platform. + # Determine if we should build shared libraries for BLAS/LAPACK on this platform. + if (NOT EIGEN_BUILD_SHARED_LIBS) get_cmake_property(EIGEN_BUILD_SHARED_LIBS TARGET_SUPPORTS_SHARED_LIBS) endif() endif() diff --git a/Eigen/Core b/Eigen/Core index e5a4e631f..e1e89f985 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -106,6 +106,11 @@ #include #endif +// for __cpp_lib feature test macros +#if defined(__has_include) && __has_include() +#include +#endif + // for std::bit_cast() #if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L #include diff --git a/Eigen/Eigenvalues b/Eigen/Eigenvalues index 3b0bdee17..c11f42ad4 100644 --- a/Eigen/Eigenvalues +++ b/Eigen/Eigenvalues @@ -32,8 +32,6 @@ * \endcode */ -#include "src/misc/RealSvd2x2.h" - // IWYU pragma: begin_exports #include "src/Eigenvalues/Tridiagonalization.h" #include "src/Eigenvalues/RealSchur.h" @@ -44,6 +42,7 @@ #include "src/Eigenvalues/ComplexSchur.h" #include "src/Eigenvalues/ComplexEigenSolver.h" #include "src/Eigenvalues/RealQZ.h" +#include "src/Eigenvalues/ComplexQZ.h" #include "src/Eigenvalues/GeneralizedEigenSolver.h" #include "src/Eigenvalues/MatrixBaseEigenvalues.h" #ifdef EIGEN_USE_LAPACKE diff --git a/Eigen/SVD b/Eigen/SVD index 2a013f825..b616a6a81 100644 --- a/Eigen/SVD +++ b/Eigen/SVD @@ -33,7 +33,6 @@ */ // IWYU pragma: begin_exports -#include "src/misc/RealSvd2x2.h" #include "src/SVD/UpperBidiagonalization.h" #include "src/SVD/SVDBase.h" #include "src/SVD/JacobiSVD.h" diff --git a/Eigen/src/Core/DenseStorage.h b/Eigen/src/Core/DenseStorage.h index d62586c99..45c8779ac 100644 --- a/Eigen/src/Core/DenseStorage.h +++ b/Eigen/src/Core/DenseStorage.h @@ -65,7 +65,8 @@ struct plain_array { template struct plain_array { - T array[Size]; + // on some 32-bit platforms, stack-allocated arrays are aligned to 4 bytes, not the preferred alignment of T + EIGEN_ALIGN_TO_BOUNDARY(alignof(T)) T array[Size]; #if defined(EIGEN_NO_DEBUG) || defined(EIGEN_TESTING_PLAINOBJECT_CTOR) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr plain_array() = default; #else @@ -73,12 +74,6 @@ struct plain_array { #endif }; -template -struct plain_array { - T array[1]; - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr plain_array() = default; -}; - template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void swap_plain_array(plain_array& a, plain_array& b, diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index 155fdad20..5e36ce84d 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h @@ -1004,8 +1004,7 @@ struct madd_impl { } }; -// Use FMA if there is a single CPU instruction. -#ifdef EIGEN_VECTORIZE_FMA +#if EIGEN_SCALAR_MADD_USE_FMA template struct madd_impl::value>> { static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run(const Scalar& x, const Scalar& y, const Scalar& z) { @@ -1927,7 +1926,6 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar arithmetic_shift_right(const Scalar return bit_cast(bit_cast(a) >> n); } -// Otherwise, rely on template implementation. template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar fma(const Scalar& x, const Scalar& y, const Scalar& z) { return internal::fma_impl::run(x, y, z); diff --git a/Eigen/src/Core/arch/AVX/TypeCasting.h b/Eigen/src/Core/arch/AVX/TypeCasting.h index 5b73ffe86..767e2d554 100644 --- a/Eigen/src/Core/arch/AVX/TypeCasting.h +++ b/Eigen/src/Core/arch/AVX/TypeCasting.h @@ -240,8 +240,8 @@ EIGEN_STRONG_INLINE Packet4d pcast(const Packet4l& a) { #if defined(EIGEN_VECTORIZE_AVX512DQ) && defined(EIGEN_VECTORIZE_AVS512VL) return _mm256_cvtepi64_pd(a); #else - EIGEN_ALIGN16 int64_t aux[4]; - pstore(aux, a); + int64_t aux[4]; + pstoreu(aux, a); return _mm256_set_pd(static_cast(aux[3]), static_cast(aux[2]), static_cast(aux[1]), static_cast(aux[0])); #endif diff --git a/Eigen/src/Core/arch/Default/ConjHelper.h b/Eigen/src/Core/arch/Default/ConjHelper.h index fd7923e16..137e7fb56 100644 --- a/Eigen/src/Core/arch/Default/ConjHelper.h +++ b/Eigen/src/Core/arch/Default/ConjHelper.h @@ -17,6 +17,9 @@ EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_REAL& x, const PACKET_CPLX& y, const PACKET_CPLX& c) const { \ return padd(c, this->pmul(x, y)); \ } \ + EIGEN_STRONG_INLINE PACKET_CPLX pmsub(const PACKET_REAL& x, const PACKET_CPLX& y, const PACKET_CPLX& c) const { \ + return psub(this->pmul(x, y), c); \ + } \ EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_REAL& x, const PACKET_CPLX& y) const { \ return PACKET_CPLX(Eigen::internal::pmul(x, y.v)); \ } \ @@ -27,6 +30,9 @@ EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_CPLX& x, const PACKET_REAL& y, const PACKET_CPLX& c) const { \ return padd(c, this->pmul(x, y)); \ } \ + EIGEN_STRONG_INLINE PACKET_CPLX pmsub(const PACKET_CPLX& x, const PACKET_REAL& y, const PACKET_CPLX& c) const { \ + return psub(this->pmul(x, y), c); \ + } \ EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_CPLX& x, const PACKET_REAL& y) const { \ return PACKET_CPLX(Eigen::internal::pmul(x.v, y)); \ } \ @@ -76,6 +82,11 @@ struct conj_helper { return this->pmul(x, y) + c; } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType pmsub(const LhsType& x, const RhsType& y, + const ResultType& c) const { + return this->pmul(x, y) - c; + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType pmul(const LhsType& x, const RhsType& y) const { return conj_if()(x) * conj_if()(y); } @@ -104,6 +115,10 @@ struct conj_helper { return Eigen::internal::pmadd(conj_if().pconj(x), conj_if().pconj(y), c); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmsub(const Packet& x, const Packet& y, const Packet& c) const { + return Eigen::internal::pmsub(conj_if().pconj(x), conj_if().pconj(y), c); + } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmul(const Packet& x, const Packet& y) const { return Eigen::internal::pmul(conj_if().pconj(x), conj_if().pconj(y)); } @@ -116,6 +131,9 @@ struct conj_helper { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmadd(const Packet& x, const Packet& y, const Packet& c) const { return Eigen::internal::pmadd(pconj(x), pconj(y), c); } + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmsub(const Packet& x, const Packet& y, const Packet& c) const { + return Eigen::internal::pmsub(pconj(x), pconj(y), c); + } // We save a conjuation by using the identity conj(a)*conj(b) = conj(a*b). EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmul(const Packet& x, const Packet& y) const { return pconj(Eigen::internal::pmul(x, y)); diff --git a/Eigen/src/Core/arch/SSE/PacketMath.h b/Eigen/src/Core/arch/SSE/PacketMath.h index e0119dd76..a5e4902c3 100644 --- a/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/Eigen/src/Core/arch/SSE/PacketMath.h @@ -1679,9 +1679,9 @@ EIGEN_STRONG_INLINE Packet16b pgather(const bool* from, Index s template <> EIGEN_STRONG_INLINE void pscatter(float* to, const Packet4f& from, Index stride) { to[stride * 0] = pfirst(from); - to[stride * 1] = pfirst(_mm_shuffle_ps(from, from, 1)); - to[stride * 2] = pfirst(_mm_shuffle_ps(from, from, 2)); - to[stride * 3] = pfirst(_mm_shuffle_ps(from, from, 3)); + to[stride * 1] = pfirst(Packet4f(_mm_shuffle_ps(from, from, 1))); + to[stride * 2] = pfirst(Packet4f(_mm_shuffle_ps(from, from, 2))); + to[stride * 3] = pfirst(Packet4f(_mm_shuffle_ps(from, from, 3))); } template <> EIGEN_STRONG_INLINE void pscatter(double* to, const Packet2d& from, Index stride) { diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h index 42318b69c..80d474520 100644 --- a/Eigen/src/Core/util/Macros.h +++ b/Eigen/src/Core/util/Macros.h @@ -52,6 +52,26 @@ #define EIGEN_STACK_ALLOCATION_LIMIT 131072 #endif +/* Specify whether to use std::fma for scalar multiply-add instructions. + * + * On machines that have FMA as a single instruction, this will generally + * improve precision without significant performance implications. + * + * Without a single instruction, performance has been found to be reduced 2-3x + * on Intel CPUs, and up to 30x for WASM. + * + * If unspecified, defaults to using FMA if hardware support is available. + * The default should be used in most cases to ensure consistency between + * vectorized and non-vectorized paths. + */ +#ifndef EIGEN_SCALAR_MADD_USE_FMA +#ifdef EIGEN_VECTORIZE_FMA +#define EIGEN_SCALAR_MADD_USE_FMA 1 +#else +#define EIGEN_SCALAR_MADD_USE_FMA 0 +#endif +#endif + //------------------------------------------------------------------------------------------ // Compiler identification, EIGEN_COMP_* //------------------------------------------------------------------------------------------ diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index d6c09a392..d1f2bf3ed 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -1345,10 +1345,10 @@ EIGEN_DEVICE_FUNC void destroy_at(T* p) { #ifndef EIGEN_ASSUME_ALIGNED #if defined(__cpp_lib_assume_aligned) && (__cpp_lib_assume_aligned >= 201811L) #define EIGEN_ASSUME_ALIGNED(PTR, ALIGN_BYTES) \ - { PTR = std::assume_aligned<8 * (ALIGN_BYTES)>(PTR); } + { PTR = std::assume_aligned(PTR); } #elif EIGEN_HAS_BUILTIN(__builtin_assume_aligned) #define EIGEN_ASSUME_ALIGNED(PTR, ALIGN_BYTES) \ - { PTR = static_cast(__builtin_assume_aligned(PTR, (ALIGN_BYTES))); } + { PTR = static_cast(__builtin_assume_aligned(PTR, ALIGN_BYTES)); } #else #define EIGEN_ASSUME_ALIGNED(PTR, ALIGN_BYTES) /* do nothing */ #endif diff --git a/Eigen/src/Eigenvalues/ComplexQZ.h b/Eigen/src/Eigenvalues/ComplexQZ.h new file mode 100644 index 000000000..817aff4a8 --- /dev/null +++ b/Eigen/src/Eigenvalues/ComplexQZ.h @@ -0,0 +1,656 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2012 Alexey Korepanov +// Copyright (C) 2025 Ludwig Striet +// +// 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 +// https://mozilla.org/MPL/2.0/. +// +// Derived from: Eigen/src/Eigenvalues/RealQZ.h + +#include "Eigen/Core" +#include "Eigen/Jacobi" + +#ifndef EIGEN_COMPLEX_QZ_H_ +#define EIGEN_COMPLEX_QZ_H_ + +#include "../../SparseQR" + +// IWYU pragma: private +#include "./InternalHeaderCheck.h" + +/** \eigenvalues_module \ingroup Eigenvalues_Module + * + * + * \class ComplexQZ + * + * \brief Performs a QZ decomposition of a pair of matrices A, B + * + * \tparam MatrixType_ the type input type of the matrix. + * + * Given to complex square matrices A and B, this class computes the QZ decomposition + * \f$ A = Q S Z \f$, \f$ B = Q T Z\f$ where Q and Z are unitary matrices and + * S and T a re upper-triangular matrices. More precisely, Q and Z fulfill + * \f$ Q Q* = Id\f$ and \f$ Z Z* = Id\f$. The generalized Eigenvalues are then + * obtained as ratios of corresponding diagonal entries, lambda(i) = S(i,i) / T(i, i). + * + * The QZ algorithm was introduced in the seminal work "An Algorithm for + * Generalized Matrix Eigenvalue Problems" by Moler & Stewart in 1973. The matrix + * pair S = A, T = B is first transformed to Hessenberg-Triangular form where S is an + * upper Hessenberg matrix and T is an upper Triangular matrix. + * + * This pair is subsequently reduced to the desired form using implicit QZ shifts as + * described in the original paper. The algorithms to find small entries on the + * diagonals and subdiagonals are based on the variants in the implementation + * for Real matrices in the RealQZ class. + * + * \sa class RealQZ + */ + +namespace Eigen { + +template +class ComplexQZ { + public: + using MatrixType = MatrixType_; + using Scalar = typename MatrixType_::Scalar; + using RealScalar = typename MatrixType_::RealScalar; + + enum { + RowsAtCompileTime = MatrixType::RowsAtCompileTime, + ColsAtCompileTime = MatrixType::ColsAtCompileTime, + Options = internal::traits::Options, + MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime + }; + + using Vec = Matrix; + using Vec2 = Matrix; + using Vec3 = Matrix; + using Row2 = Matrix; + using Mat2 = Matrix; + + /** \brief Returns matrix Q in the QZ decomposition. + * + * \returns A const reference to the matrix Q. + */ + const MatrixType& matrixQ() const { + eigen_assert(m_isInitialized && "ComplexQZ is not initialized."); + eigen_assert(m_computeQZ && "The matrices Q and Z have not been computed during the QZ decomposition."); + return m_Q; + } + + /** \brief Returns matrix Z in the QZ decomposition. + * + * \returns A const reference to the matrix Z. + */ + const MatrixType& matrixZ() const { + eigen_assert(m_isInitialized && "ComplexQZ is not initialized."); + eigen_assert(m_computeQZ && "The matrices Q and Z have not been computed during the QZ decomposition."); + return m_Z; + } + + /** \brief Returns matrix S in the QZ decomposition. + * + * \returns A const reference to the matrix S. + */ + const MatrixType& matrixS() const { + eigen_assert(m_isInitialized && "ComplexQZ is not initialized."); + return m_S; + } + + /** \brief Returns matrix S in the QZ decomposition. + * + * \returns A const reference to the matrix S. + */ + const MatrixType& matrixT() const { + eigen_assert(m_isInitialized && "ComplexQZ is not initialized."); + return m_T; + } + + /** \brief Constructor + * + * \param[in] n size of the matrices whose QZ decomposition we compute + * + * This constructor is used when we use the compute(...) method later, + * especially when we aim to compute the decomposition of two sparse + * matrices. + */ + ComplexQZ(Index n, bool computeQZ = true, unsigned int maxIters = 400) + : m_n(n), + m_S(n, n), + m_T(n, n), + m_Q(computeQZ ? n : (MatrixType::RowsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::RowsAtCompileTime), + computeQZ ? n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)), + m_Z(computeQZ ? n : (MatrixType::RowsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::RowsAtCompileTime), + computeQZ ? n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)), + m_ws(2 * n), + m_computeQZ(computeQZ), + m_maxIters(maxIters){ + + }; + + /** \brief Constructor. computes the QZ decomposition of given matrices + * upon creation + * + * \param[in] A input matrix A + * \param[in] B input matrix B + * \param[in] computeQZ If false, the matrices Q and Z are not computed + * + * This constructor calls the compute() method to compute the QZ decomposition. + * If input matrices are sparse, call the constructor that uses only the + * size as input the computeSparse(...) method. + */ + ComplexQZ(const MatrixType& A, const MatrixType& B, bool computeQZ = true, unsigned int maxIters = 400) + : m_n(A.rows()), + m_maxIters(maxIters), + m_computeQZ(computeQZ), + m_S(A.rows(), A.cols()), + m_T(A.rows(), A.cols()), + m_Q(computeQZ ? m_n : (MatrixType::RowsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::RowsAtCompileTime), + computeQZ ? m_n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)), + m_Z(computeQZ ? m_n : (MatrixType::RowsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::RowsAtCompileTime), + computeQZ ? m_n : (MatrixType::ColsAtCompileTime == Eigen::Dynamic ? 0 : MatrixType::ColsAtCompileTime)), + m_ws(2 * m_n) { + compute(A, B, computeQZ); + } + + /** \brief Compute the QZ decomposition of complex input matrices + * + * \param[in] A Matrix A. + * \param[in] B Matrix B. + * \param[in] computeQZ If false, the matrices Q and Z are not computed. + */ + void compute(const MatrixType& A, const MatrixType& B, bool computeQZ = true); + + /** \brief Compute the decomposition of sparse complex input matrices. + * Main difference to the compute(...) method is that it computes a + * SparseQR decomposition of B + * + * \param[in] A Matrix A. + * \param[in] B Matrix B. + * \param[in] computeQZ If false, the matrices Q and Z are not computed. + */ + template + void computeSparse(const SparseMatrixType_& A, const SparseMatrixType_& B, bool computeQZ = true); + + /** \brief Reports whether the last computation was successfull. + * + * \returns \c Success if computation was successfull, \c NoConvergence otherwise. + */ + ComputationInfo info() const { return m_info; }; + + /** \brief number of performed QZ steps + */ + unsigned int iterations() const { + eigen_assert(m_isInitialized && "ComplexQZ is not initialized."); + return m_global_iter; + }; + + private: + Index m_n; + const unsigned int m_maxIters; + unsigned int m_global_iter; + bool m_isInitialized; + bool m_computeQZ; + ComputationInfo m_info; + MatrixType m_S, m_T, m_Q, m_Z; + RealScalar m_normOfT, m_normOfS; + Vec m_ws; + + // Test if a Scalar is 0 up to a certain tolerance + static bool is_negligible(const Scalar x, const RealScalar tol = NumTraits::epsilon()) { + return numext::abs(x) <= tol; + } + + void do_QZ_step(Index p, Index q); + + inline Mat2 computeZk2(const Row2& b); + + // This is basically taken from from Eigen3::RealQZ + void hessenbergTriangular(const MatrixType& A, const MatrixType& B); + + // This function can be called when m_Q and m_Z are initialized and m_S, m_T + // are in hessenberg-triangular form + void reduceHessenbergTriangular(); + + // Sparse variant of the above method. + template + void hessenbergTriangularSparse(const SparseMatrixType_& A, const SparseMatrixType_& B); + + void computeNorms(); + + Index findSmallSubdiagEntry(Index l); + Index findSmallDiagEntry(Index f, Index l); + + void push_down_zero_ST(Index k, Index l); + + void reduceDiagonal2x2block(Index i); +}; + +template +void ComplexQZ::compute(const MatrixType& A, const MatrixType& B, bool computeQZ) { + m_computeQZ = computeQZ; + m_n = A.rows(); + + eigen_assert(m_n == A.cols() && "A is not a square matrix"); + eigen_assert(m_n == B.rows() && m_n == B.cols() && "B is not a square matrix or B is not of the same size as A"); + + m_isInitialized = true; + m_global_iter = 0; + + // This will initialize m_Q and m_Z and bring m_S, m_T to hessenberg-triangular form + hessenbergTriangular(A, B); + + // We assume that we already have that S is upper-Hessenberg and T is + // upper-triangular. This is what the hessenbergTriangular(...) method does + reduceHessenbergTriangular(); +} + +// This is basically taken from from Eigen3::RealQZ +template +void ComplexQZ::hessenbergTriangular(const MatrixType& A, const MatrixType& B) { + // Copy A and B, these will be the matrices on which we operate later + m_S = A; + m_T = B; + + // Perform QR decomposition of the matrix Q + HouseholderQR qr(m_T); + m_T = qr.matrixQR(); + m_T.template triangularView().setZero(); + + if (m_computeQZ) m_Q = qr.householderQ(); + + // overwrite S with Q* x S + m_S.applyOnTheLeft(qr.householderQ().adjoint()); + + if (m_computeQZ) m_Z = MatrixType::Identity(m_n, m_n); + + // reduce S to upper Hessenberg with Givens rotations + for (Index j = 0; j <= m_n - 3; j++) { + for (Index i = m_n - 1; i >= j + 2; i--) { + JacobiRotation G; + // delete S(i,j) + if (!numext::is_exactly_zero(m_S.coeff(i, j))) { + G.makeGivens(m_S.coeff(i - 1, j), m_S.coeff(i, j), &m_S.coeffRef(i - 1, j)); + m_S.coeffRef(i, j) = Scalar(0); + m_T.rightCols(m_n - i + 1).applyOnTheLeft(i - 1, i, G.adjoint()); + m_S.rightCols(m_n - j - 1).applyOnTheLeft(i - 1, i, G.adjoint()); + // This is what we want to achieve + if (!is_negligible(m_S(i, j))) + m_info = ComputationInfo::NumericalIssue; + else + m_S(i, j) = Scalar(0); + // update Q + if (m_computeQZ) m_Q.applyOnTheRight(i - 1, i, G); + } + + if (!numext::is_exactly_zero(m_T.coeff(i, i - 1))) { + // Compute rotation and update matrix T + G.makeGivens(m_T.coeff(i, i), m_T.coeff(i, i - 1), &m_T.coeffRef(i, i)); + m_T.topRows(i).applyOnTheRight(i - 1, i, G.adjoint()); + m_T.coeffRef(i, i - 1) = Scalar(0); + // Update matrix S + m_S.applyOnTheRight(i - 1, i, G.adjoint()); + // update Z + if (m_computeQZ) m_Z.applyOnTheLeft(i - 1, i, G); + } + } + } +} + +template +template +void ComplexQZ::hessenbergTriangularSparse(const SparseMatrixType_& A, const SparseMatrixType_& B) { + m_S = A.toDense(); + + SparseQR, NaturalOrdering> sparseQR; + + eigen_assert(B.isCompressed() && + "SparseQR requires a sparse matrix in compressed mode." + "Call .makeCompressed() before passing it to SparseQR"); + + // Computing QR decomposition of T... + sparseQR.setPivotThreshold(RealScalar(0)); // This prevends algorithm from doing pivoting + sparseQR.compute(B); + // perform QR decomposition of T, overwrite T with R, save Q + // HouseholderQR qrT(m_T); + m_T = sparseQR.matrixR(); + m_T.template triangularView().setZero(); + + if (m_computeQZ) m_Q = sparseQR.matrixQ(); + + // overwrite S with Q* S + m_S = sparseQR.matrixQ().adjoint() * m_S; + + if (m_computeQZ) m_Z = MatrixType::Identity(m_n, m_n); + + // reduce S to upper Hessenberg with Givens rotations + for (Index j = 0; j <= m_n - 3; j++) { + for (Index i = m_n - 1; i >= j + 2; i--) { + JacobiRotation G; + // kill S(i,j) + // if(!numext::is_exactly_zero(_S.coeff(i, j))) + if (m_S.coeff(i, j) != Scalar(0)) { + // This is the adapted code + G.makeGivens(m_S.coeff(i - 1, j), m_S.coeff(i, j), &m_S.coeffRef(i - 1, j)); + m_S.coeffRef(i, j) = Scalar(0); + m_T.rightCols(m_n - i + 1).applyOnTheLeft(i - 1, i, G.adjoint()); + m_S.rightCols(m_n - j - 1).applyOnTheLeft(i - 1, i, G.adjoint()); + // This is what we want to achieve + if (!is_negligible(m_S(i, j))) { + m_info = ComputationInfo::NumericalIssue; + } + m_S(i, j) = Scalar(0); + // update Q + if (m_computeQZ) m_Q.applyOnTheRight(i - 1, i, G); + } + + if (!numext::is_exactly_zero(m_T.coeff(i, i - 1))) { + // Compute rotation and update matrix T + G.makeGivens(m_T.coeff(i, i), m_T.coeff(i, i - 1), &m_T.coeffRef(i, i)); + m_T.topRows(i).applyOnTheRight(i - 1, i, G.adjoint()); + m_T.coeffRef(i, i - 1) = Scalar(0); + // Update matrix S + m_S.applyOnTheRight(i - 1, i, G.adjoint()); + // update Z + if (m_computeQZ) m_Z.applyOnTheLeft(i - 1, i, G); + } + } + } +} + +template +template +void ComplexQZ::computeSparse(const SparseMatrixType_& A, const SparseMatrixType_& B, bool computeQZ) { + m_computeQZ = computeQZ; + m_n = A.rows(); + eigen_assert(m_n == A.cols() && "A is not a square matrix"); + eigen_assert(m_n == B.rows() && m_n == B.cols() && "B is not a square matrix or B is not of the same size as A"); + m_isInitialized = true; + m_global_iter = 0; + hessenbergTriangularSparse(A, B); + + // We assume that we already have that A is upper-Hessenberg and B is + // upper-triangular. This is what the hessenbergTriangular(...) method does + reduceHessenbergTriangular(); +} + +template +void ComplexQZ::reduceHessenbergTriangular() { + Index l = m_n - 1, f; + unsigned int local_iter = 0; + computeNorms(); + + while (l > 0 && local_iter < m_maxIters) { + f = findSmallSubdiagEntry(l); + + // Subdiag entry is small -> can be safely set to 0 + if (f > 0) { + m_S.coeffRef(f, f - 1) = Scalar(0); + } + if (f == l) { // One root found + l--; + local_iter = 0; + } else if (f == l - 1) { // Two roots found + // We found an undesired non-zero at (f+1,f) in S and eliminate it immediately + reduceDiagonal2x2block(f); + l -= 2; + local_iter = 0; + } else { + Index z = findSmallDiagEntry(f, l); + if (z >= f) { + push_down_zero_ST(z, l); + } else { + do_QZ_step(f, m_n - l - 1); + local_iter++; + m_global_iter++; + } + } + } + + m_info = (local_iter < m_maxIters) ? Success : NoConvergence; +} + +template +inline typename ComplexQZ::Mat2 ComplexQZ::computeZk2(const Row2& b) { + Mat2 S; + S << Scalar(0), Scalar(1), Scalar(1), Scalar(0); + Vec2 bprime = S * b.adjoint(); + JacobiRotation J; + J.makeGivens(bprime(0), bprime(1)); + Mat2 Z = S; + Z.applyOnTheLeft(0, 1, J); + Z = S * Z; + return Z; +} + +template +void ComplexQZ::do_QZ_step(Index p, Index q) { + // This is certainly not the most efficient way of doing this, + // but a readable one. + const auto a = [p, this](Index i, Index j) { return m_S(p + i - 1, p + j - 1); }; + const auto b = [p, this](Index i, Index j) { return m_T(p + i - 1, p + j - 1); }; + const Index m = m_n - p - q; // Size of the inner block + Scalar x, y, z; + // We could introduce doing exceptional shifts from time to time. + Scalar W1 = a(m - 1, m - 1) / b(m - 1, m - 1) - a(1, 1) / b(1, 1), W2 = a(m, m) / b(m, m) - a(1, 1) / b(1, 1), + W3 = a(m, m - 1) / b(m - 1, m - 1); + + x = (W1 * W2 - a(m - 1, m) / b(m, m) * W3 + W3 * b(m - 1, m) / b(m, m) * a(1, 1) / b(1, 1)) * b(1, 1) / a(2, 1) + + a(1, 2) / b(2, 2) - a(1, 1) / b(1, 1) * b(1, 2) / b(2, 2); + y = (a(2, 2) / b(2, 2) - a(1, 1) / b(1, 1)) - a(2, 1) / b(1, 1) * b(1, 2) / b(2, 2) - W1 - W2 + + W3 * (b(m - 1, m) / b(m, m)); + z = a(3, 2) / b(2, 2); + Vec3 X; + const PermutationMatrix<3, 3, int> S3(Vector3i(2, 0, 1)); + for (Index k = p; k < p + m - 2; k++) { + X << x, y, z; + Vec2 ess; + Scalar tau; + RealScalar beta; + X.makeHouseholder(ess, tau, beta); + // The permutations are needed because the makeHouseHolder-method computes + // the householder transformation in a way that the vector is reflected to + // (1 0 ... 0) instead of (0 ... 0 1) + m_S.template middleRows<3>(k) + .rightCols((std::min)(m_n, m_n - k + 1)) + .applyHouseholderOnTheLeft(ess, tau, m_ws.data()); + m_T.template middleRows<3>(k).rightCols(m_n - k).applyHouseholderOnTheLeft(ess, tau, m_ws.data()); + if (m_computeQZ) m_Q.template middleCols<3>(k).applyHouseholderOnTheRight(ess, std::conj(tau), m_ws.data()); + + // Compute Matrix Zk1 s.t. (b(k+2,k) ... b(k+2, k+2)) Zk1 = (0,0,*) + Vec3 bprime = (m_T.template block<1, 3>(k + 2, k) * S3).adjoint(); + bprime.makeHouseholder(ess, tau, beta); + m_S.template middleCols<3>(k).topRows((std::min)(k + 4, m_n)).applyOnTheRight(S3); + m_S.template middleCols<3>(k) + .topRows((std::min)(k + 4, m_n)) + .applyHouseholderOnTheRight(ess, std::conj(tau), m_ws.data()); + m_S.template middleCols<3>(k).topRows((std::min)(k + 4, m_n)).applyOnTheRight(S3.transpose()); + m_T.template middleCols<3>(k).topRows((std::min)(k + 3, m_n)).applyOnTheRight(S3); + m_T.template middleCols<3>(k) + .topRows((std::min)(k + 3, m_n)) + .applyHouseholderOnTheRight(ess, std::conj(tau), m_ws.data()); + m_T.template middleCols<3>(k).topRows((std::min)(k + 3, m_n)).applyOnTheRight(S3.transpose()); + if (m_computeQZ) { + m_Z.template middleRows<3>(k).applyOnTheLeft(S3.transpose()); + m_Z.template middleRows<3>(k).applyHouseholderOnTheLeft(ess, tau, m_ws.data()); + m_Z.template middleRows<3>(k).applyOnTheLeft(S3); + } + Mat2 Zk2 = computeZk2(m_T.template block<1, 2>(k + 1, k)); + m_S.template middleCols<2>(k).topRows((std::min)(k + 4, m_n)).applyOnTheRight(Zk2); + m_T.template middleCols<2>(k).topRows((std::min)(k + 3, m_n)).applyOnTheRight(Zk2); + + if (m_computeQZ) m_Z.template middleRows<2>(k).applyOnTheLeft(Zk2.adjoint()); + + x = m_S(k + 1, k); + y = m_S(k + 2, k); + if (k < p + m - 3) { + z = m_S(k + 3, k); + } + }; + + // Find a Householdermartirx Qn1 s.t. Qn1 (x y)^T = (* 0) + JacobiRotation J; + J.makeGivens(x, y); + m_S.template middleRows<2>(p + m - 2).applyOnTheLeft(0, 1, J.adjoint()); + m_T.template middleRows<2>(p + m - 2).applyOnTheLeft(0, 1, J.adjoint()); + + if (m_computeQZ) m_Q.template middleCols<2>(p + m - 2).applyOnTheRight(0, 1, J); + + // Find a Householdermatrix Zn1 s.t. (b(n,n-1) b(n,n)) * Zn1 = (0 *) + Mat2 Zn1 = computeZk2(m_T.template block<1, 2>(p + m - 1, p + m - 2)); + m_S.template middleCols<2>(p + m - 2).applyOnTheRight(Zn1); + m_T.template middleCols<2>(p + m - 2).applyOnTheRight(Zn1); + + if (m_computeQZ) m_Z.template middleRows<2>(p + m - 2).applyOnTheLeft(Zn1.adjoint()); +} + +/** \internal we found an undesired non-zero at (i+1,i) on the subdiagonal of S and reduce the block */ +template +void ComplexQZ::reduceDiagonal2x2block(Index i) { + // We have found a non-zero on the subdiagonal and want to eliminate it + Mat2 Si = m_S.template block<2, 2>(i, i), Ti = m_T.template block<2, 2>(i, i); + if (is_negligible(Ti(0, 0)) && !is_negligible(Ti(1, 1))) { + Eigen::JacobiRotation G; + G.makeGivens(m_S(i, i), m_S(i + 1, i)); + m_S.applyOnTheLeft(i, i + 1, G.adjoint()); + m_T.applyOnTheLeft(i, i + 1, G.adjoint()); + + if (m_computeQZ) m_Q.applyOnTheRight(i, i + 1, G); + + } else if (!is_negligible(Ti(0, 0)) && is_negligible(Ti(1, 1))) { + Eigen::JacobiRotation G; + G.makeGivens(m_S(i + 1, i + 1), m_S(i + 1, i)); + m_S.applyOnTheRight(i, i + 1, G.adjoint()); + m_T.applyOnTheRight(i, i + 1, G.adjoint()); + if (m_computeQZ) m_Z.applyOnTheLeft(i, i + 1, G); + } else if (!is_negligible(Ti(0, 0)) && !is_negligible((Ti(1, 1)))) { + Scalar mu = Si(0, 0) / Ti(0, 0); + Scalar a12_bar = Si(0, 1) - mu * Ti(0, 1); + Scalar a22_bar = Si(1, 1) - mu * Ti(1, 1); + Scalar p = Scalar(0.5) * (a22_bar / Ti(1, 1) - Ti(0, 1) * Si(1, 0) / (Ti(0, 0) * Ti(1, 1))); + RealScalar sgn_p = p.real() >= RealScalar(0) ? RealScalar(1) : RealScalar(-1); + Scalar q = Si(1, 0) * a12_bar / (Ti(0, 0) * Ti(1, 1)); + Scalar r = p * p + q; + Scalar lambda = mu + p + sgn_p * numext::sqrt(r); + Mat2 E = Si - lambda * Ti; + Index l; + E.rowwise().norm().maxCoeff(&l); + JacobiRotation G; + G.makeGivens(E(l, 1), E(l, 0)); + m_S.applyOnTheRight(i, i + 1, G.adjoint()); + m_T.applyOnTheRight(i, i + 1, G.adjoint()); + + if (m_computeQZ) m_Z.applyOnTheLeft(i, i + 1, G); + + Mat2 tildeSi = m_S.template block<2, 2>(i, i), tildeTi = m_T.template block<2, 2>(i, i); + Mat2 C = tildeSi.norm() < (lambda * tildeTi).norm() ? tildeSi : lambda * tildeTi; + G.makeGivens(C(0, 0), C(1, 0)); + m_S.applyOnTheLeft(i, i + 1, G.adjoint()); + m_T.applyOnTheLeft(i, i + 1, G.adjoint()); + + if (m_computeQZ) m_Q.applyOnTheRight(i, i + 1, G); + } + + if (!is_negligible(m_S(i + 1, i), m_normOfS * NumTraits::epsilon())) { + m_info = ComputationInfo::NumericalIssue; + } else { + m_S(i + 1, i) = Scalar(0); + } +} + +/** \internal We found a zero at T(k,k) and want to "push it down" to T(l,l) */ +template +void ComplexQZ::push_down_zero_ST(Index k, Index l) { + // Test Preconditions + + JacobiRotation J; + for (Index j = k + 1; j <= l; j++) { + // Create a 0 at _T(j, j) + J.makeGivens(m_T(j - 1, j), m_T(j, j), &m_T.coeffRef(j - 1, j)); + m_T.rightCols(m_n - j - 1).applyOnTheLeft(j - 1, j, J.adjoint()); + m_T.coeffRef(j, j) = Scalar(0); + + m_S.applyOnTheLeft(j - 1, j, J.adjoint()); + + if (m_computeQZ) m_Q.applyOnTheRight(j - 1, j, J); + + // Delete the non-desired non-zero at _S(j, j-2) + if (j > 1) { + J.makeGivens(std::conj(m_S(j, j - 1)), std::conj(m_S(j, j - 2))); + m_S.applyOnTheRight(j - 1, j - 2, J); + m_S(j, j - 2) = Scalar(0); + m_T.applyOnTheRight(j - 1, j - 2, J); + if (m_computeQZ) m_Z.applyOnTheLeft(j - 1, j - 2, J.adjoint()); + } + } + + // Assume we have the desired structure now, up to the non-zero entry at + // _S(l, l-1) which we will delete through a last right-jacobi-rotation + J.makeGivens(std::conj(m_S(l, l)), std::conj(m_S(l, l - 1))); + m_S.topRows(l + 1).applyOnTheRight(l, l - 1, J); + + if (!is_negligible(m_S(l, l - 1), m_normOfS * NumTraits::epsilon())) { + m_info = ComputationInfo::NumericalIssue; + } else { + m_S(l, l - 1) = Scalar(0); + } + m_T.topRows(l + 1).applyOnTheRight(l, l - 1, J); + + if (m_computeQZ) m_Z.applyOnTheLeft(l, l - 1, J.adjoint()); + + // Ensure postconditions + if (!is_negligible(m_T(l, l)) || !is_negligible(m_S(l, l - 1))) { + m_info = ComputationInfo::NumericalIssue; + } else { + m_T(l, l) = Scalar(0); + m_S(l, l - 1) = Scalar(0); + } +} + +/** \internal Computes vector L1 norms of S and T when in Hessenberg-Triangular form already */ +template +void ComplexQZ::computeNorms() { + const Index size = m_S.cols(); + m_normOfS = RealScalar(0); + m_normOfT = RealScalar(0); + for (Index j = 0; j < size; ++j) { + m_normOfS += m_S.col(j).segment(0, (std::min)(size, j + 2)).cwiseAbs().sum(); + m_normOfT += m_T.row(j).segment(j, size - j).cwiseAbs().sum(); + } +} + +/** \internal Look for single small sub-diagonal element S(res, res-1) and return res (or 0). Copied from Eigen3 RealQZ + * implementation */ +template +inline Index ComplexQZ::findSmallSubdiagEntry(Index iu) { + Index res = iu; + while (res > 0) { + RealScalar s = numext::abs(m_S.coeff(res - 1, res - 1)) + numext::abs(m_S.coeff(res, res)); + if (s == Scalar(0)) s = m_normOfS; + if (numext::abs(m_S.coeff(res, res - 1)) < NumTraits::epsilon() * s) break; + res--; + } + return res; +} + +// +/** \internal Look for single small diagonal element T(res, res) for res between f and l, and return res (or f-1). + * Copied from Eigen3 RealQZ implementation. */ +template +inline Index ComplexQZ::findSmallDiagEntry(Index f, Index l) { + Index res = l; + while (res >= f) { + if (numext::abs(m_T.coeff(res, res)) <= NumTraits::epsilon() * m_normOfT) break; + res--; + } + return res; +} + +} // namespace Eigen + +#endif // _COMPLEX_QZ_H_ diff --git a/Eigen/src/Jacobi/Jacobi.h b/Eigen/src/Jacobi/Jacobi.h index 9bc9b1099..fa0a7ac8b 100644 --- a/Eigen/src/Jacobi/Jacobi.h +++ b/Eigen/src/Jacobi/Jacobi.h @@ -348,8 +348,8 @@ struct apply_rotation_in_the_plane_selector(px); Packet yi = pload(py); - pstore(px, padd(pm.pmul(pc, xi), pcj.pmul(ps, yi))); - pstore(py, psub(pcj.pmul(pc, yi), pm.pmul(ps, xi))); + pstore(px, pm.pmadd(pc, xi, pcj.pmul(ps, yi))); + pstore(py, pcj.pmsub(pc, yi, pm.pmul(ps, xi))); px += PacketSize; py += PacketSize; } @@ -360,18 +360,18 @@ struct apply_rotation_in_the_plane_selector(px + PacketSize); Packet yi = pload(py); Packet yi1 = pload(py + PacketSize); - pstoreu(px, padd(pm.pmul(pc, xi), pcj.pmul(ps, yi))); - pstoreu(px + PacketSize, padd(pm.pmul(pc, xi1), pcj.pmul(ps, yi1))); - pstore(py, psub(pcj.pmul(pc, yi), pm.pmul(ps, xi))); - pstore(py + PacketSize, psub(pcj.pmul(pc, yi1), pm.pmul(ps, xi1))); + pstoreu(px, pm.pmadd(pc, xi, pcj.pmul(ps, yi))); + pstoreu(px + PacketSize, pm.pmadd(pc, xi1, pcj.pmul(ps, yi1))); + pstore(py, pcj.pmsub(pc, yi, pm.pmul(ps, xi))); + pstore(py + PacketSize, pcj.pmsub(pc, yi1, pm.pmul(ps, xi1))); px += Peeling * PacketSize; py += Peeling * PacketSize; } if (alignedEnd != peelingEnd) { Packet xi = ploadu(x + peelingEnd); Packet yi = pload(y + peelingEnd); - pstoreu(x + peelingEnd, padd(pm.pmul(pc, xi), pcj.pmul(ps, yi))); - pstore(y + peelingEnd, psub(pcj.pmul(pc, yi), pm.pmul(ps, xi))); + pstoreu(x + peelingEnd, pm.pmadd(pc, xi, pcj.pmul(ps, yi))); + pstore(y + peelingEnd, pcj.pmsub(pc, yi, pm.pmul(ps, xi))); } } @@ -394,8 +394,8 @@ struct apply_rotation_in_the_plane_selector(px); Packet yi = pload(py); - pstore(px, padd(pm.pmul(pc, xi), pcj.pmul(ps, yi))); - pstore(py, psub(pcj.pmul(pc, yi), pm.pmul(ps, xi))); + pstore(px, pm.pmadd(pc, xi, pcj.pmul(ps, yi))); + pstore(py, pcj.pmsub(pc, yi, pm.pmul(ps, xi))); px += PacketSize; py += PacketSize; } @@ -433,6 +433,34 @@ EIGEN_DEVICE_FUNC void inline apply_rotation_in_the_plane(DenseBase& xp x, incrx, y, incry, size, c, s); } +template +void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q, JacobiRotation* j_left, + JacobiRotation* j_right) { + using std::abs; + using std::sqrt; + Matrix m; + m << numext::real(matrix.coeff(p, p)), numext::real(matrix.coeff(p, q)), numext::real(matrix.coeff(q, p)), + numext::real(matrix.coeff(q, q)); + JacobiRotation rot1; + RealScalar t = m.coeff(0, 0) + m.coeff(1, 1); + RealScalar d = m.coeff(1, 0) - m.coeff(0, 1); + + if (abs(d) < (std::numeric_limits::min)()) { + rot1.s() = RealScalar(0); + rot1.c() = RealScalar(1); + } else { + // If d!=0, then t/d cannot overflow because the magnitude of the + // entries forming d are not too small compared to the ones forming t. + RealScalar u = t / d; + RealScalar tmp = sqrt(RealScalar(1) + numext::abs2(u)); + rot1.s() = RealScalar(1) / tmp; + rot1.c() = u / tmp; + } + m.applyOnTheLeft(0, 1, rot1); + j_right->makeJacobi(m, 0, 1); + *j_left = rot1 * j_right->transpose(); +} + } // end namespace internal } // end namespace Eigen diff --git a/Eigen/src/KLUSupport/KLUSupport.h b/Eigen/src/KLUSupport/KLUSupport.h index 91960222d..21324ab74 100644 --- a/Eigen/src/KLUSupport/KLUSupport.h +++ b/Eigen/src/KLUSupport/KLUSupport.h @@ -182,7 +182,7 @@ class KLU : public SparseSolverBase > { /** Performs a numeric decomposition of \a matrix * - * The given matrix must has the same sparsity than the matrix on which the pattern anylysis has been performed. + * The given matrix must have the same sparsity than the matrix on which the pattern anylysis has been performed. * * \sa analyzePattern(), compute() */ diff --git a/Eigen/src/PardisoSupport/PardisoSupport.h b/Eigen/src/PardisoSupport/PardisoSupport.h index c4ca6d385..2f5d83eeb 100644 --- a/Eigen/src/PardisoSupport/PardisoSupport.h +++ b/Eigen/src/PardisoSupport/PardisoSupport.h @@ -157,7 +157,8 @@ class PardisoImpl : public SparseSolverBase { /** Performs a numeric decomposition of \a matrix * - * The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed. + * The given matrix must have the same sparsity than the matrix on which the symbolic decomposition has been + * performed. * * \sa analyzePattern() */ diff --git a/Eigen/src/SVD/JacobiSVD.h b/Eigen/src/SVD/JacobiSVD.h index da2f29593..dfcb6df5e 100644 --- a/Eigen/src/SVD/JacobiSVD.h +++ b/Eigen/src/SVD/JacobiSVD.h @@ -571,6 +571,11 @@ class JacobiSVD : public SVDBase > { compute_impl(matrix, internal::get_computation_options(Options)); } + template + explicit JacobiSVD(const TriangularBase& matrix) { + compute_impl(matrix, internal::get_computation_options(Options)); + } + /** \brief Constructor performing the decomposition of given matrix using specified options * for computing unitaries. * @@ -601,6 +606,11 @@ class JacobiSVD : public SVDBase > { return compute_impl(matrix, m_computationOptions); } + template + JacobiSVD& compute(const TriangularBase& matrix) { + return compute_impl(matrix, m_computationOptions); + } + /** \brief Method performing the decomposition of given matrix, as specified by * the `computationOptions` parameter. * @@ -638,6 +648,8 @@ class JacobiSVD : public SVDBase > { } private: + template + JacobiSVD& compute_impl(const TriangularBase& matrix, unsigned int computationOptions); template JacobiSVD& compute_impl(const MatrixBase& matrix, unsigned int computationOptions); @@ -676,6 +688,13 @@ class JacobiSVD : public SVDBase > { WorkMatrixType m_workMatrix; }; +template +template +JacobiSVD& JacobiSVD::compute_impl(const TriangularBase& matrix, + unsigned int computationOptions) { + return compute_impl(matrix.toDenseMatrix(), computationOptions); +} + template template JacobiSVD& JacobiSVD::compute_impl(const MatrixBase& matrix, diff --git a/Eigen/src/SparseCholesky/SimplicialCholesky.h b/Eigen/src/SparseCholesky/SimplicialCholesky.h index d8e29447f..14147945a 100644 --- a/Eigen/src/SparseCholesky/SimplicialCholesky.h +++ b/Eigen/src/SparseCholesky/SimplicialCholesky.h @@ -416,7 +416,8 @@ class SimplicialLLT : public SimplicialCholeskyBase > { /** Performs a numeric decomposition of \a matrix * - * The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed. + * The given matrix must have the same sparsity than the matrix on which the symbolic decomposition has been + * performed. * * \sa analyzePattern() */ @@ -791,7 +792,8 @@ class SuperILU : public SuperLUBase > { /** Performs a numeric decomposition of \a matrix * - * The given matrix must has the same sparsity than the matrix on which the symbolic decomposition has been performed. + * The given matrix must have the same sparsity than the matrix on which the symbolic decomposition has been + * performed. * * \sa analyzePattern() */ diff --git a/Eigen/src/UmfPackSupport/UmfPackSupport.h b/Eigen/src/UmfPackSupport/UmfPackSupport.h index 1df8493d3..22c701b97 100644 --- a/Eigen/src/UmfPackSupport/UmfPackSupport.h +++ b/Eigen/src/UmfPackSupport/UmfPackSupport.h @@ -425,7 +425,7 @@ class UmfPackLU : public SparseSolverBase > { /** Performs a numeric decomposition of \a matrix * - * The given matrix must has the same sparsity than the matrix on which the pattern anylysis has been performed. + * The given matrix must have the same sparsity than the matrix on which the pattern anylysis has been performed. * * \sa analyzePattern(), compute() */ diff --git a/Eigen/src/misc/RealSvd2x2.h b/Eigen/src/misc/RealSvd2x2.h deleted file mode 100644 index 332a5abbc..000000000 --- a/Eigen/src/misc/RealSvd2x2.h +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009-2010 Benoit Jacob -// Copyright (C) 2013-2016 Gael Guennebaud -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_REALSVD2X2_H -#define EIGEN_REALSVD2X2_H - -// IWYU pragma: private -#include "./InternalHeaderCheck.h" - -namespace Eigen { - -namespace internal { - -template -void real_2x2_jacobi_svd(const MatrixType &matrix, Index p, Index q, JacobiRotation *j_left, - JacobiRotation *j_right) { - using std::abs; - using std::sqrt; - Matrix m; - m << numext::real(matrix.coeff(p, p)), numext::real(matrix.coeff(p, q)), numext::real(matrix.coeff(q, p)), - numext::real(matrix.coeff(q, q)); - JacobiRotation rot1; - RealScalar t = m.coeff(0, 0) + m.coeff(1, 1); - RealScalar d = m.coeff(1, 0) - m.coeff(0, 1); - - if (abs(d) < (std::numeric_limits::min)()) { - rot1.s() = RealScalar(0); - rot1.c() = RealScalar(1); - } else { - // If d!=0, then t/d cannot overflow because the magnitude of the - // entries forming d are not too small compared to the ones forming t. - RealScalar u = t / d; - RealScalar tmp = sqrt(RealScalar(1) + numext::abs2(u)); - rot1.s() = RealScalar(1) / tmp; - rot1.c() = u / tmp; - } - m.applyOnTheLeft(0, 1, rot1); - j_right->makeJacobi(m, 0, 1); - *j_left = rot1 * j_right->transpose(); -} - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_REALSVD2X2_H diff --git a/blas/CMakeLists.txt b/blas/CMakeLists.txt index 8842b30b7..45488d73d 100644 --- a/blas/CMakeLists.txt +++ b/blas/CMakeLists.txt @@ -19,7 +19,9 @@ add_library(eigen_blas_static STATIC ${EigenBlas_SRCS}) list(APPEND EIGEN_BLAS_TARGETS eigen_blas_static) if (EIGEN_BUILD_SHARED_LIBS) - add_library(eigen_blas SHARED ${EigenBlas_SRCS}) + add_library(eigen_blas SHARED ${EigenBlas_SRCS} "eigen_blas.def") + target_compile_definitions(eigen_blas PUBLIC "EIGEN_BLAS_BUILD_DLL") + set_target_properties(eigen_blas PROPERTIES CXX_VISIBILITY_PRESET hidden) list(APPEND EIGEN_BLAS_TARGETS eigen_blas) endif() diff --git a/blas/blas.h b/blas/blas.h index 178b5e5cc..2f218a8b5 100644 --- a/blas/blas.h +++ b/blas/blas.h @@ -1,6 +1,20 @@ #ifndef BLAS_H #define BLAS_H +#if defined(_WIN32) +#if defined(EIGEN_BLAS_BUILD_DLL) +#define EIGEN_BLAS_API __declspec(dllexport) +#elif defined(EIGEN_BLAS_LINK_DLL) +#define EIGEN_BLAS_API __declspec(dllimport) +#else +#define EIGEN_BLAS_API +#endif +#elif ((defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)) && defined(EIGEN_BLAS_BUILD_DLL) +#define EIGEN_BLAS_API __attribute__((visibility("default"))) +#else +#define EIGEN_BLAS_API +#endif + #ifdef __cplusplus extern "C" { #endif @@ -15,467 +29,514 @@ typedef long BLASLONG; typedef unsigned long BLASULONG; #endif -void BLASFUNC(xerbla)(const char *, int *info); +EIGEN_BLAS_API int BLASFUNC(lsame)(const char *, const char *); +EIGEN_BLAS_API void BLASFUNC(xerbla)(const char *, int *info); -float BLASFUNC(sdot)(int *, float *, int *, float *, int *); -float BLASFUNC(sdsdot)(int *, float *, float *, int *, float *, int *); +EIGEN_BLAS_API float BLASFUNC(sdot)(int *, float *, int *, float *, int *); +EIGEN_BLAS_API float BLASFUNC(sdsdot)(int *, float *, float *, int *, float *, int *); -double BLASFUNC(dsdot)(int *, float *, int *, float *, int *); -double BLASFUNC(ddot)(int *, double *, int *, double *, int *); -double BLASFUNC(qdot)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(dsdot)(int *, float *, int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(ddot)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qdot)(int *, double *, int *, double *, int *); -void BLASFUNC(cdotuw)(int *, float *, int *, float *, int *, float *); -void BLASFUNC(cdotcw)(int *, float *, int *, float *, int *, float *); -void BLASFUNC(zdotuw)(int *, double *, int *, double *, int *, double *); -void BLASFUNC(zdotcw)(int *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(cdotu)(int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(cdotc)(int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zdotu)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(zdotc)(int *, double *, int *, double *, int *); -void BLASFUNC(saxpy)(const int *, const float *, const float *, const int *, float *, const int *); -void BLASFUNC(daxpy)(const int *, const double *, const double *, const int *, double *, const int *); -void BLASFUNC(qaxpy)(const int *, const double *, const double *, const int *, double *, const int *); -void BLASFUNC(caxpy)(const int *, const float *, const float *, const int *, float *, const int *); -void BLASFUNC(zaxpy)(const int *, const double *, const double *, const int *, double *, const int *); -void BLASFUNC(xaxpy)(const int *, const double *, const double *, const int *, double *, const int *); -void BLASFUNC(caxpyc)(const int *, const float *, const float *, const int *, float *, const int *); -void BLASFUNC(zaxpyc)(const int *, const double *, const double *, const int *, double *, const int *); -void BLASFUNC(xaxpyc)(const int *, const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(cdotuw)(int *, float *, int *, float *, int *, float *); +EIGEN_BLAS_API void BLASFUNC(cdotcw)(int *, float *, int *, float *, int *, float *); +EIGEN_BLAS_API void BLASFUNC(zdotuw)(int *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(zdotcw)(int *, double *, int *, double *, int *, double *); -void BLASFUNC(scopy)(int *, float *, int *, float *, int *); -void BLASFUNC(dcopy)(int *, double *, int *, double *, int *); -void BLASFUNC(qcopy)(int *, double *, int *, double *, int *); -void BLASFUNC(ccopy)(int *, float *, int *, float *, int *); -void BLASFUNC(zcopy)(int *, double *, int *, double *, int *); -void BLASFUNC(xcopy)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(saxpy)(const int *, const float *, const float *, const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(daxpy)(const int *, const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qaxpy)(const int *, const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(caxpy)(const int *, const float *, const float *, const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zaxpy)(const int *, const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xaxpy)(const int *, const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(caxpyc)(const int *, const float *, const float *, const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zaxpyc)(const int *, const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xaxpyc)(const int *, const double *, const double *, const int *, double *, const int *); -void BLASFUNC(sswap)(int *, float *, int *, float *, int *); -void BLASFUNC(dswap)(int *, double *, int *, double *, int *); -void BLASFUNC(qswap)(int *, double *, int *, double *, int *); -void BLASFUNC(cswap)(int *, float *, int *, float *, int *); -void BLASFUNC(zswap)(int *, double *, int *, double *, int *); -void BLASFUNC(xswap)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(scopy)(int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dcopy)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qcopy)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(ccopy)(int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zcopy)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xcopy)(int *, double *, int *, double *, int *); -float BLASFUNC(sasum)(int *, float *, int *); -float BLASFUNC(scasum)(int *, float *, int *); -double BLASFUNC(dasum)(int *, double *, int *); -double BLASFUNC(qasum)(int *, double *, int *); -double BLASFUNC(dzasum)(int *, double *, int *); -double BLASFUNC(qxasum)(int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(sswap)(int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dswap)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qswap)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(cswap)(int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zswap)(int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xswap)(int *, double *, int *, double *, int *); -int BLASFUNC(isamax)(int *, float *, int *); -int BLASFUNC(idamax)(int *, double *, int *); -int BLASFUNC(iqamax)(int *, double *, int *); -int BLASFUNC(icamax)(int *, float *, int *); -int BLASFUNC(izamax)(int *, double *, int *); -int BLASFUNC(ixamax)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(sasum)(int *, float *, int *); +EIGEN_BLAS_API float BLASFUNC(scasum)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(dasum)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qasum)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(dzasum)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qxasum)(int *, double *, int *); -int BLASFUNC(ismax)(int *, float *, int *); -int BLASFUNC(idmax)(int *, double *, int *); -int BLASFUNC(iqmax)(int *, double *, int *); -int BLASFUNC(icmax)(int *, float *, int *); -int BLASFUNC(izmax)(int *, double *, int *); -int BLASFUNC(ixmax)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(isamax)(int *, float *, int *); +EIGEN_BLAS_API int BLASFUNC(idamax)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(iqamax)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(icamax)(int *, float *, int *); +EIGEN_BLAS_API int BLASFUNC(izamax)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(ixamax)(int *, double *, int *); -int BLASFUNC(isamin)(int *, float *, int *); -int BLASFUNC(idamin)(int *, double *, int *); -int BLASFUNC(iqamin)(int *, double *, int *); -int BLASFUNC(icamin)(int *, float *, int *); -int BLASFUNC(izamin)(int *, double *, int *); -int BLASFUNC(ixamin)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(ismax)(int *, float *, int *); +EIGEN_BLAS_API int BLASFUNC(idmax)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(iqmax)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(icmax)(int *, float *, int *); +EIGEN_BLAS_API int BLASFUNC(izmax)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(ixmax)(int *, double *, int *); -int BLASFUNC(ismin)(int *, float *, int *); -int BLASFUNC(idmin)(int *, double *, int *); -int BLASFUNC(iqmin)(int *, double *, int *); -int BLASFUNC(icmin)(int *, float *, int *); -int BLASFUNC(izmin)(int *, double *, int *); -int BLASFUNC(ixmin)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(isamin)(int *, float *, int *); +EIGEN_BLAS_API int BLASFUNC(idamin)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(iqamin)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(icamin)(int *, float *, int *); +EIGEN_BLAS_API int BLASFUNC(izamin)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(ixamin)(int *, double *, int *); -float BLASFUNC(samax)(int *, float *, int *); -double BLASFUNC(damax)(int *, double *, int *); -double BLASFUNC(qamax)(int *, double *, int *); -float BLASFUNC(scamax)(int *, float *, int *); -double BLASFUNC(dzamax)(int *, double *, int *); -double BLASFUNC(qxamax)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(ismin)(int *, float *, int *); +EIGEN_BLAS_API int BLASFUNC(idmin)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(iqmin)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(icmin)(int *, float *, int *); +EIGEN_BLAS_API int BLASFUNC(izmin)(int *, double *, int *); +EIGEN_BLAS_API int BLASFUNC(ixmin)(int *, double *, int *); -float BLASFUNC(samin)(int *, float *, int *); -double BLASFUNC(damin)(int *, double *, int *); -double BLASFUNC(qamin)(int *, double *, int *); -float BLASFUNC(scamin)(int *, float *, int *); -double BLASFUNC(dzamin)(int *, double *, int *); -double BLASFUNC(qxamin)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(samax)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(damax)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qamax)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(scamax)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(dzamax)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qxamax)(int *, double *, int *); -float BLASFUNC(smax)(int *, float *, int *); -double BLASFUNC(dmax)(int *, double *, int *); -double BLASFUNC(qmax)(int *, double *, int *); -float BLASFUNC(scmax)(int *, float *, int *); -double BLASFUNC(dzmax)(int *, double *, int *); -double BLASFUNC(qxmax)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(samin)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(damin)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qamin)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(scamin)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(dzamin)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qxamin)(int *, double *, int *); -float BLASFUNC(smin)(int *, float *, int *); -double BLASFUNC(dmin)(int *, double *, int *); -double BLASFUNC(qmin)(int *, double *, int *); -float BLASFUNC(scmin)(int *, float *, int *); -double BLASFUNC(dzmin)(int *, double *, int *); -double BLASFUNC(qxmin)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(smax)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(dmax)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qmax)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(scmax)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(dzmax)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qxmax)(int *, double *, int *); -void BLASFUNC(sscal)(int *, float *, float *, int *); -void BLASFUNC(dscal)(int *, double *, double *, int *); -void BLASFUNC(qscal)(int *, double *, double *, int *); -void BLASFUNC(cscal)(int *, float *, float *, int *); -void BLASFUNC(zscal)(int *, double *, double *, int *); -void BLASFUNC(xscal)(int *, double *, double *, int *); -void BLASFUNC(csscal)(int *, float *, float *, int *); -void BLASFUNC(zdscal)(int *, double *, double *, int *); -void BLASFUNC(xqscal)(int *, double *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(smin)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(dmin)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qmin)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(scmin)(int *, float *, int *); +EIGEN_BLAS_API double BLASFUNC(dzmin)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qxmin)(int *, double *, int *); -float BLASFUNC(snrm2)(int *, float *, int *); -float BLASFUNC(scnrm2)(int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(sscal)(int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dscal)(int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qscal)(int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(cscal)(int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zscal)(int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xscal)(int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(csscal)(int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zdscal)(int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xqscal)(int *, double *, double *, int *); -double BLASFUNC(dnrm2)(int *, double *, int *); -double BLASFUNC(qnrm2)(int *, double *, int *); -double BLASFUNC(dznrm2)(int *, double *, int *); -double BLASFUNC(qxnrm2)(int *, double *, int *); +EIGEN_BLAS_API float BLASFUNC(snrm2)(int *, float *, int *); +EIGEN_BLAS_API float BLASFUNC(scnrm2)(int *, float *, int *); -void BLASFUNC(srot)(int *, float *, int *, float *, int *, float *, float *); -void BLASFUNC(drot)(int *, double *, int *, double *, int *, double *, double *); -void BLASFUNC(qrot)(int *, double *, int *, double *, int *, double *, double *); -void BLASFUNC(csrot)(int *, float *, int *, float *, int *, float *, float *); -void BLASFUNC(zdrot)(int *, double *, int *, double *, int *, double *, double *); -void BLASFUNC(xqrot)(int *, double *, int *, double *, int *, double *, double *); +EIGEN_BLAS_API double BLASFUNC(dnrm2)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qnrm2)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(dznrm2)(int *, double *, int *); +EIGEN_BLAS_API double BLASFUNC(qxnrm2)(int *, double *, int *); -void BLASFUNC(srotg)(float *, float *, float *, float *); -void BLASFUNC(drotg)(double *, double *, double *, double *); -void BLASFUNC(qrotg)(double *, double *, double *, double *); -void BLASFUNC(crotg)(float *, float *, float *, float *); -void BLASFUNC(zrotg)(double *, double *, double *, double *); -void BLASFUNC(xrotg)(double *, double *, double *, double *); +EIGEN_BLAS_API void BLASFUNC(srot)(int *, float *, int *, float *, int *, float *, float *); +EIGEN_BLAS_API void BLASFUNC(drot)(int *, double *, int *, double *, int *, double *, double *); +EIGEN_BLAS_API void BLASFUNC(qrot)(int *, double *, int *, double *, int *, double *, double *); +EIGEN_BLAS_API void BLASFUNC(csrot)(int *, float *, int *, float *, int *, float *, float *); +EIGEN_BLAS_API void BLASFUNC(zdrot)(int *, double *, int *, double *, int *, double *, double *); +EIGEN_BLAS_API void BLASFUNC(xqrot)(int *, double *, int *, double *, int *, double *, double *); -void BLASFUNC(srotmg)(float *, float *, float *, float *, float *); -void BLASFUNC(drotmg)(double *, double *, double *, double *, double *); +EIGEN_BLAS_API void BLASFUNC(srotg)(float *, float *, float *, float *); +EIGEN_BLAS_API void BLASFUNC(drotg)(double *, double *, double *, double *); +EIGEN_BLAS_API void BLASFUNC(qrotg)(double *, double *, double *, double *); +EIGEN_BLAS_API void BLASFUNC(crotg)(float *, float *, float *, float *); +EIGEN_BLAS_API void BLASFUNC(zrotg)(double *, double *, double *, double *); +EIGEN_BLAS_API void BLASFUNC(xrotg)(double *, double *, double *, double *); -void BLASFUNC(srotm)(int *, float *, int *, float *, int *, float *); -void BLASFUNC(drotm)(int *, double *, int *, double *, int *, double *); -void BLASFUNC(qrotm)(int *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(srotmg)(float *, float *, float *, float *, float *); +EIGEN_BLAS_API void BLASFUNC(drotmg)(double *, double *, double *, double *, double *); + +EIGEN_BLAS_API void BLASFUNC(srotm)(int *, float *, int *, float *, int *, float *); +EIGEN_BLAS_API void BLASFUNC(drotm)(int *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(qrotm)(int *, double *, int *, double *, int *, double *); /* Level 2 routines */ -void BLASFUNC(sger)(int *, int *, float *, float *, int *, float *, int *, float *, int *); -void BLASFUNC(dger)(int *, int *, double *, double *, int *, double *, int *, double *, int *); -void BLASFUNC(qger)(int *, int *, double *, double *, int *, double *, int *, double *, int *); -void BLASFUNC(cgeru)(int *, int *, float *, float *, int *, float *, int *, float *, int *); -void BLASFUNC(cgerc)(int *, int *, float *, float *, int *, float *, int *, float *, int *); -void BLASFUNC(zgeru)(int *, int *, double *, double *, int *, double *, int *, double *, int *); -void BLASFUNC(zgerc)(int *, int *, double *, double *, int *, double *, int *, double *, int *); -void BLASFUNC(xgeru)(int *, int *, double *, double *, int *, double *, int *, double *, int *); -void BLASFUNC(xgerc)(int *, int *, double *, double *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(sger)(int *, int *, float *, float *, int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dger)(int *, int *, double *, double *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qger)(int *, int *, double *, double *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(cgeru)(int *, int *, float *, float *, int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(cgerc)(int *, int *, float *, float *, int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zgeru)(int *, int *, double *, double *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(zgerc)(int *, int *, double *, double *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xgeru)(int *, int *, double *, double *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xgerc)(int *, int *, double *, double *, int *, double *, int *, double *, int *); -void BLASFUNC(sgemv)(const char *, const int *, const int *, const float *, const float *, const int *, const float *, - const int *, const float *, float *, const int *); -void BLASFUNC(dgemv)(const char *, const int *, const int *, const double *, const double *, const int *, - const double *, const int *, const double *, double *, const int *); -void BLASFUNC(qgemv)(const char *, const int *, const int *, const double *, const double *, const int *, - const double *, const int *, const double *, double *, const int *); -void BLASFUNC(cgemv)(const char *, const int *, const int *, const float *, const float *, const int *, const float *, - const int *, const float *, float *, const int *); -void BLASFUNC(zgemv)(const char *, const int *, const int *, const double *, const double *, const int *, - const double *, const int *, const double *, double *, const int *); -void BLASFUNC(xgemv)(const char *, const int *, const int *, const double *, const double *, const int *, - const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(sgemv)(const char *, const int *, const int *, const float *, const float *, const int *, + const float *, const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dgemv)(const char *, const int *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qgemv)(const char *, const int *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(cgemv)(const char *, const int *, const int *, const float *, const float *, const int *, + const float *, const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zgemv)(const char *, const int *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xgemv)(const char *, const int *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); -void BLASFUNC(strsv)(const char *, const char *, const char *, const int *, const float *, const int *, float *, - const int *); -void BLASFUNC(dtrsv)(const char *, const char *, const char *, const int *, const double *, const int *, double *, - const int *); -void BLASFUNC(qtrsv)(const char *, const char *, const char *, const int *, const double *, const int *, double *, - const int *); -void BLASFUNC(ctrsv)(const char *, const char *, const char *, const int *, const float *, const int *, float *, - const int *); -void BLASFUNC(ztrsv)(const char *, const char *, const char *, const int *, const double *, const int *, double *, - const int *); -void BLASFUNC(xtrsv)(const char *, const char *, const char *, const int *, const double *, const int *, double *, - const int *); +EIGEN_BLAS_API void BLASFUNC(strsv)(const char *, const char *, const char *, const int *, const float *, const int *, + float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dtrsv)(const char *, const char *, const char *, const int *, const double *, const int *, + double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qtrsv)(const char *, const char *, const char *, const int *, const double *, const int *, + double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ctrsv)(const char *, const char *, const char *, const int *, const float *, const int *, + float *, const int *); +EIGEN_BLAS_API void BLASFUNC(ztrsv)(const char *, const char *, const char *, const int *, const double *, const int *, + double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xtrsv)(const char *, const char *, const char *, const int *, const double *, const int *, + double *, const int *); -void BLASFUNC(stpsv)(char *, char *, char *, int *, float *, float *, int *); -void BLASFUNC(dtpsv)(char *, char *, char *, int *, double *, double *, int *); -void BLASFUNC(qtpsv)(char *, char *, char *, int *, double *, double *, int *); -void BLASFUNC(ctpsv)(char *, char *, char *, int *, float *, float *, int *); -void BLASFUNC(ztpsv)(char *, char *, char *, int *, double *, double *, int *); -void BLASFUNC(xtpsv)(char *, char *, char *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(stpsv)(char *, char *, char *, int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dtpsv)(char *, char *, char *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qtpsv)(char *, char *, char *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(ctpsv)(char *, char *, char *, int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(ztpsv)(char *, char *, char *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xtpsv)(char *, char *, char *, int *, double *, double *, int *); -void BLASFUNC(strmv)(const char *, const char *, const char *, const int *, const float *, const int *, float *, - const int *); -void BLASFUNC(dtrmv)(const char *, const char *, const char *, const int *, const double *, const int *, double *, - const int *); -void BLASFUNC(qtrmv)(const char *, const char *, const char *, const int *, const double *, const int *, double *, - const int *); -void BLASFUNC(ctrmv)(const char *, const char *, const char *, const int *, const float *, const int *, float *, - const int *); -void BLASFUNC(ztrmv)(const char *, const char *, const char *, const int *, const double *, const int *, double *, - const int *); -void BLASFUNC(xtrmv)(const char *, const char *, const char *, const int *, const double *, const int *, double *, - const int *); +EIGEN_BLAS_API void BLASFUNC(strmv)(const char *, const char *, const char *, const int *, const float *, const int *, + float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dtrmv)(const char *, const char *, const char *, const int *, const double *, const int *, + double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qtrmv)(const char *, const char *, const char *, const int *, const double *, const int *, + double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ctrmv)(const char *, const char *, const char *, const int *, const float *, const int *, + float *, const int *); +EIGEN_BLAS_API void BLASFUNC(ztrmv)(const char *, const char *, const char *, const int *, const double *, const int *, + double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xtrmv)(const char *, const char *, const char *, const int *, const double *, const int *, + double *, const int *); -void BLASFUNC(stpmv)(char *, char *, char *, int *, float *, float *, int *); -void BLASFUNC(dtpmv)(char *, char *, char *, int *, double *, double *, int *); -void BLASFUNC(qtpmv)(char *, char *, char *, int *, double *, double *, int *); -void BLASFUNC(ctpmv)(char *, char *, char *, int *, float *, float *, int *); -void BLASFUNC(ztpmv)(char *, char *, char *, int *, double *, double *, int *); -void BLASFUNC(xtpmv)(char *, char *, char *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(stpmv)(char *, char *, char *, int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dtpmv)(char *, char *, char *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qtpmv)(char *, char *, char *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(ctpmv)(char *, char *, char *, int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(ztpmv)(char *, char *, char *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xtpmv)(char *, char *, char *, int *, double *, double *, int *); -void BLASFUNC(stbmv)(char *, char *, char *, int *, int *, float *, int *, float *, int *); -void BLASFUNC(dtbmv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); -void BLASFUNC(qtbmv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); -void BLASFUNC(ctbmv)(char *, char *, char *, int *, int *, float *, int *, float *, int *); -void BLASFUNC(ztbmv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); -void BLASFUNC(xtbmv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(stbmv)(char *, char *, char *, int *, int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dtbmv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qtbmv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(ctbmv)(char *, char *, char *, int *, int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(ztbmv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xtbmv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); -void BLASFUNC(stbsv)(char *, char *, char *, int *, int *, float *, int *, float *, int *); -void BLASFUNC(dtbsv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); -void BLASFUNC(qtbsv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); -void BLASFUNC(ctbsv)(char *, char *, char *, int *, int *, float *, int *, float *, int *); -void BLASFUNC(ztbsv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); -void BLASFUNC(xtbsv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(stbsv)(char *, char *, char *, int *, int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dtbsv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qtbsv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(ctbsv)(char *, char *, char *, int *, int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(ztbsv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xtbsv)(char *, char *, char *, int *, int *, double *, int *, double *, int *); -void BLASFUNC(ssymv)(const char *, const int *, const float *, const float *, const int *, const float *, const int *, - const float *, float *, const int *); -void BLASFUNC(dsymv)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, const double *, double *, const int *); -void BLASFUNC(qsymv)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ssymv)(const char *, const int *, const float *, const float *, const int *, const float *, + const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dsymv)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qsymv)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); -void BLASFUNC(sspmv)(char *, int *, float *, float *, float *, int *, float *, float *, int *); -void BLASFUNC(dspmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); -void BLASFUNC(qspmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(sspmv)(char *, int *, float *, float *, float *, int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dspmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qspmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); -void BLASFUNC(ssyr)(const char *, const int *, const float *, const float *, const int *, float *, const int *); -void BLASFUNC(dsyr)(const char *, const int *, const double *, const double *, const int *, double *, const int *); -void BLASFUNC(qsyr)(const char *, const int *, const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ssyr)(const char *, const int *, const float *, const float *, const int *, float *, + const int *); +EIGEN_BLAS_API void BLASFUNC(dsyr)(const char *, const int *, const double *, const double *, const int *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(qsyr)(const char *, const int *, const double *, const double *, const int *, double *, + const int *); -void BLASFUNC(ssyr2)(const char *, const int *, const float *, const float *, const int *, const float *, const int *, - float *, const int *); -void BLASFUNC(dsyr2)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, double *, const int *); -void BLASFUNC(qsyr2)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, double *, const int *); -void BLASFUNC(csyr2)(const char *, const int *, const float *, const float *, const int *, const float *, const int *, - float *, const int *); -void BLASFUNC(zsyr2)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, double *, const int *); -void BLASFUNC(xsyr2)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ssyr2)(const char *, const int *, const float *, const float *, const int *, const float *, + const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dsyr2)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qsyr2)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(csyr2)(const char *, const int *, const float *, const float *, const int *, const float *, + const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zsyr2)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xsyr2)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, double *, const int *); -void BLASFUNC(sspr)(char *, int *, float *, float *, int *, float *); -void BLASFUNC(dspr)(char *, int *, double *, double *, int *, double *); -void BLASFUNC(qspr)(char *, int *, double *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(sspr)(char *, int *, float *, float *, int *, float *); +EIGEN_BLAS_API void BLASFUNC(dspr)(char *, int *, double *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(qspr)(char *, int *, double *, double *, int *, double *); -void BLASFUNC(sspr2)(char *, int *, float *, float *, int *, float *, int *, float *); -void BLASFUNC(dspr2)(char *, int *, double *, double *, int *, double *, int *, double *); -void BLASFUNC(qspr2)(char *, int *, double *, double *, int *, double *, int *, double *); -void BLASFUNC(cspr2)(char *, int *, float *, float *, int *, float *, int *, float *); -void BLASFUNC(zspr2)(char *, int *, double *, double *, int *, double *, int *, double *); -void BLASFUNC(xspr2)(char *, int *, double *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(sspr2)(char *, int *, float *, float *, int *, float *, int *, float *); +EIGEN_BLAS_API void BLASFUNC(dspr2)(char *, int *, double *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(qspr2)(char *, int *, double *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(cspr2)(char *, int *, float *, float *, int *, float *, int *, float *); +EIGEN_BLAS_API void BLASFUNC(zspr2)(char *, int *, double *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(xspr2)(char *, int *, double *, double *, int *, double *, int *, double *); -void BLASFUNC(cher)(char *, int *, float *, float *, int *, float *, int *); -void BLASFUNC(zher)(char *, int *, double *, double *, int *, double *, int *); -void BLASFUNC(xher)(char *, int *, double *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(cher)(char *, int *, float *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zher)(char *, int *, double *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xher)(char *, int *, double *, double *, int *, double *, int *); -void BLASFUNC(chpr)(char *, int *, float *, float *, int *, float *); -void BLASFUNC(zhpr)(char *, int *, double *, double *, int *, double *); -void BLASFUNC(xhpr)(char *, int *, double *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(chpr)(char *, int *, float *, float *, int *, float *); +EIGEN_BLAS_API void BLASFUNC(zhpr)(char *, int *, double *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(xhpr)(char *, int *, double *, double *, int *, double *); -void BLASFUNC(cher2)(char *, int *, float *, float *, int *, float *, int *, float *, int *); -void BLASFUNC(zher2)(char *, int *, double *, double *, int *, double *, int *, double *, int *); -void BLASFUNC(xher2)(char *, int *, double *, double *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(cher2)(char *, int *, float *, float *, int *, float *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zher2)(char *, int *, double *, double *, int *, double *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xher2)(char *, int *, double *, double *, int *, double *, int *, double *, int *); -void BLASFUNC(chpr2)(char *, int *, float *, float *, int *, float *, int *, float *); -void BLASFUNC(zhpr2)(char *, int *, double *, double *, int *, double *, int *, double *); -void BLASFUNC(xhpr2)(char *, int *, double *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(chpr2)(char *, int *, float *, float *, int *, float *, int *, float *); +EIGEN_BLAS_API void BLASFUNC(zhpr2)(char *, int *, double *, double *, int *, double *, int *, double *); +EIGEN_BLAS_API void BLASFUNC(xhpr2)(char *, int *, double *, double *, int *, double *, int *, double *); -void BLASFUNC(chemv)(const char *, const int *, const float *, const float *, const int *, const float *, const int *, - const float *, float *, const int *); -void BLASFUNC(zhemv)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, const double *, double *, const int *); -void BLASFUNC(xhemv)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(chemv)(const char *, const int *, const float *, const float *, const int *, const float *, + const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zhemv)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xhemv)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); -void BLASFUNC(chpmv)(char *, int *, float *, float *, float *, int *, float *, float *, int *); -void BLASFUNC(zhpmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); -void BLASFUNC(xhpmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(chpmv)(char *, int *, float *, float *, float *, int *, float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zhpmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xhpmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); -void BLASFUNC(snorm)(char *, int *, int *, float *, int *); -void BLASFUNC(dnorm)(char *, int *, int *, double *, int *); -void BLASFUNC(cnorm)(char *, int *, int *, float *, int *); -void BLASFUNC(znorm)(char *, int *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(snorm)(char *, int *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dnorm)(char *, int *, int *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(cnorm)(char *, int *, int *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(znorm)(char *, int *, int *, double *, int *); -void BLASFUNC(sgbmv)(char *, int *, int *, int *, int *, float *, float *, int *, float *, int *, float *, float *, - int *); -void BLASFUNC(dgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, - int *); -void BLASFUNC(qgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, - int *); -void BLASFUNC(cgbmv)(char *, int *, int *, int *, int *, float *, float *, int *, float *, int *, float *, float *, - int *); -void BLASFUNC(zgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, - int *); -void BLASFUNC(xgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, - int *); +EIGEN_BLAS_API void BLASFUNC(sgbmv)(char *, int *, int *, int *, int *, float *, float *, int *, float *, int *, + float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(qgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(cgbmv)(char *, int *, int *, int *, int *, float *, float *, int *, float *, int *, + float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); -void BLASFUNC(ssbmv)(char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, int *); -void BLASFUNC(dsbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); -void BLASFUNC(qsbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); -void BLASFUNC(csbmv)(char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, int *); -void BLASFUNC(zsbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); -void BLASFUNC(xsbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(ssbmv)(char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, + int *); +EIGEN_BLAS_API void BLASFUNC(dsbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, + double *, int *); +EIGEN_BLAS_API void BLASFUNC(qsbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, + double *, int *); +EIGEN_BLAS_API void BLASFUNC(csbmv)(char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, + int *); +EIGEN_BLAS_API void BLASFUNC(zsbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, + double *, int *); +EIGEN_BLAS_API void BLASFUNC(xsbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, + double *, int *); -void BLASFUNC(chbmv)(char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, int *); -void BLASFUNC(zhbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); -void BLASFUNC(xhbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(chbmv)(char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, + int *); +EIGEN_BLAS_API void BLASFUNC(zhbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, + double *, int *); +EIGEN_BLAS_API void BLASFUNC(xhbmv)(char *, int *, int *, double *, double *, int *, double *, int *, double *, + double *, int *); /* Level 3 routines */ -void BLASFUNC(sgemm)(const char *, const char *, const int *, const int *, const int *, const float *, const float *, - const int *, const float *, const int *, const float *, float *, const int *); -void BLASFUNC(dgemm)(const char *, const char *, const int *, const int *, const int *, const double *, const double *, - const int *, const double *, const int *, const double *, double *, const int *); -void BLASFUNC(qgemm)(const char *, const char *, const int *, const int *, const int *, const double *, const double *, - const int *, const double *, const int *, const double *, double *, const int *); -void BLASFUNC(cgemm)(const char *, const char *, const int *, const int *, const int *, const float *, const float *, - const int *, const float *, const int *, const float *, float *, const int *); -void BLASFUNC(zgemm)(const char *, const char *, const int *, const int *, const int *, const double *, const double *, - const int *, const double *, const int *, const double *, double *, const int *); -void BLASFUNC(xgemm)(const char *, const char *, const int *, const int *, const int *, const double *, const double *, - const int *, const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(sgemm)(const char *, const char *, const int *, const int *, const int *, const float *, + const float *, const int *, const float *, const int *, const float *, float *, + const int *); +EIGEN_BLAS_API void BLASFUNC(dgemm)(const char *, const char *, const int *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(qgemm)(const char *, const char *, const int *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(cgemm)(const char *, const char *, const int *, const int *, const int *, const float *, + const float *, const int *, const float *, const int *, const float *, float *, + const int *); +EIGEN_BLAS_API void BLASFUNC(zgemm)(const char *, const char *, const int *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(xgemm)(const char *, const char *, const int *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); -void BLASFUNC(cgemm3m)(char *, char *, int *, int *, int *, float *, float *, int *, float *, int *, float *, float *, - int *); -void BLASFUNC(zgemm3m)(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, - double *, int *); -void BLASFUNC(xgemm3m)(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, - double *, int *); +EIGEN_BLAS_API void BLASFUNC(cgemm3m)(char *, char *, int *, int *, int *, float *, float *, int *, float *, int *, + float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zgemm3m)(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xgemm3m)(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); -void BLASFUNC(sge2mm)(char *, char *, char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, - int *); -void BLASFUNC(dge2mm)(char *, char *, char *, int *, int *, double *, double *, int *, double *, int *, double *, - double *, int *); -void BLASFUNC(cge2mm)(char *, char *, char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, - int *); -void BLASFUNC(zge2mm)(char *, char *, char *, int *, int *, double *, double *, int *, double *, int *, double *, - double *, int *); +EIGEN_BLAS_API void BLASFUNC(sge2mm)(char *, char *, char *, int *, int *, float *, float *, int *, float *, int *, + float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(dge2mm)(char *, char *, char *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(cge2mm)(char *, char *, char *, int *, int *, float *, float *, int *, float *, int *, + float *, float *, int *); +EIGEN_BLAS_API void BLASFUNC(zge2mm)(char *, char *, char *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); -void BLASFUNC(strsm)(const char *, const char *, const char *, const char *, const int *, const int *, const float *, - const float *, const int *, float *, const int *); -void BLASFUNC(dtrsm)(const char *, const char *, const char *, const char *, const int *, const int *, const double *, - const double *, const int *, double *, const int *); -void BLASFUNC(qtrsm)(const char *, const char *, const char *, const char *, const int *, const int *, const double *, - const double *, const int *, double *, const int *); -void BLASFUNC(ctrsm)(const char *, const char *, const char *, const char *, const int *, const int *, const float *, - const float *, const int *, float *, const int *); -void BLASFUNC(ztrsm)(const char *, const char *, const char *, const char *, const int *, const int *, const double *, - const double *, const int *, double *, const int *); -void BLASFUNC(xtrsm)(const char *, const char *, const char *, const char *, const int *, const int *, const double *, - const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(strsm)(const char *, const char *, const char *, const char *, const int *, const int *, + const float *, const float *, const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dtrsm)(const char *, const char *, const char *, const char *, const int *, const int *, + const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qtrsm)(const char *, const char *, const char *, const char *, const int *, const int *, + const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ctrsm)(const char *, const char *, const char *, const char *, const int *, const int *, + const float *, const float *, const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(ztrsm)(const char *, const char *, const char *, const char *, const int *, const int *, + const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xtrsm)(const char *, const char *, const char *, const char *, const int *, const int *, + const double *, const double *, const int *, double *, const int *); -void BLASFUNC(strmm)(const char *, const char *, const char *, const char *, const int *, const int *, const float *, - const float *, const int *, float *, const int *); -void BLASFUNC(dtrmm)(const char *, const char *, const char *, const char *, const int *, const int *, const double *, - const double *, const int *, double *, const int *); -void BLASFUNC(qtrmm)(const char *, const char *, const char *, const char *, const int *, const int *, const double *, - const double *, const int *, double *, const int *); -void BLASFUNC(ctrmm)(const char *, const char *, const char *, const char *, const int *, const int *, const float *, - const float *, const int *, float *, const int *); -void BLASFUNC(ztrmm)(const char *, const char *, const char *, const char *, const int *, const int *, const double *, - const double *, const int *, double *, const int *); -void BLASFUNC(xtrmm)(const char *, const char *, const char *, const char *, const int *, const int *, const double *, - const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(strmm)(const char *, const char *, const char *, const char *, const int *, const int *, + const float *, const float *, const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dtrmm)(const char *, const char *, const char *, const char *, const int *, const int *, + const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qtrmm)(const char *, const char *, const char *, const char *, const int *, const int *, + const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ctrmm)(const char *, const char *, const char *, const char *, const int *, const int *, + const float *, const float *, const int *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(ztrmm)(const char *, const char *, const char *, const char *, const int *, const int *, + const double *, const double *, const int *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xtrmm)(const char *, const char *, const char *, const char *, const int *, const int *, + const double *, const double *, const int *, double *, const int *); -void BLASFUNC(ssymm)(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(dsymm)(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(qsymm)(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(csymm)(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(zsymm)(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(xsymm)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ssymm)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dsymm)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(qsymm)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(csymm)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zsymm)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(xsymm)(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(csymm3m)(char *, char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, int *); -void BLASFUNC(zsymm3m)(char *, char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, - int *); -void BLASFUNC(xsymm3m)(char *, char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, - int *); +EIGEN_BLAS_API void BLASFUNC(csymm3m)(char *, char *, int *, int *, float *, float *, int *, float *, int *, float *, + float *, int *); +EIGEN_BLAS_API void BLASFUNC(zsymm3m)(char *, char *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xsymm3m)(char *, char *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); -void BLASFUNC(ssyrk)(const char *, const char *, const int *, const int *, const float *, const float *, const int *, - const float *, float *, const int *); -void BLASFUNC(dsyrk)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, double *, const int *); -void BLASFUNC(qsyrk)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, double *, const int *); -void BLASFUNC(csyrk)(const char *, const char *, const int *, const int *, const float *, const float *, const int *, - const float *, float *, const int *); -void BLASFUNC(zsyrk)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, double *, const int *); -void BLASFUNC(xsyrk)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ssyrk)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dsyrk)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(qsyrk)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(csyrk)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zsyrk)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xsyrk)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, double *, const int *); -void BLASFUNC(ssyr2k)(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(dsyr2k)(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(qsyr2k)(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(csyr2k)(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(zsyr2k)(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(xsyr2k)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(ssyr2k)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(dsyr2k)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(qsyr2k)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(csyr2k)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zsyr2k)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(xsyr2k)(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(chemm)(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(zhemm)(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(xhemm)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(chemm)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zhemm)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(xhemm)(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(chemm3m)(char *, char *, int *, int *, float *, float *, int *, float *, int *, float *, float *, int *); -void BLASFUNC(zhemm3m)(char *, char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, - int *); -void BLASFUNC(xhemm3m)(char *, char *, int *, int *, double *, double *, int *, double *, int *, double *, double *, - int *); +EIGEN_BLAS_API void BLASFUNC(chemm3m)(char *, char *, int *, int *, float *, float *, int *, float *, int *, float *, + float *, int *); +EIGEN_BLAS_API void BLASFUNC(zhemm3m)(char *, char *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); +EIGEN_BLAS_API void BLASFUNC(xhemm3m)(char *, char *, int *, int *, double *, double *, int *, double *, int *, + double *, double *, int *); -void BLASFUNC(cherk)(const char *, const char *, const int *, const int *, const float *, const float *, const int *, - const float *, float *, const int *); -void BLASFUNC(zherk)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, double *, const int *); -void BLASFUNC(xherk)(const char *, const char *, const int *, const int *, const double *, const double *, const int *, - const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(cherk)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zherk)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, double *, const int *); +EIGEN_BLAS_API void BLASFUNC(xherk)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, double *, const int *); -void BLASFUNC(cher2k)(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(zher2k)(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(xher2k)(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(cher2m)(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(zher2m)(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(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 *); +EIGEN_BLAS_API void BLASFUNC(cher2k)(const char *, const char *, const int *, const int *, const float *, const float *, + const int *, const float *, const int *, const float *, float *, const int *); +EIGEN_BLAS_API void BLASFUNC(zher2k)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(xher2k)(const char *, const char *, const int *, const int *, const double *, + const double *, const int *, const double *, const int *, const double *, double *, + const int *); +EIGEN_BLAS_API void BLASFUNC(cher2m)(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 *); +EIGEN_BLAS_API void BLASFUNC(zher2m)(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 *); +EIGEN_BLAS_API 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 *); +EIGEN_BLAS_API 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 *); +EIGEN_BLAS_API 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 *); +EIGEN_BLAS_API 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 *); +EIGEN_BLAS_API 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 *); +EIGEN_BLAS_API 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 *); +EIGEN_BLAS_API 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 } diff --git a/blas/eigen_blas.def b/blas/eigen_blas.def new file mode 100644 index 000000000..fb18d44a0 --- /dev/null +++ b/blas/eigen_blas.def @@ -0,0 +1,222 @@ +; Definition file for eigen_blas.dll. + +LIBRARY eigen_blas +EXPORTS + ; Utilities + lsame_ + xerbla_ + + ; Level 1 + saxpy_ + daxpy_ + caxpy_ + zaxpy_ + ; caxpyc_ + ; zaxpyc_ + scopy_ + dcopy_ + ccopy_ + zcopy_ + sdot_ + sdsdot_ + dsdot_ + ddot_ + cdotc_ + zdotc_ + cdotu_ + zdotu_ + cdotcw_ + zdotcw_ + cdotuw_ + zdotuw_ + snrm2_ + dnrm2_ + scnrm2_ + dznrm2_ + srot_ + drot_ + csrot_ + zdrot_ + srotg_ + drotg_ + crotg_ + zrotg_ + srotm_ + drotm_ + srotmg_ + drotmg_ + sscal_ + dscal_ + cscal_ + zscal_ + csscal_ + zdscal_ + sswap_ + dswap_ + cswap_ + zswap_ + sasum_ + scasum_ + dasum_ + dzasum_ + ; ismax_ + ; idmax_ + ; icmax_ + ; izmax_ + isamax_ + idamax_ + icamax_ + izamax_ + isamin_ + idamin_ + icamin_ + izamin_ + ; ismin_ + ; idmin_ + ; icmin_ + ; izmin_ + ; samax_ + ; damax_ + ; scamax_ + ; dzamax_ + ; samin_ + ; damin_ + ; scamin_ + ; dzamin_ + ; smax_ + ; dmax_ + ; cmax_ + ; zmax_ + ; smin_ + ; dmin_ + ; cmin_ + ; zmin_ + + + ; Level 2 + sgemv_ + dgemv_ + cgemv_ + zgemv_ + sger_ + dger_ + cgerc_ + zgerc_ + cgeru_ + zgeru_ + ssymv_ + dsymv_ + ssyr_ + dsyr_ + ssyr2_ + dsyr2_ + ; csyr2_ + ; zsyr2_ + strmv_ + dtrmv_ + ctrmv_ + ztrmv_ + strsv_ + dtrsv_ + ctrsv_ + ztrsv_ + stpsv_ + dtpsv_ + ctpsv_ + ztpsv_ + stpmv_ + dtpmv_ + ctpmv_ + ztpmv_ + stbmv_ + dtbmv_ + ctbmv_ + ztbmv_ + stbsv_ + dtbsv_ + ctbsv_ + ztbsv_ + sspmv_ + dspmv_ + sspr_ + dspr_ + ; cspr_ + ; zspr_ + sspr2_ + dspr2_ + ; cspr2_ + ; zspr2_ + cher_ + zher_ + chpr_ + zhpr_ + cher2_ + zher2_ + chpr2_ + zhpr2_ + chemv_ + zhemv_ + chpmv_ + zhpmv_ + ; snorm_ + ; dnorm_ + ; cnorm_ + ; znorm_ + sgbmv_ + dgbmv_ + cgbmv_ + zgbmv_ + ssbmv_ + dsbmv_ + ; csbmv_ + ; zsbmv_ + chbmv_ + zhbmv_ + + ; Level 3 BLAS + sgemm_ + dgemm_ + cgemm_ + zgemm_ + ; cgemm3m_ + ; zgemm3m_ + ; sge2mm_ + ; dge2mm_ + ; cge2mm_ + ; zge2mm_ + ssymm_ + dsymm_ + csymm_ + zsymm_ + ; csymm3m_ + ; zsymm3m_ + ssyrk_ + dsyrk_ + csyrk_ + zsyrk_ + ssyr2k_ + dsyr2k_ + csyr2k_ + zsyr2k_ + strmm_ + dtrmm_ + ctrmm_ + ztrmm_ + strsm_ + dtrsm_ + ctrsm_ + ztrsm_ + chemm_ + zhemm_ + ; chemm3m_ + ; zhemm3m_ + cherk_ + zherk_ + cher2k_ + zher2k_ + ; cher2m_ + ; zher2m_ + sgemmtr_ + dgemmtr_ + cgemmtr_ + zgemmtr_ diff --git a/blas/xerbla.cpp b/blas/xerbla.cpp index 0b59c4a35..94c8c1d99 100644 --- a/blas/xerbla.cpp +++ b/blas/xerbla.cpp @@ -1,6 +1,8 @@ #include +#include "blas.h" + #if (defined __GNUC__) && (!defined __MINGW32__) && (!defined __CYGWIN__) #define EIGEN_WEAK_LINKING __attribute__((weak)) #else diff --git a/ci/build.linux.gitlab-ci.yml b/ci/build.linux.gitlab-ci.yml index 9dbb54fd1..44fff9362 100644 --- a/ci/build.linux.gitlab-ci.yml +++ b/ci/build.linux.gitlab-ci.yml @@ -176,6 +176,8 @@ 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 + cache: {} # Disable cache for ROCm, since it fails whenever the image updates. + ######## Arm ################################################################### diff --git a/ci/build.windows.gitlab-ci.yml b/ci/build.windows.gitlab-ci.yml index 87be69495..7cd4567e8 100644 --- a/ci/build.windows.gitlab-ci.yml +++ b/ci/build.windows.gitlab-ci.yml @@ -31,23 +31,20 @@ build:windows:x86:msvc-14.29:default: extends: .build:windows variables: - EIGEN_CI_MSVC_VER: "14.29" - EIGEN_CI_MSVC_ARCH: "x86" + EIGEN_CI_MSVC_ARCH: "x64_x86" # MSVC 14.29 (VS 2019) 64 bit build:windows:x86-64:msvc-14.29:default: extends: .build:windows - variables: - EIGEN_CI_MSVC_VER: "14.29" build:windows:x86-64:msvc-14.29:avx2: - extends: build:windows:x86-64:msvc-14.29:default + extends: .build:windows variables: EIGEN_CI_ADDITIONAL_ARGS: "-DEIGEN_TEST_AVX2=on" build:windows:x86-64:msvc-14.29:avx512dq: - extends: build:windows:x86-64:msvc-14.29:default + extends: .build:windows variables: EIGEN_CI_ADDITIONAL_ARGS: "-DEIGEN_TEST_AVX512DQ=on" @@ -73,5 +70,4 @@ build:windows:x86-64:msvc-14.29:avx512dq: build:windows:x86-64:cuda-11.4:msvc-14.29: extends: .build:windows:cuda variables: - EIGEN_CI_MSVC_VER: "14.29" EIGEN_CI_BEFORE_SCRIPT: $$env:CUDA_PATH=$$env:CUDA_PATH_V11_4 \ No newline at end of file diff --git a/ci/test.windows.gitlab-ci.yml b/ci/test.windows.gitlab-ci.yml index 17bb065de..3c398a4ec 100644 --- a/ci/test.windows.gitlab-ci.yml +++ b/ci/test.windows.gitlab-ci.yml @@ -19,35 +19,29 @@ # MSVC 14.29 (VS 2019) 64 bit -.test:windows:x86-64:msvc-14.29:default: +test:windows:x86-64:msvc-14.29:default:official: extends: .test:windows needs: [ build:windows:x86-64:msvc-14.29:default ] - -test:windows:x86-64:msvc-14.29:default:official: - extends: .test:windows:x86-64:msvc-14.29:default variables: EIGEN_CI_CTEST_LABEL: Official test:windows:x86-64:msvc-14.29:default:unsupported: - extends: .test:windows:x86-64:msvc-14.29:default + extends: test:windows:x86-64:msvc-14.29:default:official variables: EIGEN_CI_CTEST_LABEL: Unsupported -.test:windows:x86-64:msvc-14.29:avx2: +test:windows:x86-64:msvc-14.29:avx2:official: extends: .test:windows needs: [ build:windows:x86-64:msvc-14.29:avx2 ] - -test:windows:x86-64:msvc-14.29:avx2:official: - extends: .test:windows:x86-64:msvc-14.29:avx2 variables: EIGEN_CI_CTEST_LABEL: Official test:windows:x86-64:msvc-14.29:avx2:unsupported: - extends: .test:windows:x86-64:msvc-14.29:avx2 + extends: test:windows:x86-64:msvc-14.29:avx2:official variables: EIGEN_CI_CTEST_LABEL: Unsupported -.test:windows:x86-64:msvc-14.29:avx512dq: +test:windows:x86-64:msvc-14.29:avx512dq:official: extends: .test:windows needs: [ build:windows:x86-64:msvc-14.29:avx512dq ] tags: @@ -55,14 +49,11 @@ test:windows:x86-64:msvc-14.29:avx2:unsupported: - windows - x86-64 - avx512 - -test:windows:x86-64:msvc-14.29:avx512dq:official: - extends: .test:windows:x86-64:msvc-14.29:avx512dq variables: EIGEN_CI_CTEST_LABEL: Official test:windows:x86-64:msvc-14.29:avx512dq:unsupported: - extends: .test:windows:x86-64:msvc-14.29:avx512dq + extends: test:windows:x86-64:msvc-14.29:avx512dq:official variables: EIGEN_CI_CTEST_LABEL: Unsupported diff --git a/doc/PreprocessorDirectives.dox b/doc/PreprocessorDirectives.dox index 27ae531f6..f4af90744 100644 --- a/doc/PreprocessorDirectives.dox +++ b/doc/PreprocessorDirectives.dox @@ -18,9 +18,6 @@ one option, and other parts (or libraries that you use) are compiled with anothe fail to link or exhibit subtle bugs. Nevertheless, these options can be useful for people who know what they are doing. - - \b EIGEN2_SUPPORT and \b EIGEN2_SUPPORT_STAGEnn_xxx are disabled starting from the 3.3 release. - Defining one of these will raise a compile-error. If you need to compile Eigen2 code, - check this site. - \b EIGEN_DEFAULT_DENSE_INDEX_TYPE - the type for column and row indices in matrices, vectors and array (DenseBase::Index). Set to \c std::ptrdiff_t by default. - \b EIGEN_DEFAULT_IO_FORMAT - the IOFormat to use when printing a matrix if no %IOFormat is specified. @@ -44,7 +41,7 @@ are doing. preferable. Not defined by default. \warning See the documentation of \c EIGEN_INITIALIZE_MATRICES_BY_ZERO for a discussion on a limitations of these macros when applied to \c 1x1, \c 1x2, and \c 2x1 fixed-size matrices. - - \b EIGEN_NO_AUTOMATIC_RESIZING - if defined, the matrices (or arrays) on both sides of an assignment + - \b EIGEN_NO_AUTOMATIC_RESIZING - if defined, the matrices (or arrays) on both sides of an assignment a = b have to be of the same size; otherwise, %Eigen automatically resizes \c a so that it is of the correct size. Not defined by default. @@ -72,8 +69,8 @@ The %Eigen library contains many assertions to guard against programming errors, run time. However, these assertions do cost time and can thus be turned off. - \b EIGEN_NO_DEBUG - disables %Eigen's assertions if defined. Not defined by default, unless the - \c NDEBUG macro is defined (this is a standard C++ macro which disables all asserts). - - \b EIGEN_NO_STATIC_ASSERT - if defined, compile-time static assertions are replaced by runtime assertions; + \c NDEBUG macro is defined (this is a standard C++ macro which disables all asserts). + - \b EIGEN_NO_STATIC_ASSERT - if defined, compile-time static assertions are replaced by runtime assertions; this saves compilation time. Not defined by default. - \b eigen_assert - macro with one argument that is used inside %Eigen for assertions. By default, it is basically defined to be \c assert, which aborts the program if the assertion is violated. Redefine this @@ -90,7 +87,7 @@ run time. However, these assertions do cost time and can thus be turned off. Let us emphasize that \c EIGEN_MAX_*_ALIGN_BYTES define only a desirable upper bound. In practice data is aligned to largest power-of-two common divisor of \c EIGEN_MAX_STATIC_ALIGN_BYTES and the size of the data, such that memory is not wasted. - \b \c EIGEN_DONT_PARALLELIZE - if defined, this disables multi-threading. This is only relevant if you enabled OpenMP. See \ref TopicMultiThreading for details. - - \b \c EIGEN_DONT_VECTORIZE - disables explicit vectorization when defined. Not defined by default, unless + - \b \c EIGEN_DONT_VECTORIZE - disables explicit vectorization when defined. Not defined by default, unless alignment is disabled by %Eigen's platform test or the user defining \c EIGEN_DONT_ALIGN. - \b \c EIGEN_UNALIGNED_VECTORIZE - disables/enables vectorization with unaligned stores. Default is 1 (enabled). If set to 0 (disabled), then expression for which the destination cannot be aligned are not vectorized (e.g., unaligned diff --git a/lapack/CMakeLists.txt b/lapack/CMakeLists.txt index b0b5570e2..d837fff96 100644 --- a/lapack/CMakeLists.txt +++ b/lapack/CMakeLists.txt @@ -22,9 +22,11 @@ add_custom_target(lapack) include_directories(../blas) set(EigenLapack_SRCS - dsecnd_INT_CPU_TIME.cpp second_INT_CPU_TIME.cpp single.cpp double.cpp complex_single.cpp complex_double.cpp ../blas/xerbla.cpp + dsecnd_INT_CPU_TIME.cpp second_INT_CPU_TIME.cpp single.cpp double.cpp complex_single.cpp complex_double.cpp ) +set(EIGEN_LAPACK_DEF "eigen_lapack_cpp.def") + if(EIGEN_Fortran_COMPILER_WORKS) set(EigenLapack_SRCS ${EigenLapack_SRCS} @@ -40,6 +42,8 @@ set(EigenLapack_SRCS ${EigenLapack_SRCS} slamch.f dlamch.f ) +set(EIGEN_LAPACK_DEF "eigen_lapack.def") + option(EIGEN_ENABLE_LAPACK_TESTS OFF "Enable the Lapack unit tests") if(EIGEN_ENABLE_LAPACK_TESTS) @@ -98,12 +102,16 @@ endif() set(EIGEN_LAPACK_TARGETS "") add_library(eigen_lapack_static STATIC ${EigenLapack_SRCS} ${ReferenceLapack_SRCS}) +target_link_libraries(eigen_lapack_static eigen_blas_static) list(APPEND EIGEN_LAPACK_TARGETS eigen_lapack_static) if (EIGEN_BUILD_SHARED_LIBS) - add_library(eigen_lapack SHARED ${EigenLapack_SRCS}) - list(APPEND EIGEN_LAPACK_TARGETS eigen_lapack) + add_library(eigen_lapack SHARED ${EigenLapack_SRCS} ${EIGEN_LAPACK_DEF}) + # Build LAPACK but link BLAS. + target_compile_definitions(eigen_lapack PUBLIC "EIGEN_BLAS_LINK_DLL" "EIGEN_LAPACK_BUILD_DLL") target_link_libraries(eigen_lapack eigen_blas) + set_target_properties(eigen_lapack PROPERTIES CXX_VISIBILITY_PRESET hidden) + list(APPEND EIGEN_LAPACK_TARGETS eigen_lapack) endif() foreach(target IN LISTS EIGEN_LAPACK_TARGETS) diff --git a/lapack/cholesky.inc b/lapack/cholesky.inc index a93a51152..695d3b847 100644 --- a/lapack/cholesky.inc +++ b/lapack/cholesky.inc @@ -11,7 +11,7 @@ #include // POTRF computes the Cholesky factorization of a real symmetric positive definite matrix A. -EIGEN_LAPACK_FUNC(potrf)(char *uplo, int *n, RealScalar *pa, int *lda, int *info) { +EIGEN_LAPACK_FUNC(potrf)(const char *uplo, int *n, RealScalar *pa, int *lda, int *info) { *info = 0; if (UPLO(*uplo) == INVALID) *info = -1; @@ -38,7 +38,8 @@ EIGEN_LAPACK_FUNC(potrf)(char *uplo, int *n, RealScalar *pa, int *lda, int *info // POTRS solves a system of linear equations A*X = B with a symmetric // positive definite matrix A using the Cholesky factorization // A = U**T*U or A = L*L**T computed by DPOTRF. -EIGEN_LAPACK_FUNC(potrs)(char *uplo, int *n, int *nrhs, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, int *info) { +EIGEN_LAPACK_FUNC(potrs) +(const char *uplo, int *n, int *nrhs, RealScalar *pa, int *lda, RealScalar *pb, int *ldb, int *info) { *info = 0; if (UPLO(*uplo) == INVALID) *info = -1; diff --git a/lapack/dsecnd_INT_CPU_TIME.cpp b/lapack/dsecnd_INT_CPU_TIME.cpp index 684fa1d78..7dfc5e288 100644 --- a/lapack/dsecnd_INT_CPU_TIME.cpp +++ b/lapack/dsecnd_INT_CPU_TIME.cpp @@ -15,6 +15,8 @@ #include #endif +#include "lapack.h" + extern "C" { double dsecnd_(); } diff --git a/lapack/eigen_lapack.def b/lapack/eigen_lapack.def new file mode 100644 index 000000000..4e882cd84 --- /dev/null +++ b/lapack/eigen_lapack.def @@ -0,0 +1,143 @@ +; Definition file for eigen_lapack.dll. + +LIBRARY eigen_lapack +EXPORTS + ; Eigen C/C++ implementations + ; Utilities + xerbla_ + + ; Eigenvalues + ssyev_ + dsyev_ + + ; LU + sgetrf_ + sgetrs_ + dgetrf_ + dgetrs_ + cgetrf_ + cgetrs_ + zgetrf_ + zgetrs_ + + ; QR + spotrf_ + spotrs_ + dpotrf_ + dpotrs_ + cpotrf_ + cpotrs_ + zpotrf_ + zpotrs_ + + ; SVD + sgesdd_ + sgesvd_ + dgesdd_ + dgesvd_ + cgesdd_ + cgesvd_ + zgesdd_ + zgesvd_ + + ; Time + second_ + dsecnd_ + + ; Fortran implementations + clacgv_ + zlacgv_ + sladiv_ + dladiv_ + cladiv_ + zladiv_ + slamch_ + dlamch_ + slamc3_ + dlamc3_ + slapy2_ + dlapy2_ + slapy3_ + dlapy3_ + slarf_ + dlarf_ + clarf_ + zlarf_ + slarfb_ + dlarfb_ + clarfb_ + zlarfb_ + slarfg_ + dlarfg_ + clarfg_ + zlarfg_ + slarft_ + dlarft_ + clarft_ + zlarft_ + ilaclc_ + ilaclr_ + iladlc_ + iladlr_ + ilaslc_ + ilaslr_ + ilazlc_ + ilazlr_ + + ; Missing + ; csymv_ + ; zsymv_ + ; cspmv_ + ; zspmv_ + ; csyr_ + ; zsyr_ + ; cspr_ + ; zspr_ + ; sgemt_ + ; dgemt_ + ; cgemt_ + ; zgemt_ + ; sgema_ + ; dgema_ + ; cgema_ + ; zgema_ + ; sgems_ + ; dgems_ + ; cgems_ + ; zgems_ + ; sgetf2_ + ; dgetf2_ + ; cgetf2_ + ; zgetf2_ + ; slaswp_ + ; dlaswp_ + ; claswp_ + ; zlaswp_ + ; sgesv_ + ; dgesv_ + ; cgesv_ + ; zgesv_ + ; spotf2_ + ; dpotf2_ + ; cpotf2_ + ; zpotf2_ + ; slauu2_ + ; dlauu2_ + ; clauu2_ + ; zlauu2_ + ; slauum_ + ; dlauum_ + ; clauum_ + ; zlauum_ + ; strti2_ + ; dtrti2_ + ; ctrti2_ + ; ztrti2_ + ; strtri_ + ; dtrtri_ + ; ctrtri_ + ; ztrtri_ + ; spotri_ + ; dpotri_ + ; cpotri_ + ; zpotri_ diff --git a/lapack/eigen_lapack_cpp.def b/lapack/eigen_lapack_cpp.def new file mode 100644 index 000000000..4df600b64 --- /dev/null +++ b/lapack/eigen_lapack_cpp.def @@ -0,0 +1,143 @@ +; Definition file for eigen_lapack.dll, containing only the C++ implementations. + +LIBRARY eigen_lapack +EXPORTS + ; Eigen C/C++ implementations + ; Utilities + xerbla_ + + ; Eigenvalues + ssyev_ + dsyev_ + + ; LU + sgetrf_ + sgetrs_ + dgetrf_ + dgetrs_ + cgetrf_ + cgetrs_ + zgetrf_ + zgetrs_ + + ; QR + spotrf_ + spotrs_ + dpotrf_ + dpotrs_ + cpotrf_ + cpotrs_ + zpotrf_ + zpotrs_ + + ; SVD + sgesdd_ + sgesvd_ + dgesdd_ + dgesvd_ + cgesdd_ + cgesvd_ + zgesdd_ + zgesvd_ + + ; Time + second_ + dsecnd_ + + ; Fortran implementations + ; clacgv_ + ; zlacgv_ + ; sladiv_ + ; dladiv_ + ; cladiv_ + ; zladiv_ + ; slamch_ + ; dlamch_ + ; slamc3_ + ; dlamc3_ + ; slapy2_ + ; dlapy2_ + ; slapy3_ + ; dlapy3_ + ; slarf_ + ; dlarf_ + ; clarf_ + ; zlarf_ + ; slarfb_ + ; dlarfb_ + ; clarfb_ + ; zlarfb_ + ; slarfg_ + ; dlarfg_ + ; clarfg_ + ; zlarfg_ + ; slarft_ + ; dlarft_ + ; clarft_ + ; zlarft_ + ; ilaclc_ + ; ilaclr_ + ; iladlc_ + ; iladlr_ + ; ilaslc_ + ; ilaslr_ + ; ilazlc_ + ; ilazlr_ + + ; Missing + ; csymv_ + ; zsymv_ + ; cspmv_ + ; zspmv_ + ; csyr_ + ; zsyr_ + ; cspr_ + ; zspr_ + ; sgemt_ + ; dgemt_ + ; cgemt_ + ; zgemt_ + ; sgema_ + ; dgema_ + ; cgema_ + ; zgema_ + ; sgems_ + ; dgems_ + ; cgems_ + ; zgems_ + ; sgetf2_ + ; dgetf2_ + ; cgetf2_ + ; zgetf2_ + ; slaswp_ + ; dlaswp_ + ; claswp_ + ; zlaswp_ + ; sgesv_ + ; dgesv_ + ; cgesv_ + ; zgesv_ + ; spotf2_ + ; dpotf2_ + ; cpotf2_ + ; zpotf2_ + ; slauu2_ + ; dlauu2_ + ; clauu2_ + ; zlauu2_ + ; slauum_ + ; dlauum_ + ; clauum_ + ; zlauum_ + ; strti2_ + ; dtrti2_ + ; ctrti2_ + ; ztrti2_ + ; strtri_ + ; dtrtri_ + ; ctrtri_ + ; ztrtri_ + ; spotri_ + ; dpotri_ + ; cpotri_ + ; zpotri_ diff --git a/lapack/eigenvalues.inc b/lapack/eigenvalues.inc index 211a7ff4e..c67c82562 100644 --- a/lapack/eigenvalues.inc +++ b/lapack/eigenvalues.inc @@ -12,7 +12,8 @@ // computes eigen values and vectors of a general N-by-N matrix A EIGEN_LAPACK_FUNC(syev) -(char* jobz, char* uplo, int* n, Scalar* a, int* lda, Scalar* w, Scalar* /*work*/, int* lwork, int* info) { +(const char* jobz, const char* uplo, int* n, RealScalar* ra, int* lda, RealScalar* rw, RealScalar* /*work*/, int* lwork, + int* info) { // TODO exploit the work buffer bool query_size = *lwork == -1; @@ -40,6 +41,9 @@ EIGEN_LAPACK_FUNC(syev) if (*n == 0) return; + Scalar* a = reinterpret_cast(ra); + Scalar* w = reinterpret_cast(rw); + PlainMatrixType mat(*n, *n); if (UPLO(*uplo) == UP) mat = matrix(a, *n, *n, *lda).adjoint(); diff --git a/lapack/lapack.h b/lapack/lapack.h index 88fdb9895..ad6485db6 100644 --- a/lapack/lapack.h +++ b/lapack/lapack.h @@ -3,131 +3,192 @@ #include "../blas/blas.h" +#if defined(_WIN32) +#if defined(EIGEN_LAPACK_BUILD_DLL) +#define EIGEN_LAPACK_API __declspec(dllexport) +#elif defined(EIGEN_LAPACK_LINK_DLL) +#define EIGEN_LAPACK_API __declspec(dllimport) +#else +#define EIGEN_LAPACK_API +#endif +#elif ((defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)) && defined(EIGEN_LAPACK_BUILD_DLL) +#define EIGEN_LAPACK_API __attribute__((visibility("default"))) +#else +#define EIGEN_LAPACK_API +#endif + #ifdef __cplusplus extern "C" { #endif -void BLASFUNC(csymv)(const char *, const int *, const float *, const float *, const int *, const float *, const int *, - const float *, float *, const int *); -void BLASFUNC(zsymv)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, const double *, double *, const int *); -void BLASFUNC(xsymv)(const char *, const int *, const double *, const double *, const int *, const double *, - const int *, const double *, double *, const int *); +EIGEN_LAPACK_API void BLASFUNC(csymv)(const char *, const int *, const float *, const float *, const int *, + const float *, const int *, const float *, float *, const int *); +EIGEN_LAPACK_API void BLASFUNC(zsymv)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); +EIGEN_LAPACK_API void BLASFUNC(xsymv)(const char *, const int *, const double *, const double *, const int *, + const double *, const int *, const double *, double *, const int *); -void BLASFUNC(cspmv)(char *, int *, float *, float *, float *, int *, float *, float *, int *); -void BLASFUNC(zspmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); -void BLASFUNC(xspmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); +EIGEN_LAPACK_API void BLASFUNC(cspmv)(char *, int *, float *, float *, float *, int *, float *, float *, int *); +EIGEN_LAPACK_API void BLASFUNC(zspmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); +EIGEN_LAPACK_API void BLASFUNC(xspmv)(char *, int *, double *, double *, double *, int *, double *, double *, int *); -void BLASFUNC(csyr)(char *, int *, float *, float *, int *, float *, int *); -void BLASFUNC(zsyr)(char *, int *, double *, double *, int *, double *, int *); -void BLASFUNC(xsyr)(char *, int *, double *, double *, int *, double *, int *); +EIGEN_LAPACK_API void BLASFUNC(csyr)(char *, int *, float *, float *, int *, float *, int *); +EIGEN_LAPACK_API void BLASFUNC(zsyr)(char *, int *, double *, double *, int *, double *, int *); +EIGEN_LAPACK_API void BLASFUNC(xsyr)(char *, int *, double *, double *, int *, double *, int *); -void BLASFUNC(cspr)(char *, int *, float *, float *, int *, float *); -void BLASFUNC(zspr)(char *, int *, double *, double *, int *, double *); -void BLASFUNC(xspr)(char *, int *, double *, double *, int *, double *); +EIGEN_LAPACK_API void BLASFUNC(cspr)(char *, int *, float *, float *, int *, float *); +EIGEN_LAPACK_API void BLASFUNC(zspr)(char *, int *, double *, double *, int *, double *); +EIGEN_LAPACK_API void BLASFUNC(xspr)(char *, int *, double *, double *, int *, double *); -void BLASFUNC(sgemt)(char *, int *, int *, float *, float *, int *, float *, int *); -void BLASFUNC(dgemt)(char *, int *, int *, double *, double *, int *, double *, int *); -void BLASFUNC(cgemt)(char *, int *, int *, float *, float *, int *, float *, int *); -void BLASFUNC(zgemt)(char *, int *, int *, double *, double *, int *, double *, int *); +EIGEN_LAPACK_API void BLASFUNC(sgemt)(char *, int *, int *, float *, float *, int *, float *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgemt)(char *, int *, int *, double *, double *, int *, double *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgemt)(char *, int *, int *, float *, float *, int *, float *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgemt)(char *, int *, int *, double *, double *, int *, double *, int *); -void BLASFUNC(sgema)(char *, char *, int *, int *, float *, float *, int *, float *, float *, int *, float *, int *); -void BLASFUNC(dgema)(char *, char *, int *, int *, double *, double *, int *, double *, double *, int *, double *, - int *); -void BLASFUNC(cgema)(char *, char *, int *, int *, float *, float *, int *, float *, float *, int *, float *, int *); -void BLASFUNC(zgema)(char *, char *, int *, int *, double *, double *, int *, double *, double *, int *, double *, - int *); +EIGEN_LAPACK_API void BLASFUNC(sgema)(char *, char *, int *, int *, float *, float *, int *, float *, float *, int *, + float *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgema)(char *, char *, int *, int *, double *, double *, int *, double *, double *, + int *, double *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgema)(char *, char *, int *, int *, float *, float *, int *, float *, float *, int *, + float *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgema)(char *, char *, int *, int *, double *, double *, int *, double *, double *, + int *, double *, int *); -void BLASFUNC(sgems)(char *, char *, int *, int *, float *, float *, int *, float *, float *, int *, float *, int *); -void BLASFUNC(dgems)(char *, char *, int *, int *, double *, double *, int *, double *, double *, int *, double *, - int *); -void BLASFUNC(cgems)(char *, char *, int *, int *, float *, float *, int *, float *, float *, int *, float *, int *); -void BLASFUNC(zgems)(char *, char *, int *, int *, double *, double *, int *, double *, double *, int *, double *, - int *); +EIGEN_LAPACK_API void BLASFUNC(sgems)(char *, char *, int *, int *, float *, float *, int *, float *, float *, int *, + float *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgems)(char *, char *, int *, int *, double *, double *, int *, double *, double *, + int *, double *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgems)(char *, char *, int *, int *, float *, float *, int *, float *, float *, int *, + float *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgems)(char *, char *, int *, int *, double *, double *, int *, double *, double *, + int *, double *, int *); -void BLASFUNC(sgetf2)(int *, int *, float *, int *, int *, int *); -void BLASFUNC(dgetf2)(int *, int *, double *, int *, int *, int *); -void BLASFUNC(qgetf2)(int *, int *, double *, int *, int *, int *); -void BLASFUNC(cgetf2)(int *, int *, float *, int *, int *, int *); -void BLASFUNC(zgetf2)(int *, int *, double *, int *, int *, int *); -void BLASFUNC(xgetf2)(int *, int *, double *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(sgetf2)(int *, int *, float *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgetf2)(int *, int *, double *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qgetf2)(int *, int *, double *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgetf2)(int *, int *, float *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgetf2)(int *, int *, double *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xgetf2)(int *, int *, double *, int *, int *, int *); -void BLASFUNC(sgetrf)(int *, int *, float *, int *, int *, int *); -void BLASFUNC(dgetrf)(int *, int *, double *, int *, int *, int *); -void BLASFUNC(qgetrf)(int *, int *, double *, int *, int *, int *); -void BLASFUNC(cgetrf)(int *, int *, float *, int *, int *, int *); -void BLASFUNC(zgetrf)(int *, int *, double *, int *, int *, int *); -void BLASFUNC(xgetrf)(int *, int *, double *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qgetrf)(int *, int *, double *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xgetrf)(int *, int *, double *, int *, int *, int *); -void BLASFUNC(slaswp)(int *, float *, int *, int *, int *, int *, int *); -void BLASFUNC(dlaswp)(int *, double *, int *, int *, int *, int *, int *); -void BLASFUNC(qlaswp)(int *, double *, int *, int *, int *, int *, int *); -void BLASFUNC(claswp)(int *, float *, int *, int *, int *, int *, int *); -void BLASFUNC(zlaswp)(int *, double *, int *, int *, int *, int *, int *); -void BLASFUNC(xlaswp)(int *, double *, int *, int *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(slaswp)(int *, float *, int *, int *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dlaswp)(int *, double *, int *, int *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qlaswp)(int *, double *, int *, int *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(claswp)(int *, float *, int *, int *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zlaswp)(int *, double *, int *, int *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xlaswp)(int *, double *, int *, int *, int *, int *, int *); -void BLASFUNC(sgetrs)(char *, int *, int *, float *, int *, int *, float *, int *, int *); -void BLASFUNC(dgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); -void BLASFUNC(qgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); -void BLASFUNC(cgetrs)(char *, int *, int *, float *, int *, int *, float *, int *, int *); -void BLASFUNC(zgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); -void BLASFUNC(xgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); -void BLASFUNC(sgesv)(int *, int *, float *, int *, int *, float *, int *, int *); -void BLASFUNC(dgesv)(int *, int *, double *, int *, int *, double *, int *, int *); -void BLASFUNC(qgesv)(int *, int *, double *, int *, int *, double *, int *, int *); -void BLASFUNC(cgesv)(int *, int *, float *, int *, int *, float *, int *, int *); -void BLASFUNC(zgesv)(int *, int *, double *, int *, int *, double *, int *, int *); -void BLASFUNC(xgesv)(int *, int *, double *, int *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(sgesv)(int *, int *, float *, int *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgesv)(int *, int *, double *, int *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qgesv)(int *, int *, double *, int *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgesv)(int *, int *, float *, int *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgesv)(int *, int *, double *, int *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xgesv)(int *, int *, double *, int *, int *, double *, int *, int *); -void BLASFUNC(spotf2)(char *, int *, float *, int *, int *); -void BLASFUNC(dpotf2)(char *, int *, double *, int *, int *); -void BLASFUNC(qpotf2)(char *, int *, double *, int *, int *); -void BLASFUNC(cpotf2)(char *, int *, float *, int *, int *); -void BLASFUNC(zpotf2)(char *, int *, double *, int *, int *); -void BLASFUNC(xpotf2)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(spotf2)(char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dpotf2)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qpotf2)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cpotf2)(char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zpotf2)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xpotf2)(char *, int *, double *, int *, int *); -void BLASFUNC(spotrf)(char *, int *, float *, int *, int *); -void BLASFUNC(dpotrf)(char *, int *, double *, int *, int *); -void BLASFUNC(qpotrf)(char *, int *, double *, int *, int *); -void BLASFUNC(cpotrf)(char *, int *, float *, int *, int *); -void BLASFUNC(zpotrf)(char *, int *, double *, int *, int *); -void BLASFUNC(xpotrf)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qpotrf)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xpotrf)(char *, int *, double *, int *, int *); -void BLASFUNC(slauu2)(char *, int *, float *, int *, int *); -void BLASFUNC(dlauu2)(char *, int *, double *, int *, int *); -void BLASFUNC(qlauu2)(char *, int *, double *, int *, int *); -void BLASFUNC(clauu2)(char *, int *, float *, int *, int *); -void BLASFUNC(zlauu2)(char *, int *, double *, int *, int *); -void BLASFUNC(xlauu2)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(slauu2)(char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dlauu2)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qlauu2)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(clauu2)(char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zlauu2)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xlauu2)(char *, int *, double *, int *, int *); -void BLASFUNC(slauum)(char *, int *, float *, int *, int *); -void BLASFUNC(dlauum)(char *, int *, double *, int *, int *); -void BLASFUNC(qlauum)(char *, int *, double *, int *, int *); -void BLASFUNC(clauum)(char *, int *, float *, int *, int *); -void BLASFUNC(zlauum)(char *, int *, double *, int *, int *); -void BLASFUNC(xlauum)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(slauum)(char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dlauum)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qlauum)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(clauum)(char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zlauum)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xlauum)(char *, int *, double *, int *, int *); -void BLASFUNC(strti2)(char *, char *, int *, float *, int *, int *); -void BLASFUNC(dtrti2)(char *, char *, int *, double *, int *, int *); -void BLASFUNC(qtrti2)(char *, char *, int *, double *, int *, int *); -void BLASFUNC(ctrti2)(char *, char *, int *, float *, int *, int *); -void BLASFUNC(ztrti2)(char *, char *, int *, double *, int *, int *); -void BLASFUNC(xtrti2)(char *, char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(strti2)(char *, char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dtrti2)(char *, char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qtrti2)(char *, char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(ctrti2)(char *, char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(ztrti2)(char *, char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xtrti2)(char *, char *, int *, double *, int *, int *); -void BLASFUNC(strtri)(char *, char *, int *, float *, int *, int *); -void BLASFUNC(dtrtri)(char *, char *, int *, double *, int *, int *); -void BLASFUNC(qtrtri)(char *, char *, int *, double *, int *, int *); -void BLASFUNC(ctrtri)(char *, char *, int *, float *, int *, int *); -void BLASFUNC(ztrtri)(char *, char *, int *, double *, int *, int *); -void BLASFUNC(xtrtri)(char *, char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(strtri)(char *, char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dtrtri)(char *, char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qtrtri)(char *, char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(ctrtri)(char *, char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(ztrtri)(char *, char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xtrtri)(char *, char *, int *, double *, int *, int *); -void BLASFUNC(spotri)(char *, int *, float *, int *, int *); -void BLASFUNC(dpotri)(char *, int *, double *, int *, int *); -void BLASFUNC(qpotri)(char *, int *, double *, int *, int *); -void BLASFUNC(cpotri)(char *, int *, float *, int *, int *); -void BLASFUNC(zpotri)(char *, int *, double *, int *, int *); -void BLASFUNC(xpotri)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(spotri)(char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dpotri)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(qpotri)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cpotri)(char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zpotri)(char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(xpotri)(char *, int *, double *, int *, int *); + +//----------------------------------------------------------------------------- +// Eigen C++ implementations. +//----------------------------------------------------------------------------- + +// Cholesky. +EIGEN_LAPACK_API void BLASFUNC(spotrf)(const char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dpotrf)(const char *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cpotrf)(const char *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zpotrf)(const char *, int *, double *, int *, int *); + +EIGEN_LAPACK_API void BLASFUNC(spotrs)(const char *, int *, int *, float *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dpotrs)(const char *, int *, int *, double *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cpotrs)(const char *, int *, int *, float *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zpotrs)(const char *, int *, int *, double *, int *, double *, int *, int *); + +// Eigenvalues. +EIGEN_LAPACK_API void BLASFUNC(ssyev)(const char *, const char *, int *, float *, int *, float *, float *, int *, + int *); +EIGEN_LAPACK_API void BLASFUNC(dsyev)(const char *, const char *, int *, double *, int *, double *, double *, int *, + int *); + +// LU. +EIGEN_LAPACK_API void BLASFUNC(sgetrf)(int *, int *, float *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgetrf)(int *, int *, double *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgetrf)(int *, int *, float *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgetrf)(int *, int *, double *, int *, int *, int *); + +EIGEN_LAPACK_API void BLASFUNC(sgetrs)(const char *, int *, int *, float *, int *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgetrs)(const char *, int *, int *, double *, int *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgetrs)(const char *, int *, int *, float *, int *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgetrs)(const char *, int *, int *, double *, int *, int *, double *, int *, int *); + +// SVD. +EIGEN_LAPACK_API void BLASFUNC(sgesdd)(const char *, int *, int *, float *, int *, float *, float *, int *, float *, + int *, float *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgesdd)(const char *, int *, int *, double *, int *, double *, double *, int *, double *, + int *, double *, int *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgesdd)(const char *, int *, int *, float *, int *, float *, float *, int *, float *, + int *, float *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgesdd)(const char *, int *, int *, double *, int *, double *, double *, int *, double *, + int *, double *, int *, double *, int *, int *); + +EIGEN_LAPACK_API void BLASFUNC(sgesvd)(const char *, const char *, int *, int *, float *, int *, float *, float *, + int *, float *, int *, float *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(dgesvd)(const char *, const char *, int *, int *, double *, int *, double *, double *, + int *, double *, int *, double *, int *, int *); +EIGEN_LAPACK_API void BLASFUNC(cgesvd)(const char *, const char *, int *, int *, float *, int *, float *, float *, + int *, float *, int *, float *, int *, float *, int *); +EIGEN_LAPACK_API void BLASFUNC(zgesvd)(const char *, const char *, int *, int *, double *, int *, double *, double *, + int *, double *, int *, double *, int *, double *, int *); + +// Time. +EIGEN_LAPACK_API float BLASFUNC(second)(); +EIGEN_LAPACK_API double BLASFUNC(dsecnd)(); #ifdef __cplusplus } diff --git a/lapack/lu.inc b/lapack/lu.inc index 2ddaf957a..69fdc3ded 100644 --- a/lapack/lu.inc +++ b/lapack/lu.inc @@ -40,7 +40,7 @@ EIGEN_LAPACK_FUNC(getrf)(int *m, int *n, RealScalar *pa, int *lda, int *ipiv, in // A * X = B or A' * X = B // with a general N-by-N matrix A using the LU factorization computed by GETRF EIGEN_LAPACK_FUNC(getrs) -(char *trans, int *n, int *nrhs, RealScalar *pa, int *lda, int *ipiv, RealScalar *pb, int *ldb, int *info) { +(const char *trans, int *n, int *nrhs, RealScalar *pa, int *lda, int *ipiv, RealScalar *pb, int *ldb, int *info) { *info = 0; if (OP(*trans) == INVALID) *info = -1; diff --git a/lapack/second_INT_CPU_TIME.cpp b/lapack/second_INT_CPU_TIME.cpp index d6eb4029b..49371ffe4 100644 --- a/lapack/second_INT_CPU_TIME.cpp +++ b/lapack/second_INT_CPU_TIME.cpp @@ -15,6 +15,8 @@ #include #endif +#include "lapack.h" + extern "C" { float second_(); } diff --git a/lapack/svd.inc b/lapack/svd.inc index 262c5c696..733f07ef5 100644 --- a/lapack/svd.inc +++ b/lapack/svd.inc @@ -18,8 +18,9 @@ // computes the singular values/vectors a general M-by-N matrix A using divide-and-conquer EIGEN_LAPACK_FUNC(gesdd) -(char *jobz, int *m, int *n, Scalar *a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, - Scalar * /*work*/, int *lwork, EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar * /*rwork*/) int * /*iwork*/, int *info) { +(const char *jobz, int *m, int *n, RealScalar *ra, int *lda, RealScalar *s, RealScalar *ru, int *ldu, RealScalar *rvt, + int *ldvt, RealScalar * /*work*/, int *lwork, EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar * /*rwork*/) int * /*iwork*/, + int *info) { // TODO exploit the work buffer bool query_size = *lwork == -1; int diag_size = (std::min)(*m, *n); @@ -53,37 +54,44 @@ EIGEN_LAPACK_FUNC(gesdd) if (*n == 0 || *m == 0) return; + Scalar *a = reinterpret_cast(ra); + Scalar *u = reinterpret_cast(ru); + Scalar *vt = reinterpret_cast(rvt); + PlainMatrixType mat(*m, *n); mat = matrix(a, *m, *n, *lda); - int option = *jobz == 'A' ? Eigen::ComputeFullU | Eigen::ComputeFullV - : *jobz == 'S' ? Eigen::ComputeThinU | Eigen::ComputeThinV - : *jobz == 'O' ? Eigen::ComputeThinU | Eigen::ComputeThinV - : 0; - - Eigen::BDCSVD svd(mat, option); - - make_vector(s, diag_size) = svd.singularValues().head(diag_size); - if (*jobz == 'A') { + Eigen::BDCSVD svd(mat); + make_vector(s, diag_size) = svd.singularValues().head(diag_size); matrix(u, *m, *m, *ldu) = svd.matrixU(); matrix(vt, *n, *n, *ldvt) = svd.matrixV().adjoint(); } else if (*jobz == 'S') { + Eigen::BDCSVD svd(mat); + make_vector(s, diag_size) = svd.singularValues().head(diag_size); matrix(u, *m, diag_size, *ldu) = svd.matrixU(); matrix(vt, diag_size, *n, *ldvt) = svd.matrixV().adjoint(); } else if (*jobz == 'O' && *m >= *n) { + Eigen::BDCSVD svd(mat); + make_vector(s, diag_size) = svd.singularValues().head(diag_size); matrix(a, *m, *n, *lda) = svd.matrixU(); matrix(vt, *n, *n, *ldvt) = svd.matrixV().adjoint(); } else if (*jobz == 'O') { + Eigen::BDCSVD svd(mat); + make_vector(s, diag_size) = svd.singularValues().head(diag_size); matrix(u, *m, *m, *ldu) = svd.matrixU(); matrix(a, diag_size, *n, *lda) = svd.matrixV().adjoint(); + } else { + Eigen::BDCSVD svd(mat); + make_vector(s, diag_size) = svd.singularValues().head(diag_size); } } // computes the singular values/vectors a general M-by-N matrix A using two sided jacobi algorithm EIGEN_LAPACK_FUNC(gesvd) -(char *jobu, char *jobv, int *m, int *n, Scalar *a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, - Scalar * /*work*/, int *lwork, EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar * /*rwork*/) int *info) { +(const char *jobu, const char *jobv, int *m, int *n, RealScalar *ra, int *lda, RealScalar *s, RealScalar *ru, int *ldu, + RealScalar *rvt, int *ldvt, RealScalar * /*work*/, int *lwork, + EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar * /*rwork*/) int *info) { // TODO exploit the work buffer bool query_size = *lwork == -1; int diag_size = (std::min)(*m, *n); @@ -116,6 +124,10 @@ EIGEN_LAPACK_FUNC(gesvd) if (*n == 0 || *m == 0) return; + Scalar *a = reinterpret_cast(ra); + Scalar *u = reinterpret_cast(ru); + Scalar *vt = reinterpret_cast(rvt); + PlainMatrixType mat(*m, *n); mat = matrix(a, *m, *n, *lda); diff --git a/scripts/git_commit_mrs_and_issues.py b/scripts/git_commit_mrs_and_issues.py new file mode 100644 index 000000000..854ec390e --- /dev/null +++ b/scripts/git_commit_mrs_and_issues.py @@ -0,0 +1,128 @@ +"""Search for MRs and issues related to a list of commits.""" + +import argparse +import json +import sys +import subprocess +import re + + +def find_cherry_pick_source(commit_hash: str): + """ + For a given commit hash, find the original commit it was cherry-picked from. + + Args: + commit_hash: The commit hash to inspect. + + Returns: + The full hash of the original commit if found, otherwise None. + """ + try: + # Use 'git show' to get the full commit message for the given hash. + # The '-s' flag suppresses the diff output. + # The '--format=%B' flag prints only the raw commit body/message. + commit_message = subprocess.check_output( + ["git", "show", "-s", "--format=%B", commit_hash.strip()], + text=True, + stderr=subprocess.PIPE, + ).strip() + + # This regex looks for the specific line Git adds during a cherry-pick. + # It captures the full 40-character SHA-1 hash. + cherry_pick_pattern = re.compile( + r"\(cherry picked from commit ([a-f0-9]{40})\)" + ) + + # Search the entire commit message for the pattern. + match = cherry_pick_pattern.search(commit_message) + + if match: + # If a match is found, return the captured group (the original commit hash). + return match.group(1) + else: + return None + + except subprocess.CalledProcessError as e: + # This error occurs if the git command fails, e.g., for an invalid hash. + print( + f"Error processing commit '{commit_hash.strip()}': {e.stderr.strip()}", + file=sys.stderr, + ) + return None + except FileNotFoundError: + # This error occurs if the 'git' command itself isn't found. + print( + "Error: 'git' command not found. Please ensure Git is installed and in your PATH.", + file=sys.stderr, + ) + sys.exit(1) + + +def main(): + """ + Main function to read commit hashes from stdin and process them. + """ + parser = argparse.ArgumentParser( + description="A script to download all MRs from GitLab matching specified criteria." + ) + parser.add_argument( + "--merge_requests_file", + type=str, + required=True, + help="JSON file containing all the merge request information extracted via the GitLab API.", + ) + + # E.g. git log --pretty=%H 3e819d83bf52abda16bb53565f6801df40d071f1..3.4.1 + parser.add_argument( + "--commits", + required=True, + help="List of commits, '-' for stdin.", + ) + args = parser.parse_args() + + mrs = [] + with open(args.merge_requests_file, "r") as file: + mrs = json.load(file) + mrs_by_commit = {} + + if args.commits == "-": + commit_hashes = sys.stdin.readlines() + else: + with open(args.commits, "r") as file: + commit_hashes = file.readlines() + + # Arrange commits by SHA. + for mr in mrs: + for key in ["sha", "merge_commit_sha", "squash_commit_sha"]: + sha = mr[key] + if sha: + mrs_by_commit[sha] = mr + + # Find the MRs and issues related to each commit. + info = {} + for sha in commit_hashes: + sha = sha.strip() + if not sha: + continue + + # If a cherry-pick, extract the original hash. + sha = find_cherry_pick_source(sha) or sha + mr = mrs_by_commit.get(sha) + + commit_info = {} + if mr: + commit_info["merge_request"] = mr["iid"] + commit_info["related_issues"] = [ + issue["iid"] for issue in mr["related_issues"] + ] + commit_info["closes_issues"] = [ + issue["iid"] for issue in mr["closes_issues"] + ] + + info[sha] = commit_info + + print(json.dumps(info, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/scripts/gitlab_api_deploy_package.py b/scripts/gitlab_api_deploy_package.py new file mode 100644 index 000000000..70dc03ff1 --- /dev/null +++ b/scripts/gitlab_api_deploy_package.py @@ -0,0 +1,136 @@ +"""Helper script to download source archives and upload them to the Eigen GitLab generic package registry.""" + +import os +import requests +import hashlib +import argparse +import sys +import tempfile + +EIGEN_PROJECT_ID = 15462818 # Taken from the gitlab project page. + + +def calculate_sha256(filepath: str): + """Calculates the SHA256 checksum of a file.""" + sha256_hash = hashlib.sha256() + with open(filepath, "rb") as f: + # Read and update hash in chunks of 4K + for byte_block in iter(lambda: f.read(4096), b""): + sha256_hash.update(byte_block) + return sha256_hash.hexdigest() + + +def upload_to_generic_registry( + gitlab_private_token: str, package_name: str, package_version: str, filepath: str +): + """Uploads a file to the GitLab generic package registry.""" + headers = {"PRIVATE-TOKEN": gitlab_private_token} + filename = os.path.basename(filepath) + upload_url = f"https://gitlab.com/api/v4/projects/{EIGEN_PROJECT_ID}/packages/generic/{package_name}/{package_version}/{filename}" + + print(f"Uploading {filename} to {upload_url}...") + try: + with open(filepath, "rb") as f: + response = requests.put(upload_url, headers=headers, data=f) + response.raise_for_status() + print(f"Successfully uploaded {filename}.") + return True + except requests.exceptions.RequestException as e: + print(f"Error uploading {filename}: {e}") + if e.response is not None: + print(f"Response content: {e.response.text}") + return False + + +def main(): + """Main function to download archives and upload them to the registry.""" + parser = argparse.ArgumentParser( + description="Download GitLab release archives for Eigen and upload them to the generic package registry." + ) + parser.add_argument( + "--gitlab_private_token", + type=str, + help="GitLab private API token. Defaults to the GITLAB_PRIVATE_TOKEN environment variable if set.", + ) + parser.add_argument( + "--version", + required=True, + help="Specify a single version (tag name) to process.", + ) + parser.add_argument( + "--download-dir", help=f"Directory to store temporary downloads (optional)." + ) + args = parser.parse_args() + + if not args.gitlab_private_token: + args.gitlab_private_token = os.getenv("GITLAB_PRIVATE_TOKEN") + if not args.gitlab_private_token: + print("Could not determine GITLAB_PRIVATE_TOKEN.", file=sys.stderr) + parser.print_usage() + sys.exit(1) + + # Create download directory if it doesn't exist. + cleanup_download_dir = False + if args.download_dir: + if not os.path.exists(args.download_dir): + cleanup_download_dir = True + os.makedirs(args.download_dir) + else: + args.download_dir = tempfile.mkdtemp() + cleanup_download_dir = True + + for ext in ["tar.gz", "tar.bz2", "tar", "zip"]: + archive_filename = f"eigen-{args.version}.{ext}" + archive_url = f"https://gitlab.com/libeigen/eigen/-/archive/{args.version}/{archive_filename}" + archive_filepath = os.path.join(args.download_dir, archive_filename) + + # Download the archive + print(f"Downloading {archive_url}...") + try: + response = requests.get(archive_url, stream=True) + response.raise_for_status() + with open(archive_filepath, "wb") as f: + for chunk in response.iter_content(chunk_size=8192): + f.write(chunk) + print(f"Downloaded to {archive_filepath}") + except requests.exceptions.RequestException as e: + print(f"Error downloading {archive_url}: {e}. Skipping.") + continue + + # Calculate SHA256 sum + sha256_sum = calculate_sha256(archive_filepath) + print(f"SHA256 sum: {sha256_sum}") + + # Create SHA256 sum file + sha_filename = f"{archive_filename}.sha256" + sha_filepath = os.path.join(args.download_dir, sha_filename) + with open(sha_filepath, "w") as f: + f.write(f"{sha256_sum} {archive_filename}\n") + print(f"Created SHA256 file: {sha_filepath}") + + # Upload archive to generic registry + if not upload_to_generic_registry( + args.gitlab_private_token, "eigen", args.version, archive_filepath + ): + # If upload fails, clean up and move to the next release + os.remove(archive_filepath) + os.remove(sha_filepath) + continue + + # Upload SHA256 sum file to generic registry + upload_to_generic_registry( + args.gitlab_private_token, "eigen", args.version, sha_filepath + ) + + # Clean up downloaded files + print("Cleaning up local files...") + os.remove(archive_filepath) + os.remove(sha_filepath) + + # Clean up the download directory if it's empty + if cleanup_download_dir and not os.listdir(args.download_dir): + os.rmdir(args.download_dir) + + +if __name__ == "__main__": + main() diff --git a/scripts/gitlab_api_issues.py b/scripts/gitlab_api_issues.py new file mode 100644 index 000000000..1d191fa3e --- /dev/null +++ b/scripts/gitlab_api_issues.py @@ -0,0 +1,174 @@ +"""Downloads all issues from GitLab matching specified criteria.""" + +import argparse +import datetime +import json +import os +import requests +import sys + +EIGEN_PROJECT_ID = 15462818 # Taken from the gitlab project page. + + +def date(date_string: str): + """Convert a date YY-MM-DD string to a datetime object.""" + try: + return datetime.strptime(date_string, "%Y-%m-%d") + except ValueError: + msg = f"Not a valid date: '{date_string}'. Expected format is YYYY-MM-DD." + raise argparse.ArgumentTypeError(msg) + + +def _get_api_query( + gitlab_private_token: str, url: str, params: dict[str, str] | None = None +): + next_page = "1" + if not params: + params = dict() + params["per_page"] = "100" + headers = {"PRIVATE-TOKEN": gitlab_private_token} + out = [] + while next_page: + params["page"] = next_page + try: + resp = requests.head(url=url, params=params, headers=headers) + if resp.status_code != 200: + print("Request failed: ", resp, file=sys.stderr) + break + + next_next_page = resp.headers["x-next-page"] + + resp = requests.get(url=url, params=params, headers=headers) + if resp.status_code != 200: + # Try again. + continue + + out.extend(resp.json()) + # Advance at the end, in case an exception occurs above so we can retry + next_page = next_next_page + except: + # Keep same next_page + continue + return out + + +def get_issues( + gitlab_private_token: str, + author_username: str | None = None, + state: str | None = None, + created_before: datetime.datetime | None = None, + created_after: datetime.datetime | None = None, + updated_after: datetime.datetime | None = None, + updated_before: datetime.datetime | None = None, +): + """Return list of merge requests. + + Args: + gitlab_token: GitLab API token. + author_username: issue author username. + state: issue state (opened, closed). + created_after: datetime start of period. + created_before: datetime end of period. + updated_after: datetime start of period. + updated_before: datetime end of period. + + Returns: + List of merge requests. + """ + url = f"https://gitlab.com/api/v4/projects/{str(EIGEN_PROJECT_ID)}/issues" + params = dict() + if author_username: + params["author_username"] = author_username + + if state: + params["state"] = state + + if created_before: + params["created_before"] = created_before.isoformat() + + if created_after: + params["created_after"] = created_after.isoformat() + + if updated_before: + params["updated_before"] = updated_before.isoformat() + + if updated_after: + params["updated_after"] = updated_after.isoformat() + + params["order_by"] = "created_at" + params["sort"] = "asc" + issues = _get_api_query(gitlab_private_token, url, params) + for issue in issues: + if int(issue["merge_requests_count"]) > 0: + issue_iid = issue["iid"] + issue["related_merge_requests"] = _get_api_query( + gitlab_private_token, f"{url}/{issue_iid}/related_merge_requests" + ) + issue["closed_by_merge_requests"] = _get_api_query( + gitlab_private_token, f"{url}/{issue_iid}/closed_by" + ) + return issues + + +def main(_): + parser = argparse.ArgumentParser( + description="A script to download all issues from GitLab matching specified criteria." + ) + parser.add_argument( + "--gitlab_private_token", + type=str, + help="GitLab private API token. Defaults to the GITLAB_PRIVATE_TOKEN environment variable if set.", + ) + parser.add_argument("--author", type=str, help="The name of the author.") + parser.add_argument( + "--state", + type=str, + choices=["opened", "closed"], + help="The state of the issue.", + ) + parser.add_argument( + "--created_before", + type=date, + help="The created-before date in YYYY-MM-DD format.", + ) + parser.add_argument( + "--created_after", + type=date, + help="The created-after date in YYYY-MM-DD format.", + ) + parser.add_argument( + "--updated_before", + type=date, + help="The updated-before date in YYYY-MM-DD format.", + ) + parser.add_argument( + "--updated_after", + type=date, + help="The updated-after date in YYYY-MM-DD format.", + ) + args = parser.parse_args() + + if not args.gitlab_private_token: + args.gitlab_private_token = os.getenv("GITLAB_PRIVATE_TOKEN") + if not args.gitlab_private_token: + print("Could not determine GITLAB_PRIVATE_TOKEN.", file=sys.stderr) + parser.print_usage() + sys.exit(1) + + # Parse the arguments from the command line + issues = get_issues( + gitlab_private_token=args.gitlab_private_token, + author_username=args.author, + state=args.state, + created_before=args.created_before, + created_after=args.created_after, + updated_before=args.updated_before, + updated_after=args.updated_after, + ) + + issue_str = json.dumps(issues, indent=2) + print(issue_str) + + +if __name__ == "__main__": + main(sys.argv) diff --git a/scripts/gitlab_api_labeller.py b/scripts/gitlab_api_labeller.py new file mode 100644 index 000000000..f5d3530fc --- /dev/null +++ b/scripts/gitlab_api_labeller.py @@ -0,0 +1,122 @@ +"""Adds a label to a GitLab merge requests or issues.""" + +import os +import sys +import argparse +import requests + +EIGEN_PROJECT_ID = 15462818 # Taken from the gitlab project page. + + +def add_label_to_mr(private_token: str, mr_iid: int, label: str): + """ + Adds a label to a specific merge request in a GitLab project. + + Args: + private_token: The user's private GitLab API token. + mr_iid: The internal ID (IID) of the merge request. + label: The label to add. + """ + api_url = ( + f"https://gitlab.com/api/v4/projects/{EIGEN_PROJECT_ID}/merge_requests/{mr_iid}" + ) + headers = {"PRIVATE-TOKEN": private_token} + # Using 'add_labels' ensures we don't overwrite existing labels. + payload = {"add_labels": label} + + try: + response = requests.put(api_url, headers=headers, json=payload) + response.raise_for_status() # Raises an HTTPError for bad responses (4xx or 5xx) + print(f"✅ Successfully added label '{label}' to Merge Request !{mr_iid}.") + except requests.exceptions.RequestException as e: + print(f"❌ Error updating Merge Request !{mr_iid}: {e}", file=sys.stderr) + if hasattr(e, "response") and e.response is not None: + print(f" Response: {e.response.text}", file=sys.stderr) + + +def add_label_to_issue(private_token: str, issue_iid: int, label: str): + """ + Adds a label to a specific issue in a GitLab project. + + Args: + private_token: The user's private GitLab API token. + issue_iid: The internal ID (IID) of the issue. + label: The label to add. + """ + api_url = ( + f"https://gitlab.com/api/v4/projects/{EIGEN_PROJECT_ID}/issues/{issue_iid}" + ) + headers = {"PRIVATE-TOKEN": private_token} + payload = {"add_labels": label} + + try: + response = requests.put(api_url, headers=headers, json=payload) + response.raise_for_status() + print(f"✅ Successfully added label '{label}' to Issue #{issue_iid}.") + except requests.exceptions.RequestException as e: + print(f"❌ Error updating Issue #{issue_iid}: {e}", file=sys.stderr) + if hasattr(e, "response") and e.response is not None: + print(f" Response: {e.response.text}", file=sys.stderr) + + +def main(): + """ + Main function to parse arguments and trigger the labelling process. + """ + parser = argparse.ArgumentParser( + description="Add a label to GitLab merge requests and issues.", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument("label", help="The label to add.") + parser.add_argument( + "--mrs", + nargs="+", + type=int, + help="A space-separated list of Merge Request IIDs.", + ) + parser.add_argument( + "--issues", nargs="+", type=int, help="A space-separated list of Issue IIDs." + ) + parser.add_argument( + "--gitlab_private_token", + help="Your GitLab private access token. \n(Best practice is to use the GITLAB_PRIVATE_TOKEN environment variable instead.)", + ) + args = parser.parse_args() + + # Prefer environment variable for the token for better security. + gitlab_private_token = args.gitlab_private_token or os.environ.get( + "GITLAB_PRIVATE_TOKEN" + ) + if not gitlab_private_token: + print("Error: GitLab private token not found.", file=sys.stderr) + print( + "Please provide it using the --token argument or by setting the GITLAB_PRIVATE_TOKEN environment variable.", + file=sys.stderr, + ) + sys.exit(1) + + if not args.mrs and not args.issues: + print( + "Error: You must provide at least one merge request (--mrs) or issue (--issues) ID.", + file=sys.stderr, + ) + sys.exit(1) + + print("-" * 30) + + if args.mrs: + print(f"Processing {len(args.mrs)} merge request(s)...") + for mr_iid in args.mrs: + add_label_to_mr(gitlab_private_token, mr_iid, args.label) + + if args.issues: + print(f"\nProcessing {len(args.issues)} issue(s)...") + for issue_iid in args.issues: + add_label_to_issue(gitlab_private_token, issue_iid, args.label) + + print("-" * 30) + print("Script finished.") + + +if __name__ == "__main__": + main() diff --git a/scripts/gitlab_api_mrs.py b/scripts/gitlab_api_mrs.py new file mode 100644 index 000000000..12eb5f9b5 --- /dev/null +++ b/scripts/gitlab_api_mrs.py @@ -0,0 +1,200 @@ +"""Downloads all MRs from GitLab matching specified criteria.""" + +import argparse +import datetime +import json +import os +import requests +import sys + +EIGEN_PROJECT_ID = 15462818 # Taken from the gitlab project page. + + +def date(date_string: str): + """Convert a date YY-MM-DD string to a datetime object.""" + try: + return datetime.strptime(date_string, "%Y-%m-%d") + except ValueError: + msg = f"Not a valid date: '{date_string}'. Expected format is YYYY-MM-DD." + raise argparse.ArgumentTypeError(msg) + + +def _get_api_query( + gitlab_private_token: str, url: str, params: dict[str, str] | None = None +): + next_page = "1" + if not params: + params = dict() + params["per_page"] = "100" + headers = {"PRIVATE-TOKEN": gitlab_private_token} + out = [] + while next_page: + params["page"] = next_page + try: + resp = requests.head(url=url, params=params, headers=headers) + if resp.status_code != 200: + print("Request failed: ", resp, file=sys.stderr) + break + + next_next_page = resp.headers["x-next-page"] + + resp = requests.get(url=url, params=params, headers=headers) + if resp.status_code != 200: + # Try again. + continue + + out.extend(resp.json()) + # Advance at the end, in case an exception occurs above so we can retry + next_page = next_next_page + except: + # Keep same next_page + continue + return out + + +def get_merge_requests( + gitlab_private_token: str, + author_username: str | None = None, + state: str | None = None, + created_before: datetime.datetime | None = None, + created_after: datetime.datetime | None = None, + updated_after: datetime.datetime | None = None, + updated_before: datetime.datetime | None = None, + related_issues: bool = False, + closes_issues: bool = False, +): + """Return list of merge requests. + + Args: + gitlab_token: GitLab API token. + author_username: MR author username. + state: MR state (merged, opened, closed, locked). + created_after: datetime start of period. + created_before: datetime end of period. + updated_after: datetime start of period. + updated_before: datetime end of period. + + Returns: + List of merge requests. + """ + url = ( + "https://gitlab.com/api/v4/projects/" + + str(EIGEN_PROJECT_ID) + + "/merge_requests" + ) + params = dict() + if author_username: + params["author_username"] = author_username + + if state: + params["state"] = state + + if created_before: + params["created_before"] = created_before.isoformat() + + if created_after: + params["created_after"] = created_after.isoformat() + + if updated_before: + params["updated_before"] = updated_before.isoformat() + + if updated_after: + params["updated_after"] = updated_after.isoformat() + + params["order_by"] = "created_at" + params["sort"] = "asc" + + next_page = "1" + params["per_page"] = "100" + headers = {"PRIVATE-TOKEN": gitlab_private_token} + + mrs = _get_api_query(gitlab_private_token, url, params) + + if related_issues: + for mr in mrs: + mr["related_issues"] = _get_api_query( + gitlab_private_token, f"{url}/{mr['iid']}/related_issues" + ) + + if closes_issues: + for mr in mrs: + mr["closes_issues"] = _get_api_query( + gitlab_private_token, f"{url}/{mr['iid']}/closes_issues" + ) + + return mrs + + +def main(_): + parser = argparse.ArgumentParser( + description="A script to download all MRs from GitLab matching specified criteria." + ) + parser.add_argument( + "--gitlab_private_token", + type=str, + help="GitLab private API token. Defaults to the GITLAB_PRIVATE_TOKEN environment variable if set.", + ) + parser.add_argument("--author", type=str, help="The name of the author.") + parser.add_argument( + "--state", + type=str, + choices=["merged", "opened", "closed", "locked"], + help="The state of the MR.", + ) + parser.add_argument( + "--created_before", + type=date, + help="The created-before date in YYYY-MM-DD format.", + ) + parser.add_argument( + "--created_after", + type=date, + help="The created-after date in YYYY-MM-DD format.", + ) + parser.add_argument( + "--updated_before", + type=date, + help="The updated-before date in YYYY-MM-DD format.", + ) + parser.add_argument( + "--updated_after", + type=date, + help="The updated-after date in YYYY-MM-DD format.", + ) + parser.add_argument( + "--related_issues", action="store_true", help="Query for related issues." + ) + parser.add_argument( + "--closes_issues", + action="store_true", + help="Query for issues closed by the MR.", + ) + + args = parser.parse_args() + + if not args.gitlab_private_token: + args.gitlab_private_token = os.getenv("GITLAB_PRIVATE_TOKEN") + if not args.gitlab_private_token: + print("Could not determine GITLAB_PRIVATE_TOKEN.", file=sys.stderr) + parser.print_usage() + sys.exit(1) + + # Parse the arguments from the command line + mrs = get_merge_requests( + gitlab_private_token=args.gitlab_private_token, + author_username=args.author, + state=args.state, + created_before=args.created_before, + created_after=args.created_after, + updated_before=args.updated_before, + updated_after=args.updated_after, + related_issues=args.related_issues, + closes_issues=args.closes_issues, + ) + + mr_str = json.dumps(mrs, indent=2) + print(mr_str) + + +if __name__ == "__main__": + main(sys.argv) diff --git a/scripts/msvc_setup.ps1 b/scripts/msvc_setup.ps1 index e2d06422e..3890a4587 100644 --- a/scripts/msvc_setup.ps1 +++ b/scripts/msvc_setup.ps1 @@ -1,9 +1,6 @@ # Powershell script to set up MSVC environment. param ($EIGEN_CI_MSVC_ARCH, $EIGEN_CI_MSVC_VER) - -Set-PSDebug -Trace 1 - function Get-ScriptDirectory { Split-Path $MyInvocation.ScriptName } # Set defaults if not already set. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e372a2ce1..f704c4aa0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -257,6 +257,7 @@ ei_add_test(eigensolver_selfadjoint) ei_add_test(eigensolver_generic) ei_add_test(eigensolver_complex) ei_add_test(real_qz) +ei_add_test(complex_qz) ei_add_test(eigensolver_generalized_real) ei_add_test(jacobi) ei_add_test(jacobisvd) diff --git a/test/complex_qz.cpp b/test/complex_qz.cpp new file mode 100644 index 000000000..a6b05dc92 --- /dev/null +++ b/test/complex_qz.cpp @@ -0,0 +1,86 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2012 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/. + +#define EIGEN_RUNTIME_NO_MALLOC +#include "main.h" + +#include + +/* this test covers the following files: + ComplexQZ.h +*/ + +template +void generate_random_matrix_pair(const Index dim, MatrixType& A, MatrixType& B) { + A.resize(dim, dim); + B.resize(dim, dim); + A.setRandom(); + B.setRandom(); + // Set each row of B with a probability of 10% to 0 + for (int i = 0; i < dim; i++) { + if (internal::random(0, 10) == 0) B.row(i).setZero(); + } +} + +template +void complex_qz(const MatrixType& A, const MatrixType& B) { + using std::abs; + const Index dim = A.rows(); + ComplexQZ qz(A, B); + VERIFY_IS_EQUAL(qz.info(), Success); + auto T = qz.matrixT(), S = qz.matrixS(); + bool is_all_zero_T = true, is_all_zero_S = true; + using RealScalar = typename MatrixType::RealScalar; + RealScalar tol = dim * 10 * NumTraits::epsilon(); + for (Index j = 0; j < dim; j++) { + for (Index i = j + 1; i < dim; i++) { + if (std::abs(T(i, j)) > tol) { + std::cerr << std::abs(T(i, j)) << std::endl; + is_all_zero_T = false; + } + if (std::abs(S(i, j)) > tol) { + std::cerr << std::abs(S(i, j)) << std::endl; + is_all_zero_S = false; + } + } + } + VERIFY_IS_EQUAL(is_all_zero_T, true); + VERIFY_IS_EQUAL(is_all_zero_S, true); + VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixS() * qz.matrixZ(), A); + VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixT() * qz.matrixZ(), B); + VERIFY_IS_APPROX(qz.matrixQ() * qz.matrixQ().adjoint(), MatrixType::Identity(dim, dim)); + VERIFY_IS_APPROX(qz.matrixZ() * qz.matrixZ().adjoint(), MatrixType::Identity(dim, dim)); +} + +EIGEN_DECLARE_TEST(complex_qz) { + // const Index dim1 = 15; + // const Index dim2 = 80; + for (int i = 0; i < g_repeat; i++) { + // Check for very small, fixed-sized double- and float complex matrices + Eigen::Matrix2cd A_2x2, B_2x2; + A_2x2.setRandom(); + B_2x2.setRandom(); + B_2x2.row(1).setZero(); + Eigen::Matrix3cf A_3x3, B_3x3; + A_3x3.setRandom(); + B_3x3.setRandom(); + B_3x3.col(i % 3).setRandom(); + // Test for small float complex matrices + Eigen::MatrixXcf A_float, B_float; + const Index dim1 = internal::random(15, 80), dim2 = internal::random(15, 80); + generate_random_matrix_pair(dim1, A_float, B_float); + // Test for a bit larger double complex matrices + Eigen::MatrixXcd A_double, B_double; + generate_random_matrix_pair(dim2, A_double, B_double); + CALL_SUBTEST_1(complex_qz(A_2x2, B_2x2)); + CALL_SUBTEST_2(complex_qz(A_3x3, B_3x3)); + CALL_SUBTEST_3(complex_qz(A_float, B_float)); + CALL_SUBTEST_4(complex_qz(A_double, B_double)); + } +} diff --git a/test/geo_homogeneous.cpp b/test/geo_homogeneous.cpp index 1b515d73c..c5ee7361e 100644 --- a/test/geo_homogeneous.cpp +++ b/test/geo_homogeneous.cpp @@ -126,12 +126,12 @@ void homogeneous(void) { } { - const Eigen::PermutationMatrix P{Eigen::Vector::EqualSpaced(0, 1)}; - const auto right = Eigen::Vector::Random().eval().homogeneous(); - const auto left = Eigen::RowVector::Random().eval().homogeneous(); + PermutationMatrix P{Vector::EqualSpaced(0, 1).reverse()}; + auto right = Vector::Random().eval().nestByValue().homogeneous(); + auto left = RowVector::Random().eval().nestByValue().homogeneous(); - VERIFY_IS_APPROX(P * right, P * right.eval()); - VERIFY_IS_APPROX(left * P, left.eval() * P); + VERIFY_IS_APPROX(P * right, right.reverse()); + VERIFY_IS_APPROX(left * P, left.reverse()); } } diff --git a/test/jacobisvd.cpp b/test/jacobisvd.cpp index cf5cc5fdb..7a6d4906f 100644 --- a/test/jacobisvd.cpp +++ b/test/jacobisvd.cpp @@ -94,6 +94,19 @@ void jacobisvd_verify_inputs(const MatrixType& input = MatrixType()) { (int)ColPivHouseholderQRPreconditioner)); } +template +void svd_triangular_matrix(const MatrixType& input = MatrixType()) { + MatrixType matrix(input.rows(), input.cols()); + svd_fill_random(matrix); + // Make sure that we only consider the 'Lower' part of the matrix. + MatrixType matrix_self_adj = matrix.template selfadjointView().toDenseMatrix(); + + JacobiSVD svd_triangular(matrix.template selfadjointView()); + JacobiSVD svd_full(matrix_self_adj); + + VERIFY_IS_APPROX(svd_triangular.singularValues(), svd_full.singularValues()); +} + namespace Foo { // older compiler require a default constructor for Bar // cf: https://stackoverflow.com/questions/7411515/ @@ -211,5 +224,10 @@ EIGEN_DECLARE_TEST(jacobisvd) { CALL_SUBTEST_55(svd_underoverflow()); + // Check that the TriangularBase constructor works + CALL_SUBTEST_56((svd_triangular_matrix())); + CALL_SUBTEST_57((svd_triangular_matrix())); + CALL_SUBTEST_58((svd_triangular_matrix>())); + msvc_workaround(); } diff --git a/test/ref.cpp b/test/ref.cpp index deb238f61..8b19355a7 100644 --- a/test/ref.cpp +++ b/test/ref.cpp @@ -352,7 +352,7 @@ void test_cref_move_ctor(const DenseBase &expr) { const double *data1 = cref1.data(), *obj_data1 = static_cast(cref1).m_object.data(); VERIFY(test_is_equal(data1, obj_data1, owns_data)); CRef cref2(std::move(cref1)); - VERIFY_IS_EQUAL(data1, cref1.data()); + VERIFY_IS_EQUAL(std::uintptr_t(data1), std::uintptr_t(cref1.data())); const double *data2 = cref2.data(), *obj_data2 = static_cast(cref2).m_object.data(); VERIFY(test_is_equal(data1, data2, MatrixType::MaxSizeAtCompileTime == Dynamic || !owns_data)); VERIFY(test_is_equal(data1, obj_data2, MatrixType::MaxSizeAtCompileTime == Dynamic && owns_data));